@dogfood-lab/ingest 1.2.2 → 1.3.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/lib/rename-with-retry.js +8 -2
- package/lib/sleep-sync.js +31 -0
- package/lib/unsafe-segment.js +36 -36
- package/load-context.js +345 -131
- package/package.json +4 -5
- package/persist.js +172 -172
- package/rebuild-indexes.js +384 -356
- package/run.js +676 -540
- package/validate-record.js +77 -83
package/validate-record.js
CHANGED
|
@@ -1,83 +1,77 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Persisted-record schema validator.
|
|
3
|
-
*
|
|
4
|
-
* Enforces dogfood-record.schema.json at write time. The submission validator
|
|
5
|
-
* in @dogfood-lab/verify covers the inbound payload; this is the symmetric
|
|
6
|
-
* gate on the outbound payload — the central verifier assembles the record
|
|
7
|
-
* and the persist layer must not write anything that violates the contract.
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
keyword: err.keyword,
|
|
79
|
-
message: err.message,
|
|
80
|
-
params: err.params
|
|
81
|
-
}));
|
|
82
|
-
throw new RecordValidationError(errors);
|
|
83
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Persisted-record schema validator.
|
|
3
|
+
*
|
|
4
|
+
* Enforces dogfood-record.schema.json at write time. The submission validator
|
|
5
|
+
* in @dogfood-lab/verify covers the inbound payload; this is the symmetric
|
|
6
|
+
* gate on the outbound payload — the central verifier assembles the record
|
|
7
|
+
* and the persist layer must not write anything that violates the contract.
|
|
8
|
+
*
|
|
9
|
+
* H3 hop 4 (LAST — the C1-sealing hop): delegates to the canonical
|
|
10
|
+
* {@link validatePayload} from `@dogfood-lab/schemas`. Pre-H3 this module
|
|
11
|
+
* compiled its own Ajv2020 + ajv-formats instance for the record schema,
|
|
12
|
+
* which was the SAME schema the verifier-side path (now also canonical)
|
|
13
|
+
* compiled in a SECOND instance — the structural root of the C1 two-Ajv
|
|
14
|
+
* gap. After H3, ingest and verify share the single cached validator the
|
|
15
|
+
* canonical seam holds for `dogfood-record.schema.json`.
|
|
16
|
+
*
|
|
17
|
+
* Contract preserved:
|
|
18
|
+
* - Throws {@link RecordValidationError} on validation failure (NOT a
|
|
19
|
+
* return value — the persist layer treats a malformed record as a
|
|
20
|
+
* programming error, not user input).
|
|
21
|
+
* - `.code === 'RECORD_SCHEMA_INVALID'` is the structural error-codes
|
|
22
|
+
* gate pin (just hardened in A2.1 FX2 — see scripts/doc-drift-patterns.json
|
|
23
|
+
* error-codes check); the migration keeps it intact.
|
|
24
|
+
* - Each `errors[]` entry carries `{ path, keyword, message, params }` —
|
|
25
|
+
* the keyword pin (packages/ingest/ingest.test.js:208-220) asserts
|
|
26
|
+
* `typeof e.keyword === 'string'` for every error. The H3 keyword
|
|
27
|
+
* extension at the canonical seam (validate.ts ValidationError) is
|
|
28
|
+
* what makes this contract preservable without ingest holding its
|
|
29
|
+
* own Ajv instance.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import { validatePayload } from '@dogfood-lab/schemas';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Structured error thrown when a persisted record violates the schema.
|
|
36
|
+
* Caller code can `instanceof RecordValidationError` to distinguish from
|
|
37
|
+
* IO/path errors.
|
|
38
|
+
*/
|
|
39
|
+
export class RecordValidationError extends Error {
|
|
40
|
+
constructor(errors) {
|
|
41
|
+
const summary = errors
|
|
42
|
+
.map(e => `${e.path || '/'} ${e.message}`)
|
|
43
|
+
.join('; ');
|
|
44
|
+
super(`persisted record failed schema validation: ${summary}`);
|
|
45
|
+
this.name = 'RecordValidationError';
|
|
46
|
+
this.code = 'RECORD_SCHEMA_INVALID';
|
|
47
|
+
this.errors = errors;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Validate a persisted record against dogfood-record.schema.json.
|
|
53
|
+
* Throws RecordValidationError on failure; returns the record on success
|
|
54
|
+
* so callers can chain (`writeFile(validateRecord(r))`).
|
|
55
|
+
*
|
|
56
|
+
* @param {object} record
|
|
57
|
+
* @returns {object} the same record reference, unchanged
|
|
58
|
+
* @throws {RecordValidationError}
|
|
59
|
+
*/
|
|
60
|
+
export function validateRecord(record) {
|
|
61
|
+
const result = validatePayload('record', record);
|
|
62
|
+
if (result.valid) return record;
|
|
63
|
+
|
|
64
|
+
// Project canonical ValidationError → ingest's historical error shape:
|
|
65
|
+
// pre-H3 entries had `{ path, keyword, message, params }`. Canonical
|
|
66
|
+
// ships the same fields (keyword added in H3 hop 0). Re-construct
|
|
67
|
+
// explicitly so any future change to the canonical shape (extra
|
|
68
|
+
// fields, renames) trips an explicit migration here rather than
|
|
69
|
+
// silently widening RecordValidationError.errors[].
|
|
70
|
+
const errors = result.errors.map(err => ({
|
|
71
|
+
path: err.path,
|
|
72
|
+
keyword: err.keyword,
|
|
73
|
+
message: err.message,
|
|
74
|
+
params: err.params,
|
|
75
|
+
}));
|
|
76
|
+
throw new RecordValidationError(errors);
|
|
77
|
+
}
|