Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 25 additions & 13 deletions cueapi/resources/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,28 +132,40 @@ def send(

response = self._client._post("/v1/messages", json=payload, headers=headers)

# Verify echo if requested. The substrate-side echo lands in
# response[_VERIFY_ECHO_FIELD] when Layer 1 is deployed; absent
# otherwise (no-op in that case).
# Verify echo if requested. Empirically-locked wire shape (probed
# 2026-05-11 ~23:17Z): substrate echoes back the PARSED request
# body as a dict under ``body_received``. To diff the message
# body specifically, extract ``body_received.body`` (str) and
# compare against the str the caller sent.
#
# Backward-compat: pre-Layer-1 substrate omits ``body_received``
# entirely → SDK no-ops. Also defensive: if a future substrate
# rev returns body_received as a flat string (per the original
# spec text), the .get("body") chain returns None gracefully via
# the isinstance check, falling through to no-op rather than
# raising spuriously.
if auto_verify and isinstance(response, dict):
received = response.get(_VERIFY_ECHO_FIELD)
if received is not None and received != body:
received_dict = response.get(_VERIFY_ECHO_FIELD)
received_body: Optional[str] = None
if isinstance(received_dict, dict):
received_body = received_dict.get("body")
elif isinstance(received_dict, str):
# Defensive: future substrate rev may flatten the echo.
received_body = received_dict
if received_body is not None and received_body != body:
msg_id = response.get("id", "<unknown>")
divergence = first_divergence_byte(body, received)
if divergence == -1 and len(body) != len(received):
# One body is a proper prefix of the other; length
# mismatch is the signal. Report at boundary of the
# shorter body.
divergence = min(len(body), len(received))
divergence = first_divergence_byte(body, received_body)
if divergence == -1 and len(body) != len(received_body):
divergence = min(len(body), len(received_body))
raise BodyVerifyMismatchError(
f"Body received by substrate ({len(received)} bytes) differs from "
f"Body received by substrate ({len(received_body)} bytes) differs from "
f"body sent ({len(body)} bytes); first divergence at byte "
f"{divergence}. Likely cause: caller-side shell expansion of "
f"$(...) / backticks / ${{VAR}} in the body arg before Python "
f"received it. Mitigations: pass body via file (Path.read_text) "
f"or use --message-file in cueapi-cli.",
sent_body=body,
received_body=received,
received_body=received_body,
first_divergence_byte=divergence,
message_id=msg_id,
)
Expand Down
38 changes: 32 additions & 6 deletions tests/test_messages_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,12 +236,18 @@ def test_opt_out_omits_header(self):
assert "X-CueAPI-Verify-Echo" not in headers

def test_byte_identical_response_returns_normally(self):
"""When server echoes back the same body, send() returns response."""
"""body_received.body matches sent body → success.

Empirically-locked wire shape (probed 2026-05-11 ~23:17Z):
substrate echoes back PARSED request body as dict under
``body_received``, NOT a flat string. SDK extracts
``body_received.body`` to compare against sent body.
"""
mock_client = MagicMock()
mock_client._post.return_value = {
"id": "msg_x",
"delivery_state": "queued",
"body_received": "hi",
"body_received": {"to": "y", "body": "hi", "subject": None, "priority": 3},
}
r = MessagesResource(mock_client)

Expand All @@ -250,14 +256,19 @@ def test_byte_identical_response_returns_normally(self):
assert result["id"] == "msg_x"

def test_raises_on_body_mismatch(self):
"""When server echo differs from sent body, raises BodyVerifyMismatchError."""
"""body_received.body differs from sent body raises BodyVerifyMismatchError."""
from cueapi.exceptions import BodyVerifyMismatchError

mock_client = MagicMock()
mock_client._post.return_value = {
"id": "msg_mutated",
"delivery_state": "queued",
"body_received": "body with INJECT (caller's shell command-substituted)",
"body_received": {
"to": "y",
"body": "body with INJECT (caller's shell command-substituted)",
"subject": None,
"priority": 3,
},
}
r = MessagesResource(mock_client)

Expand Down Expand Up @@ -286,16 +297,31 @@ def test_no_op_when_substrate_omits_echo_field(self):
def test_opt_out_skips_verify_even_if_substrate_echoes(self):
"""auto_verify=False: even if substrate sends body_received, don't check."""
mock_client = MagicMock()
# Mismatched echo but opt-out → no exception
mock_client._post.return_value = {
"id": "msg_x", "body_received": "DIFFERENT BODY",
"id": "msg_x",
"body_received": {"to": "y", "body": "DIFFERENT BODY"},
}
r = MessagesResource(mock_client)

result = r.send(from_agent="x", to="y", body="hi", auto_verify=False)

assert result["id"] == "msg_x"

def test_defensive_accepts_flat_string_body_received(self):
"""Defensive: if a future substrate rev flattens body_received
back to a string (per the original spec wording), SDK still
verifies correctly. Belt + suspenders for spec drift."""
mock_client = MagicMock()
mock_client._post.return_value = {
"id": "msg_x",
"body_received": "hi", # flat-string variant
}
r = MessagesResource(mock_client)

result = r.send(from_agent="x", to="y", body="hi")

assert result["id"] == "msg_x"


class TestFirstDivergenceByte:
"""Pure helper for diagnostic byte-position-of-first-difference."""
Expand Down
Loading