@zincapp/znvault-cli 4.22.1 → 4.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/dist/commands/lmk-ceremony.d.ts +3 -0
  2. package/dist/commands/lmk-ceremony.d.ts.map +1 -0
  3. package/dist/commands/lmk-ceremony.js +597 -0
  4. package/dist/commands/lmk-ceremony.js.map +1 -0
  5. package/dist/commands/lmk-escrow.d.ts.map +1 -1
  6. package/dist/commands/lmk-escrow.js +73 -5
  7. package/dist/commands/lmk-escrow.js.map +1 -1
  8. package/dist/commands/lmk-preflight.d.ts +3 -0
  9. package/dist/commands/lmk-preflight.d.ts.map +1 -0
  10. package/dist/commands/lmk-preflight.js +117 -0
  11. package/dist/commands/lmk-preflight.js.map +1 -0
  12. package/dist/commands/lmk-restore-drill.d.ts +3 -0
  13. package/dist/commands/lmk-restore-drill.d.ts.map +1 -0
  14. package/dist/commands/lmk-restore-drill.js +160 -0
  15. package/dist/commands/lmk-restore-drill.js.map +1 -0
  16. package/dist/commands/lmk.d.ts.map +1 -1
  17. package/dist/commands/lmk.js +4 -0
  18. package/dist/commands/lmk.js.map +1 -1
  19. package/dist/index.js +35 -2
  20. package/dist/index.js.map +1 -1
  21. package/dist/lib/bsk-source.d.ts +21 -0
  22. package/dist/lib/bsk-source.d.ts.map +1 -0
  23. package/dist/lib/bsk-source.js +89 -0
  24. package/dist/lib/bsk-source.js.map +1 -0
  25. package/dist/lib/ceremony/gates.d.ts +126 -0
  26. package/dist/lib/ceremony/gates.d.ts.map +1 -0
  27. package/dist/lib/ceremony/gates.js +270 -0
  28. package/dist/lib/ceremony/gates.js.map +1 -0
  29. package/dist/lib/ceremony/system.d.ts +36 -0
  30. package/dist/lib/ceremony/system.d.ts.map +1 -0
  31. package/dist/lib/ceremony/system.js +176 -0
  32. package/dist/lib/ceremony/system.js.map +1 -0
  33. package/dist/lib/ceremony/workspace.d.ts +54 -0
  34. package/dist/lib/ceremony/workspace.d.ts.map +1 -0
  35. package/dist/lib/ceremony/workspace.js +98 -0
  36. package/dist/lib/ceremony/workspace.js.map +1 -0
  37. package/dist/lib/config/index.d.ts +1 -1
  38. package/dist/lib/config/index.d.ts.map +1 -1
  39. package/dist/lib/config/index.js +1 -1
  40. package/dist/lib/config/index.js.map +1 -1
  41. package/dist/lib/config/profile.d.ts +14 -0
  42. package/dist/lib/config/profile.d.ts.map +1 -1
  43. package/dist/lib/config/profile.js +22 -0
  44. package/dist/lib/config/profile.js.map +1 -1
  45. package/dist/lib/config.d.ts +1 -1
  46. package/dist/lib/config.d.ts.map +1 -1
  47. package/dist/lib/config.js +1 -1
  48. package/dist/lib/config.js.map +1 -1
  49. package/dist/lib/db/index.d.ts +9 -1
  50. package/dist/lib/db/index.d.ts.map +1 -1
  51. package/dist/lib/db/index.js +9 -0
  52. package/dist/lib/db/index.js.map +1 -1
  53. package/dist/lib/db/key-lifecycle.d.ts +86 -0
  54. package/dist/lib/db/key-lifecycle.d.ts.map +1 -0
  55. package/dist/lib/db/key-lifecycle.js +182 -0
  56. package/dist/lib/db/key-lifecycle.js.map +1 -0
  57. package/dist/lib/db/lmk-escrow.d.ts +18 -0
  58. package/dist/lib/db/lmk-escrow.d.ts.map +1 -1
  59. package/dist/lib/db/lmk-escrow.js +25 -0
  60. package/dist/lib/db/lmk-escrow.js.map +1 -1
  61. package/dist/lib/db/preflight.d.ts +42 -0
  62. package/dist/lib/db/preflight.d.ts.map +1 -0
  63. package/dist/lib/db/preflight.js +165 -0
  64. package/dist/lib/db/preflight.js.map +1 -0
  65. package/dist/lib/kcv.d.ts +34 -0
  66. package/dist/lib/kcv.d.ts.map +1 -0
  67. package/dist/lib/kcv.js +89 -0
  68. package/dist/lib/kcv.js.map +1 -0
  69. package/dist/lib/lmk-escrow-restore.d.ts +6 -2
  70. package/dist/lib/lmk-escrow-restore.d.ts.map +1 -1
  71. package/dist/lib/lmk-escrow-restore.js +1 -1
  72. package/dist/lib/lmk-escrow-restore.js.map +1 -1
  73. package/dist/lib/lmk-escrow.d.ts +14 -1
  74. package/dist/lib/lmk-escrow.d.ts.map +1 -1
  75. package/dist/lib/lmk-escrow.js +5 -1
  76. package/dist/lib/lmk-escrow.js.map +1 -1
  77. package/dist/lib/preflight.d.ts +93 -0
  78. package/dist/lib/preflight.d.ts.map +1 -0
  79. package/dist/lib/preflight.js +129 -0
  80. package/dist/lib/preflight.js.map +1 -0
  81. package/dist/lib/restore-drill.d.ts +73 -0
  82. package/dist/lib/restore-drill.d.ts.map +1 -0
  83. package/dist/lib/restore-drill.js +185 -0
  84. package/dist/lib/restore-drill.js.map +1 -0
  85. package/dist/lib/sentinel-client.d.ts +26 -0
  86. package/dist/lib/sentinel-client.d.ts.map +1 -0
  87. package/dist/lib/sentinel-client.js +165 -0
  88. package/dist/lib/sentinel-client.js.map +1 -0
  89. package/package.json +1 -1
