SessionUserAFS overlays caller-specific and temporary providers onto a shared per-instance world. It is deliberately not a directory that contains every user's data.
Construction is single-sited in the runtime (buildSessionView / daemon join path). Do not invent a second construction path that mounts another caller's /user.
View contract
| View | Current tested behavior |
|---|---|
/user | Resolves to the current authenticated caller's user provider. Without that provider, /user is not found; writes are rejected. |
/tmp | Resolves to a provider created for the current session. Present for every joined session. |
/space | Optional. When the runtime enables it for scope:user, an authenticated caller can see their own whole DID Space root here. Anonymous callers do not receive a substitute /space. |
Root overlays are first-class: they are enumerable via list("/"), statable, and routable for read/write/delete/exec according to each overlay's policy.
Isolation (what tests pin)
Daemon tests pin two-user isolation for the todo-style path:
- Caller A and caller B each write and read back their own
/user/app/xvalues. - Paths that try to reach another user through host layouts such as
/blocklets/<name>/users/<other-did>/…or traversal variants under/userare rejected for that session. - Isolation is structural because the session only mounts the singular
/userfor the resolved caller.
That is a session-view boundary. It is not a promise that every arbitrary path in every Blocklet has the same ACL.
Write and base-data gates
Network-origin writes and deletes that fall through to the shared base are rejected. A write that targets a permitted overlay, such as the current caller's /user provider, is evaluated by that overlay's policy instead. Internal code and network requests are not interchangeable contexts.
For /space specifically:
- In the current user-scope daemon coverage, general writes under
/spaceare rejected when the projection is readonly. - A fixed write-guard policy can allow writes only under
blocklets/<app>/user/collections/**and the canonical provenance siblingblocklets/<app>/user/.provenance/collections/**when the runtime wires that guard. Outside those roots, do not assume write access. - Consumers that need the collections write channel should check the published capability marker for the collections + provenance policy rather than inferring from path shape alone.
Do not
- Use
/useraliases, a hidden component, or a client-side route as an access-control mechanism. - Enumerate other users' data from inside a session and call it a supported API.
- Treat physical storage under
~/.afs/spacesor an isolated--root-pathas the same thing as session paths/userand/space. CLI inspection sees logical space fragments; the session view is a different composition.
Evidence
| Claim | Evidence |
|---|---|
Overlay design for /user, /tmp, /space | packages/aos/src/session/session-user-afs.ts |
Two-user /user isolation | runtimes/node/test/daemon/two-user-space-isolation.test.ts |
scope:user /space overlay (own root, cross-caller denial) | runtimes/node/test/daemon/scope-user-space-overlay.test.ts |
| Network base write gate | packages/aos/test/session/session-user-afs-base-write-gate.test.ts |
/space collections write-guard policy | packages/aos/src/session/space-write-gate.ts |
Continue with Inspect local spaces for offline CLI inspection of the same logical fragments without treating the CLI as a session.