@cello-protocol/daemon 0.0.171 → 0.0.173

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.
@@ -0,0 +1,92 @@
1
+ /**
2
+ * DOD-M12B-RESTART-SEAL-1 — resolve the sessions our own stop orphaned, with a receipt.
3
+ *
4
+ * A daemon shutdown flips every open session to `interrupted` on the way out, and nothing has ever
5
+ * moved them again: their transport keypairs died with the process, so they cannot be resumed, and
6
+ * the only exit is `cello_close_session {force:true}`, which forfeits the notarized receipt.
7
+ *
8
+ * This walks them on startup and SEALS them instead — bilateral if the counterparty answers,
9
+ * unilateral once the directory's delivery grace has elapsed. When the directory refuses
10
+ * `seal_unilateral_too_early` it hands back exactly how long is left; that number becomes a
11
+ * scheduled retry rather than a sentence asking a human to come back.
12
+ *
13
+ * SCOPE IS THE WHOLE SAFETY ARGUMENT. `listRestartOrphans` returns only sessions marked
14
+ * `interrupted_by = 'local'` — ours. A session the COUNTERPARTY ended, or one lost with the relay
15
+ * witness stream, is never touched here, so SI-001 ("no auto-seal on a session_interrupted receipt —
16
+ * a daemon that sealed on its own would notarize a conversation nobody chose to end") keeps holding
17
+ * for the live interruption it was written about.
18
+ *
19
+ * Serial and staggered on purpose: a seal is a directory ceremony, and a machine holding hundreds of
20
+ * orphans must not answer a restart with hundreds of simultaneous ceremonies.
21
+ */
22
+ import type { Logger } from "./types.js";
23
+ /** A session our own stop left behind. */
24
+ export interface RestartOrphan {
25
+ agentName: string;
26
+ sessionId: string;
27
+ messageCount: number;
28
+ }
29
+ /**
30
+ * The result of one seal attempt. `retryAfterSeconds` is the directory's own countdown from
31
+ * `seal_unilateral_too_early` — the delivery grace that has to elapse before a unilateral seal is
32
+ * allowed. It is a WAIT the directory named, not a guess.
33
+ */
34
+ export type SealOutcome = {
35
+ ok: true;
36
+ } | {
37
+ ok: false;
38
+ reason: string;
39
+ retryAfterSeconds?: number;
40
+ /** The close path's own guidance. Carried, never replaced — see the give-up log. */
41
+ guidance?: string;
42
+ /** Everything the close computed about WHY, so `reason` stops being the only fact. */
43
+ detail?: Record<string, unknown>;
44
+ };
45
+ export interface ScheduledTask {
46
+ cancel: () => void;
47
+ }
48
+ export interface RestartSealResolverDeps {
49
+ logger: Logger;
50
+ /** Sessions with status 'interrupted' AND interrupted_by 'local'. Nothing else is eligible. */
51
+ listRestartOrphans: () => RestartOrphan[];
52
+ sealSession: (agentName: string, sessionId: string) => Promise<SealOutcome>;
53
+ /**
54
+ * Record DURABLY that this session was given up on, so the next boot does not start over.
55
+ * Without it a machine restarting ~6 times a day re-attempts a hopeless session forever.
56
+ *
57
+ * REQUIRED, not optional. There is exactly one composition root, so optionality buys nothing and
58
+ * costs the compiler's ability to catch a wiring that was never done — and the whole
59
+ * justification for the two new columns is that this call happens.
60
+ */
61
+ markGaveUp: (agentName: string, sessionId: string, reason: string) => void;
62
+ now?: () => number;
63
+ schedule?: (fn: () => void, ms: number) => ScheduledTask;
64
+ /** Gap between two seal attempts. */
65
+ staggerMs?: number;
66
+ /**
67
+ * How long to wait after boot before the first attempt. A seal needs the directory, and at the
68
+ * instant the daemon finishes starting, signaling is still being established — firing
69
+ * immediately would spend an attempt on a connection that does not exist yet.
70
+ */
71
+ initialDelayMs?: number;
72
+ /** Hard ceiling on attempts for one session before it is reported as needing a manual decision. */
73
+ maxAttemptsPerSession?: number;
74
+ /**
75
+ * Ceiling on ONE seal attempt. A close that never settles would otherwise leave `#running` true
76
+ * with no timer armed and no log line — the resolver stalls, holding a full queue, silently.
77
+ */
78
+ attemptTimeoutMs?: number;
79
+ }
80
+ export declare class RestartSealResolver {
81
+ #private;
82
+ constructor(deps: RestartSealResolverDeps);
83
+ /** Enqueue every restart orphan and begin working through them. Idempotent. */
84
+ start(): void;
85
+ /**
86
+ * Stop, and start nothing further. A shutdown that keeps opening directory ceremonies is not
87
+ * draining (DOD-M12B-SHUTDOWN-1) — and the flag, not the cancelled timer, is what an attempt
88
+ * already in flight checks when it lands.
89
+ */
90
+ stop(): Promise<void>;
91
+ }
92
+ //# sourceMappingURL=restart-seal-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restart-seal-resolver.d.ts","sourceRoot":"","sources":["../src/restart-seal-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,0CAA0C;AAC1C,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IACE,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAC;AAEN,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,+FAA+F;IAC/F,kBAAkB,EAAE,MAAM,aAAa,EAAE,CAAC;IAC1C,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC5E;;;;;;;OAOG;IACH,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3E,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,aAAa,CAAC;IACzD,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mGAAmG;IACnG,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAqED,qBAAa,mBAAmB;;gBAkBlB,IAAI,EAAE,uBAAuB;IAUzC,+EAA+E;IAC/E,KAAK,IAAI,IAAI;IA+Bb;;;;OAIG;IACH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAoKtB"}
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Refusals no retry can ever help, so they cost ONE attempt and not fifteen minutes.
3
+ *
4
+ * Measured 2026-08-17 across 443 submitted seal leaves and 183 completed seals — 59% of seals that
5
+ * start never finish, and these are the reasons where trying again is not persistence:
6
+ *
7
+ * session_abandoned 10× — terminal by definition; the receipt is gone.
8
+ * leaf_count_mismatch 4× — the two trees genuinely disagree.
9
+ * seal_interrupted_rejected_by_counterparty 18× — they said NO. Asking again is worse than
10
+ * noise: it is a machine badgering a peer who
11
+ * already declined.
12
+ *
13
+ * `seal_carry_bilateral_in_progress` is deliberately NOT here either: it means the relay has what
14
+ * it needs to seal BILATERALLY, so the right move is to come back and find the session already
15
+ * sealed — which then answers `session_already_sealed`, which IS terminal.
16
+ *
17
+ * `session_incomplete` and `seal_unilateral_timeout` are deliberately NOT here. The first can be
18
+ * fixed by a relay pull filling the gap — the close's own guidance says so — and the second is a
19
+ * directory that did not answer in time, which the next attempt may well get.
20
+ */
21
+ const TERMINAL_SEAL_REFUSALS = new Set([
22
+ "session_abandoned",
23
+ "seal_interrupted_rejected_by_counterparty",
24
+ "session_already_sealed",
25
+ // OUR OWN verification finding a genuine divergence between the two trees. Distinct from the
26
+ // counterparty's `leaf_count_mismatch`, which never reaches here as a top-level reason — it
27
+ // arrives as `detail.rejection_reason` under the rejection above. Naming the bare string here
28
+ // was inert: the close cannot produce it.
29
+ "seal_interrupted_leaf_count_mismatch",
30
+ "session_not_found",
31
+ // The relay released the session (it drops one 24 h after the last message), so there is nothing
32
+ // left for any directory to rebuild the record from. No amount of retrying brings it back.
33
+ "seal_carry_empty",
34
+ // Two of our SEAL ctrl leaves in one durable carry. No directory can ever notarize it, and no
35
+ // retry changes the carry.
36
+ "seal_carry_duplicate_own_ctrl_leaf",
37
+ // The lookup that answers "is a ctrl leaf already posted?" failed. Refusing is correct — a second
38
+ // leaf is permanent — but retrying it five times cannot make the database readable.
39
+ "seal_leaf_recovery_unavailable",
40
+ // Not protocol outcomes — a wiring or caller fault. Retrying re-runs the same bug.
41
+ "session_not_closeable",
42
+ "close_handler_missing",
43
+ "missing_params",
44
+ ]);
45
+ const DEFAULT_STAGGER_MS = 5_000;
46
+ /** Long enough for the directory handshake started moments earlier to have landed. */
47
+ const DEFAULT_INITIAL_DELAY_MS = 30_000;
48
+ const DEFAULT_MAX_ATTEMPTS = 5;
49
+ /** Backoff for a failure the directory gave no deadline for. Doubles, so a bounded run spans ~1 h. */
50
+ const BASE_BACKOFF_MS = 60_000;
51
+ /** Generous: a close does discovery, a broker dial, a relay submit and a directory round. */
52
+ const DEFAULT_ATTEMPT_TIMEOUT_MS = 120_000;
53
+ function defaultSchedule(fn, ms) {
54
+ const t = setTimeout(fn, ms);
55
+ // A background resolver must never be the reason a daemon will not exit.
56
+ t.unref?.();
57
+ return { cancel: () => clearTimeout(t) };
58
+ }
59
+ export class RestartSealResolver {
60
+ #deps;
61
+ #now;
62
+ #schedule;
63
+ #staggerMs;
64
+ #maxAttempts;
65
+ #initialDelayMs;
66
+ #attemptTimeoutMs;
67
+ /** Resolves when no attempt is in flight — awaited by stop() so a shutdown does not cut a
68
+ * ceremony in half and leave the two sides permanently divergent. */
69
+ #inFlight = null;
70
+ #queue = new Map();
71
+ #timer = null;
72
+ #started = false;
73
+ #stopped = false;
74
+ #running = false;
75
+ constructor(deps) {
76
+ this.#deps = deps;
77
+ this.#now = deps.now ?? (() => Date.now());
78
+ this.#schedule = deps.schedule ?? defaultSchedule;
79
+ this.#staggerMs = deps.staggerMs ?? DEFAULT_STAGGER_MS;
80
+ this.#maxAttempts = deps.maxAttemptsPerSession ?? DEFAULT_MAX_ATTEMPTS;
81
+ this.#initialDelayMs = deps.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS;
82
+ this.#attemptTimeoutMs = deps.attemptTimeoutMs ?? DEFAULT_ATTEMPT_TIMEOUT_MS;
83
+ }
84
+ /** Enqueue every restart orphan and begin working through them. Idempotent. */
85
+ start() {
86
+ if (this.#started || this.#stopped)
87
+ return;
88
+ this.#started = true;
89
+ let orphans;
90
+ try {
91
+ orphans = this.#deps.listRestartOrphans();
92
+ }
93
+ catch (err) {
94
+ // ABSENT IS NOT FINE. If we cannot read the list, say so — silence here reads exactly like
95
+ // "there was nothing to resolve", which is the state this unit exists to end.
96
+ this.#deps.logger.error("session.restart_seal.enumerate.failed", {
97
+ error: err instanceof Error ? err.message : String(err),
98
+ impact: "sessions the last shutdown orphaned will stay interrupted and unsealed",
99
+ });
100
+ return;
101
+ }
102
+ if (orphans.length === 0)
103
+ return;
104
+ const now = this.#now();
105
+ const firstAt = now + this.#initialDelayMs;
106
+ for (const orphan of orphans) {
107
+ this.#queue.set(`${orphan.agentName}:${orphan.sessionId}`, { orphan, attempts: 0, nextAt: firstAt });
108
+ }
109
+ this.#deps.logger.info("session.restart_seal.enqueued", {
110
+ count: orphans.length,
111
+ impact: "sessions the last shutdown left open will be sealed rather than left for a force-abandon",
112
+ });
113
+ this.#arm(this.#initialDelayMs);
114
+ }
115
+ /**
116
+ * Stop, and start nothing further. A shutdown that keeps opening directory ceremonies is not
117
+ * draining (DOD-M12B-SHUTDOWN-1) — and the flag, not the cancelled timer, is what an attempt
118
+ * already in flight checks when it lands.
119
+ */
120
+ stop() {
121
+ this.#stopped = true;
122
+ this.#timer?.cancel();
123
+ this.#timer = null;
124
+ this.#queue.clear();
125
+ // AWAIT what is already in flight. Severing signaling under a half-finished seal-interrupted
126
+ // exchange leaves the counterparty holding a commitment we never acknowledged: their session
127
+ // advances to `seal_interrupted_pending` and ours stays `interrupted`, permanently divergent
128
+ // and produced automatically on every shutdown.
129
+ //
130
+ // WHAT IS AWAITED IS THE BOUNDED RACE, NOT THE CLOSE. Returning the raw `sealSession` promise
131
+ // would hang shutdown forever on a close that never settles — and shutdown holds the SQLCipher
132
+ // write lock, so "forever" means a daemon that cannot be restarted. `attemptTimeoutMs` bounds
133
+ // this wait because the raced promise is what is stored.
134
+ //
135
+ // THE RESIDUAL WINDOW IS ACCEPTED, NOT CLOSED, and it is stated here rather than implied.
136
+ // Once the timeout wins the race, `#inFlight` is cleared while the underlying close may still
137
+ // be running — so a `stop()` arriving after that point returns immediately and can still sever
138
+ // signaling under a half-finished exchange. That is the deliberate trade: a bounded shutdown is
139
+ // worth more than a guaranteed-clean one, because an unbounded wait here wedges the daemon
140
+ // permanently while the divergence it prevents is repairable by the next close. An attempt
141
+ // taking longer than `attemptTimeoutMs` is not pathological — the interrupted path can spend
142
+ // 30 s in the seal flow, 30 s in a retry after discovery, and 30 s in the escalation.
143
+ return this.#inFlight ? this.#inFlight.then(() => undefined, () => undefined) : Promise.resolve();
144
+ }
145
+ /** Arm the next pass only while there is still work. An empty queue must leave NO timer behind —
146
+ * a resolver that keeps a dead timer alive is a resolver that shows up in a shutdown trace. */
147
+ #armIfWork() {
148
+ if (this.#queue.size === 0)
149
+ return;
150
+ this.#arm(this.#staggerMs);
151
+ }
152
+ #arm(delayMs) {
153
+ if (this.#stopped)
154
+ return;
155
+ this.#timer?.cancel();
156
+ this.#timer = this.#schedule(() => {
157
+ this.#timer = null;
158
+ void this.#pump();
159
+ }, delayMs);
160
+ }
161
+ async #pump() {
162
+ if (this.#stopped || this.#running)
163
+ return;
164
+ if (this.#queue.size === 0)
165
+ return;
166
+ const now = this.#now();
167
+ let due = null;
168
+ for (const item of this.#queue.values()) {
169
+ if (item.nextAt <= now && (due === null || item.nextAt < due.nextAt))
170
+ due = item;
171
+ }
172
+ if (due === null) {
173
+ // Nothing is due yet — sleep until the earliest deadline rather than polling.
174
+ let earliest = Infinity;
175
+ for (const item of this.#queue.values())
176
+ earliest = Math.min(earliest, item.nextAt);
177
+ if (earliest !== Infinity)
178
+ this.#arm(Math.max(0, earliest - now));
179
+ return;
180
+ }
181
+ const item = due;
182
+ const key = `${item.orphan.agentName}:${item.orphan.sessionId}`;
183
+ item.attempts += 1;
184
+ this.#running = true;
185
+ let outcome;
186
+ let attemptTimer = null;
187
+ try {
188
+ const attempt = this.#deps.sealSession(item.orphan.agentName, item.orphan.sessionId);
189
+ // A close that never settles must not wedge the queue silently.
190
+ const timeout = new Promise((resolve) => {
191
+ attemptTimer = this.#schedule(() => resolve({ ok: false, reason: "restart_seal_attempt_timeout" }), this.#attemptTimeoutMs);
192
+ });
193
+ // The RACE is what stop() awaits — see stop(). Storing the raw attempt here would make a
194
+ // hung close a hung shutdown; storing the race makes the wait bounded by attemptTimeoutMs.
195
+ const raced = Promise.race([attempt, timeout]);
196
+ this.#inFlight = raced;
197
+ // A rejected `attempt` still settles the race, and #inFlight is only ever awaited with both
198
+ // handlers attached (stop()), so this cannot surface as an unhandled rejection.
199
+ attempt.catch(() => { });
200
+ outcome = await raced;
201
+ }
202
+ catch (err) {
203
+ outcome = { ok: false, reason: err instanceof Error ? err.message : String(err) };
204
+ }
205
+ finally {
206
+ attemptTimer?.cancel();
207
+ this.#inFlight = null;
208
+ this.#running = false;
209
+ }
210
+ // Re-checked AFTER the await: stop() can land while a ceremony is in flight, and the queue it
211
+ // cleared must not be repopulated by this attempt's bookkeeping.
212
+ if (this.#stopped)
213
+ return;
214
+ if (outcome.ok) {
215
+ this.#queue.delete(key);
216
+ this.#deps.logger.info("session.restart_seal.resolved", {
217
+ agentName: item.orphan.agentName,
218
+ sessionId: item.orphan.sessionId,
219
+ attempts: item.attempts,
220
+ messageCount: item.orphan.messageCount,
221
+ });
222
+ this.#armIfWork();
223
+ return;
224
+ }
225
+ const terminal = TERMINAL_SEAL_REFUSALS.has(outcome.reason);
226
+ if (terminal || item.attempts >= this.#maxAttempts) {
227
+ this.#queue.delete(key);
228
+ // DURABLE, so the next boot does not start the same five attempts over. A machine restarting
229
+ // ~6 times a day would otherwise re-try a hopeless session forever, which is the burst the
230
+ // stagger exists to prevent, merely spread out.
231
+ try {
232
+ this.#deps.markGaveUp(item.orphan.agentName, item.orphan.sessionId, outcome.reason);
233
+ }
234
+ catch (err) {
235
+ this.#deps.logger.warn("session.restart_seal.mark_gave_up.failed", {
236
+ sessionId: item.orphan.sessionId,
237
+ error: err instanceof Error ? err.message : String(err),
238
+ impact: "this session will be re-attempted on every future boot",
239
+ });
240
+ }
241
+ this.#deps.logger.warn("session.restart_seal.gave_up", {
242
+ agentName: item.orphan.agentName,
243
+ sessionId: item.orphan.sessionId,
244
+ attempts: item.attempts,
245
+ reason: outcome.reason,
246
+ // WHY it stopped, not just that it did. "We stopped because they refused" and "we stopped
247
+ // because we ran out of tries" are different facts and lead to different operator actions.
248
+ stoppedBecause: terminal ? "refusal_is_terminal" : "attempts_exhausted",
249
+ // The detail the close COMPUTED and used to drop one function later: which of the six
250
+ // causes behind `seal_interrupted_rejected_by_counterparty` this was, and the leaf counts
251
+ // that identify a frontier strand.
252
+ ...(outcome.detail ? { detail: outcome.detail } : {}),
253
+ // THE CLOSE'S OWN GUIDANCE WINS. A fixed string here told the operator to force-abandon —
254
+ // and for `session_already_sealed` the close handler says in capitals NOT to, because
255
+ // forcing there permanently forfeits a half that is still recoverable.
256
+ guidance: outcome.guidance ??
257
+ ("This session could not be sealed automatically and is still interrupted. Close it with " +
258
+ "cello_close_session, or force-abandon it — which ends it WITHOUT a notarized receipt."),
259
+ });
260
+ this.#armIfWork();
261
+ return;
262
+ }
263
+ // The directory named a deadline: wait exactly that long. Anything else either batters it with
264
+ // refusals or leaves the session sitting after the grace has elapsed.
265
+ const waitMs = typeof outcome.retryAfterSeconds === "number" && outcome.retryAfterSeconds >= 0
266
+ ? outcome.retryAfterSeconds * 1_000
267
+ : BASE_BACKOFF_MS * 2 ** (item.attempts - 1);
268
+ item.nextAt = this.#now() + waitMs;
269
+ this.#deps.logger.info("session.restart_seal.waiting", {
270
+ agentName: item.orphan.agentName,
271
+ sessionId: item.orphan.sessionId,
272
+ attempts: item.attempts,
273
+ reason: outcome.reason,
274
+ ...(typeof outcome.retryAfterSeconds === "number" ? { retryAfterSeconds: outcome.retryAfterSeconds } : {}),
275
+ retryInMs: waitMs,
276
+ });
277
+ this.#arm(Math.min(this.#staggerMs, waitMs));
278
+ }
279
+ }
280
+ //# sourceMappingURL=restart-seal-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restart-seal-resolver.js","sourceRoot":"","sources":["../src/restart-seal-resolver.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"seal-certificate-pull.d.ts","sourceRoot":"","sources":["../src/seal-certificate-pull.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAKzC,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,gBAAgB,GAAG,SAAS,CAAC;IAClE,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3G,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,6BAA6B,CAAC;IACrE,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAC9D;AAED,MAAM,MAAM,yBAAyB,GACjC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AAC/B;;;;;;;;;GASG;GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,cAAc,GAAG,aAAa,GAAG,SAAS,GAAG,WAAW,GAAG,qBAAqB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAa7H;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,uBAAuB,EAC7B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,yBAAyB,CAAC,CAkIpC"}
1
+ {"version":3,"file":"seal-certificate-pull.d.ts","sourceRoot":"","sources":["../src/seal-certificate-pull.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAKzC,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,gBAAgB,GAAG,SAAS,CAAC;IAClE,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3G,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,6BAA6B,CAAC;IACrE,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAC9D;AAED,MAAM,MAAM,yBAAyB,GACjC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AAC/B;;;;;;;;;GASG;GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,cAAc,GAAG,aAAa,GAAG,SAAS,GAAG,WAAW,GAAG,qBAAqB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAa7H;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,uBAAuB,EAC7B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,yBAAyB,CAAC,CA+IpC"}
@@ -128,8 +128,23 @@ export async function pullSealCertificate(deps, agentName, sessionIdHex) {
128
128
  verified: verdict.verified,
129
129
  impact: "a seal this side never received the push for is now local and provable",
130
130
  });
