o11y: regenerate the catalogue the app has actually served since it mounted

apps/o11y calls o11y.Mount(a) unconditionally, which registers the module's 353
typed operations. plugin/o11y's committed projections were last written the day
BEFORE that call landed, and nothing regenerated them: mcp.json held 12 tools and
openapi.json 20 paths / 32 operations.

So the fleet MCP door at POST /v1/mcp offered agents twelve o11y tools — the
reviews queue and one summary — while the process behind it served three hundred
and sixty-five. The observability surface was absent from /v1/openapi.json and
from every SDK generated off it. Regenerating with the app's own `describe`
target gives 365 tools and 289 paths / 388 operations, and takes the fleet total
from 932 to 1285.

apps/o11y/zipdoc_gen.go was stale in the same window: it still carried
POST /obs/event/claim, a route that no longer exists, and the pre-rewrite prose
for POST /v1/o11y/alerts/:receiver, which now states that delivery is
synchronous. Both come back from source.

This is what `make -f mk/fleet.mk surface-check` exists to catch, and it did not,
because the gate has been failing earlier in its own loop on unrelated apps — a
red gate stops reporting anything new. Recorded rather than papered over: the
regeneration is verified idempotent (a second run reproduces it byte for byte),
and the remaining blockers are in other apps.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
This commit is contained in:
2026-08-02 11:25:01 -07:00
parent b5190e4f9b
commit 593aa309fe
3 changed files with 48577 additions and 154 deletions
+2 -5
View File
@@ -18,7 +18,7 @@ func init() {
Example: json.RawMessage(`{"id":"annq_1"}`),
})
zip.Describe("GET /v1/o11y/alerts/last", zip.Doc{
Description: "Serves the ring as plain text, newest last, so `curl … | tail` reads\nin the order the pages arrived.",
Description: "Serves the ring as plain text, newest last, so `curl … | tail` reads\nin the order the records were made.",
})
zip.Describe("GET /v1/o11y/logs", zip.Doc{
Description: "Returns a page of one product's logs for the caller's org. A\nnormal caller sees its OWN request stream, derived from org-tagged spans; a\nvalidated platform SuperAdmin sees the product's raw infra stdout stream\ninstead. Poll for a live tail by passing the previous response's nextCursor\nback as sinceNs. A well-formed product with no backing workload answers an\nempty page rather than an error; a malformed slug is a 400.",
@@ -186,11 +186,8 @@ func init() {
zip.Describe("POST /obs/error/post", zip.Doc{
Description: "Relays one Sentry-wire request to the runtime and returns its\nanswer VERBATIM — a 401 \"invalid ingest key\" must reach the SDK as a 401, not\nbe reshaped into a plane error. The request is rebuilt here rather than\nforwarded as bytes because the runtime is an http.Handler.",
})
zip.Describe("POST /obs/event/claim", zip.Doc{
Description: "Offers a body to the LLM-obs sink. Claimed=false is the normal\nanswer for a product event and MUST leave the body untouched — the door then\nruns its own wire, so a wrong claim here silently reroutes a tenant's data.",
})
zip.Describe("POST /v1/o11y/alerts/:receiver", zip.Doc{
Description: "Records one Alertmanager notification and pages Slack. Always 200\nwith body \"ok\": Alertmanager retries on any other status, and a receipt that\npushes back is a receipt that changes the thing it is measuring.",
Description: "Records one Alertmanager notification, carries it to a human, and\nanswers with the result of the CARRYING — not of the recording.\n\nDelivery is SYNCHRONOUS. The previous version sent in a detached goroutine,\nwhich made 200 structurally incapable of meaning anything: the response was\nwritten before the send was tried. A bounded wait is what makes the status\ncode a fact rather than a hope.",
})
zip.Describe("POST /v1/o11y/reviews", zip.Doc{
Description: "Creates a human-review queue in the caller's org and\nproject. A name already used by another queue in the same project is a 409.",
+18657 -12
View File
File diff suppressed because it is too large Load Diff
+29918 -137
View File
File diff suppressed because it is too large Load Diff