Desk: bearer credential (OpenIddict validation, desk.read/desk.answer, audience bifrost-desk) and answerer masking #71

Open
heimdall wants to merge 4 commits from heimdall/desk-credential into main
Member

Production IDeskCredential and answerer masking (no deploy; no production Ratatoskr client is seeded).

  • OidcDeskCredential: OpenIddict local-server validation (OpenIddict.Validation.AspNetCore + ServerIntegration 7.7.1), not the default scheme. Authenticates only; audience, scope and per-request Active membership stay the desk's.
  • Issuer registers desk.read/desk.answer and stamps audience bifrost-desk. MAS cannot request them; its token and the session cookie are 401 on /api/desk/*. A Desk section without Oidc fails startup.
  • Notes: for non-deciders every note is nil (DeskRedaction). Bifrost masks no answerer id and no card.deciders: Huginn's door withholds both and returns counts (ruling eureka-substrate:ruling:desk-read-visibility-withheld-ids, Huginn #56 79d954c); Bifrost cannot mask what it cannot read (the card is opaque).
  • Consent gate: the training-notice receipt gates the chat token only; a desk token issues for a member with no receipt (test), a chat token is still sent to the consent page. Suspension still stops both.
  • Tests use real tokens from the test host's issuer. 1089 pass / 43 fail; the same 43 fail on f6a826b in this sandbox.

Steward answers applied: card.deciders leak is the door's (Huginn #56); consent gate chat-only; scheme name stays OpenIddict's fixed one (design note corrected in #69).

Textual overlap with the door PR (#70) in DeskReplay/test helpers; whichever merges second rebases.

🤖 Generated with Claude Code

Production IDeskCredential and answerer masking (no deploy; no production Ratatoskr client is seeded). - OidcDeskCredential: OpenIddict local-server validation (OpenIddict.Validation.AspNetCore + ServerIntegration 7.7.1), not the default scheme. Authenticates only; audience, scope and per-request Active membership stay the desk's. - Issuer registers desk.read/desk.answer and stamps audience bifrost-desk. MAS cannot request them; its token and the session cookie are 401 on /api/desk/*. A Desk section without Oidc fails startup. - Notes: for non-deciders every note is nil (DeskRedaction). Bifrost masks no answerer id and no card.deciders: Huginn's door withholds both and returns counts (ruling eureka-substrate:ruling:desk-read-visibility-withheld-ids, Huginn #56 79d954c); Bifrost cannot mask what it cannot read (the card is opaque). - Consent gate: the training-notice receipt gates the chat token only; a desk token issues for a member with no receipt (test), a chat token is still sent to the consent page. Suspension still stops both. - Tests use real tokens from the test host's issuer. 1089 pass / 43 fail; the same 43 fail on f6a826b in this sandbox. Steward answers applied: card.deciders leak is the door's (Huginn #56); consent gate chat-only; scheme name stays OpenIddict's fixed one (design note corrected in #69). Textual overlap with the door PR (#70) in DeskReplay/test helpers; whichever merges second rebases. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
DeskNotes becomes DeskRedaction: one function over entry and list that nils
every note and replaces every answerer with the fixed sentinel "masked" for a
caller who is not a decider of the Mind (X3). A decider keeps both. The
sentinel is not derived from the account id and is not a UUID.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
OidcDeskCredential authenticates a bearer through the validation scheme only
(never the default scheme; the cookie authenticates nothing on /api/desk and a
bearer authenticates no cookie page) and returns sub, audience and scopes. The
desk keeps judging audience, scope and per-request Active membership.

The issuer registers desk.read/desk.answer and stamps audience bifrost-desk on
tokens that carry one; client permissions are what limit scopes, so the MAS
client can neither ask for them nor use its chat token on the desk. A Desk
section without Bifrost:Oidc now fails startup in StartupConfigurationValidator.
Packages: OpenIddict.Validation.AspNetCore and .ServerIntegration 7.7.1.
No production Ratatoskr client is seeded.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This pull request can be merged automatically.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin heimdall/desk-credential:heimdall/desk-credential
git switch heimdall/desk-credential

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff heimdall/desk-credential
git switch heimdall/desk-credential
git rebase main
git switch main
git merge --ff-only heimdall/desk-credential
git switch heimdall/desk-credential
git rebase main
git switch main
git merge --no-ff heimdall/desk-credential
git switch main
git merge --squash heimdall/desk-credential
git switch main
git merge --ff-only heimdall/desk-credential
git switch main
git merge heimdall/desk-credential
git push origin main
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!71
No description provided.