Skip to content

feat(witan-core): send and check the Omnigraph-Http-Api contract header - #464

Merged
blarghmatey merged 2 commits into
mainfrom
omnigraph-013-http-api-header
Oct 8, 2026
Merged

blarghmatey merged 2 commits into
mainfrom
omnigraph-013-http-api-header

Conversation

@blarghmatey

Copy link
Copy Markdown
Member

What are the relevant tickets?

N/A (witan task tk-send-and-check-the-omnigraph-http-api-0-12-heade-a85e58, part of the omnigraph 0.13 upgrade, spec in #461 D7)

Description (What does it do?)

omnigraph-server 0.13 answers 400 api_contract_mismatch to any protected request without exactly one Omnigraph-Http-Api: 0.13 header, and stamps that header on every response. PooledTransport is our only direct HTTP client and sent none, so every HTTP read and write would fail after the pin bump.

This sends the header on every request. A 0.11 server ignores it, so this can merge ahead of the pin.

It also checks the response's header before decoding the body. Upstream's rule is that a missing or incompatible response header "means unknown effects, never permission to replay". A violation is a new outcome kind, CONTRACT_VIOLATION. It is never retried, and for a write the retry loop raises WriteIndeterminate, as it does for the recovery barrier.

  • A stamp naming another contract is always a violation.
  • A missing stamp is a violation for a 2xx (the body is not a result) and for any refusal of a write. We retry a write on 429/503/409 because the server saying so proves nothing was applied. A proxy saying so proves nothing.
  • A read that failed with no stamp keeps its ordinary classification, since repeating a read is safe.

0.11 sends no stamp, so the missing-stamp rule is gated on _OMNIGRAPH_INTERNAL_SCHEMA >= 14 and turns on with the pin bump. Two consequences for that bump, recorded on its task:

  • A 0.13-pinned client against a still-0.11 server would have every write applied and then reported as indeterminate. The data tier has to roll before the witan clients.
  • If anything between witan and omnigraph-server can synthesize a 429 or 503, a write that hits it becomes terminal where today it waits out the restart budget.

The contract value is its own constant. Upstream keeps it separate from the package version, so it is not derived from _OMNIGRAPH_VERSION.

How can this be tested?

  • On omnigraph 0.11.0: just test-witan-core 728 passed, just test-witan-council 1429 passed, just test-witan-code 682 passed.
  • Checked on scratch servers with curl and by driving PooledTransport at them:
    • 0.11.0 answers a query and a mutate carrying the header with 200 and returns no such response header. With the missing-stamp rule forced on, both come back as CONTRACT_VIOLATION, which is the mixed-fleet case above.
    • 0.13.0 answers 200 with the header and 400 {"code":"api_contract_mismatch"} without it or with 0.12. It stamps omnigraph-http-api: 0.13 on 200, 400, 403 and 404 responses. With the rule forced on, query and mutate return ok, and an unknown graph's 404 keeps its ordinary classification.
  • Not exercised against a real proxy or a deployed cluster.

https://claude.ai/code/session_01Mfmuz4DTn557AV8V17o98A

omnigraph-server 0.13 answers 400 api_contract_mismatch to any protected
request without exactly one `Omnigraph-Http-Api: 0.13`, and stamps the same
header on every response. PooledTransport is our only direct HTTP client,
and it sent none.

This sends the header on every request. A 0.11 server ignores it, so this
is safe ahead of the pin.

It also checks the response's header before decoding the body, following
upstream's rule that a missing or incompatible one means unknown effects
and never permission to replay. A violation is its own outcome kind,
CONTRACT_VIOLATION: never retried, and raised as WriteIndeterminate for a
write. A stamp naming another contract is always a violation. A missing
stamp is one for a 2xx and for any refusal of a write, because a
429/503/409 from something other than the server does not prove the write
was not applied. A read that failed unstamped keeps its ordinary
classification. 0.11 sends no stamp, so the missing-stamp rule is gated on
`_OMNIGRAPH_INTERNAL_SCHEMA >= 14` and turns on with the pin bump.

Claude-Session: https://claude.ai/code/session_01Mfmuz4DTn557AV8V17o98A
Copilot AI balanced review requested due to automatic review settings October 8, 2026 18:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Response validation currently occurs after body decoding and permits retries that conflict with the accepted contract.

2 open findings
What changed in this PR

Adds Omnigraph 0.13 HTTP contract negotiation to witan-core while retaining 0.11 compatibility.

Changes:

  • Sends and validates Omnigraph-Http-Api: 0.13.
  • Adds terminal and indeterminate outcome handling.
  • Expands compatibility and retry-policy tests.
File Description
packages/​witan-core/​witan_core/​omnigraph.py Handles write contract violations.
packages/​witan-core/​witan_core/​omnigraph_http.py Implements contract headers and validation.
packages/​witan-core/​tests/​test_omnigraph_http.py Tests contract behavior and retries.
packages/​witan-core/​changelog.d/​20261008_133544_blarghmatey_omnigraph_013_http_api_header.md Documents the feature.
mcp/​servers/​witan-code/​tests/​test_store.py Updates the HTTP response test double.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/witan-core/witan_core/omnigraph_http.py
Comment thread packages/witan-core/witan_core/omnigraph.py Outdated
The response body was UTF-8 decoded one line before the stamp check, which
the check's own comment and upstream's rule both say comes first. The
decode now happens after the violation branch.

The WriteIndeterminate message said the response was "without" a stamp. A
violation also covers a stamp for another contract and a repeated one, and
the appended detail can then read "found '0.14'". It now says the response
did not carry exactly the expected stamp.

Claude-Session: https://claude.ai/code/session_01Mfmuz4DTn557AV8V17o98A
@blarghmatey
blarghmatey merged commit e1d9bdb into main Oct 8, 2026
20 checks passed
@blarghmatey
blarghmatey deleted the omnigraph-013-http-api-header branch October 8, 2026 19:34
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.

2 participants