Skip to content

M1: add /v1/literature/search, /literature/domains, /v1/usage, /v1/models - #24

Merged
man4ish merged 1 commit into
mainfrom
feature/v1-literature-search-domains-usage-models
Oct 3, 2026
Merged

man4ish merged 1 commit into
mainfrom
feature/v1-literature-search-domains-usage-models

Conversation

@man4ish

@man4ish man4ish commented Oct 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

Part of M1, building on M0's contract-freeze/outbox work. Adds the four remaining endpoints from the design doc's public API table ("most public endpoints are missing"):

  • POST /v1/literature/search — billable ("1 search", ~1/10th of an answer per the design's pricing table), retrieval-only. Forwards to the companion omnibioai-rag PR's new mode="search" (no LLM call at all). Shares the exact same idempotency/quota/usage lifecycle as /literature/answers via a new _handle_billable_literature_call helper, factored out so the two billable endpoints can't silently drift apart on that sequencing. Bills literature.search, not literature.answer.
  • GET /literature/domains — the same omnibioai-rag study list /literature/studies already exposes (left untouched for backward compatibility), reshaped under the design doc's public name ("domain"). Free, rate-limited, never billed.
  • GET /v1/usage — the gateway's first synchronous call into omnibioai-billing, forwarding to its existing GET .../subscription/usage-limits and translating included/used/remaining per resource. Free. Gated on usage.read — already registered in omnibioai-auth's Permission Registry as "reserved, not yet enforced by any route" (the same state dataset.read/model.use/workflow.execute were in before this gateway's own IAM Foundation integration); this is its first real consumer. Estimated-charge-in-dollars is deliberately omitted — would need billing's cost-summary period math, not yet done, and reporting it wrong would be worse than omitting it.
  • GET /v1/models — a static one-entry catalog (no upstream call) for the one model path that actually exists today. price is null, not a placeholder number — the design doc's pricing section says to measure real GPU cost first (M0, 1,000 representative questions), which hasn't been run.

Known follow-up: usage.read is newly wired into SERVICE_PERMISSION_MAP as policy-engine context, matching the established pattern, but whether any role is actually granted usage.read today is an omnibioai-policy-engine configuration question outside this repo — flagging so it isn't missed before /v1/usage is expected to work end-to-end for real callers.

Depends on: the companion omnibioai-rag PR (mode="search") for /v1/literature/search to return real results — this gateway change is forward-compatible either way (it just forwards mode: "search" and translates whatever comes back).

Test plan

  • pytest — 353 passed, including a pre-existing test (test_pr13_role_tier_permission_forwarding.py) that parametrizes over every SERVICE_MAP key and would have caught a missing SERVICE_PERMISSION_MAP entry for billing
  • ruff check . — clean
  • New coverage: contract-translation tests for build_rag_search_query/build_public_search, and route-level tests for all four new endpoints (auth, rate-limit, billing lifecycle, upstream-error mapping, free-vs-billed)

🤖 Generated with Claude Code

…models

Part of M1 (filling in the design doc's "most public endpoints are
missing" gap) on top of M0's contract-freeze/outbox work. Adds the
four remaining endpoints from the design doc's public API table:

- POST /v1/literature/search: billable ("1 search", ~1/10th of an
  answer per the pricing table), retrieval-only -- forwards to
  omnibioai-rag's new mode="search" (no LLM call at all). Shares the
  exact same idempotency/quota/usage lifecycle as /literature/answers
  via a new _handle_billable_literature_call helper, factored out so
  the two billable endpoints can't silently drift apart on that
  sequencing. Bills "literature.search", not "literature.answer".
- GET /literature/domains: the same omnibioai-rag study list
  /literature/studies already exposes (left untouched for backward
  compatibility), reshaped under the design doc's public name
  ("domain"). Free, rate-limited, never billed.
- GET /v1/usage: the gateway's first synchronous call into
  omnibioai-billing, forwarding to its existing GET
  .../subscription/usage-limits and translating included/used/
  remaining per resource. Free. Gated on usage.read -- already
  registered in omnibioai-auth's Permission Registry as "reserved,
  not yet enforced by any route" (same state dataset.read/model.use/
  workflow.execute were in before this gateway's own IAM Foundation
  integration); this is its first real consumer. Estimated-charge-in-
  dollars is deliberately omitted (would need billing's cost-summary
  period math, not yet done -- reporting it wrong would be worse than
  omitting it).
- GET /v1/models: a static one-entry catalog (no upstream call) for
  the one model path that actually exists today. price is null, not a
  placeholder number -- the design doc's own pricing section says to
  measure real GPU cost first (M0, 1,000 representative questions),
  and that hasn't been run yet.

Tests: 353 passed (was 349 + 4 pre-existing-but-newly-triggered
failures from test_pr13_role_tier_permission_forwarding.py, which
parametrizes over every SERVICE_MAP key and asserts a matching
SERVICE_PERMISSION_MAP entry -- adding "billing" to SERVICE_MAP
without usage.read would have broken that invariant). ruff clean.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@man4ish
man4ish merged commit c27c33f into main Oct 3, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant