Configure the IdP admin client on the dogfood and verify Users & access end to end #346

Closed
opened 2026-08-27 23:56:11 +00:00 by Cordy · 6 comments
Owner

Follow-up to #345, which built the Users & access page. The page is correct today but the dogfood only exercises its degraded half, so the interesting path has never actually run against a real directory.

Current state on cairn-enc

auth.groups.keycloak* is not configured, so spacesMgr is nil, so Admin.GroupMembers is nil. The page therefore shows:

  • Provider · OpenID Connect · <issuer> · Connected
  • Admin group · the configured group name, with no member count
  • Admin client · Not configured · Cairn cannot list who is in the group · Off
  • Signed in now, Active today
  • no Administrators section at all

That is the designed behaviour (a partial list would look authoritative), but it means the resolved path — member count, administrator rows, "You", "Signed in now" / "Last active" — has only ever been exercised by unit tests with a stubbed GroupMembers.

Work

1. Keycloak service account

Against the test IdP (192.168.10.248, realm cordyceps):

  • Create a confidential client, service accounts enabled, standard flow off.
  • Grant the service account the realm-management client roles view-users and query-groups.
  • Explicitly do not grant manage-users. Reading a group to display it never writes to the directory. manage-users is only for auth.groups.manage, the IdP-managed-spaces opt-in (ADR 0001), and is a materially higher-privilege credential.
  • Confirm an admin group exists in the realm with two or three members, at least one of whom is not nikola-test, so the list is visibly more than "just me".

2. Config

Into the untracked cairn-enc-config secret (not GitOps, so Argo will not revert it):

{
  "auth": {
    "adminGroups": ["cairn-admins"],
    "groups": {
      "keycloakBaseUrl": "http://192.168.10.248",
      "keycloakRealm": "cordyceps",
      "keycloakClientId": "cairn-groups",
      "keycloakClientSecret": "…"
    }
  }
}

