@cello-protocol/protocol-types 0.0.21 → 0.0.23

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 (57) hide show
  1. package/dist/cbor.d.ts +25 -0
  2. package/dist/cbor.d.ts.map +1 -0
  3. package/dist/cbor.js +51 -0
  4. package/dist/cbor.js.map +1 -0
  5. package/dist/connection-package.d.ts +4 -0
  6. package/dist/connection-package.d.ts.map +1 -1
  7. package/dist/connection-package.js +5 -6
  8. package/dist/connection-package.js.map +1 -1
  9. package/dist/index.d.ts +5 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +7 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/limits.d.ts +10 -0
  14. package/dist/limits.d.ts.map +1 -0
  15. package/dist/limits.js +10 -0
  16. package/dist/limits.js.map +1 -0
  17. package/dist/manifest.d.ts +2 -4
  18. package/dist/manifest.d.ts.map +1 -1
  19. package/dist/manifest.js +2 -4
  20. package/dist/manifest.js.map +1 -1
  21. package/dist/primary-transfer.d.ts +6 -8
  22. package/dist/primary-transfer.d.ts.map +1 -1
  23. package/dist/primary-transfer.js +18 -13
  24. package/dist/primary-transfer.js.map +1 -1
  25. package/dist/revocation.d.ts.map +1 -1
  26. package/dist/revocation.js +2 -5
  27. package/dist/revocation.js.map +1 -1
  28. package/dist/session-liveness.js +4 -4
  29. package/dist/session-liveness.js.map +1 -1
  30. package/dist/session.d.ts +26 -61
  31. package/dist/session.d.ts.map +1 -1
  32. package/dist/session.js +22 -54
  33. package/dist/session.js.map +1 -1
  34. package/dist/structure1.d.ts +16 -0
  35. package/dist/structure1.d.ts.map +1 -0
  36. package/dist/structure1.js +33 -0
  37. package/dist/structure1.js.map +1 -0
  38. package/dist/structure2.d.ts.map +1 -1
  39. package/dist/structure2.js +7 -8
  40. package/dist/structure2.js.map +1 -1
  41. package/dist/trust-signal.d.ts +94 -0
  42. package/dist/trust-signal.d.ts.map +1 -0
  43. package/dist/trust-signal.js +252 -0
  44. package/dist/trust-signal.js.map +1 -0
  45. package/package.json +6 -3
  46. package/test/vectors/connection-package-canonical.json +10 -0
  47. package/test/vectors/envelope-v1-canonical.json +16 -0
  48. package/test/vectors/genesis-prev-root.json +53 -0
  49. package/test/vectors/scan-result-unscanned.json +5 -0
  50. package/test/vectors/structure1-canonical.json +13 -0
  51. package/test/vectors/structure2-canonical.json +12 -0
  52. package/test/vectors/tbs-v0-canonical.json +8 -0
  53. package/test/vectors/trust-signal-envelope-canonical.json +136 -0
  54. package/dist/envelope.d.ts +0 -170
  55. package/dist/envelope.d.ts.map +0 -1
  56. package/dist/envelope.js +0 -776
  57. package/dist/envelope.js.map +0 -1
