MAS-WP-0011 finished: peer authentication in mode contract v0.1

CONTRACT.md section 7 (founder-reviewed): pairwise HMAC-SHA256 over
TIMESTAMP.BODY in MAS-Modes-* headers, 300 s window; master commands only
from the configured master; statuses only at the handoff's tokenized URL
from its peer; primed webhooks must name a known peer. mas_modes.signing,
signed contract.post, authenticating json_server, EmailMode/stubs/gateway
signing. conformance/auth.json vectors + 7 authorization flows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 5787@bnt-lap001
Assistant-Session: 5db26b82-138b-40cc-9856-4d5eb0f752fd
This commit is contained in:
tegwick 2026-10-19 11:25:24 +02:00
parent 2bc41a3318
commit bdf200a600
25 changed files with 1603 additions and 151 deletions

View file

@ -5,8 +5,7 @@ from mas_modes.contract import message, post
from mas_modes.harness import Harness, ROOT
STATUTE = ROOT / "mas-modes-v0.1-spec/conformance/statute.json"
ROLES = {"ticket": {"role": "master", "modes": {"callback": "{callback}"},
"fields": ("phone", "time", "scenario"), "timeout": 3600}}
ROLES = {"ticket": {"role": "master", "fields": ("phone", "time", "scenario"), "timeout": 3600}}
DETAILS = "Phone: +49 30 1234567\nTime: tomorrow 10:00"
@ -94,7 +93,8 @@ def test_mode_not_enabled_by_statute(h):
def test_mode_endpoint_down():
roles = {"ticket": {**ROLES["ticket"], "modes": {"callback": "http://127.0.0.1:9/handoffs"}}}
roles = {"ticket": {**ROLES["ticket"],
"modes": {"callback": {"url": "http://127.0.0.1:9/handoffs", "peer": "callback-1"}}}}
h = Harness(STATUTE, roles)
try:
d = h.mail("ticket!callback", DETAILS)
@ -120,27 +120,33 @@ def test_unauthenticated_sender_gets_no_mail(h):
assert h.outbox() == [] # no creation reply, no question: principle 10
def as_mode(h):
"""Post as the callback stub does: signed, at the handoff's status URL."""
url = h.callback.received[0]["status_url"]
return lambda msg: post(url, msg, ("callback-1", h.keys["callback-1"]))
def test_contract_guards(h):
tid, hid = start(h, DETAILS + "\nScenario: completed")
case = h.callback.run()[0]["case"]
url = h.email.base_url + "/mode-status"
send = as_mode(h)
stale = message("handoff.status", case, handoff_id=hid, seq=1, status="running")
assert post(url, stale) == (200, {"ok": True, "ignored": "stale"})
code, body = post(url, message("handoff.status", case, handoff_id=hid, seq=99, status="timed-out"))
assert send(stale) == (200, {"ok": True, "ignored": "stale"})
code, body = send(message("handoff.status", case, handoff_id=hid, seq=99, status="timed-out"))
assert code == 409 and body["error"] == "invalid-transition"
code, body = post(url, message("handoff.status", case, handoff_id=hid, seq=99, status="negotiating",
needs=["phone"]))
code, body = send(message("handoff.status", case, handoff_id=hid, seq=99, status="negotiating",
needs=["phone"]))
assert code == 409 # completed is terminal
code, body = post(url, message("handoff.status", case, handoff_id="nope", seq=1, status="running"))
code, body = send(message("handoff.status", case, handoff_id="nope", seq=1, status="running"))
assert code == 404
code, body = post(url, {"type": "handoff.status"})
code, body = send({"type": "handoff.status"})
assert code == 400 and body["error"] == "schema"
def test_repeated_message_id_is_processed_once(h):
tid, hid = start(h, DETAILS + "\nScenario: silent")
case = h.callback.received[0]["case"]
url = h.email.base_url + "/mode-status"
send = as_mode(h)
msg = message("handoff.status", case, handoff_id=hid, seq=1, status="scheduled", at="x")
assert post(url, msg) == post(url, msg) == (200, {"ok": True})
assert send(msg) == send(msg) == (200, {"ok": True})
assert h.thread(tid).count("callback: scheduled at=x") == 1