@openvtc/trust-tasks 0.12.17 → 0.13.1

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.
Files changed (37) hide show
  1. package/README.md +27 -3
  2. package/dist/_runtime/canonical.d.ts +40 -0
  3. package/dist/_runtime/canonical.d.ts.map +1 -0
  4. package/dist/_runtime/canonical.js +147 -0
  5. package/dist/_runtime/canonical.js.map +1 -0
  6. package/dist/_runtime/consume.d.ts +108 -2
  7. package/dist/_runtime/consume.d.ts.map +1 -1
  8. package/dist/_runtime/consume.js +174 -8
  9. package/dist/_runtime/consume.js.map +1 -1
  10. package/dist/_runtime/document.d.ts +17 -4
  11. package/dist/_runtime/document.d.ts.map +1 -1
  12. package/dist/_runtime/document.js +17 -4
  13. package/dist/_runtime/document.js.map +1 -1
  14. package/dist/_runtime/freshness.d.ts +105 -0
  15. package/dist/_runtime/freshness.d.ts.map +1 -0
  16. package/dist/_runtime/freshness.js +142 -0
  17. package/dist/_runtime/freshness.js.map +1 -0
  18. package/dist/_runtime/index.d.ts +4 -1
  19. package/dist/_runtime/index.d.ts.map +1 -1
  20. package/dist/_runtime/index.js +4 -1
  21. package/dist/_runtime/index.js.map +1 -1
  22. package/dist/_runtime/replay.d.ts +176 -0
  23. package/dist/_runtime/replay.d.ts.map +1 -0
  24. package/dist/_runtime/replay.js +147 -0
  25. package/dist/_runtime/replay.js.map +1 -0
  26. package/dist/keys/create/0.1/payload.d.ts +14 -0
  27. package/dist/keys/create/0.1/payload.d.ts.map +1 -1
  28. package/dist/keys/create/0.1/payload.js +5 -0
  29. package/dist/keys/create/0.1/payload.js.map +1 -1
  30. package/package.json +1 -1
  31. package/src/_runtime/canonical.ts +159 -0
  32. package/src/_runtime/consume.ts +267 -10
  33. package/src/_runtime/document.ts +17 -4
  34. package/src/_runtime/freshness.ts +183 -0
  35. package/src/_runtime/index.ts +30 -0
  36. package/src/_runtime/replay.ts +250 -0
  37. package/src/keys/create/0.1/payload.ts +9 -0
@@ -12,5 +12,8 @@
12
12
  export { TRUST_TASK_ERROR_TYPE_URI, enforceAudienceBinding, enforceSpecPolicy, rejectWith, rejectWithRecipient, respondWith, toErrorPayload, validateBasic, type ErrorPayload, type ErrorResponse, type InResponseTo, type Proof, type RejectReason, type SpecPolicy, type TrustTaskDocument, } from "./document.js";
13
13
  export { STANDARD_CODES, extendedCode, familyCode, isStandardCode, normalizeCode, slugFromTypeUri, type StandardCode, } from "./codes.js";
14
14
  export { StaticTransport, UnauthenticatedTransport, identityMismatchReason, reject, resolveParties, type ConsistencyError, type ResolvedParties, type TransportContext, type TransportHandler, } from "./transport.js";
15
- export { PROOF_NOT_ACCEPTED_BY_POLICY, consumeInbound, refuse, type ConsumeOptions, type ConsumeOutcome, type PayloadPolicy, type PayloadValidator, type ProofPolicy, type ProofVerifier, } from "./consume.js";
15
+ export { ID_CONFLICT_WIRE_MESSAGE, PROOF_INVALID_WIRE_MESSAGE, PROOF_NOT_ACCEPTED_BY_POLICY, REPLAY_RECORD_UNAVAILABLE, consequentialChecks, consumeInbound, notConsequentialChecks, refuse, type ConsumeChecks, type ConsumeOptions, type ConsumeOutcome, type PayloadPolicy, type PayloadValidator, type ProofPolicy, type ProofVerifier, } from "./consume.js";
16
+ export { canonicalJson, sha256Hex } from "./canonical.js";
17
+ export { CONSEQUENTIAL_FRESHNESS, DEFAULT_FRESHNESS, DEFAULT_MAX_AGE_MS, DEFAULT_SKEW_MS, EXPIRY_NOT_AFTER_ISSUANCE, FUTURE_ISSUED_AT, ISSUED_AT_REQUIRED, STALE_WIRE_MESSAGE, recordExpiry, validateFreshness, type FreshnessPolicy, } from "./freshness.js";
18
+ export { InMemoryReplayGuard, documentDigest, type ReplayGuard, type ReplayPolicy, type ReplayVerdict, } from "./replay.js";
16
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/_runtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACtB,iBAAiB,EACjB,UAAU,EACV,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,aAAa,EACb,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,iBAAiB,GACvB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,cAAc,EACd,YAAY,EACZ,UAAU,EACV,cAAc,EACd,aAAa,EACb,eAAe,EACf,KAAK,YAAY,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,sBAAsB,EACtB,MAAM,EACN,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,4BAA4B,EAC5B,cAAc,EACd,MAAM,EACN,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,aAAa,GACnB,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/_runtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACtB,iBAAiB,EACjB,UAAU,EACV,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,aAAa,EACb,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,iBAAiB,GACvB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,cAAc,EACd,YAAY,EACZ,UAAU,EACV,cAAc,EACd,aAAa,EACb,eAAe,EACf,KAAK,YAAY,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,sBAAsB,EACtB,MAAM,EACN,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,4BAA4B,EAC5B,yBAAyB,EACzB,mBAAmB,EACnB,cAAc,EACd,sBAAsB,EACtB,MAAM,EACN,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,aAAa,GACnB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE1D,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,yBAAyB,EACzB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,aAAa,GACnB,MAAM,aAAa,CAAC"}
@@ -12,5 +12,8 @@
12
12
  export { TRUST_TASK_ERROR_TYPE_URI, enforceAudienceBinding, enforceSpecPolicy, rejectWith, rejectWithRecipient, respondWith, toErrorPayload, validateBasic, } from "./document.js";
13
13
  export { STANDARD_CODES, extendedCode, familyCode, isStandardCode, normalizeCode, slugFromTypeUri, } from "./codes.js";
14
14
  export { StaticTransport, UnauthenticatedTransport, identityMismatchReason, reject, resolveParties, } from "./transport.js";
