Skip to content

hotfix(parity): BodyVerify body_received STRING shape (cueapi/cueapi#798)#88

Merged
mikemolinet merged 1 commit into
mainfrom
hotfix/bodyverify-body-field-string-shape
May 12, 2026
Merged

hotfix(parity): BodyVerify body_received STRING shape (cueapi/cueapi#798)#88
mikemolinet merged 1 commit into
mainfrom
hotfix/bodyverify-body-field-string-shape

Conversation

@mikemolinet
Copy link
Copy Markdown
Collaborator

Summary

Parity port of cueapi/cueapi#798 (merged 23:39Z). Phase 1 echoed Pydantic envelope dump as `body_received` instead of the design-lock spec's flat STRING; caller-side `sha256(sent_body)` never matched. This hotfix restores the spec'd shape.

Direction of parity: private-leads, OSS-lags.

Fix

  • `app/utils/verify_echo.py` — helper signature changed from `parsed_body: Any` to `body_text: Optional[str]`. Caller passes the exact string to echo.
  • `app/routers/messages.py` — passes `body.body` string (the message body field).
  • `app/routers/cues.py` — passes `body_text=None` since OSS `FireRequest` carries only `send_at` (datetime). Hosted's `payload_override.message` extraction is hosted-only.
  • `tests/test_verify_echo.py` — 25 tests asserting STRING type + caller-side `sha256(sent.encode()) == response.body_received_sha256` matches.
  • `parity-manifest.json` — bumped `last_synced` and appended hotfix deviation notes on the 3 modified files.

OSS-specific fire endpoint behavior

OSS `FireRequest` has no string user-content field, so the fire endpoint passes `body_text=None` to the helper regardless. Verify-echo on the fire path is effectively a no-op contract on OSS until a content-bearing field is added (e.g. if `payload_override` is ever ported).

Test plan

  • Local: 25/25 OSS tests pass
  • CI: green on cueapi-core
  • parity-check action: no warnings (manifest updated)

🤖 Generated with Claude Code

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 11, 2026

Parity check

This PR modifies files tracked in parity-manifest.json:

  • app/routers/cues.py
  • app/routers/messages.py
  • app/utils/verify_echo.py

Please confirm one of the following in a reply or PR description update:

  1. The equivalent change has been applied to the private cueapi monorepo. Link the PR.
  2. This change is OSS-only and does not need porting. Briefly explain why (e.g. "fixes a bug that only exists in the OSS build").
  3. A follow-up issue has been filed to port the reverse direction. Link the issue.

This is a soft check — it does not block merge. The goal is visibility, not friction. See HOSTED_ONLY.md for the open-core policy.

)

Parity port of cueapi/cueapi#798 (merged 23:39:13Z) — fixes Phase 1
body_received echoing Pydantic envelope dump instead of design-lock
flat STRING. cueapi-python SDK auto-verify (cueapi-python #39) and
caller-side sha256(sent_body) match now work as designed.

Files modified:
- app/utils/verify_echo.py — helper signature changed from
  parsed_body: Any to body_text: Optional[str]
- app/routers/messages.py — passes body.body string (spec lock)
- app/routers/cues.py — passes body_text=None (OSS FireRequest carries
  only send_at datetime; no string user-content field). Hosted's
  payload_override.message extraction is hosted-only.
- tests/test_verify_echo.py — 25 tests asserting STRING type + caller-
  side sha256(sent_body.encode()) == response.body_received_sha256
- parity-manifest: bumped last_synced + appended hotfix deviation notes

25/25 OSS tests pass locally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mikemolinet mikemolinet force-pushed the hotfix/bodyverify-body-field-string-shape branch from 219c0e4 to c3264ed Compare May 11, 2026 23:55
@govindkavaturi-art govindkavaturi-art enabled auto-merge (squash) May 12, 2026 00:01
@mikemolinet mikemolinet merged commit 8b25255 into main May 12, 2026
6 checks passed
@mikemolinet mikemolinet deleted the hotfix/bodyverify-body-field-string-shape branch May 12, 2026 00:01
mikemolinet added a commit that referenced this pull request May 12, 2026
…#590) per primary's authoritative split (#89)

Adds a new `field_drift_annotations` section to parity-manifest.json
documenting why specific fields in private cueapi's Execution + Cue
schemas are absent from OSS. Authoritative split from cueapi-primary
via cue-pm relay (msg_4ofzmxcjoyu4, 2026-05-12).

## Three buckets

**A) DEFERRED — port planned on trigger** (3 fields on Execution):
- payload_override (cueapi/cueapi PR #589 / #577)
- triggered_by (Phase 18 Gap 7 family)
- payload (effective field on ExecutionResponse — depends on payload_override)

Trigger: batched Execution-schema sprint OR concrete demand from an
OSS self-hoster. Primary's verbatim annotation string used.

**B) INTENTIONAL — no port planned** (4 fields on Execution):
- outcome_state
- evidence_external_id
- evidence_result_url
- evidence_artifacts

Tied to the hosted-only verification primitive system (Phase 18
Gap 11): POST /v1/executions/{id}/verify, /verification-pending,
verification_mode config on cues. The columns alone without the
routing endpoints carry no value, so they stay hosted-only.

Also notes that other evidence_* columns (result_ref, result_type,
summary, validation_state, produced_at, metadata) ARE in the OSS
model but not surfaced through ExecutionResponse — same intentional
rationale.

**C) DEFERRED contingent on #589** (2 fields on Cue):
- require_payload_override (cueapi/cueapi PR #590)
- required_payload_keys (cueapi/cueapi PR #590)

Trigger: port after #589 (payload_override) lands; OSS self-hoster
fire-with-override usage signal. Server-side enforcement has no
override to enforce against without the prerequisite field.

## Audit date bump

last_full_audit: 2026-05-11 → 2026-05-12 (just this annotation pass;
not a full Execution-schema sprint audit).

## Provenance

Surfaced by cueapi-secondary 2026-05-12 ~00:35Z during follow-on
investigation to cueapi-core #88 (BodyVerify STRING-shape hotfix).
Initial design note went to cue-pm via Cue Messages msg_cr1v9hpu84gb
with primary on notify-list (msg_tuvn53g2h9wz). PM's CTO-concur on
Option C (defer) at msg_u7qwyrkx0wqk. Primary's full 3-way split
(this PR's authoritative source) at msg_fyfs7568tztu, relayed via
cue-pm in msg_4ofzmxcjoyu4 ~00:50Z. Tier-1-small per PM spec.

## Out of scope

- Actual Execution / Cue schema ports (bucket A + C). Backlog row
  to be filed for "cueapi-core: payload_override + triggered_by +
  payload port + #590 contingent on #589", item_status=deferred,
  priority=someday, lead_agent=cueapi-primary.
- Backfilling missing Backlog rows for the existing stale
  "Parity port: PR #589 → cueapi-core" and "Parity port: PR #590 →
  cueapi-core" rows (they predate primary's mixed-split decision and
  should be updated rather than duplicated).
mikemolinet added a commit that referenced this pull request May 12, 2026
Private cueapi #801 added docs/guides/body-verify.mdx (Mintlify, 247
lines) documenting the X-CueAPI-Verify-Echo primitive for hosted users.
cueapi-core ships the SAME substrate (Layer 1 from #86 + Layer 1.5
universal middleware from #87 + STRING-shape spec-lock from #88) but
had no user-facing guide. Self-hosters running cueapi-core need this.

## Scope

cueapi-core-flavored adaptation — plain MD (not MDX), substrate-focused
(narrower than the hosted MDX guide which covers SDK install + hosted-
specific patterns). Sections:

1. The bug class — caller-side shell expansion ($(...), `...`, ${VAR})
2. How it works — X-CueAPI-Verify-Echo header + response shape
3. Substrate architecture — Layer 1 (endpoint-specific STRING shape on
   /v1/messages + /v1/cues/{id}/fire) vs Layer 1.5 (universal middleware
   on all other POST/PATCH/PUT endpoints, OBJECT shape)
4. SDK auto-verify summary table (python / cli / mcp / action), with
   the messages-default-on vs fire-opt-in distinction explicit
5. Defense-in-depth layers — substrate + SDK + force-file + docs
6. When to disable + opt-out semantics
7. Implementation file references (app/utils/verify_echo.py,
   app/middleware/verify_echo.py, app/routers/{messages,cues}.py)
8. Background — Mike directive 2026-05-11; cross-stack ship history

## Out of scope

- Per-language SDK install / API-key bootstrap content — already in
  each SDK's own README. This guide links rather than duplicates.
- The hosted-specific Mintlify mint.json registration — cueapi-core
  uses plain MD; doc discovery via the docs/ dir, not Mintlify.

## Build / lint

- Plain Markdown; no build step required. (Other docs in this dir
  follow the same convention — see quickstart.md, configuration.md.)
mikemolinet added a commit that referenced this pull request May 12, 2026
…90)

Private cueapi #801 added docs/guides/body-verify.mdx (Mintlify, 247
lines) documenting the X-CueAPI-Verify-Echo primitive for hosted users.
cueapi-core ships the SAME substrate (Layer 1 from #86 + Layer 1.5
universal middleware from #87 + STRING-shape spec-lock from #88) but
had no user-facing guide. Self-hosters running cueapi-core need this.

## Scope

cueapi-core-flavored adaptation — plain MD (not MDX), substrate-focused
(narrower than the hosted MDX guide which covers SDK install + hosted-
specific patterns). Sections:

1. The bug class — caller-side shell expansion ($(...), `...`, ${VAR})
2. How it works — X-CueAPI-Verify-Echo header + response shape
3. Substrate architecture — Layer 1 (endpoint-specific STRING shape on
   /v1/messages + /v1/cues/{id}/fire) vs Layer 1.5 (universal middleware
   on all other POST/PATCH/PUT endpoints, OBJECT shape)
4. SDK auto-verify summary table (python / cli / mcp / action), with
   the messages-default-on vs fire-opt-in distinction explicit
5. Defense-in-depth layers — substrate + SDK + force-file + docs
6. When to disable + opt-out semantics
7. Implementation file references (app/utils/verify_echo.py,
   app/middleware/verify_echo.py, app/routers/{messages,cues}.py)
8. Background — Mike directive 2026-05-11; cross-stack ship history

## Out of scope

- Per-language SDK install / API-key bootstrap content — already in
  each SDK's own README. This guide links rather than duplicates.
- The hosted-specific Mintlify mint.json registration — cueapi-core
  uses plain MD; doc discovery via the docs/ dir, not Mintlify.

## Build / lint

- Plain Markdown; no build step required. (Other docs in this dir
  follow the same convention — see quickstart.md, configuration.md.)
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.

1 participant