docs(adr-0025): promote to accepted + sync persona matrix with test tenant #205

Merged
julien merged 1 commits from docs/adr-0025-accepted into main 2026-05-23 17:42:58 +02:00
Owner

Summary

ADR-0025 was merged as proposed in #201. The test tenant (apfrd.onmicrosoft.com) has since been provisioned with the full role / user matrix — 4 privileges + 24 security groups + 19 users with all assignments per the persona table. The ADR is now the implementation reference, so this PR:

  1. Promotes the ADR from proposed to accepted.
  2. Syncs the document with what is actually in place — the privilege catalogue grows from 1 to 4 entries (the previously "anticipated future" privileges that the test tenant already has), and the persona matrix grows from 10 to 19 entries (so every one of the 24 functional-role groups has at least one member, closing the gap that prompted notes/test-tenant-role-assignments.md and notes/entra-group-members.md).
  3. Records the Entra app-role GUIDs in a new "Provisioned in the test tenant" subsection for traceability — the GUIDs are stable IDs the implementation will need.
  4. Updates the index + the CLAUDE.md roll-up.

No code changes. No implementation skeleton — that lands in the next PR (proposed: feat(libs/feature/auth): authorization types + Principal builder skeleton).

What lands

File Change
docs/decisions/0025-authorization-model-privileges-roles-scopes.md Frontmatter status: proposed → accepted; privilege catalogue extended from 1 to 4 entries; persona matrix rewritten from 10 to 19 entries; new Provisioned in the test tenant (2026-05-20) subsection capturing the four app-role GUIDs.
docs/decisions/README.md 0025 row: proposed → accepted.
CLAUDE.md Roll-up 0001 → 0024 accepted0001 → 0025 accepted; Architecture list grows an "Authorization model" bullet.

The two operator-facing notes files (notes/test-tenant-role-assignments.md, notes/entra-group-members.md) are gitignored and unchanged — they served their purpose during tenant provisioning and remain as runbooks.

