@maadb/core 0.16.0 → 0.18.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 +2 -0
- package/dist/client/complete-delivery.d.ts +5 -0
- package/dist/client/complete-delivery.d.ts.map +1 -0
- package/dist/client/complete-delivery.js +38 -0
- package/dist/client/complete-delivery.js.map +1 -0
- package/dist/engine/compact-json.d.ts +12 -0
- package/dist/engine/compact-json.d.ts.map +1 -0
- package/dist/engine/compact-json.js +87 -0
- package/dist/engine/compact-json.js.map +1 -0
- package/dist/engine/context.d.ts +1 -0
- package/dist/engine/context.d.ts.map +1 -1
- package/dist/engine/context.js.map +1 -1
- package/dist/engine/contract-preparation-cache.d.ts +9 -0
- package/dist/engine/contract-preparation-cache.d.ts.map +1 -0
- package/dist/engine/contract-preparation-cache.js +31 -0
- package/dist/engine/contract-preparation-cache.js.map +1 -0
- package/dist/engine/create-contract.d.ts +11 -0
- package/dist/engine/create-contract.d.ts.map +1 -0
- package/dist/engine/create-contract.js +141 -0
- package/dist/engine/create-contract.js.map +1 -0
- package/dist/engine/delivery-json.d.ts +7 -0
- package/dist/engine/delivery-json.d.ts.map +1 -0
- package/dist/engine/delivery-json.js +6 -0
- package/dist/engine/delivery-json.js.map +1 -0
- package/dist/engine/document-receipt.d.ts +11 -2
- package/dist/engine/document-receipt.d.ts.map +1 -1
- package/dist/engine/document-receipt.js +19 -5
- package/dist/engine/document-receipt.js.map +1 -1
- package/dist/engine/guarded-create-types.d.ts +40 -0
- package/dist/engine/guarded-create-types.d.ts.map +1 -0
- package/dist/engine/guarded-create-types.js +2 -0
- package/dist/engine/guarded-create-types.js.map +1 -0
- package/dist/engine/guarded-create.d.ts +28 -0
- package/dist/engine/guarded-create.d.ts.map +1 -0
- package/dist/engine/guarded-create.js +100 -0
- package/dist/engine/guarded-create.js.map +1 -0
- package/dist/engine/index.d.ts +9 -0
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +65 -0
- package/dist/engine/index.js.map +1 -1
- package/dist/engine/writes.d.ts +13 -1
- package/dist/engine/writes.d.ts.map +1 -1
- package/dist/engine/writes.js +20 -11
- package/dist/engine/writes.js.map +1 -1
- package/dist/engine.d.ts +4 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +2 -0
- package/dist/engine.js.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/instance/pool.d.ts.map +1 -1
- package/dist/instance/pool.js +4 -1
- package/dist/instance/pool.js.map +1 -1
- package/dist/mcp/complete-delivery.d.ts +38 -0
- package/dist/mcp/complete-delivery.d.ts.map +1 -0
- package/dist/mcp/complete-delivery.js +126 -0
- package/dist/mcp/complete-delivery.js.map +1 -0
- package/dist/mcp/kinds.d.ts.map +1 -1
- package/dist/mcp/kinds.js +2 -1
- package/dist/mcp/kinds.js.map +1 -1
- package/dist/mcp/response.d.ts +4 -14
- package/dist/mcp/response.d.ts.map +1 -1
- package/dist/mcp/response.js +11 -16
- package/dist/mcp/response.js.map +1 -1
- package/dist/mcp/roles.js +2 -2
- package/dist/mcp/roles.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +3 -0
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/document-receipt.d.ts +5 -0
- package/dist/mcp/tools/document-receipt.d.ts.map +1 -1
- package/dist/mcp/tools/document-receipt.js +11 -2
- package/dist/mcp/tools/document-receipt.js.map +1 -1
- package/dist/mcp/tools/guarded-create.d.ts +33 -0
- package/dist/mcp/tools/guarded-create.d.ts.map +1 -0
- package/dist/mcp/tools/guarded-create.js +73 -0
- package/dist/mcp/tools/guarded-create.js.map +1 -0
- package/dist/mcp/with-session.d.ts +2 -0
- package/dist/mcp/with-session.d.ts.map +1 -1
- package/dist/mcp/with-session.js +55 -20
- package/dist/mcp/with-session.js.map +1 -1
- package/dist/schema/loader.d.ts +12 -1
- package/dist/schema/loader.d.ts.map +1 -1
- package/dist/schema/loader.js +48 -15
- package/dist/schema/loader.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,6 +25,8 @@ MAADb stores records as markdown files with YAML frontmatter for structured fiel
|
|
|
25
25
|
|
|
26
26
|
MAADb works as a context engine for AI agents — a place to hold the information they need to keep working, when that context still needs structure. Records are typed, relationships are queryable through MCP, and the data stays as readable markdown on disk. Common shapes: agent memory, project state, ongoing case files. For high-throughput transactional data or pure semantic retrieval at scale, purpose-built tools serve better.
|
|
27
27
|
|
|
28
|
+
Guarded-write consumers can use [compact complete contracts and receipt pages](docs/complete-delivery.md), with separate query and contract response budgets.
|
|
29
|
+
|
|
28
30
|
## Quick example
|
|
29
31
|
|
|
30
32
|
A record lives as markdown with a schema-validated YAML header:
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { DeliveryPage } from '../mcp/complete-delivery.js';
|
|
2
|
+
import type { JsonValue } from '../engine/document-receipt-types.js';
|
|
3
|
+
/** Assemble only complete, ordered, unexpired observations. Never accepts a summary. */
|
|
4
|
+
export declare function assembleCompleteDelivery(pages: readonly DeliveryPage[], now?: number): JsonValue;
|
|
5
|
+
//# sourceMappingURL=complete-delivery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"complete-delivery.d.ts","sourceRoot":"","sources":["../../src/client/complete-delivery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAIhE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AAErE,wFAAwF;AACxF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,EAAE,GAAG,SAAa,GAAG,SAAS,CA2BpG"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { rawSha256 } from '../engine/document-receipt.js';
|
|
2
|
+
import { canonicalDeliveryJson } from '../engine/delivery-json.js';
|
|
3
|
+
import { expandCompactJson } from '../engine/compact-json.js';
|
|
4
|
+
/** Assemble only complete, ordered, unexpired observations. Never accepts a summary. */
|
|
5
|
+
export function assembleCompleteDelivery(pages, now = Date.now()) {
|
|
6
|
+
if (!Array.isArray(pages))
|
|
7
|
+
throw new Error('Invalid delivery pages');
|
|
8
|
+
const first = pages[0];
|
|
9
|
+
if (!first || pages.length > 1024 || first.totalBytes > 1024 * 1024 || first.totalBytes <= 0
|
|
10
|
+
|| first.totalCharacters > 1024 * 1024 || first.totalCharacters <= 0)
|
|
11
|
+
throw new Error('Invalid delivery bounds');
|
|
12
|
+
let offset = 0;
|
|
13
|
+
const chunks = [];
|
|
14
|
+
for (const [index, page] of pages.entries()) {
|
|
15
|
+
if (![page.totalBytes, page.totalCharacters, page.offset, page.endOffset, page.expiresAt].every(Number.isSafeInteger)
|
|
16
|
+
|| typeof page.chunk !== 'string' || !/^[0-9a-f]{64}$/.test(page.digest) || !/^[0-9a-f]{64}$/.test(page.packedDigest)
|
|
17
|
+
|| page.delivery !== 'complete-json-v1' || page.encoding !== 'shape-json-v1'
|
|
18
|
+
|| page.snapshotId !== first.snapshotId || page.digest !== first.digest || page.packedDigest !== first.packedDigest
|
|
19
|
+
|| page.totalBytes !== first.totalBytes || page.totalCharacters !== first.totalCharacters
|
|
20
|
+
|| page.expiresAt !== first.expiresAt || page.expiresAt <= now || page.offset !== offset
|
|
21
|
+
|| page.endOffset !== page.offset + page.chunk.length || page.endOffset > first.totalCharacters
|
|
22
|
+
|| page.endOffset <= page.offset || page.complete !== (page.endOffset === first.totalCharacters)
|
|
23
|
+
|| page.complete !== (index === pages.length - 1)
|
|
24
|
+
|| page.nextCursor !== (page.complete ? null : `${page.snapshotId}:${page.endOffset}`))
|
|
25
|
+
throw new Error('Incomplete or mixed delivery');
|
|
26
|
+
chunks.push(page.chunk);
|
|
27
|
+
offset = page.endOffset;
|
|
28
|
+
}
|
|
29
|
+
const packed = chunks.join('');
|
|
30
|
+
if (offset !== first.totalCharacters || Buffer.byteLength(packed) !== first.totalBytes
|
|
31
|
+
|| rawSha256(Buffer.from(packed)) !== first.packedDigest)
|
|
32
|
+
throw new Error('Delivery integrity mismatch');
|
|
33
|
+
const data = expandCompactJson(JSON.parse(packed));
|
|
34
|
+
if (rawSha256(Buffer.from(canonicalDeliveryJson(data))) !== first.digest)
|
|
35
|
+
throw new Error('Complete digest mismatch');
|
|
36
|
+
return data;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=complete-delivery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"complete-delivery.js","sourceRoot":"","sources":["../../src/client/complete-delivery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { JsonValue } from './document-receipt-types.js';
|
|
2
|
+
export interface CompactJson {
|
|
3
|
+
encoding: 'shape-json-v1';
|
|
4
|
+
/** Each shape lists value keys, then keys whose value is exactly null. */
|
|
5
|
+
shapes: [string[], string[]][];
|
|
6
|
+
value: JsonValue;
|
|
7
|
+
}
|
|
8
|
+
/** Lossless JSON encoding. Arrays use [0,...items], objects [1,shape,...values]. */
|
|
9
|
+
export declare function compactJson(input: unknown): CompactJson;
|
|
10
|
+
/** Reference decoder: bounded input, exact arity, no prototype assignment. */
|
|
11
|
+
export declare function expandCompactJson(input: CompactJson): JsonValue;
|
|
12
|
+
//# sourceMappingURL=compact-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compact-json.d.ts","sourceRoot":"","sources":["../../src/engine/compact-json.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE7D,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,eAAe,CAAC;IAC1B,0EAA0E;IAC1E,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IAC/B,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,oFAAoF;AACpF,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAgBvD;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,CAkD/D"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { canonicalJson } from './document-receipt.js';
|
|
2
|
+
import { canonicalDeliveryJson, DELIVERY_JSON_LIMITS } from './delivery-json.js';
|
|
3
|
+
/** Lossless JSON encoding. Arrays use [0,...items], objects [1,shape,...values]. */
|
|
4
|
+
export function compactJson(input) {
|
|
5
|
+
const source = JSON.parse(canonicalDeliveryJson(input));
|
|
6
|
+
const shapes = [];
|
|
7
|
+
const indices = new Map();
|
|
8
|
+
const encode = (value) => {
|
|
9
|
+
if (value === null || typeof value !== 'object')
|
|
10
|
+
return value;
|
|
11
|
+
if (Array.isArray(value))
|
|
12
|
+
return [0, ...value.map(encode)];
|
|
13
|
+
const keys = Object.keys(value).sort();
|
|
14
|
+
const shape = [keys.filter(k => value[k] !== null), keys.filter(k => value[k] === null)];
|
|
15
|
+
const signature = JSON.stringify(shape);
|
|
16
|
+
let index = indices.get(signature);
|
|
17
|
+
if (index === undefined) {
|
|
18
|
+
index = shapes.length;
|
|
19
|
+
shapes.push(shape);
|
|
20
|
+
indices.set(signature, index);
|
|
21
|
+
}
|
|
22
|
+
return [1, index, ...shape[0].map(k => encode(value[k]))];
|
|
23
|
+
};
|
|
24
|
+
const value = encode(source);
|
|
25
|
+
return { encoding: 'shape-json-v1', shapes, value };
|
|
26
|
+
}
|
|
27
|
+
/** Reference decoder: bounded input, exact arity, no prototype assignment. */
|
|
28
|
+
export function expandCompactJson(input) {
|
|
29
|
+
// Tags add nodes that are absent from the expanded value. Bound shapes
|
|
30
|
+
// independently; the decoder and final canonicalization bound expanded data.
|
|
31
|
+
canonicalJson({ encoding: input.encoding, shapes: input.shapes }, {
|
|
32
|
+
nodes: DELIVERY_JSON_LIMITS.nodes * 4, depth: 5, scalarBytes: DELIVERY_JSON_LIMITS.scalarBytes,
|
|
33
|
+
});
|
|
34
|
+
if (input.encoding !== 'shape-json-v1' || !Array.isArray(input.shapes))
|
|
35
|
+
throw new Error('Invalid compact encoding');
|
|
36
|
+
for (const shape of input.shapes) {
|
|
37
|
+
if (!Array.isArray(shape) || shape.length !== 2 || !shape.every(keys => Array.isArray(keys) && keys.every(k => typeof k === 'string'))
|
|
38
|
+
|| new Set(shape.flat()).size !== shape.flat().length)
|
|
39
|
+
throw new Error('Invalid compact shape');
|
|
40
|
+
}
|
|
41
|
+
let nodes = 0;
|
|
42
|
+
let bytes = 0;
|
|
43
|
+
const charge = (count, size, depth) => {
|
|
44
|
+
nodes += count;
|
|
45
|
+
bytes += size;
|
|
46
|
+
if (nodes > DELIVERY_JSON_LIMITS.nodes || depth > DELIVERY_JSON_LIMITS.depth || bytes > DELIVERY_JSON_LIMITS.scalarBytes)
|
|
47
|
+
throw new Error('Compact structure exceeds bounds');
|
|
48
|
+
};
|
|
49
|
+
// Charge repeated property names and omitted nulls before allocating each
|
|
50
|
+
// object. A small shape table must not amplify into unbounded decoded data.
|
|
51
|
+
const costs = input.shapes.map(([keys, nullKeys]) => ({
|
|
52
|
+
nodes: keys.length + nullKeys.length * 2,
|
|
53
|
+
bytes: [...keys, ...nullKeys].reduce((sum, key) => sum + Buffer.byteLength(JSON.stringify(key)), nullKeys.length * 4),
|
|
54
|
+
}));
|
|
55
|
+
const decode = (value, depth) => {
|
|
56
|
+
charge(1, 0, depth);
|
|
57
|
+
if (value === null || typeof value !== 'object') {
|
|
58
|
+
if (!(value === null || typeof value === 'string' || typeof value === 'boolean' || (typeof value === 'number' && Number.isFinite(value))))
|
|
59
|
+
throw new Error('Invalid compact primitive');
|
|
60
|
+
charge(0, Buffer.byteLength(JSON.stringify(value)), depth);
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
if (!Array.isArray(value))
|
|
64
|
+
throw new Error('Invalid compact node');
|
|
65
|
+
if (value[0] === 0) {
|
|
66
|
+
const result = [];
|
|
67
|
+
for (let i = 1; i < value.length; i++)
|
|
68
|
+
result.push(decode(value[i], depth + 1));
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
const index = value[1];
|
|
72
|
+
const shape = typeof index === 'number' && Number.isInteger(index) ? input.shapes[index] : undefined;
|
|
73
|
+
if (value[0] !== 1 || !shape || value.length !== shape[0].length + 2)
|
|
74
|
+
throw new Error('Invalid compact object');
|
|
75
|
+
const cost = costs[index];
|
|
76
|
+
charge(cost.nodes, cost.bytes, cost.nodes ? depth + 1 : depth);
|
|
77
|
+
const result = Object.create(null);
|
|
78
|
+
for (const key of shape[1])
|
|
79
|
+
result[key] = null;
|
|
80
|
+
shape[0].forEach((key, i) => { result[key] = decode(value[i + 2], depth + 1); });
|
|
81
|
+
return result;
|
|
82
|
+
};
|
|
83
|
+
const value = decode(input.value, 0);
|
|
84
|
+
canonicalDeliveryJson(value);
|
|
85
|
+
return value;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=compact-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compact-json.js","sourceRoot":"","sources":["../../src/engine/compact-json.ts"],"names":[],"mappings":"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"}
|
package/dist/engine/context.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export interface CommitFailureTracker {
|
|
|
21
21
|
}
|
|
22
22
|
export declare function newCommitFailureTracker(): CommitFailureTracker;
|
|
23
23
|
export interface EngineContext {
|
|
24
|
+
contractPreparationCache?: import('./contract-preparation-cache.js').ContractPreparationCache;
|
|
24
25
|
projectRoot: string;
|
|
25
26
|
registry: Registry;
|
|
26
27
|
schemaStore: SchemaStore;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/engine/context.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAI1D;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAAC;IAClD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,wBAAgB,uBAAuB,IAAI,oBAAoB,CAS9D;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;IACnB,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,oBAAoB,CAAC;IACrC,2EAA2E;IAC3E,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC;;;;OAIG;IACH,eAAe,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAkC/F"}
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/engine/context.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAI1D;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAAC;IAClD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,wBAAgB,uBAAuB,IAAI,oBAAoB,CAS9D;AAED,MAAM,WAAW,aAAa;IAC5B,wBAAwB,CAAC,EAAE,OAAO,iCAAiC,EAAE,wBAAwB,CAAC;IAC9F,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;IACnB,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,oBAAoB,CAAC;IACrC,2EAA2E;IAC3E,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC;;;;OAIG;IACH,eAAe,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAkC/F"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/engine/context.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,6DAA6D;AAC7D,+EAA+E;AAS/E,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAiBjD,MAAM,UAAU,uBAAuB;IACrC,OAAO;QACL,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,IAAI;QACjB,UAAU,EAAE,IAAI;QAChB,SAAS,EAAE,IAAI;KAChB,CAAC;AACJ,CAAC;
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/engine/context.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,6DAA6D;AAC7D,+EAA+E;AAS/E,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAiBjD,MAAM,UAAU,uBAAuB;IACrC,OAAO;QACL,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,IAAI;QACjB,UAAU,EAAE,IAAI;QAChB,SAAS,EAAE,IAAI;KAChB,CAAC;AACJ,CAAC;AAkCD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAkB,EAAE,IAAmB;IACrE,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAC7D,oEAAoE;IACpE,4EAA4E;IAC5E,4DAA4D;IAC5D,MAAM,QAAQ,GAAkB,GAAG,CAAC,cAAc,KAAK,SAAS;QAC9D,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,cAAc,EAAE;QAC3C,CAAC,CAAC,IAAI,CAAC;IACT,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO;QACzB,CAAC,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;QACpC,CAAC,CAAC,MAAM,GAAG,CAAC,QAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAChD,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9F,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAChC,GAAG,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;QAC3B,GAAG,CAAC,cAAc,CAAC,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrD,GAAG,CAAC,cAAc,CAAC,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;QAC3C,GAAG,CAAC,cAAc,CAAC,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;QACjD,GAAG,CAAC,cAAc,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;QAC5C,GAAG,CAAC,cAAc,CAAC,SAAS,GAAG,IAAI,CAAC,KAAe,CAAC;QACpD,gBAAgB,CAAC;YACf,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM,EAAE,IAAI,CAAC,KAAe;YAC5B,QAAQ,EAAE,IAAI,CAAC,OAAiB;YAChC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;SAC9B,CAAC,CAAC;QACH,wEAAwE;QACxE,yDAAyD;QACzD,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,yBAAyB,IAAI,CAAC,KAAe,KAAK,OAAO,CAAC,IAAI,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5H,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SchemaStore } from '../types.js';
|
|
2
|
+
/** One bounded, private preparation per engine; never stores authority or history. */
|
|
3
|
+
export declare class ContractPreparationCache {
|
|
4
|
+
private entry;
|
|
5
|
+
clear(): void;
|
|
6
|
+
get(key: string, cachedFiles: SchemaStore['cachedFiles']): SchemaStore | undefined;
|
|
7
|
+
set(key: string, store: SchemaStore): void;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=contract-preparation-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-preparation-cache.d.ts","sourceRoot":"","sources":["../../src/engine/contract-preparation-cache.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,sFAAsF;AACtF,qBAAa,wBAAwB;IACnC,OAAO,CAAC,KAAK,CAA+D;IAE5E,KAAK,IAAI,IAAI;IAEb,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,CAAC,aAAa,CAAC,GAAG,WAAW,GAAG,SAAS;IAkBlF,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI;CAG3C"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { statSync } from 'node:fs';
|
|
2
|
+
/** One bounded, private preparation per engine; never stores authority or history. */
|
|
3
|
+
export class ContractPreparationCache {
|
|
4
|
+
entry;
|
|
5
|
+
clear() { this.entry = undefined; }
|
|
6
|
+
get(key, cachedFiles) {
|
|
7
|
+
if (this.entry?.key !== key)
|
|
8
|
+
return undefined;
|
|
9
|
+
// Neither callers nor the activated legacy store can mutate cached definitions.
|
|
10
|
+
const schemas = structuredClone(this.entry.schemas);
|
|
11
|
+
const files = new Map(cachedFiles);
|
|
12
|
+
return {
|
|
13
|
+
schemas, cachedFiles: files,
|
|
14
|
+
getSchema: ref => schemas.get(ref),
|
|
15
|
+
getSchemaForType: type => [...schemas.values()].find(schema => schema.type === type),
|
|
16
|
+
isStale: () => [...files].some(([file, expected]) => {
|
|
17
|
+
try {
|
|
18
|
+
const actual = statSync(file);
|
|
19
|
+
return actual.mtimeMs !== expected.mtimeMs || actual.size !== expected.size;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
}),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
set(key, store) {
|
|
28
|
+
this.entry = { key, schemas: structuredClone(store.schemas) };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=contract-preparation-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-preparation-cache.js","sourceRoot":"","sources":["../../src/engine/contract-preparation-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGnC,sFAAsF;AACtF,MAAM,OAAO,wBAAwB;IAC3B,KAAK,CAA+D;IAE5E,KAAK,KAAW,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC;IAEzC,GAAG,CAAC,GAAW,EAAE,WAAuC;QACtD,IAAI,IAAI,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG;YAAE,OAAO,SAAS,CAAC;QAC9C,gFAAgF;QAChF,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;QACnC,OAAO;YACL,OAAO,EAAE,WAAW,EAAE,KAAK;YAC3B,SAAS,EAAE,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;YAClC,gBAAgB,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC;YACpF,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE;gBAClD,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;oBAC9B,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,CAAC;gBAC9E,CAAC;gBAAC,MAAM,CAAC;oBAAC,OAAO,IAAI,CAAC;gBAAC,CAAC;YAC1B,CAAC,CAAC;SACH,CAAC;IACJ,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,KAAkB;QACjC,IAAI,CAAC,KAAK,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;IAChE,CAAC;CACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Registry, type SchemaStore } from '../types.js';
|
|
2
|
+
import type { CreateContract } from './guarded-create-types.js';
|
|
3
|
+
import type { ContractPreparationCache } from './contract-preparation-cache.js';
|
|
4
|
+
import type { EngineContext } from './context.js';
|
|
5
|
+
/** No registry activation, directory creation, index rebuild, or stale fallback. */
|
|
6
|
+
export declare function freshCreateContract(ctx: EngineContext, type: string, signal?: AbortSignal, cache?: ContractPreparationCache): Promise<{
|
|
7
|
+
contract: CreateContract;
|
|
8
|
+
registry: Registry;
|
|
9
|
+
schemaStore: SchemaStore;
|
|
10
|
+
}>;
|
|
11
|
+
//# sourceMappingURL=create-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-contract.d.ts","sourceRoot":"","sources":["../../src/engine/create-contract.ts"],"names":[],"mappings":"AAMA,OAAO,EAAwE,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAKpI,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AA4BlD,oFAAoF;AACpF,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,wBAAwB,GAAG,OAAO,CAAC;IAC3I,QAAQ,EAAE,cAAc,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,WAAW,EAAE,WAAW,CAAC;CACxE,CAAC,CA2FD"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { lstatSync } from 'node:fs';
|
|
3
|
+
import yaml from 'js-yaml';
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { loadSchemasFromSnapshot } from '../schema/loader.js';
|
|
7
|
+
import { buildSubtypeMap, DEFAULT_SUBTYPE_MAP, PRIMITIVES, docType, schemaRef } from '../types.js';
|
|
8
|
+
import { canonicalJson, rawSha256, readWorkingReceipt, readWorkingReceiptSnapshot } from './document-receipt.js';
|
|
9
|
+
import { isSafeProjectRelativePath, isSafeSchemaRef, isWritePathContainedIn } from './pathguard.js';
|
|
10
|
+
import { ReceiptError } from '../git/exact-blob.js';
|
|
11
|
+
const engineVersion = createRequire(import.meta.url)('../../package.json').version;
|
|
12
|
+
const typeDefinition = z.object({
|
|
13
|
+
path: z.string().min(1), id_prefix: z.string().regex(/^[a-z0-9]{2,5}$/),
|
|
14
|
+
schema: z.string().refine(isSafeSchemaRef), template: z.string().min(1).optional(),
|
|
15
|
+
}).passthrough();
|
|
16
|
+
const registryDefinition = z.object({
|
|
17
|
+
types: z.record(z.string().regex(/^[a-z][a-z0-9_]*$/), typeDefinition),
|
|
18
|
+
extraction: z.object({ subtypes: z.record(z.string(), z.enum(PRIMITIVES)).optional() }).passthrough().optional(),
|
|
19
|
+
}).passthrough();
|
|
20
|
+
function parseSource(raw) {
|
|
21
|
+
const text = raw.replace(/^\uFEFF/, '');
|
|
22
|
+
const match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(text);
|
|
23
|
+
const value = yaml.load(match ? match[1] : text, { schema: yaml.CORE_SCHEMA });
|
|
24
|
+
canonicalJson(value);
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
/** Ordered map entries retain schema field ordering, which affects serialization. */
|
|
28
|
+
function effectiveContract(registry, schemas) {
|
|
29
|
+
return JSON.parse(canonicalJson({
|
|
30
|
+
types: [...registry.types], extraction: registry.extraction, subtypeMap: registry.subtypeMap,
|
|
31
|
+
schemas: [...schemas.schemas].map(([ref, schema]) => [ref, { ...schema, fields: [...schema.fields] }]),
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
/** No registry activation, directory creation, index rebuild, or stale fallback. */
|
|
35
|
+
export async function freshCreateContract(ctx, type, signal, cache) {
|
|
36
|
+
const sources = Object.create(null);
|
|
37
|
+
const capturedBytes = new Map();
|
|
38
|
+
const cachedFiles = new Map();
|
|
39
|
+
let total = 0;
|
|
40
|
+
const read = async (relative) => {
|
|
41
|
+
if (Object.hasOwn(sources, relative))
|
|
42
|
+
return sources[relative];
|
|
43
|
+
if (Object.keys(sources).length >= 129)
|
|
44
|
+
throw new ReceiptError('SCHEMA_INVALID', 'Too many contract dependencies');
|
|
45
|
+
const captured = await readWorkingReceiptSnapshot(ctx.projectRoot, relative, signal);
|
|
46
|
+
const { bytes } = captured;
|
|
47
|
+
total += bytes.length;
|
|
48
|
+
if (total > 256 * 1024)
|
|
49
|
+
throw new ReceiptError('RESPONSE_TOO_LARGE', 'Schema dependency snapshot exceeds 256 KiB');
|
|
50
|
+
const text = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
|
51
|
+
sources[relative] = text;
|
|
52
|
+
capturedBytes.set(relative, bytes);
|
|
53
|
+
cachedFiles.set(path.join(ctx.projectRoot, relative), { mtimeMs: captured.mtimeMs, size: captured.size });
|
|
54
|
+
return text;
|
|
55
|
+
};
|
|
56
|
+
const parsed = registryDefinition.parse(parseSource(await read('_registry/object_types.yaml')));
|
|
57
|
+
const entries = Object.entries(parsed.types);
|
|
58
|
+
if (entries.length === 0 || entries.length > 64)
|
|
59
|
+
throw new ReceiptError('SCHEMA_INVALID', 'Contract requires 1 to 64 registered types');
|
|
60
|
+
const registry = { types: new Map(), extraction: { subtypes: parsed.extraction?.subtypes ?? {} },
|
|
61
|
+
subtypeMap: buildSubtypeMap(DEFAULT_SUBTYPE_MAP, parsed.extraction?.subtypes) };
|
|
62
|
+
const prefixes = new Set();
|
|
63
|
+
for (const [name, def] of entries) {
|
|
64
|
+
if (prefixes.has(def.id_prefix))
|
|
65
|
+
throw new ReceiptError('REGISTRY_INVALID', 'Duplicate registry prefix');
|
|
66
|
+
prefixes.add(def.id_prefix);
|
|
67
|
+
for (const relative of [def.path, ...(def.template ? [def.template] : [])]) {
|
|
68
|
+
if (!isSafeProjectRelativePath(relative) || !isWritePathContainedIn(path.join(ctx.projectRoot, relative), ctx.projectRoot)) {
|
|
69
|
+
throw new ReceiptError('PATH_OUTSIDE_PROJECT', 'Contract dependency escapes project');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
let directory = ctx.projectRoot;
|
|
73
|
+
for (const component of def.path.split('/').filter(Boolean)) {
|
|
74
|
+
directory = path.join(directory, component);
|
|
75
|
+
try {
|
|
76
|
+
const entry = lstatSync(directory);
|
|
77
|
+
if (entry.isSymbolicLink() || !entry.isDirectory())
|
|
78
|
+
throw new ReceiptError('PATH_OUTSIDE_PROJECT', 'Create directory must be a real directory');
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
if (error.code !== 'ENOENT')
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
registry.types.set(docType(name), { name: docType(name), path: def.path, idPrefix: def.id_prefix,
|
|
86
|
+
schemaRef: schemaRef(def.schema), template: def.template ?? null });
|
|
87
|
+
await read(`_schema/${def.schema}.yaml`);
|
|
88
|
+
if (def.template)
|
|
89
|
+
await read(def.template);
|
|
90
|
+
}
|
|
91
|
+
if (!registry.types.has(docType(type)))
|
|
92
|
+
throw new ReceiptError('UNKNOWN_TYPE', 'Unknown contract document type');
|
|
93
|
+
// Validate exactly the bounded captured sources, with no disk-reader fallback.
|
|
94
|
+
// Both effective identity and document preparation use this validated store.
|
|
95
|
+
// Decode like the legacy disk reader (including BOMs); capture already checked
|
|
96
|
+
// UTF-8 validity. Keep the existing source projection and parser behavior.
|
|
97
|
+
const schemaSources = new Map([...registry.types.values()].map(def => [def.schemaRef, capturedBytes.get(`_schema/${def.schemaRef}.yaml`).toString('utf8')]));
|
|
98
|
+
// Identity includes every captured dependency, not mtime/size or a type-only key.
|
|
99
|
+
const preparationKey = rawSha256(Buffer.from(canonicalJson([...capturedBytes].map(([file, bytes]) => [file, rawSha256(bytes)]))));
|
|
100
|
+
let prepared = cache?.get(preparationKey, cachedFiles);
|
|
101
|
+
if (!prepared) {
|
|
102
|
+
cache?.clear();
|
|
103
|
+
for (const [name, def] of entries) {
|
|
104
|
+
const schema = parseSource(sources[`_schema/${def.schema}.yaml`]);
|
|
105
|
+
// Refuse malformed top-level shapes that the legacy loader tolerates.
|
|
106
|
+
z.object({ type: z.literal(name), version: z.number().int().positive().optional(),
|
|
107
|
+
required: z.array(z.string()).optional(), fields: z.record(z.string(), z.object({ type: z.string() }).passthrough()),
|
|
108
|
+
template: z.object({ headings: z.array(z.object({ level: z.number().int().min(1).max(6),
|
|
109
|
+
text: z.string(), id: z.string().nullable().optional() }).passthrough()) }).passthrough().optional(),
|
|
110
|
+
}).passthrough().parse(schema);
|
|
111
|
+
}
|
|
112
|
+
const loaded = await loadSchemasFromSnapshot(registry, schemaSources, { signal, cachedFiles });
|
|
113
|
+
if (signal?.aborted)
|
|
114
|
+
throw new ReceiptError('REQUEST_TIMEOUT', 'Schema snapshot validation cancelled');
|
|
115
|
+
if (!loaded.ok)
|
|
116
|
+
throw new ReceiptError('SCHEMA_INVALID', 'Fresh schema validation failed');
|
|
117
|
+
prepared = loaded.value;
|
|
118
|
+
}
|
|
119
|
+
if (signal?.aborted)
|
|
120
|
+
throw new ReceiptError('REQUEST_TIMEOUT', 'Schema snapshot validation cancelled');
|
|
121
|
+
for (const [relative, expected] of Object.entries(sources)) {
|
|
122
|
+
const actual = await readWorkingReceipt(ctx.projectRoot, relative, signal);
|
|
123
|
+
if (!actual.equals(Buffer.from(expected)))
|
|
124
|
+
throw new ReceiptError('SCHEMA_CONTRACT_CHANGED', 'Schema changed during observation');
|
|
125
|
+
}
|
|
126
|
+
const schemaContract = {
|
|
127
|
+
projection: 'create-schema-v1', engineVersion,
|
|
128
|
+
contentProjection: 'document-content-v1',
|
|
129
|
+
sources, effective: effectiveContract(registry, prepared),
|
|
130
|
+
};
|
|
131
|
+
const canonical = canonicalJson(schemaContract);
|
|
132
|
+
if (Buffer.byteLength(canonical) > 512 * 1024)
|
|
133
|
+
throw new ReceiptError('RESPONSE_TOO_LARGE', 'Complete schema contract exceeds bound');
|
|
134
|
+
cache?.set(preparationKey, prepared);
|
|
135
|
+
return { registry, schemaStore: prepared, contract: {
|
|
136
|
+
contract: 'create-contract-v1', docType: type, schemaDigest: rawSha256(Buffer.from(canonical)),
|
|
137
|
+
schemaProjection: 'create-schema-v1', contentProjection: 'document-content-v1', schemaContract,
|
|
138
|
+
effectiveHistoryMode: ctx.history?.config.effectiveMode ?? 'feed',
|
|
139
|
+
} };
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=create-contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-contract.js","sourceRoot":"","sources":["../../src/engine/create-contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delivery-json.d.ts","sourceRoot":"","sources":["../../src/engine/delivery-json.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,oBAAoB;;;;EAAqF,CAAC;AACvH,eAAO,MAAM,qBAAqB,GAAI,OAAO,OAAO,KAAG,MAAoD,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { canonicalJson } from './document-receipt.js';
|
|
2
|
+
// Delivery contains an already-validated v1 value plus receipt/contract metadata
|
|
3
|
+
// and raw content copies. These allowances do not change v1 admission limits.
|
|
4
|
+
export const DELIVERY_JSON_LIMITS = Object.freeze({ nodes: 65536 + 256, depth: 64 + 4, scalarBytes: 2 * 1024 * 1024 });
|
|
5
|
+
export const canonicalDeliveryJson = (value) => canonicalJson(value, DELIVERY_JSON_LIMITS);
|
|
6
|
+
//# sourceMappingURL=delivery-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delivery-json.js","sourceRoot":"","sources":["../../src/engine/delivery-json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,iFAAiF;AACjF,8EAA8E;AAC9E,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;AACvH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,KAAc,EAAU,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC"}
|
|
@@ -3,7 +3,11 @@ import type { EngineContext } from './context.js';
|
|
|
3
3
|
import type { DocumentReceipt, DocumentReceiptRequest, JsonValue } from './document-receipt-types.js';
|
|
4
4
|
export declare const rawSha256: (bytes: Buffer) => string;
|
|
5
5
|
/** Explicit serialization preserves UTF-16 key ordering even for integer-like keys. */
|
|
6
|
-
export declare function canonicalJson(value: unknown
|
|
6
|
+
export declare function canonicalJson(value: unknown, limits?: {
|
|
7
|
+
nodes: number;
|
|
8
|
+
depth: number;
|
|
9
|
+
scalarBytes: number;
|
|
10
|
+
}): string;
|
|
7
11
|
export declare function contentDigest(id: string, type: string, frontmatter: Record<string, JsonValue>, body: string): string;
|
|
8
12
|
export declare function parseReceiptContent(bytes: Buffer, id: string, type: string, schema: string): {
|
|
9
13
|
rawMarkdown: string;
|
|
@@ -11,7 +15,12 @@ export declare function parseReceiptContent(bytes: Buffer, id: string, type: str
|
|
|
11
15
|
body: string;
|
|
12
16
|
contentDigest: string;
|
|
13
17
|
};
|
|
14
|
-
/** One bounded handle read; compare both handle and pathname identity around it. */
|
|
15
18
|
export declare function readWorkingReceipt(root: string, relative: string, signal?: AbortSignal): Promise<Buffer>;
|
|
19
|
+
/** One bounded handle read; compare both handle and pathname identity around it. */
|
|
20
|
+
export declare function readWorkingReceiptSnapshot(root: string, relative: string, signal?: AbortSignal): Promise<{
|
|
21
|
+
bytes: Buffer;
|
|
22
|
+
mtimeMs: number;
|
|
23
|
+
size: number;
|
|
24
|
+
}>;
|
|
16
25
|
export declare function documentReceipt(ctx: EngineContext, request: DocumentReceiptRequest, project: string, signal?: AbortSignal): Promise<Result<DocumentReceipt>>;
|
|
17
26
|
//# sourceMappingURL=document-receipt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document-receipt.d.ts","sourceRoot":"","sources":["../../src/engine/document-receipt.ts"],"names":[],"mappings":"AAMA,OAAO,EAAiB,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAI1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAItG,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,KAAG,MAA0D,CAAC;AAErG,uFAAuF;AACvF,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"document-receipt.d.ts","sourceRoot":"","sources":["../../src/engine/document-receipt.ts"],"names":[],"mappings":"AAMA,OAAO,EAAiB,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAI1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAItG,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,KAAG,MAA0D,CAAC;AAErG,uFAAuF;AACvF,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM;;;;CAAwD,GAAG,MAAM,CAuCpH;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAGpH;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;;;;;EAqB1F;AAgBD,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAE9G;AAED,oFAAoF;AACpF,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;IAC9G,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;CAC9C,CAAC,CAoCD;AAED,wBAAsB,eAAe,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,sBAAsB,EAAE,OAAO,EAAE,MAAM,EACxG,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CA2ExD"}
|
|
@@ -12,17 +12,17 @@ import { docId, docType } from '../types.js';
|
|
|
12
12
|
const version = createRequire(import.meta.url)('../../package.json').version;
|
|
13
13
|
export const rawSha256 = (bytes) => createHash('sha256').update(bytes).digest('hex');
|
|
14
14
|
/** Explicit serialization preserves UTF-16 key ordering even for integer-like keys. */
|
|
15
|
-
export function canonicalJson(value) {
|
|
15
|
+
export function canonicalJson(value, limits = { nodes: 65536, depth: 64, scalarBytes: 1024 * 1024 }) {
|
|
16
16
|
const seen = new Set();
|
|
17
17
|
let nodes = 0;
|
|
18
18
|
let bytes = 0;
|
|
19
19
|
const encode = (v, depth) => {
|
|
20
|
-
if (++nodes >
|
|
20
|
+
if (++nodes > limits.nodes || depth > limits.depth)
|
|
21
21
|
throw new ReceiptError('RECEIPT_CONTENT_INVALID', 'Content structure exceeds bounds');
|
|
22
22
|
if (v === null || typeof v === 'boolean' || typeof v === 'string' || (typeof v === 'number' && Number.isFinite(v))) {
|
|
23
23
|
const text = JSON.stringify(v);
|
|
24
24
|
bytes += Buffer.byteLength(text);
|
|
25
|
-
if (bytes >
|
|
25
|
+
if (bytes > limits.scalarBytes)
|
|
26
26
|
throw new ReceiptError('RESPONSE_TOO_LARGE', 'Canonical content exceeds bound');
|
|
27
27
|
return text;
|
|
28
28
|
}
|
|
@@ -34,6 +34,13 @@ export function canonicalJson(value) {
|
|
|
34
34
|
}
|
|
35
35
|
if (Reflect.ownKeys(v).some(key => typeof key !== 'string'))
|
|
36
36
|
throw new ReceiptError('RECEIPT_CONTENT_INVALID', 'Unsupported content key');
|
|
37
|
+
const descriptors = Object.getOwnPropertyDescriptors(v);
|
|
38
|
+
for (const [key, descriptor] of Object.entries(descriptors)) {
|
|
39
|
+
if (Array.isArray(v) && key === 'length')
|
|
40
|
+
continue;
|
|
41
|
+
if (!('value' in descriptor) || !descriptor.enumerable)
|
|
42
|
+
throw new ReceiptError('RECEIPT_CONTENT_INVALID', 'Unsupported content property');
|
|
43
|
+
}
|
|
37
44
|
seen.add(v);
|
|
38
45
|
let result;
|
|
39
46
|
if (Array.isArray(v)) {
|
|
@@ -102,8 +109,11 @@ async function checkedPath(root, relative) {
|
|
|
102
109
|
throw new ReceiptError('PATH_OUTSIDE_PROJECT', 'Receipt path escapes project');
|
|
103
110
|
return target;
|
|
104
111
|
}
|
|
105
|
-
/** One bounded handle read; compare both handle and pathname identity around it. */
|
|
106
112
|
export async function readWorkingReceipt(root, relative, signal) {
|
|
113
|
+
return (await readWorkingReceiptSnapshot(root, relative, signal)).bytes;
|
|
114
|
+
}
|
|
115
|
+
/** One bounded handle read; compare both handle and pathname identity around it. */
|
|
116
|
+
export async function readWorkingReceiptSnapshot(root, relative, signal) {
|
|
107
117
|
checkReceiptAbort(signal);
|
|
108
118
|
const target = await checkedPath(root, relative);
|
|
109
119
|
const before = await lstat(target, { bigint: true });
|
|
@@ -118,6 +128,10 @@ export async function readWorkingReceipt(root, relative, signal) {
|
|
|
118
128
|
throw new ReceiptError('RECEIPT_OBSERVATION_CHANGED', 'Working file changed before read');
|
|
119
129
|
if (opened.size > BigInt(RECEIPT_MAX_BYTES))
|
|
120
130
|
throw new ReceiptError('RESPONSE_TOO_LARGE', 'Working file exceeds bound');
|
|
131
|
+
// Cache hints come from this same handle. Bigint nanosecond identity checks
|
|
132
|
+
// below remain authoritative; retain native numeric stat precision for the
|
|
133
|
+
// existing legacy mtime/size cache comparisons.
|
|
134
|
+
const cached = await handle.stat();
|
|
121
135
|
const buffer = Buffer.alloc(Number(opened.size) + 1);
|
|
122
136
|
let length = 0;
|
|
123
137
|
while (length < buffer.length) {
|
|
@@ -140,7 +154,7 @@ export async function readWorkingReceipt(root, relative, signal) {
|
|
|
140
154
|
throw new ReceiptError('RECEIPT_OBSERVATION_CHANGED', 'Working file changed during read');
|
|
141
155
|
}
|
|
142
156
|
checkReceiptAbort(signal);
|
|
143
|
-
return buffer.subarray(0, length);
|
|
157
|
+
return { bytes: buffer.subarray(0, length), mtimeMs: cached.mtimeMs, size: cached.size };
|
|
144
158
|
}
|
|
145
159
|
finally {
|
|
146
160
|
await handle.close();
|