5bb0bb13
graph: serve /query on the anonymous router with a bearer credential
The schema was mounted by core-go's server.WithSchema, on the authenticated router, behind an ownerOnly middleware. That put it on meta.sr.ht's OAuth vocabulary while every other surface of this service — the web UI, /mcp, the REST write plane — authenticates with a tokens.sr.ht working token, so a credential that reads through /mcp was refused by the endpoint meant to be the instance-native read plane. dolt.sr.ht's graph package is the pattern; this follows it. /query is now mounted on the anonymous router and graph.Server installs its own credential middleware: a working token owned by [sr.ht] owner-name and carrying spec:read reads, one without that grant is 403, one belonging to anybody else is 403, and anything that does not verify is 401 with the bearer challenge. A cookie is not a credential here — the principal is overwritten with the anonymous one when no bearer token is presented, so no middleware above the mount point can promote a browser session into read authority. ownerOnly's rule survives the move: it compared auth.AuthContext.Username to the owner, and authn's resolver refuses a foreign token's owner at the door with the same 403. What it also did — remapping the owner to AUTH_INTERNAL so core-go's webhook engine would accept them — is now coreauth's, which is what that package was written for and had no caller for until today. A service that mounts its own /query owes the instance api-meta.json, because core-go serves that file only for the schemas it hosts itself. sr-ht-ecore's apimeta serves it, with an empty scope list: spec.sr.ht defines no meta OAuth scope and no @access directive to check one against, and a JSON null there is a 500 on meta's personal-token page for the whole instance. Two consequences worth naming. A meta.sr.ht personal access token no longer reaches /query. It did while core-go's auth.Middleware stood in front of it. Accepting one again means giving spec.sr.ht a meta scope first, and there is none to invent. WebhookSubscription.sample cannot be rendered on this endpoint and says so. corewebhooks.Exec reads the complexity bound off core-go's server context, which only WithDefaultMiddleware installs and which cannot be built from outside that package. Delivery is unaffected: the queue's context comes from WithQueues and does carry it — but MaxComplexity must now be set by hand, because zero there fails every delivery rather than imposing no limit.
Eugene Blikh <bigbes@gmail.com> — 2026-08-16 08:52:25 UTC
Commit 5bb0bb134d608263da3197df9fb4f1d8a3fe42db —
view raw patch
Parent(s):
824788ab
| File | Status | + | − |
|---|---|---|---|
cmd/specsrht/graphql.go
|
A | +55 | |
cmd/specsrht/graphql_test.go
|
A | +172 | |
cmd/specsrht/main.go
|
M | +106 | -76 |
go.mod
|
M | +1 | -1 |
go.sum
|
M | +2 | -2 |
graph/credential_test.go
|
A | +219 | |
graph/graph_test.go
|
M | +12 | -4 |
graph/resolver.go
|
M | +12 | -2 |
graph/schema.resolvers.go
|
M | +45 | -57 |
graph/server.go
|
M | +177 | -49 |