docs(kanidm): record that provision scope maps are additive, not authoritative #279

Sammanfogat
supernaut sammanfogade 1 incheckning från docs/275-scope-maps-additive in i main 2026-07-31 11:44:24 +00:00
Ägare

Follow-up to #278, which shipped half-fixed.

What happened

The #278 apply removed the localhost origin from the production bitborg-web client (verified live — that half worked), but did not fix the dev client's visibility. Live state after the apply:

bitborg-web-dev  scope = [forgejo_users@…, forgejo_admins@…]

The declared forgejo_admins mapping was added; forgejo_users was left in place. So "bitborg portal (dev)" is still listed for every user — the exact symptom the change set out to fix.

Why

kanidm-provision applies each declared scope map but has no removal logic for undeclared ones. There is no scope-map equivalent of removeOrphanedClaimMaps.

The trap is the asymmetry with origins:

Attribute Behaviour
originUrl Replaced wholesale — declaring one URL removes the others (this is why the localhost fix worked)
scopeMaps Additive only — declaring a mapping adds it; removing one from the declaration is a no-op

I read this in upstream when writing #278 — the note said "no explicit removal logic visible" — and treated it as an unimportant gap rather than a blocker, then assumed symmetry with origins. That assumption is what shipped a half-fix with a PR body claiming a full one.

Consequence worth internalising

The failure mode is silent: the converge reports success, declared and live state disagree, and nothing surfaces the difference. Anyone editing kanidm_oauth2_clients should know that removing a group from scope_maps does nothing to the server.

Removal is manual until a carried patch adds it (the entryManagedBy precedent):

kanidm system oauth2 delete-scope-map bitborg-web-dev forgejo_users --name idm_admin

Follow-up options for #275

  1. Carry a patch adding authoritative scope-map handling, so the declaration means what it appears to mean.
  2. Extend the existing account-policy drift gate to also assert live scope maps against the declaration — turning a silent mismatch into a failed apply, without needing a patch.

Option 2 is cheaper and composes with the gate already merged in #277.

Follow-up to #278, which shipped half-fixed. ## What happened The #278 apply removed the localhost origin from the production `bitborg-web` client (verified live — that half worked), but did **not** fix the dev client's visibility. Live state after the apply: ``` bitborg-web-dev scope = [forgejo_users@…, forgejo_admins@…] ``` The declared `forgejo_admins` mapping was **added**; `forgejo_users` was left in place. So "bitborg portal (dev)" is still listed for every user — the exact symptom the change set out to fix. ## Why kanidm-provision applies each declared scope map but has **no removal logic** for undeclared ones. There is no scope-map equivalent of `removeOrphanedClaimMaps`. The trap is the asymmetry with origins: | Attribute | Behaviour | | --- | --- | | `originUrl` | **Replaced wholesale** — declaring one URL removes the others (this is why the localhost fix worked) | | `scopeMaps` | **Additive only** — declaring a mapping adds it; removing one from the declaration is a no-op | I read this in upstream when writing #278 — the note said "no explicit removal logic visible" — and treated it as an unimportant gap rather than a blocker, then assumed symmetry with origins. That assumption is what shipped a half-fix with a PR body claiming a full one. ## Consequence worth internalising The failure mode is **silent**: the converge reports success, declared and live state disagree, and nothing surfaces the difference. Anyone editing `kanidm_oauth2_clients` should know that removing a group from `scope_maps` does nothing to the server. Removal is manual until a carried patch adds it (the `entryManagedBy` precedent): ``` kanidm system oauth2 delete-scope-map bitborg-web-dev forgejo_users --name idm_admin ``` ## Follow-up options for #275 1. Carry a patch adding authoritative scope-map handling, so the declaration means what it appears to mean. 2. Extend the existing account-policy drift gate to also assert live scope maps against the declaration — turning a silent mismatch into a failed apply, without needing a patch. Option 2 is cheaper and composes with the gate already merged in #277.
supernaut lade till 1 incheckning 2026-07-31 11:05:48 +00:00
docs(kanidm): record that provision scope maps are additive, not authoritative
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m24s
0b991e66d3
Follow-up to #278, which shipped half-fixed.

kanidm-provision applies each declared scope map but has no removal logic for
undeclared ones — there is no scope-map equivalent of removeOrphanedClaimMaps.
So the #278 apply ADDED forgejo_admins to gitborg-web-dev and left forgejo_users
in place, leaving the dev client visible to every user, which was the whole point
of the change.

The asymmetry is the trap: originUrl IS replaced wholesale, so removing an origin
declaratively works (the localhost redirect really did go). Scope maps are not, so
removing a group from scope_maps here does nothing to the live server. Only
additions take effect; removal is manual:

  kanidm system oauth2 delete-scope-map gitborg-web-dev forgejo_users --name idm_admin

Recorded next to the client list because the failure mode is silent — a converge
reports success, the declared state and live state disagree, and nothing surfaces
it.
supernaut tvångsskickade docs/275-scope-maps-additive från 0b991e66d3
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m24s
till 328901e55f
Alla kontroller lyckades
ci / ci (pull_request) Successful in 1m22s
2026-07-31 11:41:17 +00:00
Jämför
supernaut sammanfogade incheckning 1eb15ab76f till main 2026-07-31 11:44:24 +00:00
supernaut tog bort grenen docs/275-scope-maps-additive 2026-07-31 11:44:24 +00:00
supernaut refererade denna ändringsförfrågan från en incheckning 2026-07-31 11:47:21 +00:00
supernaut refererade denna ändringsförfrågan från en incheckning 2026-08-03 09:41:35 +00:00
Logga in för att delta i denna konversation.
Inga granskare
Ingen milstolpe
Inget projekt
Inga tilldelade
1 deltagare
Notiser
Förfallodatum
Förfallodatumet är ogiltigt eller utanför gränserna. Använd formatet "åååå-mm-dd".

Inget förfallodatum satt.

Beroenden

Inga beroenden satta

Referens
bitborg/bitborg-infra!279
Ingen beskrivning angiven.