@atcn/subledger 1.3.0 → 1.4.0

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.
@@ -2,12 +2,14 @@ import { z } from "zod";
2
2
  /**
3
3
  * Signed documents of the Agent Work Subledger (PRD v1.2 §6, §16).
4
4
  * Schema 1.3 adds closure `obligation_links`, the clearing-network claim asserters, and the `network_recorded` assurance label;
5
- * 1.2 documents must use neither (see packages/schema/COMPATIBILITY.md).
5
+ * 1.2 documents must use neither. Schema 1.4 adds delegation `execution`, the response statement fields `execution`,
6
+ * `issued_at`, `expires_at` and `refs`, and the `expired` and `revoked` labels; 1.2 and 1.3 documents must use none
7
+ * of them (see packages/schema/COMPATIBILITY.md).
6
8
  */
7
- export declare const SUBLEDGER_SCHEMA_VERSION: "1.3";
8
- export declare const SUPPORTED_SUBLEDGER_SCHEMA_VERSIONS: readonly ["1.2", "1.3"];
9
+ export declare const SUBLEDGER_SCHEMA_VERSION: "1.4";
10
+ export declare const SUPPORTED_SUBLEDGER_SCHEMA_VERSIONS: readonly ["1.2", "1.3", "1.4"];
9
11
  /** Must equal this package's version in package.json (checked by a test). */
10
- export declare const SUBLEDGER_VERIFIER_VERSION: "1.3.0";
12
+ export declare const SUBLEDGER_VERIFIER_VERSION: "1.4.0";
11
13
  export declare const RECEIPT_DOCUMENT_TYPE: "atcn.subledger.receipt";
12
14
  export declare const CLOSURE_DOCUMENT_TYPE: "atcn.subledger.closure";
13
15
  export declare const RESPONSE_STATEMENT_TYPE: "atcn.subledger.receipt_response";
@@ -180,6 +182,8 @@ export declare const DeliveryClaimSchema: z.ZodObject<{
180
182
  provider_key_signed: "provider_key_signed";
181
183
  contested: "contested";
182
184
  superseded: "superseded";
185
+ expired: "expired";
186
+ revoked: "revoked";
183
187
  }>>;
184
188
  note: z.ZodNullable<z.ZodString>;
185
189
  evidence: z.ZodArray<z.ZodObject<{
@@ -259,6 +263,20 @@ export declare const ResponseStatementSchema: z.ZodObject<{
259
263
  proposed_value: z.ZodString;
260
264
  reason: z.ZodString;
261
265
  }, z.core.$strip>>;
266
+ execution: z.ZodOptional<z.ZodObject<{
267
+ execution_id: z.ZodString;
268
+ execution_digest: z.ZodString;
269
+ }, z.core.$strip>>;
270
+ issued_at: z.ZodOptional<z.ZodString>;
271
+ expires_at: z.ZodOptional<z.ZodString>;
272
+ refs: z.ZodOptional<z.ZodArray<z.ZodObject<{
273
+ relation: z.ZodEnum<{
274
+ revokes: "revokes";
275
+ disputes: "disputes";
276
+ }>;
277
+ attestation_digest: z.ZodString;
278
+ reason: z.ZodString;
279
+ }, z.core.$strip>>>;
262
280
  }, z.core.$strip>;
263
281
  export type ResponseStatement = z.infer<typeof ResponseStatementSchema>;
264
282
  export declare const ResponseRecordSchema: z.ZodObject<{
@@ -303,6 +321,20 @@ export declare const ResponseRecordSchema: z.ZodObject<{
303
321
  proposed_value: z.ZodString;
304
322
  reason: z.ZodString;
305
323
  }, z.core.$strip>>;
324
+ execution: z.ZodOptional<z.ZodObject<{
325
+ execution_id: z.ZodString;
326
+ execution_digest: z.ZodString;
327
+ }, z.core.$strip>>;
328
+ issued_at: z.ZodOptional<z.ZodString>;
329
+ expires_at: z.ZodOptional<z.ZodString>;
330
+ refs: z.ZodOptional<z.ZodArray<z.ZodObject<{
331
+ relation: z.ZodEnum<{
332
+ revokes: "revokes";
333
+ disputes: "disputes";
334
+ }>;
335
+ attestation_digest: z.ZodString;
336
+ reason: z.ZodString;
337
+ }, z.core.$strip>>>;
306
338
  }, z.core.$strip>;
307
339
  statement_digest: z.ZodString;
