Files
o11y/pkg/query-service/app/routes_query_progress.go
zeekay c10b49bbe8 feat(o11y): nothing answers outside /v1/o11y — sentinel folds, /ws merges
Two addresses were still spelled at a root that is not this capability's, and
HIP-0139 §3 gives every route one home: /v1/<name>. Both close by fold, and
neither leaves an alias behind.

/v1/sentinel/* -> /v1/o11y/sentinel/*. The error-tracking face is twelve
concrete paths the runtime registers literally, plus the declaration table's
group over the same root, so one constant and the registrations under it move
together. It is one capability's second face, not a second capability: same
store, same runtime, same tenant rule. The ingest door is unaffected — a minted
DSN names /v1/event and always did.

/ws/query_progress merges onto /v1/o11y/query_progress. It was never a second
read: one handler answered both mount points, upgrading when the caller asked
and long-polling when it did not. The Upgrade is a property of the request, not
of the address, so two paths bought a second spelling and nothing else. /ws was
also the last address this service answered outside /v1, and the console's
api-prefix list drops it with the route.

The hatch census goes eleven to ten and the surface 367 to 366 — the numbers are
tests here, not prose, so they move in the same commit as the route.
2026-08-20 20:32:28 -07:00

29 lines
1.3 KiB
Go

package app
import (
"github.com/hanzoai/o11y/pkg/http/middleware"
"github.com/hanzoai/o11y/pkg/http/routing"
)
// Query progress streaming. 1 route, one handler, one mount point.
//
// It was two — the long-poll under /v1/o11y and a websocket under /ws — for one
// handler that reads the same progress either way. The Upgrade is a property of
// the REQUEST, not of the address: GetQueryProgressUpdates upgrades when the
// caller asks and long-polls when it does not, so a second path bought a second
// spelling of one read and nothing else. /ws was also the last address this
// service answered outside /v1.
//
// ESCAPE HATCH. It is deliberately NOT a typed query-core op:
// GetQueryProgressUpdates upgrades the connection to a websocket, and the
// query-core relay buffers a whole answer through an httptest recorder that
// cannot hijack a connection — a typed progress op would never complete the
// handshake. It stays a hatch, byte-identical; see the escape-hatch record in
// querycore.go.
// mountQueryProgress registers the progress path on the shared /v1/o11y
// subrouter owned by RegisterQueryRangeV3Routes. 1 route, both protocols.
func (aH *APIHandler) mountQueryProgress(subRouter routing.Router, am *middleware.AuthZ) {
subRouter.Get("/query_progress", am.ViewAccess(aH.GetQueryProgressUpdates))
}