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:
parent
2bc41a3318
commit
bdf200a600
25 changed files with 1603 additions and 151 deletions
190
mas_modes/conformance/auth.json
Normal file
190
mas_modes/conformance/auth.json
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
{
|
||||
"description": "Peer authentication (CONTRACT.md section 7). 'vectors': the signature for the given key (hex), timestamp and body (UTF-8, exact octets) MUST equal 'signature'. 'verify': a receiver holding 'keys' (peer -> hex key) whose clock reads 'now' MUST accept the request as 'peer' or refuse it with 'error'.",
|
||||
"vectors": [
|
||||
{
|
||||
"id": "sig-001",
|
||||
"key_hex": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
|
||||
"timestamp": 1792400000,
|
||||
"body": "{\"mas_modes_version\":\"0.1\",\"type\":\"handoff.cancel\",\"id\":\"a1\",\"case\":{\"address\":\"ticket=gs-1@modes.example\",\"key\":\"ticket=gs-1\"},\"handoff_id\":\"h1\",\"reason\":\"timed-out\"}",
|
||||
"signature": "v1=67fcf8eea6ab12dd3b863fd262fe115af8842691f562f4a6435516e3402b559f"
|
||||
},
|
||||
{
|
||||
"id": "sig-002",
|
||||
"key_hex": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
|
||||
"timestamp": 1792400000,
|
||||
"body": "",
|
||||
"signature": "v1=212ad604a508f09271a48ebcf6310e0379d03194bd404e4f8509900a4ae75531"
|
||||
},
|
||||
{
|
||||
"id": "sig-003",
|
||||
"key_hex": "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
|
||||
"timestamp": 1792400001,
|
||||
"body": "{\"mas_modes_version\":\"0.1\",\"type\":\"handoff.cancel\",\"id\":\"a1\",\"case\":{\"address\":\"ticket=gs-1@modes.example\",\"key\":\"ticket=gs-1\"},\"handoff_id\":\"h1\",\"reason\":\"timed-out\"}",
|
||||
"signature": "v1=29bf8df86413caaf51b5e0ff16f3d8e3c6aa9b026d4826a7d51e644fa1b57986"
|
||||
}
|
||||
],
|
||||
"verify": [
|
||||
{
|
||||
"id": "auth-001",
|
||||
"why": "valid",
|
||||
"keys": {
|
||||
"callback-1": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
|
||||
},
|
||||
"now": 1792400010,
|
||||
"headers": {
|
||||
"MAS-Modes-Peer": "callback-1",
|
||||
"MAS-Modes-Timestamp": "1792400000",
|
||||
"MAS-Modes-Signature": "v1=67fcf8eea6ab12dd3b863fd262fe115af8842691f562f4a6435516e3402b559f"
|
||||
},
|
||||
"body": "{\"mas_modes_version\":\"0.1\",\"type\":\"handoff.cancel\",\"id\":\"a1\",\"case\":{\"address\":\"ticket=gs-1@modes.example\",\"key\":\"ticket=gs-1\"},\"handoff_id\":\"h1\",\"reason\":\"timed-out\"}",
|
||||
"peer": "callback-1"
|
||||
},
|
||||
{
|
||||
"id": "auth-002",
|
||||
"why": "header names are case-insensitive",
|
||||
"keys": {
|
||||
"callback-1": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
|
||||
},
|
||||
"now": 1792400000,
|
||||
"headers": {
|
||||
"mas-modes-peer": "callback-1",
|
||||
"mas-modes-timestamp": "1792400000",
|
||||
"mas-modes-signature": "v1=67fcf8eea6ab12dd3b863fd262fe115af8842691f562f4a6435516e3402b559f"
|
||||
},
|
||||
"body": "{\"mas_modes_version\":\"0.1\",\"type\":\"handoff.cancel\",\"id\":\"a1\",\"case\":{\"address\":\"ticket=gs-1@modes.example\",\"key\":\"ticket=gs-1\"},\"handoff_id\":\"h1\",\"reason\":\"timed-out\"}",
|
||||
"peer": "callback-1"
|
||||
},
|
||||
{
|
||||
"id": "auth-003",
|
||||
"why": "unsigned",
|
||||
"keys": {
|
||||
"callback-1": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
|
||||
},
|
||||
"now": 1792400000,
|
||||
"headers": {},
|
||||
"body": "{\"mas_modes_version\":\"0.1\",\"type\":\"handoff.cancel\",\"id\":\"a1\",\"case\":{\"address\":\"ticket=gs-1@modes.example\",\"key\":\"ticket=gs-1\"},\"handoff_id\":\"h1\",\"reason\":\"timed-out\"}",
|
||||
"error": "unauthenticated-peer"
|
||||
},
|
||||
{
|
||||
"id": "auth-004",
|
||||
"why": "unknown peer",
|
||||
"keys": {
|
||||
"callback-1": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
|
||||
},
|
||||
"now": 1792400000,
|
||||
"headers": {
|
||||
"MAS-Modes-Peer": "mallory",
|
||||
"MAS-Modes-Timestamp": "1792400000",
|
||||
"MAS-Modes-Signature": "v1=67fcf8eea6ab12dd3b863fd262fe115af8842691f562f4a6435516e3402b559f"
|
||||
},
|
||||
"body": "{\"mas_modes_version\":\"0.1\",\"type\":\"handoff.cancel\",\"id\":\"a1\",\"case\":{\"address\":\"ticket=gs-1@modes.example\",\"key\":\"ticket=gs-1\"},\"handoff_id\":\"h1\",\"reason\":\"timed-out\"}",
|
||||
"error": "unauthenticated-peer"
|
||||
},
|
||||
{
|
||||
"id": "auth-005",
|
||||
"why": "signed with another peer's key",
|
||||
"keys": {
|
||||
"callback-1": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
|
||||
"cms-1": "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
|
||||
},
|
||||
"now": 1792400000,
|
||||
"headers": {
|
||||
"MAS-Modes-Peer": "cms-1",
|
||||
"MAS-Modes-Timestamp": "1792400000",
|
||||
"MAS-Modes-Signature": "v1=67fcf8eea6ab12dd3b863fd262fe115af8842691f562f4a6435516e3402b559f"
|
||||
},
|
||||
"body": "{\"mas_modes_version\":\"0.1\",\"type\":\"handoff.cancel\",\"id\":\"a1\",\"case\":{\"address\":\"ticket=gs-1@modes.example\",\"key\":\"ticket=gs-1\"},\"handoff_id\":\"h1\",\"reason\":\"timed-out\"}",
|
||||
"error": "unauthenticated-peer"
|
||||
},
|
||||
{
|
||||
"id": "auth-006",
|
||||
"why": "body changed after signing",
|
||||
"keys": {
|
||||
"callback-1": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
|
||||
},
|
||||
"now": 1792400000,
|
||||
"headers": {
|
||||
"MAS-Modes-Peer": "callback-1",
|
||||
"MAS-Modes-Timestamp": "1792400000",
|
||||
"MAS-Modes-Signature": "v1=67fcf8eea6ab12dd3b863fd262fe115af8842691f562f4a6435516e3402b559f"
|
||||
},
|
||||
"body": "{\"mas_modes_version\":\"0.1\",\"type\":\"handoff.cancel\",\"id\":\"a1\",\"case\":{\"address\":\"ticket=gs-1@modes.example\",\"key\":\"ticket=gs-1\"},\"handoff_id\":\"h1\",\"reason\":\"completed\"}",
|
||||
"error": "unauthenticated-peer"
|
||||
},
|
||||
{
|
||||
"id": "auth-007",
|
||||
"why": "timestamp changed after signing",
|
||||
"keys": {
|
||||
"callback-1": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
|
||||
},
|
||||
"now": 1792400000,
|
||||
"headers": {
|
||||
"MAS-Modes-Peer": "callback-1",
|
||||
"MAS-Modes-Timestamp": "1792400001",
|
||||
"MAS-Modes-Signature": "v1=67fcf8eea6ab12dd3b863fd262fe115af8842691f562f4a6435516e3402b559f"
|
||||
},
|
||||
"body": "{\"mas_modes_version\":\"0.1\",\"type\":\"handoff.cancel\",\"id\":\"a1\",\"case\":{\"address\":\"ticket=gs-1@modes.example\",\"key\":\"ticket=gs-1\"},\"handoff_id\":\"h1\",\"reason\":\"timed-out\"}",
|
||||
"error": "unauthenticated-peer"
|
||||
},
|
||||
{
|
||||
"id": "auth-008",
|
||||
"why": "older than the 300 s window",
|
||||
"keys": {
|
||||
"callback-1": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
|
||||
},
|
||||
"now": 1792400301,
|
||||
"headers": {
|
||||
"MAS-Modes-Peer": "callback-1",
|
||||
"MAS-Modes-Timestamp": "1792400000",
|
||||
"MAS-Modes-Signature": "v1=67fcf8eea6ab12dd3b863fd262fe115af8842691f562f4a6435516e3402b559f"
|
||||
},
|
||||
"body": "{\"mas_modes_version\":\"0.1\",\"type\":\"handoff.cancel\",\"id\":\"a1\",\"case\":{\"address\":\"ticket=gs-1@modes.example\",\"key\":\"ticket=gs-1\"},\"handoff_id\":\"h1\",\"reason\":\"timed-out\"}",
|
||||
"error": "replayed"
|
||||
},
|
||||
{
|
||||
"id": "auth-009",
|
||||
"why": "from the future, beyond the window",
|
||||
"keys": {
|
||||
"callback-1": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
|
||||
},
|
||||
"now": 1792399699,
|
||||
"headers": {
|
||||
"MAS-Modes-Peer": "callback-1",
|
||||
"MAS-Modes-Timestamp": "1792400000",
|
||||
"MAS-Modes-Signature": "v1=67fcf8eea6ab12dd3b863fd262fe115af8842691f562f4a6435516e3402b559f"
|
||||
},
|
||||
"body": "{\"mas_modes_version\":\"0.1\",\"type\":\"handoff.cancel\",\"id\":\"a1\",\"case\":{\"address\":\"ticket=gs-1@modes.example\",\"key\":\"ticket=gs-1\"},\"handoff_id\":\"h1\",\"reason\":\"timed-out\"}",
|
||||
"error": "replayed"
|
||||
},
|
||||
{
|
||||
"id": "auth-010",
|
||||
"why": "at the edge of the window",
|
||||
"keys": {
|
||||
"callback-1": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
|
||||
},
|
||||
"now": 1792400300,
|
||||
"headers": {
|
||||
"MAS-Modes-Peer": "callback-1",
|
||||
"MAS-Modes-Timestamp": "1792400000",
|
||||
"MAS-Modes-Signature": "v1=67fcf8eea6ab12dd3b863fd262fe115af8842691f562f4a6435516e3402b559f"
|
||||
},
|
||||
"body": "{\"mas_modes_version\":\"0.1\",\"type\":\"handoff.cancel\",\"id\":\"a1\",\"case\":{\"address\":\"ticket=gs-1@modes.example\",\"key\":\"ticket=gs-1\"},\"handoff_id\":\"h1\",\"reason\":\"timed-out\"}",
|
||||
"peer": "callback-1"
|
||||
},
|
||||
{
|
||||
"id": "auth-011",
|
||||
"why": "non-numeric timestamp",
|
||||
"keys": {
|
||||
"callback-1": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
|
||||
},
|
||||
"now": 1792400000,
|
||||
"headers": {
|
||||
"MAS-Modes-Peer": "callback-1",
|
||||
"MAS-Modes-Timestamp": "soon",
|
||||
"MAS-Modes-Signature": "v1=67fcf8eea6ab12dd3b863fd262fe115af8842691f562f4a6435516e3402b559f"
|
||||
},
|
||||
"body": "{\"mas_modes_version\":\"0.1\",\"type\":\"handoff.cancel\",\"id\":\"a1\",\"case\":{\"address\":\"ticket=gs-1@modes.example\",\"key\":\"ticket=gs-1\"},\"handoff_id\":\"h1\",\"reason\":\"timed-out\"}",
|
||||
"error": "unauthenticated-peer"
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue