API Client
link-api is Link's typed client for the account service's API, one
function a route, on link-fetch. It holds no credential of its own,
and it makes and checks the access tokens the service's routes take.
Its types
types is made at every build from openapi.yaml (build.rs, with
typify): every object closed, every pattern and limit checked as an
answer is read, every credential a Secret. A change to the API is a
change to that file first.
One function a route
Each is named as the spec's operationId, takes the route's request
type and answers its answer type. ROUTES lists each method, path
under BASE_PATH (/api/v1) and function, and a test holds them to
the spec's paths.
The report's answer
The one answer read entry by entry, not closed, is the report's
(Asked): an action of a kind this machine doesn't know is refused
alone, so a newer service never stops an older machine's actions.
Its calls
Api is the service at one URL, cheap to clone. A call that needs a
credential is handed it, a &Secret, by its caller: the accounts
plugin, which keeps this machine's key and signs for access tokens with
it (Api::sign_for), or a plugin it handed an access token to.
link-fetch's rules
https:// only (or http:// on this machine), no redirects, an
answer's size capped, and errors mapped once: a 401 is
Error::SignedOut, a 429 Error::Later. What a refusal says, in the
spec's words, is refused.
Access tokens (jwt)
Access tokens and the assertions machines sign for them, as the spec
has them (MachineAssertionHeader, MachineAssertionClaims,
AccessTokenHeader, AccessTokenClaims): compact JWS, Ed25519 alone.
assertion
A machine signs an assertion with its key for each access token it
asks for: one request, at most ASSERTION_LIFE, 60 seconds.
check
Whatever an access token is for checks it with check and the account
service's public keys alone (Keys), never asking the service. The
header is read first: alg EdDSA and typ at+jwt alone, its kid
one it holds. Then the signature, then the claims.
The claims
Closed: the issuer it trusts, its own audience, a subject of a kind it
takes, a grant of what it's asked to do (Grants::allows), and a life
no longer than its own longest, with no allowance for clocks.