Skip to content

feat(cues): add --verify opt-in flag to fire (cueapi-python #41 parity)#55

Merged
mikemolinet merged 1 commit into
mainfrom
feat/cues-fire-verify-optin
May 12, 2026
Merged

feat(cues): add --verify opt-in flag to fire (cueapi-python #41 parity)#55
mikemolinet merged 1 commit into
mainfrom
feat/cues-fire-verify-optin

Conversation

@mikemolinet
Copy link
Copy Markdown
Collaborator

Summary

Parity port of cueapi-python #41 — body-verify Phase 2 on cues fire, but OPT-IN (default off).

Design rationale (mirrors primary's #41)

Substrate's /v1/cues/{id}/fire echoes a pydantic-after-parse body that may include server-side default-population, causing spurious diff vs the CLI's canonical-JSON serialization. So --verify is opt-in — caller flips it on when they know substrate echo semantics match their serialization (typical for the sha256 constant-cost path).

This diverges from messages-send body-verify which is default-on (--no-verify opt-out): that endpoint echoes the raw STRING body field per the #798 spec-lock — no parsed-defaulted shape concern.

Wire shape

CLI invocation X-CueAPI-Verify-Echo header Verify check runs
cueapi fire cue_x omitted no
cueapi fire cue_x --verify "true" yes (SHA256 constant-cost compare + string-compare fallback on SHA drift)

Verify logic

  1. Pre-compute sha256(canonical-JSON(body)) hex client-side.
  2. On 2xx response: compare against body_received_sha256 field (constant-cost).
  3. If SHA mismatch: fall back to string compare of body_received vs canonical body JSON. Spurious SHA mismatch (e.g. JSON serialization diff) is rescued by string compare.
  4. Defensive isinstance on body_received: string (post-#798 spec-lock) OR dict (pre-#798 wire shape) — matches cueapi-cli messages-send fix(messages send + message-to): body_received is dict not flat string #53 and cueapi-python feat: cueapi message-to <name> + agents list --online-only + agents describe alias #40.
  5. On confirmed mismatch: exit 7 with byte-divergence diagnostic. Uses click.echo + raise SystemExit(7) directly (NOT echo_error, which raises SystemExit(1) and would shadow the verify-specific exit code).

Tests (4 new)

  • test_fire_verify_off_by_default_omits_header — preserves pre-#791 wire format
  • test_fire_verify_on_sends_header--verify sends header + matching SHA path passes silently
  • test_fire_verify_help_lists_flag--help discovers the opt-in rationale
  • test_fire_verify_mismatch_exits_7 — substrate echoes corrupted body ⇒ exit 7 with "body-verify mismatch"

Full file: 219/219 passing (215 + 4 new).

Parity-impact checklist

Backlog row: cmp1wj0q3.

🤖 Generated with Claude Code

…y, Mike body-verify directive 2026-05-11)

Parity port of cueapi-python #41 — body-verify Phase 2 on cues.fire,
but **OPT-IN** (not default-on) because the substrate's
/v1/cues/{id}/fire endpoint echoes a pydantic-after-parse body that
may include server-side default-population, causing spurious diff
vs the CLI's canonical-JSON serialization.

Mirrors primary's #41 design rationale: default OFF; caller opts in
with --verify when they know substrate echo semantics match their
serialization (typical for the sha256 constant-cost path).

Diverges from messages-send body-verify which is default-on
(--no-verify opt-out) because that endpoint echoes the raw STRING
body field per the spec-lock — no parsed-defaulted shape concern.

Implementation:
- New --verify click flag (is_flag, default False). Help text
  documents the OPT-IN rationale + the substrate-echo-shape concern.
- When --verify: send X-CueAPI-Verify-Echo: true header; pre-compute
  sha256(canonical-JSON(body)) hexdigest client-side.
- On 2xx response: compare sha256 first (constant-cost). If sha
  mismatch, fall back to string compare of body_received vs canonical
  body JSON. Spurious sha mismatch (e.g. canonical-JSON serialization
  diff) is rescued by the string compare.
- Defensive isinstance: body_received as string (post-#798 spec-lock)
  OR dict (pre-#798 wire shape). Matches the same pattern in
  cueapi-cli messages-send (#53) and cueapi-python messages.send
  (#40).
- On confirmed mismatch: exit 7 with byte-divergence diagnostic.
  Uses click.echo + raise SystemExit(7) directly (NOT echo_error
  which would raise SystemExit(1) and shadow the verify-specific
  exit code).

Tests (4 new):
- test_fire_verify_off_by_default_omits_header — no --verify ⇒ no
  X-CueAPI-Verify-Echo header (preserves pre-#791 wire format)
- test_fire_verify_on_sends_header — --verify ⇒ header set + sha
  match path passes silently
- test_fire_verify_help_lists_flag — --help mentions --verify + the
  opt-in rationale so users discover the design context
- test_fire_verify_mismatch_exits_7 — substrate echoes corrupted
  body ⇒ exit 7 with "body-verify mismatch" diagnostic

Full file: 219/219 passing (was 215 + 4 new = 219).

Backlog row: cmp1wj0q3.

Out of scope:
- cueapi-mcp parity (Backlog cmp1wj2a6) — separate PR.
@govindkavaturi-art govindkavaturi-art enabled auto-merge (squash) May 12, 2026 00:47
@mikemolinet mikemolinet merged commit a4b1982 into main May 12, 2026
5 checks passed
@mikemolinet mikemolinet deleted the feat/cues-fire-verify-optin branch May 12, 2026 00:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant