Expand description
Decision records: what a pushed authorization request becomes, and what an agent answers.
plan/oauth.md’s hard part is who consents. The answer this module
carries is that the pushed request itself is the question: at PAR, once
the client is known and login_hint has been resolved to an account,
this server works out what it would grant and writes that down as a
DecisionRecord the named account can read, approve or decline over
bot.did.*. Nothing about it needs a browser, and nothing about it
forbids one — GET /oauth/authorize renders the same record for a person.
§What the record says, and what it keeps to itself
DecisionRecord::to_json is the whole wire shape. The client’s own copy
of its name, its home page and its logo is kept (ClientSelf) and never
serialized: plan/app-allowlist.md’s “record the client’s own copy; do
not show it”, because showing an untrusted client’s self-description is
how impersonation works. What an agent sees about the client is the
origin it served its metadata from, the content key of that metadata, and
whether this account has approved that key before.
§Narrowing is never silent
A Verdict is one of three answers, and two of them say something was
taken away. Verdict::Narrow names the grant and the atoms the
ceiling did not give in full. See
crate::oauth::scope::ScopeSet::narrow.
An approval covers what the verdict granted, and that is what the login
is issued at. A token may do that set as the ceiling in force grants it
(crate::oauth::token::in_force), so a ceiling tightened after the
approval takes a granted atom back. A cut atom stays cut: widening the
ceiling cannot add one to a login the agent approved without it.
§Nothing here is durable
A record lives as long as the pushed request it was minted for
(crate::oauth::par::REQUEST_URI_TTL), answered or not, and is swept
when it expires: GET /oauth/authorize answers from it until then. An
approval whose code a browser carries holds its redirect here too, until
the page hands it to a browser signed in as the account
(DecisionStore::collect). MemoryDecisionStore is bounded twice
over — per account and in total — because PAR is unauthenticated, so an
unbounded queue of records would be a way to spend this server’s memory
without holding any credential.
§A remembered approval
The account’s approval of a client is remembered, per account and
ClientKey, at the grant it approved, for REMEMBERED_TTL
(DecisionStore::remember). GET /oauth/authorize reads it to confirm
a later sign-in without asking; see
crate::oauth::authorize::confirms_unasked. A confirmation does not
write one, so it never renews itself. It lives in memory, so a restart
forgets every one. See plan/remembered-consent.md.
Structs§
- Client
Self - The client’s own account of itself, kept for the audit trail and never serialized to any caller.
- Cursor
- A place in one store’s arrival order, and which store’s order it is.
- Decision
Record - One authorization request, as this server decided about it.
- Displaced
- The record one push displaced to make room for its own, and what must be undone for it.
- Inner 🔒
- Memory
Decision Store - The in-process decision store.
- Remembered
- The account’s latest approval of one client, remembered.
- Stored
- What
DecisionStore::putstored, and what it displaced to store it.
Enums§
- Decision
Refused - Why a record could not be stored.
- Decision
State - Where one decision record is in its life.
- Verdict
- What this server decided about one authorization request.
Constants§
- CEILING_
RULE - The rule a ceiling narrowing or refusal is attributed to.
- DEFAULT_
PENDING_ PER_ ACCOUNT - How many decisions one account may have awaiting an answer.
- DEFAULT_
PENDING_ TOTAL - How many decisions this server may hold in total. An answered one counts until its pushed request expires.
- EPOCH_
BYTES 🔒 - How many random bytes name one store’s epoch; see
Cursor. - REMEMBERED_
TTL - How long the account’s approval of a client is remembered: as long as the login it approved can last.
- SEEN_
CLIENTS_ 🔒MAX - How many
(account, client key)approvalsMemoryDecisionStoreremembers forDecisionRecord::first_time.
Traits§
- Decision
Store - Where decision records live between PAR and an answer.
Functions§
- atoms 🔒
- A scope set as the array of atoms the wire carries.
- hard_
blocked 🔒 - Whether this atom is one this server never grants, whatever a ceiling
says:
plan/scope-policy.md’s hard-blocked capabilities, and any atom the grammar cannot read.verdict_fordrops each from the request whole, so the rest can be granted and the agent sees it incut. - verdict_
for - The verdict a ceiling alone gives for one request.