~bigbes/sr-ht-spec

0879325b6c7e7d74454ecff0196b8d5ecc12f1ea — bigbes 27 days ago 6f4efc2
docs: the empty-space-list polarity is retracted, not just documented

Search queries now take the filter type with three explicit states, so an
empty set selects nothing everywhere and the corpus-wide case is spelled
EverythingFilter. The document previously said an empty search space list
means every space, which the fix deliberately reverses.

Also records that introspection is gated along with the rest of the read
plane, and that nothing bounds GraphQL query complexity because the
service authenticates on its own router rather than core-go's.
1 files changed, 21 insertions(+), 4 deletions(-)

M docs/DESIGN.md
M docs/DESIGN.md => docs/DESIGN.md +21 -4
@@ 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
`[<service>::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 @@ search layer, where an empty space list means *every* space:
> 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;