131
- // Marks the row sealed and tears the node down — the same terminal transition the push path makes,
132
- // so a pulled seal and a pushed one leave the daemon in identical states.
131
+ // STATUS FIRST AND SYNCHRONOUS, teardown second — the same terminal transition the push path
132
+ // makes, so a pulled seal and a pushed one leave the daemon in identical states.
133
+ //
134
+ // The comment here used to credit `destroySessionNode` with marking the row. It does not when the
135
+ // session has no live node — it returns early at `if (!entry) return` and writes the status below
136
+ // that guard — and THIS path is precisely the no-node case: a daemon pulls a certificate exactly
137
+ // when it was down or disconnected while the seal happened.
138
+ try {
139
+ sessionNodeManager.markSealed(agentName, sessionIdHex);
140
+ }
141
+ catch (err) {
142
+ logger.error("session.seal.status.write.threw", {
143
+ sessionId: sessionIdHex, agentName,
144
+ error: err instanceof Error ? err.message : String(err),
145
+ impact: "the certificate was pulled and verified, but this row still reads interrupted",
146
+ });
147
+ }
133
148
  void sessionNodeManager.destroySessionNode(agentName, sessionIdHex, "sealed");
134
149
  return { ok: true, rootHex };
135
150
  }
@@ -1 +1 @@
1
- {"version":3,"file":"seal-certificate-pull.js","sourceRoot":"","sources":["../src/seal-certificate-pull.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"seal-certificate-pull.js","sourceRoot":"","sources":["../src/seal-certificate-pull.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"seal-coordinator.d.ts","sourceRoot":"","sources":["../src/seal-coordinator.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAO1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,uGAAuG;AACvG,MAAM,MAAM,cAAc,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEvE;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACzD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,uEAAuE;IACvE,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,yBAAyB,CAAC;IACjE,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,WAAW,GAAG,SAAS,CAAC;IAC/D;;;;OAIG;IACH,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,mBAAmB;yBAOjC,MAAM,aAAa,MAAM,KAAG,MAAM;;iDAYN,cAAc,KAAK,IAAI;8CAmL1B,gBAAgB,KAAK,IAAI;uCA+VpC,gBAAgB,aAAa,MAAM,kBAAkB,MAAM,KAAG,MAAM,IAAI;EAkBnH"}
1
+ {"version":3,"file":"seal-coordinator.d.ts","sourceRoot":"","sources":["../src/seal-coordinator.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAO1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,uGAAuG;AACvG,MAAM,MAAM,cAAc,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEvE;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACzD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,uEAAuE;IACvE,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,yBAAyB,CAAC;IACjE,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,WAAW,GAAG,SAAS,CAAC;IAC/D;;;;OAIG;IACH,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,mBAAmB;yBAOjC,MAAM,aAAa,MAAM,KAAG,MAAM;;iDAYN,cAAc,KAAK,IAAI;8CAsM1B,gBAAgB,KAAK,IAAI;uCA4XpC,gBAAgB,aAAa,MAAM,kBAAkB,MAAM,KAAG,MAAM,IAAI;EAkBnH"}
@@ -189,7 +189,21 @@ export function createSealCoordinator(deps) {
189
189
  pendingSealWaiters.delete(sealKey(agentName, sidHex));
190
190
  waiter({ rootHex, legibility });
191
191
  }
192
- // Mark the session sealed + tear the node down (idempotent safe if already gone).
192
+ // STATUS FIRST AND SYNCHRONOUS, teardown second. The comment here used to read "mark the
193
+ // session sealed + tear the node down (idempotent — safe if already gone)" — it asserted the
194
+ // property the code lacked, which is why the gap survived. `destroySessionNode` returns
195
+ // early at `if (!entry) return` and writes the status BELOW that guard, so for a session
196
+ // with no live node the receipt landed and the row never moved.
197
+ try {
198
+ sessionNodeManager.markSealed(agentName, sidHex);
199
+ }
200
+ catch (err) {
201
+ logger.error("session.seal.status.write.threw", {
202
+ sessionId: sidHex, agentName,
203
+ error: err instanceof Error ? err.message : String(err),
204
+ impact: "the seal COMPLETED and the certificate is stored, but this row still reads interrupted",
205
+ });
206
+ }
193
207
  void sessionNodeManager.destroySessionNode(agentName, sidHex, "sealed");
194
208
  })();
195
209
  });
