feat(#570): shares gain an addressee — grant model, store and resolution #573
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix-570"
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 1 of #570, backend only: a share can now be addressed to a principal instead of to a URL.
What lands
SharegainsAddresseeKind(user/group),Addressee,Role(read/write) andID. A record is either a link (token-addressed) or a grant (principal-addressed) —IsGrant()is the discriminator.Entitles(username, groups)answers "does THIS record grant a role", case-insensitively, with no cross-kind matching and fail-closed on an unknown role.FileStorepersists grants alongside links. Grants have no token, so every write-side map access is re-keyed throughKey()(g:<id>for a grant, the token for a link) — including the load path and theCreaterollback. Missing one would have collapsed every grant onto""on reload.ListForPath/ListForAddresseequery grants only. Links never surface through them, or #550's Used-by count silently becomes a link count.RoleForPathresolves the strongest role a principal holds on a path, skipping the owner.Two design notes worth reading
Storeis not widened. The first attempt added the two queries toStoreand brokerecStoreinpublic_recovery_test.go— a link-only double that will never answer a grant query. The queries live on a narrowGrantQuerierinstead; the public-link handler keeps needingStoreand nothing else.Exact path match, not prefix. A grant on
/home/alice/reportsmust not reach/home/alice/reports-private. Folder sharing is a separate feature with its own semantics; inheriting by string prefix is a data leak that reads like a typo. Test:TestRoleForPathIsExact.What this deliberately does not do
/sharedtree — a recipient still cannot reach the path. The scope driver's synthetic root is/home+/spaces, and/homeresolves to the requester's own tree. This slice makes the answer computable; the next makes it reachable.share-grant/share-grant-revokehave no emit site until the grant create/revoke API and the entitled read exist. The registry ininternal/audit/verbs.gois append-only, so a name shipped ahead of its feature is permanent — they land with the code that emits them.encrypt/group.goderives the key scope from the backend path, so an entitled read goes through the owner's scope (next slice).Red witnessed on the runner for
grant_test.goandgrantstore_test.gobefore either implementation existed.