@cello-protocol/daemon 0.0.182 → 0.0.184

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 (137) hide show
  1. package/dist/agent-settings-keys.d.ts.map +1 -1
  2. package/dist/agent-settings-keys.js +18 -0
  3. package/dist/agent-settings-keys.js.map +1 -1
  4. package/dist/close-session-handler.d.ts.map +1 -1
  5. package/dist/close-session-handler.js +90 -16
  6. package/dist/close-session-handler.js.map +1 -1
  7. package/dist/consortium-bootstrap.d.ts.map +1 -1
  8. package/dist/consortium-bootstrap.js +117 -2
  9. package/dist/consortium-bootstrap.js.map +1 -1
  10. package/dist/content-encryption-status.d.ts +97 -0
  11. package/dist/content-encryption-status.d.ts.map +1 -0
  12. package/dist/content-encryption-status.js +122 -0
  13. package/dist/content-encryption-status.js.map +1 -0
  14. package/dist/content-park-client.d.ts +10 -0
  15. package/dist/content-park-client.d.ts.map +1 -1
  16. package/dist/content-park-client.js +84 -3
  17. package/dist/content-park-client.js.map +1 -1
  18. package/dist/content-park.d.ts.map +1 -1
  19. package/dist/content-park.js +184 -13
  20. package/dist/content-park.js.map +1 -1
  21. package/dist/daemon.d.ts.map +1 -1
  22. package/dist/daemon.js +671 -67
  23. package/dist/daemon.js.map +1 -1
  24. package/dist/document-handlers.d.ts.map +1 -1
  25. package/dist/document-handlers.js +119 -0
  26. package/dist/document-handlers.js.map +1 -1
  27. package/dist/document-layer.d.ts +0 -2
  28. package/dist/document-layer.d.ts.map +1 -1
  29. package/dist/document-layer.js.map +1 -1
  30. package/dist/frame-values.d.ts.map +1 -1
  31. package/dist/frame-values.js +14 -0
  32. package/dist/frame-values.js.map +1 -1
  33. package/dist/inclusion-proof-handlers.d.ts +43 -0
  34. package/dist/inclusion-proof-handlers.d.ts.map +1 -0
  35. package/dist/inclusion-proof-handlers.js +565 -0
  36. package/dist/inclusion-proof-handlers.js.map +1 -0
  37. package/dist/inclusion-proof.d.ts +151 -0
  38. package/dist/inclusion-proof.d.ts.map +1 -0
  39. package/dist/inclusion-proof.js +228 -0
  40. package/dist/inclusion-proof.js.map +1 -0
  41. package/dist/initiate-session-handler.d.ts.map +1 -1
  42. package/dist/initiate-session-handler.js +34 -3
  43. package/dist/initiate-session-handler.js.map +1 -1
  44. package/dist/manifest-deps.d.ts +0 -11
  45. package/dist/manifest-deps.d.ts.map +1 -1
  46. package/dist/manifest-deps.js +28 -2
  47. package/dist/manifest-deps.js.map +1 -1
  48. package/dist/manifest-validity.d.ts +2 -0
  49. package/dist/manifest-validity.d.ts.map +1 -1
  50. package/dist/manifest-validity.js +1 -1
  51. package/dist/manifest-validity.js.map +1 -1
  52. package/dist/network-directory-node.d.ts +16 -0
  53. package/dist/network-directory-node.d.ts.map +1 -1
  54. package/dist/network-directory-node.js +40 -0
  55. package/dist/network-directory-node.js.map +1 -1
  56. package/dist/notification-handlers.d.ts.map +1 -1
  57. package/dist/notification-handlers.js +71 -2
  58. package/dist/notification-handlers.js.map +1 -1
  59. package/dist/outbound-sessions.d.ts +6 -0
  60. package/dist/outbound-sessions.d.ts.map +1 -1
  61. package/dist/outbound-sessions.js +50 -7
  62. package/dist/outbound-sessions.js.map +1 -1
  63. package/dist/park-envelope.d.ts +23 -0
  64. package/dist/park-envelope.d.ts.map +1 -1
  65. package/dist/park-envelope.js +76 -0
  66. package/dist/park-envelope.js.map +1 -1
  67. package/dist/register-handler.d.ts.map +1 -1
  68. package/dist/register-handler.js +76 -0
  69. package/dist/register-handler.js.map +1 -1
  70. package/dist/relay-only.d.ts +133 -0
  71. package/dist/relay-only.d.ts.map +1 -0
  72. package/dist/relay-only.js +183 -0
  73. package/dist/relay-only.js.map +1 -0
  74. package/dist/retry-queue.d.ts +26 -1
  75. package/dist/retry-queue.d.ts.map +1 -1
  76. package/dist/retry-queue.js +18 -1
  77. package/dist/retry-queue.js.map +1 -1
  78. package/dist/seal-coordinator.d.ts +51 -1
  79. package/dist/seal-coordinator.d.ts.map +1 -1
  80. package/dist/seal-coordinator.js +248 -1
  81. package/dist/seal-coordinator.js.map +1 -1
  82. package/dist/seal-escalation.d.ts.map +1 -1
  83. package/dist/seal-escalation.js +28 -0
  84. package/dist/seal-escalation.js.map +1 -1
  85. package/dist/seal-failure-store.d.ts.map +1 -1
  86. package/dist/seal-failure-store.js +5 -1
  87. package/dist/seal-failure-store.js.map +1 -1
  88. package/dist/sealed-leaf-set.d.ts +92 -0
  89. package/dist/sealed-leaf-set.d.ts.map +1 -0
  90. package/dist/sealed-leaf-set.js +129 -0
  91. package/dist/sealed-leaf-set.js.map +1 -0
  92. package/dist/session-ceremony.d.ts +27 -1
  93. package/dist/session-ceremony.d.ts.map +1 -1
  94. package/dist/session-ceremony.js +109 -7
  95. package/dist/session-ceremony.js.map +1 -1
  96. package/dist/session-content-handlers.d.ts +12 -0
  97. package/dist/session-content-handlers.d.ts.map +1 -1
  98. package/dist/session-content-handlers.js +39 -4
  99. package/dist/session-content-handlers.js.map +1 -1
  100. package/dist/session-node-manager.d.ts +387 -4
  101. package/dist/session-node-manager.d.ts.map +1 -1
  102. package/dist/session-node-manager.js +3529 -279
  103. package/dist/session-node-manager.js.map +1 -1
  104. package/dist/session-read-handlers.d.ts.map +1 -1
  105. package/dist/session-read-handlers.js +16 -1
  106. package/dist/session-read-handlers.js.map +1 -1
  107. package/dist/session-relay-client.d.ts +163 -1
  108. package/dist/session-relay-client.d.ts.map +1 -1
  109. package/dist/session-relay-client.js +540 -6
  110. package/dist/session-relay-client.js.map +1 -1
  111. package/dist/session-salt-agreement.d.ts +58 -4
  112. package/dist/session-salt-agreement.d.ts.map +1 -1
  113. package/dist/session-salt-agreement.js +110 -3
  114. package/dist/session-salt-agreement.js.map +1 -1
  115. package/dist/signal-submission.d.ts +11 -1
  116. package/dist/signal-submission.d.ts.map +1 -1
  117. package/dist/signal-submission.js.map +1 -1
  118. package/dist/signaling-connect.d.ts +18 -1
  119. package/dist/signaling-connect.d.ts.map +1 -1
  120. package/dist/signaling-connect.js +164 -1
  121. package/dist/signaling-connect.js.map +1 -1
  122. package/dist/submission-retry.d.ts +208 -0
  123. package/dist/submission-retry.d.ts.map +1 -0
  124. package/dist/submission-retry.js +505 -0
  125. package/dist/submission-retry.js.map +1 -0
  126. package/dist/types.d.ts +33 -0
  127. package/dist/types.d.ts.map +1 -1
  128. package/dist/types.js.map +1 -1
  129. package/dist/vocabulary.d.ts +13 -3
  130. package/dist/vocabulary.d.ts.map +1 -1
  131. package/dist/vocabulary.js +14 -3
  132. package/dist/vocabulary.js.map +1 -1
  133. package/dist/wire-content-hash.d.ts +15 -3
  134. package/dist/wire-content-hash.d.ts.map +1 -1
  135. package/dist/wire-content-hash.js +15 -3
  136. package/dist/wire-content-hash.js.map +1 -1
  137. package/package.json +5 -5
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Proving that ONE message sits under the root the directory notarized.
3
+ *
4
+ * ─── WHAT MAKES THIS A PROOF AND NOT A DATA STRUCTURE ────────────────────────────────────────
5
+ *
6
+ * Two things, and both are easy to get wrong in a way that still looks like a proof.
7
+ *
8
+ * **1. The root comes from the CERTIFICATE, never from the proof.** A proof that carries its own
9
+ * root and is checked against it proves that the machine which wrote the proof is self-consistent —
10
+ * and that machine is the one a sceptic distrusts. So `verifyInclusionProof` REQUIRES the root as a
11
+ * separate argument, supplied by whoever holds the directory-signed certificate, and the root inside
12
+ * the proof is only ever compared to it. Drop that argument and the whole file becomes theatre.
13
+ *
14
+ * **2. The leaf is recomputed from the MESSAGE BYTES, never taken from the proof.** The Merkle leaf
15
+ * is a content hash, and since `DOD-M15-SEALWIRE-1` that hash is `HMAC-SHA256(salt, 0x00 ‖ content)`
16
+ * for a salted session. A proof over the leaf hash alone answers "is this opaque 32-byte number in
17
+ * the tree", and the operator's question is about a sentence. So the salt and the algorithm NAME
18
+ * travel with the proof, the verifier recomputes the leaf from the plaintext it holds, and a message
19
+ * that differs by one byte produces a different leaf and fails — which is the assertion the whole
20
+ * feature exists to make.
21
+ *
22
+ * Neither hash nor Merkle maths is reimplemented here. `contentHashFor` (wire-content-hash.ts) is
23
+ * the daemon's ONE content-hash derivation and `verifyInclusion` (@cello-protocol/crypto) is the ONE
24
+ * RFC 6962 verifier. A second copy of either drifts from the seal, and the drift surfaces as a lost
25
+ * dispute rather than as a failing test.
26
+ *
27
+ * Crypto refs: RFC 6962 §2.1.1 (Merkle audit paths), RFC 2104 (HMAC), FIPS 180-4 (SHA-256).
28
+ */
29
+ import { type ContentHashAlg } from "./wire-content-hash.js";
30
+ /** Everything a third party needs alongside the message bytes and the certificate. */
31
+ export interface InclusionProof {
32
+ /** Proof format version. Bumped when any field below changes meaning. */
33
+ readonly version: 1;
34
+ /** The session this proof is about, hex — so a proof cannot be silently read against another. */
35
+ readonly session_id: string;
36
+ /**
37
+ * The root this proof lands on, hex. NOT authoritative on its own: `verifyInclusionProof`
38
+ * compares it to the root the caller took from the certificate and refuses if they differ.
39
+ */
40
+ readonly certified_root: string;
41
+ /** Zero-based position of this message's leaf under the certified root. */
42
+ readonly leaf_index: number;
43
+ /** How many leaves the certified root covers (content leaves AND the seal's control leaves). */
44
+ readonly leaf_count: number;
45
+ /** The leaf hash this proof is for, hex — recomputed by the verifier, never trusted from here. */
46
+ readonly leaf_hash: string;
47
+ /** RFC 6962 §2.1.1 audit path: sibling hashes, hex, leaf level upward. */
48
+ readonly proof_path: readonly string[];
49
+ /** How the leaf hash is derived from the message bytes. Named, never assumed. */
50
+ readonly content_hash_alg: ContentHashAlg;
51
+ /**
52
+ * The session salt, hex. Required — this build issues salted proofs only, and a proof carrying no
53
+ * salt is refused rather than checked. The type stays nullable because the shape check runs over
54
+ * an object off the wire, and "carried null" must be refusable BY NAME rather than by a crash.
55
+ */
56
+ readonly content_salt: string | null;
57
+ }
58
+ /**
59
+ * Why a verification did not conclude "verified".
60
+ *
61
+ * A CLOSED set with a total guidance map below, so a new code cannot be added without something the
62
+ * reader can act on. `message_does_not_match_leaf` and `proof_path_invalid` are the two that mean
63
+ * "the proof is bad"; the rest mean "this proof was not checkable as presented".
64
+ */
65
+ export declare const INCLUSION_VERIFY_REASONS: {
66
+ /** The proof object is not a v1 proof, or a field is missing / the wrong width. */
67
+ readonly PROOF_MALFORMED: "proof_malformed";
68
+ /** The proof names a root that is not the one in the certificate the caller holds. */
69
+ readonly ROOT_NOT_FROM_CERTIFICATE: "root_not_from_certificate";
70
+ /**
71
+ * The root SUPPLIED by the caller is not a 32-byte hex value — so there is nothing to compare.
72
+ *
73
+ * Separate from the reason above because that one's guidance says *"the proof lands on a DIFFERENT
74
+ * root than the certificate you supplied"*, and for a truncated paste or a stray quote that is
75
+ * false: no root was supplied at all. Naming the exit point instead of the cause is the defect
76
+ * Invariant 3 is about, and it costs an operator the one thing they can actually fix.
77
+ */
78
+ readonly CERTIFIED_ROOT_MALFORMED: "certified_root_malformed";
79
+ /** The proof names a hash algorithm this build cannot reproduce. */
80
+ readonly UNKNOWN_HASH_ALG: "unknown_content_hash_alg";
81
+ /**
82
+ * The proof is over an UNSALTED content hash. Refused rather than checked.
83
+ *
84
+ * There is no compatibility branch here on purpose. An unsalted leaf hash is `sha256(0x00 ‖
85
+ * content)` — a value anyone holding the plaintext can compute, so it correlates the message
86
+ * across every record that carries it, which is exactly what the session salt exists to stop.
87
+ * Verifying one anyway would hand back `ok: true` for a proof carrying strictly weaker protection
88
+ * than the one this build issues, under the same word.
89
+ */
90
+ readonly UNSALTED_PROOF: "unsalted_proof_refused";
91
+ /** The salted algorithm was named and no salt was carried. */
92
+ readonly SALT_MISSING: "salt_missing";
93
+ /** The message hashes to a different leaf than the proof is for — the message was altered. */
94
+ readonly MESSAGE_DOES_NOT_MATCH_LEAF: "message_does_not_match_leaf";
95
+ /** The audit path does not reconstruct the certified root from this leaf at this index. */
96
+ readonly PROOF_PATH_INVALID: "proof_path_invalid";
97
+ };
98
+ export type InclusionVerifyReason = (typeof INCLUSION_VERIFY_REASONS)[keyof typeof INCLUSION_VERIFY_REASONS];
99
+ /** What the reader should DO about each. Total over the union by construction. */
100
+ export declare const INCLUSION_VERIFY_GUIDANCE: Record<InclusionVerifyReason, string>;
101
+ export type InclusionVerifyResult = {
102
+ ok: true;
103
+ session_id: string;
104
+ leaf_index: number;
105
+ leaf_count: number;
106
+ certified_root: string;
107
+ content_hash_alg: ContentHashAlg;
108
+ /** Always false: no part of this check binds a session id. See the note at the return site. */
109
+ session_id_verified: false;
110
+ } | {
111
+ ok: false;
112
+ reason: InclusionVerifyReason;
113
+ detail: string;
114
+ guidance: string;
115
+ };
116
+ /**
117
+ * The Merkle root over an ordered list of leaf HASHES (hex).
118
+ *
119
+ * `kind: "hash"` because these values already ARE leaf hashes — the certified root the directory
120
+ * signs is built the same way (`directory-node.ts`, over each leaf's `s2.content_hash`), and
121
+ * applying a leaf prefix here would produce a root nobody else computes.
122
+ */
123
+ export declare function rootOverLeafHashes(leafHashesHex: readonly string[]): string;
124
+ /**
125
+ * Build the audit path for one leaf of a leaf-hash list.
126
+ *
127
+ * Delegates to `inclusionProof`. Deliberately NOT a local tree walk: the seal and the proof must
128
+ * come from the same Merkle implementation or they drift, and the drift is invisible until a real
129
+ * dispute.
130
+ */
131
+ export declare function proofPathFor(leafHashesHex: readonly string[], index: number): string[];
132
+ /**
133
+ * Is this a structurally valid v1 proof? Shape only — says nothing about whether it verifies.
134
+ *
135
+ * Separated so the daemon's verify handler can refuse a malformed object by name before it reaches
136
+ * any hashing, and so a test can assert the two failure classes apart.
137
+ */
138
+ export declare function isInclusionProofShape(value: unknown): value is InclusionProof;
139
+ /**
140
+ * VERIFY — the whole point of the file, and it touches no database.
141
+ *
142
+ * Three inputs and nothing else: the proof, the message bytes, and the root the caller took from the
143
+ * directory-signed certificate. That is what makes it runnable by a third party who has never seen
144
+ * the daemon that issued the proof.
145
+ *
146
+ * `certifiedRootHex` is REQUIRED and is the anchor. Making it optional — defaulting to the root
147
+ * inside the proof — would turn every call into the proof checking itself, which is the exact shape
148
+ * this feature exists to replace.
149
+ */
150
+ export declare function verifyInclusionProof(proof: unknown, messageBytes: Uint8Array, certifiedRootHex: string): InclusionVerifyResult;
151
+ //# sourceMappingURL=inclusion-proof.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inclusion-proof.d.ts","sourceRoot":"","sources":["../src/inclusion-proof.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAGH,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,wBAAwB,CAAC;AAEhC,sFAAsF;AACtF,MAAM,WAAW,cAAc;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACpB,iGAAiG;IACjG,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,2EAA2E;IAC3E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,gGAAgG;IAChG,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,kGAAkG;IAClG,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,iFAAiF;IACjF,QAAQ,CAAC,gBAAgB,EAAE,cAAc,CAAC;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB;IACnC,mFAAmF;;IAEnF,sFAAsF;;IAEtF;;;;;;;OAOG;;IAEH,oEAAoE;;IAEpE;;;;;;;;OAQG;;IAEH,8DAA8D;;IAE9D,8FAA8F;;IAE9F,2FAA2F;;CAEnF,CAAC;AAEX,MAAM,MAAM,qBAAqB,GAC/B,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,OAAO,wBAAwB,CAAC,CAAC;AAE3E,kFAAkF;AAClF,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,qBAAqB,EAAE,MAAM,CAkC3E,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAC7B;IACE,EAAE,EAAE,IAAI,CAAC;IACT,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,cAAc,CAAC;IACjC,+FAA+F;IAC/F,mBAAmB,EAAE,KAAK,CAAC;CAC5B,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,qBAAqB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAYnF;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAG3E;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAGtF;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAkB7E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,OAAO,EACd,YAAY,EAAE,UAAU,EACxB,gBAAgB,EAAE,MAAM,GACvB,qBAAqB,CAgGvB"}
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Proving that ONE message sits under the root the directory notarized.
3
+ *
4
+ * ─── WHAT MAKES THIS A PROOF AND NOT A DATA STRUCTURE ────────────────────────────────────────
5
+ *
6
+ * Two things, and both are easy to get wrong in a way that still looks like a proof.
7
+ *
8
+ * **1. The root comes from the CERTIFICATE, never from the proof.** A proof that carries its own
9
+ * root and is checked against it proves that the machine which wrote the proof is self-consistent —
10
+ * and that machine is the one a sceptic distrusts. So `verifyInclusionProof` REQUIRES the root as a
11
+ * separate argument, supplied by whoever holds the directory-signed certificate, and the root inside
12
+ * the proof is only ever compared to it. Drop that argument and the whole file becomes theatre.
13
+ *
14
+ * **2. The leaf is recomputed from the MESSAGE BYTES, never taken from the proof.** The Merkle leaf
15
+ * is a content hash, and since `DOD-M15-SEALWIRE-1` that hash is `HMAC-SHA256(salt, 0x00 ‖ content)`
16
+ * for a salted session. A proof over the leaf hash alone answers "is this opaque 32-byte number in
17
+ * the tree", and the operator's question is about a sentence. So the salt and the algorithm NAME
18
+ * travel with the proof, the verifier recomputes the leaf from the plaintext it holds, and a message
19
+ * that differs by one byte produces a different leaf and fails — which is the assertion the whole
20
+ * feature exists to make.
21
+ *
22
+ * Neither hash nor Merkle maths is reimplemented here. `contentHashFor` (wire-content-hash.ts) is
23
+ * the daemon's ONE content-hash derivation and `verifyInclusion` (@cello-protocol/crypto) is the ONE
24
+ * RFC 6962 verifier. A second copy of either drifts from the seal, and the drift surfaces as a lost
25
+ * dispute rather than as a failing test.
26
+ *
27
+ * Crypto refs: RFC 6962 §2.1.1 (Merkle audit paths), RFC 2104 (HMAC), FIPS 180-4 (SHA-256).
28
+ */
29
+ import { verifyInclusion, buildMerkleTree, merkleRoot, inclusionProof } from "@cello-protocol/crypto";
30
+ import { CONTENT_HASH_ALGS, contentHashFor, isKnownContentHashAlg, } from "./wire-content-hash.js";
31
+ /**
32
+ * Why a verification did not conclude "verified".
33
+ *
34
+ * A CLOSED set with a total guidance map below, so a new code cannot be added without something the
35
+ * reader can act on. `message_does_not_match_leaf` and `proof_path_invalid` are the two that mean
36
+ * "the proof is bad"; the rest mean "this proof was not checkable as presented".
37
+ */
38
+ export const INCLUSION_VERIFY_REASONS = {
39
+ /** The proof object is not a v1 proof, or a field is missing / the wrong width. */
40
+ PROOF_MALFORMED: "proof_malformed",
41
+ /** The proof names a root that is not the one in the certificate the caller holds. */
42
+ ROOT_NOT_FROM_CERTIFICATE: "root_not_from_certificate",
43
+ /**
44
+ * The root SUPPLIED by the caller is not a 32-byte hex value — so there is nothing to compare.
45
+ *
46
+ * Separate from the reason above because that one's guidance says *"the proof lands on a DIFFERENT
47
+ * root than the certificate you supplied"*, and for a truncated paste or a stray quote that is
48
+ * false: no root was supplied at all. Naming the exit point instead of the cause is the defect
49
+ * Invariant 3 is about, and it costs an operator the one thing they can actually fix.
50
+ */
51
+ CERTIFIED_ROOT_MALFORMED: "certified_root_malformed",
52
+ /** The proof names a hash algorithm this build cannot reproduce. */
53
+ UNKNOWN_HASH_ALG: "unknown_content_hash_alg",
54
+ /**
55
+ * The proof is over an UNSALTED content hash. Refused rather than checked.
56
+ *
57
+ * There is no compatibility branch here on purpose. An unsalted leaf hash is `sha256(0x00 ‖
58
+ * content)` — a value anyone holding the plaintext can compute, so it correlates the message
59
+ * across every record that carries it, which is exactly what the session salt exists to stop.
60
+ * Verifying one anyway would hand back `ok: true` for a proof carrying strictly weaker protection
61
+ * than the one this build issues, under the same word.
62
+ */
63
+ UNSALTED_PROOF: "unsalted_proof_refused",
64
+ /** The salted algorithm was named and no salt was carried. */
65
+ SALT_MISSING: "salt_missing",
66
+ /** The message hashes to a different leaf than the proof is for — the message was altered. */
67
+ MESSAGE_DOES_NOT_MATCH_LEAF: "message_does_not_match_leaf",
68
+ /** The audit path does not reconstruct the certified root from this leaf at this index. */
69
+ PROOF_PATH_INVALID: "proof_path_invalid",
70
+ };
71
+ /** What the reader should DO about each. Total over the union by construction. */
72
+ export const INCLUSION_VERIFY_GUIDANCE = {
73
+ [INCLUSION_VERIFY_REASONS.PROOF_MALFORMED]: "This is not a well-formed CELLO inclusion proof. Ask whoever gave it to you for the exact JSON " +
74
+ "object cello_get_inclusion_proof returned — a proof that has been reformatted, truncated, or " +
75
+ "had fields renamed cannot be checked.",
76
+ [INCLUSION_VERIFY_REASONS.ROOT_NOT_FROM_CERTIFICATE]: "The proof lands on a DIFFERENT root than the certificate you supplied. It may be a proof for " +
77
+ "another session, or for an earlier seal of this one. Check the session id on both, and take the " +
78
+ "root from the certificate (cello_sealed_receipt reports it as sealed_root) — never from the proof.",
79
+ [INCLUSION_VERIFY_REASONS.CERTIFIED_ROOT_MALFORMED]: "The certified_root you supplied is not a 64-character hex value, so there was nothing to check " +
80
+ "the proof against and NOTHING about the proof has been established either way. Copy sealed_root " +
81
+ "from cello_sealed_receipt exactly — a truncated paste, an added quote or a stray newline is the " +
82
+ "usual cause.",
83
+ [INCLUSION_VERIFY_REASONS.UNKNOWN_HASH_ALG]: "The proof names a content-hash algorithm this build does not implement, so there is no value to " +
84
+ "compare against. This is a version difference, NOT evidence of tampering. Upgrade the client and " +
85
+ "check again before drawing any conclusion.",
86
+ [INCLUSION_VERIFY_REASONS.UNSALTED_PROOF]: "This proof is over an UNSALTED content hash, which this build does not accept — a leaf anyone " +
87
+ "holding the plaintext can recompute is the exact correlation the session salt exists to prevent. " +
88
+ "It has NOT been shown to be false; it has not been checked. Ask for a proof from a salted " +
89
+ "session (cello_sealed_receipt reports whether the session's content hashes are salted).",
90
+ [INCLUSION_VERIFY_REASONS.SALT_MISSING]: "The proof names the salted algorithm and carries no salt, so the leaf cannot be recomputed from " +
91
+ "the message. Ask for the proof to be re-issued; do not treat this as a failed verification.",
92
+ [INCLUSION_VERIFY_REASONS.MESSAGE_DOES_NOT_MATCH_LEAF]: "THE MESSAGE YOU SUPPLIED IS NOT THE ONE THIS PROOF IS ABOUT. Its bytes hash to a different leaf. " +
93
+ "Either the text was altered (even by one character, or by trailing whitespace a copy/paste added) " +
94
+ "or this proof belongs to a different message. Compare against the exact bytes from cello_transcript.",
95
+ [INCLUSION_VERIFY_REASONS.PROOF_PATH_INVALID]: "The audit path does not rebuild the certified root from this message. The proof does not " +
96
+ "establish that this message is in the sealed conversation. Ask for a freshly issued proof; if a " +
97
+ "fresh one fails the same way, the record and the certificate genuinely disagree.",
98
+ };
99
+ const HEX32 = /^[0-9a-f]{64}$/;
100
+ function hexToBytes(hex) {
101
+ return new Uint8Array(Buffer.from(hex, "hex"));
102
+ }
103
+ function bytesToHex(bytes) {
104
+ return Buffer.from(bytes).toString("hex");
105
+ }
106
+ /**
107
+ * The Merkle root over an ordered list of leaf HASHES (hex).
108
+ *
109
+ * `kind: "hash"` because these values already ARE leaf hashes — the certified root the directory
110
+ * signs is built the same way (`directory-node.ts`, over each leaf's `s2.content_hash`), and
111
+ * applying a leaf prefix here would produce a root nobody else computes.
112
+ */
113
+ export function rootOverLeafHashes(leafHashesHex) {
114
+ const inputs = leafHashesHex.map((h) => ({ kind: "hash", data: hexToBytes(h) }));
115
+ return bytesToHex(merkleRoot(buildMerkleTree(inputs)));
116
+ }
117
+ /**
118
+ * Build the audit path for one leaf of a leaf-hash list.
119
+ *
120
+ * Delegates to `inclusionProof`. Deliberately NOT a local tree walk: the seal and the proof must
121
+ * come from the same Merkle implementation or they drift, and the drift is invisible until a real
122
+ * dispute.
123
+ */
124
+ export function proofPathFor(leafHashesHex, index) {
125
+ const inputs = leafHashesHex.map((h) => ({ kind: "hash", data: hexToBytes(h) }));
126
+ return inclusionProof(buildMerkleTree(inputs), index).map(bytesToHex);
127
+ }
128
+ /**
129
+ * Is this a structurally valid v1 proof? Shape only — says nothing about whether it verifies.
130
+ *
131
+ * Separated so the daemon's verify handler can refuse a malformed object by name before it reaches
132
+ * any hashing, and so a test can assert the two failure classes apart.
133
+ */
134
+ export function isInclusionProofShape(value) {
135
+ if (typeof value !== "object" || value === null)
136
+ return false;
137
+ const p = value;
138
+ if (p["version"] !== 1)
139
+ return false;
140
+ if (typeof p["session_id"] !== "string" || p["session_id"].length === 0)
141
+ return false;
142
+ if (typeof p["certified_root"] !== "string" || !HEX32.test(p["certified_root"]))
143
+ return false;
144
+ if (typeof p["leaf_hash"] !== "string" || !HEX32.test(p["leaf_hash"]))
145
+ return false;
146
+ if (!Number.isInteger(p["leaf_index"]) || p["leaf_index"] < 0)
147
+ return false;
148
+ if (!Number.isInteger(p["leaf_count"]) || p["leaf_count"] <= 0)
149
+ return false;
150
+ if (p["leaf_index"] >= p["leaf_count"])
151
+ return false;
152
+ const path = p["proof_path"];
153
+ if (!Array.isArray(path) || path.some((s) => typeof s !== "string" || !HEX32.test(s)))
154
+ return false;
155
+ if (typeof p["content_hash_alg"] !== "string")
156
+ return false;
157
+ const salt = p["content_salt"];
158
+ if (salt !== null && (typeof salt !== "string" || salt.length === 0 || !/^([0-9a-f]{2})+$/.test(salt))) {
159
+ return false;
160
+ }
161
+ return true;
162
+ }
163
+ /**
164
+ * VERIFY — the whole point of the file, and it touches no database.
165
+ *
166
+ * Three inputs and nothing else: the proof, the message bytes, and the root the caller took from the
167
+ * directory-signed certificate. That is what makes it runnable by a third party who has never seen
168
+ * the daemon that issued the proof.
169
+ *
170
+ * `certifiedRootHex` is REQUIRED and is the anchor. Making it optional — defaulting to the root
171
+ * inside the proof — would turn every call into the proof checking itself, which is the exact shape
172
+ * this feature exists to replace.
173
+ */
174
+ export function verifyInclusionProof(proof, messageBytes, certifiedRootHex) {
175
+ const fail = (reason, detail) => ({
176
+ ok: false,
177
+ reason,
178
+ detail,
179
+ guidance: INCLUSION_VERIFY_GUIDANCE[reason],
180
+ });
181
+ if (!isInclusionProofShape(proof)) {
182
+ return fail(INCLUSION_VERIFY_REASONS.PROOF_MALFORMED, "the proof is not a version-1 inclusion proof with the required fields at their required widths");
183
+ }
184
+ if (typeof certifiedRootHex !== "string" || !HEX32.test(certifiedRootHex.toLowerCase())) {
185
+ return fail(INCLUSION_VERIFY_REASONS.CERTIFIED_ROOT_MALFORMED, `the certified root supplied is not a 32-byte hex value (got ${typeof certifiedRootHex === "string" ? `${certifiedRootHex.length} chars` : typeof certifiedRootHex})`);
186
+ }
187
+ const anchor = certifiedRootHex.toLowerCase();
188
+ if (proof.certified_root !== anchor) {
189
+ return fail(INCLUSION_VERIFY_REASONS.ROOT_NOT_FROM_CERTIFICATE, `the proof lands on ${proof.certified_root} and the certificate names ${anchor}`);
190
+ }
191
+ if (!isKnownContentHashAlg(proof.content_hash_alg)) {
192
+ return fail(INCLUSION_VERIFY_REASONS.UNKNOWN_HASH_ALG, `the proof names content-hash algorithm "${proof.content_hash_alg}"`);
193
+ }
194
+ if (proof.content_hash_alg !== CONTENT_HASH_ALGS.HMAC_SALT_V1) {
195
+ return fail(INCLUSION_VERIFY_REASONS.UNSALTED_PROOF, `the proof names content-hash algorithm "${proof.content_hash_alg}"; only ${CONTENT_HASH_ALGS.HMAC_SALT_V1} is accepted`);
196
+ }
197
+ if (proof.content_salt === null) {
198
+ return fail(INCLUSION_VERIFY_REASONS.SALT_MISSING, `algorithm ${proof.content_hash_alg} needs a salt and the proof carries none`);
199
+ }
200
+ // The leaf is DERIVED from the bytes in hand, never read out of the proof. This line is what makes
201
+ // a one-byte edit fail.
202
+ const recomputed = bytesToHex(contentHashFor(messageBytes, { alg: proof.content_hash_alg, salt: hexToBytes(proof.content_salt) }));
203
+ if (recomputed !== proof.leaf_hash) {
204
+ return fail(INCLUSION_VERIFY_REASONS.MESSAGE_DOES_NOT_MATCH_LEAF, `the message supplied hashes to ${recomputed} under ${proof.content_hash_alg}; the proof is for leaf ${proof.leaf_hash}`);
205
+ }
206
+ const verified = verifyInclusion(hexToBytes(recomputed), proof.leaf_index, proof.leaf_count, proof.proof_path.map(hexToBytes), hexToBytes(anchor));
207
+ if (!verified) {
208
+ return fail(INCLUSION_VERIFY_REASONS.PROOF_PATH_INVALID, `the audit path (${proof.proof_path.length} sibling hashes) does not rebuild ${anchor} from leaf ${proof.leaf_index} of ${proof.leaf_count}`);
209
+ }
210
+ return {
211
+ ok: true,
212
+ /**
213
+ * ⚠️ UNVERIFIED, AND THE FIELD SAYS SO ONE LEVEL UP — the caller must not present this as checked.
214
+ *
215
+ * Nothing here binds a session id: the anchor is the ROOT, and the root is what the certificate
216
+ * signs. This value is copied out of the proof, so a relabelled proof reports a session it was
217
+ * never checked against. It is returned because a reader holding several proofs needs to tell
218
+ * them apart, not because it has been established.
219
+ */
220
+ session_id: proof.session_id,
221
+ session_id_verified: false,
222
+ leaf_index: proof.leaf_index,
223
+ leaf_count: proof.leaf_count,
224
+ certified_root: anchor,
225
+ content_hash_alg: proof.content_hash_alg,
226
+ };
227
+ }
228
+ //# sourceMappingURL=inclusion-proof.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inclusion-proof.js","sourceRoot":"","sources":["../src/inclusion-proof.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"initiate-session-handler.d.ts","sourceRoot":"","sources":["../src/initiate-session-handler.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACxF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAA2B,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEnH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAEjE,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,eAAe,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IACtE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,YAAY,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,CAAC;IAC9D,mBAAmB,EAAE,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,EAAE,aAAa,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACjG,yBAAyB,EAAE,OAAO,CAAC;IACnC,yBAAyB,EAAE,iBAAiB,CAAC;IAC7C,iBAAiB,EAAE,kBAAkB,CAAC;IACtC,cAAc,EAAE,eAAe,CAAC;IAChC,uBAAuB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,KAAK,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAAC;IACvH,sBAAsB,CAAC,EAAE,MAAM,MAAM,CAAC;CACvC;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,mBAAmB,GAAG;IACzE;;;OAGG;IACH,aAAa,CACX,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAC1C,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACpC;;;;;;;;;OASG;IACH,cAAc,CACZ,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,GAC/B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACrC,CA0LA"}
1
+ {"version":3,"file":"initiate-session-handler.d.ts","sourceRoot":"","sources":["../src/initiate-session-handler.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACxF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAA2B,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAGnH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAEjE,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,eAAe,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IACtE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,YAAY,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,CAAC;IAC9D,mBAAmB,EAAE,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,EAAE,aAAa,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACjG,yBAAyB,EAAE,OAAO,CAAC;IACnC,yBAAyB,EAAE,iBAAiB,CAAC;IAC7C,iBAAiB,EAAE,kBAAkB,CAAC;IACtC,cAAc,EAAE,eAAe,CAAC;IAChC,uBAAuB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,KAAK,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAAC;IACvH,sBAAsB,CAAC,EAAE,MAAM,MAAM,CAAC;CACvC;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,mBAAmB,GAAG;IACzE;;;OAGG;IACH,aAAa,CACX,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAC1C,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACpC;;;;;;;;;OASG;IACH,cAAc,CACZ,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,GAC/B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACrC,CA0NA"}
@@ -11,6 +11,7 @@
11
11
  import { randomUUID } from "node:crypto";
12
12
  import { selectAdvertisedAddress } from "./transport-selector.js";
13
13
  import { TIER } from "./contacts-tier-migration.js";
14
+ import { relayOnlyState, dialableAddrs } from "./relay-only.js";
14
15
  /**
15
16
  * Registers `cello_initiate_session` and returns the agent-scoped opener behind it, so a worker can
16
17
  * open a session without an IPC connection. See `openSessionAs`.
@@ -130,12 +131,42 @@ export function registerInitiateSessionHandler(deps) {
130
131
  // directly-reachable one — localhost or a public addr — advertises a direct multiaddr), so
131
132
  // attempt the dial whenever the assignment carries counterparty session addrs, regardless
132
133
  // of the transport_mode LABEL (the local selector stub labels everything "relay" even when
133
- // the addrs are directly dialable). A failure is NOT fatal: per the dead-channel contract,
134
+ // the addrs are directly dialable).
135
+ //
136
+ // ⚠️ DOD-M15-RELAYONLY-1 NARROWED THIS: the label is still not the authority, but the ADDRESS
137
+ // SET now is. Under relay-only only `/p2p-circuit` addrs are dialled — see `dialableAddrs`.
138
+ //
139
+ // A failure is NOT fatal: per the dead-channel contract,
134
140
  // the session stays active and a later cello_send queues the content in the durable retry
135
141
  // queue until a route exists (the relay-park path is MSG-001-3b).
136
142
  const counterpartyAddrs = assignment.counterparty_session_addrs ?? [];
137
- if (counterpartyAddrs.length > 0) {
138
- const connected = await sessionNodeManager.connectToCounterparty(agentName, sessionId, counterpartyAddrs);
143
+ // DOD-M15-RELAYONLY-1: the OTHER half of the control. Suppressing our own published addresses
144
+ // stops them dialing US; this stops us handing our IP to THEM. Both are needed, because the
145
+ // counterparty may not be relay-only themselves — they will still advertise addresses, and the
146
+ // gate below is otherwise satisfied by exactly that.
147
+ // ⚠️ TRI-STATE HERE TOO. The publish half was fixed to treat "cannot read the setting" as
148
+ // distinct from "off"; leaving the DIAL half on the plain boolean kept the old failure direction
149
+ // on this side — a closed or not-yet-opened database read as `false` and the operator's IP went
150
+ // out on the dial. `unknown` is treated as ON for the same reason it is when publishing: a
151
+ // narrowed route is recoverable and a disclosed address is not.
152
+ const relayOnly = relayOnlyState((key) => sessionNodeManager.getSetting(agentName, key), sessionNodeManager.hasDatabase()) !== "off";
153
+ const dialable = dialableAddrs(counterpartyAddrs, relayOnly);
154
+ if (relayOnly && counterpartyAddrs.length > dialable.length) {
155
+ logger.info("session.initiate.direct_dial.suppressed", {
156
+ sessionId,
157
+ suppressed: counterpartyAddrs.length - dialable.length,
158
+ dialing: dialable.length,
159
+ impact: "relay-only is on: dialling only the counterparty's relay-circuit address, which terminates " +
160
+ "at the relay, and dropping any direct address that would reveal this node's own",
161
+ correlationId,
162
+ });
163
+ }
164
+ // ⚠️ THE FILTERED LIST, not a boolean. Relay-only does not mean "do not connect" — it means
165
+ // "connect only over the circuit". Refusing EVERY address (the first build) also refused the
166
+ // `/p2p-circuit` one, which is the relay route this setting exists to force everything onto, and
167
+ // dropped every session onto the store-and-forward backstop.
168
+ if (dialable.length > 0) {
169
+ const connected = await sessionNodeManager.connectToCounterparty(agentName, sessionId, dialable);
139
170
  if (!connected.ok) {
140
171
  logger.warn("session.initiate.connect.failed", {
141
172
  sessionId,
@@ -1 +1 @@
1
- {"version":3,"file":"initiate-session-handler.js","sourceRoot":"","sources":["../src/initiate-session-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAKzC,OAAO,EAAE,uBAAuB,EAAmD,MAAM,yBAAyB,CAAC;AACnH,OAAO,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AAuBpD;;;GAGG;AACH,MAAM,UAAU,8BAA8B,CAAC,IAAyB;IAwBtE,MAAM,EACJ,QAAQ,EAAE,MAAM,EAAE,kBAAkB,EAAE,YAAY,EAAE,mBAAmB,EACvE,yBAAyB,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,cAAc,EACvF,uBAAuB,EAAE,sBAAsB,GAChD,GAAG,IAAI,CAAC;IAET,+EAA+E;IAC/E,4EAA4E;IAC5E,QAAQ;IACR,gCAAgC;IAChC,sEAAsE;IACtE,gFAAgF;IAChF,gFAAgF;IAChF,sEAAsE;IACtE,+EAA+E;IAC/E,2EAA2E;IAC3E,oFAAoF;IACpF,uEAAuE;IACvE,mFAAmF;IACnF,4BAA4B;IAC5B;;;;;;;;;;;;OAYG;IACH,KAAK,UAAU,aAAa,CAC1B,SAAiB,EACjB,MAA2C;QAE3C,MAAM,aAAa,GAAG,UAAU,EAAE,CAAC;QAEnC,+EAA+E;QAC/E,8EAA8E;QAC9E,MAAM,WAAW,GAAG,cAAc,CAAC,cAAc,EAAE,CAAC;QACpD,MAAM,gBAAgB,GAAG,sBAAsB,CAAC,CAAC,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChF,MAAM,iBAAiB,GAAG,uBAAuB,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;QAEjF,iFAAiF;QACjF,qFAAqF;QACrF,wFAAwF;QACxF,MAAM,WAAW,GAAG,MAAM,yBAAyB,CAAC,SAAS,CAAC;YAC5D,SAAS;YACT,aAAa;YACb,iBAAiB;YACjB,MAAM,EAAE,MAAM,IAAI,EAAE;SACrB,CAAC,CAAC;QACH,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC;YACpB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,WAAW,CAAC,QAAQ,EAAE,CAAC;QACnF,CAAC;QAED,8EAA8E;QAC9E,4DAA4D;QAC5D,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC;QAE1C,sFAAsF;QACtF,yFAAyF;QACzF,+EAA+E;QAC/E,qFAAqF;QACrF,mFAAmF;QACnF,gFAAgF;QAChF,+DAA+D;QAC/D,IAAI,CAAC,UAAU,CAAC,4BAA4B,EAAE,CAAC;YAC7C,MAAM,CAAC,IAAI,CAAC,2CAA2C,EAAE;gBACvD,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAC7D,SAAS;gBACT,aAAa;aACd,CAAC,CAAC;YACH,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,0BAA0B;gBAClC,QAAQ,EAAE,2OAA2O;aACtP,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC;QAC3E,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAErE,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,2EAA2E;YAC3E,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;QACzE,CAAC;QAED,mFAAmF;QACnF,kFAAkF;QAClF,iFAAiF;QACjF,oFAAoF;QACpF,iFAAiF;QACjF,sFAAsF;QACtF,EAAE;QACF,iFAAiF;QACjF,qFAAqF;QACrF,iFAAiF;QACjF,iFAAiF;QACjF,8DAA8D;QAC9D,sFAAsF;QACtF,oFAAoF;QACpF,kFAAkF;QAClF,qFAAqF;QACrF,4EAA4E;QAC5E,MAAM,kBAAkB,GACtB,OAAO,MAAM,EAAE,aAAa,KAAK,QAAQ;YACvC,CAAC,CAAC,MAAM,CAAC,aAAa;YACtB,CAAC,CAAC,OAAO,MAAM,EAAE,mBAAmB,KAAK,QAAQ;gBAC/C,CAAC,CAAC,MAAM,CAAC,mBAAmB;gBAC5B,CAAC,CAAC,EAAE,CAAC;QACX,MAAM,kBAAkB,GAAG,UAAU,CAAC,4BAA4B,IAAI,EAAE,CAAC;QACzE,qFAAqF;QACrF,qFAAqF;QACrF,MAAM,WAAW,GAAG,MAAM,uBAAuB,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QACzE,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,iBAAiB,CACxD,SAAS,EACT,SAAS,EACT,kBAAkB,EAClB,kBAAkB,EAClB,aAAa;QACb,qFAAqF;QACrF,+EAA+E;QAC/E,IAAI,EACJ,WAAW,CACZ,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;YAChB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;QAC3E,CAAC;QAED,uFAAuF;QACvF,yFAAyF;QACzF,0FAA0F;QAC1F,2FAA2F;QAC3F,0FAA0F;QAC1F,2FAA2F;QAC3F,2FAA2F;QAC3F,0FAA0F;QAC1F,kEAAkE;QAClE,MAAM,iBAAiB,GAAG,UAAU,CAAC,0BAA0B,IAAI,EAAE,CAAC;QACtE,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjC,MAAM,SAAS,GAAG,MAAM,kBAAkB,CAAC,qBAAqB,CAAC,SAAS,EAAE,SAAS,EAAE,iBAAiB,CAAC,CAAC;YAC1G,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;gBAClB,MAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE;oBAC7C,SAAS;oBACT,MAAM,EAAE,SAAS,CAAC,MAAM;oBACxB,KAAK,EAAE,SAAS,CAAC,KAAK;oBACtB,aAAa,EAAE,UAAU,CAAC,cAAc;oBACxC,aAAa;iBACd,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,4FAA4F;QAC5F,kGAAkG;QAClG,+FAA+F;QAC/F,0CAA0C;QAC1C,kBAAkB,CAAC,UAAU,CAAC,SAAS,EAAE,kBAAkB,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAEjG,gFAAgF;QAChF,wEAAwE;QACxE,IAAI,CAAC,eAAe,EAAE,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;QACtD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,CAAC,IAAI,EAAE,aAAa,EAAE,CAAC;IAC5E,CAAC;IAED,QAAQ,CAAC,GAAG,CAAC,wBAAwB,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE;QACpE,MAAM,SAAS,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;QAC7C,4FAA4F;QAC5F,gGAAgG;QAChG,iGAAiG;QACjG,MAAM,SAAS,GAAG,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,KAA2B,CAAC,CAAC;QACtF,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,yBAAyB,CAAC;QACnC,CAAC;QACD,OAAO,aAAa,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,aAAa;QACb,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE;QACpC,+DAA+D;QAC/D,aAAa,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC;KACnE,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"initiate-session-handler.js","sourceRoot":"","sources":["../src/initiate-session-handler.ts"],"names":[],"mappings":"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"}
@@ -21,16 +21,5 @@ export interface ManifestDeps {
21
21
  manifestVersionStore?: IManifestVersionStore;
22
22
  manifestPollScheduler?: IManifestPollScheduler;
23
23
  }
24
- /**
25
- * Build the consortium-manifest deps.
26
- *
27
- * CELLO_CONSORTIUM_MANIFEST absolute path to an override manifest JSON (opt-in)
28
- * CELLO_CONSORTIUM_ROOT_KEYS comma-separated officer root pubkeys (hex) — override path only
29
- * CELLO_CONSORTIUM_THRESHOLD minimum officer signatures (integer) — override path only
30
- * CELLO_MANIFEST_POLL_MIN_MS / _MAX_MS optional background poll window — override path only
31
- *
32
- * The single manifestProvider instance is shared between startDaemon's loadAndVerify call and the
33
- * ManifestDirectoryChallengeVerifier, so step-6 reads the same cached, verified manifest.
34
- */
35
24
  export declare function buildManifestDeps(logger: Logger): ManifestDeps;
36
25
  //# sourceMappingURL=manifest-deps.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"manifest-deps.d.ts","sourceRoot":"","sources":["../src/manifest-deps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC5B,MAAM,2BAA2B,CAAC;AASnC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAYzC,MAAM,WAAW,YAAY;IAC3B,gBAAgB,CAAC,EAAE,iBAAiB,CAAC;IACrC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,2BAA2B,CAAC;IAChD,oBAAoB,CAAC,EAAE,qBAAqB,CAAC;IAC7C,qBAAqB,CAAC,EAAE,sBAAsB,CAAC;CAChD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CA8F9D"}
1
+ {"version":3,"file":"manifest-deps.d.ts","sourceRoot":"","sources":["../src/manifest-deps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC5B,MAAM,2BAA2B,CAAC;AASnC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAazC,MAAM,WAAW,YAAY;IAC3B,gBAAgB,CAAC,EAAE,iBAAiB,CAAC;IACrC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,2BAA2B,CAAC;IAChD,oBAAoB,CAAC,EAAE,qBAAqB,CAAC;IAC7C,qBAAqB,CAAC,EAAE,sBAAsB,CAAC;CAChD;AA4CD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAgG9D"}
@@ -16,6 +16,7 @@ import { FileManifestProvider, EmbeddedManifestProvider } from "./file-manifest-
16
16
  import { BUNDLED_CONSORTIUM_MANIFEST, BUNDLED_CONSORTIUM_ROOT_KEYS, BUNDLED_CONSORTIUM_THRESHOLD, } from "./bundled-consortium-manifest.js";
17
17
  import { resolveDirectoryUrl } from "./directory-bootstrap.js";
18
18
  import { RandomizedPollScheduler } from "./manifest-poll-scheduler.js";
19
+ import { remedyFor } from "./manifest-validity.js";
19
20
  /** Normalize a directory URL for comparison (trim, drop trailing slashes, lowercase). */
20
21
  function normalizeUrl(u) {
21
22
  return u.trim().replace(/\/+$/, "").toLowerCase();
@@ -33,6 +34,31 @@ const BUNDLED_ENDPOINTS = new Set(BUNDLED_CONSORTIUM_MANIFEST.nodes.map((n) => n
33
34
  * The single manifestProvider instance is shared between startDaemon's loadAndVerify call and the
34
35
  * ManifestDirectoryChallengeVerifier, so step-6 reads the same cached, verified manifest.
35
36
  */
37
+ /**
38
+ * DOD-M15-EXPIRY-CONSUMER-POLICY-1 — ONE callback, built per origin.
39
+ *
40
+ * It was duplicated verbatim across the bundled and file branches, and the one place the two copies
41
+ * had to DIFFER was the one place they were identical: the remedy. "Install a current manifest and
42
+ * restart" is advice that cannot be followed on the bundled path — the manifest is compiled in, that
43
+ * branch wires no poll, so it can never self-heal — and the workaround an operator reaches for
44
+ * instead (repointing CELLO_DIRECTORY_URL) starts the daemon with directory identity authentication
45
+ * SILENTLY OFF. Guidance that routes a stuck operator into disabling a security control is a defect
46
+ * in the guidance, which `remedyFor` already exists to prevent.
47
+ */
48
+ function lapsedManifestReporter(logger, origin) {
49
+ return (info) => {
50
+ logger.warn("directory.auth.manifest.lapsed", {
51
+ ...info,
52
+ origin,
53
+ impact: "a directory node was SUCCESSFULLY authenticated against a manifest whose validity window " +
54
+ "has closed, so its key was trusted on the strength of a check that has expired. If that " +
55
+ "node has been rotated or removed since, this daemon would not know.",
56
+ guidance: "Signaling was NOT blocked — refusing here would leave a long-running daemon unable to " +
57
+ "authenticate any directory, taking every agent offline. " + remedyFor(origin) +
58
+ " cello_status reports the expiry.",
59
+ });
60
+ };
61
+ }
36
62
  export function buildManifestDeps(logger) {
37
63
  const manifestPath = process.env.CELLO_CONSORTIUM_MANIFEST;
38
64
  if (!manifestPath) {
@@ -74,7 +100,7 @@ export function buildManifestDeps(logger) {
74
100
  return {};
75
101
  }
76
102
  const manifestProvider = new EmbeddedManifestProvider(BUNDLED_CONSORTIUM_MANIFEST);
77
- const challengeVerifier = new ManifestDirectoryChallengeVerifier(manifestProvider);
103
+ const challengeVerifier = new ManifestDirectoryChallengeVerifier(manifestProvider, lapsedManifestReporter(logger, "bundled"));
78
104
  logger.info("daemon.manifest.bundled", {
79
105
  version: BUNDLED_CONSORTIUM_MANIFEST.version,
80
106
  nodeCount: BUNDLED_CONSORTIUM_MANIFEST.nodes.length,
@@ -95,7 +121,7 @@ export function buildManifestDeps(logger) {
95
121
  throw new Error("CELLO_CONSORTIUM_MANIFEST is set but CELLO_CONSORTIUM_ROOT_KEYS / CELLO_CONSORTIUM_THRESHOLD are missing or invalid");
96
122
  }
97
123
  const manifestProvider = new FileManifestProvider({ path: manifestPath });
98
- const challengeVerifier = new ManifestDirectoryChallengeVerifier(manifestProvider);
124
+ const challengeVerifier = new ManifestDirectoryChallengeVerifier(manifestProvider, lapsedManifestReporter(logger, "file"));
99
125
  // DOD-AUTH-2: background manifest poll. The directory is re-polled on a randomized 6–12h interval
100
126
  // (thundering-herd avoidance) and a newer signed manifest is adopted. The interval is env-injectable
101
127
  // so the live binary test can poll sub-second instead of waiting hours; production leaves these
@@ -1 +1 @@
1
- {"version":3,"file":"manifest-deps.js","sourceRoot":"","sources":["../src/manifest-deps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,kCAAkC,GAKnC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC7F,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,yFAAyF;AACzF,SAAS,YAAY,CAAC,CAAS;IAC7B,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;AACpD,CAAC;AAED,gFAAgF;AAChF,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAC/B,2BAA2B,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,CAAE,CAA6B,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAC/G,CAAC;AAWF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;IAC3D,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,8FAA8F;QAC9F,6FAA6F;QAC7F,8FAA8F;QAC9F,8FAA8F;QAC9F,iGAAiG;QACjG,+FAA+F;QAC/F,+FAA+F;QAC/F,+FAA+F;QAC/F,EAAE;QACF,6FAA6F;QAC7F,+FAA+F;QAC/F,iGAAiG;QACjG,4FAA4F;QAC5F,iGAAiG;QACjG,6FAA6F;QAC7F,+FAA+F;QAC/F,mGAAmG;QACnG,4FAA4F;QAC5F,EAAE;QACF,iGAAiG;QACjG,gGAAgG;QAChG,uFAAuF;QACvF,MAAM,YAAY,GAAG,YAAY,CAAC,mBAAmB,EAAE,CAAC,CAAC;QACzD,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YACzC,6FAA6F;YAC7F,+FAA+F;YAC/F,qFAAqF;YACrF,6FAA6F;YAC7F,gEAAgE;YAChE,MAAM,OAAO,GAAG,iFAAiF,CAAC,IAAI,CACpG,YAAY,CACb,CAAC;YACF,MAAM,MAAM,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,iCAAiC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;YAC9F,IAAI,OAAO;gBAAE,MAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE,MAAM,CAAC,CAAC;;gBAC/D,MAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE,MAAM,CAAC,CAAC;YAC5D,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,gBAAgB,GAAG,IAAI,wBAAwB,CAAC,2BAA2B,CAAC,CAAC;QACnF,MAAM,iBAAiB,GAAG,IAAI,kCAAkC,CAAC,gBAAgB,CAAC,CAAC;QACnF,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE;YACrC,OAAO,EAAE,2BAA2B,CAAC,OAAO;YAC5C,SAAS,EAAE,2BAA2B,CAAC,KAAK,CAAC,MAAM;YACnD,YAAY,EAAE,4BAA4B,CAAC,MAAM;YACjD,SAAS,EAAE,4BAA4B;SACxC,CAAC,CAAC;QACH,OAAO;YACL,gBAAgB;YAChB,gBAAgB,EAAE,4BAA4B;YAC9C,iBAAiB,EAAE,4BAA4B;YAC/C,iBAAiB;SAClB,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,0BAA0B,IAAI,EAAE,CAAC;IACjE,MAAM,gBAAgB,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACjG,MAAM,iBAAiB,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,0BAA0B,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAC5F,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CACb,qHAAqH,CACtH,CAAC;IACJ,CAAC;IAED,MAAM,gBAAgB,GAAG,IAAI,oBAAoB,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;IAC1E,MAAM,iBAAiB,GAAG,IAAI,kCAAkC,CAAC,gBAAgB,CAAC,CAAC;IACnF,kGAAkG;IAClG,qGAAqG;IACrG,gGAAgG;IAChG,8FAA8F;IAC9F,mGAAmG;IACnG,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC;IAC1D,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC;IAC1D,IAAI,QAAsD,CAAC;IAC3D,IAAI,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QACzD,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,UAAU,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,UAAU,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACpD,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,GAAG,KAAK,EAAE,CAAC;YAC9E,MAAM,IAAI,KAAK,CACb,4FAA4F,CAC7F,CAAC;QACJ,CAAC;QACD,QAAQ,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC;IACD,MAAM,qBAAqB,GAAG,IAAI,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IACpE,MAAM,CAAC,IAAI,CAAC,4BAA4B,EAAE;QACxC,YAAY;QACZ,YAAY,EAAE,gBAAgB,CAAC,MAAM;QACrC,SAAS,EAAE,iBAAiB;QAC5B,SAAS,EAAE,QAAQ,EAAE,KAAK,IAAI,IAAI;QAClC,SAAS,EAAE,QAAQ,EAAE,KAAK,IAAI,IAAI;KACnC,CAAC,CAAC;IACH,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,CAAC;AAC7G,CAAC"}
1
+ {"version":3,"file":"manifest-deps.js","sourceRoot":"","sources":["../src/manifest-deps.ts"],"names":[],"mappings":"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"}
@@ -124,6 +124,8 @@ export declare function classifyManifestValidity(manifest: Pick<ConsortiumManife
124
124
  * guidance.
125
125
  */
126
126
  export type ManifestOrigin = "bundled" | "file";
127
+ /** What to actually DO about a manifest that needs replacing, given where it came from. */
128
+ export declare function remedyFor(origin: ManifestOrigin): string;
127
129
  export declare function describeManifestValidity(v: ManifestValidity, origin?: ManifestOrigin): Record<string, unknown> | undefined;
128
130
  /** Minimal structural logger — `domain.noun.verb` taxonomy, injected. */
129
131
  export interface ManifestValidityLogger {
@@ -1 +1 @@
1
- {"version":3,"file":"manifest-validity.d.ts","sourceRoot":"","sources":["../src/manifest-validity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEzE;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,QAAiB,CAAC;AAEzD,MAAM,MAAM,gBAAgB,GACxB;IAAE,KAAK,EAAE,gBAAgB,CAAA;CAAE,GAC3B;IAAE,KAAK,EAAE,eAAe,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AAC/C;;;;;;;GAOG;GACD;IAAE,KAAK,EAAE,mBAAmB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,KAAK,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,GACrE;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,IAAI,CAAC,kBAAkB,EAAE,YAAY,GAAG,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,EAC/E,KAAK,EAAE,MAAM,GACZ,gBAAgB,CAgDlB;AAED;;;;;;GAMG;AACH;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,MAAM,CAAC;AAahD,wBAAgB,wBAAwB,CACtC,CAAC,EAAE,gBAAgB,EACnB,MAAM,GAAE,cAAuB,GAC9B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CA+ErC;AAED,yEAAyE;AACzE,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzD,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzD,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC3D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE;IAC/C,WAAW,EAAE,MAAM,IAAI,CAAC,kBAAkB,EAAE,YAAY,GAAG,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;IACzF,MAAM,EAAE,sBAAsB,CAAC;IAC/B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB,GAAG,MAAM,gBAAgB,CAqDzB"}
1
+ {"version":3,"file":"manifest-validity.d.ts","sourceRoot":"","sources":["../src/manifest-validity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEzE;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,QAAiB,CAAC;AAEzD,MAAM,MAAM,gBAAgB,GACxB;IAAE,KAAK,EAAE,gBAAgB,CAAA;CAAE,GAC3B;IAAE,KAAK,EAAE,eAAe,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AAC/C;;;;;;;GAOG;GACD;IAAE,KAAK,EAAE,mBAAmB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,KAAK,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,GACrE;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,IAAI,CAAC,kBAAkB,EAAE,YAAY,GAAG,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,EAC/E,KAAK,EAAE,MAAM,GACZ,gBAAgB,CAgDlB;AAED;;;;;;GAMG;AACH;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,MAAM,CAAC;AAEhD,2FAA2F;AAC3F,wBAAgB,SAAS,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAQxD;AAED,wBAAgB,wBAAwB,CACtC,CAAC,EAAE,gBAAgB,EACnB,MAAM,GAAE,cAAuB,GAC9B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CA+ErC;AAED,yEAAyE;AACzE,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzD,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzD,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC3D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE;IAC/C,WAAW,EAAE,MAAM,IAAI,CAAC,kBAAkB,EAAE,YAAY,GAAG,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;IACzF,MAAM,EAAE,sBAAsB,CAAC;IAC/B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB,GAAG,MAAM,gBAAgB,CAqDzB"}
@@ -121,7 +121,7 @@ export function classifyManifestValidity(manifest, nowMs) {
121
121
  : { state: "valid", expires: manifest.expires, secondsRemaining };
122
122
  }
123
123
  /** What to actually DO about a manifest that needs replacing, given where it came from. */
124
- function remedyFor(origin) {
124
+ export function remedyFor(origin) {
125
125
  return origin === "bundled"
126
126
  ? "This daemon uses the COMPILED-IN consortium manifest, so there is no file to replace: " +
127
127
  "upgrade the @cello-protocol/connect package to get a newer one. Do NOT repoint " +