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.
- package/README.md +144 -2
- package/dist/consensus/parser.js +18 -3
- package/dist/consensus/parser.js.map +1 -1
- package/dist/consensus/types.d.ts +9 -0
- package/dist/evidence/original-run/decode.d.ts +14 -0
- package/dist/evidence/original-run/decode.js +157 -0
- package/dist/evidence/original-run/decode.js.map +1 -0
- package/dist/evidence/original-run/journal.d.ts +13 -0
- package/dist/evidence/original-run/journal.js +116 -0
- package/dist/evidence/original-run/journal.js.map +1 -0
- package/dist/evidence/original-run/lock-path.d.ts +17 -0
- package/dist/evidence/original-run/lock-path.js +116 -0
- package/dist/evidence/original-run/lock-path.js.map +1 -0
- package/dist/evidence/original-run/lock-scope.d.ts +21 -0
- package/dist/evidence/original-run/lock-scope.js +61 -0
- package/dist/evidence/original-run/lock-scope.js.map +1 -0
- package/dist/evidence/original-run/lock.d.ts +31 -0
- package/dist/evidence/original-run/lock.js +258 -0
- package/dist/evidence/original-run/lock.js.map +1 -0
- package/dist/evidence/original-run/remote.d.ts +22 -0
- package/dist/evidence/original-run/remote.js +104 -0
- package/dist/evidence/original-run/remote.js.map +1 -0
- package/dist/evidence/original-run/source.d.ts +60 -0
- package/dist/evidence/original-run/source.js +205 -0
- package/dist/evidence/original-run/source.js.map +1 -0
- package/dist/evidence/recover-run.d.ts +25 -0
- package/dist/evidence/recover-run.js +180 -0
- package/dist/evidence/recover-run.js.map +1 -0
- package/dist/index.js +80 -15
- package/dist/index.js.map +1 -1
- package/dist/telemetry/deliver.d.ts +7 -0
- package/dist/telemetry/deliver.js +75 -16
- package/dist/telemetry/deliver.js.map +1 -1
- package/dist/telemetry/envelope-validation.d.ts +11 -0
- package/dist/telemetry/envelope-validation.js +117 -0
- package/dist/telemetry/envelope-validation.js.map +1 -0
- package/dist/telemetry/envelope.d.ts +8 -0
- package/dist/telemetry/envelope.js +20 -0
- package/dist/telemetry/envelope.js.map +1 -1
- package/dist/telemetry/quarantine.d.ts +105 -0
- package/dist/telemetry/quarantine.js +224 -0
- package/dist/telemetry/quarantine.js.map +1 -0
- package/dist/telemetry/recovery/source.d.ts +219 -0
- package/dist/telemetry/recovery/source.js +10 -3
- package/dist/telemetry/recovery/source.js.map +1 -1
- package/dist/telemetry/sink.d.ts +7 -0
- package/dist/telemetry/sink.js +59 -1
- package/dist/telemetry/sink.js.map +1 -1
- 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 `
|
|
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
|
|
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
|
package/dist/consensus/parser.js
CHANGED
|
@@ -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.
|
|
7
|
-
*
|
|
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.
|
|
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":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;GAMG;AACH,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;
|
|
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 {};
|