308
340
  provider_signature: z.ZodNullable<z.ZodObject<{
@@ -320,6 +352,8 @@ export declare const ResponseRecordSchema: z.ZodObject<{
320
352
  provider_key_signed: "provider_key_signed";
321
353
  contested: "contested";
322
354
  superseded: "superseded";
355
+ expired: "expired";
356
+ revoked: "revoked";
323
357
  }>>;
324
358
  decision: z.ZodNullable<z.ZodObject<{
325
359
  status: z.ZodEnum<{
@@ -410,8 +444,9 @@ export declare const ReceiptFinancialEventSchema: z.ZodObject<{
410
444
  export declare const ReceiptPayloadSchema: z.ZodObject<{
411
445
  document_type: z.ZodLiteral<"atcn.subledger.receipt">;
412
446
  schema_version: z.ZodEnum<{
413
- 1.3: "1.3";
447
+ 1.4: "1.4";
414
448
  1.2: "1.2";
449
+ 1.3: "1.3";
415
450
  }>;
416
451
  receipt_id: z.ZodString;
417
452
  revision: z.ZodNumber;
@@ -445,6 +480,30 @@ export declare const ReceiptPayloadSchema: z.ZodObject<{
445
480
  disclosed: "disclosed";
446
481
  none: "none";
447
482
  }>;
483
+ execution: z.ZodOptional<z.ZodObject<{
484
+ execution_id: z.ZodString;
485
+ protocol: z.ZodOptional<z.ZodObject<{
486
+ name: z.ZodLiteral<"a2a">;
487
+ task_id: z.ZodString;
488
+ context_id: z.ZodOptional<z.ZodString>;
489
+ }, z.core.$strip>>;
490
+ agent: z.ZodObject<{
491
+ agent_id: z.ZodString;
492
+ agent_version: z.ZodString;
493
+ card_digest: z.ZodOptional<z.ZodString>;
494
+ model: z.ZodOptional<z.ZodObject<{
495
+ provider: z.ZodString;
496
+ name: z.ZodString;
497
+ version: z.ZodString;
498
+ }, z.core.$strip>>;
499
+ config_digest: z.ZodOptional<z.ZodString>;
500
+ }, z.core.$strip>;
501
+ skill: z.ZodOptional<z.ZodObject<{
502
+ namespace: z.ZodString;
503
+ skill_id: z.ZodString;
504
+ agent_card_url: z.ZodOptional<z.ZodURL>;
505
+ }, z.core.$strip>>;
506
+ }, z.core.$strip>>;
448
507
  }, z.core.$strip>;
449
508
  provider: z.ZodObject<{
450
509
  provider_id: z.ZodNullable<z.ZodString>;
@@ -493,6 +552,8 @@ export declare const ReceiptPayloadSchema: z.ZodObject<{
493
552
  provider_key_signed: "provider_key_signed";
494
553
  contested: "contested";
495
554
  superseded: "superseded";
555
+ expired: "expired";
556
+ revoked: "revoked";
496
557
  }>>;
497
558
  recorded_at: z.ZodString;
498
559
  }, z.core.$strip>>;
@@ -612,8 +673,9 @@ export declare const SignedReceiptSchema: z.ZodObject<{
612
673
  payload: z.ZodObject<{
613
674
  document_type: z.ZodLiteral<"atcn.subledger.receipt">;
614
675
  schema_version: z.ZodEnum<{
615
- 1.3: "1.3";
676
+ 1.4: "1.4";
616
677
  1.2: "1.2";
678
+ 1.3: "1.3";
617
679
  }>;
618
680
  receipt_id: z.ZodString;
619
681
  revision: z.ZodNumber;
@@ -647,6 +709,30 @@ export declare const SignedReceiptSchema: z.ZodObject<{
647
709
  disclosed: "disclosed";
648
710
  none: "none";
649
711
  }>;
712
+ execution: z.ZodOptional<z.ZodObject<{
713
+ execution_id: z.ZodString;
714
+ protocol: z.ZodOptional<z.ZodObject<{
715
+ name: z.ZodLiteral<"a2a">;
716
+ task_id: z.ZodString;
717
+ context_id: z.ZodOptional<z.ZodString>;
718
+ }, z.core.$strip>>;
719
+ agent: z.ZodObject<{
720
+ agent_id: z.ZodString;
721
+ agent_version: z.ZodString;
722
+ card_digest: z.ZodOptional<z.ZodString>;
723
+ model: z.ZodOptional<z.ZodObject<{
724
+ provider: z.ZodString;
725
+ name: z.ZodString;
726
+ version: z.ZodString;
727
+ }, z.core.$strip>>;
728
+ config_digest: z.ZodOptional<z.ZodString>;
729
+ }, z.core.$strip>;
730
+ skill: z.ZodOptional<z.ZodObject<{
731
+ namespace: z.ZodString;
732
+ skill_id: z.ZodString;
733
+ agent_card_url: z.ZodOptional<z.ZodURL>;
734
+ }, z.core.$strip>>;
735
+ }, z.core.$strip>>;
650
736
  }, z.core.$strip>;
651
737
  provider: z.ZodObject<{
652
738
  provider_id: z.ZodNullable<z.ZodString>;
@@ -695,6 +781,8 @@ export declare const SignedReceiptSchema: z.ZodObject<{
695
781
  provider_key_signed: "provider_key_signed";
696
782
  contested: "contested";
697
783
  superseded: "superseded";
784
+ expired: "expired";
785
+ revoked: "revoked";
698
786
  }>>;
699
787
  recorded_at: z.ZodString;
700
788
  }, z.core.$strip>>;
@@ -848,6 +936,30 @@ export declare const ClosureDelegationSchema: z.ZodObject<{
848
936
  delivery_status: z.ZodString;
849
937
  retrospective: z.ZodBoolean;
850
938
  created_at: z.ZodString;
939
+ execution: z.ZodOptional<z.ZodObject<{
940
+ execution_id: z.ZodString;
941
+ protocol: z.ZodOptional<z.ZodObject<{
942
+ name: z.ZodLiteral<"a2a">;
943
+ task_id: z.ZodString;
944
+ context_id: z.ZodOptional<z.ZodString>;
945
+ }, z.core.$strip>>;
946
+ agent: z.ZodObject<{
947
+ agent_id: z.ZodString;
948
+ agent_version: z.ZodString;
949
+ card_digest: z.ZodOptional<z.ZodString>;
950
+ model: z.ZodOptional<z.ZodObject<{
951
+ provider: z.ZodString;
952
+ name: z.ZodString;
953
+ version: z.ZodString;
954
+ }, z.core.$strip>>;
955
+ config_digest: z.ZodOptional<z.ZodString>;
956
+ }, z.core.$strip>;
957
+ skill: z.ZodOptional<z.ZodObject<{
958
+ namespace: z.ZodString;
959
+ skill_id: z.ZodString;
960
+ agent_card_url: z.ZodOptional<z.ZodURL>;
961
+ }, z.core.$strip>>;
962
+ }, z.core.$strip>>;
851
963
  }, z.core.$strip>;
852
964
  export type ClosureDelegation = z.infer<typeof ClosureDelegationSchema>;
853
965
  export declare const AllocationRecordSchema: z.ZodObject<{
@@ -1052,8 +1164,9 @@ export type ObligationLink = z.infer<typeof ObligationLinkSchema>;
1052
1164
  export declare const ClosurePayloadSchema: z.ZodObject<{
1053
1165
  document_type: z.ZodLiteral<"atcn.subledger.closure">;
1054
1166
  schema_version: z.ZodEnum<{
1055
- 1.3: "1.3";
1167
+ 1.4: "1.4";
1056
1168
  1.2: "1.2";
1169
+ 1.3: "1.3";
1057
1170
  }>;
1058
1171
  closure_id: z.ZodString;
1059
1172
  version: z.ZodNumber;
@@ -1105,6 +1218,30 @@ export declare const ClosurePayloadSchema: z.ZodObject<{
1105
1218
  delivery_status: z.ZodString;
1106
1219
  retrospective: z.ZodBoolean;
1107
1220
  created_at: z.ZodString;
1221
+ execution: z.ZodOptional<z.ZodObject<{
1222
+ execution_id: z.ZodString;
1223
+ protocol: z.ZodOptional<z.ZodObject<{
1224
+ name: z.ZodLiteral<"a2a">;
1225
+ task_id: z.ZodString;
1226
+ context_id: z.ZodOptional<z.ZodString>;
1227
+ }, z.core.$strip>>;
1228
+ agent: z.ZodObject<{
1229
+ agent_id: z.ZodString;
1230
+ agent_version: z.ZodString;
1231
+ card_digest: z.ZodOptional<z.ZodString>;
1232
+ model: z.ZodOptional<z.ZodObject<{
1233
+ provider: z.ZodString;
1234
+ name: z.ZodString;
1235
+ version: z.ZodString;
1236
+ }, z.core.$strip>>;
1237
+ config_digest: z.ZodOptional<z.ZodString>;
1238
+ }, z.core.$strip>;
1239
+ skill: z.ZodOptional<z.ZodObject<{
1240
+ namespace: z.ZodString;
1241
+ skill_id: z.ZodString;
1242
+ agent_card_url: z.ZodOptional<z.ZodURL>;
1243
+ }, z.core.$strip>>;
1244
+ }, z.core.$strip>>;
1108
1245
  }, z.core.$strip>>;
1109
1246
  delivery_claims: z.ZodArray<z.ZodObject<{
1110
1247
  event_id: z.ZodString;
@@ -1135,6 +1272,8 @@ export declare const ClosurePayloadSchema: z.ZodObject<{
1135
1272
  provider_key_signed: "provider_key_signed";
1136
1273
  contested: "contested";
1137
1274
  superseded: "superseded";
1275
+ expired: "expired";
1276
+ revoked: "revoked";
1138
1277
  }>>;
1139
1278
  note: z.ZodNullable<z.ZodString>;
1140
1279
  evidence: z.ZodArray<z.ZodObject<{
@@ -1386,6 +1525,20 @@ export declare const ClosurePayloadSchema: z.ZodObject<{
1386
1525
  proposed_value: z.ZodString;
1387
1526
  reason: z.ZodString;
1388
1527
  }, z.core.$strip>>;
1528
+ execution: z.ZodOptional<z.ZodObject<{
1529
+ execution_id: z.ZodString;
1530
+ execution_digest: z.ZodString;
1531
+ }, z.core.$strip>>;
1532
+ issued_at: z.ZodOptional<z.ZodString>;
1533
+ expires_at: z.ZodOptional<z.ZodString>;
1534
+ refs: z.ZodOptional<z.ZodArray<z.ZodObject<{
1535
+ relation: z.ZodEnum<{
1536
+ revokes: "revokes";
1537
+ disputes: "disputes";
1538
+ }>;
1539
+ attestation_digest: z.ZodString;
1540
+ reason: z.ZodString;
1541
+ }, z.core.$strip>>>;
1389
1542
  }, z.core.$strip>;
1390
1543
  statement_digest: z.ZodString;
1391
1544
  provider_signature: z.ZodNullable<z.ZodObject<{
@@ -1403,6 +1556,8 @@ export declare const ClosurePayloadSchema: z.ZodObject<{
1403
1556
  provider_key_signed: "provider_key_signed";
1404
1557
  contested: "contested";
1405
1558
  superseded: "superseded";
1559
+ expired: "expired";
1560
+ revoked: "revoked";
1406
1561
  }>>;
1407
1562
  decision: z.ZodNullable<z.ZodObject<{
1408
1563
  status: z.ZodEnum<{
@@ -1459,8 +1614,9 @@ export declare const SignedClosureSchema: z.ZodObject<{
1459
1614
  payload: z.ZodObject<{
1460
1615
  document_type: z.ZodLiteral<"atcn.subledger.closure">;
1461
1616
  schema_version: z.ZodEnum<{
1462
- 1.3: "1.3";
1617
+ 1.4: "1.4";
1463
1618
  1.2: "1.2";
1619
+ 1.3: "1.3";
1464
1620
  }>;
1465
1621
  closure_id: z.ZodString;
1466
1622
  version: z.ZodNumber;
@@ -1512,6 +1668,30 @@ export declare const SignedClosureSchema: z.ZodObject<{
1512
1668
  delivery_status: z.ZodString;
1513
1669
  retrospective: z.ZodBoolean;
1514
1670
  created_at: z.ZodString;
1671
+ execution: z.ZodOptional<z.ZodObject<{
1672
+ execution_id: z.ZodString;
1673
+ protocol: z.ZodOptional<z.ZodObject<{
1674
+ name: z.ZodLiteral<"a2a">;
1675
+ task_id: z.ZodString;
1676
+ context_id: z.ZodOptional<z.ZodString>;
1677
+ }, z.core.$strip>>;
1678
+ agent: z.ZodObject<{
1679
+ agent_id: z.ZodString;
1680
+ agent_version: z.ZodString;
1681
+ card_digest: z.ZodOptional<z.ZodString>;
1682
+ model: z.ZodOptional<z.ZodObject<{
1683
+ provider: z.ZodString;
1684
+ name: z.ZodString;
1685
+ version: z.ZodString;
1686
+ }, z.core.$strip>>;
1687
+ config_digest: z.ZodOptional<z.ZodString>;
1688
+ }, z.core.$strip>;
1689
+ skill: z.ZodOptional<z.ZodObject<{
1690
+ namespace: z.ZodString;
1691
+ skill_id: z.ZodString;
1692
+ agent_card_url: z.ZodOptional<z.ZodURL>;
1693
+ }, z.core.$strip>>;
1694
+ }, z.core.$strip>>;
1515
1695
  }, z.core.$strip>>;
1516
1696
  delivery_claims: z.ZodArray<z.ZodObject<{
1517
1697
  event_id: z.ZodString;
@@ -1542,6 +1722,8 @@ export declare const SignedClosureSchema: z.ZodObject<{
1542
1722
  provider_key_signed: "provider_key_signed";
1543
1723
  contested: "contested";
1544
1724
  superseded: "superseded";
1725
+ expired: "expired";
1726
+ revoked: "revoked";
1545
1727
  }>>;
1546
1728
  note: z.ZodNullable<z.ZodString>;
1547
1729
  evidence: z.ZodArray<z.ZodObject<{
@@ -1793,6 +1975,20 @@ export declare const SignedClosureSchema: z.ZodObject<{
1793
1975
  proposed_value: z.ZodString;
1794
1976
  reason: z.ZodString;
1795
1977
  }, z.core.$strip>>;
1978
+ execution: z.ZodOptional<z.ZodObject<{
1979
+ execution_id: z.ZodString;
1980
+ execution_digest: z.ZodString;
1981
+ }, z.core.$strip>>;
1982
+ issued_at: z.ZodOptional<z.ZodString>;
1983
+ expires_at: z.ZodOptional<z.ZodString>;
1984
+ refs: z.ZodOptional<z.ZodArray<z.ZodObject<{
1985
+ relation: z.ZodEnum<{
1986
+ revokes: "revokes";
1987
+ disputes: "disputes";
1988
+ }>;
1989
+ attestation_digest: z.ZodString;
1990
+ reason: z.ZodString;
1991
+ }, z.core.$strip>>>;
1796
1992
  }, z.core.$strip>;
1797
1993
  statement_digest: z.ZodString;
1798
1994
  provider_signature: z.ZodNullable<z.ZodObject<{
@@ -1810,6 +2006,8 @@ export declare const SignedClosureSchema: z.ZodObject<{
1810
2006
  provider_key_signed: "provider_key_signed";
1811
2007
  contested: "contested";
1812
2008
  superseded: "superseded";
2009
+ expired: "expired";
2010
+ revoked: "revoked";
1813
2011
  }>>;
1814
2012
  decision: z.ZodNullable<z.ZodObject<{
1815
2013
  status: z.ZodEnum<{
package/dist/documents.js CHANGED
@@ -1,14 +1,17 @@
1
+ import { AttestationRefSchema, ExecutionBindingSchema, ExecutionDescriptorSchema } from "@atcn/schema";
1
2
  import { z } from "zod";
2
3
  import { ASSURANCE_LABELS, ATTESTABLE_FIELDS, CLAIM_ASSERTERS, Currency, DELIVERY_EVENT_TYPES, EvidenceRefSchema, FINANCIAL_EVENT_TYPES, FxSchema, Minor, NORMALIZED_STATUSES, PAYERS, RESPONSE_TYPES } from "./types.js";
3
4
  /**
4
5
  * Signed documents of the Agent Work Subledger (PRD v1.2 §6, §16).
5
6
  * Schema 1.3 adds closure `obligation_links`, the clearing-network claim asserters, and the `network_recorded` assurance label;
6
- * 1.2 documents must use neither (see packages/schema/COMPATIBILITY.md).
7
+ * 1.2 documents must use neither. Schema 1.4 adds delegation `execution`, the response statement fields `execution`,
8
+ * `issued_at`, `expires_at` and `refs`, and the `expired` and `revoked` labels; 1.2 and 1.3 documents must use none
9
+ * of them (see packages/schema/COMPATIBILITY.md).
7
10
  */
8
- export const SUBLEDGER_SCHEMA_VERSION = "1.3";
9
- export const SUPPORTED_SUBLEDGER_SCHEMA_VERSIONS = ["1.2", "1.3"];
11
+ export const SUBLEDGER_SCHEMA_VERSION = "1.4";
12
+ export const SUPPORTED_SUBLEDGER_SCHEMA_VERSIONS = ["1.2", "1.3", "1.4"];
10
13
  /** Must equal this package's version in package.json (checked by a test). */
11
- export const SUBLEDGER_VERIFIER_VERSION = "1.3.0";
14
+ export const SUBLEDGER_VERIFIER_VERSION = "1.4.0";
12
15
  export const RECEIPT_DOCUMENT_TYPE = "atcn.subledger.receipt";
13
16
  export const CLOSURE_DOCUMENT_TYPE = "atcn.subledger.closure";
14
17
  export const RESPONSE_STATEMENT_TYPE = "atcn.subledger.receipt_response";
@@ -120,6 +123,13 @@ export const ResponseStatementSchema = z.object({
120
123
  note: z.string().max(2000).nullable(),
121
124
  evidence: z.array(EvidenceRefSchema).max(20),
122
125
  corrections: z.array(CorrectionSchema).max(20),
126
+ /** Schema 1.4: the run the statement is about; must match the delegation's recorded execution. */
127
+ execution: ExecutionBindingSchema.optional(),
128
+ /** Schema 1.4: when the provider signed. Required with expires_at or refs. */
129
+ issued_at: Iso.optional(),
130
+ expires_at: Iso.optional(),
131
+ /** Schema 1.4: earlier statements this one revokes (same provider only) or disputes, by statement digest. */
132
+ refs: z.array(AttestationRefSchema).max(20).optional(),
123
133
  });
124
134
  export const ResponseRecordSchema = z.object({
125
135
  response_id: z.string(),
@@ -180,6 +190,8 @@ export const ReceiptPayloadSchema = z.object({
180
190
  expected_delivery: Iso.nullable(),
181
191
  retrospective: z.boolean(),
182
192
  downstream_visibility: z.enum(["unknown", "disclosed", "none"]),
193
+ /** Schema 1.4, present only when recorded: the run a provider statement can cite. */
194
+ execution: ExecutionDescriptorSchema.optional(),
183
195
  }),
184
196
  provider: z.object({
185
197
  provider_id: z.string().nullable(),
@@ -219,6 +231,8 @@ export const ClosureDelegationSchema = z.object({
219
231
  delivery_status: z.string(),
220
232
  retrospective: z.boolean(),
221
233
  created_at: Iso,
234
+ /** Schema 1.4, present only when recorded, so older closures keep their bytes. */
235
+ execution: ExecutionDescriptorSchema.optional(),
222
236
  });
223
237
  export const AllocationRecordSchema = z.object({
224
238
  allocation_id: z.string(),
@@ -1,3 +1,4 @@
1
+ import { type AttestationItem } from "@atcn/schema";
1
2
  import { type Rollup } from "./rollup.js";
2
3
  import { type AllocationRecord, type CaptureGap, type ClosureDelegation, type ClosurePayload, type DeliveryClaim, type Disclosure, type ExceptionRecord, type FieldState, type Issuer, type KeyBindingRecord, type ObligationLink, type ReceiptPayload, type ReceiptTotals, type ResponseRecord } from "./documents.js";
3
4
  import { type AttestableField, type FinancialEventRecord } from "./types.js";
@@ -23,6 +24,10 @@ export type DelegationRecord = ClosureDelegation & {
23
24
  };
24
25
  /** Claims superseded by a later correction stay visible and gain the "superseded" label. */
25
26
  export declare function labelClaims(claims: DeliveryClaim[]): DeliveryClaim[];
27
+ /** A response as an attestation. Only a key-signed statement has a signer, so only it can revoke or be revoked. */
28
+ export declare function responseAttestation(response: ResponseRecord): AttestationItem;
29
+ /** Recomputes the "expired" and "revoked" labels as of `at`. Revoked and expired responses stay visible. */
30
+ export declare function labelResponses(responses: ResponseRecord[], at: string): ResponseRecord[];
26
31
  /** Delivery status is the latest non-superseded status claim. It is a recorded claim, not an adjudicated truth. */
27
32
  export declare function deliveryStatus(claims: DeliveryClaim[]): string;
28
33
  /** Totals for a single delegation's own events (no allocation detail, which may name other cost centers). */
@@ -1,4 +1,4 @@
1
- import { digestOf } from "@atcn/schema";
1
+ import { digestOf, resolveAttestations } from "@atcn/schema";
2
2
  import { computeRollup, costSign } from "./rollup.js";
3
3
  import { CLOSURE_DOCUMENT_TYPE, RECEIPT_DOCUMENT_TYPE, SUBLEDGER_SCHEMA_VERSION, } from "./documents.js";
4
4
  import { ATTESTABLE_FIELDS } from "./types.js";
@@ -7,6 +7,32 @@ export function labelClaims(claims) {
7
7
  const superseded = new Set(claims.map((c) => c.supersedes_event_id).filter((id) => id !== null));
8
8
  return claims.map((c) => (superseded.has(c.event_id) && !c.assurance.includes("superseded") ? { ...c, assurance: [...c.assurance, "superseded"] } : c));
9
9
  }
10
+ /** A response as an attestation. Only a key-signed statement has a signer, so only it can revoke or be revoked. */
11
+ export function responseAttestation(response) {
12
+ const s = response.statement;
13
+ return {
14
+ digest: response.statement_digest,
15
+ signer: response.assurance.includes("provider_key_signed") ? response.provider_id : null,
16
+ issued_at: s.issued_at,
17
+ expires_at: s.expires_at,
18
+ refs: s.refs,
19
+ };
20
+ }
21
+ const TIME_LABELS = ["expired", "revoked"];
22
+ /** Recomputes the "expired" and "revoked" labels as of `at`. Revoked and expired responses stay visible. */
23
+ export function labelResponses(responses, at) {
24
+ const { status } = resolveAttestations(responses.map(responseAttestation), at);
25
+ return responses.map((r) => {
26
+ const kept = r.assurance.filter((label) => !TIME_LABELS.includes(label));
27
+ const added = [];
28
+ if (status[r.statement_digest].time === "expired")
29
+ added.push("expired");
30
+ if (status[r.statement_digest].revoked_by !== null)
31
+ added.push("revoked");
32
+ const assurance = [...kept, ...added];
33
+ return assurance.length === r.assurance.length && assurance.every((label, i) => label === r.assurance[i]) ? r : { ...r, assurance };
34
+ });
35
+ }
10
36
  const STATUS_BY_CLAIM = {
11
37
  acceptance: "accepted",
12
38
  completion: "completed",
@@ -103,6 +129,7 @@ export function buildReceiptPayload(input) {
103
129
  expected_delivery: d.expected_delivery,
104
130
  retrospective: d.retrospective,
105
131
  downstream_visibility: d.downstream_visibility,
132
+ ...(d.execution ? { execution: d.execution } : {}),
106
133
  },
107
134
  provider: {
108
135
  provider_id: input.provider?.provider_id ?? null,
@@ -205,7 +232,7 @@ export function buildClosurePayload(input) {
205
232
  rollup: rollupFor(input.task, input.delegations, input.events, input.allocations),
206
233
  open_exceptions: input.open_exceptions,
207
234
  receipts: input.receipts,
208
- responses: input.responses,
235
+ responses: labelResponses(input.responses, input.generated_at),
209
236
  key_bindings: input.key_bindings,
210
237
  lineage: {
211
238
  complete: input.capture_gaps.length === 0,
@@ -1,3 +1,4 @@
1
+ import { type AttestationRef, type ExecutionBinding } from "@atcn/schema";
1
2
  import { type Correction, type ResponseStatement } from "./documents.js";
2
3
  import type { AttestableField, EvidenceRef, ResponseType } from "./types.js";
3
4
  export interface StatementInput {
@@ -12,6 +13,11 @@ export interface StatementInput {
12
13
  note?: string | null;
13
14
  evidence?: EvidenceRef[];
14
15
  corrections?: Correction[];
16
+ /** Schema 1.4 fields. Each is left out of the statement when not given, so older statements keep their bytes. */
17
+ execution?: ExecutionBinding;
18
+ issued_at?: string;
19
+ expires_at?: string;
20
+ refs?: AttestationRef[];
15
21
  }
16
22
  /** Builds the statement a provider responds with. Field order is irrelevant: the signature covers canonical JSON. */
17
23
  export declare function buildResponseStatement(input: StatementInput): ResponseStatement;
package/dist/response.js CHANGED
@@ -13,6 +13,10 @@ export function buildResponseStatement(input) {
13
13
  note: input.note ?? null,
14
14
  evidence: input.evidence ?? [],
15
15
  corrections: input.corrections ?? [],
16
+ ...(input.execution !== undefined ? { execution: input.execution } : {}),
17
+ ...(input.issued_at !== undefined ? { issued_at: input.issued_at } : {}),
18
+ ...(input.expires_at !== undefined ? { expires_at: input.expires_at } : {}),
19
+ ...(input.refs !== undefined ? { refs: input.refs } : {}),
16
20
  };
17
21
  }
18
22
  export function statementDigest(statement) {
package/dist/types.d.ts CHANGED
@@ -20,7 +20,7 @@ export type ClaimAsserter = (typeof CLAIM_ASSERTERS)[number];
20
20
  export declare const EXCEPTION_KINDS: readonly ["budget_overrun", "unmatched_charge", "ambiguous_match", "missing_receipt", "duplicate_event", "amount_mismatch", "currency_mismatch", "stale_quote", "refund_after_close", "allocation_changed_after_close", "incomplete_lineage"];
21
21
  export type ExceptionKind = (typeof EXCEPTION_KINDS)[number];
22
22
  /** Trust labels kept separate on every screen and export (PRD §16 "Identity assurance"). Never collapsed into "verified". */
23
- export declare const ASSURANCE_LABELS: readonly ["issuer_signed", "buyer_recorded", "network_recorded", "recipient_viewed", "link_authenticated_response", "provider_identity_bound", "provider_key_signed", "contested", "superseded"];
23
+ export declare const ASSURANCE_LABELS: readonly ["issuer_signed", "buyer_recorded", "network_recorded", "recipient_viewed", "link_authenticated_response", "provider_identity_bound", "provider_key_signed", "contested", "superseded", "expired", "revoked"];
24
24
  export type AssuranceLabel = (typeof ASSURANCE_LABELS)[number];
25
25
  export declare const RESPONSE_TYPES: readonly ["acknowledge_view", "acknowledge_delivery", "submit_evidence", "propose_correction", "signed_attestation"];
26
26
  export type ResponseType = (typeof RESPONSE_TYPES)[number];
@@ -76,6 +76,30 @@ export declare const DelegationInputSchema: z.ZodObject<{
76
76
  none: "none";
77
77
  }>>;
78
78
  retrospective: z.ZodDefault<z.ZodBoolean>;
79
+ execution: z.ZodOptional<z.ZodObject<{
80
+ execution_id: z.ZodString;
81
+ protocol: z.ZodOptional<z.ZodObject<{
82
+ name: z.ZodLiteral<"a2a">;
83
+ task_id: z.ZodString;
84
+ context_id: z.ZodOptional<z.ZodString>;
85
+ }, z.core.$strip>>;
86
+ agent: z.ZodObject<{
87
+ agent_id: z.ZodString;
88
+ agent_version: z.ZodString;
89
+ card_digest: z.ZodOptional<z.ZodString>;
90
+ model: z.ZodOptional<z.ZodObject<{
91
+ provider: z.ZodString;
92
+ name: z.ZodString;
93
+ version: z.ZodString;
94
+ }, z.core.$strip>>;
95
+ config_digest: z.ZodOptional<z.ZodString>;
96
+ }, z.core.$strip>;
97
+ skill: z.ZodOptional<z.ZodObject<{
98
+ namespace: z.ZodString;
99
+ skill_id: z.ZodString;
100
+ agent_card_url: z.ZodOptional<z.ZodURL>;
101
+ }, z.core.$strip>>;
102
+ }, z.core.$strip>>;
79
103
  }, z.core.$strip>;
80
104
  export type DelegationInput = z.infer<typeof DelegationInputSchema>;
81
105
  export declare const DelegationEventInputSchema: z.ZodObject<{
package/dist/types.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { ExecutionDescriptorSchema } from "@atcn/schema";
1
2
  import { z } from "zod";
2
3
  /** Agent Work Subledger record shapes (PRD v1.2 §6-§7). Amounts are integer minor units; currencies are ISO 4217. */
3
4
  export const Currency = z.string().regex(/^[A-Z]{3}$/, "ISO 4217 currency code");
@@ -41,6 +42,10 @@ export const ASSURANCE_LABELS = [
41
42
  "provider_key_signed",
42
43
  "contested",
43
44
  "superseded",
45
+ /** A response statement past its signed expires_at at the document's time (schema 1.4). */
46
+ "expired",
47
+ /** A response statement revoked by a later statement from the same provider (schema 1.4). */
48
+ "revoked",
44
49
  ];
45
50
  export const RESPONSE_TYPES = ["acknowledge_view", "acknowledge_delivery", "submit_evidence", "propose_correction", "signed_attestation"];
46
51
  export const SHARE_ACTIONS = ["view", "acknowledge_delivery", "submit_evidence", "propose_correction", "signed_attestation"];
@@ -93,6 +98,8 @@ export const DelegationInputSchema = z.object({
93
98
  /** Whether the provider disclosed its own subdelegations. Absent data stays "unknown" (acceptance 24). */
94
99
  downstream_visibility: z.enum(["unknown", "disclosed", "none"]).default("unknown"),
95
100
  retrospective: z.boolean().default(false),
101
+ /** The provider's run as the buyer recorded it (for A2A, from the task and agent card). Provider statements can cite it. */
102
+ execution: ExecutionDescriptorSchema.optional(),
96
103
  });
97
104
  export const DelegationEventInputSchema = z.object({
98
105
  type: z.enum(DELIVERY_EVENT_TYPES),
package/dist/verify.d.ts CHANGED
@@ -23,6 +23,8 @@ export interface SubledgerVerifyOptions {
23
23
  requireOperatorSignature?: boolean;
24
24
  /** Closure packages (GET /v1/exports/{obligation_id}) of the obligations backing linked delegations, to cross-check them. */
25
25
  obligationPackages?: unknown[];
26
+ /** Time to check a receipt's expires_at against (ISO 8601). Defaults to now. */
27
+ at?: string;
26
28
  }
27
29
  /** Detects the document type and verifies it offline: no network calls, no service access (acceptance 9). */
28
30
  export declare function verifySubledgerDocument(input: unknown, options: SubledgerVerifyOptions): SubledgerVerificationReport;
package/dist/verify.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { verifyClosurePackage } from "@atcn/core";
2
- import { ClosurePackageSchema, digestOf, verifyPayload } from "@atcn/schema";
2
+ import { ClosurePackageSchema, digestOf, executionBinding, resolveAttestations, verifyPayload } from "@atcn/schema";
3
3
  import { CLEARING_SOURCE, clearingFacts, settlementEvidence, undoneBatch } from "./bridge.js";
4
4
  import { CLOSURE_DOCUMENT_TYPE, RECEIPT_DOCUMENT_TYPE, SignedClosureSchema, SignedReceiptSchema, SIGNED_BY_HOSTED_SERVICE, SUBLEDGER_VERIFIER_VERSION, SUPPORTED_SUBLEDGER_SCHEMA_VERSIONS, } from "./documents.js";
5
- import { receiptTotals, rollupFor } from "./projection.js";
5
+ import { labelResponses, receiptTotals, responseAttestation, rollupFor } from "./projection.js";
6
6
  import { verifyCountersignature, verifyStatementSignature } from "./response.js";
7
7
  import { ATTESTABLE_FIELDS } from "./types.js";
8
8
  const SERVICE_ACTOR = "svc_atcn";
@@ -65,8 +65,9 @@ function unsupportedVersion(documentType, input) {
65
65
  const supported = SUPPORTED_SUBLEDGER_SCHEMA_VERSIONS;
66
66
  if (supported.includes(version))
67
67
  return null;
68
+ const versions = [...SUPPORTED_SUBLEDGER_SCHEMA_VERSIONS];
68
69
  const detail = `unsupported schema_version ${String(version)}: this verifier (@atcn/subledger ${SUBLEDGER_VERIFIER_VERSION}) supports ` +
69
- `${SUPPORTED_SUBLEDGER_SCHEMA_VERSIONS.join(" and ")}. Upgrade @atcn/verify-cli (or @atcn/subledger) to the minimum ` +
70
+ `${versions.slice(0, -1).join(", ")} and ${versions.at(-1)}. Upgrade @atcn/verify-cli (or @atcn/subledger) to the minimum ` +
70
71
  "version listed for this schema in packages/schema/COMPATIBILITY.md.";
71
72
  return { valid: false, document_type: documentType, unsupported_schema_version: String(version), checks: [check("schema_version", [detail])] };
72
73
  }
@@ -84,6 +85,24 @@ function versionFeatureProblems(version, signedBy, claims, hasObligationLinks) {
84
85
  problems.push(`schema 1.2 does not allow signed_by ${signedBy}`);
85
86
  return problems;
86
87
  }
88
+ const SCHEMA_1_4_STATEMENT_FIELDS = ["execution", "issued_at", "expires_at", "refs"];
89
+ const SCHEMA_1_4_LABELS = ["expired", "revoked"];
90
+ /** A document that declares 1.2 or 1.3 must not carry 1.4 fields, which those verifiers would drop before checking signatures. */
91
+ function schema14Problems(version, delegations, responses, claims) {
92
+ if (version !== "1.2" && version !== "1.3")
93
+ return [];
94
+ const problems = delegations.filter((d) => d.execution !== undefined).map((d) => `schema ${version} does not allow execution on delegation ${d.delegation_id}`);
95
+ for (const r of responses) {
96
+ for (const field of SCHEMA_1_4_STATEMENT_FIELDS)
97
+ if (r.statement[field] !== undefined)
98
+ problems.push(`schema ${version} does not allow statement ${field} (response ${r.response_id})`);
99
+ }
100
+ for (const item of [...responses, ...claims]) {
101
+ for (const label of item.assurance.filter((l) => SCHEMA_1_4_LABELS.includes(l)))
102
+ problems.push(`schema ${version} does not allow assurance ${label}`);
103
+ }
104
+ return problems;
105
+ }
87
106
  function reversalProblems(events) {
88
107
  const byId = new Map(events.map((e) => [e.financial_event_id, e]));
89
108
  const problems = [];
@@ -105,7 +124,10 @@ export function verifyReceipt(input, options) {
105
124
  return schemaFailure(RECEIPT_DOCUMENT_TYPE, parsed.error.issues);
106
125
  const doc = parsed.data;
107
126
  const r = doc.payload;
108
- const schemaProblems = versionFeatureProblems(r.schema_version, r.issuer.signed_by, r.delivery_claims, false);
127
+ const schemaProblems = [
128
+ ...versionFeatureProblems(r.schema_version, r.issuer.signed_by, r.delivery_claims, false),
129
+ ...schema14Problems(r.schema_version, [r.delegation], [], r.delivery_claims),
130
+ ];
109
131
  const checks = [check("schema", schemaProblems), signatureCheck(doc, r.issued_at, options.trustedKeys), operatorSignatureCheck(r, r.issuer.operator_id, doc.operator_signatures, options)];
110
132
  const events = r.financial_events.map(({ allocation_version: _version, ...e }) => ({ ...e, liability_owner: null, economic_event_id: null, fx: null }));
111
133
  checks.push(check("reversals", reversalProblems(events)));
@@ -120,8 +142,17 @@ export function verifyReceipt(input, options) {
120
142
  fieldProblems.push(`field_status is missing ${f}`);
121
143
  checks.push(check("field_disclosure", fieldProblems));
122
144
  checks.push(receiptChainCheck(r, options));
145
+ checks.push(receiptExpiryCheck(r, options.at ?? new Date().toISOString()));
123
146
  return finish(RECEIPT_DOCUMENT_TYPE, checks);
124
147
  }
148
+ /** The issuer signed expires_at, so a receipt past it no longer stands, even though its signature still verifies. */
149
+ function receiptExpiryCheck(r, at) {
150
+ if (r.expires_at === null)
151
+ return { name: "expiry", ok: true, details: ["no expiry"] };
152
+ if (Date.parse(at) >= Date.parse(r.expires_at))
153
+ return check("expiry", [`receipt expired at ${r.expires_at} (checked at ${at})`]);
154
+ return { name: "expiry", ok: true, details: [`valid until ${r.expires_at} (checked at ${at})`] };
155
+ }
125
156
  function receiptChainCheck(r, options) {
126
157
  if (r.revision === 1)
127
158
  return check("revision_chain", r.previous_receipt_digest === null && r.previous_receipt_id === null ? [] : ["revision 1 must not reference a previous receipt"]);
@@ -155,7 +186,10 @@ export function verifyClosure(input, options) {
155
186
  return schemaFailure(CLOSURE_DOCUMENT_TYPE, parsed.error.issues);
156
187
  const doc = parsed.data;
157
188
  const c = doc.payload;
158
- const schemaProblems = versionFeatureProblems(c.schema_version, c.issuer.signed_by, c.delivery_claims, c.obligation_links !== undefined);
189
+ const schemaProblems = [
190
+ ...versionFeatureProblems(c.schema_version, c.issuer.signed_by, c.delivery_claims, c.obligation_links !== undefined),
191
+ ...schema14Problems(c.schema_version, c.delegations, c.responses, c.delivery_claims),
192
+ ];
159
193
  const checks = [check("schema", schemaProblems), signatureCheck(doc, c.generated_at, options.trustedKeys), operatorSignatureCheck(c, c.issuer.operator_id, doc.operator_signatures, options)];
160
194
  const digestProblems = c.financial_events.filter((e) => digestOf(e.record) !== e.event_digest).map((e) => `event ${e.record.financial_event_id} digest mismatch`);
161
195
  const ids = c.financial_events.map((e) => e.record.financial_event_id);
@@ -167,7 +201,7 @@ export function verifyClosure(input, options) {
167
201
  checks.push(check("allocations", allocationProblems(c)));
168
202
  const recomputed = rollupFor(c.task, c.delegations, c.financial_events, c.allocations);
169
203
  checks.push(check("totals", digestOf(recomputed) === digestOf(c.rollup) ? [] : ["roll-up does not match events, attribution, and allocations"]));
170
- checks.push(check("provider_responses", responseProblems(c)));
204
+ checks.push(providerResponsesCheck(c));
171
205
  checks.push(closureChainCheck(c, options));
172
206
  checks.push(obligationLinkCheck(c, options));
173
207
  return finish(CLOSURE_DOCUMENT_TYPE, checks);
@@ -309,12 +343,39 @@ function allocationProblems(c) {
309
343
  }
310
344
  return problems;
311
345
  }
346
+ function providerResponsesCheck(c) {
347
+ const problems = responseProblems(c);
348
+ const notes = [];
349
+ const resolution = resolveAttestations(c.responses.map(responseAttestation), c.generated_at);
350
+ const responseIdOf = new Map(c.responses.map((r) => [r.statement_digest, r.response_id]));
351
+ for (const p of resolution.problems) {
352
+ const id = responseIdOf.get(p.digest);
353
+ if (p.code === "revocation_not_by_signer")
354
+ problems.push(`response ${id} revokes ${p.target}, which its provider key did not sign`);
355
+ else
356
+ notes.push(`response ${id} references ${p.target}, which is not in this closure`);
357
+ }
358
+ for (const r of c.responses) {
359
+ if (resolution.status[r.statement_digest].time === "not_yet_valid")
360
+ problems.push(`response ${r.response_id} was issued after the closure was generated`);
361
+ }
362
+ const expected = new Map(labelResponses(c.responses, c.generated_at).map((r) => [r.response_id, r.assurance]));
363
+ for (const r of c.responses) {
364
+ for (const label of SCHEMA_1_4_LABELS) {
365
+ const shouldHave = expected.get(r.response_id).includes(label);
366
+ if (shouldHave !== r.assurance.includes(label)) {
367
+ problems.push(`response ${r.response_id} ${shouldHave ? "lacks" : "carries"} assurance ${label}, which does not match its expiry and revocations at ${c.generated_at}`);
368
+ }
369
+ }
370
+ }
371
+ return problems.length > 0 ? check("provider_responses", problems) : { name: "provider_responses", ok: true, details: notes };
372
+ }
312
373
  function responseProblems(c) {
313
374
  const problems = [];
314
375
  const receipts = new Map(c.receipts.map((r) => [r.receipt_id, r]));
315
- const delegationIds = new Set(c.delegations.map((d) => d.delegation_id));
376
+ const delegations = new Map(c.delegations.map((d) => [d.delegation_id, d]));
316
377
  for (const r of c.receipts)
317
- if (!delegationIds.has(r.delegation_id))
378
+ if (!delegations.has(r.delegation_id))
318
379
  problems.push(`receipt ${r.receipt_id} covers a delegation outside the task`);
319
380
  for (const response of c.responses) {
320
381
  const receipt = receipts.get(response.receipt_id);
@@ -330,6 +391,17 @@ function responseProblems(c) {
330
391
  }
331
392
  if (s.issuer_operator_id !== c.issuer.operator_id)
332
393
  problems.push(`response ${response.response_id} names another issuer`);
394
+ if (s.issued_at === undefined && (s.expires_at !== undefined || s.refs !== undefined))
395
+ problems.push(`response ${response.response_id} needs issued_at with expires_at or refs`);
396
+ if (s.issued_at !== undefined && s.expires_at !== undefined && Date.parse(s.expires_at) <= Date.parse(s.issued_at))
397
+ problems.push(`response ${response.response_id} expires before it was issued`);
398
+ if (s.execution) {
399
+ const declared = delegations.get(receipt.delegation_id)?.execution;
400
+ if (!declared)
401
+ problems.push(`response ${response.response_id} cites run ${s.execution.execution_id}, but delegation ${receipt.delegation_id} records none`);
402
+ else if (digestOf(executionBinding(declared)) !== digestOf(s.execution))
403
+ problems.push(`response ${response.response_id} cites run ${s.execution.execution_id}, which is not the run recorded on delegation ${receipt.delegation_id}`);
404
+ }
333
405
  const claimsKeySigned = response.assurance.includes("provider_key_signed");
334
406
  if (!claimsKeySigned)
335
407
  continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atcn/subledger",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Agent Work Subledger: deterministic attribution, roll-up, exceptions, signed receipts and closures, and offline verification",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -33,8 +33,8 @@
33
33
  "build": "tsc -p tsconfig.build.json"
34
34
  },
35
35
  "dependencies": {
36
- "@atcn/core": "1.3.0",
37
- "@atcn/schema": "1.3.0",
36
+ "@atcn/core": "1.4.0",
37
+ "@atcn/schema": "1.4.0",
38
38
  "zod": "^4.1.0"
39
39
  }
40
40
  }
@@ -90,6 +90,63 @@
90
90
  "canonical": "{\"corrections\":[{\"field\":\"delivery.status\",\"proposed_value\":\"partial_completion\",\"reason\":\"file 3 missing\"}],\"document_type\":\"atcn.subledger.receipt_response\",\"evidence\":[{\"digest\":null,\"evidence_type\":\"delivery_log\",\"uri\":\"https://provider.example/delivery/7\"}],\"fields\":[],\"issuer_operator_id\":\"ten_01J00000000000000000000001\",\"note\":\"café: two of three files\",\"receipt_digest\":\"sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\"receipt_id\":\"rcp_01J00000000000000000000002\",\"receipt_revision\":1,\"response_type\":\"propose_correction\"}",
91
91
  "digest": "sha256:633530c26ed9133457be0a7d4a1417f24c73dc17fcbd20f58901cfb462390e15",
92
92
  "signature": "XKtJa41QABDVCDvyKIGqNejsQAvqHaKqh_yanIrNWPcehrnLCNW28L621ar__eHdqP2-64yvZnwbuJD0efi4Aw"
93
+ },
94
+ {
95
+ "input": {
96
+ "receipt": {
97
+ "receipt_id": "rcp_01J00000000000000000000003",
98
+ "digest": "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
99
+ "revision": 1,
100
+ "issuer_operator_id": "ten_01J00000000000000000000001"
101
+ },
102
+ "response_type": "signed_attestation",
103
+ "fields": [
104
+ "delivery.status"
105
+ ],
106
+ "execution": {
107
+ "execution_id": "run_01J00000000000000000000001",
108
+ "execution_digest": "sha256:9e282402ebfefeb4924e034733742b7cd346b022313e3e7f5b77d93651d11952"
109
+ },
110
+ "issued_at": "2026-10-01T00:00:00.000Z",
111
+ "expires_at": "2026-11-01T00:00:00.000Z",
112
+ "refs": [
113
+ {
114
+ "relation": "revokes",
115
+ "attestation_digest": "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
116
+ "reason": "attested the wrong run"
117
+ }
118
+ ]
119
+ },
120
+ "statement": {
121
+ "document_type": "atcn.subledger.receipt_response",
122
+ "receipt_id": "rcp_01J00000000000000000000003",
123
+ "receipt_digest": "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
124
+ "receipt_revision": 1,
125
+ "issuer_operator_id": "ten_01J00000000000000000000001",
126
+ "response_type": "signed_attestation",
127
+ "fields": [
128
+ "delivery.status"
129
+ ],
130
+ "note": null,
131
+ "evidence": [],
132
+ "corrections": [],
133
+ "execution": {
134
+ "execution_id": "run_01J00000000000000000000001",
135
+ "execution_digest": "sha256:9e282402ebfefeb4924e034733742b7cd346b022313e3e7f5b77d93651d11952"
136
+ },
137
+ "issued_at": "2026-10-01T00:00:00.000Z",
138
+ "expires_at": "2026-11-01T00:00:00.000Z",
139
+ "refs": [
140
+ {
141
+ "relation": "revokes",
142
+ "attestation_digest": "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
143
+ "reason": "attested the wrong run"
144
+ }
145
+ ]
146
+ },
147
+ "canonical": "{\"corrections\":[],\"document_type\":\"atcn.subledger.receipt_response\",\"evidence\":[],\"execution\":{\"execution_digest\":\"sha256:9e282402ebfefeb4924e034733742b7cd346b022313e3e7f5b77d93651d11952\",\"execution_id\":\"run_01J00000000000000000000001\"},\"expires_at\":\"2026-11-01T00:00:00.000Z\",\"fields\":[\"delivery.status\"],\"issued_at\":\"2026-10-01T00:00:00.000Z\",\"issuer_operator_id\":\"ten_01J00000000000000000000001\",\"note\":null,\"receipt_digest\":\"sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\",\"receipt_id\":\"rcp_01J00000000000000000000003\",\"receipt_revision\":1,\"refs\":[{\"attestation_digest\":\"sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\",\"reason\":\"attested the wrong run\",\"relation\":\"revokes\"}],\"response_type\":\"signed_attestation\"}",
148
+ "digest": "sha256:f4839d189a371531782b945d494462c209b57a9988344b149315d61772b3c81d",
149
+ "signature": "TgkbCF-2xoTAWDQJqGtiMMvQ26nliShYzU6mJbJhWD6Q-y35FlwNA9L4ijdne9whcouQCTxlI8sZIsR_KpJBCQ"
93
150
  }
94
151
  ],
95
152
  "countersignature": {
@@ -104,5 +161,33 @@
104
161
  }
105
162
  },
106
163
  "signature": "jUnhhTUE28I9wdyO15cFLm1aB9Lo-3r6d1cif7HPFLDIvLr8GngoKNCYtlTftNwxP1b7ARBUkwLga-PywmFtBA"
164
+ },
165
+ "execution_binding": {
166
+ "descriptor": {
167
+ "execution_id": "run_01J00000000000000000000001",
168
+ "protocol": {
169
+ "name": "a2a",
170
+ "task_id": "task-7",
171
+ "context_id": "ctx-7"
172
+ },
173
+ "agent": {
174
+ "agent_id": "agt_01J00000000000000000000002",
175
+ "agent_version": "2.1.0",
176
+ "card_digest": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
177
+ "model": {
178
+ "provider": "example",
179
+ "name": "coder",
180
+ "version": "2026-09"
181
+ }
182
+ },
183
+ "skill": {
184
+ "namespace": "a2a",
185
+ "skill_id": "code-fix"
186
+ }
187
+ },
188
+ "binding": {
189
+ "execution_id": "run_01J00000000000000000000001",
190
+ "execution_digest": "sha256:9e282402ebfefeb4924e034733742b7cd346b022313e3e7f5b77d93651d11952"
191
+ }
107
192
  }
108
193
  }