"""Deduplicated informed-decision notification contract.""" from __future__ import annotations import json NOTICE = { "memo_id": "infd-20261003-p01", "question": "Accept the forwarded draft?", "memo_class": "work-record-accept", "submitter": "example-submitter", } KEY = "state-hub.delivery.0001" async def _messages(client): listed = await client.get("/messages/", params={"to_agent": "bernd"}) assert listed.status_code == 200, listed.text return listed.json() async def test_notification_is_deduplicated_and_limited_to_four_fields(client): first = await client.post( "/informed-decision/notifications", json=NOTICE, headers={"Idempotency-Key": KEY}, ) assert first.status_code == 201, first.text body = first.json() assert body["status"] == "accepted" assert body["authoritative_review"] == "signed-in-overview" assert body["delivery_id"] == KEY raw = json.dumps({ "submitter": NOTICE["submitter"], "memo_class": NOTICE["memo_class"], "question": NOTICE["question"], "memo_id": NOTICE["memo_id"], }) second = await client.post( "/informed-decision/notifications", content=raw, headers={"Idempotency-Key": KEY, "Content-Type": "application/json"}, ) assert second.status_code == 200, second.text assert second.headers["x-statehub-idempotency-replay"] == "true" assert second.json()["message_id"] == body["message_id"] messages = await _messages(client) assert len(messages) == 1 text = messages[0]["body"] assert text.startswith("The signed-in overview is the authoritative review entry point.\n") assert set(json.loads(text.split("\n", 1)[1])) == set(NOTICE) assert "://" not in text assert "packet" not in text assert "highlight" not in text assert messages[0]["from_agent"] == "informed-decision" assert messages[0]["to_agent"] == "bernd" async def test_conflict_leaves_the_original_receipt_readable(client): created = await client.post( "/informed-decision/notifications", json=NOTICE, headers={"Idempotency-Key": KEY}, ) assert created.status_code == 201, created.text changed = dict(NOTICE, question="Decline the forwarded draft?") conflict = await client.post( "/informed-decision/notifications", json=changed, headers={"Idempotency-Key": KEY}, ) assert conflict.status_code == 409 assert conflict.json() == {"error": "notification_conflict", "delivery_id": KEY} assert "Decline" not in conflict.text current = await client.get(f"/informed-decision/notifications/{KEY}") assert current.status_code == 200 assert current.json()["question"] == NOTICE["question"] assert len(await _messages(client)) == 1 async def test_notification_refuses_extra_secret_and_link_without_echo(client): extra = dict(NOTICE, packet="SECRET-PACKET-VALUE") refused = await client.post( "/informed-decision/notifications", json=extra, headers={"Idempotency-Key": KEY}, ) assert refused.status_code == 400 assert refused.json() == {"error": "unknown_field"} assert "SECRET-PACKET-VALUE" not in refused.text secret = dict(NOTICE, question="Is Bearer " + ("A" * 16) + " acceptable?") marked = await client.post( "/informed-decision/notifications", json=secret, headers={"Idempotency-Key": "state-hub.delivery.0002"}, ) assert marked.status_code == 400 assert marked.json() == {"error": "secret_marker"} assert "AAAA" not in marked.text linked = dict(NOTICE, question="Open https://overview.example/review?") link = await client.post( "/informed-decision/notifications", json=linked, headers={"Idempotency-Key": "state-hub.delivery.0003"}, ) assert link.status_code == 400 assert link.json() == {"error": "notification_has_link"} assert "overview.example" not in link.text assert await _messages(client) == [] async def test_delivery_id_and_size_are_required(client): missing = await client.post("/informed-decision/notifications", json=NOTICE) assert missing.status_code == 400 assert missing.json()["error"] == "delivery_id_required" short = await client.post( "/informed-decision/notifications", json=NOTICE, headers={"Idempotency-Key": "short"}, ) assert short.status_code == 400 assert short.json()["error"] == "delivery_id_invalid" huge = await client.post( "/informed-decision/notifications", content=b"{" + b"x" * 9000, headers={"Idempotency-Key": KEY, "Content-Type": "application/json"}, ) assert huge.status_code == 413 assert huge.json()["error"] == "notification_too_large" assert b"xxx" not in huge.content missing_receipt = await client.get("/informed-decision/notifications/" + KEY) assert missing_receipt.status_code == 404 async def test_distinct_delivery_ids_are_distinct_notices(client): first = await client.post( "/informed-decision/notifications", json=NOTICE, headers={"Idempotency-Key": "state-hub.delivery.0001"}, ) second_body = dict(NOTICE, memo_id="infd-20261003-p02", question="Decline the other draft?") second = await client.post( "/informed-decision/notifications", json=second_body, headers={"Idempotency-Key": "state-hub.delivery.0002"}, ) assert first.status_code == 201 and second.status_code == 201 assert first.json()["message_id"] != second.json()["message_id"] assert len(await _messages(client)) == 2