Chat sign-in needs a live consent receipt; notice frozen as version 1 #59

Merged
heimdall merged 2 commits from heimdall/chat-consent-gate into main 2026-11-11 14:32:07 +00:00
Member

Meta's ruling 2026-11-11 (operator-level), implemented as ordered.

Gate. The OIDC issuer is the chat tier. It now needs a live ConsentReceipt for TrainingNotice.Version (one reading, ConsentEndpoints.HasLiveReceiptAsync, shared by authorize, token, userinfo and the logout reconciler).

  • Authorize with no/withdrawn/other-version receipt: 302 to /auth/bifrost/consent?returnUrl=<the parked /connect/authorize?request_uri=...>; no code, no OIDC error. Checked last, so suspended/no-identity/reserved are refused as before. Agreeing 303s back to the return path (local paths only) and the request resumes (single use, 10 min).
  • Token: invalid_grant. Userinfo: 403 insufficient_access, no claims; existing access tokens stop answering as soon as the receipt goes. No refresh token exists.
  • Reconciler: accounts whose receipt is gone get the back-channel logout and lose their authorizations.
  • Account sign-in, /App, the members page and votes need no receipt (tested).

Notice. Frozen as version 1 (was the unreleased "v2" draft). Says "Agreement is needed to speak in a recorded room" and "Lines you have already spoken stay"; both the consent page (notice now above the buttons) and the registration form render it beside the agree control. A test pins the text hash per version: text change requires a version bump. Nothing deployed, no production receipts: unreleased migrations 20261111090000/20261111100000 untouched (the version is an int column; no schema change was needed, so editing or adding a migration would only add surface).

Docs. training-notice.md, oidc-issuer.md (gate, behaviour table, "Userinfo smoke notes for Eureka"), registration-gates.md.

Tests. Baseline on 1571bf3: 38 failing (CultCache TS runtime absent, OIDC userinfo on .NET 10, concept tally). This branch: 42 failing = the same 38 plus 4 new tests whose positive assertion is userinfo 200 (the known Results.Json PipeWriter fault on the .NET 10 host runtime). With userinfo temporarily switched to Results.Text (not committed) the focused Oidc/Consent/Logout/Frozen set is 124/124 green. Mutations (gate removed at authorize; token+userinfo gate removed; version compare loosened to any receipt; withdrawn ignored; notice text edited without bump) each turn tests red.

Gap: all of this runs on the in-memory provider; the filtered unique index and the Postgres unique-violation path are not exercised.

🤖 Generated with Claude Code

Meta's ruling 2026-11-11 (operator-level), implemented as ordered. **Gate.** The OIDC issuer is the chat tier. It now needs a live `ConsentReceipt` for `TrainingNotice.Version` (one reading, `ConsentEndpoints.HasLiveReceiptAsync`, shared by authorize, token, userinfo and the logout reconciler). - Authorize with no/withdrawn/other-version receipt: 302 to `/auth/bifrost/consent?returnUrl=<the parked /connect/authorize?request_uri=...>`; no code, no OIDC error. Checked last, so suspended/no-identity/reserved are refused as before. Agreeing 303s back to the return path (local paths only) and the request resumes (single use, 10 min). - Token: `invalid_grant`. Userinfo: 403 `insufficient_access`, no claims; existing access tokens stop answering as soon as the receipt goes. No refresh token exists. - Reconciler: accounts whose receipt is gone get the back-channel logout and lose their authorizations. - Account sign-in, `/App`, the members page and votes need no receipt (tested). **Notice.** Frozen as version 1 (was the unreleased "v2" draft). Says "Agreement is needed to speak in a recorded room" and "Lines you have already spoken stay"; both the consent page (notice now above the buttons) and the registration form render it beside the agree control. A test pins the text hash per version: text change requires a version bump. Nothing deployed, no production receipts: unreleased migrations `20261111090000`/`20261111100000` untouched (the version is an int column; no schema change was needed, so editing or adding a migration would only add surface). **Docs.** `training-notice.md`, `oidc-issuer.md` (gate, behaviour table, "Userinfo smoke notes for Eureka"), `registration-gates.md`. **Tests.** Baseline on 1571bf3: 38 failing (CultCache TS runtime absent, OIDC userinfo on .NET 10, concept tally). This branch: 42 failing = the same 38 plus 4 new tests whose positive assertion is userinfo 200 (the known `Results.Json` PipeWriter fault on the .NET 10 host runtime). With userinfo temporarily switched to `Results.Text` (not committed) the focused Oidc/Consent/Logout/Frozen set is 124/124 green. Mutations (gate removed at authorize; token+userinfo gate removed; version compare loosened to any receipt; withdrawn ignored; notice text edited without bump) each turn tests red. Gap: all of this runs on the in-memory provider; the filtered unique index and the Postgres unique-violation path are not exercised. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Meta's ruling 2026-11-11. The OIDC issuer (the chat tier) now requires a live
receipt for TrainingNotice.Version: a refused authorize redirects to the consent
page with the parked request as returnUrl (agreeing resumes it); token and
userinfo re-read the receipt (invalid_grant / 403 insufficient_access, no
claims); the back-channel reconciler ends sessions of accounts whose receipt is
gone. Account sign-in, the members page and votes need no receipt.

The notice states, beside the Agree button, that agreement is needed "to speak
in a recorded room" and that lines already spoken stay. It is relabelled
version 1 (nothing was deployed, so no receipts migrate; the unreleased
migrations are untouched) and its text hash is pinned by a test.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
heimdall force-pushed heimdall/chat-consent-gate from 5064b4098c to dff217329f 2026-11-11 14:15:38 +00:00 Compare
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
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
GameCult/Bifrost!59
No description provided.