You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: ATTENUATION.md
+10-11Lines changed: 10 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,24 +4,23 @@ Here’s a clean way to model the same thing in capc with what you’ve already
4
4
5
5
1) Make “caps” affine + non-forgeable
6
6
7
-
Keep using opaque struct as “this is a capability/handle.” That gives you:
7
+
Use `capability struct` as “this is a capability/handle.” That gives you:
8
8
• cannot copy (your Token test)
9
-
• cannot fabricate (opaque means no public fields / no user construction unless you allow Cap{} for opaques — you probably shouldn’t)
9
+
• cannot fabricate (capability types are opaque: no public fields / no user construction outside the defining module)
10
10
11
-
Also: your current is_affine_type doesn’t automatically make sys.* opaque types affine. If RootCap is supposed to be the “source of authority,” it should be affine too (Austral’s root capability is special and is threaded through main). 
12
-
So: add it to AFFINE_ROOTS (whatever its fully-qualified name is in your world, e.g. "sys.RootCap" or "rc.RootCap").
11
+
Capability types default to affine unless marked `copy` or `linear`.
13
12
14
13
2) Encode attenuation as “only downward constructors”
15
14
16
15
Design the stdlib so the only way to get a capability is from a stronger one, and the API only lets you narrow.
17
16
18
17
A minimal pattern:
19
18
20
-
opaque struct RootCap
21
-
opaque struct Filesystem
22
-
opaque struct Dir
23
-
opaque struct FileRead
24
-
opaque struct FileWrite
19
+
capability struct RootCap
20
+
capability struct Filesystem
21
+
capability struct Dir
22
+
capability struct FileRead
23
+
capability struct FileWrite
25
24
26
25
module fs {
27
26
// mint broad cap from root (borrow root so you can mint others too)
@@ -49,7 +48,7 @@ Notes:
49
48
50
49
For a capability/handle, this is exactly the point:
51
50
52
-
opaque struct Token
51
+
capability struct Token
53
52
54
53
pub fn main() -> i32 {
55
54
let t = Token{}
@@ -58,7 +57,7 @@ pub fn main() -> i32 {
58
57
return 0
59
58
}
60
59
61
-
It’s only “too restrictive” if Token is meant to be data (copyable value). In that case, don’t make it opaque, or give it a non-affine representation (plain struct of copyable fields).
60
+
It’s only “too restrictive” if Token is meant to be data (copyable value). In that case, don’t make it capability/opaque, or give it a non-affine representation (plain struct of copyable fields).
62
61
63
62
4) The tests that actually prove “caps can’t be reused”
This is attenuation: each step narrows authority. There is no safe API to widen back.
148
148
149
-
## 7) Opaque, copy, affine, linear
149
+
To make attenuation one-way at compile time, any method that returns a capability must take `self` by value. Methods that take `&self` cannot return capabilities.
- The bad example lets you keep the more powerful `Dir` and also get a `FileRead`.
170
+
- We want “one-way” attenuation: when you make something less powerful, you give up the more powerful one.
171
+
172
+
So methods that return capabilities must take `self` by value, which consumes the old capability.
173
+
174
+
## 7) Capability, opaque, copy, affine, linear
175
+
176
+
`capability struct` is the explicit “this is an authority token” marker. Capability types are always opaque (no public fields, no user construction) and default to affine unless marked `copy` or `linear`. This exists so the capability surface is obvious in code and the compiler can enforce one‑way attenuation (methods returning capabilities must take `self` by value).
150
177
151
178
Structs can declare their kind:
152
179
153
180
```cap
154
-
opaque struct Token // affine by default (move-only)
0 commit comments