Skip to content

Publish a machine-readable API contract (OpenAPI 3.1) - #10

Merged
lgelauff merged 1 commit into
mainfrom
feat/openapi-contract
Sep 19, 2026
Merged

lgelauff merged 1 commit into
mainfrom
feat/openapi-contract

Conversation

@lgelauff

Copy link
Copy Markdown
Owner

The contract existed only as prose and tests, so a consumer had to hand-code the response shape and could get it wrong without either side noticing. That is what happened: wiki-polis reads event from a /check response, which never carries it.

  • openapi.json describes /check, /policies, /policies/{id}, /health and /, with schemas for Verdict, Criterion, Requirement, PolicyText, PolicySummary, PolicyList, PolicyDetail, PolicyRule, Error, Health and Index.
  • Served at /openapi.json; version written once (VERSION), echoed on / and as the Canivote-Version header.
  • Errors carry a stable code; 429 now returns the same Error shape instead of the limiter's body.
  • Removed the event alias for policy; no consumer reached it.
  • tests/test_openapi_contract.py validates fixture-driven responses against the document and asserts the three version sources agree. It immediately caught two under-typed fields: list-valued criteria values and the queries list.

Refs #9

The contract existed only as prose and tests, so a consumer had to hand-code
the response shape and could get it wrong without either side noticing. That is
what happened: wiki-polis reads `event` from a /check response, which never
carries it.

- openapi.json describes /check, /policies, /policies/{id}, /health and /,
  with schemas for Verdict, Criterion, Requirement, PolicyText, PolicySummary,
  PolicyList, PolicyDetail, PolicyRule, Error, Health and Index.
- Served at /openapi.json; version written once (VERSION), echoed on / and as
  the Canivote-Version header.
- Errors carry a stable `code`; 429 now returns the same Error shape instead
  of the limiter's body.
- Removed the `event` alias for `policy`; no consumer reached it.
- tests/test_openapi_contract.py validates fixture-driven responses against the
  document and asserts the three version sources agree. It immediately caught
  two under-typed fields: list-valued criteria values and the queries list.

Refs #9
@lgelauff
lgelauff merged commit d106e63 into main Sep 19, 2026
2 checks passed
@lgelauff
lgelauff deleted the feat/openapi-contract branch September 19, 2026 12:41
@lgelauff

Copy link
Copy Markdown
Owner Author

Live verification of the published contract

Deployed at https://canivote.toolforge.org and checked from a separate consumer (wiki-polis staging):

Check Result
/ version + Canivote-Version header 1.0.0
/openapi.json served, OpenAPI 3.1.0, all five paths present
event alias removed 400 bad_request
unknown policy 404 unknown_policy + known_policies
/policies 200; validates as PolicyList
live /check?user=Jimbo Wales&policy=meta-global 200, eligible; validates as Verdict against the deployed document
429 returns the shared Error shape

The consumer that motivated this (wiki-polis #425) was reading event from /check; with the contract pinned, its fix now reads policy, and its tests build a response shaped like this document. Staging end-to-end: a not-eligible account is refused with eligibility_denied, and an eligible one passes.

Follow-ups filed: #11 (bad requests should show a good one), #12 (verbose / non-verbose).

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.

Publish a machine-readable API contract, so consumers stop guessing at the response shape

1 participant