test(auth): pin the bunyip userinfo email_verified contract (PMS-248) #179

Merged
longjacksonle merged 1 commit from chore/mapps-248-userinfo-email-verified-contract into main 2026-06-11 18:56:44 +02:00

What

PMS-248: verify the PMS-244 invite gate's dependency - bunyip's /oauth2/userinfo must report email_verified - and pin it.

Finding (verified, no fix needed)

bunyip-api's userinfo handler (crates/bunyip-oidc/src/handlers/oidc.rs) emits email_verified straight from the users.email_verified column. That column is NOT NULL DEFAULT FALSE and set TRUE on email verification (magic-link / password-reset / verify paths via set_email_verified). So a real verified Bunyip login carries email_verified=true to mokosh, and the PMS-244 invite gate (email_verified == true) works as designed. An unverified account correctly does NOT get invites applied.

Change

Documentation + a regression guard on the consuming side - no behavior change:

  • Doc note on UserInfo.email_verified recording the verified Bunyip contract.
  • userinfo_email_verified_contract test: verified payload -> Some(true), unverified -> Some(false), omitted field -> None (the gate fails closed, never erroring the request).

Verification

cargo test --lib oidc_rs::tests::userinfo_email_verified_contract passes; cargo clippy --lib clean.

🤖 Generated with Claude Code

## What PMS-248: verify the PMS-244 invite gate's dependency - bunyip's `/oauth2/userinfo` must report `email_verified` - and pin it. ## Finding (verified, no fix needed) bunyip-api's userinfo handler (`crates/bunyip-oidc/src/handlers/oidc.rs`) emits `email_verified` straight from the `users.email_verified` column. That column is `NOT NULL DEFAULT FALSE` and set `TRUE` on email verification (magic-link / password-reset / verify paths via `set_email_verified`). So a real verified Bunyip login carries `email_verified=true` to mokosh, and the PMS-244 invite gate (`email_verified == true`) works as designed. An unverified account correctly does NOT get invites applied. ## Change Documentation + a regression guard on the consuming side - no behavior change: - Doc note on `UserInfo.email_verified` recording the verified Bunyip contract. - `userinfo_email_verified_contract` test: verified payload -> `Some(true)`, unverified -> `Some(false)`, omitted field -> `None` (the gate fails closed, never erroring the request). ## Verification `cargo test --lib oidc_rs::tests::userinfo_email_verified_contract` passes; `cargo clippy --lib` clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
test(auth): pin the bunyip userinfo email_verified contract (PMS-248)
Some checks failed
Check / fmt + clippy + compile + tests (pull_request) Failing after 11s
E2E (staging) / Playwright against staging (pull_request) Successful in 34s
Build OCI container / Build and push mokosh-api image (push) Successful in 3m47s
Create release / Create release from merged PR (pull_request) Has been skipped
fd253a679b
PMS-248 verification: the PMS-244 invite flow consumes a pending invite only when bunyip's `/oauth2/userinfo` reports `email_verified = true`, so that field is load-bearing. Confirmed it is supplied: bunyip-api's userinfo handler emits `email_verified` from the `users.email_verified` column (`NOT NULL DEFAULT FALSE`, set `TRUE` on email verification / magic-link / reset), so a real verified login carries `email_verified=true` to mokosh and the gate works as designed. No bunyip or gate change is needed.

To keep the consuming side from silently drifting, this documents the contract on `UserInfo.email_verified` and adds a deserialization regression test: a verified payload -> `Some(true)`, an unverified one -> `Some(false)`, and an omitted field -> `None` (the gate fails closed, never erroring the request).

Verification: `cargo test --lib oidc_rs::tests::userinfo_email_verified_contract` passes; `cargo clippy --lib` clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
longjacksonle deleted branch chore/mapps-248-userinfo-email-verified-contract 2026-06-11 18:56:45 +02: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
psa-systems/mokosh-server!179
No description provided.