diff --git a/docs/DESIGN.md b/docs/DESIGN.md index 7d8960658b5a3994ab85d84cc2e50acd1433a987..b83f3268e4d625fbd94eb920beeebcab81d02a26 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -1049,6 +1049,18 @@ hot loop: schema refresh is **SIGHUP-driven, not on a ticker** (the goroutine selects on `signalChan`), so the fetch happens at startup and explicit reload only. dolt.sr.ht and compare.sr.ht run with exactly this property today. +**Introspection is content, and is gated.** The read plane is fail-closed, and +the schema is authenticated along with everything else — so a federating +`api.sr.ht` must present a token or it will log "Unable to update service" and +skip us. Given the retraction above, that is an acceptable cost rather than a +reason to open the endpoint. + +**No complexity limit.** core-go's `WithSchema` would supply one from +`[::api] max-complexity`, but this service authenticates on its own +router and does not use it, so nothing bounds query cost. Low risk on a +single-user authenticated surface; worth revisiting before any surface becomes +reachable without a credential. + **Open:** whether `api.sr.ht` is deployed on this instance at all is unconfirmed — `sourcehut/sr.ht-nginx/` is the upstream mirror, not our instance config, and no `api.srht.bigb.es` reference exists in the tree. Given the retraction above this @@ -1194,10 +1206,15 @@ > through inverts the meaning of an empty project — from "nothing" to "the entire > corpus".** A silent scope inversion, invisible in any test that only uses > non-empty projects. -Documented on both types today; the durable fix is for the query to take the -filter type itself rather than a bare slice, so the mistake stops being -expressible. That change is deferred only because the read surfaces were being -built against the current signature at the time. +**Fixed, and the fix retracts the polarity described above.** A search query now +takes the filter *type* rather than a bare slice, with unexported fields and +three explicit states — everything, a named set, and nothing. The zero value is +none of them and a query carrying it is **refused** rather than defaulted, since +both plausible defaults are wrong for one of the callers that can produce one. + +So "an empty space list means every space" is no longer true anywhere: an empty +set selects nothing, and the corpus-wide case is `EverythingFilter()`, spelled +out. The mistake is now inexpressible rather than documented. The meta-project is **corpus-wide, not viewer-scoped**. With no visibility levels and no ACL rows in v1 there is no "spaces the caller may read" to scope it to;