@agent-custody/receipts 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -171,5 +171,25 @@ The remote log also serves `GET /head`, its current tree head signed with the lo
171
171
 
172
172
  On a gateway receipt the execution is `observed`: the gateway saw what the upstream returned. An upstream that holds a key can do better and sign its result for the receipt being issued; the gateway embeds the signature, and a verifier given the upstream's public key checks it and reports the execution as `attested` by that key. The check binds the signature to the receipt id, the tool, and the digest of the result content, so a signature cannot be moved between receipts.
173
173
 
174
- For upstream authors, `signResult(result, key, receiptId, tool)` from `@agent-custody/receipts` does the signing; the receipt id arrives in the call's `_meta["agent-custody/receipt"]`. The memory server in `@agent-custody/state` signs when started with `--key`, and the demo's fake upstream does too. Provider-native signatures, such as Stripe's webhook signatures, are adapters on top of the same field and are not implemented yet.
174
+ For upstream authors, `signResult(result, key, receiptId, tool)` from `@agent-custody/receipts` does the signing; the receipt id arrives in the call's `_meta["agent-custody/receipt"]`. The memory server in `@agent-custody/state` signs when started with `--key`, and the demo's fake upstream does too.
175
+
176
+ ### Provider-native deliveries
177
+
178
+ Real providers do not sign per receipt. Stripe signs webhooks and GitHub signs deliveries with an HMAC over the raw body under a shared secret, unbound to any receipt. An MCP server wrapping such a provider can attach the delivery that corresponds to the call, with `attachProviderAttestation(result, { provider: "stripe-webhook", rawBody, signature, bind: "data.object.id" })`, and the gateway embeds it as `execution.upstream`. A verifier given the secret recomputes the HMAC, checks Stripe's timestamp against the receipt's within five minutes, and checks that the value at `bind` in the delivery appears in the receipt's result, which is what ties a delivery to this call.
179
+
180
+ ```bash
181
+ STRIPE_WEBHOOK_SECRET=whsec_... node src/cli.ts verify receipts/<id>.json --issuer-key keys/gateway.pub --principal-key keys/principal.pub --stripe-secret-env STRIPE_WEBHOOK_SECRET
182
+ ```
183
+
184
+ The report then says `attested (shared secret)`, deliberately distinct from `attested`: anyone holding the secret could forge a delivery, so this is the provider's word as far as the secret is trusted, not a signature only the provider could make. Without the secret the delivery is carried and not checked, and the report says so. The demo's fake Stripe attaches webhooks when started with `--webhook-secret`; the conformance vectors include a receipt verified with and without the secret.
185
+
186
+ ## Retention on the log
187
+
188
+ Receipts hold values: request arguments, results, facts. The log is append-only and hashed, so nothing can simply be deleted from it. `prune` is how retention reaches it without breaking a proof:
189
+
190
+ ```bash
191
+ node src/cli.ts prune --log log.jsonl --before 2026-06-01T00:00:00Z --receipts receipts
192
+ ```
193
+
194
+ Every leaf whose receipt is older than the cutoff is replaced in the file by its leaf hash, and the receipt's bundle file is deleted. The Merkle tree is built from leaf hashes, so every root, every inclusion proof, and every consistency proof for the remaining leaves is unchanged, and `--log` verification of later receipts still passes. Someone who kept a pruned receipt's bundle can still prove it was in the log; nobody holding only the log can recover what it said. Run it on the same schedule as memory retention.
175
195
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-custody/receipts",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Chain of custody for AI agents: signed, independently verifiable receipts for tool calls. MCP gateway + Cedar policy + Merkle transparency log",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -39,6 +39,10 @@
39
39
  "./sdk/langchain": {
40
40
  "types": "./dist/sdk/langchain.d.ts",
41
41
  "default": "./dist/sdk/langchain.js"
42
+ },
43
+ "./cli": {
44
+ "types": "./dist/cli.d.ts",
45
+ "default": "./dist/cli.js"
42
46
  }
43
47
  },
