feat(cues): opt-in auto_verify on cueapi_fire_cue (cueapi-cli #55 + cueapi-python #41 parity)#36
Merged
Merged
Conversation
…ueapi-python #41 parity)
Parity port of cueapi-cli #55 and cueapi-python #41 — body-verify
Phase 2 on cueapi_fire_cue tool, OPT-IN (default false).
## Design rationale (verbatim from primary's #41)
Substrate /v1/cues/{id}/fire echoes a pydantic-after-parse body that
may include server-side default-population, causing spurious diff vs
the tool's JSON.stringify(body). So auto_verify is opt-in — caller
flips it on when they know substrate echo semantics match their
serialization.
Diverges from cueapi_send_message (cueapi-mcp #35) which is default-
on: that endpoint echoes the raw STRING body field per the #798 spec-
lock — no parsed-defaulted shape concern.
## Implementation
- Schema: auto_verify: optional<boolean> (default false). Help text
documents the opt-in rationale + the substrate-echo-shape concern.
- Handler: when auto_verify=true, sends X-CueAPI-Verify-Echo: true
header + captures sentBodyStr = JSON.stringify(body). After response,
compares against body_received (defensive isinstance: STRING per
spec-lock OR dict pre-#798 wire shape → JSON.stringify for compare).
- Throws on mismatch with byte-divergence index + execution id +
diagnostic pointing to caller-side payload mutation as typical cause.
## Notable trade-off vs cueapi-cli/python
Skips the SHA256 constant-cost fast-path that python #41 and cli #55
both have. Reason: Web Crypto SubtleCrypto.digest() is async; embedding
it in this synchronous-shape handler would force the whole tool async-
contortion. Accepts the trade-off of string-compare-only for the MCP
TS port. JSON.stringify deterministic serialization on Node makes the
string compare reliable for non-trivial payloads.
## Tests (7 new)
- default (no auto_verify) omits X-CueAPI-Verify-Echo header
- auto_verify=true sends the header
- matching body_received (STRING shape post-#798) passes silently
- matching body_received (dict shape pre-#798) passes via
JSON.stringify-equivalence
- mismatched body_received throws with byte-divergence diagnostic
- mismatch error includes execution id from response
- missing body_received (substrate didn't echo) is silently OK
Full suite: 149/149 passing (was 142 + 7 new).
Backlog row: cmp1wj2a6.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Parity port of cueapi-cli #55 and cueapi-python #41 — body-verify Phase 2 on
cueapi_fire_cuetool, OPT-IN (default false).Design rationale (verbatim from primary's #41)
Substrate
/v1/cues/{id}/fireechoes a pydantic-after-parse body that may include server-side default-population, causing spurious diff vs the tool'sJSON.stringify(body). Soauto_verifyis opt-in — caller flips it on when they know substrate echo semantics match their serialization.Diverges from
cueapi_send_message(cueapi-mcp #35) which is default-on: that endpoint echoes the raw STRING body field per the #798 spec-lock — no parsed-defaulted concern.Wire shape
X-CueAPI-Verify-Echoheaderauto_verify)auto_verify: true"true"auto_verify: falseNotable trade-off vs python/cli
Skips the SHA256 constant-cost fast-path that python #41 and cli #55 both have. Reason: Web Crypto
SubtleCrypto.digest()is async; embedding it here would force the whole tool async-contortion. The string-compare-only trade-off is reliable sinceJSON.stringifyis deterministic on Node for non-trivial payloads. If MCP ever needs hash-based verify, the helper can move to a separate async path.Tests (7 new)
auto_verify) omits header — preserves wire format for non-opted callersauto_verify: truesends headerbody_received(STRING shape post-#798) passes silentlybody_received(dict shape pre-#798) passes via JSON.stringify-equivalencebody_receivedin response (substrate didn't echo) is silently OKFull suite: 149/149 passing (was 142 + 7 new).
Parity-impact checklist
body_receivedshapesBacklog row:
cmp1wj2a6.🤖 Generated with Claude Code