Skip to content

Discovery advertises capabilities.search = {enabled:false} while GET /api/v1/search serves 200 with real hits #7541

Description

@huangyiirene

Symptom

On a live showcase host, /discovery reports:

capabilities.search = { "enabled": false }
services.search = { "enabled": false, "status": "unavailable", ... }

while the endpoint those bits describe is fully live:

GET /api/v1/search?q=audit → 200, 5 real hits

Expected: the declared capability matches served behaviour (Prime Directive #10, declared === enforced) — either the bit is enabled: true, or the endpoint refuses.

Impact: a client that trusts the discovery document — which is exactly what the document is for — skips a working surface. This is the failure mode discovery exists to prevent, inverted: not an advertised endpoint that 404s, but a real endpoint no conforming client will ever call.

Root cause

The capability bit derives from a registered search service slotsearch: registeredServices.has('search') in the well-known capability builder (packages/metadata-protocol/src/protocol.ts) — while the route (registerSearchEndpoints, packages/rest/src/rest-server.ts) gates on something else entirely: it only answers 501 NOT_IMPLEMENTED when protocol.searchAll is missing, and the protocol implements searchAllregardless of whether any search service slot is registered. The two producers answer the same question with two unrelated predicates.

Note the neighbouring keys in that same builder are already serveability-gated with a comment stating the rule ("the predicate is deliberately the SAME one that decides whether the route is advertised — what we advertise and what we claim cannot disagree"; chunkedUpload was moved onto it in #5672). search is one of the keys still on bare slot presence, and its route does not consult the slot at all — so the fix must pick ONE predicate for both ends: either derive the bit from typeof protocol.searchAll === 'function', or make the route honour the slot. Primary lane is the capability builder in packages/metadata-protocol; the seam reaches packages/rest.

Reproduction

  1. Boot showcase on a fresh isolated file DB (SqlDriver / better-sqlite3); authenticate as admin@objectos.ai.
  2. GET /api/v1/discoverycapabilities.search.enabled === false, services.search.status === "unavailable".
  3. GET /api/v1/search?q=audit200 with 5 real hits.

Source

Extracted from the QA run #7463 (framework a86db17).

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions