@gradial/aci 0.1.52-rc.9 → 0.1.52
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 +126 -0
- package/README.md +86 -5
- package/dist/astro/error-page.js +1 -0
- package/dist/astro/index.js +4 -0
- package/dist/astro/page.d.ts +5 -2
- package/dist/astro/page.js +35 -23
- package/dist/astro/preview.js +2 -17
- package/dist/audience-data-models.d.ts +308 -197
- package/dist/audience-data-models.js +313 -51
- package/dist/cli/compile-registry.mjs +6 -34
- package/dist/cli/mintlify-render.mjs +8 -0
- package/dist/collect/aci.js +1 -1
- package/dist/collect/aci.js.sha256 +1 -1
- package/dist/collect/api.d.ts +6 -7
- package/dist/collect/api.js +21 -8
- package/dist/collect/assignments.d.ts +7 -9
- package/dist/collect/assignments.js +23 -32
- package/dist/collect/batcher.d.ts +9 -7
- package/dist/collect/batcher.js +6 -5
- package/dist/collect/consent/envelope.d.ts +7 -1
- package/dist/collect/consent/envelope.js +3 -1
- package/dist/collect/consent/mapping.d.ts +2 -0
- package/dist/collect/consent/mapping.js +1 -0
- package/dist/collect/consenthold.d.ts +38 -0
- package/dist/collect/consenthold.js +82 -0
- package/dist/collect/declarative.js +7 -5
- package/dist/collect/gapbuffer.d.ts +13 -4
- package/dist/collect/gapbuffer.js +21 -10
- package/dist/collect/index.js +78 -21
- package/dist/collect/pageviews.d.ts +11 -11
- package/dist/collect/pageviews.js +27 -22
- package/dist/consent-banner/index.d.ts +17 -0
- package/dist/consent-banner/index.js +23 -0
- package/dist/content/index.d.ts +2 -1
- package/dist/content/index.js +4 -1
- package/dist/content/provider.d.ts +16 -2
- package/dist/content/provider.js +5 -1
- package/dist/content/resolve-slots.d.ts +24 -2
- package/dist/content/resolve-slots.js +127 -21
- package/dist/content/types.d.ts +5 -1
- package/dist/edge/expression-capabilities.v1.d.ts +106 -0
- package/dist/edge/expression-capabilities.v1.js +165 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.js +0 -1
- package/dist/internal/domain/edge/identity.d.ts +47 -4
- package/dist/internal/domain/edge/identity.js +130 -26
- package/dist/internal/domain/edge/index.d.ts +1 -1
- package/dist/internal/domain/edge/index.js +1 -1
- package/dist/internal/domain/edge/mimic_token.d.ts +14 -0
- package/dist/internal/domain/edge/mimic_token.js +125 -0
- package/dist/internal/domain/edge/personalization-core.d.ts +61 -22
- package/dist/internal/domain/edge/personalization-core.js +790 -200
- package/dist/internal/domain/edge/personalization_index.d.ts +17 -0
- package/dist/internal/domain/edge/personalization_index.js +55 -0
- package/dist/internal/domain/edge/resolve.js +76 -39
- package/dist/internal/domain/edge/testdata/flat_only_validator_v1.d.ts +10 -0
- package/dist/internal/domain/edge/testdata/flat_only_validator_v1.js +253 -0
- package/dist/internal/domain/edge/types.d.ts +82 -78
- package/dist/internal/domain/edge/types.js +3 -3
- package/dist/internal/domain/edge/variant_key.d.ts +4 -0
- package/dist/internal/domain/edge/variant_key.js +56 -0
- package/dist/internal/platform/collectionstore/errors.d.ts +24 -0
- package/dist/internal/platform/collectionstore/errors.js +48 -0
- package/dist/mintlify/blocks.d.ts +6 -0
- package/dist/mintlify/blocks.js +201 -0
- package/dist/mintlify/config.d.ts +3 -0
- package/dist/mintlify/config.js +77 -0
- package/dist/mintlify/index.d.ts +3 -0
- package/dist/mintlify/index.js +2 -0
- package/dist/mintlify/json.d.ts +8 -0
- package/dist/mintlify/json.js +37 -0
- package/dist/mintlify/materialize.d.ts +14 -0
- package/dist/mintlify/materialize.js +254 -0
- package/dist/mintlify/types.d.ts +74 -0
- package/dist/mintlify/types.js +1 -0
- package/dist/mintlify/validate.d.ts +7 -0
- package/dist/mintlify/validate.js +256 -0
- package/dist/next/assignments-navigation.d.ts +4 -0
- package/dist/next/assignments-navigation.js +18 -0
- package/dist/next/assignments-script.d.ts +3 -2
- package/dist/next/assignments-script.js +5 -5
- package/dist/next/error-pages.d.ts +4 -0
- package/dist/next/error-pages.js +4 -0
- package/dist/next/error-seat-payload.d.ts +2 -1
- package/dist/next/error-seat-payload.js +14 -24
- package/dist/next/error-seat.js +7 -2
- package/dist/next/index.d.ts +1 -1
- package/dist/next/index.js +3 -1
- package/dist/next/page.d.ts +2 -1
- package/dist/next/page.js +15 -4
- package/dist/next/release-context.d.ts +30 -0
- package/dist/next/release-context.js +56 -0
- package/dist/next/render.d.ts +1 -1
- package/dist/next/render.js +15 -5
- package/dist/next/server.d.ts +9 -3
- package/dist/next/server.js +17 -32
- package/dist/preview/core.d.ts +1 -0
- package/dist/preview/core.js +27 -0
- package/dist/react/VideoPlayer.d.ts +3 -3
- package/dist/react/index.d.ts +3 -3
- package/dist/registry.d.ts +4 -2
- package/dist/testing/conformance/checks.d.ts +2 -2
- package/dist/testing/conformance/checks.js +2 -0
- package/dist/testing/conformance/index.d.ts +1 -0
- package/dist/testing/conformance/index.js +1 -0
- package/dist/testing/conformance/next-stubs.d.ts +6 -0
- package/dist/testing/conformance/next-stubs.js +9 -0
- package/dist/testing/conformance/preset.d.ts +3 -2
- package/dist/testing/conformance/preset.js +15 -8
- package/dist/testing/conformance/root-identity.d.ts +31 -0
- package/dist/testing/conformance/root-identity.js +361 -0
- package/dist/testing/conformance/stubs/next-image.d.ts +7 -0
- package/dist/testing/conformance/stubs/next-image.js +5 -0
- package/dist/testing/conformance/stubs/next-link.d.ts +7 -0
- package/dist/testing/conformance/stubs/next-link.js +4 -0
- package/dist/testing/conformance/types.d.ts +5 -2
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.js +4 -3
- package/dist/types/block-ref.js +2 -2
- package/dist/types/component.d.ts +9 -0
- package/dist/types/config.d.ts +0 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.js +0 -1
- package/dist/types/page.d.ts +0 -1
- package/migrations/conformance-registry.md +22 -0
- package/migrations/experiment-goal-ids.md +43 -0
- package/package.json +21 -7
- package/src/cli/compile-registry.mjs +6 -30
- package/src/cli/mintlify-render.mjs +9 -0
- package/src/types/block-ref.test.ts +16 -1
- package/src/types/block-ref.ts +2 -2
- package/src/types/component.ts +10 -0
- package/src/types/config.ts +0 -1
- package/src/types/index.ts +0 -1
- package/src/types/page.ts +0 -1
- package/templates/astro/starter-content/src/components/chrome/Footer.astro +5 -3
- package/templates/astro/starter-content/src/components/chrome/Header.astro +5 -3
- package/templates/astro/starter-content/src/components/elements/Button.astro +5 -2
- package/templates/astro/starter-content/src/components/elements/ButtonBlock.astro +5 -3
- package/templates/astro/starter-content/src/components/sections/ContainerSection.astro +4 -3
- package/templates/astro/starter-content/src/components/sections/FeatureCard.astro +4 -3
- package/templates/astro/starter-content/src/components/sections/FeatureGrid.astro +4 -3
- package/templates/astro/starter-content/src/components/sections/HomeHero.astro +5 -3
- package/templates/astro/starter-content/src/components/sections/PersonalizationChoice.astro +4 -3
- package/templates/astro/starter-content/src/components/sections/StatsBar.astro +4 -3
- package/templates/astro/starter-content/src/fixtures/sections.ts +1 -1
- package/templates/astro/starter-content/src/stories/CompositionStoryFrame.astro +7 -2
- package/templates/astro/template/.aci.yaml.tmpl +0 -1
- package/templates/astro/template/package.json.tmpl +5 -5
- package/templates/astro/template/src/layouts/SiteLayout.astro +2 -2
- package/templates/common/.agents/skills/aci/SKILL.md +58 -1
- package/templates/common/.agents/skills/authoring/SKILL.md +194 -42
- package/templates/common/.agents/skills/authoring/references/block-registry.md +19 -3
- package/templates/common/.agents/skills/authoring/references/contracts.md +9 -30
- package/templates/common/.agents/skills/authoring/references/repo-structure.md +5 -4
- package/templates/common/.agents/skills/authoring/references/sdk-server-functions.md +3 -3
- package/templates/common/.agents/skills/dam-delivery/SKILL.md +216 -0
- package/templates/common/.agents/skills/dam-delivery/references/permalink-grammar.md +167 -0
- package/templates/common/.agents/skills/migration/references/canon-migration.md +18 -67
- package/templates/common/.agents/skills/migration/references/selector-map.md +1 -1
- package/templates/common/.content/fragments/navbar/_index.json +24 -0
- package/templates/common/.content/fragments/site-footer/_index.json +61 -0
- package/templates/common/.content/pages/404/_index.json +4 -2
- package/templates/common/.content/pages/_index.json +0 -1
- package/templates/common/.content/pages/error/_index.json +4 -2
- package/templates/common/.content/schemas/site.schema.json +11 -1
- package/templates/common/.content/templates/error.json +24 -0
- package/templates/common/.content/templates/home.json +28 -0
- package/templates/common/.content/templates/site.json +8 -0
- package/templates/common/.content/templates/standard.json +24 -0
- package/templates/common/.nvmrc +1 -1
- package/templates/common/starter-content/.content/config/site.json +1 -1
- package/templates/common/starter-content/.content/dam/README.md +74 -0
- package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000101}/asset.json +1 -1
- package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000102}/asset.json +1 -1
- package/templates/common/starter-content/.content/pages/404/_index.json +1 -2
- package/templates/common/starter-content/.content/pages/{home/_index.json → _index.json} +14 -3
- package/templates/common/starter-content/.content/pages/about/_index.json +2 -2
- package/templates/common/starter-content/.content/pages/error/_index.json +1 -2
- package/templates/common/starter-content/.content/patterns/components/button.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/container.json +8 -3
- package/templates/common/starter-content/.content/patterns/components/feature_card.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/feature_grid.json +5 -3
- package/templates/common/starter-content/.content/patterns/components/home_hero.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/personalization_choice.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/site-footer.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/site-navigation.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/stats_bar.json +2 -2
- package/templates/common/starter-content/.content/schemas/site.schema.json +11 -1
- package/templates/nextjs/starter-content/src/components/chrome/Footer.tsx +4 -3
- package/templates/nextjs/starter-content/src/components/chrome/Header.tsx +4 -3
- package/templates/nextjs/starter-content/src/components/elements/Button.tsx +4 -3
- package/templates/nextjs/starter-content/src/components/elements/ButtonBlock.tsx +4 -3
- package/templates/nextjs/starter-content/src/components/sections/ContainerSection.tsx +4 -2
- package/templates/nextjs/starter-content/src/components/sections/FeatureCard.tsx +4 -3
- package/templates/nextjs/starter-content/src/components/sections/FeatureGrid.tsx +4 -2
- package/templates/nextjs/starter-content/src/components/sections/HomeHero.tsx +4 -3
- package/templates/nextjs/starter-content/src/components/sections/PersonalizationChoice.tsx +4 -2
- package/templates/nextjs/starter-content/src/components/sections/StatsBar.tsx +4 -3
- package/templates/nextjs/template/.aci.yaml +0 -1
- package/templates/nextjs/template/.aci.yaml.tmpl +0 -1
- package/templates/nextjs/template/package.json.tmpl +4 -3
- package/templates/nextjs/template/src/app/_components/c15t-bridge.ts +30 -0
- package/templates/nextjs/template/src/app/_components/c15t-consent-ui.tsx +37 -0
- package/templates/nextjs/template/src/app/_components/consent-manager.css +63 -0
- package/templates/nextjs/template/src/app/_components/consent-manager.tsx +76 -0
- package/templates/nextjs/template/src/app/fonts/inter/OFL.txt +93 -0
- package/templates/nextjs/template/src/app/fonts/inter/inter-latin.woff2 +0 -0
- package/templates/nextjs/template/src/app/fonts/space-grotesk/OFL.txt +93 -0
- package/templates/nextjs/template/src/app/fonts/space-grotesk/space-grotesk-latin.woff2 +0 -0
- package/templates/nextjs/template/src/app/layout.tsx +12 -7
- package/templates/nextjs/template/tests/conformance.test.ts.tmpl +1 -0
- package/dist/define-layout.d.ts +0 -6
- package/dist/define-layout.js +0 -14
- package/dist/edge/personalization-core.d.ts +0 -11
- package/dist/edge/personalization-core.js +0 -269
- package/dist/internal/domain/edge/compose.d.ts +0 -24
- package/dist/internal/domain/edge/compose.js +0 -89
- package/dist/internal/domain/edge/record/codec.d.ts +0 -71
- package/dist/internal/domain/edge/record/codec.js +0 -401
- package/dist/next/collect-route.d.ts +0 -19
- package/dist/next/collect-route.js +0 -459
- package/dist/next/edge-config.d.ts +0 -1
- package/dist/next/edge-config.js +0 -92
- package/dist/next/envelope-digest.d.ts +0 -21
- package/dist/next/envelope-digest.js +0 -58
- package/dist/next/middleware.d.ts +0 -40
- package/dist/next/middleware.js +0 -475
- package/dist/next/personalization-host.d.ts +0 -134
- package/dist/next/personalization-host.js +0 -270
- package/dist/next/root-layout.d.ts +0 -4
- package/dist/next/root-layout.js +0 -5
- package/dist/next/vercel-collect-sdk-route.d.ts +0 -27
- package/dist/next/vercel-collect-sdk-route.js +0 -181
- package/dist/next/vercel-edge-projection-v1.d.ts +0 -24
- package/dist/next/vercel-edge-projection-v1.js +0 -880
- package/dist/next/vercel-personalization.d.ts +0 -4
- package/dist/next/vercel-personalization.js +0 -4
- package/dist/next/vercel-s3-personalization.d.ts +0 -79
- package/dist/next/vercel-s3-personalization.js +0 -570
- package/dist/types/layout.d.ts +0 -24
- package/src/types/layout.ts +0 -29
- package/templates/astro/starter-content/src/render/RenderPage.astro +0 -67
- package/templates/astro/template/src/cms/contracts/layouts/index.ts +0 -18
- package/templates/common/starter-content/.content/patterns/layouts/default.json +0 -14
- package/templates/nextjs/starter-content/src/components/elements/AtomicBlock.tsx +0 -13
- package/templates/nextjs/template/src/cms/contracts/layouts/index.ts +0 -16
- /package/dist/{types/layout.js → cli/mintlify-render.d.mts} +0 -0
- /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000101}/editorial.json +0 -0
- /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000101}/governance.json +0 -0
- /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000101}/versions/v0001.json +0 -0
- /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000102}/editorial.json +0 -0
- /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000102}/governance.json +0 -0
- /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000102}/versions/v0001.json +0 -0
|
@@ -1,26 +1,132 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Shared Go/TS limit contract (sdk I-21). These values are pinned against
|
|
3
|
+
* internal/domain/content/compiler/testdata/limit-conformance.v1.json by
|
|
4
|
+
* limit-conformance.test.ts (TS) and limit_conformance_test.go (Go); the
|
|
5
|
+
* compiler's MaxFragmentDepth/MaxExpandedBlocks must match.
|
|
6
|
+
*/
|
|
7
|
+
/** Bounds a selected fragment reference chain, counting its root fragment. */
|
|
8
|
+
export const MAX_FRAGMENT_DEPTH = 10;
|
|
9
|
+
/** Bounds rendered component occurrences per page, including repeated placements. */
|
|
10
|
+
export const MAX_EXPANDED_BLOCKS = 4096;
|
|
11
|
+
/** Failures in a selected fragment are never eligible for local-content fallback. */
|
|
12
|
+
export class FragmentResolutionError extends Error {
|
|
13
|
+
constructor(message, options) {
|
|
14
|
+
super(message, options);
|
|
15
|
+
this.name = 'FragmentResolutionError';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
// Runtime-only provenance keeps each fragment placement's authored IDs in its
|
|
19
|
+
// own validation scope. It is never emitted into compiled JSON or HTML.
|
|
20
|
+
export const fragmentRootScope = Symbol('aci.fragment-root-scope');
|
|
21
|
+
export function preserveFragmentScope(source, target) {
|
|
22
|
+
return Object.hasOwn(source, fragmentRootScope)
|
|
23
|
+
? Object.defineProperty(target, fragmentRootScope, { value: true })
|
|
24
|
+
: target;
|
|
25
|
+
}
|
|
26
|
+
export async function resolveSlots(plan, pageRegions, getFragment) {
|
|
27
|
+
return resolveAsync(walkSlots(plan, pageRegions), getFragment);
|
|
28
|
+
}
|
|
29
|
+
/** The config-time error seat uses the identical traversal with synchronous file reads. */
|
|
30
|
+
export function resolveSlotsSync(plan, pageRegions, getFragment) {
|
|
31
|
+
const walk = walkSlots(plan, pageRegions);
|
|
32
|
+
let step = walk.next();
|
|
33
|
+
while (!step.done) {
|
|
34
|
+
let fragment;
|
|
35
|
+
try {
|
|
36
|
+
fragment = getFragment(step.value);
|
|
8
37
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const blocks = [];
|
|
12
|
-
for (const ref of defaults) {
|
|
13
|
-
const fragment = await getFragment(ref.fragmentId);
|
|
14
|
-
const block = fragment.block ?? { component: fragment.component ?? '', props: fragment.props };
|
|
15
|
-
blocks.push({
|
|
16
|
-
$type: 'component',
|
|
17
|
-
id: fragment.id ?? fragment.fragmentId ?? ref.fragmentId,
|
|
18
|
-
component: block.component,
|
|
19
|
-
props: block.props || {},
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
resolved[slot.name] = blocks;
|
|
38
|
+
catch (cause) {
|
|
39
|
+
throw bindingError(step.value, cause);
|
|
23
40
|
}
|
|
41
|
+
step = walk.next(fragment);
|
|
42
|
+
}
|
|
43
|
+
return step.value;
|
|
44
|
+
}
|
|
45
|
+
/** Resolve compiled references through the exact fragment bindings selected for this page. */
|
|
46
|
+
export async function resolveFragmentNodes(nodes, getFragment) {
|
|
47
|
+
return resolveAsync(walkNodes(nodes, { blocks: 0 }), getFragment);
|
|
48
|
+
}
|
|
49
|
+
async function resolveAsync(walk, getFragment) {
|
|
50
|
+
let step = walk.next();
|
|
51
|
+
while (!step.done) {
|
|
52
|
+
let fragment;
|
|
53
|
+
try {
|
|
54
|
+
fragment = await getFragment(step.value);
|
|
55
|
+
}
|
|
56
|
+
catch (cause) {
|
|
57
|
+
throw bindingError(step.value, cause);
|
|
58
|
+
}
|
|
59
|
+
step = walk.next(fragment);
|
|
60
|
+
}
|
|
61
|
+
return step.value;
|
|
62
|
+
}
|
|
63
|
+
function bindingError(id, cause) {
|
|
64
|
+
return new FragmentResolutionError(`ACI fragment ${id} selected binding failed: ${String(cause)}`, { cause });
|
|
65
|
+
}
|
|
66
|
+
function* walkSlots(plan, pageRegions) {
|
|
67
|
+
const resolved = {};
|
|
68
|
+
const state = { blocks: 0 };
|
|
69
|
+
for (const slot of plan.slots) {
|
|
70
|
+
const pageBlocks = pageRegions[slot.name];
|
|
71
|
+
const nodes = pageBlocks?.length ? pageBlocks : plan.defaults?.[slot.name];
|
|
72
|
+
if (nodes?.length)
|
|
73
|
+
resolved[slot.name] = yield* walkNodes(nodes, state);
|
|
24
74
|
}
|
|
25
75
|
return resolved;
|
|
26
76
|
}
|
|
77
|
+
function* walkNodes(nodes, state) {
|
|
78
|
+
const blocks = [];
|
|
79
|
+
for (const node of nodes)
|
|
80
|
+
blocks.push((yield* walkValue(node, [], state)));
|
|
81
|
+
return blocks;
|
|
82
|
+
}
|
|
83
|
+
// Active ancestry belongs to each placement, while the block budget belongs to
|
|
84
|
+
// the whole rendered page. A repeated fragment in another branch is valid.
|
|
85
|
+
function* walkValue(value, ancestry, state) {
|
|
86
|
+
if (Array.isArray(value)) {
|
|
87
|
+
const result = [];
|
|
88
|
+
for (const child of value)
|
|
89
|
+
result.push(yield* walkValue(child, ancestry, state));
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
if (value === null || typeof value !== 'object')
|
|
93
|
+
return value;
|
|
94
|
+
const node = value;
|
|
95
|
+
if (node.kind === 'fragment-ref') {
|
|
96
|
+
const id = node.fragmentId;
|
|
97
|
+
if (typeof id !== 'string' || !id)
|
|
98
|
+
throw new FragmentResolutionError('ACI fragment reference has no fragmentId');
|
|
99
|
+
const chain = [...ancestry, id];
|
|
100
|
+
if (ancestry.includes(id))
|
|
101
|
+
throw new FragmentResolutionError(`ACI fragment cycle: ${chain.join(' -> ')}`);
|
|
102
|
+
if (chain.length > MAX_FRAGMENT_DEPTH)
|
|
103
|
+
throw new FragmentResolutionError(`ACI fragment depth exceeds ${MAX_FRAGMENT_DEPTH}: ${chain.join(' -> ')}`);
|
|
104
|
+
const fragment = yield id;
|
|
105
|
+
const block = (yield* walkValue(fragmentToBlock(fragment, id), chain, state));
|
|
106
|
+
return Object.defineProperty(block, fragmentRootScope, { value: true });
|
|
107
|
+
}
|
|
108
|
+
const isBlock = node.$type === 'component'
|
|
109
|
+
|| (typeof node.component === 'string' && node.component.length > 0
|
|
110
|
+
&& node.props !== null && typeof node.props === 'object' && !Array.isArray(node.props));
|
|
111
|
+
if (isBlock && ++state.blocks > MAX_EXPANDED_BLOCKS) {
|
|
112
|
+
throw new FragmentResolutionError(`ACI rendered page exceeds ${MAX_EXPANDED_BLOCKS} component blocks`);
|
|
113
|
+
}
|
|
114
|
+
const result = {};
|
|
115
|
+
for (const [key, child] of Object.entries(node))
|
|
116
|
+
result[key] = yield* walkValue(child, ancestry, state);
|
|
117
|
+
return preserveFragmentScope(node, result);
|
|
118
|
+
}
|
|
119
|
+
/** Use the same fragment root identity for layout defaults and region placements. */
|
|
120
|
+
export function fragmentToBlock(fragment, id) {
|
|
121
|
+
const block = fragment?.block ?? fragment;
|
|
122
|
+
if (!block || typeof block.component !== 'string' || !block.component
|
|
123
|
+
|| (block.props !== undefined && (typeof block.props !== 'object' || block.props === null || Array.isArray(block.props)))) {
|
|
124
|
+
throw new FragmentResolutionError(`ACI fragment ${id} has no component block`);
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
$type: 'component',
|
|
128
|
+
id: fragment.id ?? fragment.fragmentId ?? id,
|
|
129
|
+
component: block.component,
|
|
130
|
+
props: block.props || {},
|
|
131
|
+
};
|
|
132
|
+
}
|
package/dist/content/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ExperimentAssignmentContext, SitePersonalizationConfig } from './personalization.js';
|
|
2
|
+
import type { FragmentRefNode } from '../types/page.js';
|
|
2
3
|
export type ButtonVariant = 'primary' | 'secondary' | 'tertiary' | 'outline' | 'ghost';
|
|
3
4
|
export interface KernelImage {
|
|
4
5
|
src: string;
|
|
@@ -47,6 +48,7 @@ export interface KernelPageBlock {
|
|
|
47
48
|
component: string;
|
|
48
49
|
props: Record<string, unknown>;
|
|
49
50
|
}
|
|
51
|
+
export type KernelPageNode = KernelPageBlock | FragmentRefNode;
|
|
50
52
|
export interface KernelAtomicBlock {
|
|
51
53
|
$type: 'component';
|
|
52
54
|
id: string;
|
|
@@ -59,7 +61,7 @@ export interface KernelPage {
|
|
|
59
61
|
status: string;
|
|
60
62
|
layout: string;
|
|
61
63
|
metadata: KernelPageSeo;
|
|
62
|
-
regions: Record<string,
|
|
64
|
+
regions: Record<string, KernelPageNode[]>;
|
|
63
65
|
/**
|
|
64
66
|
* Build-time experiment assignment context (personalization-reporting
|
|
65
67
|
* design/04); present only on experiment variant payloads. The starters
|
|
@@ -110,6 +112,8 @@ export interface KernelRouteMetadata {
|
|
|
110
112
|
}
|
|
111
113
|
export interface RenderInput<TPage extends KernelPage = KernelPage, TSiteConfig extends KernelSiteConfig = KernelSiteConfig> {
|
|
112
114
|
route: string;
|
|
115
|
+
/** Selected render tuple. Unpersonalized renders explicitly use "base". */
|
|
116
|
+
variantKey: string;
|
|
113
117
|
domain: string;
|
|
114
118
|
locale: string;
|
|
115
119
|
siteConfig: TSiteConfig;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
export declare const expressionCapabilities: {
|
|
2
|
+
readonly schemaVersion: 1;
|
|
3
|
+
readonly contract: "personalization-expression";
|
|
4
|
+
readonly maxConditions: 64;
|
|
5
|
+
readonly maxDepth: 5;
|
|
6
|
+
readonly maxInValues: 32;
|
|
7
|
+
readonly grammars: {
|
|
8
|
+
readonly number: "^-?(0|[1-9][0-9]*)(\\.[0-9]+)?([eE][+-]?[0-9]+)?$";
|
|
9
|
+
readonly timestamp: "^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(\\.\\d{1,9})?(Z|[+-]\\d{2}:\\d{2})$";
|
|
10
|
+
};
|
|
11
|
+
readonly operators: readonly [{
|
|
12
|
+
readonly name: "equals";
|
|
13
|
+
readonly operand: "scalar";
|
|
14
|
+
readonly compact: "eq";
|
|
15
|
+
}, {
|
|
16
|
+
readonly name: "contains";
|
|
17
|
+
readonly operand: "scalar";
|
|
18
|
+
readonly compact: "ct";
|
|
19
|
+
}, {
|
|
20
|
+
readonly name: "startsWith";
|
|
21
|
+
readonly operand: "scalar";
|
|
22
|
+
readonly compact: "sw";
|
|
23
|
+
}, {
|
|
24
|
+
readonly name: "exists";
|
|
25
|
+
readonly operand: "optionalBoolean";
|
|
26
|
+
readonly compact: "ex";
|
|
27
|
+
}, {
|
|
28
|
+
readonly name: "greaterThan";
|
|
29
|
+
readonly operand: "number";
|
|
30
|
+
readonly compact: "gt";
|
|
31
|
+
}, {
|
|
32
|
+
readonly name: "greaterThanOrEqual";
|
|
33
|
+
readonly operand: "number";
|
|
34
|
+
readonly compact: "ge";
|
|
35
|
+
}, {
|
|
36
|
+
readonly name: "lessThan";
|
|
37
|
+
readonly operand: "number";
|
|
38
|
+
readonly compact: "lt";
|
|
39
|
+
}, {
|
|
40
|
+
readonly name: "lessThanOrEqual";
|
|
41
|
+
readonly operand: "number";
|
|
42
|
+
readonly compact: "le";
|
|
43
|
+
}, {
|
|
44
|
+
readonly name: "before";
|
|
45
|
+
readonly operand: "timestamp";
|
|
46
|
+
readonly compact: "bf";
|
|
47
|
+
}, {
|
|
48
|
+
readonly name: "after";
|
|
49
|
+
readonly operand: "timestamp";
|
|
50
|
+
readonly compact: "af";
|
|
51
|
+
}, {
|
|
52
|
+
readonly name: "between";
|
|
53
|
+
readonly operand: "range";
|
|
54
|
+
readonly compact: "bt";
|
|
55
|
+
readonly range: {
|
|
56
|
+
readonly memberTypes: readonly ["number", "timestamp"];
|
|
57
|
+
readonly homogeneous: true;
|
|
58
|
+
readonly inclusive: true;
|
|
59
|
+
};
|
|
60
|
+
}, {
|
|
61
|
+
readonly name: "in";
|
|
62
|
+
readonly operand: "scalarList";
|
|
63
|
+
readonly compact: "in";
|
|
64
|
+
readonly maxValues: 32;
|
|
65
|
+
}];
|
|
66
|
+
readonly scopes: readonly [{
|
|
67
|
+
readonly scope: "request";
|
|
68
|
+
readonly allowsEmpty: false;
|
|
69
|
+
readonly fields: readonly [{
|
|
70
|
+
readonly field: "referrer";
|
|
71
|
+
}, {
|
|
72
|
+
readonly field: "query.*";
|
|
73
|
+
}, {
|
|
74
|
+
readonly field: "header.*";
|
|
75
|
+
}, {
|
|
76
|
+
readonly field: "cookie.*";
|
|
77
|
+
}, {
|
|
78
|
+
readonly field: "geo.*";
|
|
79
|
+
}, {
|
|
80
|
+
readonly field: "utm.*";
|
|
81
|
+
}, {
|
|
82
|
+
readonly field: "device.class";
|
|
83
|
+
readonly operators: readonly ["equals", "in", "exists"];
|
|
84
|
+
readonly values: readonly ["desktop", "mobile", "tablet", "unknown"];
|
|
85
|
+
}, {
|
|
86
|
+
readonly field: "time.now";
|
|
87
|
+
readonly operators: readonly ["before", "after", "between", "exists"];
|
|
88
|
+
readonly instant: true;
|
|
89
|
+
}, {
|
|
90
|
+
readonly field: "audience.memberships";
|
|
91
|
+
readonly operators: readonly ["equals", "in", "exists"];
|
|
92
|
+
}];
|
|
93
|
+
}, {
|
|
94
|
+
readonly scope: "event";
|
|
95
|
+
readonly allowsEmpty: true;
|
|
96
|
+
readonly fields: readonly [{
|
|
97
|
+
readonly field: "referrer";
|
|
98
|
+
}, {
|
|
99
|
+
readonly field: "page.path";
|
|
100
|
+
}, {
|
|
101
|
+
readonly field: "properties.*";
|
|
102
|
+
}, {
|
|
103
|
+
readonly field: "utm.*";
|
|
104
|
+
}];
|
|
105
|
+
}];
|
|
106
|
+
};
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// GENERATED by scripts/generate-expression-capabilities.go — DO NOT EDIT.
|
|
2
|
+
// Regenerate: make expression-capabilities
|
|
3
|
+
//
|
|
4
|
+
// The published capability discovery schema for the personalization
|
|
5
|
+
// expression contract (ADR 0038), generated from the Go vocabulary tables
|
|
6
|
+
// and drift-gated in CI against the canonical JSON artifact at
|
|
7
|
+
// internal/domain/personalization/expression/schema/.
|
|
8
|
+
export const expressionCapabilities = {
|
|
9
|
+
"schemaVersion": 1,
|
|
10
|
+
"contract": "personalization-expression",
|
|
11
|
+
"maxConditions": 64,
|
|
12
|
+
"maxDepth": 5,
|
|
13
|
+
"maxInValues": 32,
|
|
14
|
+
"grammars": {
|
|
15
|
+
"number": "^-?(0|[1-9][0-9]*)(\\.[0-9]+)?([eE][+-]?[0-9]+)?$",
|
|
16
|
+
"timestamp": "^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(\\.\\d{1,9})?(Z|[+-]\\d{2}:\\d{2})$"
|
|
17
|
+
},
|
|
18
|
+
"operators": [
|
|
19
|
+
{
|
|
20
|
+
"name": "equals",
|
|
21
|
+
"operand": "scalar",
|
|
22
|
+
"compact": "eq"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"name": "contains",
|
|
26
|
+
"operand": "scalar",
|
|
27
|
+
"compact": "ct"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "startsWith",
|
|
31
|
+
"operand": "scalar",
|
|
32
|
+
"compact": "sw"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"name": "exists",
|
|
36
|
+
"operand": "optionalBoolean",
|
|
37
|
+
"compact": "ex"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "greaterThan",
|
|
41
|
+
"operand": "number",
|
|
42
|
+
"compact": "gt"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"name": "greaterThanOrEqual",
|
|
46
|
+
"operand": "number",
|
|
47
|
+
"compact": "ge"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"name": "lessThan",
|
|
51
|
+
"operand": "number",
|
|
52
|
+
"compact": "lt"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"name": "lessThanOrEqual",
|
|
56
|
+
"operand": "number",
|
|
57
|
+
"compact": "le"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "before",
|
|
61
|
+
"operand": "timestamp",
|
|
62
|
+
"compact": "bf"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "after",
|
|
66
|
+
"operand": "timestamp",
|
|
67
|
+
"compact": "af"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"name": "between",
|
|
71
|
+
"operand": "range",
|
|
72
|
+
"compact": "bt",
|
|
73
|
+
"range": {
|
|
74
|
+
"memberTypes": [
|
|
75
|
+
"number",
|
|
76
|
+
"timestamp"
|
|
77
|
+
],
|
|
78
|
+
"homogeneous": true,
|
|
79
|
+
"inclusive": true
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"name": "in",
|
|
84
|
+
"operand": "scalarList",
|
|
85
|
+
"compact": "in",
|
|
86
|
+
"maxValues": 32
|
|
87
|
+
}
|
|
88
|
+
],
|
|
89
|
+
"scopes": [
|
|
90
|
+
{
|
|
91
|
+
"scope": "request",
|
|
92
|
+
"allowsEmpty": false,
|
|
93
|
+
"fields": [
|
|
94
|
+
{
|
|
95
|
+
"field": "referrer"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"field": "query.*"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"field": "header.*"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"field": "cookie.*"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"field": "geo.*"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"field": "utm.*"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"field": "device.class",
|
|
114
|
+
"operators": [
|
|
115
|
+
"equals",
|
|
116
|
+
"in",
|
|
117
|
+
"exists"
|
|
118
|
+
],
|
|
119
|
+
"values": [
|
|
120
|
+
"desktop",
|
|
121
|
+
"mobile",
|
|
122
|
+
"tablet",
|
|
123
|
+
"unknown"
|
|
124
|
+
]
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"field": "time.now",
|
|
128
|
+
"operators": [
|
|
129
|
+
"before",
|
|
130
|
+
"after",
|
|
131
|
+
"between",
|
|
132
|
+
"exists"
|
|
133
|
+
],
|
|
134
|
+
"instant": true
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"field": "audience.memberships",
|
|
138
|
+
"operators": [
|
|
139
|
+
"equals",
|
|
140
|
+
"in",
|
|
141
|
+
"exists"
|
|
142
|
+
]
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"scope": "event",
|
|
148
|
+
"allowsEmpty": true,
|
|
149
|
+
"fields": [
|
|
150
|
+
{
|
|
151
|
+
"field": "referrer"
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"field": "page.path"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"field": "properties.*"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"field": "utm.*"
|
|
161
|
+
}
|
|
162
|
+
]
|
|
163
|
+
}
|
|
164
|
+
]
|
|
165
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
export { defineComponentContract } from './define-component.js';
|
|
2
|
-
export { defineLayoutContract, slot, fragmentDefault } from './define-layout.js';
|
|
3
2
|
export { createRegistry, registryLookup } from './registry.js';
|
|
4
3
|
export type { Registry, RegistryEntry, AnyComponent } from './registry.js';
|
|
5
4
|
export { blockRef, blockRefArray } from './types/block-ref.js';
|
|
6
5
|
export type { BlockRef, BlockRefEntry, BlockRefMeta, BlockRefUnion } from './types/block-ref.js';
|
|
7
|
-
export type { ComponentContract, ComponentContractID, ComponentContractValidator, ComponentRegistry, ComponentValidationContext, ComponentValidationIssue, InferComponentProps, } from './types/component.js';
|
|
6
|
+
export type { ComponentContract, ComponentContractID, ComponentContractValidator, ComponentRegistry, ComponentValidationContext, ComponentValidationIssue, InferComponentProps, RootIdentityProps, } from './types/component.js';
|
|
8
7
|
export { ImageSchema, imageAttrs, primaryImageSource, type Image, type ImageSource, type ImageAttrs, type ImageSlotContract, type SlotOutput, } from './types/image.js';
|
|
9
8
|
export { LinkSchema, type Link, type LinkTarget, type LinkResolverContext, resolveLink, resolveHref, assertSafeHref, normalizeLinkRel, } from './types/link.js';
|
|
10
9
|
export { HeadingSchema, InlineContentSchema, RichTextValueSchema, type Heading, type InlineContent, type RichTextValue, } from './types/rich-text.js';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { defineComponentContract } from './define-component.js';
|
|
2
|
-
export { defineLayoutContract, slot, fragmentDefault } from './define-layout.js';
|
|
3
2
|
export { createRegistry, registryLookup } from './registry.js';
|
|
4
3
|
export { blockRef, blockRefArray } from './types/block-ref.js';
|
|
5
4
|
export { ImageSchema, imageAttrs, primaryImageSource, } from './types/image.js';
|
|
@@ -1,14 +1,57 @@
|
|
|
1
|
-
import type { IdentitySigningKeys, SigningKey,
|
|
1
|
+
import type { IdentitySigningKeys, SigningKey, ConsentSnapshot, ConsentSignals } from './types.js';
|
|
2
2
|
export declare const DEFAULT_IDENTITY_TTL_SECONDS: number;
|
|
3
3
|
export declare function parseCookieHeader(value: string | null): Map<string, string>;
|
|
4
4
|
export declare function consentSignals(request: Request, cookies: Map<string, string>): ConsentSignals;
|
|
5
|
+
export declare function identityIssuancePermitted(consent: ConsentSignals, country: string, optOutCountries: readonly string[]): boolean;
|
|
5
6
|
export declare function parseConsent(raw: string, decodeCookieValue?: boolean): ConsentSnapshot | null;
|
|
6
7
|
export declare function trimConsentWhitespace(value: string): string;
|
|
7
8
|
export declare function verifyIdentityCookie(value: string, keys: IdentitySigningKeys): Promise<string | null>;
|
|
8
9
|
export declare function signIdentity(rawID: string, key: SigningKey): Promise<string>;
|
|
9
10
|
export declare function randomIdentity(random?: (length: number) => Uint8Array): string;
|
|
10
11
|
export declare function identityHashHex(namespace: string, value: string): Promise<string>;
|
|
11
|
-
export declare function sha256Hex(value: string): Promise<string>;
|
|
12
12
|
export declare function verifyClaims(value: string, keys: Record<string, string>, now: Date): Promise<Record<string, unknown> | null>;
|
|
13
|
-
export declare function
|
|
14
|
-
|
|
13
|
+
export declare function verifyClaimsEvidence(value: string, keys: Record<string, string>, now: Date): Promise<Record<string, unknown> | null>;
|
|
14
|
+
/**
|
|
15
|
+
* The minting path that signed an aci_claims value: 'aci' claims contain
|
|
16
|
+
* first-party memberships only; 'edge' claims are the minted first-party ∪
|
|
17
|
+
* external union and require a matching live b2 receipt on a
|
|
18
|
+
* provider-enabled release.
|
|
19
|
+
*/
|
|
20
|
+
export type ClaimsIssuer = 'aci' | 'edge';
|
|
21
|
+
/**
|
|
22
|
+
* Exposes the payload's `iss` marker. Malformed/unknown markers — and
|
|
23
|
+
* pre-0059 unmarked payloads — yield undefined; since the §6 cutover,
|
|
24
|
+
* verifyClaims rejects those payloads outright, so a verified payload always
|
|
25
|
+
* carries a marker. The marker identifies the minting path; it does not
|
|
26
|
+
* grant membership by itself.
|
|
27
|
+
*/
|
|
28
|
+
export declare function claimsIssuer(payload: Record<string, unknown> | null): ClaimsIssuer | undefined;
|
|
29
|
+
/** audience.MaxClaimsCookieBytes — the hard 1 KiB aci_claims budget. */
|
|
30
|
+
export declare const MAX_CLAIMS_COOKIE_BYTES = 1024;
|
|
31
|
+
/** audience.DefaultClaimsTTL — the 24-hour signed-lifetime ceiling. */
|
|
32
|
+
export declare const DEFAULT_CLAIMS_TTL_SECONDS: number;
|
|
33
|
+
/**
|
|
34
|
+
* Mint rejection: oversize, a malformed key, or a missing issuer marker.
|
|
35
|
+
* Callers fail closed on it — the edge never truncates or subsets
|
|
36
|
+
* memberships to fit (ADR 0059 §2/§3).
|
|
37
|
+
*/
|
|
38
|
+
export declare class ClaimsMintError extends Error {
|
|
39
|
+
readonly name = "ClaimsMintError";
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Mints one signed aci_claims value: v1.{kid}.{base64url(payload)}.{hmac},
|
|
43
|
+
* byte-identical to Go's ClaimsIssuer.IssueClaims — payload field order is
|
|
44
|
+
* aud (omitted when empty), seg (omitted when empty), iat, exp, iss, and the
|
|
45
|
+
* TTL clamps to the 24-hour ceiling. The exact bytes are pinned against the
|
|
46
|
+
* Go golden in claims_contract.test.ts. Issuance requires an explicit issuer
|
|
47
|
+
* marker; the marker identifies the minting path, it does not grant
|
|
48
|
+
* membership by itself.
|
|
49
|
+
*/
|
|
50
|
+
export declare function issueClaims(memberships: {
|
|
51
|
+
aud?: string[];
|
|
52
|
+
seg?: string[];
|
|
53
|
+
}, issuer: ClaimsIssuer, key: SigningKey, now: Date, ttlSeconds?: number): Promise<string>;
|
|
54
|
+
export declare function verifyHMAC(value: string, signature: string, secret: string): Promise<boolean>;
|
|
55
|
+
export declare function hmacSHA256(value: string, secret: string): Promise<string>;
|
|
56
|
+
export declare function base64URLEncode(bytes: Uint8Array): string;
|
|
57
|
+
export declare function base64URLDecode(value: string): Uint8Array;
|