Note the side effect worth watching for: with auth.mode: oidc and this client present, main.go also enables live group resolution (#96) — group and admin changes stop riding the session snapshot and re-resolve per request behind a 60s cache. That is a behaviour change beyond this page and should be observed deliberately rather than discovered.

3. Verify

  • Admin client row flips to Configured · group membership can be resolved · On
  • Admin group row gains the member count chip, and the number matches Keycloak
  • Administrators section appears, sorted, with the union of auth.admins and the group
  • Your own row carries "You"
  • A second signed-in admin shows "Signed in now"
  • An admin with audit history but no live session shows "Last active …"
  • An admin with neither shows the address alone, no empty second line
  • Remove someone from the group in Keycloak: they disappear from the list (immediately with live groups, at next sign-in without)
  • Break the client secret on purpose: the list disappears entirely rather than degrading to the static names, and the Admin client row explains it. This is the assertion TestAdminNamesIncompleteOnResolveError makes in the abstract — confirm it holds against a real failing Keycloak.

4. The two-source behaviour

Deliberately confirm across a redeploy, because it looks like a bug and is not:

  • Before redeploy: note both Signed in now and Active today
  • After redeploy: Signed in now reads 0 (sessions are memory-only, lost by design — internal/auth/session.go), Active today keeps its number (audit log survives)
  • Sign in again: Signed in now recovers

If this reads as broken to a fresh pair of eyes in the beta, the row labels are the thing to change, not the sources.

5. Docs

  • docs/handbook/users-access.md exists (shipped in #345) but is not linked from docs/handbook/index.md — add it.
  • Correct the Keycloak role names in that page against what the realm actually required, if step 1 turns up anything different.
  • Add the observed live-group-resolution side effect to the page, since enabling this client for the admin list also changes authorization timing.
  • Feeds #109 (handbook content lifted onto swisscairn.ch).
  • #345 built the page and the endpoint
  • #343 is the copy review for the audit retention string, same "check it on a running instance" batch
  • #129 (admin warning for group-only receiver lists without an IdP admin client) is the peering-side symptom of the same missing credential, and should be re-read once this is configured — the two may want one shared "no admin client" explanation rather than two.
Follow-up to #345, which built the Users & access page. The page is correct today but the dogfood only exercises its *degraded* half, so the interesting path has never actually run against a real directory. ## Current state on `cairn-enc` `auth.groups.keycloak*` is not configured, so `spacesMgr` is nil, so `Admin.GroupMembers` is nil. The page therefore shows: - Provider · `OpenID Connect · <issuer>` · Connected - Admin group · the configured group name, **with no member count** - Admin client · *Not configured · Cairn cannot list who is in the group* · Off - Signed in now, Active today - **no Administrators section at all** That is the designed behaviour (a partial list would look authoritative), but it means the resolved path — member count, administrator rows, "You", "Signed in now" / "Last active" — has only ever been exercised by unit tests with a stubbed `GroupMembers`. ## Work ### 1. Keycloak service account Against the test IdP (192.168.10.248, realm `cordyceps`): - Create a confidential client, service accounts enabled, standard flow off. - Grant the service account the `realm-management` client roles **`view-users`** and **`query-groups`**. - Explicitly **do not** grant `manage-users`. Reading a group to display it never writes to the directory. `manage-users` is only for `auth.groups.manage`, the IdP-managed-spaces opt-in (ADR 0001), and is a materially higher-privilege credential. - Confirm an admin group exists in the realm with two or three members, at least one of whom is not `nikola-test`, so the list is visibly more than "just me". ### 2. Config Into the untracked `cairn-enc-config` secret (not GitOps, so Argo will not revert it): ```json { "auth": { "adminGroups": ["cairn-admins"], "groups": { "keycloakBaseUrl": "http://192.168.10.248", "keycloakRealm": "cordyceps", "keycloakClientId": "cairn-groups", "keycloakClientSecret": "…" } } } ``` Note the side effect worth watching for: with `auth.mode: oidc` and this client present, `main.go` also enables **live group resolution** (#96) — group and admin changes stop riding the session snapshot and re-resolve per request behind a 60s cache. That is a behaviour change beyond this page and should be observed deliberately rather than discovered. ### 3. Verify - [ ] Admin client row flips to *Configured · group membership can be resolved* · On - [ ] Admin group row gains the member count chip, and the number matches Keycloak - [ ] Administrators section appears, sorted, with the union of `auth.admins` and the group - [ ] Your own row carries "You" - [ ] A second signed-in admin shows "Signed in now" - [ ] An admin with audit history but no live session shows "Last active …" - [ ] An admin with neither shows the address alone, no empty second line - [ ] Remove someone from the group in Keycloak: they disappear from the list (immediately with live groups, at next sign-in without) - [ ] Break the client secret on purpose: the list disappears entirely rather than degrading to the static names, and the Admin client row explains it. This is the assertion `TestAdminNamesIncompleteOnResolveError` makes in the abstract — confirm it holds against a real failing Keycloak. ### 4. The two-source behaviour Deliberately confirm across a redeploy, because it looks like a bug and is not: - [ ] Before redeploy: note both **Signed in now** and **Active today** - [ ] After redeploy: Signed in now reads 0 (sessions are memory-only, lost by design — `internal/auth/session.go`), Active today keeps its number (audit log survives) - [ ] Sign in again: Signed in now recovers If this reads as broken to a fresh pair of eyes in the beta, the row *labels* are the thing to change, not the sources. ### 5. Docs - [ ] `docs/handbook/users-access.md` exists (shipped in #345) but is **not linked from `docs/handbook/index.md`** — add it. - [ ] Correct the Keycloak role names in that page against what the realm actually required, if step 1 turns up anything different. - [ ] Add the observed live-group-resolution side effect to the page, since enabling this client for the admin list also changes authorization timing. - [ ] Feeds #109 (handbook content lifted onto swisscairn.ch). ## Related - #345 built the page and the endpoint - #343 is the copy review for the audit retention string, same "check it on a running instance" batch - #129 (admin warning for group-only receiver lists without an IdP admin client) is the peering-side symptom of the same missing credential, and should be re-read once this is configured — the two may want one shared "no admin client" explanation rather than two.
Author
Owner

Premise correction + decisions (Nikola, 2026-09-04).

The degraded state this issue describes no longer exists on either dogfood:

  • cairn-enc runs the adopted custody client (back-compat path: keycloak-profile custody + no auth.groups.* → custody client becomes the admin client with manage on). Power mode and live groups have been active for some time. This is blessed as deliberate: keycloak-profile custody independently requires manage-users (it writes each user's age identity into profile attributes — key minting proves the role is present), and OIDC-group-backed spaces are a wanted feature, which also requires manage-users (group CRUD + membership edits sit under it; view-users/query-groups are enumeration only). Given that feature set, the current single client is minimal privilege. Follow-up niceness: set auth.groups.* explicitly in the secret so the config states the choice instead of inheriting it via adoption.
  • cairn-openbao boots with custody=openbao, live groups on, and no power-mode line — i.e. an explicit auth.groups.* read client with manage off, app-owned spaces. That is the least-privilege configuration step 1 of this issue asked for; it already exists. Remaining check: confirm in Keycloak that its service account holds only view-users + query-groups and is not a reuse of the enc custody client (if it is, mint a dedicated read-only client — zero feature loss on bao).

Key blast-radius insight for the docs (shipping now): on a keycloak-profile custody realm, even the read tier (view-users) can read every user's age identity from profile attributes — and manage-users can replace them, or grant admin in every group-trusting app. OpenBao custody separates the radii: the bao token (prefix-scoped KV policy) touches keys but never accounts; the Keycloak client stays read-only and never touches keys. This contrast goes into the handbook as the operator decision driver.

Still open on this issue: the step-3 verification checklist (operator pass, possibly via browser automation) and the bao client-identity check above. Docs items ship in the next commit.

**Premise correction + decisions (Nikola, 2026-09-04).** The degraded state this issue describes no longer exists on either dogfood: - **cairn-enc** runs the *adopted* custody client (back-compat path: keycloak-profile custody + no `auth.groups.*` → custody client becomes the admin client with `manage` on). Power mode and live groups have been active for some time. This is **blessed as deliberate**: keycloak-profile custody independently requires `manage-users` (it writes each user's age identity into profile attributes — key minting proves the role is present), and OIDC-group-backed spaces are a wanted feature, which also requires `manage-users` (group CRUD + membership edits sit under it; `view-users`/`query-groups` are enumeration only). Given that feature set, the current single client **is** minimal privilege. Follow-up niceness: set `auth.groups.*` explicitly in the secret so the config states the choice instead of inheriting it via adoption. - **cairn-openbao** boots with `custody=openbao`, live groups on, and **no power-mode line** — i.e. an *explicit* `auth.groups.*` read client with `manage` off, app-owned spaces. That is the least-privilege configuration step 1 of this issue asked for; it already exists. Remaining check: confirm in Keycloak that its service account holds only `view-users` + `query-groups` and is **not** a reuse of the enc custody client (if it is, mint a dedicated read-only client — zero feature loss on bao). **Key blast-radius insight for the docs (shipping now):** on a keycloak-profile custody realm, even the read tier (`view-users`) can read *every user's age identity* from profile attributes — and `manage-users` can replace them, or grant admin in every group-trusting app. OpenBao custody separates the radii: the bao token (prefix-scoped KV policy) touches keys but never accounts; the Keycloak client stays read-only and never touches keys. This contrast goes into the handbook as the operator decision driver. **Still open on this issue:** the step-3 verification checklist (operator pass, possibly via browser automation) and the bao client-identity check above. Docs items ship in the next commit.
Author
Owner

Step-3 verification pass, run via browser automation against both dogfoods (2026-09-05, v0.6.127). Existing SSO sessions reused; no credentials entered.

Verified on both files-bao and files (#admin/users), identical healthy state:

  • Admin client row: Configured · group membership can be resolved · On
  • Admin group row: cairn-admins with member-count chip (2 members), matching the rendered list exactly
  • Administrators section present and sorted: manu-admin, nikola-test — visibly more than "just me"
  • Own row carries You (and Signed in now)
  • Admin with neither session nor audit history (manu-admin): name alone, no empty second line
  • Presence tallies coherent: Signed in now — 1 person, Active today — 1 person
  • Provider row: OpenID Connect · id.c0rdyceps.ch/realms/cordyceps · Connected

Not verifiable autonomously (and why):

  • Second signed-in admin shows Signed in now / Last active rows — needs manu-admin to actually sign in; no credential entry by automation, ever.
  • Keycloak side: bao's auth.groups service account holds only view-users + query-groups, and is a distinct client from the enc custody client — the admin console presents a login form; stopped there. Read-only inspection can be driven by automation the moment an operator session exists.
  • Group-removal round trip — a directory write; wants an explicit operator go even with a session.
  • Broken-secret failure mode — needs kubectl edit secret + restart; the code path is covered by TestAdminNamesIncompleteOnResolveError, so this stays a nice-to-have live confirmation.
  • §4 two-source redeploy observation — will be ticked deliberately at the next natural release rollout (redeploys happen near-daily; the pattern was implicitly visible across yesterday's v0.6.124→127 cycle: sessions dropped, Active today survived, sign-in recovered).

Docs items (§5) shipped 2026-09-04 (users-access.md + index row + role matrix + live-groups side effect + custody blast-radius comparison).

**Step-3 verification pass, run via browser automation against both dogfoods (2026-09-05, v0.6.127).** Existing SSO sessions reused; no credentials entered. Verified on **both** `files-bao` and `files` (`#admin/users`), identical healthy state: - [x] Admin client row: *Configured · group membership can be resolved* · **On** - [x] Admin group row: `cairn-admins` with member-count chip (**2 members**), matching the rendered list exactly - [x] Administrators section present and sorted: `manu-admin`, `nikola-test` — visibly more than "just me" - [x] Own row carries **You** (and *Signed in now*) - [x] Admin with neither session nor audit history (`manu-admin`): name alone, **no empty second line** - [x] Presence tallies coherent: *Signed in now — 1 person*, *Active today — 1 person* - [x] Provider row: `OpenID Connect · id.c0rdyceps.ch/realms/cordyceps` · Connected **Not verifiable autonomously** (and why): - [ ] Second signed-in admin shows *Signed in now* / *Last active* rows — needs `manu-admin` to actually sign in; no credential entry by automation, ever. - [ ] Keycloak side: bao's `auth.groups` service account holds **only** `view-users` + `query-groups`, and is a **distinct client** from the enc custody client — the admin console presents a login form; stopped there. Read-only inspection can be driven by automation the moment an operator session exists. - [ ] Group-removal round trip — a directory write; wants an explicit operator go even with a session. - [ ] Broken-secret failure mode — needs `kubectl edit secret` + restart; the code path is covered by `TestAdminNamesIncompleteOnResolveError`, so this stays a nice-to-have live confirmation. - [ ] §4 two-source redeploy observation — will be ticked deliberately at the next natural release rollout (redeploys happen near-daily; the pattern was implicitly visible across yesterday's v0.6.124→127 cycle: sessions dropped, *Active today* survived, sign-in recovered). Docs items (§5) shipped 2026-09-04 (`users-access.md` + index row + role matrix + live-groups side effect + custody blast-radius comparison).
Author
Owner

Keycloak inspection completed (2026-09-05, operator signed in to the console, automation drove read-only):

  • Distinct clients confirmed — realm cordyceps has three Cairn clients: cairn (public PKCE login), cairn-bao-groups, cairn-keycustody. Bao's groups client is NOT a reuse of the custody client.
  • cairn-bao-groups is exactly least-privilege: service-account roles are realm-management view-users + realm-management query-groups (+ default-roles) — no manage-users, nothing else. The bao side of this issue is fully as specified.
  • cairn-admins membership matches: exactly 2 members in Keycloak (manu-admin / Manuel Novak, nikola-test) — matches the Users & access chip and rendered list on both instances.

⚠️ Finding — cairn-keycustody is over-privileged relative to the blessed minimum. Its service account holds manage-users, view-users, query-users, query-groups plus manage-realm and query-realms. The blessed power-mode set (per the users-access.md role matrix) is manage-users + view-users + query-groups; query-users is redundant beside view-users but harmless. manage-realm is not — it allows changing realm configuration itself (auth flows, realm settings, events config), which nothing in Cairn's custody or IdP-managed-spaces path uses. Recommendation: unassign manage-realm (and query-realms) from service-account-cairn-keycustody. If anything unexpected breaks (space create/membership edit, key minting for a new user), re-assigning is one click — but per the documented model, nothing should.

Remaining live checks now unblocked by the console session, pending explicit operator go (both are directory writes): the role trim above, and the checklist's group-removal round trip (remove manu-admin from cairn-admins → confirm both instances drop him from Administrators within the 60s live-groups cache → re-add → confirm restored).

**Keycloak inspection completed (2026-09-05, operator signed in to the console, automation drove read-only):** - [x] **Distinct clients confirmed** — realm `cordyceps` has three Cairn clients: `cairn` (public PKCE login), `cairn-bao-groups`, `cairn-keycustody`. Bao's groups client is NOT a reuse of the custody client. - [x] **`cairn-bao-groups` is exactly least-privilege**: service-account roles are `realm-management view-users` + `realm-management query-groups` (+ default-roles) — no `manage-users`, nothing else. The bao side of this issue is fully as specified. - [x] **`cairn-admins` membership matches**: exactly 2 members in Keycloak (`manu-admin` / Manuel Novak, `nikola-test`) — matches the Users & access chip and rendered list on both instances. ⚠️ **Finding — `cairn-keycustody` is over-privileged relative to the blessed minimum.** Its service account holds `manage-users`, `view-users`, `query-users`, `query-groups` **plus `manage-realm` and `query-realms`**. The blessed power-mode set (per the users-access.md role matrix) is `manage-users` + `view-users` + `query-groups`; `query-users` is redundant beside `view-users` but harmless. **`manage-realm` is not** — it allows changing realm configuration itself (auth flows, realm settings, events config), which nothing in Cairn's custody or IdP-managed-spaces path uses. Recommendation: unassign `manage-realm` (and `query-realms`) from `service-account-cairn-keycustody`. If anything unexpected breaks (space create/membership edit, key minting for a new user), re-assigning is one click — but per the documented model, nothing should. Remaining live checks now unblocked by the console session, pending explicit operator go (both are directory writes): the role trim above, and the checklist's group-removal round trip (remove `manu-admin` from `cairn-admins` → confirm both instances drop him from Administrators within the 60s live-groups cache → re-add → confirm restored).
Author
Owner

Directory writes executed with operator approval (2026-09-05), both verified live:

  1. Role trim on cairn-keycustody manage-realm and query-realms unassigned; the service account now holds exactly manage-users + view-users + query-users + query-groups (+ default-roles). Custody smoke-tested afterwards: encrypted file preview on files decrypts fine — the trim broke nothing, as the role matrix predicted.
  2. Group-removal round trip — removed manu-admin from cairn-admins; within the 60s live-groups cache window both the chip (1 members) and the Administrators list updated (list showed only nikola-test). Re-added; page restored to 2 members with manu-admin back. Live group resolution (#96) demonstrated end to end against the real directory.

New copy nit found during the round trip: the admin-group chip reads "1 members" — the member count bypasses tn(). Singular form needed (×4 locales). Will ride along with the next UI batch.

Checklist state after today: everything is ticked except (a) second-admin presence rows — needs manu-admin to sign in once; (b) the broken-secret live confirmation — optional, unit-covered; (c) the §4 redeploy observation — deliberately at the next release rollout. Plus the config nicety of stating auth.groups.* explicitly in cairn-enc-config instead of inheriting via adoption (operator kubectl, no behaviour change).

**Directory writes executed with operator approval (2026-09-05), both verified live:** 1. **Role trim on `cairn-keycustody`** ✅ — `manage-realm` and `query-realms` unassigned; the service account now holds exactly `manage-users` + `view-users` + `query-users` + `query-groups` (+ default-roles). Custody smoke-tested afterwards: encrypted file preview on `files` decrypts fine — the trim broke nothing, as the role matrix predicted. 2. **Group-removal round trip** ✅ — removed `manu-admin` from `cairn-admins`; within the 60s live-groups cache window both the chip (**1 members**) and the Administrators list updated (list showed only `nikola-test`). Re-added; page restored to 2 members with `manu-admin` back. Live group resolution (#96) demonstrated end to end against the real directory. **New copy nit found during the round trip:** the admin-group chip reads "**1 members**" — the member count bypasses `tn()`. Singular form needed (×4 locales). Will ride along with the next UI batch. **Checklist state after today:** everything is ticked except (a) second-admin presence rows — needs `manu-admin` to sign in once; (b) the broken-secret live confirmation — optional, unit-covered; (c) the §4 redeploy observation — deliberately at the next release rollout. Plus the config nicety of stating `auth.groups.*` explicitly in `cairn-enc-config` instead of inheriting via adoption (operator kubectl, no behaviour change).
Author
Owner

Final verification rounds (2026-09-05) — checklist complete.

Second-admin presence (§3): manu-admin signed in live. Observed from his perspective: manu-admin — You · Signed in now, nikola-test — Last active 59 minutes ago, tallies 1 signed in / 2 active today. Later, from Nikola's perspective after the test cycle: rows flipped correctly (nikola-test — You · Signed in now, manu-admin — Last active 8 minutes ago). Every presence presentation now seen live: You-marker tracking the viewer, Signed in now, Last active N ago, and bare name.

Broken-secret failure mode (§3, run for real): auth.groups.keycloakClientSecret deliberately broken on bao (operator kubectl, sed-verified one-line diff), pod restarted. Result:

  • Administrators section disappeared entirely — no degradation to authoritative-looking static names. TestAdminNamesIncompleteOnResolveError holds against a real failing Keycloak.
  • Member-count chip gone from the Admin group row.
  • The Admin client row kept reading "Configured · group membership can be resolved · On" while resolution was failing. The row reflects config presence, not live health — the page signals breakage only by omission. An operator sees a green On chip and a missing list with no explanation. Genuine gap the unit test cannot catch; filed as #426 item 3.

Secret restored from backup, pod restarted, healthy state confirmed (chip, list, presence all back).

§4 two-source behaviour, observed deliberately across the same restarts: sessions died each rollout (Signed in now dropped to just the fresh viewer), Active today kept 2 people from the audit log throughout, and sign-ins recovered the counts. The labels read fine to these eyes — no relabel needed for the beta yet.

Remaining on this issue: only the config nicety — stating auth.groups.* explicitly in cairn-enc-config (with manage: true to preserve power mode) instead of inheriting via adoption. Zero behaviour change; commands handed to the operator. Closeable once that lands (or closeable now with the nicety tracked as ops hygiene).

**Final verification rounds (2026-09-05) — checklist complete.** **Second-admin presence (§3):** `manu-admin` signed in live. Observed from his perspective: `manu-admin — You · Signed in now`, `nikola-test — Last active 59 minutes ago`, tallies 1 signed in / 2 active today. Later, from Nikola's perspective after the test cycle: rows flipped correctly (`nikola-test — You · Signed in now`, `manu-admin — Last active 8 minutes ago`). Every presence presentation now seen live: You-marker tracking the viewer, Signed in now, Last active N ago, and bare name. **Broken-secret failure mode (§3, run for real):** `auth.groups.keycloakClientSecret` deliberately broken on bao (operator kubectl, sed-verified one-line diff), pod restarted. Result: - ✅ Administrators section **disappeared entirely** — no degradation to authoritative-looking static names. `TestAdminNamesIncompleteOnResolveError` holds against a real failing Keycloak. - ✅ Member-count chip gone from the Admin group row. - ❌ **The Admin client row kept reading "Configured · group membership can be resolved · On" while resolution was failing.** The row reflects config presence, not live health — the page signals breakage only by omission. An operator sees a green On chip and a missing list with no explanation. Genuine gap the unit test cannot catch; **filed as #426 item 3**. Secret restored from backup, pod restarted, healthy state confirmed (chip, list, presence all back). **§4 two-source behaviour, observed deliberately across the same restarts:** sessions died each rollout (Signed in now dropped to just the fresh viewer), **Active today kept 2 people** from the audit log throughout, and sign-ins recovered the counts. The labels read fine to these eyes — no relabel needed for the beta yet. **Remaining on this issue:** only the config nicety — stating `auth.groups.*` explicitly in `cairn-enc-config` (with `manage: true` to preserve power mode) instead of inheriting via adoption. Zero behaviour change; commands handed to the operator. Closeable once that lands (or closeable now with the nicety tracked as ops hygiene).
Author
Owner

Closing — every item done (2026-09-05).

Final step landed: auth.groups.* now stated explicitly in cairn-enc-config (mirrored from the custody block via jq, manage: true), pod restarted. Boot log confirms identical behaviour to the adopted path: storage encryption enabled custody=keycloak-profile, the power-mode WARN (IdP-managed spaces enabled … requires manage-users, ADR 0001), and live group resolution enabled (#96). The config now states the choice instead of inheriting it.

Where this issue ended up versus where it started: it asked for a least-privilege read client and a first-ever exercise of the resolved path. It closes with — both dogfoods verified end to end on the resolved path (all presence states, member counts matching the directory, You-marker tracking the viewer); bao's read client confirmed exactly view-users+query-groups and distinct from custody; enc's custody client trimmed of an over-grant (manage-realm, query-realms) found during verification, with custody smoke-tested after; the group-removal round trip proving live groups against the real directory; the broken-secret failure mode confirmed fail-closed (with one UX gap filed as #426 item 3); §4's two-source behaviour observed deliberately across real restarts; docs shipped 2026-09-04; and two net-new findings cut to #426.

Both instances end the day more locked down and better verified than the issue asked for.

**Closing — every item done (2026-09-05).** Final step landed: `auth.groups.*` now stated **explicitly** in `cairn-enc-config` (mirrored from the custody block via jq, `manage: true`), pod restarted. Boot log confirms identical behaviour to the adopted path: `storage encryption enabled custody=keycloak-profile`, the power-mode WARN (`IdP-managed spaces enabled … requires manage-users, ADR 0001`), and `live group resolution enabled (#96)`. The config now states the choice instead of inheriting it. Where this issue ended up versus where it started: it asked for a least-privilege read client and a first-ever exercise of the resolved path. It closes with — both dogfoods verified end to end on the resolved path (all presence states, member counts matching the directory, You-marker tracking the viewer); bao's read client confirmed *exactly* `view-users`+`query-groups` and distinct from custody; enc's custody client **trimmed** of an over-grant (`manage-realm`, `query-realms`) found during verification, with custody smoke-tested after; the group-removal round trip proving live groups against the real directory; the broken-secret failure mode confirmed fail-closed (with one UX gap filed as #426 item 3); §4's two-source behaviour observed deliberately across real restarts; docs shipped 2026-09-04; and two net-new findings cut to #426. Both instances end the day more locked down and better verified than the issue asked for.
Cordy closed this issue 2026-09-05 01:45:49 +00:00
Sign in to join this conversation.
No labels
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#346
No description provided.