@batterai/host 0.1.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/CHANGELOG.md +6 -0
- package/LICENSE +21 -0
- package/README.md +23 -0
- package/dist/cache/dependency-graph.d.ts +18 -0
- package/dist/cache/dependency-graph.d.ts.map +1 -0
- package/dist/cache/dependency-graph.js +30 -0
- package/dist/cache/dependency-graph.js.map +1 -0
- package/dist/cache/render-cache.d.ts +39 -0
- package/dist/cache/render-cache.d.ts.map +1 -0
- package/dist/cache/render-cache.js +60 -0
- package/dist/cache/render-cache.js.map +1 -0
- package/dist/client/mount.d.ts +9 -0
- package/dist/client/mount.d.ts.map +1 -0
- package/dist/client/mount.js +69 -0
- package/dist/client/mount.js.map +1 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +2 -0
- package/dist/client.js.map +1 -0
- package/dist/collab/in-memory-page-draft-store.d.ts +44 -0
- package/dist/collab/in-memory-page-draft-store.d.ts.map +1 -0
- package/dist/collab/in-memory-page-draft-store.js +217 -0
- package/dist/collab/in-memory-page-draft-store.js.map +1 -0
- package/dist/collab/page-doc-page-draft-store.d.ts +41 -0
- package/dist/collab/page-doc-page-draft-store.d.ts.map +1 -0
- package/dist/collab/page-doc-page-draft-store.js +328 -0
- package/dist/collab/page-doc-page-draft-store.js.map +1 -0
- package/dist/collab/page-draft-store.d.ts +152 -0
- package/dist/collab/page-draft-store.d.ts.map +1 -0
- package/dist/collab/page-draft-store.js +61 -0
- package/dist/collab/page-draft-store.js.map +1 -0
- package/dist/content-source/conformance/cases-delegation.d.ts +3 -0
- package/dist/content-source/conformance/cases-delegation.d.ts.map +1 -0
- package/dist/content-source/conformance/cases-delegation.js +55 -0
- package/dist/content-source/conformance/cases-delegation.js.map +1 -0
- package/dist/content-source/conformance/cases-fidelity.d.ts +3 -0
- package/dist/content-source/conformance/cases-fidelity.d.ts.map +1 -0
- package/dist/content-source/conformance/cases-fidelity.js +67 -0
- package/dist/content-source/conformance/cases-fidelity.js.map +1 -0
- package/dist/content-source/conformance/cases-isolation.d.ts +3 -0
- package/dist/content-source/conformance/cases-isolation.d.ts.map +1 -0
- package/dist/content-source/conformance/cases-isolation.js +57 -0
- package/dist/content-source/conformance/cases-isolation.js.map +1 -0
- package/dist/content-source/conformance/cases-permissions.d.ts +3 -0
- package/dist/content-source/conformance/cases-permissions.d.ts.map +1 -0
- package/dist/content-source/conformance/cases-permissions.js +50 -0
- package/dist/content-source/conformance/cases-permissions.js.map +1 -0
- package/dist/content-source/conformance/cases-reads.d.ts +3 -0
- package/dist/content-source/conformance/cases-reads.d.ts.map +1 -0
- package/dist/content-source/conformance/cases-reads.js +216 -0
- package/dist/content-source/conformance/cases-reads.js.map +1 -0
- package/dist/content-source/conformance/cases-writes.d.ts +11 -0
- package/dist/content-source/conformance/cases-writes.d.ts.map +1 -0
- package/dist/content-source/conformance/cases-writes.js +73 -0
- package/dist/content-source/conformance/cases-writes.js.map +1 -0
- package/dist/content-source/conformance/session-required.d.ts +10 -0
- package/dist/content-source/conformance/session-required.d.ts.map +1 -0
- package/dist/content-source/conformance/session-required.js +11 -0
- package/dist/content-source/conformance/session-required.js.map +1 -0
- package/dist/content-source/conformance/sessionless-viewer.d.ts +12 -0
- package/dist/content-source/conformance/sessionless-viewer.d.ts.map +1 -0
- package/dist/content-source/conformance/sessionless-viewer.js +5 -0
- package/dist/content-source/conformance/sessionless-viewer.js.map +1 -0
- package/dist/content-source/conformance/target.d.ts +111 -0
- package/dist/content-source/conformance/target.d.ts.map +1 -0
- package/dist/content-source/conformance/target.js +2 -0
- package/dist/content-source/conformance/target.js.map +1 -0
- package/dist/content-source/conformance-kit.d.ts +4 -0
- package/dist/content-source/conformance-kit.d.ts.map +1 -0
- package/dist/content-source/conformance-kit.js +41 -0
- package/dist/content-source/conformance-kit.js.map +1 -0
- package/dist/content-source/content-source.d.ts +153 -0
- package/dist/content-source/content-source.d.ts.map +1 -0
- package/dist/content-source/content-source.js +12 -0
- package/dist/content-source/content-source.js.map +1 -0
- package/dist/content-source/permissions.d.ts +46 -0
- package/dist/content-source/permissions.d.ts.map +1 -0
- package/dist/content-source/permissions.js +33 -0
- package/dist/content-source/permissions.js.map +1 -0
- package/dist/content-source/viewer.d.ts +48 -0
- package/dist/content-source/viewer.d.ts.map +1 -0
- package/dist/content-source/viewer.js +24 -0
- package/dist/content-source/viewer.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/lifecycle/cms-lifecycle-store.d.ts +72 -0
- package/dist/lifecycle/cms-lifecycle-store.d.ts.map +1 -0
- package/dist/lifecycle/cms-lifecycle-store.js +150 -0
- package/dist/lifecycle/cms-lifecycle-store.js.map +1 -0
- package/dist/lifecycle/lifecycle-store.d.ts +35 -0
- package/dist/lifecycle/lifecycle-store.d.ts.map +1 -0
- package/dist/lifecycle/lifecycle-store.js +69 -0
- package/dist/lifecycle/lifecycle-store.js.map +1 -0
- package/dist/lifecycle/version-token.d.ts +30 -0
- package/dist/lifecycle/version-token.d.ts.map +1 -0
- package/dist/lifecycle/version-token.js +22 -0
- package/dist/lifecycle/version-token.js.map +1 -0
- package/dist/messages.d.ts +26 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +31 -0
- package/dist/messages.js.map +1 -0
- package/dist/render/image-usage-preview.d.ts +19 -0
- package/dist/render/image-usage-preview.d.ts.map +1 -0
- package/dist/render/image-usage-preview.js +25 -0
- package/dist/render/image-usage-preview.js.map +1 -0
- package/dist/render/image-usage.d.ts +32 -0
- package/dist/render/image-usage.d.ts.map +1 -0
- package/dist/render/image-usage.js +116 -0
- package/dist/render/image-usage.js.map +1 -0
- package/dist/render/page-renderer.d.ts +44 -0
- package/dist/render/page-renderer.d.ts.map +1 -0
- package/dist/render/page-renderer.js +115 -0
- package/dist/render/page-renderer.js.map +1 -0
- package/dist/resolver/data-loader.d.ts +49 -0
- package/dist/resolver/data-loader.d.ts.map +1 -0
- package/dist/resolver/data-loader.js +121 -0
- package/dist/resolver/data-loader.js.map +1 -0
- package/dist/resolver/resolution-service.d.ts +49 -0
- package/dist/resolver/resolution-service.d.ts.map +1 -0
- package/dist/resolver/resolution-service.js +193 -0
- package/dist/resolver/resolution-service.js.map +1 -0
- package/dist/routing/route-resolver.d.ts +73 -0
- package/dist/routing/route-resolver.d.ts.map +1 -0
- package/dist/routing/route-resolver.js +114 -0
- package/dist/routing/route-resolver.js.map +1 -0
- package/dist/scope-engine/build-stack.d.ts +49 -0
- package/dist/scope-engine/build-stack.d.ts.map +1 -0
- package/dist/scope-engine/build-stack.js +77 -0
- package/dist/scope-engine/build-stack.js.map +1 -0
- package/dist/scope-engine/repeater-query.d.ts +9 -0
- package/dist/scope-engine/repeater-query.d.ts.map +1 -0
- package/dist/scope-engine/repeater-query.js +39 -0
- package/dist/scope-engine/repeater-query.js.map +1 -0
- package/dist/seo/metadata.d.ts +30 -0
- package/dist/seo/metadata.d.ts.map +1 -0
- package/dist/seo/metadata.js +118 -0
- package/dist/seo/metadata.js.map +1 -0
- package/dist/seo/sitemap.d.ts +11 -0
- package/dist/seo/sitemap.d.ts.map +1 -0
- package/dist/seo/sitemap.js +20 -0
- package/dist/seo/sitemap.js.map +1 -0
- package/dist/write/write-path.d.ts +63 -0
- package/dist/write/write-path.d.ts.map +1 -0
- package/dist/write/write-path.js +139 -0
- package/dist/write/write-path.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conformance cases — DELEGATED AUTH leg (decision 012 phase 1): calibrated
|
|
3
|
+
* ONLY for targets whose source declares `auth.mode === "delegated"`; ambient
|
|
4
|
+
* targets (today: all three adapters) skip entirely — zero behavior change.
|
|
5
|
+
* Every ContentSource method that takes a viewer must refuse a sessionless
|
|
6
|
+
* viewer (`sessionlessViewer(target)`, which by construction carries no `session`)
|
|
7
|
+
* with a `SessionRequired` refusal BEFORE any CMS I/O. Registered LAST by the
|
|
8
|
+
* assembler, after isolation, so ambient-adapter case order is unaffected.
|
|
9
|
+
*/
|
|
10
|
+
import { expectSessionRequired } from "./session-required.js";
|
|
11
|
+
import { sessionlessViewer } from "./sessionless-viewer.js";
|
|
12
|
+
export function registerDelegationCases(target, hooks) {
|
|
13
|
+
if (target.source.capabilities.auth.mode !== "delegated") {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const { test, expect } = hooks;
|
|
17
|
+
test("delegated auth: permit() refuses a sessionless viewer before any I/O", async () => {
|
|
18
|
+
await expectSessionRequired(expect, () => target.source.permit({ contentTypeId: target.contentTypeId }, sessionlessViewer(target)));
|
|
19
|
+
});
|
|
20
|
+
test("delegated auth: listInstances refuses a sessionless viewer", async () => {
|
|
21
|
+
await expectSessionRequired(expect, () => target.source.listInstances(target.contentTypeId, { pageSize: 1 }, undefined, sessionlessViewer(target)));
|
|
22
|
+
});
|
|
23
|
+
test("delegated auth: getInstance refuses a sessionless viewer", async () => {
|
|
24
|
+
const page = await target.source.listInstances(target.contentTypeId, { pageSize: 1 }, undefined, target.editor);
|
|
25
|
+
const id = page.items[0].id;
|
|
26
|
+
await expectSessionRequired(expect, () => target.source.getInstance(target.contentTypeId, id, sessionlessViewer(target)));
|
|
27
|
+
});
|
|
28
|
+
test("delegated auth: getInstancesByIds refuses a sessionless viewer", async () => {
|
|
29
|
+
const page = await target.source.listInstances(target.contentTypeId, { pageSize: 1 }, undefined, target.editor);
|
|
30
|
+
const ids = page.items.map((i) => i.id);
|
|
31
|
+
await expectSessionRequired(expect, () => target.source.getInstancesByIds(target.contentTypeId, ids, sessionlessViewer(target)));
|
|
32
|
+
});
|
|
33
|
+
test("delegated auth: getVersion refuses a sessionless viewer", async () => {
|
|
34
|
+
const page = await target.source.listInstances(target.contentTypeId, { pageSize: 1 }, undefined, target.editor);
|
|
35
|
+
const subject = { kind: "instance", contentTypeId: target.contentTypeId, instanceId: page.items[0].id };
|
|
36
|
+
await expectSessionRequired(expect, () => target.source.getVersion(subject, sessionlessViewer(target)));
|
|
37
|
+
});
|
|
38
|
+
test("delegated auth: writeInstanceField refuses a sessionless viewer", async () => {
|
|
39
|
+
const page = await target.source.listInstances(target.contentTypeId, { pageSize: 1 }, undefined, target.editor);
|
|
40
|
+
const inst = page.items[0];
|
|
41
|
+
await expectSessionRequired(expect, () => target.source.writeInstanceField(target.contentTypeId, inst.id, target.writableField, inst.values[target.writableField], undefined, sessionlessViewer(target)));
|
|
42
|
+
});
|
|
43
|
+
test("delegated auth: createInstance refuses a sessionless viewer (when supported)", async () => {
|
|
44
|
+
if (target.source.capabilities.create.mode === "absent" || target.create === undefined)
|
|
45
|
+
return;
|
|
46
|
+
const createInstance = target.source.createInstance?.bind(target.source);
|
|
47
|
+
if (!createInstance)
|
|
48
|
+
return;
|
|
49
|
+
await expectSessionRequired(expect, () => createInstance(target.contentTypeId, target.create.initialValues, sessionlessViewer(target)));
|
|
50
|
+
});
|
|
51
|
+
test("delegated auth: describe() refuses a sessionless viewer", async () => {
|
|
52
|
+
await expectSessionRequired(expect, () => target.provider.describe(target.contentTypeId, sessionlessViewer(target)));
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=cases-delegation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cases-delegation.js","sourceRoot":"","sources":["../../../src/content-source/conformance/cases-delegation.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAGzD,MAAM,UAAU,uBAAuB,CAAC,MAAyB,EAAE,KAAuB;IACxF,IAAI,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QACzD,OAAO;IACT,CAAC;IACD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAE/B,IAAI,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;QACtF,MAAM,qBAAqB,CAAC,MAAM,EAAE,GAAG,EAAE,CACvC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,aAAa,EAAE,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,CACzF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC5E,MAAM,qBAAqB,CAAC,MAAM,EAAE,GAAG,EAAE,CACvC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,CACzG,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAChH,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC;QAC7B,MAAM,qBAAqB,CAAC,MAAM,EAAE,GAAG,EAAE,CACvC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAC/E,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAChH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,qBAAqB,CAAC,MAAM,EAAE,GAAG,EAAE,CACvC,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,aAAa,EAAE,GAAG,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,CACtF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAChH,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,UAAmB,EAAE,aAAa,EAAE,MAAM,CAAC,aAAa,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,EAAE,EAAE,CAAC;QAClH,MAAM,qBAAqB,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC1G,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QACjF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAChH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;QAC5B,MAAM,qBAAqB,CAAC,MAAM,EAAE,GAAG,EAAE,CACvC,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAC9B,MAAM,CAAC,aAAa,EACpB,IAAI,CAAC,EAAE,EACP,MAAM,CAAC,aAAa,EACpB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,EACjC,SAAS,EACT,iBAAiB,CAAC,MAAM,CAAC,CAC1B,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,8EAA8E,EAAE,KAAK,IAAI,EAAE;QAC9F,IAAI,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO;QAC/F,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACzE,IAAI,CAAC,cAAc;YAAE,OAAO;QAC5B,MAAM,qBAAqB,CAAC,MAAM,EAAE,GAAG,EAAE,CACvC,cAAc,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,MAAO,CAAC,aAAa,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAC9F,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,qBAAqB,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,aAAa,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACvH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cases-fidelity.d.ts","sourceRoot":"","sources":["../../../src/content-source/conformance/cases-fidelity.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAuBpE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CA+C9F"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conformance cases — DELEGATION-FIDELITY leg (decision 012 phase 4, the plan's
|
|
3
|
+
* delegation-fidelity requirement: "a request with user A's session sees exactly
|
|
4
|
+
* what the CMS grants A; no session ⇒ refused"). Calibrated ONLY for targets
|
|
5
|
+
* whose source declares `auth.mode === "delegated"`; ambient targets skip
|
|
6
|
+
* entirely. Complements cases-delegation.ts (the sessionless-refusal half) with:
|
|
7
|
+
* 1. a VALID session is honored (a read via `target.editor` succeeds);
|
|
8
|
+
* 2. the CMS's refusal SURFACES, never fall-open — a WELL-FORMED but INVALID
|
|
9
|
+
* token reaches the CMS, whose 401/403 must surface as the adapter's typed
|
|
10
|
+
* unavailable error (NOT SessionRequired — the request got past the pre-I/O
|
|
11
|
+
* guard — and NEVER data or all-allowed grants);
|
|
12
|
+
* 3. for `acl.document: "native"` targets, permit's grant matches the fixture.
|
|
13
|
+
* Registered after cases-delegation by the assembler.
|
|
14
|
+
*/
|
|
15
|
+
import { CANVAS_ACTIONS } from "../permissions.js";
|
|
16
|
+
import { cmsSessionFromToken, delegatedViewer } from "../viewer.js";
|
|
17
|
+
/** Assert `fn` rejects with a TYPED adapter error that reached the CMS — the
|
|
18
|
+
* error is defined, and its name is NOT `SessionRequired` (that would mean it
|
|
19
|
+
* was refused BEFORE any I/O, i.e. the request never reached the CMS). */
|
|
20
|
+
async function expectCmsRefusal(expect, fn) {
|
|
21
|
+
let threw = false;
|
|
22
|
+
let name;
|
|
23
|
+
try {
|
|
24
|
+
await fn();
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
threw = true;
|
|
28
|
+
name = e instanceof Error ? e.name : undefined;
|
|
29
|
+
}
|
|
30
|
+
// It rejected (never resolved to data / all-allowed) AND the rejection came
|
|
31
|
+
// from the CMS round-trip, not the sessionless pre-I/O guard.
|
|
32
|
+
expect(threw).toBe(true);
|
|
33
|
+
expect(name === "SessionRequired").toBe(false);
|
|
34
|
+
}
|
|
35
|
+
export function registerFidelityCases(target, hooks) {
|
|
36
|
+
if (target.source.capabilities.auth.mode !== "delegated") {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const { test, expect } = hooks;
|
|
40
|
+
test("delegation fidelity: a valid session is honored (read succeeds)", async () => {
|
|
41
|
+
const page = await target.source.listInstances(target.contentTypeId, { pageSize: 1 }, undefined, target.editor);
|
|
42
|
+
expect(Array.isArray(page.items)).toBe(true);
|
|
43
|
+
});
|
|
44
|
+
test("delegation fidelity: the CMS's refusal surfaces (invalid token ⇒ typed error, never fall-open)", async () => {
|
|
45
|
+
// A well-formed but invalid session — carries a token (so the pre-I/O guard
|
|
46
|
+
// passes), but the CMS cannot authenticate it and MUST refuse.
|
|
47
|
+
const invalid = delegatedViewer(cmsSessionFromToken("expired.or.garbage.jwt"), target.editor.locale);
|
|
48
|
+
// Reuse a real id so the failing op is a genuine access refusal, not a 404.
|
|
49
|
+
const page = await target.source.listInstances(target.contentTypeId, { pageSize: 1 }, undefined, target.editor);
|
|
50
|
+
const id = page.items[0].id;
|
|
51
|
+
await expectCmsRefusal(expect, () => target.source.listInstances(target.contentTypeId, { pageSize: 1 }, undefined, invalid));
|
|
52
|
+
await expectCmsRefusal(expect, () => target.source.getInstance(target.contentTypeId, id, invalid));
|
|
53
|
+
await expectCmsRefusal(expect, () => target.source.getInstancesByIds(target.contentTypeId, [id], invalid));
|
|
54
|
+
await expectCmsRefusal(expect, () => target.source.getVersion({ kind: "instance", contentTypeId: target.contentTypeId, instanceId: id }, invalid));
|
|
55
|
+
await expectCmsRefusal(expect, () => target.source.writeInstanceField(target.contentTypeId, id, target.writableField, page.items[0].values[target.writableField], undefined, invalid));
|
|
56
|
+
});
|
|
57
|
+
test("delegation fidelity: native ACL permit matches the CMS grant for the editor", async () => {
|
|
58
|
+
if (target.source.capabilities.acl.document !== "native" || !target.nativeAcl)
|
|
59
|
+
return;
|
|
60
|
+
const allowed = new Set(target.nativeAcl.expectAllowed);
|
|
61
|
+
const grants = await target.source.permit({ contentTypeId: target.contentTypeId }, target.editor);
|
|
62
|
+
for (const action of CANVAS_ACTIONS) {
|
|
63
|
+
expect(grants[action].allowed).toBe(allowed.has(action));
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=cases-fidelity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cases-fidelity.js","sourceRoot":"","sources":["../../../src/content-source/conformance/cases-fidelity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cases-isolation.d.ts","sourceRoot":"","sources":["../../../src/content-source/conformance/cases-isolation.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAGpE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CA+D/F"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conformance cases — ISOLATION leg (G3, extracted from conformance-kit.ts for
|
|
3
|
+
* A6): a draft edit is invisible to PUBLISHED reads and visible to DRAFT reads.
|
|
4
|
+
* Capability-gated (skips when draftPublish is unclaimed or the fixture is
|
|
5
|
+
* absent). Registered LAST by the assembler via `registerIsolationCases`, so
|
|
6
|
+
* the overall case order that adapters snapshot/depend on is preserved.
|
|
7
|
+
*/
|
|
8
|
+
import { expectSessionRequired } from "./session-required.js";
|
|
9
|
+
import { sessionlessViewer } from "./sessionless-viewer.js";
|
|
10
|
+
import { publicDeliveryViewer } from "../viewer.js";
|
|
11
|
+
export function registerIsolationCases(target, hooks) {
|
|
12
|
+
const { test, expect } = hooks;
|
|
13
|
+
test("draft/publish isolation (G3): a draft edit is invisible to PUBLISHED reads, visible to DRAFT reads", async () => {
|
|
14
|
+
// Capability-gated like `create`: an adapter that does not claim a
|
|
15
|
+
// draft/publish split (or does not wire the fixture) never reaches this
|
|
16
|
+
// assertion — skip with a trivial pass so read-only / draft-less targets
|
|
17
|
+
// stay green. `draftPublish` is declared "native" | "bridged" (both mean
|
|
18
|
+
// the adapter MUST isolate drafts from published reads); only the
|
|
19
|
+
// fixture's presence decides whether we exercise it for real here.
|
|
20
|
+
if (target.draftPublish === undefined) {
|
|
21
|
+
expect(["native", "bridged"].includes(target.source.capabilities.draftPublish.mode)).toBe(true);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const { instanceId, field, publishedValue, draftValue } = await target.draftPublish.writeDraft();
|
|
26
|
+
// Sanity: the fixture must actually change the value, else the
|
|
27
|
+
// isolation assertion below is vacuous (draft === published).
|
|
28
|
+
expect(JSON.stringify(draftValue)).not.toBe(JSON.stringify(publishedValue));
|
|
29
|
+
if (target.source.capabilities.auth.mode === "delegated") {
|
|
30
|
+
// Phase-1 calibration (decision 012): delegated adapters refuse
|
|
31
|
+
// a bare sessionless viewer. The real anonymous delivery path is an
|
|
32
|
+
// explicit publicDeliveryViewer below.
|
|
33
|
+
await expectSessionRequired(expect, () => target.source.getInstance(target.contentTypeId, instanceId, sessionlessViewer(target)));
|
|
34
|
+
await expectSessionRequired(expect, () => target.source.getInstancesByIds(target.contentTypeId, [instanceId], sessionlessViewer(target)));
|
|
35
|
+
}
|
|
36
|
+
// PUBLISHED read (public viewer): the draft MUST NOT leak. This is
|
|
37
|
+
// the isolation property the capability declares — proven, not assumed.
|
|
38
|
+
const publicViewer = publicDeliveryViewer(target.editor.locale);
|
|
39
|
+
const publicSingle = await target.source.getInstance(target.contentTypeId, instanceId, publicViewer);
|
|
40
|
+
expect(publicSingle).toBeDefined();
|
|
41
|
+
expect(JSON.stringify(publicSingle.values[field])).toBe(JSON.stringify(publishedValue));
|
|
42
|
+
const publicBatch = await target.source.getInstancesByIds(target.contentTypeId, [instanceId], publicViewer);
|
|
43
|
+
const publicFromBatch = publicBatch.find((i) => i.id === instanceId);
|
|
44
|
+
expect(publicFromBatch).toBeDefined();
|
|
45
|
+
expect(JSON.stringify(publicFromBatch.values[field])).toBe(JSON.stringify(publishedValue));
|
|
46
|
+
// DRAFT read (editor viewer): the pending edit IS visible — the draft
|
|
47
|
+
// layer is not a black hole, it just doesn't cross into published.
|
|
48
|
+
const draftSingle = await target.source.getInstance(target.contentTypeId, instanceId, target.editor);
|
|
49
|
+
expect(draftSingle).toBeDefined();
|
|
50
|
+
expect(JSON.stringify(draftSingle.values[field])).toBe(JSON.stringify(draftValue));
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
await target.cleanup();
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=cases-isolation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cases-isolation.js","sourceRoot":"","sources":["../../../src/content-source/conformance/cases-isolation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cases-permissions.d.ts","sourceRoot":"","sources":["../../../src/content-source/conformance/cases-permissions.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAEpE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAiEhG"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conformance cases — PERMISSIONS leg (locked decision 2026-07-07 §1.1/1.2):
|
|
3
|
+
* capability x permission gate every action; "hidden in permit" and "refused at
|
|
4
|
+
* the adapter" must AGREE — a grant the adapter won't honor (or a refusal permit
|
|
5
|
+
* didn't disclose) is a conformance failure, not a UI bug. Runs the SAME
|
|
6
|
+
* assertions against every adapter (vendor-neutrality proof).
|
|
7
|
+
*/
|
|
8
|
+
import { CANVAS_ACTIONS } from "../permissions.js";
|
|
9
|
+
export function registerPermissionCases(target, hooks) {
|
|
10
|
+
const { test, expect } = hooks;
|
|
11
|
+
test("permit(): every action answered; reason REQUIRED on every denial", async () => {
|
|
12
|
+
const page = await target.source.listInstances(target.contentTypeId, { pageSize: 1 }, undefined, target.editor);
|
|
13
|
+
const grants = await target.source.permit({ contentTypeId: target.contentTypeId, instanceId: page.items[0].id }, target.editor);
|
|
14
|
+
for (const action of CANVAS_ACTIONS) {
|
|
15
|
+
const g = grants[action];
|
|
16
|
+
expect(typeof g.allowed).toBe("boolean");
|
|
17
|
+
if (!g.allowed)
|
|
18
|
+
expect(typeof g.reason).toBe("string");
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
// NB: the "public viewer: mutations hidden/refused" case is GONE (decision
|
|
22
|
+
// 012 phase 2). Public-write refusal is deleted (the CMS decides what a
|
|
23
|
+
// delegated session may write); delegated adapters' sessionless refusal is
|
|
24
|
+
// proven comprehensively by the delegation leg (permit + write). There is no
|
|
25
|
+
// battery-editor kind clamp left to assert here.
|
|
26
|
+
test("editor viewer: update granted in permit AND honored by the write (agreement)", async () => {
|
|
27
|
+
const page = await target.source.listInstances(target.contentTypeId, { pageSize: 1 }, undefined, target.editor);
|
|
28
|
+
const inst = page.items[0];
|
|
29
|
+
const grants = await target.source.permit({ contentTypeId: target.contentTypeId, instanceId: inst.id }, target.editor);
|
|
30
|
+
expect(grants.update.allowed).toBe(true);
|
|
31
|
+
try {
|
|
32
|
+
const result = await target.source.writeInstanceField(target.contentTypeId, inst.id, target.writableField, inst.values[target.writableField], undefined, target.editor);
|
|
33
|
+
expect(result.version).toBeDefined();
|
|
34
|
+
}
|
|
35
|
+
finally {
|
|
36
|
+
await target.cleanup();
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
test("capability<->permission coupling: an absent capability is a denied grant", async () => {
|
|
40
|
+
const grants = await target.source.permit({ contentTypeId: target.contentTypeId }, target.editor);
|
|
41
|
+
if (target.source.capabilities.create.mode === "absent") {
|
|
42
|
+
expect(grants.create.allowed).toBe(false);
|
|
43
|
+
expect(typeof grants.create.reason).toBe("string");
|
|
44
|
+
}
|
|
45
|
+
if (target.source.capabilities.draftPublish.mode === "absent") {
|
|
46
|
+
expect(grants.publish.allowed).toBe(false);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=cases-permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cases-permissions.js","sourceRoot":"","sources":["../../../src/content-source/conformance/cases-permissions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cases-reads.d.ts","sourceRoot":"","sources":["../../../src/content-source/conformance/cases-reads.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAEpE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAuP1F"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { expectSessionRequired } from "./session-required.js";
|
|
2
|
+
import { sessionlessViewer } from "./sessionless-viewer.js";
|
|
3
|
+
export function registerReadCases(target, hooks) {
|
|
4
|
+
const { test, expect } = hooks;
|
|
5
|
+
test("capabilities are declared, structured, and tolerance-honest", () => {
|
|
6
|
+
const c = target.source.capabilities;
|
|
7
|
+
expect(["version-token", "timestamp"].includes(c.concurrency.strategy)).toBe(true);
|
|
8
|
+
// Tolerance honesty: a real token has NO race window; a timestamp bridge
|
|
9
|
+
// MUST declare a nonzero one (declared, never hidden — decision 004).
|
|
10
|
+
if (c.concurrency.strategy === "version-token") {
|
|
11
|
+
expect(c.concurrency.raceWindowMs).toBe(0);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
expect(c.concurrency.raceWindowMs).toBeGreaterThanOrEqual(1);
|
|
15
|
+
}
|
|
16
|
+
expect(["keyset", "bridged-keyset"].includes(c.pagination.mode)).toBe(true);
|
|
17
|
+
expect(c.populate.maxDepth).toBeGreaterThanOrEqual(1);
|
|
18
|
+
expect(["native", "projected"].includes(c.acl.document)).toBe(true);
|
|
19
|
+
expect(["native", "projected"].includes(c.acl.field)).toBe(true);
|
|
20
|
+
expect(["native", "bridged", "absent"].includes(c.draftPublish.mode)).toBe(true);
|
|
21
|
+
expect(["field-level", "entry-level", "none"].includes(c.localization.strategy)).toBe(true);
|
|
22
|
+
expect(Array.isArray(c.pushdown.ops)).toBe(true);
|
|
23
|
+
expect(["native", "absent"].includes(c.create.mode)).toBe(true);
|
|
24
|
+
expect(["native", "absent"].includes(c.history.mode)).toBe(true);
|
|
25
|
+
expect(["native", "bridged", "absent"].includes(c.bulkWrite.mode)).toBe(true);
|
|
26
|
+
expect(["native", "absent"].includes(c.preview.mode)).toBe(true);
|
|
27
|
+
expect(["delegated", "ambient"].includes(c.auth.mode)).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
test("absent capabilities are PROVABLY absent — affordance missing, not merely untested", async () => {
|
|
30
|
+
const c = target.source.capabilities;
|
|
31
|
+
// create: 'absent' ⇒ the optional method is OMITTED (I-5: read-only-with-
|
|
32
|
+
// reason at pre-focus, never a save-time surprise); declaring native
|
|
33
|
+
// without the method is already a writes-leg failure.
|
|
34
|
+
if (c.create.mode === "absent") {
|
|
35
|
+
expect(target.source.createInstance).toBeUndefined();
|
|
36
|
+
}
|
|
37
|
+
// absent capability ⇒ permit() discloses the denial (coupling, §2.2) — so
|
|
38
|
+
// 'absent' carries BOTH a structural and a discovery proof.
|
|
39
|
+
const grants = await target.source.permit({ contentTypeId: target.contentTypeId }, target.editor);
|
|
40
|
+
if (c.create.mode === "absent")
|
|
41
|
+
expect(grants.create.allowed).toBe(false);
|
|
42
|
+
if (c.draftPublish.mode === "absent")
|
|
43
|
+
expect(grants.publish.allowed).toBe(false);
|
|
44
|
+
});
|
|
45
|
+
test("localization: the viewer's locale selects the localized value (native, not post-filtered)", async () => {
|
|
46
|
+
const strategy = target.source.capabilities.localization.strategy;
|
|
47
|
+
if (target.localization === undefined) {
|
|
48
|
+
// Declared 'none' MUST mean no fixture — a misdeclaration fails here.
|
|
49
|
+
expect(strategy).toBe("none");
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
expect(strategy).not.toBe("none");
|
|
53
|
+
const { localizedField, locales, expected, instanceId } = target.localization;
|
|
54
|
+
for (let i = 0; i < 2; i += 1) {
|
|
55
|
+
const viewer = { ...target.editor, locale: locales[i] };
|
|
56
|
+
const inst = await target.source.getInstance(target.contentTypeId, instanceId, viewer);
|
|
57
|
+
expect(inst).toBeDefined();
|
|
58
|
+
expect(JSON.stringify(inst.values[localizedField])).toBe(JSON.stringify(expected[i]));
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
test("describe(): shape + restricted field ABSENT for EVERY viewer (unconditional projection)", async () => {
|
|
62
|
+
if (target.source.capabilities.auth.mode === "delegated") {
|
|
63
|
+
// Delegated adapters refuse sessionless viewers before any I/O (D1).
|
|
64
|
+
await expectSessionRequired(expect, () => target.provider.describe(target.contentTypeId, sessionlessViewer(target)));
|
|
65
|
+
}
|
|
66
|
+
const ed = await target.provider.describe(target.contentTypeId, target.editor);
|
|
67
|
+
expect(ed.contentType.id).toBe(target.contentTypeId);
|
|
68
|
+
expect(ed.readableFields.length).toBeGreaterThanOrEqual(1);
|
|
69
|
+
// restrictedFields are embedder config that never flows into Canvas
|
|
70
|
+
// (decision 012 phase 2): omitted for the editor too, not shown read-only.
|
|
71
|
+
expect(ed.readableFields.some((f) => f.schema.name === target.restrictedField)).toBe(false);
|
|
72
|
+
});
|
|
73
|
+
test("instance reads omit restricted field values for EVERY viewer (unconditional projection)", async () => {
|
|
74
|
+
const delegated = target.source.capabilities.auth.mode === "delegated";
|
|
75
|
+
if (delegated) {
|
|
76
|
+
// Delegated adapters refuse sessionless viewers before any I/O (D1).
|
|
77
|
+
await expectSessionRequired(expect, () => target.source.listInstances(target.contentTypeId, { pageSize: 2 }, undefined, sessionlessViewer(target)));
|
|
78
|
+
}
|
|
79
|
+
const editorPage = await target.source.listInstances(target.contentTypeId, { pageSize: 50 }, undefined, target.editor);
|
|
80
|
+
expect(editorPage.items.length).toBeGreaterThanOrEqual(1);
|
|
81
|
+
// The restricted field is stripped for the editor too (012 ph2).
|
|
82
|
+
for (const inst of editorPage.items) {
|
|
83
|
+
expect(Object.prototype.hasOwnProperty.call(inst.values, target.restrictedField)).toBe(false);
|
|
84
|
+
}
|
|
85
|
+
const firstId = editorPage.items[0].id;
|
|
86
|
+
if (delegated) {
|
|
87
|
+
await expectSessionRequired(expect, () => target.source.getInstance(target.contentTypeId, firstId, sessionlessViewer(target)));
|
|
88
|
+
await expectSessionRequired(expect, () => target.source.getInstancesByIds(target.contentTypeId, [firstId], sessionlessViewer(target)));
|
|
89
|
+
}
|
|
90
|
+
const editorSingle = await target.source.getInstance(target.contentTypeId, firstId, target.editor);
|
|
91
|
+
expect(Object.prototype.hasOwnProperty.call(editorSingle?.values ?? {}, target.restrictedField)).toBe(false);
|
|
92
|
+
const editorBatch = await target.source.getInstancesByIds(target.contentTypeId, [firstId], target.editor);
|
|
93
|
+
for (const inst of editorBatch) {
|
|
94
|
+
expect(Object.prototype.hasOwnProperty.call(inst.values, target.restrictedField)).toBe(false);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
test("cursor pagination: pages are disjoint, ordered, complete", async () => {
|
|
98
|
+
const p1 = await target.source.listInstances(target.contentTypeId, { pageSize: 2 }, undefined, target.editor);
|
|
99
|
+
expect(p1.items.length).toBe(2);
|
|
100
|
+
expect(p1.hasMore).toBe(true);
|
|
101
|
+
const p2 = await target.source.listInstances(target.contentTypeId, { pageSize: 2 }, p1.cursor, target.editor);
|
|
102
|
+
const ids1 = p1.items.map((i) => i.id);
|
|
103
|
+
const ids2 = p2.items.map((i) => i.id);
|
|
104
|
+
for (const id of ids2)
|
|
105
|
+
expect(ids1.includes(id)).toBe(false); // disjoint
|
|
106
|
+
});
|
|
107
|
+
test("row cap/exhaustion: final page has no phantom cursor and one-page-at-cap tiles exactly", async () => {
|
|
108
|
+
const seen = new Set();
|
|
109
|
+
let cursor;
|
|
110
|
+
let lastHasMore = true;
|
|
111
|
+
let lastCursor;
|
|
112
|
+
for (let guard = 0; guard < 50; guard += 1) {
|
|
113
|
+
const page = await target.source.listInstances(target.contentTypeId, { pageSize: 2 }, cursor, target.editor);
|
|
114
|
+
for (const item of page.items) {
|
|
115
|
+
const id = item.id;
|
|
116
|
+
expect(seen.has(id)).toBe(false);
|
|
117
|
+
seen.add(id);
|
|
118
|
+
}
|
|
119
|
+
lastHasMore = page.hasMore;
|
|
120
|
+
lastCursor = page.cursor;
|
|
121
|
+
if (!page.hasMore)
|
|
122
|
+
break;
|
|
123
|
+
cursor = page.cursor;
|
|
124
|
+
}
|
|
125
|
+
expect(lastHasMore).toBe(false);
|
|
126
|
+
expect(lastCursor).toBeUndefined();
|
|
127
|
+
expect(seen.size).toBeGreaterThanOrEqual(1);
|
|
128
|
+
const atCap = await target.source.listInstances(target.contentTypeId, { pageSize: seen.size }, undefined, target.editor);
|
|
129
|
+
expect(atCap.items.length).toBe(seen.size);
|
|
130
|
+
expect(atCap.hasMore).toBe(false);
|
|
131
|
+
expect(atCap.cursor).toBeUndefined();
|
|
132
|
+
expect(new Set(atCap.items.map((i) => i.id)).size).toBe(seen.size);
|
|
133
|
+
});
|
|
134
|
+
test("keyset stability: an insert between pages never re-serves or skips", async () => {
|
|
135
|
+
const p1 = await target.source.listInstances(target.contentTypeId, { pageSize: 2 }, undefined, target.editor);
|
|
136
|
+
const lastOfP1 = p1.items.at(-1).id;
|
|
137
|
+
const insertedId = await target.insertBetween(lastOfP1);
|
|
138
|
+
try {
|
|
139
|
+
const p2 = await target.source.listInstances(target.contentTypeId, { pageSize: 50 }, p1.cursor, target.editor);
|
|
140
|
+
const ids2 = p2.items.map((i) => i.id);
|
|
141
|
+
// No P1 row re-served...
|
|
142
|
+
for (const row of p1.items)
|
|
143
|
+
expect(ids2.includes(row.id)).toBe(false);
|
|
144
|
+
// ...and rows strictly after the cursor (incl. the insert when it
|
|
145
|
+
// sorts after) all present exactly once.
|
|
146
|
+
expect(new Set(ids2).size).toBe(ids2.length);
|
|
147
|
+
void insertedId;
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
await target.cleanup();
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
test("global sorted top-N: sort is applied before pagination, not after the id page", async () => {
|
|
154
|
+
const all = [];
|
|
155
|
+
let cursor;
|
|
156
|
+
for (let guard = 0; guard < 50; guard += 1) {
|
|
157
|
+
const page = await target.source.listInstances(target.contentTypeId, { pageSize: 2 }, cursor, target.editor);
|
|
158
|
+
all.push(...page.items);
|
|
159
|
+
if (!page.hasMore)
|
|
160
|
+
break;
|
|
161
|
+
cursor = page.cursor;
|
|
162
|
+
}
|
|
163
|
+
expect(all.length).toBeGreaterThanOrEqual(3);
|
|
164
|
+
const expectedIds = [...all]
|
|
165
|
+
.sort((a, b) => {
|
|
166
|
+
const av = a.values[target.sortField];
|
|
167
|
+
const bv = b.values[target.sortField];
|
|
168
|
+
const valueCompare = String(av ?? "").localeCompare(String(bv ?? ""));
|
|
169
|
+
if (valueCompare !== 0)
|
|
170
|
+
return valueCompare;
|
|
171
|
+
return String(a.id).localeCompare(String(b.id));
|
|
172
|
+
})
|
|
173
|
+
.slice(0, 3)
|
|
174
|
+
.map((item) => item.id);
|
|
175
|
+
const idOrderIds = all.slice(0, 3).map((item) => item.id);
|
|
176
|
+
expect(expectedIds.join("|")).not.toBe(idOrderIds.join("|"));
|
|
177
|
+
const sort = {
|
|
178
|
+
v: 1,
|
|
179
|
+
k: "ref",
|
|
180
|
+
scope: "instance",
|
|
181
|
+
scopeId: "conformance-instance",
|
|
182
|
+
path: [target.sortField],
|
|
183
|
+
};
|
|
184
|
+
const sortedPage = await target.source.listInstances(target.contentTypeId, { pageSize: 3, sort }, undefined, target.editor);
|
|
185
|
+
expect(sortedPage.items.map((item) => item.id)).toEqual(expectedIds);
|
|
186
|
+
});
|
|
187
|
+
test("getInstance + batched getInstancesByIds agree", async () => {
|
|
188
|
+
const page = await target.source.listInstances(target.contentTypeId, { pageSize: 3 }, undefined, target.editor);
|
|
189
|
+
const ids = page.items.map((i) => i.id);
|
|
190
|
+
const batch = await target.source.getInstancesByIds(target.contentTypeId, ids, target.editor);
|
|
191
|
+
expect(batch.length).toBe(ids.length);
|
|
192
|
+
const single = await target.source.getInstance(target.contentTypeId, ids[0], target.editor);
|
|
193
|
+
expect(single).toBeDefined();
|
|
194
|
+
expect(JSON.stringify(batch.find((b) => b.id === ids[0]))).toBe(JSON.stringify(single));
|
|
195
|
+
});
|
|
196
|
+
test("reference field resolves to a real instance id", async () => {
|
|
197
|
+
const page = await target.source.listInstances(target.contentTypeId, { pageSize: 1 }, undefined, target.editor);
|
|
198
|
+
const refValue = page.items[0].values[target.referenceField];
|
|
199
|
+
expect(typeof refValue).toBe("string");
|
|
200
|
+
});
|
|
201
|
+
test("schema-drift: a declared field no document carries projects as ABSENT — batch and single agree", async () => {
|
|
202
|
+
const described = await target.provider.describe(target.contentTypeId, target.editor);
|
|
203
|
+
expect(described.readableFields.some((f) => f.schema.name === target.absentField)).toBe(true);
|
|
204
|
+
const page = await target.source.listInstances(target.contentTypeId, { pageSize: 3 }, undefined, target.editor);
|
|
205
|
+
expect(page.items.length).toBeGreaterThanOrEqual(1);
|
|
206
|
+
for (const inst of page.items) {
|
|
207
|
+
// Absent (undefined) or explicit null — the resolver turns either into
|
|
208
|
+
// typed MissingData (invariant C); "" or a made-up default would leak
|
|
209
|
+
// a fake value into rendered pages.
|
|
210
|
+
expect(inst.values[target.absentField] ?? null).toBe(null);
|
|
211
|
+
}
|
|
212
|
+
const single = await target.source.getInstance(target.contentTypeId, page.items[0].id, target.editor);
|
|
213
|
+
expect(single?.values[target.absentField] ?? null).toBe(null);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=cases-reads.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cases-reads.js","sourceRoot":"","sources":["../../../src/content-source/conformance/cases-reads.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conformance cases — WRITE leg (extracted from conformance-kit.ts for A6):
|
|
3
|
+
* CAS stale/fresh precondition and the capability-gated create case. The
|
|
4
|
+
* cross-scope refusal cases (foreign read/write/viewer/create) are GONE
|
|
5
|
+
* (decision 012: battery-editor owns no access scoping; the CMS scopes by the
|
|
6
|
+
* delegated identity). Registered by the assembler in the SAME order (adapters
|
|
7
|
+
* snapshot/depend on the order) via `registerWriteCases`.
|
|
8
|
+
*/
|
|
9
|
+
import type { ConformanceHooks, ConformanceTarget } from "./target";
|
|
10
|
+
export declare function registerWriteCases(target: ConformanceTarget, hooks: ConformanceHooks): void;
|
|
11
|
+
//# sourceMappingURL=cases-writes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cases-writes.d.ts","sourceRoot":"","sources":["../../../src/content-source/conformance/cases-writes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAEpE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAoF3F"}
|