@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.
- package/dist/agent-settings-keys.d.ts.map +1 -1
- package/dist/agent-settings-keys.js +18 -0
- package/dist/agent-settings-keys.js.map +1 -1
- package/dist/close-session-handler.d.ts.map +1 -1
- package/dist/close-session-handler.js +90 -16
- package/dist/close-session-handler.js.map +1 -1
- package/dist/consortium-bootstrap.d.ts.map +1 -1
- package/dist/consortium-bootstrap.js +117 -2
- package/dist/consortium-bootstrap.js.map +1 -1
- package/dist/content-encryption-status.d.ts +97 -0
- package/dist/content-encryption-status.d.ts.map +1 -0
- package/dist/content-encryption-status.js +122 -0
- package/dist/content-encryption-status.js.map +1 -0
- package/dist/content-park-client.d.ts +10 -0
- package/dist/content-park-client.d.ts.map +1 -1
- package/dist/content-park-client.js +84 -3
- package/dist/content-park-client.js.map +1 -1
- package/dist/content-park.d.ts.map +1 -1
- package/dist/content-park.js +184 -13
- package/dist/content-park.js.map +1 -1
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +671 -67
- package/dist/daemon.js.map +1 -1
- package/dist/document-handlers.d.ts.map +1 -1
- package/dist/document-handlers.js +119 -0
- package/dist/document-handlers.js.map +1 -1
- package/dist/document-layer.d.ts +0 -2
- package/dist/document-layer.d.ts.map +1 -1
- package/dist/document-layer.js.map +1 -1
- package/dist/frame-values.d.ts.map +1 -1
- package/dist/frame-values.js +14 -0
- package/dist/frame-values.js.map +1 -1
- package/dist/inclusion-proof-handlers.d.ts +43 -0
- package/dist/inclusion-proof-handlers.d.ts.map +1 -0
- package/dist/inclusion-proof-handlers.js +565 -0
- package/dist/inclusion-proof-handlers.js.map +1 -0
- package/dist/inclusion-proof.d.ts +151 -0
- package/dist/inclusion-proof.d.ts.map +1 -0
- package/dist/inclusion-proof.js +228 -0
- package/dist/inclusion-proof.js.map +1 -0
- package/dist/initiate-session-handler.d.ts.map +1 -1
- package/dist/initiate-session-handler.js +34 -3
- package/dist/initiate-session-handler.js.map +1 -1
- package/dist/manifest-deps.d.ts +0 -11
- package/dist/manifest-deps.d.ts.map +1 -1
- package/dist/manifest-deps.js +28 -2
- package/dist/manifest-deps.js.map +1 -1
- package/dist/manifest-validity.d.ts +2 -0
- package/dist/manifest-validity.d.ts.map +1 -1
- package/dist/manifest-validity.js +1 -1
- package/dist/manifest-validity.js.map +1 -1
- package/dist/network-directory-node.d.ts +16 -0
- package/dist/network-directory-node.d.ts.map +1 -1
- package/dist/network-directory-node.js +40 -0
- package/dist/network-directory-node.js.map +1 -1
- package/dist/notification-handlers.d.ts.map +1 -1
- package/dist/notification-handlers.js +71 -2
- package/dist/notification-handlers.js.map +1 -1
- package/dist/outbound-sessions.d.ts +6 -0
- package/dist/outbound-sessions.d.ts.map +1 -1
- package/dist/outbound-sessions.js +50 -7
- package/dist/outbound-sessions.js.map +1 -1
- package/dist/park-envelope.d.ts +23 -0
- package/dist/park-envelope.d.ts.map +1 -1
- package/dist/park-envelope.js +76 -0
- package/dist/park-envelope.js.map +1 -1
- package/dist/register-handler.d.ts.map +1 -1
- package/dist/register-handler.js +76 -0
- package/dist/register-handler.js.map +1 -1
- package/dist/relay-only.d.ts +133 -0
- package/dist/relay-only.d.ts.map +1 -0
- package/dist/relay-only.js +183 -0
- package/dist/relay-only.js.map +1 -0
- package/dist/retry-queue.d.ts +26 -1
- package/dist/retry-queue.d.ts.map +1 -1
- package/dist/retry-queue.js +18 -1
- package/dist/retry-queue.js.map +1 -1
- package/dist/seal-coordinator.d.ts +51 -1
- package/dist/seal-coordinator.d.ts.map +1 -1
- package/dist/seal-coordinator.js +248 -1
- package/dist/seal-coordinator.js.map +1 -1
- package/dist/seal-escalation.d.ts.map +1 -1
- package/dist/seal-escalation.js +28 -0
- package/dist/seal-escalation.js.map +1 -1
- package/dist/seal-failure-store.d.ts.map +1 -1
- package/dist/seal-failure-store.js +5 -1
- package/dist/seal-failure-store.js.map +1 -1
- package/dist/sealed-leaf-set.d.ts +92 -0
- package/dist/sealed-leaf-set.d.ts.map +1 -0
- package/dist/sealed-leaf-set.js +129 -0
- package/dist/sealed-leaf-set.js.map +1 -0
- package/dist/session-ceremony.d.ts +27 -1
- package/dist/session-ceremony.d.ts.map +1 -1
- package/dist/session-ceremony.js +109 -7
- package/dist/session-ceremony.js.map +1 -1
- package/dist/session-content-handlers.d.ts +12 -0
- package/dist/session-content-handlers.d.ts.map +1 -1
- package/dist/session-content-handlers.js +39 -4
- package/dist/session-content-handlers.js.map +1 -1
- package/dist/session-node-manager.d.ts +387 -4
- package/dist/session-node-manager.d.ts.map +1 -1
- package/dist/session-node-manager.js +3529 -279
- package/dist/session-node-manager.js.map +1 -1
- package/dist/session-read-handlers.d.ts.map +1 -1
- package/dist/session-read-handlers.js +16 -1
- package/dist/session-read-handlers.js.map +1 -1
- package/dist/session-relay-client.d.ts +163 -1
- package/dist/session-relay-client.d.ts.map +1 -1
- package/dist/session-relay-client.js +540 -6
- package/dist/session-relay-client.js.map +1 -1
- package/dist/session-salt-agreement.d.ts +58 -4
- package/dist/session-salt-agreement.d.ts.map +1 -1
- package/dist/session-salt-agreement.js +110 -3
- package/dist/session-salt-agreement.js.map +1 -1
- package/dist/signal-submission.d.ts +11 -1
- package/dist/signal-submission.d.ts.map +1 -1
- package/dist/signal-submission.js.map +1 -1
- package/dist/signaling-connect.d.ts +18 -1
- package/dist/signaling-connect.d.ts.map +1 -1
- package/dist/signaling-connect.js +164 -1
- package/dist/signaling-connect.js.map +1 -1
- package/dist/submission-retry.d.ts +208 -0
- package/dist/submission-retry.d.ts.map +1 -0
- package/dist/submission-retry.js +505 -0
- package/dist/submission-retry.js.map +1 -0
- package/dist/types.d.ts +33 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vocabulary.d.ts +13 -3
- package/dist/vocabulary.d.ts.map +1 -1
- package/dist/vocabulary.js +14 -3
- package/dist/vocabulary.js.map +1 -1
- package/dist/wire-content-hash.d.ts +15 -3
- package/dist/wire-content-hash.d.ts.map +1 -1
- package/dist/wire-content-hash.js +15 -3
- package/dist/wire-content-hash.js.map +1 -1
- 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":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,cAAc,EAAkB,MAAM,wBAAwB,CAAC;AACtH,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,qBAAqB,GAEtB,MAAM,wBAAwB,CAAC;AA+BhC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,mFAAmF;IACnF,eAAe,EAAE,iBAAiB;IAClC,sFAAsF;IACtF,yBAAyB,EAAE,2BAA2B;IACtD;;;;;;;OAOG;IACH,wBAAwB,EAAE,0BAA0B;IACpD,oEAAoE;IACpE,gBAAgB,EAAE,0BAA0B;IAC5C;;;;;;;;OAQG;IACH,cAAc,EAAE,wBAAwB;IACxC,8DAA8D;IAC9D,YAAY,EAAE,cAAc;IAC5B,8FAA8F;IAC9F,2BAA2B,EAAE,6BAA6B;IAC1D,2FAA2F;IAC3F,kBAAkB,EAAE,oBAAoB;CAChC,CAAC;AAKX,kFAAkF;AAClF,MAAM,CAAC,MAAM,yBAAyB,GAA0C;IAC9E,CAAC,wBAAwB,CAAC,eAAe,CAAC,EACxC,iGAAiG;QACjG,+FAA+F;QAC/F,uCAAuC;IACzC,CAAC,wBAAwB,CAAC,yBAAyB,CAAC,EAClD,+FAA+F;QAC/F,kGAAkG;QAClG,oGAAoG;IACtG,CAAC,wBAAwB,CAAC,wBAAwB,CAAC,EACjD,iGAAiG;QACjG,kGAAkG;QAClG,kGAAkG;QAClG,cAAc;IAChB,CAAC,wBAAwB,CAAC,gBAAgB,CAAC,EACzC,kGAAkG;QAClG,mGAAmG;QACnG,4CAA4C;IAC9C,CAAC,wBAAwB,CAAC,cAAc,CAAC,EACvC,gGAAgG;QAChG,mGAAmG;QACnG,4FAA4F;QAC5F,yFAAyF;IAC3F,CAAC,wBAAwB,CAAC,YAAY,CAAC,EACrC,kGAAkG;QAClG,6FAA6F;IAC/F,CAAC,wBAAwB,CAAC,2BAA2B,CAAC,EACpD,mGAAmG;QACnG,oGAAoG;QACpG,sGAAsG;IACxG,CAAC,wBAAwB,CAAC,kBAAkB,CAAC,EAC3C,2FAA2F;QAC3F,kGAAkG;QAClG,kFAAkF;CACrF,CAAC;AAeF,MAAM,KAAK,GAAG,gBAAgB,CAAC;AAE/B,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,UAAU,CAAC,KAAiB;IACnC,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,aAAgC;IACjE,MAAM,MAAM,GAAgB,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACvG,OAAO,UAAU,CAAC,UAAU,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,aAAgC,EAAE,KAAa;IAC1E,MAAM,MAAM,GAAgB,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACvG,OAAO,cAAc,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AACxE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,IAAI,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,IAAI,OAAO,CAAC,CAAC,YAAY,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACtF,IAAI,OAAO,CAAC,CAAC,gBAAgB,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9F,IAAI,OAAO,CAAC,CAAC,WAAW,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACpF,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,IAAK,CAAC,CAAC,YAAY,CAAY,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACxF,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,IAAK,CAAC,CAAC,YAAY,CAAY,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACzF,IAAK,CAAC,CAAC,YAAY,CAAY,IAAK,CAAC,CAAC,YAAY,CAAY;QAAE,OAAO,KAAK,CAAC;IAC7E,MAAM,IAAI,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC;IAC7B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACpG,IAAI,OAAO,CAAC,CAAC,kBAAkB,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5D,MAAM,IAAI,GAAG,CAAC,CAAC,cAAc,CAAC,CAAC;IAC/B,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QACvG,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAAc,EACd,YAAwB,EACxB,gBAAwB;IAExB,MAAM,IAAI,GAAG,CAAC,MAA6B,EAAE,MAAc,EAAyB,EAAE,CAAC,CAAC;QACtF,EAAE,EAAE,KAAK;QACT,MAAM;QACN,MAAM;QACN,QAAQ,EAAE,yBAAyB,CAAC,MAAM,CAAC;KAC5C,CAAC,CAAC;IAEH,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,IAAI,CACT,wBAAwB,CAAC,eAAe,EACxC,gGAAgG,CACjG,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,gBAAgB,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QACxF,OAAO,IAAI,CACT,wBAAwB,CAAC,wBAAwB,EACjD,+DAA+D,OAAO,gBAAgB,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAC,OAAO,gBAAgB,GAAG,CACtK,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,WAAW,EAAE,CAAC;IAC9C,IAAI,KAAK,CAAC,cAAc,KAAK,MAAM,EAAE,CAAC;QACpC,OAAO,IAAI,CACT,wBAAwB,CAAC,yBAAyB,EAClD,sBAAsB,KAAK,CAAC,cAAc,8BAA8B,MAAM,EAAE,CACjF,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACnD,OAAO,IAAI,CACT,wBAAwB,CAAC,gBAAgB,EACzC,2CAA2C,KAAK,CAAC,gBAAgB,GAAG,CACrE,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,gBAAgB,KAAK,iBAAiB,CAAC,YAAY,EAAE,CAAC;QAC9D,OAAO,IAAI,CACT,wBAAwB,CAAC,cAAc,EACvC,2CAA2C,KAAK,CAAC,gBAAgB,WAAW,iBAAiB,CAAC,YAAY,cAAc,CACzH,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;QAChC,OAAO,IAAI,CACT,wBAAwB,CAAC,YAAY,EACrC,aAAa,KAAK,CAAC,gBAAgB,0CAA0C,CAC9E,CAAC;IACJ,CAAC;IAED,mGAAmG;IACnG,wBAAwB;IACxB,MAAM,UAAU,GAAG,UAAU,CAC3B,cAAc,CAAC,YAAY,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,gBAAgB,EAAE,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC,CACpG,CAAC;IAEF,IAAI,UAAU,KAAK,KAAK,CAAC,SAAS,EAAE,CAAC;QACnC,OAAO,IAAI,CACT,wBAAwB,CAAC,2BAA2B,EACpD,kCAAkC,UAAU,UAAU,KAAK,CAAC,gBAAgB,2BAA2B,KAAK,CAAC,SAAS,EAAE,CACzH,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,eAAe,CAC9B,UAAU,CAAC,UAAU,CAAC,EACtB,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,EAChC,UAAU,CAAC,MAAM,CAAC,CACnB,CAAC;IAEF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,CACT,wBAAwB,CAAC,kBAAkB,EAC3C,mBAAmB,KAAK,CAAC,UAAU,CAAC,MAAM,qCAAqC,MAAM,cAAc,KAAK,CAAC,UAAU,OAAO,KAAK,CAAC,UAAU,EAAE,CAC7I,CAAC;IACJ,CAAC;IAED,OAAO;QACL,EAAE,EAAE,IAAI;QACR;;;;;;;WAOG;QACH,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,mBAAmB,EAAE,KAAK;QAC1B,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,cAAc,EAAE,MAAM;QACtB,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;KACzC,CAAC;AACJ,CAAC"}
|
|
@@ -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;
|
|
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).
|
|
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
|
-
|
|
138
|
-
|
|
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;
|
|
1
|
+
{"version":3,"file":"initiate-session-handler.js","sourceRoot":"","sources":["../src/initiate-session-handler.ts"],"names":[],"mappings":"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"}
|
package/dist/manifest-deps.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/manifest-deps.js
CHANGED
|
@@ -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;
|
|
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;
|
|
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 " +
|