@@ -205,6 +219,13 @@ export function createSealCoordinator(deps) {
205
219
  // bilateral close (not cryptographic parity: this cert is directory-attested, see FINDING-5). undefined
206
220
  // when the directory shipped none (a pre-cascade-2 directory): the seal still completes, but no
207
221
  // retrievable receipt is produced (the pre-fix behavior).
222
+ // KEYED `agent\x1f session`, like `sealInterruptedInProgress` — NOT by session id alone.
223
+ //
224
+ // Two agents on one daemon is a supported topology (and the one the operator actually runs), and
225
+ // the away-path one-shot escalation can overlap a manual close. Keyed by session id, whichever
226
+ // registered second CLOBBERED the first's resolver: the loser waited out the full 30 s and
227
+ // reported `seal_unilateral_timeout` for a seal that SUCCEEDED — the operator is then told the
228
+ // directory could not verify their root, for a session that is notarized.
208
229
  const pendingUnilateralWaiters = new Map();
209
230
  // SESSION-002: per-agent listener for the unilateral certificate. Verifies the FROST
210
231
  // signature over the rebuilt TBS against the agent's own primary_pubkey BEFORE resolving
@@ -217,11 +238,11 @@ export function createSealCoordinator(deps) {
217
238
  const sidHex = frameValueToHex(frame["session_id"]);
218
239
  if (!sidHex)
219
240
  return;
220
- const waiter = pendingUnilateralWaiters.get(sidHex);
241
+ const waiter = pendingUnilateralWaiters.get(sealKey(agentName, sidHex));
221
242
  if (!waiter)
222
243
  return;
223
244
  if (ftype === "seal_unilateral_too_early") {
224
- pendingUnilateralWaiters.delete(sidHex);
245
+ pendingUnilateralWaiters.delete(sealKey(agentName, sidHex));
225
246
  // F20: thread the directory's remaining_seconds through so the close guidance can
226
247
  // say when the unilateral seal becomes available.
227
248
  const rs = frame["remaining_seconds"];
@@ -244,12 +265,12 @@ export function createSealCoordinator(deps) {
244
265
  if (!sessionId || !sealedRoot || !frostSig || leafCount === null || closeTs === null ||
245
266
  (sigType !== "frost" && sigType !== "single")) {
246
267
  logger.warn("session.unilateral.certificate.invalid", { sessionId: sidHex, reason: "malformed_certificate" });
247
- pendingUnilateralWaiters.delete(sidHex);
268
+ pendingUnilateralWaiters.delete(sealKey(agentName, sidHex));
248
269
  waiter({ ok: false, reason: "malformed_certificate" });
249
270
  return;
250
271
  }
251
272
  const result = await verifyUnilateralCertificate({ persistence: getPersistence(agentName), agentPubkeyHex, logger }, { sessionId, sealedRoot, leafCount, closeTimestamp: closeTs, frostSignature: frostSig, signatureType: sigType });
252
- pendingUnilateralWaiters.delete(sidHex);
273
+ pendingUnilateralWaiters.delete(sealKey(agentName, sidHex));
253
274
  if (!result.ok) {
254
275
  // SI-003: do NOT mark sealed when the certificate signature does not verify.
255
276
  logger.warn("session.unilateral.certificate.invalid", { sessionId: sidHex, reason: result.reason, signatureType: sigType });
@@ -367,8 +388,29 @@ export function createSealCoordinator(deps) {
367
388
  // The seal is valid, but no receipt is retrievable — a directory that predates cascade-2.
368
389
  logger.warn("session.unilateral.receipt.absent", { sessionId: sidHex, reason: "no_legibility_on_frame" });
369
390
  }
370
- void sessionNodeManager.destroySessionNode(agentName, sidHex, "sealed");
391
+ // THE WAITER IS ANSWERED FIRST. `markSealed` is SYNCHRONOUS and reaches `#requireAgentId`,
392
+ // which throws for a retired agent or a closed database — and a throw here would escape
393
+ // this frame, leave the waiter unresolved, and make the close sit out its full timeout and
394
+ // report `seal_unilateral_timeout` for a seal that COMPLETED and whose certificate is
395
+ // already on disk. That is the error-substitution defect this milestone was opened on,
396
+ // reproduced on the path that fixes it. The old line was an async `void`, whose throw
397
+ // became a discarded rejection and could not do this.
371
398
  waiter({ ok: true, sealedRootHex: rootHex, legibility });
399
+ // STATUS THEN TEARDOWN — and on THIS path the node is gone by construction. A unilateral
400
+ // seal is what an interrupted session escalates to, and every producer of `interrupted`
401
+ // deletes the `#activeNodes` entry, so `destroySessionNode` alone would return before the
402
+ // status write every single time.
403
+ try {
404
+ sessionNodeManager.markSealed(agentName, sidHex);
405
+ }
406
+ catch (err) {
407
+ logger.error("session.seal.status.write.threw", {
408
+ sessionId: sidHex, agentName,
409
+ error: err instanceof Error ? err.message : String(err),
410
+ impact: "the seal COMPLETED and the certificate is stored, but this row still reads interrupted",
411
+ });
412
+ }
413
+ void sessionNodeManager.destroySessionNode(agentName, sidHex, "sealed");
372
414
  })();
373
415
  });
374
416
  }
@@ -476,6 +518,17 @@ export function createSealCoordinator(deps) {
476
518
  logger.warn("seal.certificate.persist.failed", { sessionId: sidHex, reason: error instanceof Error ? error.message : String(error) });
477
519
  }
478
520
  }
521
+ // STATUS FIRST — same reason as the two sites above.
522
+ try {
523
+ sessionNodeManager.markSealed(agentName, sidHex);
524
+ }
525
+ catch (err) {
526
+ logger.error("session.seal.status.write.threw", {
527
+ sessionId: sidHex, agentName,
528
+ error: err instanceof Error ? err.message : String(err),
529
+ impact: "the seal COMPLETED and the certificate is stored, but this row still reads interrupted",
530
+ });
531
+ }
479
532
  void sessionNodeManager.destroySessionNode(agentName, sidHex, "sealed");
480
533
  }
481
534
  /**