review-council 3.7.0 → 3.8.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 (49) hide show
  1. package/README.md +144 -2
  2. package/dist/consensus/parser.js +18 -3
  3. package/dist/consensus/parser.js.map +1 -1
  4. package/dist/consensus/types.d.ts +9 -0
  5. package/dist/evidence/original-run/decode.d.ts +14 -0
  6. package/dist/evidence/original-run/decode.js +157 -0
  7. package/dist/evidence/original-run/decode.js.map +1 -0
  8. package/dist/evidence/original-run/journal.d.ts +13 -0
  9. package/dist/evidence/original-run/journal.js +116 -0
  10. package/dist/evidence/original-run/journal.js.map +1 -0
  11. package/dist/evidence/original-run/lock-path.d.ts +17 -0
  12. package/dist/evidence/original-run/lock-path.js +116 -0
  13. package/dist/evidence/original-run/lock-path.js.map +1 -0
  14. package/dist/evidence/original-run/lock-scope.d.ts +21 -0
  15. package/dist/evidence/original-run/lock-scope.js +61 -0
  16. package/dist/evidence/original-run/lock-scope.js.map +1 -0
  17. package/dist/evidence/original-run/lock.d.ts +31 -0
  18. package/dist/evidence/original-run/lock.js +258 -0
  19. package/dist/evidence/original-run/lock.js.map +1 -0
  20. package/dist/evidence/original-run/remote.d.ts +22 -0
  21. package/dist/evidence/original-run/remote.js +104 -0
  22. package/dist/evidence/original-run/remote.js.map +1 -0
  23. package/dist/evidence/original-run/source.d.ts +60 -0
  24. package/dist/evidence/original-run/source.js +205 -0
  25. package/dist/evidence/original-run/source.js.map +1 -0
  26. package/dist/evidence/recover-run.d.ts +25 -0
  27. package/dist/evidence/recover-run.js +180 -0
  28. package/dist/evidence/recover-run.js.map +1 -0
  29. package/dist/index.js +80 -15
  30. package/dist/index.js.map +1 -1
  31. package/dist/telemetry/deliver.d.ts +7 -0
  32. package/dist/telemetry/deliver.js +75 -16
  33. package/dist/telemetry/deliver.js.map +1 -1
  34. package/dist/telemetry/envelope-validation.d.ts +11 -0
  35. package/dist/telemetry/envelope-validation.js +117 -0
  36. package/dist/telemetry/envelope-validation.js.map +1 -0
  37. package/dist/telemetry/envelope.d.ts +8 -0
  38. package/dist/telemetry/envelope.js +20 -0
  39. package/dist/telemetry/envelope.js.map +1 -1
  40. package/dist/telemetry/quarantine.d.ts +105 -0
  41. package/dist/telemetry/quarantine.js +224 -0
  42. package/dist/telemetry/quarantine.js.map +1 -0
  43. package/dist/telemetry/recovery/source.d.ts +219 -0
  44. package/dist/telemetry/recovery/source.js +10 -3
  45. package/dist/telemetry/recovery/source.js.map +1 -1
  46. package/dist/telemetry/sink.d.ts +7 -0
  47. package/dist/telemetry/sink.js +59 -1
  48. package/dist/telemetry/sink.js.map +1 -1
  49. package/package.json +2 -2
package/README.md CHANGED
@@ -275,7 +275,7 @@ preliminary-truncation behavior of RCL 3.6.0. Existing source reports are not
275
275
  rewritten to add explanations; legacy backfill retains its declared artifact
276
276
  scrubbing and deterministic source identity rules.
277
277
 
278
- ### `rcl telemetry status` and `rcl telemetry flush`
278
+ ### `rcl telemetry status`, `flush` and `rejected`
279
279
 
280
280
  Evidence delivery to Harness (epic IO-12475). In a repository that carries
