Elke eerste Microsoft-login faalde met 403 "Only superusers can perform this action" op auth-with-oauth2. PocketBase past de createRule toe op het automatisch aanmaken van het record tijdens de OAuth2-sign-up; team_members stond op createRule: null (= superuser-only). Omdat de pre-Azure-records bewust gedropt zijn, was íedereen een eerste login → niemand kon erin. Volledige analyse + lokale repro in #22.
De fix
createRule: '@request.context = "oauth2"' — record-creatie mag uitsluitend vanuit de OAuth2-flow. Anonieme REST-creates (waarmee anders vooraf rogue admin-profielen klaargezet zouden kunnen worden) blijven geweigerd; expliciet getest.
1781000002_allow_oauth2_signup.js (nieuw): past de rule toe op reeds-gemigreerde omgevingen (Labs), guarded + down-migratie
1781000000_team_members_to_auth.js: zelfde rule voor verse omgevingen (bestandsnaam ongewijzigd — ledger-veilig)
⚠️Deze branch is gestapeld op fix/issue-20-caddyfile-crash (PR #21, nog niet gemerged) — bewust: aftakken van main zou de PR-pipeline het kapotte Caddyfile laten bouwen en Labs opnieuw neerhalen. Deze PR mergen brengt óók de #20-fix binnen (PR #21 wordt daarmee leeg en kan dicht). Volgorde-alternatief: eerst #21 mergen, dan krimpt deze diff automatisch.
Resterende menselijke check na deploy: inloggen met een echt Microsoft-account (E2E uit #18).
Closes #22
## Wat dit oplost
Elke **eerste** Microsoft-login faalde met 403 *"Only superusers can perform this action"* op `auth-with-oauth2`. PocketBase past de `createRule` toe op het automatisch aanmaken van het record tijdens de OAuth2-sign-up; `team_members` stond op `createRule: null` (= superuser-only). Omdat de pre-Azure-records bewust gedropt zijn, was íedereen een eerste login → niemand kon erin. Volledige analyse + lokale repro in #22.
## De fix
`createRule: '@request.context = "oauth2"'` — record-creatie mag uitsluitend vanuit de OAuth2-flow. Anonieme REST-creates (waarmee anders vooraf rogue admin-profielen klaargezet zouden kunnen worden) blijven geweigerd; expliciet getest.
- `1781000002_allow_oauth2_signup.js` (nieuw): past de rule toe op reeds-gemigreerde omgevingen (Labs), guarded + down-migratie
- `1781000000_team_members_to_auth.js`: zelfde rule voor verse omgevingen (bestandsnaam ongewijzigd — ledger-veilig)
- `scripts/setup-pb-collections.mjs` gespiegeld; `docs/auth-spec.md` ADR 009
## Verificatie (mock-OIDC tegen PocketBase v0.30.4)
| # | Scenario | Resultaat |
|---|---|---|
| A0 | Baseline met oude regel | **403 exact gereproduceerd** |
| A1–A4 | Upgrade-pad (= Labs): eerste login | 200, record met role uit allow-list, `enrollment_status=not_started`, naam uit OIDC-claim |
| A5 | Tweede login | Zelfde record, geen duplicaat |
| A6 | Anonieme REST-create | Geweigerd (400) |
| B1–B2 | Verse DB + admin-mapping | 200, `role=admin` via `ENTRA_ADMIN_EMAILS` |
Regressie: DoD-harness #18 **15/15**, `npm test` **112/112**.
## Let op bij de merge
⚠️ **Deze branch is gestapeld op `fix/issue-20-caddyfile-crash` (PR #21, nog niet gemerged)** — bewust: aftakken van main zou de PR-pipeline het kapotte Caddyfile laten bouwen en Labs opnieuw neerhalen. **Deze PR mergen brengt óók de #20-fix binnen** (PR #21 wordt daarmee leeg en kan dicht). Volgorde-alternatief: eerst #21 mergen, dan krimpt deze diff automatisch.
Resterende menselijke check na deploy: inloggen met een echt Microsoft-account (E2E uit #18).
## Follow-up (bewust buiten scope, zie #22)
TeamManager: `updateRule`/`deleteRule` staan rolbeheer door app-admins niet toe (alleen superusers via dashboard) — eigen afweging waard.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The learning-platform (Caddy) container crash-looped since this morning's
89d3395: `Content-Type application/json` is not a valid subdirective of
`respond` — a Caddyfile parse error aborts Caddy at startup, taking the
whole app offline for authenticated users while every CI run stayed green.
Verified with caddy v2.10.0: "unrecognized subdirective 'Content-Type',
at Caddyfile:53"; the fixed file validates clean.
CI was blind to this twice over: test.yml swaps the real Caddyfile for
Caddyfile.test in the test image, and the deploy health-gate from #18
only covers PocketBase.
- Caddyfile: set Content-Type via a `header @api` directive before the
`respond`; behaviour of the JSON error response is unchanged
- infra/*/site/deploy-playbook.yml: frontend health-gate (docker exec
wget --spider on the container) with log dump + abort on failure, and
an always-on post-deploy smoke report (compose ps, proxy health,
team_members auth-methods, PocketBase log tail) for visibility behind
the auth perimeter
Closes#20
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every first Microsoft login failed with 403 "Only superusers can perform
this action": PocketBase applies the collection createRule to the
automatic record creation during OAuth2 sign-up, and team_members was
created with createRule null (superuser-only) on the wrong assumption
that the OAuth2 flow bypasses it. Since the pre-Azure records were
deliberately dropped, every user was a first login and nobody could get
in. Reproduced locally against a mock OIDC provider (PocketBase v0.30.4).
createRule becomes '@request.context = "oauth2"': record creation is
allowed exclusively from within the OAuth2 flow. Anonymous REST creates
(which could otherwise pre-seed rogue admin profiles) remain rejected —
covered by an explicit test.
- pb_migrations/1781000002_allow_oauth2_signup.js: applies the rule on
already-migrated environments (Labs); idempotent, guarded, with down
- pb_migrations/1781000000_team_members_to_auth.js: same rule for fresh
environments (filename unchanged — ledger-safe)
- scripts/setup-pb-collections.mjs: fallback entry mirrored
- docs/auth-spec.md: ADR 009 + files table
Verified with a mock-OIDC matrix (9/9): baseline reproduces the 403 on
the old rule; upgrade path heals (first login 200, role/enrollment/name
defaults, second login no duplicate, anonymous create still rejected);
fresh chain + admin allow-list mapping OK. DoD harness regression 15/15,
npm test 112/112.
Closes#22
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Live-rollout geslaagd (run #93): deploy-dev groen, PLAY RECAP failed=0, beide gates gepasseerd, migratie 1781000002 toegepast bij boot (PB start anders niet), proxy-keten 200, OIDC-provider aanwezig, reconciler in-sync.
Lokale bewijsmatrix (mock-OIDC, v0.30.4): 9/9 — incl. baseline die de productie-403 exact reproduceert op de oude regel, en de check dat anonieme REST-creates geweigerd blijven. Regressie: #18-harness 15/15, npm test 112/112.
Laatste check (mens): log in met een Microsoft-account op Labs — de eerste login hoort nu een team_members-record aan te maken (rol via ENTRA_ADMIN_EMAILS, onboarding-status not_started).
Merge-volgorde: deze branch bevat de #20-commits (PR #21) — deze PR mergen sluit beide gaten in één keer; PR #21 kan daarna dicht.
**Live-rollout geslaagd (run #93):** deploy-dev groen, PLAY RECAP `failed=0`, beide gates gepasseerd, migratie `1781000002` toegepast bij boot (PB start anders niet), proxy-keten 200, OIDC-provider aanwezig, reconciler `in-sync`.
Lokale bewijsmatrix (mock-OIDC, v0.30.4): **9/9** — incl. baseline die de productie-403 exact reproduceert op de oude regel, en de check dat anonieme REST-creates geweigerd blijven. Regressie: #18-harness 15/15, `npm test` 112/112.
**Laatste check (mens):** log in met een Microsoft-account op Labs — de eerste login hoort nu een `team_members`-record aan te maken (rol via `ENTRA_ADMIN_EMAILS`, onboarding-status `not_started`).
Merge-volgorde: deze branch bevat de #20-commits (PR #21) — deze PR mergen sluit beide gaten in één keer; PR #21 kan daarna dicht.
rve
merged commit 8decdd454f into main2026-07-12 15:11:25 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #22
Wat dit oplost
Elke eerste Microsoft-login faalde met 403 "Only superusers can perform this action" op
auth-with-oauth2. PocketBase past decreateRuletoe op het automatisch aanmaken van het record tijdens de OAuth2-sign-up;team_membersstond opcreateRule: null(= superuser-only). Omdat de pre-Azure-records bewust gedropt zijn, was íedereen een eerste login → niemand kon erin. Volledige analyse + lokale repro in #22.De fix
createRule: '@request.context = "oauth2"'— record-creatie mag uitsluitend vanuit de OAuth2-flow. Anonieme REST-creates (waarmee anders vooraf rogue admin-profielen klaargezet zouden kunnen worden) blijven geweigerd; expliciet getest.1781000002_allow_oauth2_signup.js(nieuw): past de rule toe op reeds-gemigreerde omgevingen (Labs), guarded + down-migratie1781000000_team_members_to_auth.js: zelfde rule voor verse omgevingen (bestandsnaam ongewijzigd — ledger-veilig)scripts/setup-pb-collections.mjsgespiegeld;docs/auth-spec.mdADR 009Verificatie (mock-OIDC tegen PocketBase v0.30.4)
enrollment_status=not_started, naam uit OIDC-claimrole=adminviaENTRA_ADMIN_EMAILSRegressie: DoD-harness #18 15/15,
npm test112/112.Let op bij de merge
⚠️ Deze branch is gestapeld op
fix/issue-20-caddyfile-crash(PR #21, nog niet gemerged) — bewust: aftakken van main zou de PR-pipeline het kapotte Caddyfile laten bouwen en Labs opnieuw neerhalen. Deze PR mergen brengt óók de #20-fix binnen (PR #21 wordt daarmee leeg en kan dicht). Volgorde-alternatief: eerst #21 mergen, dan krimpt deze diff automatisch.Resterende menselijke check na deploy: inloggen met een echt Microsoft-account (E2E uit #18).
Follow-up (bewust buiten scope, zie #22)
TeamManager:
updateRule/deleteRulestaan rolbeheer door app-admins niet toe (alleen superusers via dashboard) — eigen afweging waard.🤖 Generated with Claude Code
Live-rollout geslaagd (run #93): deploy-dev groen, PLAY RECAP
failed=0, beide gates gepasseerd, migratie1781000002toegepast bij boot (PB start anders niet), proxy-keten 200, OIDC-provider aanwezig, reconcilerin-sync.Lokale bewijsmatrix (mock-OIDC, v0.30.4): 9/9 — incl. baseline die de productie-403 exact reproduceert op de oude regel, en de check dat anonieme REST-creates geweigerd blijven. Regressie: #18-harness 15/15,
npm test112/112.Laatste check (mens): log in met een Microsoft-account op Labs — de eerste login hoort nu een
team_members-record aan te maken (rol viaENTRA_ADMIN_EMAILS, onboarding-statusnot_started).Merge-volgorde: deze branch bevat de #20-commits (PR #21) — deze PR mergen sluit beide gaten in één keer; PR #21 kan daarna dicht.