feat(spaces): app-owned membership grants scope access (#214) #221

Merged
Cordy merged 3 commits from feat-scope-appowned into main 2026-08-13 16:33:23 +00:00
Owner

Wires spacestore (#213) into the scope driver so app-owned space memberships grant /spaces/<name> access, unioned with the existing read-only IdP-group spaces.

  • scope.Driver gains an optional *spacestore.Store (WithSpaces); nil = IdP groups only, unchanged behaviour.
  • resolve: after the IdP write/read-group checks, consults the store — owner/write member → read-write, read member → read-only. Non-members still get ErrNotFound. #177 (admins scoped like users) intact — no admin exemption added.
  • List("/spaces"): unions app-owned spaces with IdP-group spaces, deduped by name.
  • main.go: opens the store (cfg.SpacesPath, default /data/.cairn/spaces.json), attaches it to the scope driver, and registers the path in statePaths so it's age-encrypted in the backend like shares/holds.
  • config: SpacesPath field + default.

New scope_appowned_test.go: member write, owner write, read-role read-only (write → ErrReadOnly), non-member denied, /spaces listing + union-with-groups dedupe. Existing scope/IdP-group tests unchanged.

Nothing writes to the store via the API yet — that's #216. This makes the grants real and testable.

Wires `spacestore` (#213) into the scope driver so app-owned space memberships grant `/spaces/<name>` access, unioned with the existing read-only IdP-group spaces. - `scope.Driver` gains an optional `*spacestore.Store` (`WithSpaces`); nil = IdP groups only, unchanged behaviour. - `resolve`: after the IdP write/read-group checks, consults the store — owner/write member → read-write, read member → read-only. Non-members still get `ErrNotFound`. #177 (admins scoped like users) intact — no admin exemption added. - `List("/spaces")`: unions app-owned spaces with IdP-group spaces, deduped by name. - `main.go`: opens the store (`cfg.SpacesPath`, default `/data/.cairn/spaces.json`), attaches it to the scope driver, and registers the path in `statePaths` so it's age-encrypted in the backend like shares/holds. - `config`: `SpacesPath` field + default. New `scope_appowned_test.go`: member write, owner write, read-role read-only (write → `ErrReadOnly`), non-member denied, `/spaces` listing + union-with-groups dedupe. Existing scope/IdP-group tests unchanged. Nothing writes to the store via the API yet — that's #216. This makes the grants real and testable.
scaffold: run #214 wiring
All checks were successful
ship214 / edit (push) Successful in 7s
ffb995ea5b
feat(spaces): wire app-owned membership into scope + main (#214)
All checks were successful
ci / test-and-build (pull_request) Successful in 35s
cdf44e2de8
Cordy merged commit 133240e3b8 into main 2026-08-13 16:33:23 +00:00
Cordy deleted branch feat-scope-appowned 2026-08-13 16:33:25 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/Cairn#221
No description provided.