Notes for the reviewer

  • Why promote now rather than couple with the first implementation PR (the pattern from #194#195#196). The Entra-side provisioning is the implementation for this ADR — the next PR is a portal-side reflection of decisions that are already concrete in the tenant. Promoting now keeps the document honest about what the test tenant runs against.
  • Why all 4 privileges enter the v1 catalogue. The ADR originally shipped Portal.Admin as the sole v1 entry and listed the other three under "anticipated near-future entries". The test tenant has all four; the catalogue should match. The three new entries are explicitly marked "provisioned; consumer surface deferred" so a reader does not look for non-existent surfaces.
  • Why 19 personas, not the cleaner 24 (one per role). Several APF jobs genuinely combine multiple roles (RH siège often handles paie + compta; DPO often wears the quality officer hat; local delegates often grow out of volunteer roles). Densifying these existing personas is more faithful to real APF org structure than inventing 14 single-role test users. Distinct personas were created where the scenario is distinct (scope variations, governance positions) — see the matrix in the ADR for the breakdown.
  • Why apf-role-partenaire stays empty in v1. Placeholder per the original ADR; no consuming surface to test against. The group exists in Entra so the schema is locked, but a user assignment without a guard to exercise would be theatre. The first partner-facing feature adds the user.
  • GUIDs in the ADR. The four app-role GUIDs are repo-stable identifiers; recording them in the ADR keeps the document self-sufficient when a future contributor opens it without access to the Entra portal. The 24 functional-role group GUIDs are tenant-specific and stay in a gitignored infra/test-tenant.entra.json once the implementation PR creates it — referenced by name only in libs/feature/auth/src/lib/entra-group-to-role.ts.
  • No prettier --write damage. The persona matrix is a wide table; Prettier sometimes reflows wide markdown tables. The diff is clean — Prettier left the table intact on this run.

Test plan

  • prettier --check docs/decisions/0025-authorization-model-privileges-roles-scopes.md — passes (hook ran on commit).
  • Markdown links inside the ADR still resolve (0020, references to other ADRs unchanged).
  • Status row in docs/decisions/README.md reflects accepted.
  • CLAUDE.md roll-up line + Architecture list updated; no other instances of "0024" needed bumping.
  • Review focus — the expanded privilege catalogue (4 entries, one of them already had a guard, three new ones documented), the 19-entry persona matrix, the "Provisioned in the test tenant" subsection (especially the GUIDs — make sure none was mistyped from notes/role-user.txt).

What's next

With ADR-0025 accepted, the implementation phasing recorded in its §More Information opens:

  1. PR — libs/feature/auth extension : authorization.types.ts (catalogue constants for the 4 privileges + 24 functional roles + 6 scope kinds), entra-group-to-role.ts (slug map skeleton with placeholder GUIDs ; the operator drops real GUIDs into infra/test-tenant.entra.json separately), Principal builder hook on the OIDC callback, no new guards yet.
  2. PR — @RequireRole + @RequireScope decorators + guard tests : real composition tests against the 19 personas.
  3. PR — drift CI gate : ESLint custom rule asserting every @RequireRole('...') literal in code is in the catalogue.
  4. PR — prisma/seed.ts for user_scopes : depends on the Person + User schema (proposed ADR-0026).
## Summary ADR-0025 was merged as `proposed` in #201. The test tenant (`apfrd.onmicrosoft.com`) has since been provisioned with the full role / user matrix — 4 privileges + 24 security groups + 19 users with all assignments per the persona table. The ADR is now the implementation reference, so this PR: 1. Promotes the ADR from `proposed` to `accepted`. 2. Syncs the document with what is actually in place — the privilege catalogue grows from 1 to 4 entries (the previously "anticipated future" privileges that the test tenant already has), and the persona matrix grows from 10 to 19 entries (so every one of the 24 functional-role groups has at least one member, closing the gap that prompted `notes/test-tenant-role-assignments.md` and `notes/entra-group-members.md`). 3. Records the Entra app-role GUIDs in a new "Provisioned in the test tenant" subsection for traceability — the GUIDs are stable IDs the implementation will need. 4. Updates the index + the `CLAUDE.md` roll-up. No code changes. No implementation skeleton — that lands in the next PR (proposed: `feat(libs/feature/auth): authorization types + Principal builder skeleton`). ## What lands | File | Change | |---|---| | `docs/decisions/0025-authorization-model-privileges-roles-scopes.md` | Frontmatter `status: proposed → accepted`; privilege catalogue extended from 1 to 4 entries; persona matrix rewritten from 10 to 19 entries; new `Provisioned in the test tenant (2026-05-20)` subsection capturing the four app-role GUIDs. | | `docs/decisions/README.md` | 0025 row: `proposed → accepted`. | | `CLAUDE.md` | Roll-up `0001 → 0024 accepted` → `0001 → 0025 accepted`; Architecture list grows an "Authorization model" bullet. | The two operator-facing notes files (`notes/test-tenant-role-assignments.md`, `notes/entra-group-members.md`) are gitignored and unchanged — they served their purpose during tenant provisioning and remain as runbooks. ## Notes for the reviewer - **Why promote now rather than couple with the first implementation PR (the pattern from #194 → #195 → #196).** The Entra-side provisioning *is* the implementation for this ADR — the next PR is a portal-side reflection of decisions that are already concrete in the tenant. Promoting now keeps the document honest about what the test tenant runs against. - **Why all 4 privileges enter the v1 catalogue.** The ADR originally shipped `Portal.Admin` as the sole v1 entry and listed the other three under "anticipated near-future entries". The test tenant has all four; the catalogue should match. The three new entries are explicitly marked "provisioned; consumer surface deferred" so a reader does not look for non-existent surfaces. - **Why 19 personas, not the cleaner 24 (one per role).** Several APF jobs genuinely combine multiple roles (RH siège often handles paie + compta; DPO often wears the quality officer hat; local delegates often grow out of volunteer roles). Densifying these existing personas is more faithful to real APF org structure than inventing 14 single-role test users. Distinct personas were created where the *scenario* is distinct (scope variations, governance positions) — see the matrix in the ADR for the breakdown. - **Why `apf-role-partenaire` stays empty in v1.** Placeholder per the original ADR; no consuming surface to test against. The group exists in Entra so the schema is locked, but a user assignment without a guard to exercise would be theatre. The first partner-facing feature adds the user. - **GUIDs in the ADR.** The four app-role GUIDs are repo-stable identifiers; recording them in the ADR keeps the document self-sufficient when a future contributor opens it without access to the Entra portal. The 24 functional-role group GUIDs are tenant-specific and stay in a gitignored `infra/test-tenant.entra.json` once the implementation PR creates it — referenced by name only in `libs/feature/auth/src/lib/entra-group-to-role.ts`. - **No `prettier --write` damage.** The persona matrix is a wide table; Prettier sometimes reflows wide markdown tables. The diff is clean — Prettier left the table intact on this run. ## Test plan - [x] `prettier --check docs/decisions/0025-authorization-model-privileges-roles-scopes.md` — passes (hook ran on commit). - [x] Markdown links inside the ADR still resolve (`0020`, references to other ADRs unchanged). - [x] Status row in `docs/decisions/README.md` reflects `accepted`. - [x] `CLAUDE.md` roll-up line + Architecture list updated; no other instances of "0024" needed bumping. - [ ] **Review focus** — the expanded privilege catalogue (4 entries, one of them already had a guard, three new ones documented), the 19-entry persona matrix, the "Provisioned in the test tenant" subsection (especially the GUIDs — make sure none was mistyped from `notes/role-user.txt`). ## What's next With ADR-0025 accepted, the implementation phasing recorded in its `§More Information` opens: 1. **PR — `libs/feature/auth` extension** : `authorization.types.ts` (catalogue constants for the 4 privileges + 24 functional roles + 6 scope kinds), `entra-group-to-role.ts` (slug map skeleton with placeholder GUIDs ; the operator drops real GUIDs into `infra/test-tenant.entra.json` separately), `Principal` builder hook on the OIDC callback, no new guards yet. 2. **PR — `@RequireRole` + `@RequireScope` decorators + guard tests** : real composition tests against the 19 personas. 3. **PR — drift CI gate** : ESLint custom rule asserting every `@RequireRole('...')` literal in code is in the catalogue. 4. **PR — `prisma/seed.ts` for `user_scopes`** : depends on the `Person` + `User` schema (proposed ADR-0026).
julien added 1 commit 2026-05-23 17:40:08 +02:00
docs(adr-0025): promote to accepted + sync persona matrix with test tenant
CI / scan (pull_request) Failing after 2m31s
CI / commits (pull_request) Successful in 2m56s
CI / check (pull_request) Successful in 3m10s
CI / a11y (pull_request) Successful in 2m46s
Docs site / build (pull_request) Successful in 2m56s
CI / perf (pull_request) Successful in 7m6s
985b0cb5d3
The test tenant (apfrd.onmicrosoft.com) has been provisioned with the
full role / user matrix. ADR-0025 was accepted as the implementation
reference; this commit aligns the document with what is actually in
place.

Changes:

- Frontmatter status: proposed -> accepted; date unchanged
  (decision was already final on 2026-05-20).
- Privilege catalogue: expanded from 1 to 4 entries. Portal.Auditor,
  Portal.SecurityOfficer and Portal.DPO were anticipated future
  entries; they are now provisioned in the test tenant alongside
  Portal.Admin and ride the catalogue while their consuming
  surfaces land in subsequent PRs.
- Test-tenant personas: rewritten from 10 to 19 entries so every
  one of the 24 functional-role groups carries at least one user
  (apf-role-partenaire remains intentionally empty as a placeholder
  per the existing rationale). The four privileges each have an
  assigned user.
- New 'Provisioned in the test tenant' subsection records the
  Entra app-role GUIDs (kept in-repo because they are stable IDs
  the implementation will reference; group GUIDs stay
  gitignored).
- README.md index: status row flipped to accepted.
- CLAUDE.md: roll-up extended from '0001 -> 0024 accepted' to
  '0001 -> 0025 accepted', Architecture list grows an
  'Authorization model' bullet.
julien merged commit c9a1e195fe into main 2026-05-23 17:42:58 +02:00
julien deleted branch docs/adr-0025-accepted 2026-05-23 17:43:02 +02:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: julien/apf_portal#205