package/dist/session.d.ts CHANGED
@@ -1,13 +1,14 @@
1
1
  /**
2
- * CELLO-SESSION-002/MSG-004/SESSION-003/SESSION-004/SESSION-005 — session.ts
2
+ * session.ts — session wire types and their to-be-signed encodings.
3
3
  *
4
4
  * SessionAssignment: shared wire type used by directory (sender), client (receiver),
5
5
  * and relay (verifier). Lives here so client can import it without touching @cello-protocol/directory.
6
6
  *
7
- * SESSION-004 additions to SessionAssignment:
7
+ * SessionAssignment is a discriminated union on `signature_type`, so TypeScript enforces that
8
+ * `signer_pubkey` is present exactly when the signature is FROST:
8
9
  * signature_type: 'frost' | 'single'
9
10
  * - 'frost': the directory_signature field carries the 64-byte combined FROST output
10
- * - 'single': M1-era single-key directory signature (refused by M2 clients)
11
+ * - 'single': legacy single-key directory signature (refused by current clients)
11
12
  * signer_pubkey?: Uint8Array (32 bytes, present when signature_type === 'frost')
12
13
  * - The initiator's primary_pubkey (group FROST key). Embedded so the counterparty
13
14
  * can verify without a separate directory round-trip.
@@ -19,11 +20,11 @@
19
20
  * Note: signer_pubkey is NOT in the TBS — it is derived from DKG and embedded in the frame.
20
21
  *
21
22
  * SealPayload: canonical CBOR of [session_id, final_root, close_timestamp, "PENDING"].
22
- * Per SESSION-003. content_hash = SHA-256(0x00 || SealPayload) per MERKLE-001.
23
+ * content_hash = SHA-256(0x00 || SealPayload).
23
24
  *
24
25
  * computeGenesisPrevRoot: deterministic genesis prev_root for a two-party session.
25
26
  *
26
- * Formula (SI-004):
27
+ * Formula:
27
28
  * SHA-256(min(A_pubkey, B_pubkey) || max(A_pubkey, B_pubkey) || session_id || timestamp_be8)
28
29
  *
29
30
  * Pubkeys are sorted bytewise-lexicographically (Buffer.compare).
@@ -31,46 +32,13 @@
31
32
  * (milliseconds since Unix epoch). Raw byte concatenation — no CBOR at this boundary,
32
33
  * which would introduce width ambiguity on the timestamp encoding.
33
34
  *
34
- * Per FIPS 180-4 (SHA-256) and SESSION-002 SI-004.
35
+ * Per FIPS 180-4 (SHA-256).
35
36
  *
36
- * ─── Phase P: SESSION-004 Pseudocode ─────────────────────────────────────────
37
+ * buildSessionEstablishmentTbs is exported from protocol-types so that BOTH the directory
38
+ * (signer) and the client (verifier) use identical canonical CBOR encoding. Any encoding
39
+ * drift causes silent verification failures.
37
40
  *
38
- * SessionAssignment type changes (MEDIUM-6: discriminated union enforces signer_pubkey):
39
- * // Use a discriminated union so TypeScript enforces signer_pubkey is present for 'frost'
40
- * type SessionAssignmentFrost = { ...common fields..., signature_type: 'frost', signer_pubkey: Uint8Array }
41
- * type SessionAssignmentSingle = { ...common fields..., signature_type: 'single' }
42
- * type SessionAssignment = SessionAssignmentFrost | SessionAssignmentSingle
43
- *
44
- * // Common fields (all existing SessionAssignment fields plus signature_type + signer_pubkey):
45
- * session_id, participant_a, participant_b, relay_endpoint, directory_endpoint,
46
- * session_timestamp, directory_pubkey, directory_signature
47
- *
48
- * buildSessionEstablishmentTbs(sessionId, pubA, pubB, genesisPrevRoot, timestamp):
49
- * // HIGH-5: exported from protocol-types so both directory and client use identical CBOR encoding
50
- * // Any encoding drift would cause silent verification failures.
51
- * // TBS = canonical CBOR([session_id, agent_A_pubkey, agent_B_pubkey, genesis_prev_root, timestamp])
52
- * // Per CONTEXT.md: uses CBOR_ENC.encode() with tagUint8Array: false
53
- * // timestamp is uint32 or BigInt depending on size (>0xffffffff → BigInt)
54
- * return CBOR_ENC.encode([sessionId, pubA, pubB, genesisPrevRoot,
55
- * timestamp > 0xffffffff ? BigInt(timestamp) : timestamp])
56
- *
57
- * IMPORTANT-8: Existing test files that build SessionAssignment objects need updating to
58
- * include signature_type. Files affected (all M1 tests add signature_type: 'single'):
59
- * - packages/client/src/__tests__/session.test.ts (makeDirectoryAssignment helper)
60
- * - packages/client/src/__tests__/msg004.test.ts (makeDirectoryAssignment helper)
61
- * - packages/client/src/__tests__/session003.test.ts (multiple construction sites)
62
- * - packages/client/src/__tests__/session006.test.ts (makeDirectoryAssignment helper)
63
- * - packages/e2e-tests/src/__tests__/mcp-002.test.ts (assignment construction)
64
- * - packages/relay/src/__tests__/relay-node.test.ts (makeAssignment helper)
65
- * - packages/relay/src/__tests__/relay-incremental.test.ts (makeAssignment helper)
66
- * - packages/directory/src/directory-frames.ts (decodeOutboundSignalingFrame parser)
67
- *
68
- * IMPORTANT-9: ReceiveAssignmentResult in client/src/types.ts needs 'unsupported_signature_type'
69
- * added to its reason union.
70
- *
71
- * ─── End Phase P Pseudocode ───────────────────────────────────────────────────
72
- *
73
- * buildSealTbs: FROST TBS for conversation seal (SESSION-005).
41
+ * buildSealTbs: FROST TBS for a conversation seal.
74
42
  * FROST TBS fields: [session_id, sealed_root, leaf_count, timestamp]
75
43
  * Context string: "cello-frost-seal-v1" (per CONTEXT.md)
76
44
  * Both sides (directory as signer, client as verifier) must use the same encoding.
@@ -103,16 +71,16 @@ interface SessionAssignmentCommon {
103
71
  transport_mode?: 'direct' | 'relay';
104
72
  }
105
73
  /**
106
- * SESSION-004: FROST-signed assignment. `signer_pubkey` is the initiator's
107
- * group public key (primary_pubkey from DKG / trustedDealer commitments[0]).
108
- * Embedded so the counterparty can verify without a directory round-trip.
74
+ * FROST-signed assignment. `signer_pubkey` is the initiator's group public key
75
+ * (primary_pubkey from DKG / trustedDealer commitments[0]). Embedded so the
76
+ * counterparty can verify without a directory round-trip.
109
77
  */
110
78
  export interface SessionAssignmentFrost extends SessionAssignmentCommon {
111
79
  signature_type: "frost";
112
80
  signer_pubkey: Uint8Array;
113
81
  }
114
82
  /**
115
- * M1-era single-key directory signature. Refused by M2+ clients.
83
+ * Legacy single-key directory signature. Refused by current clients.
116
84
  */
