@cello-protocol/daemon 0.0.196 → 0.0.198
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-admin-handlers.d.ts +56 -0
- package/dist/agent-admin-handlers.d.ts.map +1 -0
- package/dist/agent-admin-handlers.js +70 -0
- package/dist/agent-admin-handlers.js.map +1 -0
- package/dist/agent-handlers.d.ts +8 -7
- package/dist/agent-handlers.d.ts.map +1 -1
- package/dist/agent-handlers.js.map +1 -1
- package/dist/agent-selection-root.d.ts +29 -0
- package/dist/agent-selection-root.d.ts.map +1 -0
- package/dist/agent-selection-root.js +126 -0
- package/dist/agent-selection-root.js.map +1 -0
- package/dist/attendance-wiring.d.ts +44 -0
- package/dist/attendance-wiring.d.ts.map +1 -0
- package/dist/attendance-wiring.js +432 -0
- package/dist/attendance-wiring.js.map +1 -0
- package/dist/backup-restore-handlers.d.ts +10 -0
- package/dist/backup-restore-handlers.d.ts.map +1 -0
- package/dist/backup-restore-handlers.js +82 -0
- package/dist/backup-restore-handlers.js.map +1 -0
- package/dist/boot-agents.d.ts +64 -0
- package/dist/boot-agents.d.ts.map +1 -0
- package/dist/boot-agents.js +241 -0
- package/dist/boot-agents.js.map +1 -0
- package/dist/boot-connection-state.d.ts +40 -0
- package/dist/boot-connection-state.d.ts.map +1 -0
- package/dist/boot-connection-state.js +136 -0
- package/dist/boot-connection-state.js.map +1 -0
- package/dist/boot-core.d.ts +36 -0
- package/dist/boot-core.d.ts.map +1 -0
- package/dist/boot-core.js +292 -0
- package/dist/boot-core.js.map +1 -0
- package/dist/boot-parked-content.d.ts +34 -0
- package/dist/boot-parked-content.d.ts.map +1 -0
- package/dist/boot-parked-content.js +527 -0
- package/dist/boot-parked-content.js.map +1 -0
- package/dist/boot-sweeps.d.ts +22 -0
- package/dist/boot-sweeps.d.ts.map +1 -0
- package/dist/boot-sweeps.js +50 -0
- package/dist/boot-sweeps.js.map +1 -0
- package/dist/connection-agents.d.ts +16 -0
- package/dist/connection-agents.d.ts.map +1 -0
- package/dist/connection-agents.js +68 -0
- package/dist/connection-agents.js.map +1 -0
- package/dist/content-park.d.ts.map +1 -1
- package/dist/content-park.js +274 -25
- package/dist/content-park.js.map +1 -1
- package/dist/daemon-handle.d.ts +57 -0
- package/dist/daemon-handle.d.ts.map +1 -0
- package/dist/daemon-handle.js +2 -0
- package/dist/daemon-handle.js.map +1 -0
- package/dist/daemon-status-report.d.ts +40 -0
- package/dist/daemon-status-report.d.ts.map +1 -0
- package/dist/daemon-status-report.js +78 -0
- package/dist/daemon-status-report.js.map +1 -0
- package/dist/daemon.d.ts +5 -66
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +332 -4894
- package/dist/daemon.js.map +1 -1
- package/dist/delivery-open-registry.d.ts +1 -1
- package/dist/delivery-open-registry.js +1 -1
- package/dist/directory-connect.d.ts +27 -0
- package/dist/directory-connect.d.ts.map +1 -0
- package/dist/directory-connect.js +98 -0
- package/dist/directory-connect.js.map +1 -0
- package/dist/disconnect-cleanup.d.ts +45 -0
- package/dist/disconnect-cleanup.d.ts.map +1 -0
- package/dist/disconnect-cleanup.js +65 -0
- package/dist/disconnect-cleanup.js.map +1 -0
- package/dist/document-surface.d.ts +32 -0
- package/dist/document-surface.d.ts.map +1 -0
- package/dist/document-surface.js +150 -0
- package/dist/document-surface.js.map +1 -0
- package/dist/document-wiring.d.ts +53 -0
- package/dist/document-wiring.d.ts.map +1 -0
- package/dist/document-wiring.js +323 -0
- package/dist/document-wiring.js.map +1 -0
- package/dist/held-content.d.ts +7 -3
- package/dist/held-content.d.ts.map +1 -1
- package/dist/held-content.js.map +1 -1
- package/dist/inbound-sessions.d.ts +9 -1
- package/dist/inbound-sessions.d.ts.map +1 -1
- package/dist/inbound-sessions.js +9 -1
- package/dist/inbound-sessions.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/ipc-surface.d.ts +44 -0
- package/dist/ipc-surface.d.ts.map +1 -0
- package/dist/ipc-surface.js +106 -0
- package/dist/ipc-surface.js.map +1 -0
- package/dist/network-directory-node.d.ts +0 -18
- package/dist/network-directory-node.d.ts.map +1 -1
- package/dist/network-directory-node.js +1 -38
- package/dist/network-directory-node.js.map +1 -1
- package/dist/notification-handlers.d.ts.map +1 -1
- package/dist/notification-handlers.js +2 -0
- package/dist/notification-handlers.js.map +1 -1
- package/dist/operator-guidance.d.ts +25 -0
- package/dist/operator-guidance.d.ts.map +1 -0
- package/dist/operator-guidance.js +50 -0
- package/dist/operator-guidance.js.map +1 -0
- package/dist/park-recovery.d.ts +22 -1
- package/dist/park-recovery.d.ts.map +1 -1
- package/dist/park-recovery.js.map +1 -1
- package/dist/park-refusals.d.ts +147 -0
- package/dist/park-refusals.d.ts.map +1 -0
- package/dist/park-refusals.js +331 -0
- package/dist/park-refusals.js.map +1 -0
- package/dist/refusal-notices.d.ts.map +1 -1
- package/dist/refusal-notices.js +22 -2
- package/dist/refusal-notices.js.map +1 -1
- package/dist/refusal-reasons.d.ts +13 -0
- package/dist/refusal-reasons.d.ts.map +1 -1
- package/dist/refusal-reasons.js +19 -0
- package/dist/refusal-reasons.js.map +1 -1
- package/dist/register-handler.d.ts +8 -7
- package/dist/register-handler.d.ts.map +1 -1
- package/dist/register-handler.js.map +1 -1
- package/dist/session-content-context.d.ts +144 -0
- package/dist/session-content-context.d.ts.map +1 -0
- package/dist/session-content-context.js +2 -0
- package/dist/session-content-context.js.map +1 -0
- package/dist/session-content-handlers.d.ts.map +1 -1
- package/dist/session-content-handlers.js +2 -0
- package/dist/session-content-handlers.js.map +1 -1
- package/dist/session-content-ingest.d.ts +209 -0
- package/dist/session-content-ingest.d.ts.map +1 -0
- package/dist/session-content-ingest.js +2216 -0
- package/dist/session-content-ingest.js.map +1 -0
- package/dist/session-content-send.d.ts +184 -0
- package/dist/session-content-send.d.ts.map +1 -0
- package/dist/session-content-send.js +1300 -0
- package/dist/session-content-send.js.map +1 -0
- package/dist/session-lifecycle.d.ts +303 -0
- package/dist/session-lifecycle.d.ts.map +1 -0
- package/dist/session-lifecycle.js +1643 -0
- package/dist/session-lifecycle.js.map +1 -0
- package/dist/session-node-factory.d.ts +18 -0
- package/dist/session-node-factory.d.ts.map +1 -0
- package/dist/session-node-factory.js +182 -0
- package/dist/session-node-factory.js.map +1 -0
- package/dist/session-node-manager.d.ts +68 -766
- package/dist/session-node-manager.d.ts.map +1 -1
- package/dist/session-node-manager.js +966 -7940
- package/dist/session-node-manager.js.map +1 -1
- package/dist/session-node-types.d.ts +30 -0
- package/dist/session-node-types.d.ts.map +1 -1
- package/dist/session-node-types.js.map +1 -1
- package/dist/session-notify.d.ts +46 -0
- package/dist/session-notify.d.ts.map +1 -0
- package/dist/session-notify.js +115 -0
- package/dist/session-notify.js.map +1 -0
- package/dist/session-read-handlers.d.ts.map +1 -1
- package/dist/session-read-handlers.js +0 -1
- package/dist/session-read-handlers.js.map +1 -1
- package/dist/session-relay.d.ts +361 -0
- package/dist/session-relay.d.ts.map +1 -0
- package/dist/session-relay.js +1471 -0
- package/dist/session-relay.js.map +1 -0
- package/dist/session-salt-agreement.d.ts +0 -7
- package/dist/session-salt-agreement.d.ts.map +1 -1
- package/dist/session-salt-agreement.js +0 -7
- package/dist/session-salt-agreement.js.map +1 -1
- package/dist/session-salts.d.ts +13 -0
- package/dist/session-salts.d.ts.map +1 -1
- package/dist/session-salts.js +13 -0
- package/dist/session-salts.js.map +1 -1
- package/dist/session-seal.d.ts +336 -0
- package/dist/session-seal.d.ts.map +1 -0
- package/dist/session-seal.js +948 -0
- package/dist/session-seal.js.map +1 -0
- package/dist/session-views.d.ts +46 -0
- package/dist/session-views.d.ts.map +1 -0
- package/dist/session-views.js +197 -0
- package/dist/session-views.js.map +1 -0
- package/dist/signal-handlers.d.ts +66 -0
- package/dist/signal-handlers.d.ts.map +1 -0
- package/dist/signal-handlers.js +975 -0
- package/dist/signal-handlers.js.map +1 -0
- package/dist/signaling-wiring.d.ts +100 -0
- package/dist/signaling-wiring.d.ts.map +1 -0
- package/dist/signaling-wiring.js +392 -0
- package/dist/signaling-wiring.js.map +1 -0
- package/dist/start-agent.d.ts +64 -0
- package/dist/start-agent.d.ts.map +1 -0
- package/dist/start-agent.js +136 -0
- package/dist/start-agent.js.map +1 -0
- package/dist/status-handler.d.ts +46 -0
- package/dist/status-handler.d.ts.map +1 -0
- package/dist/status-handler.js +58 -0
- package/dist/status-handler.js.map +1 -0
- package/dist/test-handlers.d.ts +62 -0
- package/dist/test-handlers.d.ts.map +1 -0
- package/dist/test-handlers.js +239 -0
- package/dist/test-handlers.js.map +1 -0
- package/dist/types.d.ts +0 -11
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -12
- package/dist/types.js.map +1 -1
- package/dist/unresolved-nodes-report.d.ts +14 -0
- package/dist/unresolved-nodes-report.d.ts.map +1 -0
- package/dist/unresolved-nodes-report.js +96 -0
- package/dist/unresolved-nodes-report.js.map +1 -0
- package/dist/who-resolver.d.ts +15 -0
- package/dist/who-resolver.d.ts.map +1 -0
- package/dist/who-resolver.js +46 -0
- package/dist/who-resolver.js.map +1 -0
- package/dist/wire-content-hash.d.ts +0 -2
- package/dist/wire-content-hash.d.ts.map +1 -1
- package/dist/wire-content-hash.js +0 -4
- package/dist/wire-content-hash.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import type { SealUpgradeReadiness } from "./seal-upgrade.js";
|
|
2
|
+
import type { Logger, SealReadinessView } from "./types.js";
|
|
3
|
+
import type { SessionTree } from "./session-tree.js";
|
|
4
|
+
import type { DaemonDatabase } from "./sqlcipher-db.js";
|
|
5
|
+
import { type AgentRelayClient } from "./session-relay-client.js";
|
|
6
|
+
import { RelayReceiptStore } from "./relay-receipt-store.js";
|
|
7
|
+
import { SessionSealLeafStore, type SealCarryLeaf } from "./session-seal-leaf-store.js";
|
|
8
|
+
import type { SessionOwnChainStore } from "./session-own-chain-store.js";
|
|
9
|
+
import type { SessionRecords } from "./session-records.js";
|
|
10
|
+
import type { SessionQueries } from "./session-queries.js";
|
|
11
|
+
import type { ParkRecovery } from "./park-recovery.js";
|
|
12
|
+
import type { HeldContent, HeldEntry } from "./held-content.js";
|
|
13
|
+
import type { SessionLeafRecords } from "./session-leaf-records.js";
|
|
14
|
+
import type { StandingReceivers } from "./standing-receivers.js";
|
|
15
|
+
import type { ActiveSessionEntry } from "./session-node-types.js";
|
|
16
|
+
/** What the seal path needs from the manager. */
|
|
17
|
+
export interface SessionSealContext {
|
|
18
|
+
readonly logger: Logger;
|
|
19
|
+
readonly records: SessionRecords;
|
|
20
|
+
readonly queries: SessionQueries;
|
|
21
|
+
readonly park: ParkRecovery;
|
|
22
|
+
readonly held: HeldContent;
|
|
23
|
+
readonly leafRecords: SessionLeafRecords;
|
|
24
|
+
readonly receivers: StandingReceivers;
|
|
25
|
+
/** A function: the manager opens its database after construction. Re-exposed below as `#db`. */
|
|
26
|
+
db(): DaemonDatabase | null;
|
|
27
|
+
readonly activeNodes: Map<string, ActiveSessionEntry>;
|
|
28
|
+
readonly heldContent: Map<string, Map<number, HeldEntry>>;
|
|
29
|
+
readonly witnessedSeq: Map<string, Map<string, number>>;
|
|
30
|
+
readonly highWaterSeq: Map<string, number>;
|
|
31
|
+
readonly orderingObserved: Set<string>;
|
|
32
|
+
readonly contentDesynced: Map<string, "tampered" | "unverifiable">;
|
|
33
|
+
readonly responderSealSubmitted: Map<string, {
|
|
34
|
+
reportedRootHex: string;
|
|
35
|
+
sequenceNumber: number;
|
|
36
|
+
} | null>;
|
|
37
|
+
readonly relayClients: Map<string, AgentRelayClient>;
|
|
38
|
+
/**
|
|
39
|
+
* ⚠️ READ-WRITE, both of them, and deliberately so — see the file header. They are `null` until
|
|
40
|
+
* something needs them, and whichever side reaches for one first is the side that opens it. A
|
|
41
|
+
* read-only view here would have meant this file opening its own second instance over the same
|
|
42
|
+
* rows the manager writes.
|
|
43
|
+
*/
|
|
44
|
+
relayReceiptStore: RelayReceiptStore | null;
|
|
45
|
+
sealLeafStore: SessionSealLeafStore | null;
|
|
46
|
+
/**
|
|
47
|
+
* Assigned by `setEnsureSealBroker`, which lives here; the manager only forwards to it.
|
|
48
|
+
*
|
|
49
|
+
* ⚠️ `undefined`, not `null` — matching the manager's field exactly rather than tidying it. The
|
|
50
|
+
* broker returns a HANDLE with a `stop`, not a boolean: it is the thing keeping a seal ceremony
|
|
51
|
+
* alive, and a caller has to be able to end it. Simplifying that to a success flag here would
|
|
52
|
+
* have compiled against a wrapper and lost the only way to cancel.
|
|
53
|
+
*/
|
|
54
|
+
ensureSealBroker: ((agentName: string, sessionId: string) => Promise<{
|
|
55
|
+
stop: (reason: string) => Promise<void>;
|
|
56
|
+
} | null>) | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* ⚠️ FOUR PARAMETERS. The last two — the state name and the counterparty key — are what the
|
|
59
|
+
* notification carries to the operator's channel; a two-parameter version would have type-checked
|
|
60
|
+
* at the call site and delivered a state change with no state in it.
|
|
61
|
+
*/
|
|
62
|
+
readonly onSessionStateChanged: ((agentName: string, sessionId: string, state: string, counterpartyPubkey: string | null) => void) | null;
|
|
63
|
+
readonly ownChainStore: SessionOwnChainStore | null;
|
|
64
|
+
/**
|
|
65
|
+
* ⚠️ THE `stores` ARGUMENT IS NOT OPTIONAL DECORATION. A client built without it has no receipt
|
|
66
|
+
* store and no seal-leaf store, so `#captureReceipt` silently returns false: the submit reports
|
|
67
|
+
* ok while the relay's signed receipt — the evidence the seal rests on — is never written.
|
|
68
|
+
*/
|
|
69
|
+
readonly detachedRelayClientBuilder: ((agentName: string, relayPeerId: string, relayAddrs: string[], stores: {
|
|
70
|
+
receiptStore?: RelayReceiptStore;
|
|
71
|
+
sealLeafStore?: SessionSealLeafStore;
|
|
72
|
+
ownChainStore?: SessionOwnChainStore;
|
|
73
|
+
onlineToken: () => Uint8Array | undefined;
|
|
74
|
+
}) => AgentRelayClient | undefined) | null;
|
|
75
|
+
/** DOD-LOOP-1: (agentName, sessionId), never sessionId alone — see the manager's own note. */
|
|
76
|
+
sessionKey(agentName: string, sessionId: string): string;
|
|
77
|
+
requireAgentId(agentName: string): string;
|
|
78
|
+
getSessionTree(agentName: string, sessionId: string): SessionTree;
|
|
79
|
+
getSessionTreeRootHex(agentName: string, sessionId: string): string;
|
|
80
|
+
getDirectoryOnlineToken(agentName: string): Uint8Array | undefined;
|
|
81
|
+
destroySessionSeed(agentName: string, sessionId: string): void;
|
|
82
|
+
updateSessionStatus(agentName: string, sessionId: string, status: "active" | "sealed" | "interrupted" | "abandoned", interruptedBy?: "local"): boolean;
|
|
83
|
+
}
|
|
84
|
+
export declare class SessionSeal {
|
|
85
|
+
#private;
|
|
86
|
+
constructor(ctx: SessionSealContext);
|
|
87
|
+
/**
|
|
88
|
+
* REBUILD THE CERTIFIED ROOT FROM THIS DAEMON'S OWN LEAVES — `DOD-M15-SEALWIRE-1` bullet 2.
|
|
89
|
+
*
|
|
90
|
+
* The receipt used to prove only that the directory signed SOMETHING: the client took the sealed
|
|
91
|
+
* root off the wire, confirmed the directory's signature over those bytes, stored it, and threw
|
|
92
|
+
* away the root it had computed a step earlier. At co-signing time that means **your key signs a
|
|
93
|
+
* root you never checked.**
|
|
94
|
+
*
|
|
95
|
+
* Bullet 1 moved the certified root into the content-hash domain, which is the domain this daemon
|
|
96
|
+
* can actually rebuild — each carry leaf's `content_hash` is the leaf hash (RFC 6962 §2.1 "hash"
|
|
97
|
+
* leaves are used as-is), and the carry is ordered by the relay's canonical `sequence_number`,
|
|
98
|
+
* which is the order the directory rebuilds in.
|
|
99
|
+
*
|
|
100
|
+
* ─── Why this returns "cannot judge" instead of always answering ───────────────────────────
|
|
101
|
+
*
|
|
102
|
+
* A root comparison that is WRONG makes every session unsealable, and force-abandon — no receipt —
|
|
103
|
+
* becomes the only exit. That failure is worse than the one being guarded, and this file already
|
|
104
|
+
* carries two comments saying so about other gates.
|
|
105
|
+
*
|
|
106
|
+
* The carry is this daemon's view, and it is not guaranteed complete at the instant a certificate
|
|
107
|
+
* arrives: the counterparty's SEAL ctrl leaf is what TRIGGERS the seal, so it may not have been
|
|
108
|
+
* witnessed here yet. So completeness is checked FIRST, against the certificate's own leaf count.
|
|
109
|
+
* A short carry means this daemon cannot judge — which is a different answer from "the roots
|
|
110
|
+
* disagree", and conflating them would turn a local timing gap into an accusation.
|
|
111
|
+
*/
|
|
112
|
+
verifyCertifiedRoot(agentPubkeyHex: string, sessionIdHex: string, certifiedRoot: Uint8Array, certifiedLeafCount: number): {
|
|
113
|
+
verdict: "match";
|
|
114
|
+
} | {
|
|
115
|
+
verdict: "mismatch";
|
|
116
|
+
ownRootHex: string | null;
|
|
117
|
+
detail: string;
|
|
118
|
+
} | {
|
|
119
|
+
verdict: "cannot_judge";
|
|
120
|
+
reason: string;
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* FED-OPTIONB-SEAL-001: the complete ordered leaf chain (both parties) a UNILATERAL seal carries to the
|
|
124
|
+
* directory for the OFFLINE tree rebuild. Empty when no leaves were logged (e.g. a direct-only session
|
|
125
|
+
* with no relay witness) — the caller then has nothing to carry and the seal stays bilateral/pending.
|
|
126
|
+
*
|
|
127
|
+
* ⚠️ Stranded on `verifyCertifiedRoot` before this split — the third block found doing that, and the
|
|
128
|
+
* reason the rule is now written down: a method reduced to a delegator leaves its documentation
|
|
129
|
+
* behind, and the block below it ends up carrying two descriptions of which the first is a stranger.
|
|
130
|
+
*/
|
|
131
|
+
getSealCarry(agentPubkeyHex: string, sessionIdHex: string): SealCarryLeaf[];
|
|
132
|
+
/** Fix #1 EXTENSION: inject the broker-connection opener. Setter injection, same construction-order reason. */
|
|
133
|
+
setEnsureSealBroker(cb: (agentName: string, sessionId: string) => Promise<{
|
|
134
|
+
stop: (reason: string) => Promise<void>;
|
|
135
|
+
} | null>): void;
|
|
136
|
+
/**
|
|
137
|
+
* DOD-M12B-INTERRUPTED-ESCALATE-1 — flip a session to `sealed`, synchronously, without needing a
|
|
138
|
+
* live node.
|
|
139
|
+
*
|
|
140
|
+
* **`destroySessionNode(…, "sealed")` cannot be relied on to do this.** It returns early at
|
|
141
|
+
* `if (!entry) return`, and the status write lives 26 lines BELOW that guard — so it flips the
|
|
142
|
+
* status only for a session that still has an `#activeNodes` entry. An interrupted session has
|
|
143
|
+
* none by construction: every producer of that status deletes the entry. Before this method, a
|
|
144
|
+
* unilateral seal on an interrupted session stored the notarized root and the certificate and
|
|
145
|
+
* left the row saying `interrupted` — the receipt landed and nothing that represents it moved.
|
|
146
|
+
* `cello_sessions` still showed it stuck, `cello_close_session` still refused it by name, and the
|
|
147
|
+
* restart-seal resolver re-selected it on the next boot to run the whole ceremony again against a
|
|
148
|
+
* session that already held a receipt.
|
|
149
|
+
*
|
|
150
|
+
* STATUS FIRST AND SYNCHRONOUS, teardown second — the order `abandonSession` uses and the one
|
|
151
|
+
* `retireSession` documents. The flip is the load-bearing half; the teardown makes memory agree
|
|
152
|
+
* with it. `#updateSessionStatus` also runs the terminal disposition hooks (held content is
|
|
153
|
+
* annexed, not stranded), which the early return skipped entirely.
|
|
154
|
+
*/
|
|
155
|
+
markSealed(agentName: string, sessionId: string): boolean;
|
|
156
|
+
/**
|
|
157
|
+
* M8B FINDING-6 (cascade-2): persist a seal certificate for a session that may have NO local
|
|
158
|
+
* `sessions` row. recordSealCertificate (a manager delegator onto `session-queries.ts`) is an `UPDATE ... WHERE` — a SILENT no-op when the
|
|
159
|
+
* row is absent (the exact trap the cascade-2 reviewer flagged). The ABSENT party (B), learning of
|
|
160
|
+
* a seal on reconnect via seal_unilateral_notification, may never have persisted a row for this
|
|
161
|
+
* session. This ensures a minimal stub row first (INSERT OR IGNORE — a no-op if a row already
|
|
162
|
+
* exists, e.g. an 'interrupted' row after a restart) so B's receipt is actually durable + retrievable
|
|
163
|
+
* via cello_get_sealed_receipt. The counterparty pubkey is required by the schema (NOT NULL); B
|
|
164
|
+
* derives it from the notification's present_pubkey.
|
|
165
|
+
*/
|
|
166
|
+
recordSealCertificateEnsuringRow(agentName: string, sessionId: string, counterpartyPubkeyHex: string, sealedRootHex: string, legibilityJson: string): void;
|
|
167
|
+
/**
|
|
168
|
+
* M7-SESSION-001 (H-1): persist a verified bilateral SEAL-INTERRUPTED
|
|
169
|
+
* commitment and transition the session to 'seal_interrupted_pending'.
|
|
170
|
+
*
|
|
171
|
+
* This is NOT a seal. It records that both parties produced and exchanged
|
|
172
|
+
* K_local-signed SEAL-INTERRUPTED leaves over the same {leafCount, merkleRoot}.
|
|
173
|
+
* The FROST threshold notarization is a separate, currently-unwired step (see
|
|
174
|
+
* daemon.ts handleSealInterruptedFlow H-1 note), which is precisely why the
|
|
175
|
+
* status is 'seal_interrupted_pending' and never 'sealed'.
|
|
176
|
+
*
|
|
177
|
+
* The status update is guarded so it only advances a session out of the
|
|
178
|
+
* 'interrupted' state — it will not overwrite a 'sealed' row.
|
|
179
|
+
*
|
|
180
|
+
* @returns true if the session row was advanced to seal_interrupted_pending.
|
|
181
|
+
*/
|
|
182
|
+
persistSealInterruptedCommitment(opts: {
|
|
183
|
+
agentName: string;
|
|
184
|
+
sessionId: string;
|
|
185
|
+
role: "initiator" | "responder";
|
|
186
|
+
ownLeaf: unknown;
|
|
187
|
+
counterpartyLeaf: unknown;
|
|
188
|
+
merkleRoot: string;
|
|
189
|
+
nonce: string;
|
|
190
|
+
}): boolean;
|
|
191
|
+
/**
|
|
192
|
+
* M7 DOD-SPINE-7: submit THIS party's SEAL ctrl leaf (0x02) to the relay witness.
|
|
193
|
+
* Structure: content_hash = SHA-256(0x02 || encodeSealPayload({session_id, final_root,
|
|
194
|
+
* close_timestamp, "PENDING"})), where final_root is the daemon's OWN tree root. Two
|
|
195
|
+
* distinct-sender SEAL leaves in the relay's log trigger the relay's #maybeProcessSeal
|
|
196
|
+
* → directory processSeal (rebuild + verify the signed chain) → FROST notarization →
|
|
197
|
+
* session_sealed. Requires an active relay client; the caller falls back to the
|
|
198
|
+
* directory-mediated path when this returns relay_unavailable.
|
|
199
|
+
*/
|
|
200
|
+
submitSealLeaf(agentName: string, sessionId: string, correlationId?: string): Promise<{
|
|
201
|
+
ok: true;
|
|
202
|
+
sequenceNumber: number;
|
|
203
|
+
reportedRootHex: string;
|
|
204
|
+
} | {
|
|
205
|
+
ok: false;
|
|
206
|
+
reason: string;
|
|
207
|
+
reportedRootHex?: string;
|
|
208
|
+
sequenceNumber?: number;
|
|
209
|
+
}>;
|
|
210
|
+
/**
|
|
211
|
+
* CELLO-M7-UPGRADE-001 (DOD-UP-1): readiness of a session for B to RATIFY a unilateral seal
|
|
212
|
+
* (the returning absent party). This is the SAME verifiability bar as the UP-2 auto-ack gate:
|
|
213
|
+
*
|
|
214
|
+
* - `known`: the session exists locally with its content (B has a transcript to ratify). After a
|
|
215
|
+
* restart B reloads it from SQLite, and autoRecoverForAgent re-pulls any parked content first.
|
|
216
|
+
* - `tampered`: the content cross-check flagged a content_hash mismatch (#contentDesynced) — B
|
|
217
|
+
* must NEVER ratify content it could not integrity-verify (the KERNEL refusal, AC-003).
|
|
218
|
+
*
|
|
219
|
+
* The directory separately verifies B's ack signature is genuine; B separately verifies the
|
|
220
|
+
* unilateral cert signature (R1 is authentic). NOTE: a full "B's frontier covers R1's tail"
|
|
221
|
+
* completeness check (the `desynced` reason) requires the deferred MSG-001-3b canonical-sequence
|
|
222
|
+
* reconciliation — same documented limitation as the UP-2 gate above.
|
|
223
|
+
*/
|
|
224
|
+
getSealUpgradeReadiness(agentName: string, sessionId: string): SealUpgradeReadiness;
|
|
225
|
+
/**
|
|
226
|
+
* M7-UPGRADE-002: auto-acknowledge close (POSTMORTEM Workstream E / C-5). When B's daemon
|
|
227
|
+
* ingests the COUNTERPARTY's SEAL control leaf and B has verified the content, B's OWN node
|
|
228
|
+
* auto-co-signs + submits its responder SEAL leaf WITHOUT waiting for B's agent to call
|
|
229
|
+
* cello_close_session — so a bilateral seal completes promptly instead of degrading to
|
|
230
|
+
* unilateral on a slow/busy/crashed agent.
|
|
231
|
+
*
|
|
232
|
+
* SI-001 (non-negotiable): B's signature is ALWAYS produced by B's own node — submitSealLeaf
|
|
233
|
+
* signs the responder SEAL leaf with B's K_local. We remove the agent PROMPT, never the SIGNER;
|
|
234
|
+
* nothing here lets the directory or the peer synthesize B's acknowledgement.
|
|
235
|
+
*
|
|
236
|
+
* SI-002 (verifiability gate): auto-ack ONLY content B has verified. A session whose content
|
|
237
|
+
* cross-check failed (content_hash_mismatch = tamper, recorded in #contentDesynced) is NEVER
|
|
238
|
+
* auto-signed — it surfaces to the agent as a genuine decision point. DISAGREEMENT with the
|
|
239
|
+
* content is NOT a gate failure (C-6): the gate is "can I verify integrity?", never "do I agree?"
|
|
240
|
+
* — a verified-but-disliked tail is auto-sealed and the transcript speaks for B.
|
|
241
|
+
*
|
|
242
|
+
* Idempotent + non-throwing: marks #responderSealSubmitted BEFORE the async submit so a
|
|
243
|
+
* redelivered ctrl leaf cannot double-submit; clears the mark on submit failure so a later
|
|
244
|
+
* agent close / reconnect can still complete the seal (DB-001 — never a silent half-seal).
|
|
245
|
+
*/
|
|
246
|
+
maybeAutoAcknowledgeSeal(agentName: string, sessionId: string, correlationId: string): void;
|
|
247
|
+
/**
|
|
248
|
+
* M12-P14: is this side's chain COMPLETE enough to be sealed?
|
|
249
|
+
*
|
|
250
|
+
* A seal is a bilateral signature over the same conversation, so a side that is missing a leaf
|
|
251
|
+
* cannot produce a signable one — the counterparty compares frontiers and refuses with
|
|
252
|
+
* `leaf_count_mismatch`. That refusal is correct and it is also terminal: there is no backfill
|
|
253
|
+
* request in the protocol, so the only exit is a force-abandon, which yields NO notarized receipt.
|
|
254
|
+
* Measured 2026-08-05 on two sessions that died exactly this way (initiator 2 leaves, responder 3).
|
|
255
|
+
*
|
|
256
|
+
* The cheap prevention is to notice BEFORE asking. Two local signals already exist and, until now,
|
|
257
|
+
* nothing read either of them at close time:
|
|
258
|
+
* - `#highWaterSeq` — the largest canonical sequence the RELAY has witnessed for this session.
|
|
259
|
+
* The relay is the ordering authority, so a high-water above our own frontier is proof that a
|
|
260
|
+
* leaf exists which we have not appended. (Its own doc comment called it "reserved … NOT yet
|
|
261
|
+
* consumed by the gate" — this is that consumer.)
|
|
262
|
+
* - `#heldContent` — content we HAVE received and verified but cannot append because it sits
|
|
263
|
+
* behind a gap. Holding content and sealing anyway would seal a chain we know is short.
|
|
264
|
+
*
|
|
265
|
+
* Deliberately NOT a network call: it must work when the counterparty is unreachable, which is
|
|
266
|
+
* the whole situation a seal-interrupted exists for.
|
|
267
|
+
*
|
|
268
|
+
* KNOWN LIMIT, stated rather than hidden: both maps are in-memory and cleared on teardown, so
|
|
269
|
+
* after a daemon restart this returns ready for a session whose gap predates the restart — which
|
|
270
|
+
* is the shape of the 2026-08-05 incident itself. Closing that needs the mailbox drained (or the
|
|
271
|
+
* high-water persisted) before the check; tracked with M12-P14, not claimed here.
|
|
272
|
+
*/
|
|
273
|
+
sealReadiness(agentName: string, sessionId: string): {
|
|
274
|
+
ready: boolean;
|
|
275
|
+
treeSize: number;
|
|
276
|
+
highWaterSeq: number;
|
|
277
|
+
heldCount: number;
|
|
278
|
+
missingLeaves: number;
|
|
279
|
+
/** DOD-M12B-INDEX-1: of `heldCount`, how many are THIS side's own sends versus the
|
|
280
|
+
* counterparty's. They block a seal identically and mean completely different things. */
|
|
281
|
+
heldOwn: number;
|
|
282
|
+
heldReceived: number;
|
|
283
|
+
/**
|
|
284
|
+
* DOD-M15-DIVERGE-1 — this tree and the relay's counter have PROVABLY parted.
|
|
285
|
+
*
|
|
286
|
+
* The other two counters both measure the same direction: positions the relay committed that
|
|
287
|
+
* this tree has not appended. This is the OPPOSITE direction — this tree holds a leaf at a
|
|
288
|
+
* position the relay assigned to something else — and it is the direction an injected or forged
|
|
289
|
+
* leaf appears in. Without it `ready` was asymmetric, and a diverged session read as perfectly
|
|
290
|
+
* sealable right up until the counterparty answered `leaf_count_mismatch`, which is terminal.
|
|
291
|
+
*/
|
|
292
|
+
diverged: boolean;
|
|
293
|
+
};
|
|
294
|
+
/**
|
|
295
|
+
* DOD-M12B-SEAL-STUCK-1 — the operator-facing answer to "can this session be closed?".
|
|
296
|
+
*
|
|
297
|
+
* THREE STATES, because there are three answers. `sealReadiness` above returns a boolean plus raw
|
|
298
|
+
* counters, and both of its counters are easy to misread on a surface:
|
|
299
|
+
*
|
|
300
|
+
* - `missingLeaves` is `#witnessedSeq.size`, which is every position the relay witnessed that
|
|
301
|
+
* this tree has not appended — and a HELD frame keeps its witness entry. So it INCLUDES the
|
|
302
|
+
* held ones. Reporting it beside `heldCount` counts the same message twice and labels one copy
|
|
303
|
+
* "never received" when it is sitting on our own disk. Split here into what each actually is.
|
|
304
|
+
* - Neither counter survives a restart on its own: `#witnessedSeq` is memory-only. Held content
|
|
305
|
+
* is durable since DOD-M12B-STRAND-1, but a position the relay witnessed for content that
|
|
306
|
+
* never arrived leaves no trace. So for a session carrying leaves this process did not watch
|
|
307
|
+
* arrive, "clean" is unknowable — and saying `ready` there invites a close that gets
|
|
308
|
+
* `leaf_count_mismatch` back, which is terminal and costs the receipt for good.
|
|
309
|
+
*/
|
|
310
|
+
sealReadinessView(agentName: string, sessionId: string): SealReadinessView;
|
|
311
|
+
/**
|
|
312
|
+
* WHERE THE MUTUALLY-SIGNED PREFIX ENDS, DERIVED FROM THIS DAEMON'S OWN LEAVES —
|
|
313
|
+
* `DOD-M15-UNILATERAL-1`, review F2.
|
|
314
|
+
*
|
|
315
|
+
* ⚠️ **THE FIRST VERSION COMPUTED THIS FROM THE CERTIFICATE'S OWN PARTICIPANT LIST, AND CALLED
|
|
316
|
+
* THAT "recomputed, cannot be steered".** It could be steered. On the SOLO path the certificate's
|
|
317
|
+
* TBS binds no legibility at all, and the client verifies only the *live* party's frontier — so
|
|
318
|
+
* the absent party's `content_frontier_seq` and every `last_authored_seq` arrived unchecked. One
|
|
319
|
+
* directory node could publish the absent party's frontier as 3 and the receipt would say
|
|
320
|
+
* "mutually signed through 3" over a transcript that party never signed for. That is the precise
|
|
321
|
+
* conflation this field exists to prevent, reintroduced by the field itself.
|
|
322
|
+
*
|
|
323
|
+
* The carry answers it without trusting anybody. This daemon holds the counterparty's own leaves,
|
|
324
|
+
* each carrying, inside the bytes THEY signed, both the sequence they authored and the
|
|
325
|
+
* `last_seen_seq` they acknowledged. So a party's commitment reaches
|
|
326
|
+
* `max(highest sequence they authored, highest sequence they acknowledged)`, and the transcript is
|
|
327
|
+
* mutually signed only as far as the LEAST-committed party reaches.
|
|
328
|
+
*
|
|
329
|
+
* Fewer than two distinct authors ⇒ `0`: nobody countersigned anything, which is the honest floor
|
|
330
|
+
* for a conversation where the other side only ever received. `null` when the carry is empty or
|
|
331
|
+
* unreadable — the caller must then publish NO boundary rather than fall back to a number
|
|
332
|
+
* somebody else supplied.
|
|
333
|
+
*/
|
|
334
|
+
countersignedThroughSeqFromCarry(agentPubkeyHex: string, sessionIdHex: string): number | null;
|
|
335
|
+
}
|
|
336
|
+
//# sourceMappingURL=session-seal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-seal.d.ts","sourceRoot":"","sources":["../src/session-seal.ts"],"names":[],"mappings":"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"}
|