@@ -0,0 +1,3 @@
1
+ import { type Command } from 'commander';
2
+ export declare function registerLmkCeremonyCommands(escrow: Command): void;
3
+ //# sourceMappingURL=lmk-ceremony.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lmk-ceremony.d.ts","sourceRoot":"","sources":["../../src/commands/lmk-ceremony.ts"],"names":[],"mappings":"AAyBA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAoLzC,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAygBjE"}
@@ -0,0 +1,597 @@
1
+ // Path: znvault-cli/src/commands/lmk-ceremony.ts
2
+ //
3
+ // `znvault superadmin lmk escrow ceremony` — the escrow ceremony as a command
4
+ // rather than a script.
5
+ //
6
+ // WHY A COMMAND. A script goes stale, gets edited without a trace, and if it
7
+ // dies halfway it leaves nothing behind. A command is versioned, released and
8
+ // tested — and, more to the point, it can write to `key_lifecycle_operations`
9
+ // (zn-vault migration 093) who ran the ceremony, when, and how far it got.
10
+ //
11
+ // WHAT IT DOES AND DOES NOT DO. It owns the state machine and the gates. It
12
+ // does NOT copy key material for you: fetching the legacy BSK, the mini-CA and
13
+ // the Sentinel configuration is `ssh` and `scp`, and wrapping that in a CLI
14
+ // would add a large, fragile surface for no safety. The operator performs those
15
+ // copies into the RAM workspace; the command refuses to advance until it has
16
+ // verified the result.
17
+ //
18
+ // That division is the honest one. The command can only guarantee what it can
19
+ // check, and what it can check is exactly where a ceremony fails silently:
20
+ // a workspace that is not really in RAM, a key that is not really the right
21
+ // key, a device that is not really the copy you think.
22
+ import { hostname, userInfo } from 'node:os';
23
+ import { readFileSync } from 'node:fs';
24
+ import { resolve } from 'node:path';
25
+ import * as output from '../lib/output.js';
26
+ import { LocalDBClient, isLocalDbAvailable } from '../lib/db/index.js';
27
+ import { KeyLifecycleOperations } from '../lib/db/key-lifecycle.js';
28
+ import { getVersion } from '../lib/version.js';
29
+ import { assertCeremonyIsOurs, assertCopyLabel, assertKeyMatchesEnvelope, assertKeyMatchesExpectedKcv, assertNoOtherCeremonyRunning, assertNotTheOtherCopy, assertRouteComplete, assertTransitionAllowed, } from '../lib/ceremony/gates.js';
30
+ import { readAndVerifyLmkEscrowBundle } from '../lib/lmk-escrow.js';
31
+ import { assertRamBacked, assertTornDown, CEREMONY_MOUNT_POINT } from '../lib/ceremony/workspace.js';
32
+ import { createRamWorkspace, describeDevice, destroyRamWorkspace, indexingEnabled, listEscrowDevices, } from '../lib/ceremony/system.js';
33
+ /**
34
+ * Minimum vault release whose schema this command relies on (migration 093).
35
+ *
36
+ * 1.68.0 and not 1.67.x: migration 093 is not in 1.67.1. `schemaPresent()` is
37
+ * the check that actually guards — this is what the record and the refusal
38
+ * MESSAGE claim, and a message that names a release which does not carry the
39
+ * table sends the reader to look in the wrong place.
40
+ */
41
+ const MIN_RELEASE = '1.68.0';
42
+ const WORKSPACE_MB = 64;
43
+ function requireLocalDb() {
44
+ if (!isLocalDbAvailable()) {
45
+ throw new Error('The ceremony is local-only: it needs direct PostgreSQL access to read the ' +
46
+ 'root-key envelopes and to record the operation. Set DATABASE_URL (an SSH ' +
47
+ 'tunnel to the cluster is fine) and try again.');
48
+ }
49
+ }
50
+ /** Open the lifecycle store, refusing clearly if the schema is not deployed. */
51
+ async function lifecycle() {
52
+ const ops = new KeyLifecycleOperations();
53
+ if (!(await ops.schemaPresent())) {
54
+ await ops.close();
55
+ throw new Error('This deployment has no key_lifecycle_operations table, so a ceremony cannot ' +
56
+ `be recorded. It arrives with zn-vault migration 093 (release ${MIN_RELEASE}). ` +
57
+ 'Refusing to run an unrecorded ceremony — the record is the point.');
58
+ }
59
+ return ops;
60
+ }
61
+ /** The in-flight ceremony, or a clear refusal. */
62
+ async function requireActive(ops) {
63
+ const active = await ops.active();
64
+ if (active === null) {
65
+ throw new Error("No ceremony is in progress. Start one with 'ceremony start'.");
66
+ }
67
+ if (active.kind !== 'ESCROW_SNAPSHOT') {
68
+ throw new Error(`The operation in progress is a ${active.kind}, not a ceremony. Do not run a ` +
69
+ 'ceremony alongside it: the bundle and the inventory would describe ' +
70
+ 'different moments.');
71
+ }
72
+ // Every fact the gates judge is gathered on THIS machine.
73
+ assertCeremonyIsOurs(active, hostname());
74
+ return active;
75
+ }
76
+ /**
77
+ * Move to the next phase, refusing any move the route does not allow.
78
+ *
79
+ * The gate lives HERE rather than in each subcommand because an audit found the
80
+ * subcommands each jumped to a fixed phase from wherever the ceremony happened
81
+ * to be — so `start` then `teardown` then `finish` recorded a COMPLETED
82
+ * ceremony that had done nothing at all. One choke point, and every caller
83
+ * passes through it.
84
+ */
85
+ async function advance(ops, active, phase, detail) {
86
+ assertTransitionAllowed(active.phase, phase);
87
+ await ops.advance({
88
+ operationId: active.operationId,
89
+ expectedEpoch: active.epoch,
90
+ phase,
91
+ nodeId: hostname(),
92
+ ...(detail ? { detail } : {}),
93
+ });
94
+ }
95
+ /**
96
+ * What was recorded for the most recent event of this phase.
97
+ *
98
+ * Reading the ceremony's OWN append-only record is the point: it is the one
99
+ * source in reach that the operator cannot retype at the moment it is checked.
100
+ */
101
+ async function recordedDetail(ops, operationId, phase) {
102
+ const history = await ops.history(operationId);
103
+ // The LAST event for the phase: `material` repeats, and a re-check supersedes
104
+ // what it re-checked.
105
+ const match = [...history].reverse().find((event) => event.phase === phase);
106
+ return match?.detail ?? null;
107
+ }
108
+ function recordedString(detail, key) {
109
+ const value = detail?.[key];
110
+ return typeof value === 'string' ? value : null;
111
+ }
112
+ /** The phase a copy is recorded under. */
113
+ function phaseForCopy(copy) {
114
+ return copy === 'A' ? 'write-a' : 'write-b';
115
+ }
116
+ /**
117
+ * The workspace device this ceremony proved to be RAM-backed.
118
+ *
119
+ * @throws if no workspace was ever recorded — which means there is nothing to
120
+ * tear down and the ceremony is not where the caller thinks it is.
121
+ */
122
+ async function recordedWorkspaceDevice(ops, operationId) {
123
+ const device = recordedString(await recordedDetail(ops, operationId, 'workspace'), 'device');
124
+ if (device === null) {
125
+ throw new Error('This ceremony has no recorded workspace, so there is no device that was ' +
126
+ 'ever proven to be RAM-backed. Nothing to tear down.');
127
+ }
128
+ return device;
129
+ }
130
+ /**
131
+ * Refuse a path that is not inside the RAM workspace.
132
+ *
133
+ * Checking a key that sits on the SSD and recording the 'material' phase for it
134
+ * is a check that measured the wrong thing: the point of the phase is that the
135
+ * material was handled in volatile memory.
136
+ */
137
+ function assertInsideWorkspace(path, what) {
138
+ const absolute = resolve(path);
139
+ if (absolute !== CEREMONY_MOUNT_POINT && !absolute.startsWith(`${CEREMONY_MOUNT_POINT}/`)) {
140
+ throw new Error(`${what} is at ${absolute}, outside the ceremony workspace ` +
141
+ `(${CEREMONY_MOUNT_POINT}). Key material is handled in the RAM volume and ` +
142
+ 'nowhere else; verifying a copy that lives somewhere else would record a ' +
143
+ 'precaution that was not taken.');
144
+ }
145
+ return absolute;
146
+ }
147
+ export function registerLmkCeremonyCommands(escrow) {
148
+ const ceremony = escrow
149
+ .command('ceremony')
150
+ .description('Escrow ceremony with recorded state and enforced gates. Records who ran ' +
151
+ 'it, when, and how far it got, in key_lifecycle_operations.');
152
+ // ---------------------------------------------------------------- start ---
153
+ ceremony
154
+ .command('start')
155
+ .description('Claim the ceremony slot and run the preflight gates')
156
+ .option('--operator <who>', 'Who is performing it (defaults to the login name)')
157
+ .option('--json', 'Output as JSON')
158
+ .action(async (options) => {
159
+ requireLocalDb();
160
+ const ops = await lifecycle();
161
+ try {
162
+ // Not "is anything running?" then INSERT — that is the race the index
163
+ // exists to close. But a friendly message beforehand costs nothing.
164
+ assertNoOtherCeremonyRunning(await ops.active());
165
+ const operator = options.operator ?? userInfo().username;
166
+ const claimed = await ops.claim({
167
+ phase: 'preflight',
168
+ ownerNodeId: hostname(),
169
+ ownerPrincipal: operator,
170
+ minRelease: MIN_RELEASE,
171
+ detail: { cliVersion: getVersion() },
172
+ });
173
+ if (!claimed.ok) {
174
+ assertNoOtherCeremonyRunning(claimed.active);
175
+ throw new Error('The ceremony slot was taken between the check and the claim.');
176
+ }
177
+ const devices = listEscrowDevices();
178
+ const payload = {
179
+ operationId: claimed.operation.operationId,
180
+ operator,
181
+ host: hostname(),
182
+ cliVersion: getVersion(),
183
+ devices: devices.map((d) => ({
184
+ mountPoint: d.mountPoint,
185
+ usbSerial: d.usbSerial,
186
+ volumeLabel: d.volumeLabel,
187
+ indexing: indexingEnabled(d.mountPoint),
188
+ })),
189
+ };
190
+ if (options.json === true) {
191
+ output.json(payload);
192
+ }
193
+ else {
194
+ output.section('Escrow ceremony started');
195
+ output.keyValue({
196
+ Operation: payload.operationId,
197
+ Operator: operator,
198
+ Host: payload.host,
199
+ CLI: payload.cliVersion,
200
+ });
201
+ if (devices.length === 0) {
202
+ output.warn('No datAshur device is mounted. Unlock and mount both before continuing.');
203
+ }
204
+ else {
205
+ output.table(['Mount point', 'USB serial', 'Label', 'Spotlight'], payload.devices.map((d) => [
206
+ d.mountPoint,
207
+ d.usbSerial ?? '(unreadable)',
208
+ d.volumeLabel,
209
+ d.indexing === true ? 'INDEXING — turn it off' : d.indexing === false ? 'off' : 'unknown',
210
+ ]));
211
+ }
212
+ output.info("Next: 'ceremony workspace' to create the RAM-backed working volume.");
213
+ }
214
+ }
215
+ finally {
216
+ await ops.close();
217
+ }
218
+ });
219
+ // --------------------------------------------------------------- status ---
220
+ ceremony
221
+ .command('status')
222
+ .description('Where the ceremony is, and the whole route it travelled')
223
+ .option('--json', 'Output as JSON')
224
+ .action(async (options) => {
225
+ requireLocalDb();
226
+ const ops = await lifecycle();
227
+ try {
228
+ const active = await ops.active();
229
+ if (active === null) {
230
+ if (options.json === true)
231
+ output.json({ active: null });
232
+ else
233
+ output.info('No ceremony or other key-lifecycle operation is in progress.');
234
+ return;
235
+ }
236
+ const history = await ops.history(active.operationId);
237
+ if (options.json === true) {
238
+ output.json({ active, history });
239
+ return;
240
+ }
241
+ output.section(`In progress: ${active.kind}`);
242
+ output.keyValue({
243
+ Operation: active.operationId,
244
+ Phase: active.phase,
245
+ Operator: active.ownerPrincipal,
246
+ Host: active.ownerNodeId,
247
+ Started: active.startedAt,
248
+ });
249
+ output.table(['#', 'Phase', 'State', 'At'], history.map((e) => [String(e.seq), e.phase, e.state, e.at]));
250
+ }
251
+ finally {
252
+ await ops.close();
253
+ }
254
+ });
255
+ // ------------------------------------------------------------ workspace ---
256
+ ceremony
257
+ .command('workspace')
258
+ .description('Create the RAM-backed working volume, and PROVE it is in RAM')
259
+ .action(async () => {
260
+ requireLocalDb();
261
+ const ops = await lifecycle();
262
+ try {
263
+ const active = await requireActive(ops);
264
+ const facts = createRamWorkspace(WORKSPACE_MB);
265
+ // The gate, not the return code. A failed mount leaves the mount point
266
+ // as an ordinary directory and every write below lands on the SSD,
267
+ // silently. See workspace.ts.
268
+ assertRamBacked(facts);
269
+ await advance(ops, active, 'workspace', { device: facts.device, imagePath: facts.imagePath });
270
+ output.success(`Workspace ready at ${CEREMONY_MOUNT_POINT} (${facts.device}, ${facts.imagePath ?? '?'})`);
271
+ output.info('Copy the key material INTO this directory and nowhere else, then check ' +
272
+ "each item with 'ceremony check-key'.");
273
+ }
274
+ finally {
275
+ await ops.close();
276
+ }
277
+ });
278
+ // ------------------------------------------------------------ check-key ---
279
+ ceremony
280
+ .command('check-key <path>')
281
+ .description('Verify a key file against its recorded fingerprint before it is escrowed')
282
+ .option('--against-envelope <providerId>', "Compare against root_key_envelopes (e.g. 'sentinel')")
283
+ .option('--expect-kcv <kcv1:...>', 'Compare against a known fingerprint (for the legacy BSK)')
284
+ .option('--label <name>', 'What this key is, for the message', 'key')
285
+ .action(async (path, options) => {
286
+ requireLocalDb();
287
+ if ((options.againstEnvelope === undefined) === (options.expectKcv === undefined)) {
288
+ throw new Error('Pass exactly one of --against-envelope or --expect-kcv.');
289
+ }
290
+ const ops = await lifecycle();
291
+ const db = new LocalDBClient();
292
+ let key = null;
293
+ try {
294
+ const active = await requireActive(ops);
295
+ // The workspace was proven RAM-backed when it was CREATED, and the
296
+ // process then exited. Minutes pass while material is copied in. If the
297
+ // volume was unmounted in between, the mount point survives as an
298
+ // ordinary directory on the SSD and quietly absorbs everything — the
299
+ // documented failure, reintroduced as a check-then-use gap. So prove it
300
+ // again, here, against the device this ceremony recorded.
301
+ const absolute = assertInsideWorkspace(path, 'The key file');
302
+ assertRamBacked(describeDevice(await recordedWorkspaceDevice(ops, active.operationId)));
303
+ key = readFileSync(absolute);
304
+ if (options.againstEnvelope !== undefined) {
305
+ const envelope = await db.getRootKeyEnvelope(options.againstEnvelope);
306
+ if (envelope === null) {
307
+ throw new Error(`No envelope recorded for provider '${options.againstEnvelope}'. Without it ` +
308
+ 'there is nothing to check the key against, and an unchecked key is how ' +
309
+ 'an escrow ends up holding the wrong one.');
310
+ }
311
+ assertKeyMatchesEnvelope(key, envelope);
312
+ output.success(`${options.label ?? 'key'} matches the '${envelope.providerId}' envelope (${envelope.kcv})`);
313
+ // The KCV goes into the record, not just the message: an acta written
314
+ // from this trail should not have to trust that someone read the
315
+ // screen correctly. A KCV is publishable by construction.
316
+ await advance(ops, active, 'material', {
317
+ checked: options.label, against: envelope.providerId, kcv: envelope.kcv,
318
+ });
319
+ }
320
+ else if (options.expectKcv !== undefined) {
321
+ assertKeyMatchesExpectedKcv(key, options.expectKcv, options.label ?? 'key');
322
+ output.success(`${options.label ?? 'key'} matches ${options.expectKcv}`);
323
+ await advance(ops, active, 'material', {
324
+ checked: options.label, against: 'recorded fingerprint', kcv: options.expectKcv,
325
+ });
326
+ }
327
+ }
328
+ finally {
329
+ key?.fill(0);
330
+ await db.close();
331
+ await ops.close();
332
+ }
333
+ });
334
+ // --------------------------------------------------------- check-device ---
335
+ //
336
+ // A CHECK, and it no longer pretends to be more. The previous version looked
337
+ // the device up BY the serial the operator typed and then "verified" that the
338
+ // device it found had that serial — a tautology that could only ever pass,
339
+ // while the failure it claimed to prevent (both bundles on one stick) stayed
340
+ // wide open. What actually binds a copy to a device is `confirm-copy` below,
341
+ // which compares against the serial already recorded for the other copy.
342
+ ceremony
343
+ .command('check-device')
344
+ .description('Show whether the device you mean is mounted, before writing to it')
345
+ .requiredOption('--copy <label>', 'Which copy this should be: A or B')
346
+ .requiredOption('--serial <serial>', 'The USB serial recorded for that copy')
347
+ .action(async (options) => {
348
+ requireLocalDb();
349
+ const ops = await lifecycle();
350
+ try {
351
+ const active = await requireActive(ops);
352
+ const copy = assertCopyLabel(options.copy);
353
+ const devices = listEscrowDevices();
354
+ const match = devices.find((d) => d.usbSerial === options.serial);
355
+ if (match === undefined) {
356
+ throw new Error(`No mounted device has USB serial ${options.serial}. Mounted: ` +
357
+ `${devices.map((d) => `${d.mountPoint}=${d.usbSerial ?? '?'}`).join(', ') || '(none)'}.`);
358
+ }
359
+ const other = copy === 'A' ? 'B' : 'A';
360
+ assertNotTheOtherCopy(options.serial, copy, recordedString(await recordedDetail(ops, active.operationId, phaseForCopy(other)), 'serial'));
361
+ output.success(`${match.mountPoint} is mounted with serial ${options.serial}.`);
362
+ output.info(`Write copy ${copy}: znvault superadmin lmk escrow snapshot --mount ` +
363
+ `${match.mountPoint} --copy-label ${copy} …`);
364
+ output.info(`Then record it: ceremony confirm-copy --copy ${copy} --serial ${options.serial} ` +
365
+ '--bundle <file on the device>');
366
+ }
367
+ finally {
368
+ await ops.close();
369
+ }
370
+ });
371
+ // --------------------------------------------------------- confirm-copy ---
372
+ //
373
+ // THE PHASE IS RECORDED AFTER THE WRITE, AND ONLY IF THE WRITE IS THERE.
374
+ // Previously `check-device` advanced to write-a/write-b BEFORE anything was
375
+ // written, and no command ever checked that a bundle had landed — so the trail
376
+ // could read `write-a, write-b, teardown, COMPLETED` for a ceremony whose
377
+ // devices were empty. The phases described intentions. Now they describe a
378
+ // bundle that was read back OFF the device and verified.
379
+ ceremony
380
+ .command('confirm-copy')
381
+ .description('Verify the bundle actually on the device, and record that copy')
382
+ .requiredOption('--copy <label>', 'Which copy this is: A or B')
383
+ .requiredOption('--serial <serial>', 'USB serial of the device it was written to')
384
+ .requiredOption('--bundle <path>', 'The bundle file, on that device')
385
+ .action(async (options) => {
386
+ requireLocalDb();
387
+ const ops = await lifecycle();
388
+ try {
389
+ const active = await requireActive(ops);
390
+ const copy = assertCopyLabel(options.copy);
391
+ const devices = listEscrowDevices();
392
+ const match = devices.find((d) => d.usbSerial === options.serial);
393
+ if (match === undefined) {
394
+ throw new Error(`No mounted device has USB serial ${options.serial}, so there is nothing ` +
395
+ 'to verify. Plug in the device the bundle was written to.');
396
+ }
397
+ const other = copy === 'A' ? 'B' : 'A';
398
+ assertNotTheOtherCopy(options.serial, copy, recordedString(await recordedDetail(ops, active.operationId, phaseForCopy(other)), 'serial'));
399
+ // The bundle has to be ON the device. Verifying a copy that still sits
400
+ // in the workspace would pass while the device stayed empty.
401
+ const bundlePath = resolve(options.bundle);
402
+ if (!bundlePath.startsWith(`${match.mountPoint}/`)) {
403
+ throw new Error(`${bundlePath} is not on ${match.mountPoint}. The point of this step is ` +
404
+ 'that the bundle reached the device — a copy verified anywhere else ' +
405
+ 'leaves the device empty and the record saying otherwise.');
406
+ }
407
+ const report = readAndVerifyLmkEscrowBundle(bundlePath);
408
+ if (report.copyLabel.toUpperCase() !== copy) {
409
+ throw new Error(`That bundle is labelled copy ${report.copyLabel}, not ${copy}. Writing ` +
410
+ 'it here would leave two copies with the same label and no way to tell ' +
411
+ 'from the bundles which device is missing.');
412
+ }
413
+ await advance(ops, active, phaseForCopy(copy), {
414
+ copy,
415
+ serial: options.serial,
416
+ mountPoint: match.mountPoint,
417
+ bundlePath,
418
+ bundleId: report.bundleId,
419
+ bskKcv: report.bskKcv,
420
+ recoverability: report.recoverability,
421
+ });
422
+ output.success(`Copy ${copy} verified on ${match.mountPoint}: bundle ${report.bundleId}, ` +
423
+ `BSK ${report.bskKcv}, ${report.recoverability}.`);
424
+ }
425
+ finally {
426
+ await ops.close();
427
+ }
428
+ });
429
+ // --------------------------------------------------------------- verify ---
430
+ //
431
+ // Both copies, at the same time, on two different devices. `confirm-copy` can
432
+ // only ever see one device at a time, so on its own it cannot rule out that
433
+ // the second copy went onto the first stick after the first was unplugged.
434
+ // This is the step that makes "two copies in two places" an observed fact.
435
+ ceremony
436
+ .command('verify')
437
+ .description('Re-read BOTH bundles, from both devices, at the same time')
438
+ .action(async () => {
439
+ requireLocalDb();
440
+ const ops = await lifecycle();
441
+ try {
442
+ const active = await requireActive(ops);
443
+ const recorded = await Promise.all(['A', 'B'].map(async (copy) => {
444
+ const detail = await recordedDetail(ops, active.operationId, phaseForCopy(copy));
445
+ const serial = recordedString(detail, 'serial');
446
+ const bundlePath = recordedString(detail, 'bundlePath');
447
+ if (serial === null || bundlePath === null) {
448
+ throw new Error(`Copy ${copy} was never confirmed, so there is nothing to verify. Run ` +
449
+ `'ceremony confirm-copy --copy ${copy} …' first.`);
450
+ }
451
+ return { copy, serial, bundlePath };
452
+ }));
453
+ const [a, b] = recorded;
454
+ if (a.serial === b.serial) {
455
+ throw new Error(`Both copies were recorded against the same device (${a.serial}). That is ` +
456
+ 'one stick holding both bundles and another holding none.');
457
+ }
458
+ const mounted = listEscrowDevices();
459
+ const results = recorded.map((r) => {
460
+ if (!mounted.some((d) => d.usbSerial === r.serial)) {
461
+ throw new Error(`Copy ${r.copy} (serial ${r.serial}) is not mounted. Both devices must ` +
462
+ 'be present for this check — that is what it is for.');
463
+ }
464
+ const report = readAndVerifyLmkEscrowBundle(r.bundlePath);
465
+ return { ...r, bundleId: report.bundleId, bskKcv: report.bskKcv };
466
+ });
467
+ const [ra, rb] = results;
468
+ if (ra.bskKcv !== rb.bskKcv) {
469
+ throw new Error(`The two copies hold different bootstrap keys (${ra.bskKcv} and ` +
470
+ `${rb.bskKcv}). One of them will not open this deployment.`);
471
+ }
472
+ await advance(ops, active, 'verify', {
473
+ copies: results.map((r) => ({ copy: r.copy, serial: r.serial, bundleId: r.bundleId })),
474
+ bskKcv: ra.bskKcv,
475
+ });
476
+ output.success('Both copies verified, on two distinct devices, holding the same key.');
477
+ output.table(['Copy', 'USB serial', 'Bundle'], results.map((r) => [r.copy, r.serial, r.bundleId]));
478
+ output.info("Next: 'ceremony teardown' to destroy the RAM workspace.");
479
+ }
480
+ finally {
481
+ await ops.close();
482
+ }
483
+ });
484
+ // ------------------------------------------------------------- teardown ---
485
+ ceremony
486
+ .command('teardown [device]')
487
+ .description('Destroy the RAM workspace and PROVE it is gone')
488
+ .action(async (device) => {
489
+ requireLocalDb();
490
+ const ops = await lifecycle();
491
+ try {
492
+ const active = await requireActive(ops);
493
+ // THE DEVICE COMES FROM THE RECORD, not from argv. It used to come from
494
+ // argv and was never compared with anything: a typo destroyed nothing,
495
+ // reported success — `hdiutil detach` on a device that does not exist
496
+ // fails quietly and the checks then observe that the nonexistent device
497
+ // is indeed gone — and left the real RAM disk attached with the
498
+ // bootstrap key in it. The optional argument is now only a cross-check.
499
+ const recordedDevice = await recordedWorkspaceDevice(ops, active.operationId);
500
+ if (device !== undefined && device !== recordedDevice) {
501
+ throw new Error(`This ceremony's workspace is ${recordedDevice}, not ${device}. Tearing ` +
502
+ `down ${device} would report success while ${recordedDevice} stayed ` +
503
+ 'attached with key material in it.');
504
+ }
505
+ const facts = destroyRamWorkspace(recordedDevice);
506
+ // Unmounting is not destroying: the RAM still holds the bytes and the
507
+ // device can be remounted by anyone.
508
+ assertTornDown(facts);
509
+ await advance(ops, active, 'teardown', { device: recordedDevice });
510
+ output.success(`${recordedDevice} unmounted and detached; the workspace is gone.`);
511
+ output.info("Close the ceremony with 'ceremony finish'.");
512
+ }
513
+ finally {
514
+ await ops.close();
515
+ }
516
+ });
517
+ // --------------------------------------------------------------- finish ---
518
+ ceremony
519
+ .command('finish')
520
+ .description('Close the ceremony as COMPLETED')
521
+ .action(async () => {
522
+ requireLocalDb();
523
+ const ops = await lifecycle();
524
+ try {
525
+ const active = await requireActive(ops);
526
+ // Over the RECORDED ROUTE, not the current phase. Checking only "are we
527
+ // at teardown?" let a ceremony that had done nothing but start and tear
528
+ // down close as COMPLETED — and COMPLETED is the word somebody reads
529
+ // years later, on the day the escrow is all that is left.
530
+ const history = await ops.history(active.operationId);
531
+ assertRouteComplete(history.map((e) => e.phase));
532
+ const verified = await recordedDetail(ops, active.operationId, 'verify');
533
+ await ops.finish({
534
+ operationId: active.operationId,
535
+ expectedEpoch: active.epoch,
536
+ outcome: 'COMPLETED',
537
+ nodeId: hostname(),
538
+ ...(verified ? { detail: verified } : {}),
539
+ });
540
+ output.success(`Ceremony ${active.operationId} closed as COMPLETED.`);
541
+ output.info('The bundle ids, the KCV and both serials are in the record: ceremony status.');
542
+ }
543
+ finally {
544
+ await ops.close();
545
+ }
546
+ });
547
+ // ---------------------------------------------------------------- abort ---
548
+ ceremony
549
+ .command('abort')
550
+ .description('Close the ceremony as ABANDONED, keeping the reason')
551
+ .requiredOption('--reason <text>', 'Why it was abandoned — the next person will read this')
552
+ .option('--force', 'Abandon even if the RAM workspace could not be destroyed')
553
+ .action(async (options) => {
554
+ requireLocalDb();
555
+ const ops = await lifecycle();
556
+ try {
557
+ const active = await requireActive(ops);
558
+ // ABANDONING CLEANS UP, because nothing else can. Abandoning frees the
559
+ // slot, and `teardown` needs an active ceremony — so an abort that left
560
+ // the workspace behind would strand a mounted RAM volume holding the
561
+ // bootstrap key with no command able to destroy it. The hint that used
562
+ // to say "run teardown afterwards" was advice that could not be taken.
563
+ const device = recordedString(await recordedDetail(ops, active.operationId, 'workspace'), 'device');
564
+ if (device !== null) {
565
+ try {
566
+ assertTornDown(destroyRamWorkspace(device));
567
+ output.info(`RAM workspace ${device} destroyed.`);
568
+ }
569
+ catch (error) {
570
+ if (options.force !== true) {
571
+ throw new Error(`The ceremony has NOT been abandoned: its RAM workspace ${device} ` +
572
+ 'could not be destroyed, and abandoning would free the slot while ' +
573
+ 'leaving key material mounted with no command able to reach it. ' +
574
+ `Deal with it by hand ('hdiutil detach ${device}'), then abort again. ` +
575
+ 'To abandon anyway, add --force. Underlying reason: ' +
576
+ (error instanceof Error ? error.message : String(error)));
577
+ }
578
+ output.warn(`Abandoning with --force: ${device} may still be attached WITH KEY ` +
579
+ 'MATERIAL IN IT. Destroy it by hand, now.');
580
+ }
581
+ }
582
+ await ops.finish({
583
+ operationId: active.operationId,
584
+ expectedEpoch: active.epoch,
585
+ outcome: 'ABANDONED',
586
+ nodeId: hostname(),
587
+ error: options.reason,
588
+ });
589
+ output.warn(`Ceremony ${active.operationId} abandoned at phase '${active.phase}'.`);
590
+ output.info('The slot is free and the workspace is gone.');
591
+ }
592
+ finally {
593
+ await ops.close();
594
+ }
595
+ });
596
+ }
597
+ //# sourceMappingURL=lmk-ceremony.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lmk-ceremony.js","sourceRoot":"","sources":["../../src/commands/lmk-ceremony.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"lmk-escrow.d.ts","sourceRoot":"","sources":["../../src/commands/lmk-escrow.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+EzC,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAgJ5D"}
1
+ {"version":3,"file":"lmk-escrow.d.ts","sourceRoot":"","sources":["../../src/commands/lmk-escrow.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuJzC,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAmK5D"}