117
85
  export interface SessionAssignmentSingle extends SessionAssignmentCommon {
118
86
  signature_type: "single";
@@ -121,8 +89,8 @@ export interface SessionAssignmentSingle extends SessionAssignmentCommon {
121
89
  * Discriminated union. TypeScript enforces `signer_pubkey` is present only
122
90
  * when `signature_type === 'frost'`.
123
91
  *
124
- * SESSION-004: M2+ code should only handle 'frost'. M1 assignments with
125
- * 'single' are rejected with `unsupported_signature_type`.
92
+ * Only 'frost' is handled. A 'single' assignment is rejected with
93
+ * `unsupported_signature_type`.
126
94
  */
127
95
  export type SessionAssignment = SessionAssignmentFrost | SessionAssignmentSingle;
128
96
  /**
@@ -157,7 +125,6 @@ export declare function buildSessionEstablishmentTbs(sessionId: Uint8Array, pubA
157
125
  /**
158
126
  * SEAL control payload carried as the content_bytes of a ctrl leaf.
159
127
  * Canonical CBOR encoding: [session_id, final_root, close_timestamp, "PENDING"].
160
- * Per SESSION-003 behavior spec.
161
128
  */
162
129
  export interface SealPayload {
163
130
  session_id: Uint8Array;
@@ -167,7 +134,7 @@ export interface SealPayload {
167
134
  }
168
135
  /**
169
136
  * Encode a SealPayload as canonical CBOR: [session_id, final_root, close_timestamp, "PENDING"].
170
- * Per SESSION-003 behavior spec and RFC 8949 §4.2.1.
137
+ * Per RFC 8949 §4.2.1.
171
138
  */
172
139
  export declare function encodeSealPayload(payload: SealPayload): Uint8Array;
173
140
  /**
@@ -195,9 +162,8 @@ export interface SessionAbandoned {
195
162
  session_id: Uint8Array;
196
163
  }
197
164
  /**
198
- * M1 session_sealed frame (single-key directory signature).
199
- * Refused in M2 clients per SESSION-005 SI-003.
200
- * @deprecated Use SessionSealedFrost instead in M2+.
165
+ * Legacy session_sealed frame (single-key directory signature). Refused by current clients.
166
+ * @deprecated Use SessionSealedFrost.
201
167
  */
202
168
  export interface SessionSealedSingle {
203
169
  type: "session_sealed";
@@ -209,8 +175,8 @@ export interface SessionSealedSingle {
209
175
  legibility?: SealLegibility;
210
176
  }
211
177
  /**
212
- * M2 session_sealed frame (FROST-notarized ceremony signature).
213
- * SESSION-005: seal_type is 'frost' when the FROST ceremony completes.
178
+ * session_sealed frame carrying the FROST-notarized ceremony signature.
179
+ * signature_type is 'frost' when the FROST ceremony completes.
214
180
  */
215
181
  export interface SessionSealedFrost {
216
182
  type: "session_sealed";
@@ -223,16 +189,16 @@ export interface SessionSealedFrost {
223
189
  leaf_count?: number;
224
190
  legibility?: SealLegibility;
225
191
  }
226
- /** Discriminated union: M2 sends SessionSealedFrost; old M1 wire format is SessionSealedSingle. */
192
+ /** Discriminated union: current senders emit SessionSealedFrost; SessionSealedSingle is the legacy wire format. */
227
193
  export type SessionSealed = SessionSealedSingle | SessionSealedFrost;
228
194
  /**
229
195
  * Per-attestation marker.
230
196
  * 'live' — the participant produced their SEAL acknowledgement leaf
231
197
  * contemporaneously in this ceremony (full-bilateral / present-party).
232
198
  * 'absent' — the participant produced no acknowledgement (counterparty ABSENT;
233
- * populated by the unilateral-notarization flow, Workstream A).
234
- * 'recovered' — the acknowledgement was added post-hoc on return (populated by the
235
- * bilateral-upgrade flow, Workstream C).
199
+ * set by the unilateral-notarization flow).
200
+ * 'recovered' — the acknowledgement was added post-hoc on return (set by the
201
+ * bilateral-upgrade flow).
236
202
  */
237
203
  export type AttestationMode = "live" | "recovered" | "absent";
238
204
  /**
@@ -289,7 +255,6 @@ export interface SessionSealRejected {
289
255
  /**
290
256
  * seal_verified: directory → seal initiator, after all three verification passes pass.
291
257
  * Tells the initiator: "I've verified the tree — coordinate the FROST ceremony now."
292
- * Per SESSION-005 step 4 in the seal ceremony flow.
293
258
  */
294
259
  export interface SealVerified {
295
260
  type: "seal_verified";
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
package/dist/session.js CHANGED
@@ -1,13 +1,14 @@
1
1
  /**
2
- * CELLO-SESSION-002/MSG-004/SESSION-003/SESSION-004/SESSION-005 — session.ts
2
+ * session.ts — session wire types and their to-be-signed encodings.
3
3
  *
4
4
  * SessionAssignment: shared wire type used by directory (sender), client (receiver),
5
5
  * and relay (verifier). Lives here so client can import it without touching @cello-protocol/directory.
6
6
  *
7
- * SESSION-004 additions to SessionAssignment:
7
+ * SessionAssignment is a discriminated union on `signature_type`, so TypeScript enforces that
8
+ * `signer_pubkey` is present exactly when the signature is FROST:
8
9
  * signature_type: 'frost' | 'single'
9
10
  * - 'frost': the directory_signature field carries the 64-byte combined FROST output
10
- * - 'single': M1-era single-key directory signature (refused by M2 clients)
11
+ * - 'single': legacy single-key directory signature (refused by current clients)
11
12
  * signer_pubkey?: Uint8Array (32 bytes, present when signature_type === 'frost')
12
13
  * - The initiator's primary_pubkey (group FROST key). Embedded so the counterparty
13
14
  * can verify without a separate directory round-trip.
@@ -19,11 +20,11 @@
19
20
  * Note: signer_pubkey is NOT in the TBS — it is derived from DKG and embedded in the frame.
20
21
  *
21
22
  * SealPayload: canonical CBOR of [session_id, final_root, close_timestamp, "PENDING"].
22
- * Per SESSION-003. content_hash = SHA-256(0x00 || SealPayload) per MERKLE-001.
23
+ * content_hash = SHA-256(0x00 || SealPayload).
23
24
  *
24
25
  * computeGenesisPrevRoot: deterministic genesis prev_root for a two-party session.
25
26
  *
26
- * Formula (SI-004):
27
+ * Formula:
27
28
  * SHA-256(min(A_pubkey, B_pubkey) || max(A_pubkey, B_pubkey) || session_id || timestamp_be8)
28
29
  *
29
30
  * Pubkeys are sorted bytewise-lexicographically (Buffer.compare).
@@ -31,55 +32,22 @@
31
32
  * (milliseconds since Unix epoch). Raw byte concatenation — no CBOR at this boundary,
32
33
  * which would introduce width ambiguity on the timestamp encoding.
33
34
  *
34
- * Per FIPS 180-4 (SHA-256) and SESSION-002 SI-004.
35
- *
36
- * ─── Phase P: SESSION-004 Pseudocode ─────────────────────────────────────────
37
- *
38
- * SessionAssignment type changes (MEDIUM-6: discriminated union enforces signer_pubkey):
39
- * // Use a discriminated union so TypeScript enforces signer_pubkey is present for 'frost'
40
- * type SessionAssignmentFrost = { ...common fields..., signature_type: 'frost', signer_pubkey: Uint8Array }
41
- * type SessionAssignmentSingle = { ...common fields..., signature_type: 'single' }
42
- * type SessionAssignment = SessionAssignmentFrost | SessionAssignmentSingle
43
- *
44
- * // Common fields (all existing SessionAssignment fields plus signature_type + signer_pubkey):
45
- * session_id, participant_a, participant_b, relay_endpoint, directory_endpoint,
46
- * session_timestamp, directory_pubkey, directory_signature
47
- *
48
- * buildSessionEstablishmentTbs(sessionId, pubA, pubB, genesisPrevRoot, timestamp):
49
- * // HIGH-5: exported from protocol-types so both directory and client use identical CBOR encoding
50
- * // Any encoding drift would cause silent verification failures.
51
- * // TBS = canonical CBOR([session_id, agent_A_pubkey, agent_B_pubkey, genesis_prev_root, timestamp])
52
- * // Per CONTEXT.md: uses CBOR_ENC.encode() with tagUint8Array: false
53
- * // timestamp is uint32 or BigInt depending on size (>0xffffffff → BigInt)
54
- * return CBOR_ENC.encode([sessionId, pubA, pubB, genesisPrevRoot,
55
- * timestamp > 0xffffffff ? BigInt(timestamp) : timestamp])
56
- *
57
- * IMPORTANT-8: Existing test files that build SessionAssignment objects need updating to
58
- * include signature_type. Files affected (all M1 tests add signature_type: 'single'):
59
- * - packages/client/src/__tests__/session.test.ts (makeDirectoryAssignment helper)
60
- * - packages/client/src/__tests__/msg004.test.ts (makeDirectoryAssignment helper)
61
- * - packages/client/src/__tests__/session003.test.ts (multiple construction sites)
62
- * - packages/client/src/__tests__/session006.test.ts (makeDirectoryAssignment helper)
63
- * - packages/e2e-tests/src/__tests__/mcp-002.test.ts (assignment construction)
64
- * - packages/relay/src/__tests__/relay-node.test.ts (makeAssignment helper)
65
- * - packages/relay/src/__tests__/relay-incremental.test.ts (makeAssignment helper)
66
- * - packages/directory/src/directory-frames.ts (decodeOutboundSignalingFrame parser)
67
- *
68
- * IMPORTANT-9: ReceiveAssignmentResult in client/src/types.ts needs 'unsupported_signature_type'
69
- * added to its reason union.
70
- *
71
- * ─── End Phase P Pseudocode ───────────────────────────────────────────────────
72
- *
73
- * buildSealTbs: FROST TBS for conversation seal (SESSION-005).
35
+ * Per FIPS 180-4 (SHA-256).
36
+ *
37
+ * buildSessionEstablishmentTbs is exported from protocol-types so that BOTH the directory
38
+ * (signer) and the client (verifier) use identical canonical CBOR encoding. Any encoding
39
+ * drift causes silent verification failures.
40
+ *
41
+ * buildSealTbs: FROST TBS for a conversation seal.
74
42
  * FROST TBS fields: [session_id, sealed_root, leaf_count, timestamp]
75
43
  * Context string: "cello-frost-seal-v1" (per CONTEXT.md)
76
44
  * Both sides (directory as signer, client as verifier) must use the same encoding.
77
45
  * Per RFC 9591 (FROST), RFC 8949 (CBOR canonical), FIPS 180-4 (SHA-256).
78
46
  */
79
47
  import { createHash } from "node:crypto";
80
- import { Encoder, decode as cborDecode } from "cbor-x";
81
- const CBOR_ENC = new Encoder({ tagUint8Array: false });
82
- // ─── Session establishment TBS builder (SESSION-004 / HIGH-5) ─────────────────
48
+ import { decode as cborDecode } from "cbor-x";
49
+ import { encodeCbor } from "./cbor.js";
50
+ // ─── Session establishment TBS builder ────────────────────────────────────────
83
51
  /**
84
52
  * Build the FROST to-be-signed bytes for session establishment.
85
53
  *
@@ -116,7 +84,7 @@ export function buildSessionEstablishmentTbs(sessionId, pubA, pubB, genesisPrevR
116
84
  counterpartySessionPeerId !== undefined &&
117
85
  counterpartySessionAddrs !== undefined &&
118
86
  transportMode !== undefined) {
119
- return CBOR_ENC.encode([
87
+ return encodeCbor([
120
88
  sessionId,
121
89
  pubA,
122
90
  pubB,
@@ -130,7 +98,7 @@ export function buildSessionEstablishmentTbs(sessionId, pubA, pubB, genesisPrevR
130
98
  ]);
131
99
  }
132
100
  // Legacy (M1–M6): encode only the original 5 fields
133
- return CBOR_ENC.encode([
101
+ return encodeCbor([
134
102
  sessionId,
135
103
  pubA,
136
104
  pubB,
@@ -140,10 +108,10 @@ export function buildSessionEstablishmentTbs(sessionId, pubA, pubB, genesisPrevR
140
108
  }
141
109
  /**
142
110
  * Encode a SealPayload as canonical CBOR: [session_id, final_root, close_timestamp, "PENDING"].
143
- * Per SESSION-003 behavior spec and RFC 8949 §4.2.1.
111
+ * Per RFC 8949 §4.2.1.
144
112
  */
145
113
  export function encodeSealPayload(payload) {
146
- return CBOR_ENC.encode([
114
+ return encodeCbor([
147
115
  payload.session_id,
148
116
  payload.final_root,
149
117
  payload.close_timestamp > 0xffffffff
@@ -179,7 +147,7 @@ export function decodeSealPayload(bytes) {
179
147
  return null;
180
148
  return { session_id: sid, final_root: root, close_timestamp: ts, attestation: "PENDING" };
181
149
  }
182
- // ─── buildSealTbs (SESSION-005) ───────────────────────────────────────────────
150
+ // ─── buildSealTbs ─────────────────────────────────────────────────────────────
183
151
  /**
184
152
  * Build the FROST to-be-signed bytes for a conversation seal ceremony.
185
153
  *
@@ -196,7 +164,7 @@ export function decodeSealPayload(bytes) {
196
164
  * @param timestamp - Unix milliseconds at the time of verification
197
165
  */
198
166
  export function buildSealTbs(sessionId, sealedRoot, leafCount, timestamp) {
199
- return CBOR_ENC.encode([
167
+ return encodeCbor([
200
168
  sessionId,
201
169
  sealedRoot,
202
170
  leafCount,
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAoEvC,iFAAiF;AAEjF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,4BAA4B,CAC1C,SAAqB,EACrB,IAAgB,EAChB,IAAgB,EAChB,eAA2B,EAC3B,SAA0B,EAC1B,sBAA+B,EAC/B,qBAAgC,EAChC,yBAAkC,EAClC,wBAAmC,EACnC,aAAkC;IAElC,MAAM,SAAS,GAAG,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE1G,8DAA8D;IAC9D,IACE,sBAAsB,KAAK,SAAS;QACpC,qBAAqB,KAAK,SAAS;QACnC,yBAAyB,KAAK,SAAS;QACvC,wBAAwB,KAAK,SAAS;QACtC,aAAa,KAAK,SAAS,EAC3B,CAAC;QACD,OAAO,UAAU,CAAC;YAChB,SAAS;YACT,IAAI;YACJ,IAAI;YACJ,eAAe;YACf,SAAS;YACT,sBAAsB;YACtB,IAAI,CAAC,SAAS,CAAC,qBAAqB,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC;YACpD,yBAAyB;YACzB,IAAI,CAAC,SAAS,CAAC,wBAAwB,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC;YACvD,aAAa;SACd,CAAe,CAAC;IACnB,CAAC;IAED,oDAAoD;IACpD,OAAO,UAAU,CAAC;QAChB,SAAS;QACT,IAAI;QACJ,IAAI;QACJ,eAAe;QACf,SAAS;KACV,CAAe,CAAC;AACnB,CAAC;AAeD;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAoB;IACpD,OAAO,UAAU,CAAC;QAChB,OAAO,CAAC,UAAU;QAClB,OAAO,CAAC,UAAU;QAClB,OAAO,CAAC,eAAe,GAAG,UAAU;YAClC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC;YACjC,CAAC,CAAC,OAAO,CAAC,eAAe;QAC3B,OAAO,CAAC,WAAW;KACpB,CAAe,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAiB;IACjD,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACzD,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,GAAG,CAAC;IACxC,MAAM,GAAG,GAAG,IAAI,YAAY,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,IAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9G,MAAM,IAAI,GAAG,KAAK,YAAY,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,KAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACnH,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC3C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC7C,MAAM,EAAE,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACxF,IAAI,EAAE,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC7B,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;AAC5F,CAAC;AAED,iFAAiF;AAEjF;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,YAAY,CAC1B,SAAqB,EACrB,UAAsB,EACtB,SAAiB,EACjB,SAAiB;IAEjB,OAAO,UAAU,CAAC;QAChB,SAAS;QACT,UAAU;QACV,SAAS;QACT,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS;KACvD,CAAe,CAAC;AACnB,CAAC;AAsED;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAClC,4EAA4E;IAC5E,+EAA+E;IAC/E,gFAAgF;IAChF,wFAAwF,CAAC;AAwE3F,iFAAiF;AAEjF;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAmB,EACnB,OAAmB,EACnB,SAAqB,EACrB,kBAAmC;IAEnC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE/B,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAE/D,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7B,IAAI,CAAC,gBAAgB,CAAC,OAAO,kBAAkB,KAAK,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAEhH,OAAO,IAAI,UAAU,CACnB,UAAU,CAAC,QAAQ,CAAC;SACjB,MAAM,CAAC,GAAG,CAAC;SACX,MAAM,CAAC,GAAG,CAAC;SACX,MAAM,CAAC,SAAS,CAAC;SACjB,MAAM,CAAC,IAAI,CAAC;SACZ,MAAM,EAAE,CACZ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ /** The Structure 1 version tag. Bound as the FIRST field, so a v1 claim can never read as a v2 one. */
2
+ export declare const STRUCTURE1_VERSION = 1;
3
+ /**
4
+ * Canonical Structure 1 bytes: [version, content_hash, sender_pubkey, session_id, last_seen_seq, timestamp].
5
+ *
6
+ * A timestamp above 2^32-1 is encoded as a CBOR bigint — a plain number would silently lose
7
+ * precision, and the sender's signature is over THESE bytes.
8
+ */
9
+ export declare function encodeStructure1(fields: {
10
+ contentHash: Uint8Array;
11
+ senderPubkey: Uint8Array;
12
+ sessionId: Uint8Array;
13
+ lastSeenSeq: number;
14
+ timestamp: number;
15
+ }): Uint8Array;
16
+ //# sourceMappingURL=structure1.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure1.d.ts","sourceRoot":"","sources":["../src/structure1.ts"],"names":[],"mappings":"AAcA,uGAAuG;AACvG,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IACvC,WAAW,EAAE,UAAU,CAAC;IACxB,YAAY,EAAE,UAAU,CAAC;IACzB,SAAS,EAAE,UAAU,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,UAAU,CAUb"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Structure 1 — the sender's signed ordering claim, canonical CBOR.
3
+ *
4
+ * The daemon PARSES Structure 1 (it arrives from the relay, the ordering authority) but does not
5
+ * build one, so this encoder has no production caller. It is kept because it is the only written
6
+ * definition of the Structure 1 FIELD ORDER, and `structure1-canonical.json` is the only vector in
7
+ * either repo pinning the resulting bytes. Delete it and the wire format is defined solely by
8
+ * whatever the relay happens to emit, with nothing to catch a drift.
9
+ *
10
+ * Field order is LOAD-BEARING: it is signed over. Reorder a field and signatures produced by any
11
+ * other implementation stop verifying against ours.
12
+ */
13
+ import { encodeCbor } from "./cbor.js";
14
+ /** The Structure 1 version tag. Bound as the FIRST field, so a v1 claim can never read as a v2 one. */
15
+ export const STRUCTURE1_VERSION = 1;
16
+ /**
17
+ * Canonical Structure 1 bytes: [version, content_hash, sender_pubkey, session_id, last_seen_seq, timestamp].
18
+ *
19
+ * A timestamp above 2^32-1 is encoded as a CBOR bigint — a plain number would silently lose
20
+ * precision, and the sender's signature is over THESE bytes.
21
+ */
22
+ export function encodeStructure1(fields) {
23
+ const ts = fields.timestamp > 0xffffffff ? BigInt(fields.timestamp) : fields.timestamp;
24
+ return encodeCbor([
25
+ STRUCTURE1_VERSION,
26
+ fields.contentHash,
27
+ fields.senderPubkey,
28
+ fields.sessionId,
29
+ fields.lastSeenSeq,
30
+ ts,
31
+ ]);
32
+ }
33
+ //# sourceMappingURL=structure1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure1.js","sourceRoot":"","sources":["../src/structure1.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,uGAAuG;AACvG,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAMhC;IACC,MAAM,EAAE,GAAG,MAAM,CAAC,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC;IACvF,OAAO,UAAU,CAAC;QAChB,kBAAkB;QAClB,MAAM,CAAC,WAAW;QAClB,MAAM,CAAC,YAAY;QACnB,MAAM,CAAC,SAAS;QAChB,MAAM,CAAC,WAAW;QAClB,EAAE;KACH,CAAC,CAAC;AACL,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"structure2.d.ts","sourceRoot":"","sources":["../src/structure2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAMhD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,IAAI,CAAC;IACZ,OAAO,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,UAAU,CAAC;IAC1B,YAAY,EAAE,UAAU,CAAC;IACzB,gBAAgB,EAAE,UAAU,CAAC;IAC7B,WAAW,EAAE,kBAAkB,CAAC;IAChC,SAAS,EAAE,UAAU,CAAC;CACvB;AAED,MAAM,MAAM,qBAAqB,GAC7B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,GACpC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,aAAa,CAAA;CAAE,CAAC;AAIxC,4FAA4F;AAC5F,eAAO,MAAM,oBAAoB,EAAE,kBAIjC,CAAC;AAEH;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,IAAI,UAAU,CAiBrD;AAID;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,UAAU,EACzB,YAAY,EAAE,UAAU,EACxB,gBAAgB,EAAE,UAAU,EAC5B,SAAS,EAAE,UAAU,GACpB,qBAAqB,CAqCvB;AAID;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,UAAU,GAAG,UAAU,CAc3D;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,UAAU,EACd,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,GAAG,MAAM,GACzB,OAAO,CAWT"}
1
+ {"version":3,"file":"structure2.d.ts","sourceRoot":"","sources":["../src/structure2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAKhD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,IAAI,CAAC;IACZ,OAAO,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,UAAU,CAAC;IAC1B,YAAY,EAAE,UAAU,CAAC;IACzB,gBAAgB,EAAE,UAAU,CAAC;IAC7B,WAAW,EAAE,kBAAkB,CAAC;IAChC,SAAS,EAAE,UAAU,CAAC;CACvB;AAED,MAAM,MAAM,qBAAqB,GAC7B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,GACpC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,aAAa,CAAA;CAAE,CAAC;AAIxC,4FAA4F;AAC5F,eAAO,MAAM,oBAAoB,EAAE,kBAIjC,CAAC;AAEH;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,IAAI,UAAU,CAiBrD;AAID;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,UAAU,EACzB,YAAY,EAAE,UAAU,EACxB,gBAAgB,EAAE,UAAU,EAC5B,SAAS,EAAE,UAAU,GACpB,qBAAqB,CAqCvB;AAID;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,UAAU,GAAG,UAAU,CAc3D;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,UAAU,EACd,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,GAAG,MAAM,GACzB,OAAO,CAWT"}
@@ -15,9 +15,8 @@
15
15
  * This is what the sender signs; verifyStructure2Signature reconstructs it from Structure 2 fields
16
16
  * plus the session_id, last_seen_seq, and timestamp carried through the relay path.
17
17
  */
18
- import { Encoder } from "cbor-x";
18
+ import { encodeCbor } from "./cbor.js";
19
19
  import { verify } from "@cello-protocol/crypto";
20
- const CBOR_ENC = new Encoder({ tagUint8Array: false });
21
20
  // ─── Sentinel ─────────────────────────────────────────────────────────────────
22
21
  /** M1 placeholder scan_result sentinel. The scanner field is stable but unset until M4+. */
23
22
  export const SCAN_RESULT_SENTINEL = Object.freeze({
@@ -102,11 +101,11 @@ export function encodeStructure2(s2) {
102
101
  // We must embed the pre-encoded sentinel bytes as raw CBOR, not re-encode the object.
103
102
  // Construct the 6-element array manually to preserve canonical byte representation.
104
103
  const arrayHeader = new Uint8Array([0x86]); // 6-element CBOR array
105
- const seqBytes = CBOR_ENC.encode(s2.sequence_number);
106
- const pubBytes = CBOR_ENC.encode(s2.sender_pubkey);
107
- const hashBytes = CBOR_ENC.encode(s2.content_hash);
108
- const sigBytes = CBOR_ENC.encode(s2.sender_signature);
109
- const prevBytes = CBOR_ENC.encode(s2.prev_root);
104
+ const seqBytes = encodeCbor(s2.sequence_number);
105
+ const pubBytes = encodeCbor(s2.sender_pubkey);
106
+ const hashBytes = encodeCbor(s2.content_hash);
107
+ const sigBytes = encodeCbor(s2.sender_signature);
108
+ const prevBytes = encodeCbor(s2.prev_root);
110
109
  return new Uint8Array(Buffer.concat([arrayHeader, seqBytes, pubBytes, hashBytes, sigBytes, sentinelBytes, prevBytes]));
111
110
  }
112
111
  // ─── Verify ───────────────────────────────────────────────────────────────────
@@ -125,7 +124,7 @@ export function encodeStructure2(s2) {
125
124
  */
126
125
  export function verifyStructure2Signature(s2, session_id, last_seen_seq, timestamp) {
127
126
  const tsEncoded = typeof timestamp === "bigint" ? timestamp : timestamp > 0xffffffff ? BigInt(timestamp) : timestamp;
128
- const tbs = CBOR_ENC.encode([
127
+ const tbs = encodeCbor([
129
128
  1,
130
129
  s2.content_hash,
131
130
  s2.sender_pubkey,
@@ -1 +1 @@
1
- {"version":3,"file":"structure2.js","sourceRoot":"","sources":["../src/structure2.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"structure2.js","sourceRoot":"","sources":["../src/structure2.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * The canonical trust-signal envelope (M10 / DOD-CBOR-1): serialize, hash, verify.
3
+ *
4
+ * Four parties independently re-derive this hash — the portal at mint, the directory at submission
5
+ * (INV-CHOKEPOINT's re-hash before store), the directory again at presentation (dumb check 1), and
6
+ * the holder/recipient daemons on receipt and at verification. They must agree byte-for-byte,
7
+ * forever, across three repos and two languages' worth of tooling. A single divergent byte turns a
8
+ * valid signal into a false `hash_mismatch` — unpresentable, and censorship-shaped, because it can
9
+ * differ per node or per client version.
10
+ *
11
+ * THE PREIMAGE IS AN ARRAY, NOT A MAP, AND THAT IS LOAD-BEARING (M10-D15).
12
+ * The shared encoder (`cbor.ts`) is not RFC 8949 §4.2 deterministic for MAPS: map keys follow
13
+ * INSERTION ORDER, and map headers are not minimal-length (a 2-entry map emits `b9 0002`, not `a2`).
14
+ * Arrays, text strings, byte strings, integers and null are all minimal and order-fixed. Encoding
15
+ * the preimage as a fixed-order array therefore makes determinism STRUCTURAL — a property of the
16
+ * shape, not of the encoder's configuration — and costs no encoder change and no migration of the
17
+ * blobs already on disk. Every signed TBS in CELLO is an array for this same reason
18
+ * (`buildAgentRevocationTbs`, `buildPrimaryTransferTbs`, `buildSealTbs`, `buildParkContentTbs`).
19
+ *
20
+ * Consequences, all enforced below:
21
+ * - FIELD ORDER IS THE WIRE FORMAT. Reordering the array is a breaking hash change, not a
22
+ * refactor. Retrofitting a canonical form later breaks every hash already minted (spec §5).
23
+ * - THE FIELD SET IS CLOSED (spec §4). An unknown field is REJECTED, never ignored: silently
24
+ * dropping it would let two parties who disagree about the field set still agree on the hash,
25
+ * making the extra field unauthenticated data riding inside a "verified" signal.
26
+ * - `status` / `class` / `verified_at` ARE NOT IN THE PREIMAGE. They are mutable after minting —
27
+ * that is the entire point of excluding them. If `status` were hashed, revoking a signal would
28
+ * change its hash and the directory could never find it again.
29
+ * - OPTIONAL FIELDS ARE AN EXPLICIT `null` IN A FIXED SLOT, NEVER OMITTED (M10-D17). In an array,
30
+ * omitting a field shifts every later field and changes the arity, so an absent `expires_at`
31
+ * becomes confusable with a misaligned `supersedes_hash`.
32
+ * - NO FLOATING POINT. Timestamps are integer epoch SECONDS. A float would not survive
33
+ * byte-agreement across languages.
34
+ * - `payload` IS OPAQUE BYTES, never decoded or re-encoded. A payload parsed and re-serialized
35
+ * would change bytes under a different encoder version. This is also what INV-ZERO-BUMP rests
36
+ * on: a type this code has never seen must hash and flow through untouched.
37
+ */
38
+ /** Domain separation, bound as element 0 of the preimage array — the house convention
39
+ * (`AGENT_REVOCATION_DOMAIN`, `PRIMARY_TRANSFER_DOMAIN`). A trust-signal hash can therefore never
40
+ * collide with, or be replayed as, any other hashed/signed CELLO structure. */
41
+ export declare const TRUST_SIGNAL_DOMAIN = "CELLO-TSIG-v1";
42
+ /** Whose fact this is. Account-subject signals (phone, email, social) are presentable by every agent
43
+ * under the account; agent-subject signals (track record) belong to one agent. Both are HASHED, so
44
+ * the scope cannot be changed after minting (M10-D5). */
45
+ export type SignalSubjectKind = "account" | "agent";
46
+ /** Who attested it. Drives FRAMING at the consuming LLM (INV-FRAMING): `portal` is portal-attested;
47
+ * `agent` is quoted-untrusted ("Bob says:"). Hashed, so framing cannot be laundered by a relabel. */
48
+ export type SignalIssuerKind = "portal" | "agent";
49
+ /**
50
+ * The hashed part of a trust signal. This is the WHOLE preimage and nothing else — see spec §4's
51
+ * mandatory-disclosure set. `type` is an OPAQUE STRING here and everywhere in the client and the
52
+ * directory: never an enum, never switched on (INV-ZERO-BUMP).
53
+ */
54
+ export interface TrustSignalEnvelope {
55
+ subject_kind: SignalSubjectKind;
56
+ /** The account id or agent id this fact is about. */
57
+ subject: string;
58
+ issuer_kind: SignalIssuerKind;
59
+ /** Hex-encoded Ed25519 public key of the issuer. Verified against the directory's authorized set. */
60
+ issuer_pubkey: string;
61
+ /** OPAQUE type string. Adding a type must require no code change anywhere but the portal. */
62
+ type: string;
63
+ schema_version: number;
64
+ /** OPAQUE payload bytes. Never parsed, never re-encoded, never hoisted into a column. */
65
+ payload: Uint8Array;
66
+ /** Integer epoch SECONDS. */
67
+ issued_at: number;
68
+ /** Integer epoch SECONDS, or null for a signal that never expires. */
69
+ expires_at: number | null;
70
+ /** The 32-byte hash this envelope replaces, or null for a first mint. */
71
+ supersedes_hash: Uint8Array | null;
72
+ }
73
+ /** The canonical preimage bytes. Deterministic across every party that runs this code. */
74
+ export declare function encodeTrustSignalEnvelope(envelope: TrustSignalEnvelope): Uint8Array;
75
+ /** The signal's identity: SHA-256 over the canonical preimage. This is the `signal_hash` that the
76
+ * directory stores, the holder presents, and the recipient re-derives. */
77
+ export declare function hashTrustSignalEnvelope(envelope: TrustSignalEnvelope): Uint8Array;
78
+ /**
79
+ * Does this envelope actually hash to `expected`? Length is checked first, so a truncated hash can
80
+ * never pass by matching a prefix. The comparison is constant-time in the length of the input: a
81
+ * signal hash is public, but the habit is cheap and the alternative invites a timing oracle the day
82
+ * one of these stops being public.
83
+ *
84
+ * ⚠️ THIS RETURNS `false` FOR A WRONG HASH BUT **THROWS** FOR A MALFORMED ENVELOPE, AND THAT
85
+ * ASYMMETRY IS DELIBERATE. A wrong hash is a normal, expected answer ("no, this doesn't match"). A
86
+ * malformed envelope is not an answer at all — it is an envelope that cannot be canonicalized, so
87
+ * there is no hash to compare and any boolean would be a lie.
88
+ *
89
+ * The directory calls this on hostile input. DO NOT wrap it in `try { … } catch { return false }`:
90
+ * that converts "this envelope is unhashable garbage" into "this envelope simply didn't match",
91
+ * which is the silent swallow that hides the attack. Let it throw, and log the cause.
92
+ */
93
+ export declare function verifyTrustSignalHash(envelope: TrustSignalEnvelope, expected: Uint8Array): boolean;
94
+ //# sourceMappingURL=trust-signal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust-signal.d.ts","sourceRoot":"","sources":["../src/trust-signal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAKH;;gFAEgF;AAChF,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AAEnD;;0DAE0D;AAC1D,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,OAAO,CAAC;AAEpD;sGACsG;AACtG,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAElD;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,iBAAiB,CAAC;IAChC,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,gBAAgB,CAAC;IAC9B,qGAAqG;IACrG,aAAa,EAAE,MAAM,CAAC;IACtB,6FAA6F;IAC7F,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,yFAAyF;IACzF,OAAO,EAAE,UAAU,CAAC;IACpB,6BAA6B;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,yEAAyE;IACzE,eAAe,EAAE,UAAU,GAAG,IAAI,CAAC;CACpC;AAmND,0FAA0F;AAC1F,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,UAAU,CAEnF;AAED;2EAC2E;AAC3E,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,UAAU,CAEjF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,mBAAmB,EAAE,QAAQ,EAAE,UAAU,GAAG,OAAO,CAMlG"}