15
- export { PROOF_NOT_ACCEPTED_BY_POLICY, consumeInbound, refuse, } from "./consume.js";
15
+ export { ID_CONFLICT_WIRE_MESSAGE, PROOF_INVALID_WIRE_MESSAGE, PROOF_NOT_ACCEPTED_BY_POLICY, REPLAY_RECORD_UNAVAILABLE, consequentialChecks, consumeInbound, notConsequentialChecks, refuse, } from "./consume.js";
16
+ export { canonicalJson, sha256Hex } from "./canonical.js";
17
+ export { CONSEQUENTIAL_FRESHNESS, DEFAULT_FRESHNESS, DEFAULT_MAX_AGE_MS, DEFAULT_SKEW_MS, EXPIRY_NOT_AFTER_ISSUANCE, FUTURE_ISSUED_AT, ISSUED_AT_REQUIRED, STALE_WIRE_MESSAGE, recordExpiry, validateFreshness, } from "./freshness.js";
18
+ export { InMemoryReplayGuard, documentDigest, } from "./replay.js";
16
19
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/_runtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACtB,iBAAiB,EACjB,UAAU,EACV,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,aAAa,GAQd,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,cAAc,EACd,YAAY,EACZ,UAAU,EACV,cAAc,EACd,aAAa,EACb,eAAe,GAEhB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,sBAAsB,EACtB,MAAM,EACN,cAAc,GAKf,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,4BAA4B,EAC5B,cAAc,EACd,MAAM,GAOP,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/_runtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACtB,iBAAiB,EACjB,UAAU,EACV,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,aAAa,GAQd,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,cAAc,EACd,YAAY,EACZ,UAAU,EACV,cAAc,EACd,aAAa,EACb,eAAe,GAEhB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,sBAAsB,EACtB,MAAM,EACN,cAAc,GAKf,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,4BAA4B,EAC5B,yBAAyB,EACzB,mBAAmB,EACnB,cAAc,EACd,sBAAsB,EACtB,MAAM,GAQP,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE1D,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,yBAAyB,EACzB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,GAElB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,mBAAmB,EACnB,cAAc,GAIf,MAAM,aAAa,CAAC"}
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Duplicate-execution protection — SPEC §7.2 item 11, §8.4, §10.1.
3
+ *
4
+ * Mirrors `replay.rs` in trust-tasks-rs, check for check.
5
+ *
6
+ * # The rule
7
+ *
8
+ * §7.2 item 11 is normative and unconditional for a *consequential Trust
9
+ * Task*: once a consumer has accepted a document with a given `id` for
10
+ * execution, receiving that same document again **MUST NOT** cause the
11
+ * consequential effect a second time, and receiving a *different* document
12
+ * under the same `id` **MUST** be rejected with `idConflict`.
13
+ *
14
+ * §8.4 is the same mechanism from the producer's end: a retry is a bit-for-bit
15
+ * identical resend, and it is safe *precisely because* item 11 obliges the
16
+ * consumer to absorb it. Every transport binding in this repo delegates replay
17
+ * defence to the consumer — `bindings/https/0.2` §5 says "Freshness / replay:
18
+ * None", and the DIDComm and TSP bindings say the same — so if the consumer
19
+ * does not do it, nobody does, and an ordinary mediator redelivery grants an
20
+ * ACL entry twice by accident. §10.1: "The rule deliberately does not
21
+ * distinguish a hostile replay from a legitimate transport retry, because at
22
+ * the document layer the two are indistinguishable."
23
+ *
24
+ * # The key
25
+ *
26
+ * The `id` **alone** — "Transport request identifiers, transport message
27
+ * identifiers, and execution handles **MUST NOT** substitute" — plus a digest
28
+ * of the canonical serialization, because "an `id` alone cannot distinguish
29
+ * the retry it must absorb from the conflict it must reject".
30
+ *
31
+ * {@link documentDigest} hashes {@link canonicalJson} of the whole document
32
+ * rather than the octets as received: a re-indented body or a member order
33
+ * chosen by an intermediary would otherwise make a legitimate §8.4 retry look
34
+ * like a *different* document.
35
+ *
36
+ * The digest covers the **entire** document, `proof` included. That differs
37
+ * deliberately from the §4.9.3 *task digest*, computed over
38
+ * `JCS(document ∖ proof)`, and the spec spells the distinction out: "Item 11
39
+ * and §8.4 ask *which serialization arrived*, so a re-signed `proof` over
40
+ * identical content makes a different document — that is the `idConflict`
41
+ * case, and the distinction is the whole point of the rule."
42
+ */
43
+ import type { TrustTaskDocument } from "./document.js";
44
+ /**
45
+ * The content identity of a document, per SPEC §7.2's keying paragraph:
46
+ * SHA-256 over the canonical serialization of the whole document, as hex.
47
+ *
48
+ * Consumer-local. Never on the wire, and **not** the §4.9.3 task digest.
49
+ */
50
+ export declare function documentDigest<P>(doc: TrustTaskDocument<P>): string;
51
+ /** What a {@link ReplayGuard} says about a document offered for execution. */
52
+ export type ReplayVerdict =
53
+ /** Not seen before. The caller may execute. */
54
+ {
55
+ kind: "fresh";
56
+ }
57
+ /**
58
+ * Already accepted under the *same* digest — a §8.4 retry, or a replay. The
59
+ * caller **MUST NOT** execute again.
60
+ */
61
+ | {
62
+ kind: "duplicate";
63
+ /** The response the first execution produced, where one was retained. */
64
+ priorResponse?: unknown;
65
+ /** Whether that first execution is still running. */
66
+ inFlight: boolean;
67
+ }
68
+ /**
69
+ * Already accepted under a *different* digest. §7.2 item 11 requires
70
+ * `idConflict`, and requires that this not be treated as a retry.
71
+ */
72
+ | {
73
+ kind: "conflict";
74
+ };
75
+ /**
76
+ * The consumer-side record that makes SPEC §7.2 item 11 true.
77
+ *
78
+ * An interface, so a deployment can back it with Redis, Postgres, or anything
79
+ * that survives a process restart. {@link InMemoryReplayGuard} is the default
80
+ * and is correct for a single-process consumer; it is **not** correct behind a
81
+ * load balancer, where two replicas would each accept the same document once.
82
+ */
83
+ export interface ReplayGuard {
84
+ /**
85
+ * Claim `id` for execution on behalf of a document with identity `digest`.
86
+ *
87
+ * `retainUntil` is the instant past which the record may be dropped —
88
+ * {@link recordExpiry}, which SPEC §7.2 makes the same instant as the end of
89
+ * the consumer's willingness to execute the document. An implementation
90
+ * SHOULD treat a record whose `retainUntil` has passed as absent, so the key
91
+ * is released rather than conflicting forever with a document nobody would
92
+ * execute.
93
+ *
94
+ * Implementations **MUST** make claim-and-record atomic with respect to
95
+ * concurrent calls: two simultaneous deliveries of the same document must
96
+ * not both receive `fresh`. That is the whole guarantee.
97
+ *
98
+ * Throwing means the record could not be consulted. {@link consumeInbound}
99
+ * fails closed on that, mapping it to `unavailable` with `retryable: true` —
100
+ * a consumer that cannot establish whether a document is a duplicate has not
101
+ * satisfied item 11, and executing anyway is the double execution the rule
102
+ * forbids.
103
+ */
104
+ claim(id: string, digest: string, retainUntil: number | undefined, now: number): Promise<ReplayVerdict> | ReplayVerdict;
105
+ /**
106
+ * Attach the response a completed execution produced, so a later duplicate
107
+ * can be answered with it per §7.2 (*Disposition of a duplicate*) rather
108
+ * than merely absorbed in silence.
109
+ *
110
+ * Optional: a guard that records nothing still satisfies item 11 — the
111
+ * effect does not happen twice — and is the right shape for a
112
+ * fire-and-forget specification, which has no response to return.
113
+ */
114
+ recordResponse?(id: string, response: unknown): Promise<void> | void;
115
+ /**
116
+ * Release a claim whose execution is not to stand — for example a refusal
117
+ * the consumer marked `retryable`, where §8.4 has just invited the producer
118
+ * to re-send the same bytes. Without this, that invited retry would come
119
+ * back as an absorbed duplicate carrying the same failure forever.
120
+ */
121
+ release?(id: string, digest: string): Promise<void> | void;
122
+ }
123
+ /** How a consumer applies SPEC §7.2 item 11 in {@link consumeInbound}. */
124
+ export type ReplayPolicy =
125
+ /** Apply item 11 using this guard. Correct for any consequential spec. */
126
+ {
127
+ kind: "guard";
128
+ guard: ReplayGuard;
129
+ }
130
+ /**
131
+ * Keep no duplicate-execution record. Conformant **only** where the task is
132
+ * not consequential (§2), or where the specification "explicitly declares
133
+ * repeated execution safe and intended" — a property of the operation, not
134
+ * of the consumer's convenience.
135
+ */
136
+ | {
137
+ kind: "notConsequential";
138
+ };
139
+ /**
140
+ * A bounded, in-process {@link ReplayGuard}: an LRU map from `id` to the
141
+ * digest accepted under it, its retention deadline, and the response it
142
+ * produced.
143
+ *
144
+ * **Suitable when** one process is the sole consumer for the `recipient` VID
145
+ * it serves and losing the record on restart is acceptable.
146
+ *
147
+ * **Not suitable when** the consumer is replicated: two replicas hold separate
148
+ * maps, so a document accepted by replica A is `fresh` at replica B and the
149
+ * effect happens twice — the exact failure item 11 exists to prevent.
150
+ * Replicated deployments MUST back the guard with a shared store.
151
+ *
152
+ * Eviction is by capacity as well as by `retainUntil`: a burst of distinct
153
+ * documents can push an older record out before its deadline, and a replay
154
+ * arriving after that would be accepted. Size the capacity above the number of
155
+ * distinct documents the widest acceptance window can hold.
156
+ *
157
+ * `Map` preserves insertion order, which is what makes the LRU a delete-then-
158
+ * reinsert rather than a second index.
159
+ */
160
+ export declare class InMemoryReplayGuard implements ReplayGuard {
161
+ #private;
162
+ /**
163
+ * @param capacity Maximum records retained. Must be positive: a guard that
164
+ * retains nothing answers `fresh` to everything, which is a silent total
165
+ * defeat of item 11 rather than a visible misconfiguration.
166
+ */
167
+ constructor(capacity?: number);
168
+ /** Number of records currently retained. For tests and metrics. */
169
+ get size(): number;
170
+ /** Drop every record whose `retainUntil` has passed. */
171
+ purgeExpired(now: number): void;
172
+ claim(id: string, digest: string, retainUntil: number | undefined, now: number): ReplayVerdict;
173
+ recordResponse(id: string, response: unknown): void;
174
+ release(id: string, digest: string): void;
175
+ }
176
+ //# sourceMappingURL=replay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/_runtime/replay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,MAAM,CAEnE;AAED,8EAA8E;AAC9E,MAAM,MAAM,aAAa;AACvB,+CAA+C;AAC7C;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE;AACnB;;;GAGG;GACD;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,yEAAyE;IACzE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qDAAqD;IACrD,QAAQ,EAAE,OAAO,CAAC;CACnB;AACH;;;GAGG;GACD;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAEzB;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,KAAK,CACH,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,aAAa,CAAC,GAAG,aAAa,CAAC;IAE1C;;;;;;;;OAQG;IACH,cAAc,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAErE;;;;;OAKG;IACH,OAAO,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC5D;AAED,0EAA0E;AAC1E,MAAM,MAAM,YAAY;AACtB,0EAA0E;AACxE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE;AACvC;;;;;GAKG;GACD;IAAE,IAAI,EAAE,kBAAkB,CAAA;CAAE,CAAC;AASjC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,mBAAoB,YAAW,WAAW;;IAIrD;;;;OAIG;gBACS,QAAQ,SAAS;IAO7B,mEAAmE;IACnE,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,wDAAwD;IACxD,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAM/B,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,aAAa;IAgC9F,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI;IAOnD,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;CAS1C"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Duplicate-execution protection — SPEC §7.2 item 11, §8.4, §10.1.
3
+ *
4
+ * Mirrors `replay.rs` in trust-tasks-rs, check for check.
5
+ *
6
+ * # The rule
7
+ *
8
+ * §7.2 item 11 is normative and unconditional for a *consequential Trust
9
+ * Task*: once a consumer has accepted a document with a given `id` for
10
+ * execution, receiving that same document again **MUST NOT** cause the
11
+ * consequential effect a second time, and receiving a *different* document
12
+ * under the same `id` **MUST** be rejected with `idConflict`.
13
+ *
14
+ * §8.4 is the same mechanism from the producer's end: a retry is a bit-for-bit
15
+ * identical resend, and it is safe *precisely because* item 11 obliges the
16
+ * consumer to absorb it. Every transport binding in this repo delegates replay
17
+ * defence to the consumer — `bindings/https/0.2` §5 says "Freshness / replay:
18
+ * None", and the DIDComm and TSP bindings say the same — so if the consumer
19
+ * does not do it, nobody does, and an ordinary mediator redelivery grants an
20
+ * ACL entry twice by accident. §10.1: "The rule deliberately does not
21
+ * distinguish a hostile replay from a legitimate transport retry, because at
22
+ * the document layer the two are indistinguishable."
23
+ *
24
+ * # The key
25
+ *
26
+ * The `id` **alone** — "Transport request identifiers, transport message
27
+ * identifiers, and execution handles **MUST NOT** substitute" — plus a digest
28
+ * of the canonical serialization, because "an `id` alone cannot distinguish
29
+ * the retry it must absorb from the conflict it must reject".
30
+ *
31
+ * {@link documentDigest} hashes {@link canonicalJson} of the whole document
32
+ * rather than the octets as received: a re-indented body or a member order
33
+ * chosen by an intermediary would otherwise make a legitimate §8.4 retry look
34
+ * like a *different* document.
35
+ *
36
+ * The digest covers the **entire** document, `proof` included. That differs
37
+ * deliberately from the §4.9.3 *task digest*, computed over
38
+ * `JCS(document ∖ proof)`, and the spec spells the distinction out: "Item 11
39
+ * and §8.4 ask *which serialization arrived*, so a re-signed `proof` over
40
+ * identical content makes a different document — that is the `idConflict`
41
+ * case, and the distinction is the whole point of the rule."
42
+ */
43
+ import { canonicalJson, sha256Hex } from "./canonical.js";
44
+ /**
45
+ * The content identity of a document, per SPEC §7.2's keying paragraph:
46
+ * SHA-256 over the canonical serialization of the whole document, as hex.
47
+ *
48
+ * Consumer-local. Never on the wire, and **not** the §4.9.3 task digest.
49
+ */
50
+ export function documentDigest(doc) {
51
+ return sha256Hex(canonicalJson(doc));
52
+ }
53
+ /**
54
+ * A bounded, in-process {@link ReplayGuard}: an LRU map from `id` to the
55
+ * digest accepted under it, its retention deadline, and the response it
56
+ * produced.
57
+ *
58
+ * **Suitable when** one process is the sole consumer for the `recipient` VID
59
+ * it serves and losing the record on restart is acceptable.
60
+ *
61
+ * **Not suitable when** the consumer is replicated: two replicas hold separate
62
+ * maps, so a document accepted by replica A is `fresh` at replica B and the
63
+ * effect happens twice — the exact failure item 11 exists to prevent.
64
+ * Replicated deployments MUST back the guard with a shared store.
65
+ *
66
+ * Eviction is by capacity as well as by `retainUntil`: a burst of distinct
67
+ * documents can push an older record out before its deadline, and a replay
68
+ * arriving after that would be accepted. Size the capacity above the number of
69
+ * distinct documents the widest acceptance window can hold.
70
+ *
71
+ * `Map` preserves insertion order, which is what makes the LRU a delete-then-
72
+ * reinsert rather than a second index.
73
+ */
74
+ export class InMemoryReplayGuard {
75
+ #entries = new Map();
76
+ #capacity;
77
+ /**
78
+ * @param capacity Maximum records retained. Must be positive: a guard that
79
+ * retains nothing answers `fresh` to everything, which is a silent total
80
+ * defeat of item 11 rather than a visible misconfiguration.
81
+ */
82
+ constructor(capacity = 10_000) {
83
+ if (!Number.isInteger(capacity) || capacity < 1) {
84
+ throw new RangeError("InMemoryReplayGuard capacity must be a positive integer");
85
+ }
86
+ this.#capacity = capacity;
87
+ }
88
+ /** Number of records currently retained. For tests and metrics. */
89
+ get size() {
90
+ return this.#entries.size;
91
+ }
92
+ /** Drop every record whose `retainUntil` has passed. */
93
+ purgeExpired(now) {
94
+ for (const [id, entry] of this.#entries) {
95
+ if (entry.retainUntil !== undefined && entry.retainUntil <= now)
96
+ this.#entries.delete(id);
97
+ }
98
+ }
99
+ claim(id, digest, retainUntil, now) {
100
+ const existing = this.#entries.get(id);
101
+ // An expired record is treated as absent: the consumer would refuse the
102
+ // document under §7.2 item 4 or the acceptance window anyway, so holding
103
+ // the key would only manufacture a permanent `idConflict` for an `id`
104
+ // nobody can use.
105
+ if (existing !== undefined && existing.retainUntil !== undefined && existing.retainUntil <= now) {
106
+ this.#entries.delete(id);
107
+ }
108
+ else if (existing !== undefined) {
109
+ if (existing.digest !== digest) {
110
+ // A conflicting document is not a *use* of the record, so it does not
111
+ // refresh recency — otherwise a flood of conflicts could pin an entry
112
+ // and evict live ones.
113
+ return { kind: "conflict" };
114
+ }
115
+ this.#entries.delete(id);
116
+ this.#entries.set(id, existing);
117
+ return existing.response === undefined
118
+ ? { kind: "duplicate", inFlight: !existing.completed }
119
+ : { kind: "duplicate", priorResponse: existing.response, inFlight: !existing.completed };
120
+ }
121
+ this.#entries.set(id, { digest, retainUntil, response: undefined, completed: false });
122
+ while (this.#entries.size > this.#capacity) {
123
+ const oldest = this.#entries.keys().next();
124
+ if (oldest.done === true)
125
+ break;
126
+ this.#entries.delete(oldest.value);
127
+ }
128
+ return { kind: "fresh" };
129
+ }
130
+ recordResponse(id, response) {
131
+ const entry = this.#entries.get(id);
132
+ if (entry === undefined)
133
+ return;
134
+ entry.response = response;
135
+ entry.completed = true;
136
+ }
137
+ release(id, digest) {
138
+ const entry = this.#entries.get(id);
139
+ // Only release the claim this digest made, and only while it is
140
+ // unfinished: a concurrent arrival that legitimately holds the key must
141
+ // not have it taken away by another document's cleanup.
142
+ if (entry !== undefined && entry.digest === digest && !entry.completed) {
143
+ this.#entries.delete(id);
144
+ }
145
+ }
146
+ }
147
+ //# sourceMappingURL=replay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/_runtime/replay.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,10 @@ export interface KeysCreatePayload {
24
24
  * Hierarchical-deterministic path to derive at. Where the custodian derives from a seed, supplying the path makes the key reproducible from that seed; omitting it leaves the choice to the custodian. MUST NOT be combined with `internal: true`, which derives from no seed and records no path — a request carrying both is contradictory and the maintainer SHOULD reject it.
