~bigbes/sr-ht-ecore

ref: b36a927213562090e100c8b43ab27ef9094b1de9 sr-ht-ecore/bearer/bearer.go -rw-r--r-- 24.1 KiB
89fa694c — Eugene Blikh 2 days ago
metapat: the meta.sr.ht PAT plane a federated endpoint needs

api.sr.ht forwards ONE client Authorization header to every service a
federated query touches — AuthMiddleware copies it verbatim, and the
Internal credential it can mint is used only to fetch schemas at startup.
So a GraphQL endpoint that refuses meta.sr.ht personal access tokens
cannot be federated: the first authenticated query answers 401. Four
services on this instance refuse them today and publish an empty scope
list besides, which is the stronger half of the same problem — meta
cannot mint a token for a service whose api-meta.json names no scope.

This is the half of accepting one that is the same everywhere: routing a
credential to its plane, the decode/lookup/revocation path, and the
OAuth scope gate. dolt is where it is written today; putting a fourth
and fifth copy of a credential path in four services is how the copies
start to disagree.

PlaneOf routes without a validator, which matters more than it looks: an
instance with no [tokens.sr.ht] section holds no working-token validator
to call, and its PAT plane must keep working anyway. Only successes are
cached, so an outage cannot be pinned into the cache and outlive itself,
and the cache is bounded — dolt's grows without one.

Options.Service is required because auth.DecodeGrants reads the calling
service's name off the context and config.ServiceName PANICS for the
absence of it rather than answering "". In production config.Middleware
puts it there; anywhere else — a job, a CLI, a test — a validator that
leaned on the ambient context would take the process down. So the
validator carries its own.

bearer's step-2 prose said bench and cover had no reason to accept a
meta PAT. That was true of a service reached only by its own clients and
is not true of one behind the gateway; it now says which surface accepts
which credential, and points at PlaneOf.
e8a96725 — Eugene Blikh 9 days ago
bearer: mint the internal authorization through internalauth

This package assembled the header by hand — json.Marshal of an auth.InternalAuth
plus "Internal " and a fernet seal — two files away from the package whose whole
purpose is to hold both ends of that handshake. It is the same drift internalauth
was hoisted to end, sitting inside the library that hoisted it: a change to the
payload shape here would have gone unnoticed by every Guard on the instance until
a revocation check started failing.
17411599 — Eugene Blikh 10 days ago
bearer: split the grant check out of validation

A sourcehut service resolves identity once per request in middleware, upstream
of the router — that is where the cookie plane and the bearer plane meet and
where a principal is put on the context — and at that point nothing knows which
route will run, so nothing knows the action. The action is known one layer down,
in the handler.

Validate insisted on both at once, which left every adopting service two bad
options: invent an action before it has one, or lift its bearer plane out of the
middleware every other plane goes through. The second is how a surface ends up
with two different ideas of who is calling.

So Inspect answers steps 1, 2 and 4 — who, what may they do, is it still live —
and Token.Authorize is step 3, asked where the action finally exists. Validate
is unchanged for callers that know both at one point.

It keeps its own ordering rather than becoming Inspect+Authorize: step 3 before
step 4 means a token that does not carry the grant is refused without a round
trip to the daemon, and a test pins that. Inspect cannot keep that ordering,
having no action to refuse on, and that is the one cost of the split — written
down at both call sites.
86de8532 — Eugene Blikh 10 days ago
bearer: the shared working-token validator of SPEC ch. 6