#550: app-owned groups + Accounts/Groups tabs under Users & access (v0.6.199–200) #551

Merged
Cordy merged 21 commits from feat-550 into main 2026-09-14 19:00:30 +00:00
Owner

Implements #550 as approved (mockup admin-accounts-groups-mockup.html + review decisions).

Backend (v0.6.199, TDD red→green): auth.GroupStore at /data/.cairn/groups.json (statestore-bound, internal ids, case-insensitive single namespace, idempotent membership); WithAppGroups merges membership into User.Groups under the admin flag so app groups work as admin groups and peering allow-list entries; GroupsAPI under /api/v1/admin/groups (CRUD, bulk member add with per-name reporting, directory listing via the IdP admin client with known-names fallback, member drill-in); peering group resolution consults app groups first, then the IdP; spaces.Manager.ListGroups; five new audit verbs in the users group; collision with a known directory name is refused with 409 (decision 1).

Frontend (v0.6.200): Users & access becomes Access · Accounts · Groups · Seats. Access slims to identity wiring and counters — Administrators section removed as redundant (decision 4). Accounts hosts both account lists with one filter (name substring, the word "admin", app-group names) and a paged directory list. Groups: app-owned CRUD with chip member editing and reference-aware delete confirm, beside the read-only directory view with the honest no-client degradation. i18n ×4; #389 fence gate green on both frontend commits.

Full go test ./... green; red suite witnessed on the runner before implementation.

Implements #550 as approved (mockup `admin-accounts-groups-mockup.html` + review decisions). **Backend (v0.6.199, TDD red→green):** `auth.GroupStore` at `/data/.cairn/groups.json` (statestore-bound, internal ids, case-insensitive single namespace, idempotent membership); `WithAppGroups` merges membership into `User.Groups` under the admin flag so app groups work as admin groups and peering allow-list entries; `GroupsAPI` under `/api/v1/admin/groups` (CRUD, bulk member add with per-name reporting, directory listing via the IdP admin client with known-names fallback, member drill-in); peering group resolution consults app groups first, then the IdP; `spaces.Manager.ListGroups`; five new audit verbs in the `users` group; collision with a known directory name is refused with 409 (decision 1). **Frontend (v0.6.200):** Users & access becomes Access · Accounts · Groups · Seats. Access slims to identity wiring and counters — Administrators section removed as redundant (decision 4). Accounts hosts both account lists with one filter (name substring, the word "admin", app-group names) and a paged directory list. Groups: app-owned CRUD with chip member editing and reference-aware delete confirm, beside the read-only directory view with the honest no-client degradation. i18n ×4; #389 fence gate green on both frontend commits. Full `go test ./...` green; red suite witnessed on the runner before implementation.
Red phase. Pins: OpenGroupStore with internal ids and case-insensitive
name uniqueness, ErrGroupExists/ErrNoGroup, idempotent AddMember,
GroupsOf/MembersOf, WithAppGroups dedup merge into User.Groups, and
the GroupsAPI handler surface (create/list/rename/delete/members with
audit verbs group-create/-rename/-remove/-member-add/-member-remove,
single-namespace 409s per approved decision 1).
feat(#550): app-owned groups - store, auth merge, admin API, wiring (v0.6.199)
All checks were successful
release / image (push) Successful in 24s
696420cd39
GroupStore at /data/.cairn/groups.json (statestore-bound, internal ids,
case-insensitive single namespace, idempotent membership). WithAppGroups
merges membership into User.Groups under the admin flag, so app groups
work as admin groups and peering allow-list entries. GroupsAPI serves
/api/v1/admin/groups CRUD + bulk member add with per-name reporting,
plus a read-only directory-group listing (IdP admin client when
configured, known-names fallback otherwise) and the dir member
drill-in. Peering group resolution consults app groups first, then the
IdP. Five new audit verbs in the users group. Green on the red suite
from the previous commit.
one-shot: #550 wave 2a - Accounts tab split, Access slimmed, filter + paging
Some checks failed
ts550c-acc.yml / one-shot: #550 wave 2a - Accounts tab split, Access slimmed, filter + paging (push) Failing after 0s
ed4201464e
one-shot: #550 wave 2a rev2 - YAML-safe impl block
Some checks failed
ts550c-acc.yml / one-shot: #550 wave 2a rev2 - YAML-safe impl block (push) Failing after 0s
736ff11772
Users & access grows an Accounts tab: the local-accounts and
directory-accounts sections move there from Access, which slims to
identity wiring and counters (the Administrators section is removed
as redundant - approved in the mockup review). One filter covers both
sections and matches name substrings, the word 'admin', and app-group
names; rows show their app groups; the directory section pages 25 at
a time instead of rendering everything. #389 fence gate green.
feat(#550): Groups tab - app-owned CRUD beside read-only directory groups (v0.6.200)
All checks were successful
ci / test-and-build (pull_request) Successful in 54s
cc4bc60fc9
Fourth tab under Users & access. App-owned groups: create/rename/delete
dialogs, chip-style member editing with comma-separated bulk add and
per-name reporting, reference counts (peering lists, admin group) on
every row and in the delete confirm. Directory groups: read-only, live
listing through the IdP admin client when configured, honest
known-names fallback with an explanatory note otherwise, member
drill-in per group. i18n x4, #389 fence gate green, CHANGELOG
v0.6.200.
Cordy scheduled this pull request to auto merge when all checks succeed 2026-09-14 18:59:31 +00:00
Cordy merged commit 9eed140cb1 into main 2026-09-14 19:00:30 +00:00
Cordy deleted branch feat-550 2026-09-14 19:00:33 +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#551
No description provided.