mail-address-semantics/mas_modes/conformance/flows.json
tegwick ecb1ba47f6 MAS-WP-0013 finished: mode contract flows runnable from the bundle alone
conformance/FLOWS.md defines setup, steps, captures and expectations, all
observable at the contract boundary. flows.json carries setups (peer ids),
fixed test keys, statute, scenario and explicit assign steps;
scenarios.json holds the callback scenarios (the stub loads them).
CONTRACT.md defines the case.assign response. Runner reads only the
bundle and rejects undefined keys; new flow s-006 (held over cap).

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
2026-10-19 12:49:15 +02:00

851 lines
19 KiB
JSON

{
"description": "Scripted flows (CONTRACT.md section 8). The format, steps, expectations and captures are defined in conformance/FLOWS.md. Everything a run needs is in this file, scenarios.json and statute.json.",
"statute": "statute.json",
"peers": {
"callback-1": "6d61732d6d6f6465732d76302e312d746573742d6b65792d63616c6c6261636b31",
"cms-1": "6d61732d6d6f6465732d76302e312d746573742d6b65792d636d732d312d2d2d2d",
"gateway": "6d61732d6d6f6465732d76302e312d746573742d6b65792d676174657761792d2d"
},
"setups": {
"master": {
"roles": {
"ticket": {
"role": "master",
"modes": {
"callback": {
"peer": "callback-1"
}
},
"fields": [
"phone",
"time",
"scenario"
],
"timeout": 3600
}
}
},
"slave": {
"roles": {
"case": {
"role": "slave",
"master_peer": "cms-1",
"autonomous_send": false,
"transfers": "block"
}
}
},
"slave-webhook": {
"roles": {
"case": {
"role": "slave",
"master_peer": "cms-1",
"autonomous_send": false,
"transfers": {
"webhook": "<mode:callback-1>",
"peer": "callback-1"
}
}
}
}
},
"flows": [
{
"id": "m-001",
"setup": "master",
"title": "callback completes",
"scenario": "completed",
"steps": [
{
"mail": {
"to": "ticket!callback",
"text": "Phone: +49 30 1234567\nTime: tomorrow 10:00"
},
"expect": {
"event_accepted": true,
"mode_received": 1
}
},
{
"mode": "run",
"expect": {
"mode_statuses": [
"scheduled",
"running",
"completed"
],
"last_mail_contains": "has taken place"
}
}
]
},
{
"id": "m-002",
"setup": "master",
"title": "negotiation over email",
"scenario": "negotiate",
"steps": [
{
"mail": {
"to": "ticket!callback",
"text": "Please call me."
},
"expect": {
"event_accepted": true
}
},
{
"mode": "run",
"expect": {
"mode_statuses": [
"negotiating"
],
"last_mail_contains": "Phone: ..."
}
},
{
"mail": {
"to": "ticket={case_id}",
"text": "Phone: +49 30 1234567\nTime: tomorrow 10:00"
},
"expect": {
"event_accepted": true,
"mode_received_last": "handoff.update"
}
},
{
"mode": "run",
"expect": {
"mode_statuses": [
"negotiating",
"scheduled",
"running",
"completed"
],
"last_mail_contains": "has taken place"
}
}
]
},
{
"id": "m-003",
"setup": "master",
"title": "no answer, retried, completed",
"scenario": "no-answer-retry",
"steps": [
{
"mail": {
"to": "ticket!callback",
"text": "Phone: +49 30 1234567\nTime: tomorrow 10:00"
}
},
{
"mode": "run",
"expect": {
"mode_statuses": [
"scheduled",
"attempted",
"scheduled",
"running",
"completed"
]
}
}
]
},
{
"id": "m-004",
"setup": "master",
"title": "no answer twice, failed",
"scenario": "no-answer-fail",
"steps": [
{
"mail": {
"to": "ticket!callback",
"text": "Phone: +49 30 1234567\nTime: tomorrow 10:00"
}
},
{
"mode": "run",
"expect": {
"mode_statuses": [
"scheduled",
"attempted",
"scheduled",
"attempted",
"failed"
],
"last_mail_contains": "did not succeed"
}
}
]
},
{
"id": "m-005",
"setup": "master",
"title": "refused out of hours",
"scenario": "out-of-hours",
"steps": [
{
"mail": {
"to": "ticket!callback",
"text": "Phone: +49 30 1234567\nTime: tomorrow 10:00"
}
},
{
"mode": "run",
"expect": {
"mode_statuses": [
"refused"
],
"last_mail_contains": "out-of-hours"
}
}
]
},
{
"id": "m-006",
"setup": "master",
"title": "email owns the timeout",
"scenario": "silent",
"steps": [
{
"mail": {
"to": "ticket!callback",
"text": "Phone: +49 30 1234567\nTime: tomorrow 10:00"
},
"expect": {
"mails_sent": 1
}
},
{
"mode": "run",
"expect": {
"mode_statuses": []
}
},
{
"advance": 3599,
"expect": {
"mode_received": 1,
"mails_sent": 1
}
},
{
"advance": 2,
"expect": {
"mode_received_last": "handoff.cancel",
"mails_sent": 2,
"last_mail_contains": "could not arrange"
}
},
{
"advance": 100000,
"expect": {
"mode_received": 2,
"mails_sent": 2
}
}
]
},
{
"id": "m-007",
"setup": "master",
"title": "mode not enabled by the statute",
"scenario": "completed",
"steps": [
{
"mail": {
"to": "ticket!chat",
"text": "hi"
},
"expect": {
"event_accepted": true,
"mode_received": 0,
"mails_sent": 1
}
}
]
},
{
"id": "m-008",
"setup": "master",
"title": "unauthenticated sender gets no mail",
"scenario": "negotiate",
"steps": [
{
"mail": {
"to": "ticket!callback",
"text": "call me",
"dmarc": "fail"
},
"expect": {
"event_accepted": true
}
},
{
"mode": "run",
"expect": {
"mode_statuses": [
"negotiating"
],
"mails_sent": 0
}
}
]
},
{
"id": "s-001",
"setup": "slave",
"title": "master issues the id; email sends only on instruction",
"scenario": "completed",
"steps": [
{
"mail": {
"to": "case",
"text": "My order is late"
},
"expect": {
"event_accepted": true,
"master_received": {
"case.intake": 1
},
"mails_sent": 0
}
},
{
"master": {
"command": "assign",
"resource_id": "EXT-100"
},
"expect": {
"response_ok": true,
"case_address": "case=EXT-100@modes.example"
}
},
{
"mail": {
"to": "case={case_id}",
"text": "more"
},
"expect": {
"master_received": {
"case.message": 1
},
"mails_sent": 0
}
},
{
"master": {
"command": "send",
"in_reply_to": "{message_ref}",
"body": "We are on it."
},
"expect": {
"response_ok": true,
"mails_sent": 1
}
}
]
},
{
"id": "s-002",
"setup": "slave",
"title": "principle 10 refuses a master send",
"scenario": "completed",
"steps": [
{
"mail": {
"to": "case",
"text": "hi",
"dmarc": "fail"
}
},
{
"master": {
"command": "assign",
"resource_id": "EXT-100"
}
},
{
"master": {
"command": "send",
"in_reply_to": "{message_ref}",
"body": "x"
},
"expect": {
"response_ok": false,
"response_reason": "unauthenticated-sender",
"mails_sent": 0
}
}
]
},
{
"id": "s-003",
"setup": "slave",
"title": "transfer blocked",
"scenario": "completed",
"steps": [
{
"mail": {
"to": "case!callback",
"text": "Phone: +49 30 1234567\nTime: tomorrow 10:00"
},
"expect": {
"master_received": {
"case.intake": 1
}
}
},
{
"master": {
"command": "assign",
"resource_id": "EXT-100"
},
"expect": {
"master_received": {
"handoff.requested": 1,
"handoff.status": 1
},
"relayed": [
"refused"
],
"mode_received": 0
}
}
]
},
{
"id": "s-004",
"setup": "slave-webhook",
"title": "transfer to the primed webhook; statuses relayed",
"scenario": "completed",
"steps": [
{
"mail": {
"to": "case!callback",
"text": "Phone: +49 30 1234567\nTime: tomorrow 10:00"
}
},
{
"master": {
"command": "assign",
"resource_id": "EXT-100"
},
"expect": {
"mode_received": 1
}
},
{
"mode": "run",
"expect": {
"relayed": [
"scheduled",
"running",
"completed"
],
"mails_sent": 0
}
},
{
"advance": 1000000,
"expect": {
"mode_received": 1
}
}
]
},
{
"id": "s-005",
"setup": "slave-webhook",
"title": "the master owns the timeout",
"scenario": "silent",
"steps": [
{
"mail": {
"to": "case!callback",
"text": "Phone: +49 30 1234567\nTime: tomorrow 10:00"
}
},
{
"master": {
"command": "assign",
"resource_id": "EXT-100"
}
},
{
"mode": "run",
"expect": {
"relayed": []
}
},
{
"advance": 1000000,
"expect": {
"mode_received": 1
}
},
{
"master": {
"command": "cancel",
"handoff_id": "{handoff_id}"
},
"expect": {
"response_ok": true,
"mode_received_last": "handoff.cancel"
}
},
{
"mode": "run",
"expect": {
"relayed": [
"cancelled"
]
}
}
]
},
{
"id": "s-006",
"setup": "slave",
"title": "over the cap a master send is held",
"scenario": "completed",
"steps": [
{
"mail": {
"to": "case",
"text": "hi"
}
},
{
"master": {
"command": "assign",
"resource_id": "EXT-100"
}
},
{
"master": {
"command": "send",
"in_reply_to": "{message_ref}",
"body": "one"
},
"expect": {
"response_ok": true,
"mails_sent": 1
}
},
{
"master": {
"command": "send",
"in_reply_to": "{message_ref}",
"body": "two"
},
"expect": {
"response_ok": false,
"response_reason": "send-cap-reached",
"response_held": true,
"mails_sent": 1
}
}
],
"max_sent": 1
},
{
"id": "a-001",
"setup": "slave",
"title": "unsigned master command refused",
"scenario": "completed",
"steps": [
{
"mail": {
"to": "case",
"text": "hi"
}
},
{
"master": {
"command": "assign",
"resource_id": "EXT-100"
}
},
{
"inject": {
"endpoint": "master",
"sign": "none",
"message": {
"type": "mail.send",
"case": "current",
"in_reply_to": "{message_ref}",
"body": "hello"
}
},
"expect": {
"http_status": 401,
"error": "unauthenticated-peer",
"mails_sent": 0
}
}
]
},
{
"id": "a-002",
"setup": "slave",
"title": "a mode cannot assign case ids",
"scenario": "completed",
"steps": [
{
"mail": {
"to": "case",
"text": "hi"
}
},
{
"inject": {
"endpoint": "master",
"as": "callback-1",
"message": {
"type": "case.assign",
"intake_ref": "{intake_ref}",
"resource_id": "EVIL-1"
}
},
"expect": {
"http_status": 403,
"error": "wrong-peer"
}
},
{
"master": {
"command": "assign",
"resource_id": "EXT-100"
},
"expect": {
"case_address": "case=EXT-100@modes.example"
}
}
]
},
{
"id": "a-003",
"setup": "slave",
"title": "webhook to a peer email has no key for",
"scenario": "completed",
"steps": [
{
"mail": {
"to": "case",
"text": "hi"
}
},
{
"master": {
"command": "assign",
"resource_id": "EXT-100"
}
},
{
"inject": {
"endpoint": "master",
"as": "cms-1",
"message": {
"type": "case.policy",
"case": "current",
"transfers": {
"webhook": "http://attacker.example/h",
"peer": "mallory"
}
}
},
"expect": {
"http_status": 400,
"error": "unknown-peer"
}
}
]
},
{
"id": "a-004",
"setup": "slave",
"title": "replayed master command",
"scenario": "completed",
"steps": [
{
"mail": {
"to": "case",
"text": "hi"
}
},
{
"master": {
"command": "assign",
"resource_id": "EXT-100"
}
},
{
"inject": {
"endpoint": "master",
"as": "cms-1",
"sign": "stale",
"message": {
"type": "mail.send",
"case": "current",
"in_reply_to": "{message_ref}",
"body": "hello"
}
},
"expect": {
"http_status": 401,
"error": "replayed",
"mails_sent": 0
}
}
]
},
{
"id": "a-005",
"setup": "slave",
"title": "master command signed with the wrong key",
"scenario": "completed",
"steps": [
{
"mail": {
"to": "case",
"text": "hi"
}
},
{
"master": {
"command": "assign",
"resource_id": "EXT-100"
}
},
{
"inject": {
"endpoint": "master",
"as": "cms-1",
"sign": "wrong-key",
"message": {
"type": "mail.send",
"case": "current",
"in_reply_to": "{message_ref}",
"body": "hello"
}
},
"expect": {
"http_status": 401,
"error": "unauthenticated-peer",
"mails_sent": 0
}
},
{
"inject": {
"endpoint": "master",
"as": "cms-1",
"message": {
"type": "mail.send",
"case": "current",
"in_reply_to": "{message_ref}",
"body": "hello"
}
},
"expect": {
"http_status": 200,
"mails_sent": 1
}
}
]
},
{
"id": "a-006",
"setup": "master",
"title": "statuses only from the handoff's peer, at its URL",
"scenario": "silent",
"steps": [
{
"mail": {
"to": "ticket!callback",
"text": "Phone: +49 30 1234567\nTime: tomorrow 10:00"
},
"expect": {
"mails_sent": 1
}
},
{
"inject": {
"endpoint": "status",
"as": "cms-1",
"message": {
"type": "handoff.status",
"case": "current",
"handoff_id": "{handoff_id}",
"seq": 1,
"status": "completed"
}
},
"expect": {
"http_status": 403,
"error": "wrong-peer"
}
},
{
"inject": {
"endpoint": "status",
"as": "callback-1",
"token": "bogus",
"message": {
"type": "handoff.status",
"case": "current",
"handoff_id": "{handoff_id}",
"seq": 1,
"status": "completed"
}
},
"expect": {
"http_status": 404,
"error": "unknown-handoff",
"mails_sent": 1
}
},
{
"inject": {
"endpoint": "status",
"as": "callback-1",
"message": {
"type": "handoff.status",
"case": "current",
"handoff_id": "{handoff_id}",
"seq": 1,
"status": "scheduled",
"at": "x"
}
},
"expect": {
"http_status": 200
}
}
]
},
{
"id": "a-007",
"setup": "master",
"title": "only the gateway posts events",
"scenario": "completed",
"steps": [
{
"inject": {
"endpoint": "events",
"as": "callback-1",
"message": {
"type": "x"
}
},
"expect": {
"http_status": 403,
"error": "wrong-peer"
}
}
]
}
]
}