From d3774b799b39a48ca7262a422e14e8d79953bafd Mon Sep 17 00:00:00 2001 From: Steven Welch Date: Fri, 4 Sep 2026 22:07:43 -0600 Subject: [PATCH 1/2] test(sms-bridge): cover prompt route and sender gate --- opencode-sms-bridge/test_server.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/opencode-sms-bridge/test_server.py b/opencode-sms-bridge/test_server.py index 50785c6..c2460d6 100644 --- a/opencode-sms-bridge/test_server.py +++ b/opencode-sms-bridge/test_server.py @@ -4,6 +4,7 @@ import tempfile import unittest from pathlib import Path +from unittest.mock import patch from cryptography.fernet import Fernet from fastapi.testclient import TestClient @@ -12,6 +13,7 @@ from server import ( BridgeError, + OpenCodeClient, Routing, SQLiteStore, Settings, @@ -115,19 +117,28 @@ def test_ingress_accepts_signed_approved_message_once(self): self.assertIsNotNone(self.store.claim()) self.assertIsNone(self.store.claim()) - def test_ingress_ignores_unapproved_sender_after_signature_validation(self): + def test_ingress_ignores_unapproved_sender_before_queueing(self): form = {"AccountSid": "AC1234567890", "MessageSid": "SM124", "From": "+15558888888", "To": "+15550000001", "Body": "hello", "NumMedia": "0"} signature = RequestValidator("auth-token").compute_signature(self.settings.canonical_webhook_url, form) client = TestClient(create_ingress_app(self.settings, self.store)) - with self.assertLogs("opencode-sms-bridge", level="INFO") as captured: - response = client.post("/twilio/inbound", data=form, headers={"X-Twilio-Signature": signature}) + with patch.object(self.store, "enqueue", wraps=self.store.enqueue) as enqueue: + with self.assertLogs("opencode-sms-bridge", level="INFO") as captured: + response = client.post("/twilio/inbound", data=form, headers={"X-Twilio-Signature": signature}) telemetry = "\n".join(captured.output) self.assertEqual(response.status_code, 200) self.assertIn("event=inbound_ignored reason=account-destination-or-sender", telemetry) for unsafe_value in (form["From"], form["To"], form["MessageSid"], form["Body"]): self.assertNotIn(unsafe_value, telemetry) + enqueue.assert_not_called() self.assertIsNone(self.store.claim()) + def test_prompt_uses_compatible_session_message_route(self): + parts = [{"type": "text", "text": "hello"}] + client = OpenCodeClient(self.settings) + with patch.object(client, "_request", return_value={"parts": [{"type": "text", "text": "reply"}]}) as request: + self.assertEqual(client.prompt("ses_123", parts), "reply") + request.assert_called_once_with("/session/ses_123/message", {"parts": parts}) + def test_image_sanitization_removes_exif(self): image = Image.new("RGB", (8, 8), color="red") original = tempfile.SpooledTemporaryFile() From bd108e8b92ba0c5f2471d157df6161a2c1252c22 Mon Sep 17 00:00:00 2001 From: Steven Welch Date: Fri, 4 Sep 2026 22:10:03 -0600 Subject: [PATCH 2/2] fix(sms-bridge): use compatible OpenCode prompt route --- opencode-sms-bridge/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opencode-sms-bridge/server.py b/opencode-sms-bridge/server.py index 4166ca1..2279ba8 100644 --- a/opencode-sms-bridge/server.py +++ b/opencode-sms-bridge/server.py @@ -502,7 +502,7 @@ def create_session(self, agent: str) -> str: return session_id def prompt(self, session_id: str, parts: list[dict[str, str]]) -> str: - response = self._request(f"/api/session/{session_id}/message", {"parts": parts}) + response = self._request(f"/session/{session_id}/message", {"parts": parts}) data = response.get("data", response) candidates = data.get("parts", []) if isinstance(data, dict) else [] text = "".join(part.get("text", "") for part in candidates if part.get("type") == "text")