Skip to content

docs(api): REST API docs systemically wrong — 102 high-severity gaps across 34 services trace to ~8 single-source root causes (fix the generator, not the endpoints) #4599

Description

@koala73

Summary

A full documentation-gap audit of the REST surface (34 services, 192 endpoints, 341 query params) confirmed 102 high-severity gaps. They are not 192 independent bugs — they are a handful of defects stamped repeatedly by three shared layers: the proto→OpenAPI generator, the generated router, and the seed-cache handler pattern. Fixing each root cause once (in the generator / router codegen / proto conventions) resolves the large majority of findings in a few regenerate commits. Per-endpoint doc editing is the wrong altitude.

Hard-verified ground truth:

  • Auth undocumented on 100% of endpoints: 0 components.securitySchemes, 0 operation security blocks, 0 401 bodies — yet every endpoint is API-key-enforced at the gateway.
  • Examples: 0/192.
  • 74/341 query params (22%) have empty descriptions.
  • Generator hardcodes required:false on every query param, ignoring proto buf.validate.required=true → ~25 effectively-required params documented as optional (and contradicting their own component required:[...]).
  • Filter params are bare strings while handlers exact-match fixed token sets → wrong value = silent empty 200.
  • Router coerces absent bbox corners to 0 (a real coordinate) → 6+ endpoints silently return empty 200 instead of 400.
  • Seed-cache handlers ignore documented pagination/time/geo/severity params and return empty-on-degradation; the spec explains neither.
  • Pro/entitlement gating is invisible (some 403, some silent empty 200; one doc even claims a gated RPC is "Free/public").

Systemic root causes (each: scope → the ONE upstream fix)

  1. No auth in any spec. Scope: 34/34 services, 192 eps. Fix: generator injects shared securitySchemes.apiKey (X-API-Key/X-WorldMonitor-Key) + global security + reusable 401; regenerate.
  2. Zero examples. Scope: 192/192 eps. Fix: proto message sample annotations → generator emits examples; regenerate.
  3. required:false hardcoded. Scope: ~25 params, ≥12 services. Fix: generator reads buf.validate.required → sets parameter required:true; regenerate.
  4. Filter params have no enum. Scope: Cyber, Military(type/kind), Infrastructure(status), Prediction(category), Research(type/feed_type), Intelligence(chokepoint_id/fuel_mode), Conflict/Market(country_code), Economic(BLS). Fix: propagate proto enums onto query-param schemas + lift in-code Set allow-lists into proto enums/registry; regenerate.
  5. bbox absent→0 coercion. Scope: 6 bbox eps + Imagery + Webcam. Fix: router codegen coerces missing numerics to undefined + shared requireBbox() → 400 with debug header. (= feat(api/dx): military bbox endpoints return silent empty 200 on missing/all-zero bbox — surface 400 or debug header #4595)
  6. Documented-but-ignored params on seed-cache handlers. Scope: ~20 services. Fix: proto (sebuf.doc.unimplemented) annotation rendered as "accepted but ignored" + buf-lint cross-check of handler param usage.
  7. Empty 200 = degradation, indistinguishable from "no data". Scope: ~all seed-backed services. Fix: shared degraded/stale/fetchedAt response field + doc-generator seed-cache note.
  8. Invisible Pro/entitlement gating. Scope: SupplyChain(8), Trade(2), Sanctions, Forecast, Scenario, Market(4). Fix: entitlement registry → generator emits 403 + "PRO-gated" note; standardize gated behavior.

Per-service matrix

Legend: D=empty param-desc · R=required · E=enum · Rs=response-contract · B=behavioral. A (auth) + X (examples) gaps are universal (34/34) and omitted below.

Service Eps High Categories
SupplyChain 20 12 D R Rs B
Economic 28 8 D R E Rs B
Military 9 8 D R E Rs B
Intelligence 25 7 D R E Rs B
Market 23 7 D R E Rs B
Leads 2 6 R E B
Research 4 6 E Rs B
Conflict 5 5 R E Rs B
Trade 6 5 E Rs B
Aviation 11 3 R E Rs B
Infrastructure 11 3 D R E Rs B
News 3 3 R E Rs B
Prediction 1 3 R E Rs B
Scenario 3 3 R E Rs B
Unrest 1 3 Rs B
Webcam 2 3 D R E Rs B
Climate 6 2 E Rs B
Cyber 1 2 E Rs B
Displacement 2 2 E Rs B
Forecast 4 2-3 D E Rs B
Imagery 1 2 D R E Rs B
Maritime 2 2 R B
Natural 1 2 D Rs B
Sanctions 2 2 D R Rs B
Seismology 1 2 Rs B
ShippingV2 3 2 R E B
Wildfire 1 2 B
ConsumerPrices 6 1 R E B
Giving 1 1 Rs B
Health 2 1 Rs B
PositiveEvents 1 1 Rs B
Radiation 1 1 B
Resilience 3 1 D E Rs B
Thermal 1 1 D Rs B
Total 192 ~102 auth+examples 34/34 · 74/341 empty desc

Prioritized fix plan (fix-once beats per-endpoint)

  1. Generator: auth (securityScheme + security + 401) — 34 services, one change.
  2. Generator: required propagation — ~25 params corrected on regenerate.
  3. Router codegen: bbox (undefined coercion + requireBbox() 400) — delivers feat(api/dx): military bbox endpoints return silent empty 200 on missing/all-zero bbox — surface 400 or debug header #4595.
  4. Generator: enum propagation + lift in-code allow-lists to proto enums.
  5. Proto: field-comment convention + buf-lint gate — fills 74 empty descriptions.
  6. Shared response convention: degraded/stale/fetchedAt + seed-cache doc note.
  7. Proto: (sebuf.doc.unimplemented) annotation + handler-param-usage lint.
  8. Entitlement registry → generator: 403 + PRO-gated note; standardize gated behavior.
  9. Generator: examples from proto samples.
  10. Long-tail per-endpoint edits (<20): Aviation date default; Military force_refresh + aircraft-batch cap 10; Research false "0=unlimited"/max 500 clamps; Webcam lastUpdated int64→ISO; misleading example values.

Fold-in checklist

Note: 13 additional high-severity candidates were rejected on verification (already documented or code-truth wrong); the 102 confirmed set above is authoritative.


Audit provenance

Method: full-surface sweep — one deep auditor per service diffing proto + generated routes + handlers against docs/api/*.openapi.json, then adversarial verification of every high-severity gap (34 audit agents + 102 verifiers + synthesis). 349 total gaps, 115 high → 102 confirmed, 13 rejected as already-documented/incorrect.

Independently re-verified before filing: 340/341 query params are required:false (1 true); 0/34 services declare components.securitySchemes; 0/192 operations carry examples; 74/341 params have empty descriptions; concrete param-vs-component contradiction confirmed (AnalyzeStockRequest.required:[symbol] vs symbol query param required:false).

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: APIBackend API, sidecar, keysenhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions