From 6e59bf0ffc7d16f509dad40063d35bf8f6fb98a7 Mon Sep 17 00:00:00 2001 From: Eugene Blikh Date: Mon, 10 Aug 2026 11:23:12 +0300 Subject: [PATCH] api: advertise an empty scope list, not null MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit core-go serves the second argument of WithSchema verbatim at /query/api-meta.json, so a nil slice reaches the wire as `"scopes": null`. meta.sr.ht discovers every *.sr.ht service at import time and iterates that field when rendering /oauth2/personal-token, so the null turned the whole instance's personal-token page into a 500 — no token could be minted at all while spec.sr.ht was up. The other custom services answer 404 there and are skipped, which is why only this one broke it. Empty is the accurate value: the service is owner-only and defines no AccessScope enum to grant against. --- cmd/specsrht/main.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cmd/specsrht/main.go b/cmd/specsrht/main.go index cd46b92445598f3323bf8172eae9cada76f17043..8d678a15609bec4a671e88bcb8c3405c01d7d5e7 100644 --- a/cmd/specsrht/main.go +++ b/cmd/specsrht/main.go @@ -357,11 +357,18 @@ func run(conf ini.File, log *slog.Logger) error { // WithQueues starts the webhook delivery worker with a context carrying that // same stack; the queue executes a subscription's stored query against the // shared schema at delivery time. + // The scope list must be an empty slice and not nil. core-go serves it + // verbatim at /query/api-meta.json, where a nil slice marshals to + // `"scopes": null` — and meta.sr.ht's OAuth page iterates that field for + // every service it discovers, so one null there is a 500 on + // /oauth2/personal-token for the whole instance, not a degraded entry. + // Empty is also the honest answer: this service is owner-only (see + // ownerOnly above) and defines no AccessScope enum to grant against. webhookQueue := webhooks.NewQueue(surf.schema, conf) srv := coreserver.New(serviceName, defaultBind, conf, os.Args). WithDefaultMiddleware(). WithMiddleware(ownerOnly(cfg.Instance.OwnerName)). - WithSchema(surf.schema, nil). + WithSchema(surf.schema, []string{}). WithQueues(webhookQueue.Queue) mountRoutes(srv.AnonRouter(), conf, surf)