44
48
  "files": [
@@ -7,26 +7,26 @@
7
7
  "description": "The tree head from the first remote receipt and the log's later head, with the proof the log served.",
8
8
  "older": {
9
9
  "payloadType": "application/vnd.agent-custody.treehead+json",
10
- "payload": "eyJyb290SGFzaCI6IjY4ODlmODQyNmVkODg4YTVlNzI0Y2YzNThlNmI0Y2E3ZmI3YWVmMTkwODkxOWE5MGYxZjNlNzFjMWU3MmNkODUiLCJ0aW1lc3RhbXAiOiIyMDI2LTA5LTA3VDA4OjM3OjM0LjkyOVoiLCJ0cmVlU2l6ZSI6MX0=",
10
+ "payload": "eyJyb290SGFzaCI6ImFmYjZhMmJjNThiZmQwNDk4YWNjZTZiYTY1MTAxM2IwY2JiYjlmNTI1MWM1NTI0Nzg3NGY5ZWYzOGM3YjAxMjMiLCJ0aW1lc3RhbXAiOiIyMDI2LTA5LTA3VDEzOjQ4OjQyLjQ0OVoiLCJ0cmVlU2l6ZSI6MX0=",
11
11
  "signatures": [
12
12
  {
13
- "keyid": "48967bd6051d66cebf961f226a6ae4e90dce91ead9ac10c0f9aaa427d40c4c16",
14
- "sig": "FL7TL3y1JgXinAkxywmKfoULNe2V8D+JpIcsJWok54rIun70z7bmj78R1VnNe9aADLSGQb0JTYhdaODn9mOnCg=="
13
+ "keyid": "402c5fa71d8055eadffe3e33d7847e543551d24c002a9adf86286f03eb5e4538",
14
+ "sig": "ZcTaC2tLzE32o+sIj0qFr9lRWaidilkLf6VkVTt6N3McGnp/lISpE0f+naKlRvvQR70kreVm43mwHeMnLBUPCw=="
15
15
  }
16
16
  ]
17
17
  },
18
18
  "newer": {
19
19
  "payloadType": "application/vnd.agent-custody.treehead+json",
20
- "payload": "eyJyb290SGFzaCI6IjUxY2MyNzIzMzM0NzhmMjYxNDU1MWFmMWM1NjExMzBjOTBlODEwM2JhYmI1NzNkZjY2YjM3ZTVhMDk1YjI0ZWYiLCJ0aW1lc3RhbXAiOiIyMDI2LTA5LTA3VDA4OjM3OjM0LjkzM1oiLCJ0cmVlU2l6ZSI6Mn0=",
20
+ "payload": "eyJyb290SGFzaCI6IjJlZTc2MmUzYzdlYzdhODE4ODc4MjUwNDhiZGMwZTEyMWFjNDQzM2VjM2FlNjFjYjU5MjM3MWNmYWMxNDVjZmEiLCJ0aW1lc3RhbXAiOiIyMDI2LTA5LTA3VDEzOjQ4OjQyLjQ1M1oiLCJ0cmVlU2l6ZSI6Mn0=",
21
21
  "signatures": [
22
22
  {
23
- "keyid": "48967bd6051d66cebf961f226a6ae4e90dce91ead9ac10c0f9aaa427d40c4c16",
24
- "sig": "o/zrDH6/I3VPabSVS4RozKm945Nd+hiwt6JTytpyMavxizlR8ZuGmG6lX56+A0M4wAk/H0qmmHXoLCGuobhdCw=="
23
+ "keyid": "402c5fa71d8055eadffe3e33d7847e543551d24c002a9adf86286f03eb5e4538",
24
+ "sig": "++9Ra+7i8vejqY418WnWH4CXA9Rxgb/gDHWrEWgZLYpSPjOdbEXB3XlEArIKaP3+I19eTjK4EQQ07mI2WM3ZCQ=="
25
25
  }
26
26
  ]
27
27
  },
28
28
  "proof": [
29
- "e74d1e2874003df276b93e2e764da876201bcc1a9efe8752118676eafc4ce5eb"
29
+ "ae2d0fcc4034cc32db9e07e9f039358baaef3ae6e22533b9c273ee9042a51d5b"
30
30
  ],
31
31
  "keys": [
32
32
  "log"
@@ -41,26 +41,26 @@
41
41
  "description": "The same heads the wrong way round.",
42
42
  "older": {
43
43
  "payloadType": "application/vnd.agent-custody.treehead+json",
44
- "payload": "eyJyb290SGFzaCI6IjUxY2MyNzIzMzM0NzhmMjYxNDU1MWFmMWM1NjExMzBjOTBlODEwM2JhYmI1NzNkZjY2YjM3ZTVhMDk1YjI0ZWYiLCJ0aW1lc3RhbXAiOiIyMDI2LTA5LTA3VDA4OjM3OjM0LjkzM1oiLCJ0cmVlU2l6ZSI6Mn0=",
44
+ "payload": "eyJyb290SGFzaCI6IjJlZTc2MmUzYzdlYzdhODE4ODc4MjUwNDhiZGMwZTEyMWFjNDQzM2VjM2FlNjFjYjU5MjM3MWNmYWMxNDVjZmEiLCJ0aW1lc3RhbXAiOiIyMDI2LTA5LTA3VDEzOjQ4OjQyLjQ1M1oiLCJ0cmVlU2l6ZSI6Mn0=",
45
45
  "signatures": [
46
46
  {
47
- "keyid": "48967bd6051d66cebf961f226a6ae4e90dce91ead9ac10c0f9aaa427d40c4c16",
48
- "sig": "o/zrDH6/I3VPabSVS4RozKm945Nd+hiwt6JTytpyMavxizlR8ZuGmG6lX56+A0M4wAk/H0qmmHXoLCGuobhdCw=="
47
+ "keyid": "402c5fa71d8055eadffe3e33d7847e543551d24c002a9adf86286f03eb5e4538",
48
+ "sig": "++9Ra+7i8vejqY418WnWH4CXA9Rxgb/gDHWrEWgZLYpSPjOdbEXB3XlEArIKaP3+I19eTjK4EQQ07mI2WM3ZCQ=="
49
49
  }
50
50
  ]
51
51
  },
52
52
  "newer": {
53
53
  "payloadType": "application/vnd.agent-custody.treehead+json",
54
- "payload": "eyJyb290SGFzaCI6IjY4ODlmODQyNmVkODg4YTVlNzI0Y2YzNThlNmI0Y2E3ZmI3YWVmMTkwODkxOWE5MGYxZjNlNzFjMWU3MmNkODUiLCJ0aW1lc3RhbXAiOiIyMDI2LTA5LTA3VDA4OjM3OjM0LjkyOVoiLCJ0cmVlU2l6ZSI6MX0=",
54
+ "payload": "eyJyb290SGFzaCI6ImFmYjZhMmJjNThiZmQwNDk4YWNjZTZiYTY1MTAxM2IwY2JiYjlmNTI1MWM1NTI0Nzg3NGY5ZWYzOGM3YjAxMjMiLCJ0aW1lc3RhbXAiOiIyMDI2LTA5LTA3VDEzOjQ4OjQyLjQ0OVoiLCJ0cmVlU2l6ZSI6MX0=",
55
55
  "signatures": [
56
56
  {
57
- "keyid": "48967bd6051d66cebf961f226a6ae4e90dce91ead9ac10c0f9aaa427d40c4c16",
58
- "sig": "FL7TL3y1JgXinAkxywmKfoULNe2V8D+JpIcsJWok54rIun70z7bmj78R1VnNe9aADLSGQb0JTYhdaODn9mOnCg=="
57
+ "keyid": "402c5fa71d8055eadffe3e33d7847e543551d24c002a9adf86286f03eb5e4538",
58
+ "sig": "ZcTaC2tLzE32o+sIj0qFr9lRWaidilkLf6VkVTt6N3McGnp/lISpE0f+naKlRvvQR70kreVm43mwHeMnLBUPCw=="
59
59
  }
60
60
  ]
61
61
  },
62
62
  "proof": [
63
- "e74d1e2874003df276b93e2e764da876201bcc1a9efe8752118676eafc4ce5eb"
63
+ "ae2d0fcc4034cc32db9e07e9f039358baaef3ae6e22533b9c273ee9042a51d5b"
64
64
  ],
65
65
  "keys": [
66
66
  "log"
@@ -77,26 +77,26 @@
77
77
  "description": "Tree heads checked against the app key, which did not sign them.",
78
78
  "older": {
79
79
  "payloadType": "application/vnd.agent-custody.treehead+json",
80
- "payload": "eyJyb290SGFzaCI6IjY4ODlmODQyNmVkODg4YTVlNzI0Y2YzNThlNmI0Y2E3ZmI3YWVmMTkwODkxOWE5MGYxZjNlNzFjMWU3MmNkODUiLCJ0aW1lc3RhbXAiOiIyMDI2LTA5LTA3VDA4OjM3OjM0LjkyOVoiLCJ0cmVlU2l6ZSI6MX0=",
80
+ "payload": "eyJyb290SGFzaCI6ImFmYjZhMmJjNThiZmQwNDk4YWNjZTZiYTY1MTAxM2IwY2JiYjlmNTI1MWM1NTI0Nzg3NGY5ZWYzOGM3YjAxMjMiLCJ0aW1lc3RhbXAiOiIyMDI2LTA5LTA3VDEzOjQ4OjQyLjQ0OVoiLCJ0cmVlU2l6ZSI6MX0=",
81
81
  "signatures": [
82
82
  {
83
- "keyid": "48967bd6051d66cebf961f226a6ae4e90dce91ead9ac10c0f9aaa427d40c4c16",
84
- "sig": "FL7TL3y1JgXinAkxywmKfoULNe2V8D+JpIcsJWok54rIun70z7bmj78R1VnNe9aADLSGQb0JTYhdaODn9mOnCg=="
83
+ "keyid": "402c5fa71d8055eadffe3e33d7847e543551d24c002a9adf86286f03eb5e4538",
84
+ "sig": "ZcTaC2tLzE32o+sIj0qFr9lRWaidilkLf6VkVTt6N3McGnp/lISpE0f+naKlRvvQR70kreVm43mwHeMnLBUPCw=="
85
85
  }
86
86
  ]
87
87
  },
88
88
  "newer": {
89
89
  "payloadType": "application/vnd.agent-custody.treehead+json",
90
- "payload": "eyJyb290SGFzaCI6IjUxY2MyNzIzMzM0NzhmMjYxNDU1MWFmMWM1NjExMzBjOTBlODEwM2JhYmI1NzNkZjY2YjM3ZTVhMDk1YjI0ZWYiLCJ0aW1lc3RhbXAiOiIyMDI2LTA5LTA3VDA4OjM3OjM0LjkzM1oiLCJ0cmVlU2l6ZSI6Mn0=",
90
+ "payload": "eyJyb290SGFzaCI6IjJlZTc2MmUzYzdlYzdhODE4ODc4MjUwNDhiZGMwZTEyMWFjNDQzM2VjM2FlNjFjYjU5MjM3MWNmYWMxNDVjZmEiLCJ0aW1lc3RhbXAiOiIyMDI2LTA5LTA3VDEzOjQ4OjQyLjQ1M1oiLCJ0cmVlU2l6ZSI6Mn0=",
91
91
  "signatures": [
92
92
  {
93
- "keyid": "48967bd6051d66cebf961f226a6ae4e90dce91ead9ac10c0f9aaa427d40c4c16",
94
- "sig": "o/zrDH6/I3VPabSVS4RozKm945Nd+hiwt6JTytpyMavxizlR8ZuGmG6lX56+A0M4wAk/H0qmmHXoLCGuobhdCw=="
93
+ "keyid": "402c5fa71d8055eadffe3e33d7847e543551d24c002a9adf86286f03eb5e4538",
94
+ "sig": "++9Ra+7i8vejqY418WnWH4CXA9Rxgb/gDHWrEWgZLYpSPjOdbEXB3XlEArIKaP3+I19eTjK4EQQ07mI2WM3ZCQ=="
95
95
  }
96
96
  ]
97
97
  },
98
98
  "proof": [
99
- "e74d1e2874003df276b93e2e764da876201bcc1a9efe8752118676eafc4ce5eb"
99
+ "ae2d0fcc4034cc32db9e07e9f039358baaef3ae6e22533b9c273ee9042a51d5b"
100
100
  ],
101
101
  "keys": [
102
102
  "app"
@@ -114,21 +114,21 @@
114
114
  "description": "A proof with a hash removed.",
115
115
  "older": {
116
116
  "payloadType": "application/vnd.agent-custody.treehead+json",
117
- "payload": "eyJyb290SGFzaCI6IjY4ODlmODQyNmVkODg4YTVlNzI0Y2YzNThlNmI0Y2E3ZmI3YWVmMTkwODkxOWE5MGYxZjNlNzFjMWU3MmNkODUiLCJ0aW1lc3RhbXAiOiIyMDI2LTA5LTA3VDA4OjM3OjM0LjkyOVoiLCJ0cmVlU2l6ZSI6MX0=",
117
+ "payload": "eyJyb290SGFzaCI6ImFmYjZhMmJjNThiZmQwNDk4YWNjZTZiYTY1MTAxM2IwY2JiYjlmNTI1MWM1NTI0Nzg3NGY5ZWYzOGM3YjAxMjMiLCJ0aW1lc3RhbXAiOiIyMDI2LTA5LTA3VDEzOjQ4OjQyLjQ0OVoiLCJ0cmVlU2l6ZSI6MX0=",
118
118
  "signatures": [
119
119
  {
120
- "keyid": "48967bd6051d66cebf961f226a6ae4e90dce91ead9ac10c0f9aaa427d40c4c16",
121
- "sig": "FL7TL3y1JgXinAkxywmKfoULNe2V8D+JpIcsJWok54rIun70z7bmj78R1VnNe9aADLSGQb0JTYhdaODn9mOnCg=="
120
+ "keyid": "402c5fa71d8055eadffe3e33d7847e543551d24c002a9adf86286f03eb5e4538",
121
+ "sig": "ZcTaC2tLzE32o+sIj0qFr9lRWaidilkLf6VkVTt6N3McGnp/lISpE0f+naKlRvvQR70kreVm43mwHeMnLBUPCw=="
122
122
  }
123
123
  ]
124
124
  },
125
125
  "newer": {
126
126
  "payloadType": "application/vnd.agent-custody.treehead+json",
127
- "payload": "eyJyb290SGFzaCI6IjUxY2MyNzIzMzM0NzhmMjYxNDU1MWFmMWM1NjExMzBjOTBlODEwM2JhYmI1NzNkZjY2YjM3ZTVhMDk1YjI0ZWYiLCJ0aW1lc3RhbXAiOiIyMDI2LTA5LTA3VDA4OjM3OjM0LjkzM1oiLCJ0cmVlU2l6ZSI6Mn0=",
127
+ "payload": "eyJyb290SGFzaCI6IjJlZTc2MmUzYzdlYzdhODE4ODc4MjUwNDhiZGMwZTEyMWFjNDQzM2VjM2FlNjFjYjU5MjM3MWNmYWMxNDVjZmEiLCJ0aW1lc3RhbXAiOiIyMDI2LTA5LTA3VDEzOjQ4OjQyLjQ1M1oiLCJ0cmVlU2l6ZSI6Mn0=",
128
128
  "signatures": [
129
129
  {
130
- "keyid": "48967bd6051d66cebf961f226a6ae4e90dce91ead9ac10c0f9aaa427d40c4c16",
131
- "sig": "o/zrDH6/I3VPabSVS4RozKm945Nd+hiwt6JTytpyMavxizlR8ZuGmG6lX56+A0M4wAk/H0qmmHXoLCGuobhdCw=="
130
+ "keyid": "402c5fa71d8055eadffe3e33d7847e543551d24c002a9adf86286f03eb5e4538",
131
+ "sig": "++9Ra+7i8vejqY418WnWH4CXA9Rxgb/gDHWrEWgZLYpSPjOdbEXB3XlEArIKaP3+I19eTjK4EQQ07mI2WM3ZCQ=="
132
132
  }
133
133
  ]
134
134
  },
@@ -53,18 +53,18 @@
53
53
  }
54
54
  ],
55
55
  "keyid": {
56
- "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEADBTs73puK6sTeOys85s6w1yJCBPt+eiQheOIszKqBiU=\n-----END PUBLIC KEY-----\n",
57
- "keyid": "9dd265bc328e448488e35ec8ca89cc3b4270bfc6c8a0ba01845bb8867f1c7c60"
56
+ "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAPkUEkHrnkfYttWXvl/rsSvOqIW8k0HvjQknUWhsI0tI=\n-----END PUBLIC KEY-----\n",
57
+ "keyid": "b8f05ee956d16bc7e981e1cc6e62739623e3a169d8e14aa43d2c2b32ce956b44"
58
58
  },
59
59
  "dsse": {
60
- "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEADBTs73puK6sTeOys85s6w1yJCBPt+eiQheOIszKqBiU=\n-----END PUBLIC KEY-----\n",
60
+ "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAPkUEkHrnkfYttWXvl/rsSvOqIW8k0HvjQknUWhsI0tI=\n-----END PUBLIC KEY-----\n",
61
61
  "envelope": {
62
62
  "payloadType": "application/vnd.example+json",
63
63
  "payload": "eyJoZWxsbyI6IndvcmxkIn0=",
64
64
  "signatures": [
65
65
  {
66
- "keyid": "9dd265bc328e448488e35ec8ca89cc3b4270bfc6c8a0ba01845bb8867f1c7c60",
67
- "sig": "6zlQBbpy7oGNtH2d5gJ5ZmHzrKIjF8gT0XDkjhzafjCWWphFCcyZaVzZumJOjl6hnhzvu73FgHenAjyImMA0Cg=="
66
+ "keyid": "b8f05ee956d16bc7e981e1cc6e62739623e3a169d8e14aa43d2c2b32ce956b44",
67
+ "sig": "sSViplEmHbNqomtr8I67F+jIH8JDbmFhGkioDN8nXxpb1yg21/FLP2wqBVHrTMveuCtF4O+EoxO7dlBITeoIBw=="
68
68
  }
69
69
  ]
70
70
  },