25
25
  */
26
26
  derivationPath?: string;
27
+ /**
28
+ * Durable identifier to give the new key. Where the maintainer derives from a seed it MAY default this to `derivationPath`, which is what makes the member optional for an ordinary create. It is **not** optional in practice for `internal: true`: such a key has no derivation path to be named after, so a maintainer that offers internal keys and receives no `keyId` has nothing to call the key and SHOULD reject the request. A maintainer MUST reject a `keyId` that collides with an existing key rather than overwrite it.
29
+ */
30
+ keyId?: string;
27
31
  /**
28
32
  * Absent is the same as `false`, and this member deliberately declares no JSON Schema `default`: a declared default is materialised by generated bindings, so an absent `internal` would reappear as an explicit `false` on re-serialisation and break round-trip idempotence for every existing request document. Request a key generated from the maintainer's CSPRNG rather than derived from a seed. Such a key is reproducible from nothing: it is not recoverable from a recovery phrase, and a maintainer offering it SHOULD exclude it from backup and export. A consumer asks for this when the key's value lies in being unexportable — the maintainer can sign with it and nothing can take it away — and accepts that losing the maintainer's storage destroys it permanently.
29
33
  *
@@ -137,6 +141,11 @@ export declare const PAYLOAD_SCHEMA: {
137
141
  readonly type: "string";
138
142
  readonly description: "Hierarchical-deterministic path to derive at. Where the custodian derives from a seed, supplying the path makes the key reproducible from that seed; omitting it leaves the choice to the custodian. MUST NOT be combined with `internal: true`, which derives from no seed and records no path — a request carrying both is contradictory and the maintainer SHOULD reject it.";
139
143
  };
144
+ readonly keyId: {
145
+ readonly type: "string";
146
+ readonly minLength: 1;
147
+ readonly description: "Durable identifier to give the new key. Where the maintainer derives from a seed it MAY default this to `derivationPath`, which is what makes the member optional for an ordinary create. It is **not** optional in practice for `internal: true`: such a key has no derivation path to be named after, so a maintainer that offers internal keys and receives no `keyId` has nothing to call the key and SHOULD reject the request. A maintainer MUST reject a `keyId` that collides with an existing key rather than overwrite it.";
148
+ };
140
149
  readonly internal: {
141
150
  readonly type: "boolean";
142
151
  readonly description: "Absent is the same as `false`, and this member deliberately declares no JSON Schema `default`: a declared default is materialised by generated bindings, so an absent `internal` would reappear as an explicit `false` on re-serialisation and break round-trip idempotence for every existing request document. Request a key generated from the maintainer's CSPRNG rather than derived from a seed. Such a key is reproducible from nothing: it is not recoverable from a recovery phrase, and a maintainer offering it SHOULD exclude it from backup and export. A consumer asks for this when the key's value lies in being unexportable — the maintainer can sign with it and nothing can take it away — and accepts that losing the maintainer's storage destroys it permanently.\n\nA maintainer that cannot mint such a key MUST reject the request rather than silently return a derived one, because the consumer's whole reason for asking is a property the derived key does not have. Consumers MUST confirm the outcome by reading `origin` on the returned record, which is `internal` iff the request was honoured; a maintainer that ignored an unrecognised member returns `derived`, and that difference is the consumer's only reliable signal.";
@@ -401,6 +410,11 @@ export declare const SPEC: {
401
410
  readonly type: "string";
402
411
  readonly description: "Hierarchical-deterministic path to derive at. Where the custodian derives from a seed, supplying the path makes the key reproducible from that seed; omitting it leaves the choice to the custodian. MUST NOT be combined with `internal: true`, which derives from no seed and records no path — a request carrying both is contradictory and the maintainer SHOULD reject it.";
403
412
  };
413
+ readonly keyId: {
414
+ readonly type: "string";
415
+ readonly minLength: 1;
416
+ readonly description: "Durable identifier to give the new key. Where the maintainer derives from a seed it MAY default this to `derivationPath`, which is what makes the member optional for an ordinary create. It is **not** optional in practice for `internal: true`: such a key has no derivation path to be named after, so a maintainer that offers internal keys and receives no `keyId` has nothing to call the key and SHOULD reject the request. A maintainer MUST reject a `keyId` that collides with an existing key rather than overwrite it.";
417
+ };
404
418
  readonly internal: {
405
419
  readonly type: "boolean";
406
420
  readonly description: "Absent is the same as `false`, and this member deliberately declares no JSON Schema `default`: a declared default is materialised by generated bindings, so an absent `internal` would reappear as an explicit `false` on re-serialisation and break round-trip idempotence for every existing request document. Request a key generated from the maintainer's CSPRNG rather than derived from a seed. Such a key is reproducible from nothing: it is not recoverable from a recovery phrase, and a maintainer offering it SHOULD exclude it from backup and export. A consumer asks for this when the key's value lies in being unexportable — the maintainer can sign with it and nothing can take it away — and accepts that losing the maintainer's storage destroys it permanently.\n\nA maintainer that cannot mint such a key MUST reject the request rather than silently return a derived one, because the consumer's whole reason for asking is a property the derived key does not have. Consumers MUST confirm the outcome by reading `origin` on the returned record, which is `internal` iff the request was honoured; a maintainer that ignored an unrecognised member returns `derived`, and that difference is the consumer's only reliable signal.";
@@ -1 +1 @@
1
- {"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../../../src/keys/create/0.1/payload.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../../../src/keys/create/0.1/payload.ts"],"names":[],"mappings":"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"}
@@ -33,6 +33,11 @@ export const PAYLOAD_SCHEMA = {
33
33
  "type": "string",
34
34
  "description": "Hierarchical-deterministic path to derive at. Where the custodian derives from a seed, supplying the path makes the key reproducible from that seed; omitting it leaves the choice to the custodian. MUST NOT be combined with `internal: true`, which derives from no seed and records no path — a request carrying both is contradictory and the maintainer SHOULD reject it."
35
35
  },
36
+ "keyId": {
37
+ "type": "string",
38
+ "minLength": 1,
39
+ "description": "Durable identifier to give the new key. Where the maintainer derives from a seed it MAY default this to `derivationPath`, which is what makes the member optional for an ordinary create. It is **not** optional in practice for `internal: true`: such a key has no derivation path to be named after, so a maintainer that offers internal keys and receives no `keyId` has nothing to call the key and SHOULD reject the request. A maintainer MUST reject a `keyId` that collides with an existing key rather than overwrite it."
40
+ },
36
41
  "internal": {
37
42
  "type": "boolean",
38
43
  "description": "Absent is the same as `false`, and this member deliberately declares no JSON Schema `default`: a declared default is materialised by generated bindings, so an absent `internal` would reappear as an explicit `false` on re-serialisation and break round-trip idempotence for every existing request document. Request a key generated from the maintainer's CSPRNG rather than derived from a seed. Such a key is reproducible from nothing: it is not recoverable from a recovery phrase, and a maintainer offering it SHOULD exclude it from backup and export. A consumer asks for this when the key's value lies in being unexportable — the maintainer can sign with it and nothing can take it away — and accepts that losing the maintainer's storage destroys it permanently.\n\nA maintainer that cannot mint such a key MUST reject the request rather than silently return a derived one, because the consumer's whole reason for asking is a property the derived key does not have. Consumers MUST confirm the outcome by reading `origin` on the returned record, which is `internal` iff the request was honoured; a maintainer that ignored an unrecognised member returns `derived`, and that difference is the consumer's only reliable signal."
@@ -1 +1 @@
1
- {"version":3,"file":"payload.js","sourceRoot":"","sources":["../../../../src/keys/create/0.1/payload.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA0GH,2BAA2B;AAC3B,MAAM,CAAC,MAAM,QAAQ,GAAG,6CAAsD,CAAC;AAK/E,qEAAqE;AACrE,MAAM,CAAC,MAAM,iBAAiB,GAAG,sDAA+D,CAAC;AAKjG;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,SAAS,EAAE,8CAA8C;IACzD,KAAK,EAAE,6CAA6C;IACpD,OAAO,EAAE,uBAAuB;IAChC,MAAM,EAAE,QAAQ;IAChB,sBAAsB,EAAE,KAAK;IAC7B,UAAU,EAAE;QACV,SAAS;KACV;IACD,YAAY,EAAE;QACZ,SAAS,EAAE;YACT,MAAM,EAAE,iBAAiB;YACzB,aAAa,EAAE,wBAAwB;SACxC;QACD,gBAAgB,EAAE;YAChB,MAAM,EAAE,QAAQ;YAChB,aAAa,EAAE,iXAAiX;SACjY;QACD,UAAU,EAAE;YACV,MAAM,EAAE,SAAS;YACjB,aAAa,EAAE,ssCAAssC;SACttC;QACD,UAAU,EAAE;YACV,MAAM,EAAE,QAAQ;YAChB,aAAa,EAAE,scAAsc;SACtd;QACD,OAAO,EAAE;YACP,MAAM,EAAE,QAAQ;YAChB,aAAa,EAAE,yDAAyD;SACzE;QACD,WAAW,EAAE;YACX,MAAM,EAAE,QAAQ;YAChB,aAAa,EAAE,iHAAiH;SACjI;QACD,KAAK,EAAE;YACL,MAAM,EAAE,aAAa;YACrB,aAAa,EAAE,yDAAyD;SACzE;KACF;IACD,OAAO,EAAE;QACP,UAAU,EAAE;YACV,SAAS,EAAE,UAAU;YACrB,OAAO,EAAE,gCAAgC;YACzC,aAAa,EAAE,yLAAyL;YACxM,MAAM,EAAE,QAAQ;YAChB,sBAAsB,EAAE,KAAK;YAC7B,UAAU,EAAE;gBACV,KAAK;aACN;YACD,YAAY,EAAE;gBACZ,KAAK,EAAE;oBACL,MAAM,EAAE,mBAAmB;oBAC3B,aAAa,EAAE,oFAAoF;iBACpG;gBACD,KAAK,EAAE;oBACL,MAAM,EAAE,aAAa;iBACtB;aACF;SACF;QACD,KAAK,EAAE;YACL,OAAO,EAAE,KAAK;YACd,aAAa,EAAE,uKAAuK;YACtL,MAAM,EAAE,QAAQ;YAChB,eAAe,EAAE,CAAC;YAClB,sBAAsB,EAAE,IAAI;YAC5B,eAAe,EAAE;gBACf,SAAS,EAAE,mCAAmC;aAC/C;SACF;QACD,WAAW,EAAE;YACX,OAAO,EAAE,WAAW;YACpB,MAAM,EAAE,QAAQ;YAChB,sBAAsB,EAAE,KAAK;YAC7B,UAAU,EAAE;gBACV,OAAO;gBACP,SAAS;gBACT,QAAQ;gBACR,WAAW;gBACX,WAAW;aACZ;YACD,YAAY,EAAE;gBACZ,OAAO,EAAE;oBACP,MAAM,EAAE,QAAQ;oBAChB,WAAW,EAAE,CAAC;oBACd,aAAa,EAAE,mHAAmH;iBACnI;gBACD,SAAS,EAAE;oBACT,MAAM,EAAE,iBAAiB;iBAC1B;gBACD,QAAQ,EAAE;oBACR,MAAM,EAAE,mBAAmB;iBAC5B;gBACD,WAAW,EAAE;oBACX,MAAM,EAAE,QAAQ;oBAChB,WAAW,EAAE,CAAC;oBACd,aAAa,EAAE,+FAA+F;iBAC/G;gBACD,gBAAgB,EAAE;oBAChB,MAAM,EAAE,QAAQ;oBAChB,aAAa,EAAE,mIAAmI;iBACnJ;gBACD,QAAQ,EAAE;oBACR,MAAM,EAAE,SAAS;oBACjB,SAAS,EAAE,CAAC;oBACZ,aAAa,EAAE,qHAAqH;iBACrI;gBACD,QAAQ,EAAE;oBACR,MAAM,EAAE,mBAAmB;iBAC5B;gBACD,OAAO,EAAE;oBACP,MAAM,EAAE,QAAQ;oBAChB,aAAa,EAAE,wFAAwF;iBACxG;gBACD,WAAW,EAAE;oBACX,MAAM,EAAE,QAAQ;oBAChB,aAAa,EAAE,kRAAkR;iBAClS;gBACD,WAAW,EAAE;oBACX,MAAM,EAAE,QAAQ;oBAChB,QAAQ,EAAE,WAAW;oBACrB,aAAa,EAAE,8DAA8D;iBAC9E;gBACD,WAAW,EAAE;oBACX,MAAM,EAAE,QAAQ;oBAChB,QAAQ,EAAE,WAAW;oBACrB,aAAa,EAAE,2EAA2E;iBAC3F;gBACD,KAAK,EAAE;oBACL,MAAM,EAAE,aAAa;iBACtB;aACF;SACF;QACD,WAAW,EAAE;YACX,OAAO,EAAE,WAAW;YACpB,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE;gBACN,SAAS;gBACT,UAAU;gBACV,UAAU;aACX;YACD,aAAa,EAAE,8wBAA8wB;YAC7xB,SAAS,EAAE,SAAS;SACrB;QACD,WAAW,EAAE;YACX,OAAO,EAAE,WAAW;YACpB,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE;gBACN,QAAQ;gBACR,SAAS;aACV;YACD,aAAa,EAAE,+KAA+K;SAC/L;QACD,SAAS,EAAE;YACT,OAAO,EAAE,SAAS;YAClB,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE;gBACN,SAAS;gBACT,QAAQ;gBACR,MAAM;aACP;YACD,aAAa,EAAE,sJAAsJ;SACtK;KACF;CACO,CAAC;AAEX,mEAAmE;AACnE,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,SAAS,EAAE,8CAA8C;IACzD,MAAM,EAAE,kBAAkB;IAC1B,OAAO,EAAE;QACP,UAAU,EAAE;YACV,SAAS,EAAE,UAAU;YACrB,OAAO,EAAE,gCAAgC;YACzC,aAAa,EAAE,yLAAyL;YACxM,MAAM,EAAE,QAAQ;YAChB,sBAAsB,EAAE,KAAK;YAC7B,UAAU,EAAE;gBACV,KAAK;aACN;YACD,YAAY,EAAE;gBACZ,KAAK,EAAE;oBACL,MAAM,EAAE,mBAAmB;oBAC3B,aAAa,EAAE,oFAAoF;iBACpG;gBACD,KAAK,EAAE;oBACL,MAAM,EAAE,aAAa;iBACtB;aACF;SACF;QACD,KAAK,EAAE;YACL,OAAO,EAAE,KAAK;YACd,aAAa,EAAE,uKAAuK;YACtL,MAAM,EAAE,QAAQ;YAChB,eAAe,EAAE,CAAC;YAClB,sBAAsB,EAAE,IAAI;YAC5B,eAAe,EAAE;gBACf,SAAS,EAAE,mCAAmC;aAC/C;SACF;QACD,WAAW,EAAE;YACX,OAAO,EAAE,WAAW;YACpB,MAAM,EAAE,QAAQ;YAChB,sBAAsB,EAAE,KAAK;YAC7B,UAAU,EAAE;gBACV,OAAO;gBACP,SAAS;gBACT,QAAQ;gBACR,WAAW;gBACX,WAAW;aACZ;YACD,YAAY,EAAE;gBACZ,OAAO,EAAE;oBACP,MAAM,EAAE,QAAQ;oBAChB,WAAW,EAAE,CAAC;oBACd,aAAa,EAAE,mHAAmH;iBACnI;gBACD,SAAS,EAAE;oBACT,MAAM,EAAE,iBAAiB;iBAC1B;gBACD,QAAQ,EAAE;oBACR,MAAM,EAAE,mBAAmB;iBAC5B;gBACD,WAAW,EAAE;oBACX,MAAM,EAAE,QAAQ;oBAChB,WAAW,EAAE,CAAC;oBACd,aAAa,EAAE,+FAA+F;iBAC/G;gBACD,gBAAgB,EAAE;oBAChB,MAAM,EAAE,QAAQ;oBAChB,aAAa,EAAE,mIAAmI;iBACnJ;gBACD,QAAQ,EAAE;oBACR,MAAM,EAAE,SAAS;oBACjB,SAAS,EAAE,CAAC;oBACZ,aAAa,EAAE,qHAAqH;iBACrI;gBACD,QAAQ,EAAE;oBACR,MAAM,EAAE,mBAAmB;iBAC5B;gBACD,OAAO,EAAE;oBACP,MAAM,EAAE,QAAQ;oBAChB,aAAa,EAAE,wFAAwF;iBACxG;gBACD,WAAW,EAAE;oBACX,MAAM,EAAE,QAAQ;oBAChB,aAAa,EAAE,kRAAkR;iBAClS;gBACD,WAAW,EAAE;oBACX,MAAM,EAAE,QAAQ;oBAChB,QAAQ,EAAE,WAAW;oBACrB,aAAa,EAAE,8DAA8D;iBAC9E;gBACD,WAAW,EAAE;oBACX,MAAM,EAAE,QAAQ;oBAChB,QAAQ,EAAE,WAAW;oBACrB,aAAa,EAAE,2EAA2E;iBAC3F;gBACD,KAAK,EAAE;oBACL,MAAM,EAAE,aAAa;iBACtB;aACF;SACF;QACD,WAAW,EAAE;YACX,OAAO,EAAE,WAAW;YACpB,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE;gBACN,SAAS;gBACT,UAAU;gBACV,UAAU;aACX;YACD,aAAa,EAAE,8wBAA8wB;YAC7xB,SAAS,EAAE,SAAS;SACrB;QACD,WAAW,EAAE;YACX,OAAO,EAAE,WAAW;YACpB,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE;gBACN,QAAQ;gBACR,SAAS;aACV;YACD,aAAa,EAAE,+KAA+K;SAC/L;QACD,SAAS,EAAE;YACT,OAAO,EAAE,SAAS;YAClB,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE;gBACN,SAAS;gBACT,QAAQ;gBACR,MAAM;aACP;YACD,aAAa,EAAE,sJAAsJ;SACtK;KACF;CACO,CAAC;AAEX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,OAAO,EAAE,QAAQ;IACjB,QAAQ,EAAE,KAAK;IACf,eAAe,EAAE,IAAI;IACrB,mBAAmB,EAAE,IAAI;IACzB,aAAa,EAAE,cAAc;CACrB,CAAC;AAEX;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,OAAO,EAAE,iBAAiB;IAC1B,QAAQ,EAAE,KAAK;IACf,eAAe,EAAE,IAAI;IACrB,mBAAmB,EAAE,IAAI;IACzB,aAAa,EAAE,uBAAuB;CAC9B,CAAC"}
1
+ {"version":3,"file":"payload.js","sourceRoot":"","sources":["../../../../src/keys/create/0.1/payload.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openvtc/trust-tasks",
3
- "version": "0.12.17",
3
+ "version": "0.13.1",
4
4
  "description": "Generated TypeScript bindings for the Trust Tasks framework registry.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Deterministic document serialization and the SHA-256 digest over it.
3
+ *
4
+ * Mirrors `canonical.rs` in trust-tasks-rs. SPEC §7.2 (*Keying and comparison
5
+ * for item 11*) defines two documents sharing an `id` as **the same document**
6
+ * when their serializations are identical under RFC 8785 canonicalization —
7
+ * the same identity §8.4 gives a retry. A consumer implementing item 11 has to
8
+ * retain a digest of what it accepted, not merely the `id`.
9
+ *
10
+ * `canonicalJson` here is closer to literal RFC 8785 than the Rust side is,
11
+ * because JavaScript's own primitives are what JCS was specified against:
12
+ * `Array.prototype.sort()` orders by UTF-16 code unit, and `JSON.stringify`
13
+ * formats numbers with `Number::toString` and escapes strings with exactly the
14
+ * §3.2.2.2 escape set. The only thing this adds is recursive member ordering.
15
+ *
16
+ * The item-11 digest is **consumer-local**: it goes into this consumer's own
17
+ * replay record and never onto the wire, into a citation, or into a proof. It
18
+ * is *not* the §4.9.3 task digest, which is computed over `document ∖ proof`
19
+ * and is a published, multibase-encoded multihash. See `replay.ts`.
20
+ *
21
+ * Hand-written, and dependency-free on purpose: this package ships no runtime
22
+ * dependencies, and `node:crypto` would not resolve in a browser or a worker.
23
+ */
24
+
25
+ /**
26
+ * Serialize `value` with object members recursively ordered and no
27
+ * insignificant whitespace.
28
+ *
29
+ * `undefined` members are omitted, as `JSON.stringify` omits them — which is
30
+ * what makes this agree with the document as it would be sent.
31
+ */
32
+ export function canonicalJson(value: unknown): string {
33
+ if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "null";
34
+ if (Array.isArray(value)) return `[${value.map((v) => canonicalJson(v)).join(",")}]`;
35
+
36
+ const entries = Object.entries(value as Record<string, unknown>)
37
+ .filter(([, v]) => v !== undefined)
38
+ // RFC 8785 §3.2.3: sort by UTF-16 code unit, which is what the default
39
+ // comparator does after String() — and these are already strings.
40
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
41
+
42
+ return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson(v)}`).join(",")}}`;
43
+ }
44
+
45
+ const K = new Uint32Array([
46
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
47
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
48
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
49
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
50
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
51
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
52
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
53
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
54
+ ]);
55
+
56
+ const rotr = (x: number, n: number): number => (x >>> n) | (x << (32 - n));
57
+
58
+ /**
59
+ * UTF-8 encode `s`, without `TextEncoder`.
60
+ *
61
+ * `TextEncoder` is a host global, not an ES2022 one: this package's `lib` is
62
+ * `["ES2022"]` and adding `DOM` to reach one name would pull the whole browser
63
+ * surface into a package that must also typecheck for Node and for workers.
64
+ * Fifteen lines is the cheaper price.
65
+ *
66
+ * Unpaired surrogates — which `JSON.parse` will produce from a `\uD800` escape
67
+ * — encode as U+FFFD, matching `TextEncoder`. Two documents differing only in
68
+ * an unpaired surrogate would therefore collide; they are not valid JSON text
69
+ * to begin with, and the collision absorbs a duplicate rather than executing
70
+ * one, so it fails safe.
71
+ */
72
+ function utf8(s: string): Uint8Array {
73
+ const out: number[] = [];
74
+ for (let i = 0; i < s.length; i++) {
75
+ let cp = s.charCodeAt(i);
76
+ if (cp >= 0xd800 && cp <= 0xdbff && i + 1 < s.length) {
77
+ const low = s.charCodeAt(i + 1);
78
+ if (low >= 0xdc00 && low <= 0xdfff) {
79
+ cp = 0x10000 + ((cp - 0xd800) << 10) + (low - 0xdc00);
80
+ i++;
81
+ }
82
+ }
83
+ if (cp >= 0xd800 && cp <= 0xdfff) cp = 0xfffd; // unpaired surrogate
84
+
85
+ if (cp < 0x80) out.push(cp);
86
+ else if (cp < 0x800) out.push(0xc0 | (cp >> 6), 0x80 | (cp & 0x3f));
87
+ else if (cp < 0x10000)
88
+ out.push(0xe0 | (cp >> 12), 0x80 | ((cp >> 6) & 0x3f), 0x80 | (cp & 0x3f));
89
+ else
90
+ out.push(
91
+ 0xf0 | (cp >> 18),
92
+ 0x80 | ((cp >> 12) & 0x3f),
93
+ 0x80 | ((cp >> 6) & 0x3f),
94
+ 0x80 | (cp & 0x3f),
95
+ );
96
+ }
97
+ return Uint8Array.from(out);
98
+ }
99
+
100
+ /**
101
+ * FIPS 180-4 SHA-256 over the UTF-8 encoding of `input`, as lowercase hex.
102
+ *
103
+ * Synchronous by necessity: `crypto.subtle.digest` is a Promise, and the
104
+ * consume pipeline needs the digest before it decides whether to await
105
+ * anything. Pinned to the standard's published vectors in `test/`.
106
+ */
107
+ export function sha256Hex(input: string): string {
108
+ const bytes = utf8(input);
109
+ const bitLen = bytes.length * 8;
110
+
111
+ // Pad to a multiple of 64 bytes: 0x80, zeroes, then the 64-bit big-endian
112
+ // bit length.
113
+ const padded = new Uint8Array(Math.ceil((bytes.length + 9) / 64) * 64);
114
+ padded.set(bytes);
115
+ padded[bytes.length] = 0x80;
116
+ const view = new DataView(padded.buffer);
117
+ // Lengths above 2^53 bits are unreachable from a JS string; the high word is
118
+ // written anyway so the padding is well-formed.
119
+ view.setUint32(padded.length - 8, Math.floor(bitLen / 0x100000000), false);
120
+ view.setUint32(padded.length - 4, bitLen >>> 0, false);
121
+
122
+ const h = new Uint32Array([
123
+ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
124
+ ]);
125
+ const w = new Uint32Array(64);
126
+
127
+ for (let offset = 0; offset < padded.length; offset += 64) {
128
+ for (let i = 0; i < 16; i++) w[i] = view.getUint32(offset + i * 4, false);
129
+ for (let i = 16; i < 64; i++) {
130
+ const s0 = rotr(w[i - 15]!, 7) ^ rotr(w[i - 15]!, 18) ^ (w[i - 15]! >>> 3);
131
+ const s1 = rotr(w[i - 2]!, 17) ^ rotr(w[i - 2]!, 19) ^ (w[i - 2]! >>> 10);
132
+ w[i] = (w[i - 16]! + s0 + w[i - 7]! + s1) >>> 0;
133
+ }
134
+
135
+ let [a, b, c, d, e, f, g, hh] = [h[0]!, h[1]!, h[2]!, h[3]!, h[4]!, h[5]!, h[6]!, h[7]!];
136
+ for (let i = 0; i < 64; i++) {
137
+ const s1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
138
+ const ch = (e & f) ^ (~e & g);
139
+ const temp1 = (hh + s1 + ch + K[i]! + w[i]!) >>> 0;
140
+ const s0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
141
+ const maj = (a & b) ^ (a & c) ^ (b & c);
142
+ const temp2 = (s0 + maj) >>> 0;
143
+
144
+ hh = g;
145
+ g = f;
146
+ f = e;
147
+ e = (d + temp1) >>> 0;
148
+ d = c;
149
+ c = b;
150
+ b = a;
151
+ a = (temp1 + temp2) >>> 0;
152
+ }
153
+
154
+ const next = [a, b, c, d, e, f, g, hh];
155
+ for (let i = 0; i < 8; i++) h[i] = (h[i]! + next[i]!) >>> 0;
156
+ }
157
+
158
+ return Array.from(h, (word) => word.toString(16).padStart(8, "0")).join("");
159
+ }