#690: opt-in group space - app groups stop synthesizing /spaces #710

Merged
Cordy merged 20 commits from feat-690 into main 2026-09-24 02:29:17 +00:00
Owner

Closes #690

App-owned groups are principals, not spaces. auth.WithAppGroups merging group names into User.Groups made every app group silently appear as /spaces/<group>; this PR ends that and replaces it with an explicit opt-in.

  • scope: new WithGroupExclusion(fn) predicate (wired to GroupStore.Has in main.go) removes app groups from /spaces synthesis in both the listing and path resolution. A provisioned space of the same name still grants through the spacestore.
  • spacestore: Space.Group link + SetGroup/FindByGroup.
  • groups API: POST /admin/groups accepts space/spaceName (default "<group> space"), provisions and links the space, materializes members as write members; member add/remove mirrors into the linked space (owner never evicted); DELETE /admin/groups/{id} on a linked group requires ?space=delete|keep (409 without), delete = trash + deactivate + tombstone, keep = unlink; appGroupRow.Space and spaceEntry.Group surface the link.
  • UI: New-group checkbox with prefilled, hand-edit-tracked space name (approved mockup, both amendments); interim guNewSpaceNote hint removed; delete dialog gains fate radios; spaces inventory shows Owned by X · group Y; 8 new i18n keys ×4.
  • Tests: scope_exclude_test.go, spacestore/grouplink_test.go, api/groups_space_test.go, web/test/qa690.test.js; the stale interim pin in qa2.test.js retired.

No migration for previously synthesized dogfood spaces by design (manual cleanup, per decision on the issue).

Closes #690 App-owned groups are principals, not spaces. `auth.WithAppGroups` merging group names into `User.Groups` made every app group silently appear as `/spaces/<group>`; this PR ends that and replaces it with an explicit opt-in. - **scope**: new `WithGroupExclusion(fn)` predicate (wired to `GroupStore.Has` in main.go) removes app groups from `/spaces` synthesis in both the listing and path resolution. A provisioned space of the same name still grants through the spacestore. - **spacestore**: `Space.Group` link + `SetGroup`/`FindByGroup`. - **groups API**: `POST /admin/groups` accepts `space`/`spaceName` (default `"<group> space"`), provisions and links the space, materializes members as write members; member add/remove mirrors into the linked space (owner never evicted); `DELETE /admin/groups/{id}` on a linked group requires `?space=delete|keep` (409 without), delete = trash + deactivate + tombstone, keep = unlink; `appGroupRow.Space` and `spaceEntry.Group` surface the link. - **UI**: New-group checkbox with prefilled, hand-edit-tracked space name (approved mockup, both amendments); interim `guNewSpaceNote` hint removed; delete dialog gains fate radios; spaces inventory shows `Owned by X · group Y`; 8 new i18n keys ×4. - **Tests**: `scope_exclude_test.go`, `spacestore/grouplink_test.go`, `api/groups_space_test.go`, `web/test/qa690.test.js`; the stale interim pin in `qa2.test.js` retired. No migration for previously synthesized dogfood spaces by design (manual cleanup, per decision on the issue).
scout(#690): exact UI anchors for gadddlg/gdeldlg/renderer/main wiring
All checks were successful
scout-f690b / scout (push) Successful in 1s
5af9a4cc90
test(#690): RED - spacestore group link (SetGroup/FindByGroup)
All checks were successful
scout-f690b / scout (push) Successful in 1s
0ca2c0222d
test(#690): RED - scope group exclusion (app groups stop synthesizing spaces)
All checks were successful
scout-f690b / scout (push) Successful in 1s
66ec2bd702
test(#690): RED - opt-in group space (create, mirror, delete fate, inventory link)
All checks were successful
scout-f690b / scout (push) Successful in 1s
fcd31c3075
test(#690): RED - UI pins for opt-in group space, delete fate, honest inventory
All checks were successful
scout-f690b / scout (push) Successful in 1s
dcdb744154
test(#690): pin the house tf() idiom for the group label
All checks were successful
scout-f690b / scout (push) Successful in 1s
7694492109
splice(#690): anchored edits - scope exclusion, spacestore link, groups API, UI
All checks were successful
scout-f690b / scout (push) Successful in 1s
23516aed0a
one-shot(#690): RED gate, splice, gofmt+vet+build+test, self-cleaning commit
Some checks failed
fix-690 / fix (push) Failing after 1m10s
scout-f690b / scout (push) Successful in 1s
60752e6d6e
splice(#690): deactivate before tombstone in the delete fate (DeleteTombstone precondition)
Some checks failed
fix-690 / fix (push) Failing after 1m6s
scout-f690b / scout (push) Successful in 1s
ef901ce914
test(#690): retire the interim guNewSpaceNote pin - the hint is removed for good
All checks were successful
fix-690 / fix (push) Successful in 1m13s
scout-f690b / scout (push) Successful in 0s
aab153a196
Scope exclusion wired to GroupStore.Has; spacestore Group link; groups API provisions, mirrors membership and settles the space fate (?space=delete|keep); UI checkbox with prefilled name, delete-fate radios, owner+group inventory line; i18n x4.
one-shot: apply v0.6.261 changelog entry, self-remove
All checks were successful
chg-261 / chg (push) Successful in 5s
6d73b801ba
docs: changelog for v0.6.261 (#690 opt-in group space)
All checks were successful
ci / test-and-build (pull_request) Successful in 1m23s
10da4265a9
Cordy merged commit b1fb64b796 into main 2026-09-24 02:29:17 +00:00
Cordy deleted branch feat-690 2026-09-24 02:29:19 +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#710
No description provided.