281
281
  `.harness-cli/config.json` and with a `harness login` (or `HARNESS_API_TOKEN` +
@@ -290,7 +290,7 @@ provider API keys, `GITHUB_TOKEN`, the Harness credential, environment
290
290
  variables, prompts or raw model answers; every free-text field is truncated
291
291
  and scrubbed for key-shaped strings before it leaves the process.
292
292
 
293
- The review never blocks on the network. A delivery Harness could not take is
293
+ The review never blocks on the network. A retryable delivery outage is
294
294
  spooled to `~/.rcl/outbox/<run id>/` and retried, with its original run id,
295
295
  at the start of every rcl command (bounded to five seconds) or by
296
296
  `rcl telemetry flush`. One dim status line says what happened:
@@ -306,10 +306,30 @@ evidence failure is printed beside it. The first delivery from a machine
306
306
  prints a one-time notice naming the host and what is sent
307
307
  (`~/.rcl/telemetry-notice` records it).
308
308
 
309
+ Completed envelopes are validated locally before transmission. Two valid
310
+ reversed line numbers are ordered before finding identity is allocated, with
311
+ the original numeric pair retained as parser provenance. Missing, blank,
312
+ boolean, negative, fractional or non-finite coordinates remain parser errors;
313
+ valid sibling findings are preserved. Provenance delivery requires the server
314
+ to advertise evidence protocol version 2.
315
+
316
+ Local validation failures and terminal server refusals retain the exact JSON
317
+ and Markdown bytes in `~/.rcl/quarantine/<run id>/` (or under `RCL_DATA_DIR`).
318
+ The immutable manifest records original digests, delivery mode and diagnostics;
319
+ distinct later delivery observations are appended separately. Interrupted or
320
+ corrupted entries are reported as incomplete. Retention failure, including a
321
+ read-only filesystem or the 1 GiB storage cap, is reported explicitly.
322
+ `rcl telemetry rejected` inspects these files and verifies their digests without
323
+ contacting Harness, flushing the outbox, changing native review accounting or
324
+ applying recovery. Retained evidence is not server acknowledgment. Attested
325
+ evidence is never queued for replay with ordinary credentials. Recovery of an
326
+ already-completed historical run remains a separate operation.
327
+
309
328
  ```bash
310
329
  rcl telemetry status # level, credential source, what waits in the outbox
311
330
  rcl telemetry flush # deliver everything spooled, to completion
312
331
  rcl telemetry flush --run <run id> # one run only
332
+ rcl telemetry rejected --run <run id> --json # inspect one retained original
313
333
  rcl review owner/repo#7 --no-telemetry # keep this review on the machine
314
334
  ```
315
335
 
@@ -424,6 +444,128 @@ rcl evidence status https://github.com/allocator-one/rcl/pull/42
424
444
  rcl evidence show 01a08032-0838-76db-ade3-1990f6e54072
425
445
  ```
426
446
 
447
+ ### `rcl evidence recover-run`
448
+
449
+ Recover one original completed asserted run without rerunning review, changing its
450
+ UUID or rewriting its JSON/Markdown artifacts. This is delivery only: it does not
451
+ admit a native round, record verdicts, change attempts/precision, flush unrelated
452
+ outbox entries or confer gate approval. Semantic claim splits are not part of this
453
+ command.
454
+
455
+ First prepare an exclusive manifest using explicit original source pins:
456
+
457
+ ```sh
458
+ rcl evidence recover-run --preview --manifest original-run.json \
459
+ --run "$ORIGINAL_RUN_ID" --for-pr owner/repo#123 --head "$ORIGINAL_HEAD_SHA" \
460
+ --report-json /absolute/original/report.json --report-sha256 "$JSON_SHA256" \
461
+ --report-md /absolute/original/report.md --markdown-sha256 "$MARKDOWN_SHA256" \
462
+ --original-mode asserted --json
463
+ ```
464
+
465
+ Markdown is optional; its path and digest must be supplied together. The report
466
+ must retain its complete modern header, explicit finding identities, and an exact
467
+ PR or PR-bound patch target. Original UUIDs must already be lowercase; recovery
468
+ refuses other spellings instead of rewriting identity. Headerless imports, CI/attested/backfill originals,
469
+ unknown mode fields, missing sources and ambiguous bindings refuse. The explicit
470
+ asserted mode is an **operator assertion**, checked against the retained non-CI
471
+ runner metadata; it is not cryptographic proof of the original invocation. A
472
+ run-bound credential is never converted to a normal login.
473
+
474
+ Preview validates all local inputs before HTTP and writes only the explicitly
475
+ named manifest. Its formatted UTF-8 representation, including the final newline,
476
+ must fit within 8 MiB so apply and resume can read it. Oversized prepared evidence
477
+ refuses before HTTP; the complete manifest is checked again before publication.
478
+ It makes scoped authenticated GET requests, requires
479
+ `meta.original_report_recovery_version: 1` and evidence protocol 2, and binds the
480
+ host and server organization. An older or disabled server remains unsupported.
481
+ Inspect the manifest's exact envelope, source digests, transformations and retained
482
+ content limitations, then use the digest printed by preview:
483
+
484
+ ```sh
485
+ rcl evidence recover-run --apply --manifest original-run.json \
486
+ --manifest-sha256 "$MANIFEST_SHA256" --json
487
+
488
+ # After interruption or an uncertain acknowledgment, reuse that same operation.
489
+ rcl evidence recover-run --resume --manifest original-run.json \
490
+ --manifest-sha256 "$MANIFEST_SHA256" --json
491
+ ```
492
+
493
+ Apply starts an adjacent `original-run.json.journal` directory with append-only,
494
+ fsynced checkpoints before every remote write. Each checkpoint has an
495
+ 8 MiB + 1 KiB read/write bound, retaining the manifest's full prose audit and
496
+ reserving space for the checkpoint wrapper.
497
+ Oversized checkpoints refuse before publication. Apply and resume require the
498
+ journal to be effective-user-owned mode 0700, on the supported local storage
499
+ listed below, with protected ancestors and no harmful or unknown ACL grants.
500
+ Apply checks the selected parent before creating the journal exclusively; resume
501
+ never creates missing state or repairs permissions. Each append checks the
502
+ selected journal's device/inode identity before writing. This detects replacement
503
+ between checkpoints; it does not claim protection against concurrent privileged
504
+ or same-user path manipulation. Resume requires that directory;
505
+ it never generates a replacement operation. A dedicated
506
+ `RCL_DATA_DIR/original-run-recovery-locks` directory serializes applies for the same
507
+ host/organization/run, including different manifest paths. Native accounting
508
+ locks and stores are not used. Locks with incomplete or unverifiable ownership
509
+ fail closed and require inspection; never delete a live lock.
510
+
511
+ The lock uses a unique registration per acquisition and automatically removes a
512
+ dead participant only when its PID is absent in the same kernel boot and PID
513
+ namespace. A reboot, foreign scope, PID reuse or uncertain liveness requires
514
+ inspection or a bounded retry; age alone never permits deletion. Legacy private
515
+ `.lock`/`.reclaim` state is refused, not migrated or bypassed. Empty `.bakery`
516
+ registries remain in place, and an interrupted unpublished `.tmp` is harmless.
517
+ Concurrent older private recovery clients are unsupported.
518
+
519
+ This protocol requires coherent ordinary local storage: local APFS/HFS with
520
+ ownership enabled on macOS, or ext2/3/4, tmpfs, XFS or Btrfs on Linux. Network,
521
+ FUSE, overlay and unknown filesystems are unsupported. macOS refuses an ambiguous
522
+ system mount listing, including an ambiguous entry for an unrelated mount. It
523
+ uses the existing directory's filesystem name and mountpoint from bounded
524
+ `df --libxo json` output, matched to one exact mount-table entry; firmlink or case
525
+ aliases never select an ancestor's flags. Unavailable structured inspection or
526
+ unmatched/ambiguous attribution refuses without a fallback. It
527
+ rejects ACL allow grants or unrecognized ACL output; restrictive deny-only ACLs
528
+ are allowed. The root must already be private (effective-user-owned
529
+ mode 0700), and ancestors must be protected against other users' writes, apart
530
+ from root-owned sticky temporary directories. Missing private directories are
531
+ created; existing permissions are never silently repaired. These checks do not
532
+ certify arbitrary filesystem implementations or protect against hostile code
533
+ running as the same user or a privileged administrator.
534
+
535
+ Every invocation rechecks source bytes and the reviewed manifest. Before retrying,
536
+ it reads and compares all immutable run header/settings/findings/calls/artifact
537
+ declarations, then fetches exact raw artifact bytes and verifies their digest and
538
+ size. A POST duplicate receipt or a stored-artifact flag alone is insufficient.
539
+ Lost POST/PUT acknowledgment can finish through exact reads; otherwise the same
540
+ journal remains incomplete. Changed bytes, organization, header, findings or calls
541
+ refuse. A torn last checkpoint is retained and bound into the next append; it is
542
+ never treated as acknowledgment. Preserve the manifest, journal and sources until
543
+ independent reconciliation is complete.
544
+
545
+ Only unpaired UTF-16 units in actual finding `title`, `description` or
546
+ `suggestedFix` prose receive a derived wire spelling: visible ASCII `\uD800`,
547
+ using uppercase hex. Valid surrogate pairs and existing literal backslash-u text
548
+ remain unchanged. Each transformation records the original JSON path, code-unit
549
+ index and byte offset. Keys, identifiers, descriptors and structural fields cannot
550
+ receive that transformation. Existing producer `[redacted]` literals in finding
551
+ prose stay unchanged and are listed as retained-content limitations; markers in
552
+ protected bindings, or any newly required secret redaction, refuse. Markdown
553
+ requiring redaction is unsupported. No fresh-report normalizer or backfill UUID
554
+ is applied to the original.
555
+
556
+ Existing transport scrubbing, limits, call summaries and duration rounding remain
557
+ explicitly recorded derivations. Two valid reversed integer coordinates may use
558
+ `report_projection` provenance bound to the original coordinates and JSON digest;
559
+ original finding identities are never recomputed from the normalized interval.
560
+ Unsupported coordinate types refuse rather than being guessed.
561
+
562
+ Exit codes: `0` means preview prepared or delivery independently verified; `2`
563
+ means invalid/unavailable local selection; `3` means remote capability/read/delivery
564
+ unanswered; `4` means conflicting destination, evidence or journal bindings; `5` means local durable
565
+ journal/lock persistence failed. JSON diagnostics include the stage and next step.
566
+ Even successful delivery does not establish current-head review freshness,
567
+ convergence, attestation or historical accounting repair.
568
+
427
569
  ### `rcl evidence recover-finding`
428
570
 
429
571
  Recover one recorded finding whose report identity collided, using its retained
@@ -3,10 +3,10 @@ import { z } from 'zod';
3
3
  * Models emit line numbers as JSON strings often enough ("startLine": "59")
4
4
  * that a strict `z.number()` silently discards otherwise-perfect findings —
5
5
  * and when EVERY finding in a response is affected, the whole reviewer is
6
- * lost. Coerce instead, then enforce the integer/non-negative shape, so a
7
- * genuinely nonsensical value is still rejected.
6
+ * lost. Preserve numeric-string compatibility, but never coerce null, a
7
+ * boolean, a blank string or a container into an invented coordinate.
8
8
  */
9
- const LineNumber = z.coerce.number().int().nonnegative();
9
+ const LineNumber = z.preprocess((value) => typeof value === 'string' && value.trim() !== '' ? Number(value) : value, z.number().int().nonnegative());
10
10
  /**
11
11
  * Enum-ish fields arrive with stray casing or whitespace ("Critical",
12
12
  * " security"). Normalizing before validation costs nothing and is the same
@@ -28,6 +28,21 @@ const FindingSchema = z.object({
28
28
  title: z.string().max(200),
29
29
  description: z.string(),
30
30
  suggestedFix: z.string().optional(),
31
+ }).transform((finding) => {
32
+ if (finding.startLine <= finding.endLine)
33
+ return finding;
34
+ return {
35
+ ...finding,
36
+ startLine: finding.endLine,
37
+ endLine: finding.startLine,
38
+ locationProvenance: {
39
+ version: 1,
40
+ source: 'parser',
41
+ reason: 'reversed_range',
42
+ originalStartLine: finding.startLine,
43
+ originalEndLine: finding.endLine,
44
+ },
45
+ };
31
46
  });
32
47
  const ReviewOutputSchema = z.object({
33
48
  findings: z.array(FindingSchema),
@@ -1 +1 @@
1
- {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/consensus/parser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/consensus/parser.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,17 @@
1
+ /** The original numeric interval when a model returned its endpoints reversed. */
2
+ export interface LocationProvenance {
3
+ version: 1;
4
+ source: 'parser';
5
+ reason: 'reversed_range';
6
+ originalStartLine: number;
7
+ originalEndLine: number;
8
+ }
1
9
  export interface Finding {
2
10
  id: string;
3
11
  file: string;
4
12
  startLine: number;
5
13
  endLine: number;
14
+ locationProvenance?: LocationProvenance;
6
15
  severity: 'critical' | 'important' | 'minor' | 'nitpick';
7
16
  category: 'security' | 'correctness' | 'best-practices' | 'tests' | 'api-design';
8
17
  title: string;
@@ -0,0 +1,14 @@
1
+ /** An interpretation of immutable JSON, never replacement artifact bytes. */
2
+ export interface ProseTransformation {
3
+ path: string;
4
+ code_unit_offset: number;
5
+ source_byte_offset: number;
6
+ original_unit: string;
7
+ replacement: string;
8
+ }
9
+ export declare const findingProsePath: RegExp;
10
+ /** Strict JSON with duplicate-key detection and explicit prose-only lone-surrogate notation. */
11
+ export declare function decodeOriginalReport(text: string): {
12
+ value: unknown;
13
+ transformations: ProseTransformation[];
14
+ };
@@ -0,0 +1,157 @@
1
+ export const findingProsePath = /^(?:\/(?:findings|belowThresholdFindings)\/\d+|\/reviews\/\d+\/findings\/\d+)\/(?:title|description|suggestedFix)$/;
2
+ const pointer = (parts) => '/' + parts.map(p => p.replace(/~/g, '~0').replace(/\//g, '~1')).join('/');
3
+ const scalarToken = /(?:-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?|true|false|null)/y;
4
+ /** UTF-8 prefix lengths for the immutable source, computed once only when needed. */
5
+ function utf8Offsets(text) {
6
+ const offsets = new Uint32Array(text.length + 1);
7
+ let bytes = 0;
8
+ for (let index = 0; index < text.length; index++) {
9
+ offsets[index] = bytes;
10
+ const unit = text.charCodeAt(index);
11
+ if (unit <= 0x7f)
12
+ bytes++;
13
+ else if (unit <= 0x7ff)
14
+ bytes += 2;
15
+ else if (unit >= 0xd800 && unit <= 0xdbff && text.charCodeAt(index + 1) >= 0xdc00 && text.charCodeAt(index + 1) <= 0xdfff) {
16
+ // Buffer.byteLength on a prefix ending between a valid pair encodes the
17
+ // detached high unit as U+FFFD; normal scanner offsets never land there.
18
+ offsets[index + 1] = bytes + 3;
19
+ bytes += 4;
20
+ index++;
21
+ }
22
+ else
23
+ bytes += 3;
24
+ }
25
+ offsets[text.length] = bytes;
26
+ return offsets;
27
+ }
28
+ /** Strict JSON with duplicate-key detection and explicit prose-only lone-surrogate notation. */
29
+ export function decodeOriginalReport(text) {
30
+ let at = 0;
31
+ const transformations = [];
32
+ let sourceOffsets;
33
+ const fail = () => { throw new Error('invalid_or_ambiguous_original_json'); };
34
+ const whitespace = () => { while (/[\x20\t\r\n]/.test(text[at] ?? 'x'))
35
+ at++; };
36
+ function string(path, key = false) {
37
+ const start = at++;
38
+ if (text[start] !== '"')
39
+ return fail();
40
+ const offsets = new Map();
41
+ let units = 0;
42
+ while (at < text.length && text[at] !== '"') {
43
+ // Valid UTF-8 cannot contain a literal unpaired unit. Only \u escapes
44
+ // need source positions; avoid one allocation per prose character.
45
+ if (text[at] === '\\' && text[at + 1] === 'u')
46
+ offsets.set(units, at);
47
+ if (text[at] === '\\') {
48
+ at += text[at + 1] === 'u' ? 6 : 2;
49
+ }
50
+ else
51
+ at++;
52
+ units++;
53
+ }
54
+ if (text[at++] !== '"')
55
+ return fail();
56
+ let value;
57
+ try {
58
+ value = JSON.parse(text.slice(start, at));
59
+ }
60
+ catch {
61
+ return fail();
62
+ }
63
+ let result = '';
64
+ for (let i = 0; i < value.length; i++) {
65
+ const unit = value.charCodeAt(i);
66
+ if (unit === 0)
67
+ throw new Error('unsupported_nul_in_original');
68
+ if (unit >= 0xd800 && unit <= 0xdbff && value.charCodeAt(i + 1) >= 0xdc00 && value.charCodeAt(i + 1) <= 0xdfff) {
69
+ result += value.slice(i, i + 2);
70
+ i++;
71
+ continue;
72
+ }
73
+ if (unit >= 0xd800 && unit <= 0xdfff) {
74
+ if (key || !findingProsePath.test(pointer(path)))
75
+ throw new Error('unsupported_structural_surrogate');
76
+ const hex = unit.toString(16).toUpperCase();
77
+ const replacement = `\\u${hex}`;
78
+ const source = offsets.get(i);
79
+ if (source === undefined)
80
+ throw new Error('unsupported_literal_surrogate');
81
+ sourceOffsets ??= utf8Offsets(text);
82
+ transformations.push({ path: pointer(path), code_unit_offset: i, source_byte_offset: sourceOffsets[source], original_unit: hex, replacement });
83
+ result += replacement;
84
+ }
85
+ else
86
+ result += value[i];
87
+ }
88
+ return result;
89
+ }
90
+ function value(path, depth) {
91
+ if (depth > 64)
92
+ throw new Error('original_json_too_deep');
93
+ whitespace();
94
+ if (text[at] === '"')
95
+ return string(path);
96
+ if (text[at] === '{') {
97
+ at++;
98
+ whitespace();
99
+ const out = Object.create(null);
100
+ if (text[at] === '}') {
101
+ at++;
102
+ return out;
103
+ }
104
+ for (;;) {
105
+ whitespace();
106
+ const key = string(path, true);
107
+ if (Object.hasOwn(out, key) || ['__proto__', 'constructor', 'prototype'].includes(key))
108
+ return fail();
109
+ whitespace();
110
+ if (text[at++] !== ':')
111
+ return fail();
112
+ out[key] = value([...path, key], depth + 1);
113
+ whitespace();
114
+ if (text[at] === '}') {
115
+ at++;
116
+ return out;
117
+ }
118
+ if (text[at++] !== ',')
119
+ return fail();
120
+ }
121
+ }
122
+ if (text[at] === '[') {
123
+ at++;
124
+ whitespace();
125
+ const out = [];
126
+ if (text[at] === ']') {
127
+ at++;
128
+ return out;
129
+ }
130
+ for (;;) {
131
+ out.push(value([...path, String(out.length)], depth + 1));
132
+ whitespace();
133
+ if (text[at] === ']') {
134
+ at++;
135
+ return out;
136
+ }
137
+ if (text[at++] !== ',')
138
+ return fail();
139
+ }
140
+ }
141
+ scalarToken.lastIndex = at;
142
+ const token = scalarToken.exec(text);
143
+ if (!token)
144
+ return fail();
145
+ at += token[0].length;
146
+ const parsed = JSON.parse(token[0]);
147
+ if (typeof parsed === 'number' && (!Number.isFinite(parsed) || Math.abs(parsed) > Number.MAX_SAFE_INTEGER))
148
+ return fail();
149
+ return parsed;
150
+ }
151
+ const result = value([], 0);
152
+ whitespace();
153
+ if (at !== text.length)
154
+ return fail();
155
+ return { value: JSON.parse(JSON.stringify(result)), transformations };
156
+ }
157
+ //# sourceMappingURL=decode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode.js","sourceRoot":"","sources":["../../../src/evidence/original-run/decode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export declare const MAX_RECOVERY_DOCUMENT_BYTES: number;
2
+ export declare const MAX_RECOVERY_CHECKPOINT_BYTES: number;
3
+ export declare function syncDirectory(path: string): Promise<void>;
4
+ /** One byte representation for size checks, immutable writes and digests. */
5
+ export declare function serializeRecoveryDocument(value: unknown, limit?: number): string;
6
+ /** Exclusive named publication; a failed write is retained and never overwritten. */
7
+ export declare function writeExclusive(path: string, value: unknown, limit?: number): Promise<void>;
8
+ export { withRecoveryLock } from './lock.js';
9
+ export interface Journal {
10
+ append: (phase: string, data?: unknown) => Promise<void>;
11
+ }
12
+ /** Checkpoints are audit facts, never a substitute for fresh server readback. */
13
+ export declare function openJournal(path: string, manifestSha: string, operation: string, mode: 'apply' | 'resume', beforeWrite?: (phase: string) => Promise<void>): Promise<Journal>;
@@ -0,0 +1,116 @@
1
+ import { constants } from 'node:fs';
2
+ import { lstat, mkdir, open, readdir, realpath } from 'node:fs/promises';
3
+ import { dirname, join } from 'node:path';
4
+ import { isDeepStrictEqual } from 'node:util';
5
+ import { platformPath, readStable, sha256 } from '../../telemetry/recovery/files.js';
6
+ import { inspectRecoveryDirectory } from './lock-path.js';
7
+ // Prepared checkpoint data copies manifest subtrees at the same indentation,
8
+ // except for the destination's extra level and the longer source field name.
9
+ // Reserve 1 KiB beyond the manifest for those bytes and the bounded journal
10
+ // wrapper (UUID, hashes, sequence, phase and timestamp); do not truncate audit.
11
+ export const MAX_RECOVERY_DOCUMENT_BYTES = 8 * 1024 * 1024;
12
+ export const MAX_RECOVERY_CHECKPOINT_BYTES = MAX_RECOVERY_DOCUMENT_BYTES + 1024;
13
+ async function parentSafe(path) {
14
+ if (await realpath(dirname(path)) !== dirname(path))
15
+ throw new Error('symlink_directory');
16
+ }
17
+ export async function syncDirectory(path) {
18
+ const handle = await open(path, 'r');
19
+ try {
20
+ await handle.sync();
21
+ }
22
+ finally {
23
+ await handle.close();
24
+ }
25
+ }
26
+ /** One byte representation for size checks, immutable writes and digests. */
27
+ export function serializeRecoveryDocument(value, limit = Infinity) {
28
+ const text = JSON.stringify(value, null, 2) + '\n';
29
+ if (Buffer.byteLength(text, 'utf8') > limit)
30
+ throw new Error('recovery_document_too_large');
31
+ return text;
32
+ }
33
+ /** Exclusive named publication; a failed write is retained and never overwritten. */
34
+ export async function writeExclusive(path, value, limit = Infinity) {
35
+ const text = serializeRecoveryDocument(value, limit);
36
+ const file = platformPath(path);
37
+ await parentSafe(file);
38
+ const handle = await open(file, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY | constants.O_NOFOLLOW, 0o600);
39
+ try {
40
+ await handle.writeFile(text);
41
+ await handle.sync();
42
+ }
43
+ finally {
44
+ await handle.close();
45
+ }
46
+ await syncDirectory(dirname(file));
47
+ }
48
+ export { withRecoveryLock } from './lock.js';
49
+ async function inspectJournalDirectory(path, privateRoot) {
50
+ try {
51
+ await inspectRecoveryDirectory(path, privateRoot);
52
+ }
53
+ catch (error) {
54
+ if (error instanceof Error && /^(unsafe|unsupported)_recovery_lock_/.test(error.message)) {
55
+ throw new Error(error.message.replace('_lock_', '_journal_'));
56
+ }
57
+ throw error;
58
+ }
59
+ }
60
+ /** Checkpoints are audit facts, never a substitute for fresh server readback. */
61
+ export async function openJournal(path, manifestSha, operation, mode, beforeWrite) {
62
+ path = platformPath(path);
63
+ await parentSafe(path);
64
+ await inspectJournalDirectory(dirname(path), false);
65
+ if (mode === 'apply') {
66
+ await mkdir(path, { mode: 0o700 });
67
+ await syncDirectory(dirname(path));
68
+ }
69
+ else if (await realpath(path) !== path || !(await lstat(path)).isDirectory())
70
+ throw new Error('recovery_journal_unavailable');
71
+ await inspectJournalDirectory(path, true);
72
+ const directory = await lstat(path, { bigint: true });
73
+ const files = (await readdir(path)).sort();
74
+ if (files.some(n => !/^\d{8}\.json$/.test(n)))
75
+ throw new Error('unknown_recovery_journal_file');
76
+ let sequence = 0;
77
+ let previous = manifestSha;
78
+ let torn = [];
79
+ for (const name of files) {
80
+ if (name !== `${String(++sequence).padStart(8, '0')}.json`)
81
+ throw new Error('recovery_journal_sequence_gap');
82
+ const snapshot = await readStable(join(path, name), MAX_RECOVERY_CHECKPOINT_BYTES);
83
+ let record;
84
+ try {
85
+ record = JSON.parse(snapshot.text);
86
+ }
87
+ catch {
88
+ // Only an explicitly hash-bound acknowledgment can bridge interrupted
89
+ // appends. That acknowledgment remains traversable on every later resume.
90
+ torn.push({ file: name, sha256: snapshot.sha256 });
91
+ previous = snapshot.sha256;
92
+ continue;
93
+ }
94
+ if (record.operation_id !== operation || record.manifest_sha256 !== manifestSha || record.sequence !== sequence || record.previous_sha256 !== previous)
95
+ throw new Error('recovery_journal_binding_conflict');
96
+ if (torn.length && (record.phase !== 'interrupted_checkpoints_retained' || !isDeepStrictEqual(record.data, { files: torn })))
97
+ throw new Error('corrupt_recovery_journal');
98
+ torn = [];
99
+ previous = snapshot.sha256;
100
+ }
101
+ const journal = { append: async (phase, data = null) => {
102
+ await beforeWrite?.(phase);
103
+ const current = await lstat(path, { bigint: true });
104
+ if (!current.isDirectory() || current.dev !== directory.dev || current.ino !== directory.ino)
105
+ throw new Error('recovery_journal_replaced');
106
+ const record = { operation_id: operation, manifest_sha256: manifestSha, sequence: sequence + 1, previous_sha256: previous, phase, recorded_at: new Date().toISOString(), data };
107
+ const name = join(path, `${String(sequence + 1).padStart(8, '0')}.json`);
108
+ await writeExclusive(name, record, MAX_RECOVERY_CHECKPOINT_BYTES);
109
+ sequence++;
110
+ previous = sha256(JSON.stringify(record, null, 2) + '\n');
111
+ } };
112
+ if (torn.length)
113
+ await journal.append('interrupted_checkpoints_retained', { files: torn });
114
+ return journal;
115
+ }
116
+ //# sourceMappingURL=journal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"journal.js","sourceRoot":"","sources":["../../../src/evidence/original-run/journal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ interface DirectoryMetadata {
2
+ uid: number;
3
+ mode: number;
4
+ isDirectory: () => boolean;
5
+ isSymbolicLink: () => boolean;
6
+ }
7
+ export declare function checkLockDirectory(info: DirectoryMetadata, uid: number, privateRoot: boolean): void;
8
+ /** Darwin ACL allow entries can grant access despite mode 0700. Deny-only ACLs are safe. */
9
+ export declare function checkDarwinLockACL(output: string): void;
10
+ /** Match path-bound statfs information from df, including firmlink/case aliases. */
11
+ export declare function checkDarwinLockMount(output: string, filesystemOutput: string): void;
12
+ export declare function checkLinuxLockFilesystem(type: bigint): void;
13
+ /** Inspect existing recovery storage without creating or adopting missing state. */
14
+ export declare function inspectRecoveryDirectory(input: string, privateRoot: boolean): Promise<string>;
15
+ /** Validate before creating children, then recheck after concurrent mkdir. */
16
+ export declare function prepareLockRoot(input: string): Promise<string>;
17
+ export {};