Skip to content

feat: version HTTP API under /v1 and publish OpenAPI (#12) - #40

Merged
cursor[bot] merged 1 commit into
mainfrom
cursor/api-v1-versioning-1cc6
Aug 17, 2026
Merged

cursor[bot] merged 1 commit into
mainfrom
cursor/api-v1-versioning-1cc6

Conversation

@leo-aa88

Copy link
Copy Markdown
Member

Closes #12.

Serves ingest, query, and config under /v1/ as the stable contract. Unversioned /ingestions, /query/*, and /config remain as deprecated aliases for one release (Deprecation: true plus a Link successor header). /health, the UI, and /static stay unversioned.

JSON response bodies are unchanged; structured evidence schema is G7 (#16).

Canonical paths

  • POST /v1/ingestions, GET /v1/ingestions*
  • POST /v1/query/{explain,ask,clusters,timeline,compare}
  • GET /v1/config

Auth treats /v1/... the same as the unversioned paths. The web UI now calls /v1.

OpenAPI and clients

  • make openapi writes clients/openapi.json
  • CI uploads that file as an artifact and attaches it to tagged GitHub Releases
  • Python: src.clients.v1.RaglogsClient (httpx, targets /v1)
  • make client-go runs oapi-codegen when installed, otherwise prints an install hint

Compatibility policy: additive changes within v1; breaking changes require v2.

Tests

Contract tests assert required /v1 paths exist on app.openapi(). Existing unversioned TestClient tests still pass; new tests cover /v1 parity and the Deprecation header.

Open in Web Open in Cursor 

Dual-mount ingest/query/config at /v1 (canonical) and keep unversioned
paths as deprecated aliases. Export OpenAPI for client codegen.
JSON response bodies are unchanged; G7 is separate.

Refs #12

Co-authored-by: Leonardo <leo-aa88@users.noreply.github.com>
@cursor

cursor Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@cursor

cursor Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Code review — PR #40 (issue #12)

must-fix

None

Dual-mount is correct: _include_v1_and_alias in src/api/app.py:69 mounts the same routers at /v1{suffix} and {suffix} (deprecated=True). Canonical /v1/ingestions (GET+POST) and /v1/query/{explain,ask,clusters,timeline,compare} exist in app.openapi() and in committed clients/openapi.json. Unversioned TestClient tests still hit /ingestions and /query/* and remain valid aliases.

Auth does not bypass via /v1: required_roles strips /v<digits> in src/api/auth/roles.py:45 before matching. Middleware tests cover POST /v1/query/explain 401 without a token, query-role 403 on POST /v1/ingestions, and ingest-role allowed on POST /v1/ingestions. /health and / / /static are not deprecated (DeprecationHeaderMiddleware only tags /ingestions, /query, /config).

Contract test tests/unit/test_openapi_contract.py:28 (test_canonical_v1_paths_exist) fails if a required /v1 path disappears from app.openapi(). CI exports clients/openapi.json as an artifact; publish-openapi-release is gated on startsWith(github.ref, 'refs/tags/') so skip on this PR is expected. make client-go exits 0 when oapi-codegen is missing; CI does not invoke it. Python RaglogsClient hardcodes /v1/.... Same handlers → JSON bodies unchanged. No secrets; migrations/versions/ untouched.

should-fix

None

nice-to-have

  • tests/unit/test_openapi_contract.py:28 (test_canonical_v1_paths_exist) asserts live app.openapi(), not committed clients/openapi.json. CI uploads a freshly exported artifact, so the Actions file stays current; a forgotten make openapi can still leave the vendored spec stale for local make client-go. Optional: assert the committed file equals app.openapi().
  • tests/unit/test_v1_client.py:31 (test_explain_targets_v1_and_returns_body) never checks the request path. Unversioned /query/explain still returns 200, so a client regression off /v1 would still pass. Optional: assert the URL contains /v1/query/explain.
  • src/api/routes/ingestions.py:104 (create_ingestion docstring) still says GET /ingestions/jobs/{worker_job_id} and /query/explain. That text is now published on POST /v1/ingestions in OpenAPI, so codegen docs point at the deprecated aliases. Aliases still work for this release; updating the docstring to /v1/... would match the new contract.

Verdict

must-fix count: 0
should-fix count: 0

@cursor
cursor Bot merged commit 53ba88f into main Aug 17, 2026
2 checks passed
@leo-aa88
leo-aa88 deleted the cursor/api-v1-versioning-1cc6 branch August 17, 2026 07:23
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.

feat(G3): API versioning under /v1 + published OpenAPI & client codegen

2 participants