feat(#570): the /shared overlay — reaching a granted path as its owner #574
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix-570b"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Slice 2 of #570. Slice 1 made the answer computable; this makes it reachable.
The overlay
/sharedbecomes a third synthetic root beside/homeand/spaces, laid out/shared/<owner>/<name>. The owner folder is not decoration — two people can each share areport.pdf, and a flat tree would have to mangle one of the names.It is shown only when the user actually has a grant. A folder that sits empty forever for everyone who was never shared anything reads as broken, not as a feature.
TestSyntheticRootListstill asserts exactly two entries and still passes.Reaching the file
encrypt/group.goderives the key scope from the backend path, so a personal file is encrypted to its owner. An entitled read therefore descends with the owner's identity (auth.ContextWithUser, the patternpeering/deliver.goandwopi.goalready use) or it decrypts to nothing. For a/spacespath the space's own identity already covers every member, so the swap is inert there.Write-role grants are writable on the same footing: the write re-encrypts into the owner's scope, which is the only scope the file can live in.
The attribution problem, and why the audit hook is where it is
Everything below the scope decorator sees the owner. Emitting the audit record down there would produce "alice read her own file" for every entitled access, making a share indistinguishable from ordinary activity — the opposite of what the record is for. So the hook fires in the scope driver, above the swap, with the real reader and the owner passed separately.
TestSharedAuditNamesTheReaderNotTheOwneris the fence, and it also asserts the inner driver saw the owner, so neither half can drift.share-grant-readandshare-grant-writeare registered ininternal/audit/verbs.gonow that they have an emit site — the deferral recorded on #570 when slice 1 landed.Boundaries held
reportsdoes not reachreports-private;TestSharedSiblingPrefixIsNotReachablefences it. Descending into a granted directory matches segment by segment.ensureRealskips granted paths. For a file grant the "prefix" is the file itself, and the lazy Mkdir would have put a directory over it.isRoot()replaces the four open-coded root guards. A granted path is never a root — its prefix is exactly the thing the grant exists to permit — and the old guard would otherwise have refused every write to a granted file.Still not wired
WithGrantsis not called incmd/cairnd/main.go, so/sharedis inert in a running instance. Nothing can create a grant yet — that is #571's panel and its API. Wiring it before then would ship a root that can only ever be empty.Red witnessed on the runner: fourteen tests, all failing on the missing overlay, before any of it existed.