@gradial/aci 0.1.52-rc.3 → 0.1.52-rc.34-e2e.1

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.
Files changed (276) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/README.md +86 -5
  3. package/dist/astro/error-page.js +1 -0
  4. package/dist/astro/index.js +4 -0
  5. package/dist/astro/page.d.ts +5 -2
  6. package/dist/astro/page.js +35 -23
  7. package/dist/astro/preview.js +2 -17
  8. package/dist/audience-data-models.d.ts +308 -194
  9. package/dist/audience-data-models.js +314 -51
  10. package/dist/cli/compile-registry.d.mts +5 -1
  11. package/dist/cli/compile-registry.mjs +31 -46
  12. package/dist/cli/mintlify-render.mjs +8 -0
  13. package/dist/cli/validate-content.d.mts +31 -1
  14. package/dist/cli/validate-content.mjs +50 -12
  15. package/dist/collect/aci.js +1 -1
  16. package/dist/collect/aci.js.sha256 +1 -1
  17. package/dist/collect/api.d.ts +6 -7
  18. package/dist/collect/api.js +21 -8
  19. package/dist/collect/assignments.d.ts +7 -9
  20. package/dist/collect/assignments.js +23 -32
  21. package/dist/collect/batcher.d.ts +9 -7
  22. package/dist/collect/batcher.js +6 -5
  23. package/dist/collect/consent/envelope.d.ts +7 -1
  24. package/dist/collect/consent/envelope.js +3 -1
  25. package/dist/collect/consent/mapping.d.ts +2 -0
  26. package/dist/collect/consent/mapping.js +1 -0
  27. package/dist/collect/consenthold.d.ts +38 -0
  28. package/dist/collect/consenthold.js +82 -0
  29. package/dist/collect/declarative.js +7 -5
  30. package/dist/collect/gapbuffer.d.ts +13 -4
  31. package/dist/collect/gapbuffer.js +21 -10
  32. package/dist/collect/index.js +67 -20
  33. package/dist/collect/pageviews.d.ts +11 -11
  34. package/dist/collect/pageviews.js +27 -22
  35. package/dist/consent-banner/index.d.ts +17 -0
  36. package/dist/consent-banner/index.js +23 -0
  37. package/dist/content/index.d.ts +2 -1
  38. package/dist/content/index.js +4 -1
  39. package/dist/content/provider.d.ts +16 -2
  40. package/dist/content/provider.js +5 -1
  41. package/dist/content/resolve-slots.d.ts +33 -4
  42. package/dist/content/resolve-slots.js +127 -19
  43. package/dist/content/types.d.ts +7 -1
  44. package/dist/edge/expression-capabilities.v1.d.ts +106 -0
  45. package/dist/edge/expression-capabilities.v1.js +165 -0
  46. package/dist/index.d.ts +1 -2
  47. package/dist/index.js +0 -1
  48. package/dist/internal/domain/edge/compose.d.ts +24 -0
  49. package/dist/internal/domain/edge/compose.js +89 -0
  50. package/dist/internal/domain/edge/identity.d.ts +5 -0
  51. package/dist/internal/domain/edge/identity.js +50 -14
  52. package/dist/internal/domain/edge/index.d.ts +2 -0
  53. package/dist/internal/domain/edge/index.js +2 -0
  54. package/dist/internal/domain/edge/mimic_token.d.ts +14 -0
  55. package/dist/internal/domain/edge/mimic_token.js +125 -0
  56. package/dist/internal/domain/edge/personalization-core.d.ts +61 -22
  57. package/dist/internal/domain/edge/personalization-core.js +789 -198
  58. package/dist/internal/domain/edge/personalization_index.d.ts +17 -0
  59. package/dist/internal/domain/edge/personalization_index.js +56 -0
  60. package/dist/internal/domain/edge/record/codec.d.ts +6 -32
  61. package/dist/internal/domain/edge/record/codec.js +86 -168
  62. package/dist/internal/domain/edge/resolve.js +76 -39
  63. package/dist/internal/domain/edge/testdata/flat_only_validator_v1.d.ts +10 -0
  64. package/dist/internal/domain/edge/testdata/flat_only_validator_v1.js +253 -0
  65. package/dist/internal/domain/edge/types.d.ts +93 -41
  66. package/dist/internal/domain/edge/types.js +3 -3
  67. package/dist/internal/domain/edge/variant_key.d.ts +3 -0
  68. package/dist/internal/domain/edge/variant_key.js +44 -0
  69. package/dist/internal/platform/collectionstore/errors.d.ts +24 -0
  70. package/dist/internal/platform/collectionstore/errors.js +48 -0
  71. package/dist/mimic/core.d.ts +2 -0
  72. package/dist/mimic/core.js +31 -0
  73. package/dist/mintlify/blocks.d.ts +6 -0
  74. package/dist/mintlify/blocks.js +201 -0
  75. package/dist/mintlify/config.d.ts +3 -0
  76. package/dist/mintlify/config.js +77 -0
  77. package/dist/mintlify/index.d.ts +3 -0
  78. package/dist/mintlify/index.js +2 -0
  79. package/dist/mintlify/json.d.ts +8 -0
  80. package/dist/mintlify/json.js +37 -0
  81. package/dist/mintlify/materialize.d.ts +14 -0
  82. package/dist/mintlify/materialize.js +254 -0
  83. package/dist/mintlify/types.d.ts +74 -0
  84. package/dist/mintlify/types.js +1 -0
  85. package/dist/mintlify/validate.d.ts +7 -0
  86. package/dist/mintlify/validate.js +256 -0
  87. package/dist/next/assignments-navigation.d.ts +4 -0
  88. package/dist/next/assignments-navigation.js +18 -0
  89. package/dist/next/assignments-script.d.ts +3 -2
  90. package/dist/next/assignments-script.js +5 -5
  91. package/dist/next/error-pages.d.ts +4 -0
  92. package/dist/next/error-pages.js +4 -0
  93. package/dist/next/error-seat-payload.d.ts +2 -1
  94. package/dist/next/error-seat-payload.js +14 -24
  95. package/dist/next/error-seat.js +7 -2
  96. package/dist/next/hosted-page-target.d.ts +7 -0
  97. package/dist/next/hosted-page-target.js +39 -0
  98. package/dist/next/index.d.ts +1 -1
  99. package/dist/next/index.js +3 -1
  100. package/dist/next/page.d.ts +29 -6
  101. package/dist/next/page.js +47 -25
  102. package/dist/next/release-context.d.ts +29 -0
  103. package/dist/next/release-context.js +55 -0
  104. package/dist/next/render.d.ts +1 -1
  105. package/dist/next/render.js +15 -5
  106. package/dist/next/server.d.ts +8 -0
  107. package/dist/next/server.js +44 -3
  108. package/dist/next/vercel-edge-projection-v1.d.ts +0 -9
  109. package/dist/next/vercel-edge-projection-v1.js +9 -539
  110. package/dist/preview/core.d.ts +1 -0
  111. package/dist/preview/core.js +27 -0
  112. package/dist/react/VideoPlayer.d.ts +3 -3
  113. package/dist/react/VideoPlayer.js +2 -2
  114. package/dist/react/index.d.ts +4 -4
  115. package/dist/react/index.js +2 -3
  116. package/dist/registry.d.ts +4 -2
  117. package/dist/testing/conformance/checks.d.ts +2 -2
  118. package/dist/testing/conformance/checks.js +2 -0
  119. package/dist/testing/conformance/index.d.ts +1 -0
  120. package/dist/testing/conformance/index.js +1 -0
  121. package/dist/testing/conformance/next-stubs.d.ts +6 -0
  122. package/dist/testing/conformance/next-stubs.js +9 -0
  123. package/dist/testing/conformance/preset.d.ts +3 -2
  124. package/dist/testing/conformance/preset.js +15 -8
  125. package/dist/testing/conformance/root-identity.d.ts +31 -0
  126. package/dist/testing/conformance/root-identity.js +361 -0
  127. package/dist/testing/conformance/stubs/next-image.d.ts +7 -0
  128. package/dist/testing/conformance/stubs/next-image.js +5 -0
  129. package/dist/testing/conformance/stubs/next-link.d.ts +7 -0
  130. package/dist/testing/conformance/stubs/next-link.js +4 -0
  131. package/dist/testing/conformance/types.d.ts +5 -2
  132. package/dist/testing/index.d.ts +1 -1
  133. package/dist/testing/index.js +4 -3
  134. package/dist/types/block-ref.d.ts +2 -0
  135. package/dist/types/block-ref.js +3 -2
  136. package/dist/types/component.d.ts +9 -0
  137. package/dist/types/config.d.ts +0 -1
  138. package/dist/types/image.d.ts +54 -17
  139. package/dist/types/image.js +102 -18
  140. package/dist/types/index.d.ts +0 -1
  141. package/dist/types/index.js +0 -1
  142. package/dist/types/media.d.ts +14 -6
  143. package/dist/types/page.d.ts +0 -1
  144. package/dist/types/video.d.ts +7 -3
  145. package/migrations/conformance-registry.md +22 -0
  146. package/package.json +21 -7
  147. package/src/cli/compile-registry.mjs +30 -42
  148. package/src/cli/mintlify-render.mjs +9 -0
  149. package/src/cli/validate-content.mjs +52 -13
  150. package/src/types/block-ref.test.ts +60 -0
  151. package/src/types/block-ref.ts +4 -2
  152. package/src/types/component.ts +10 -0
  153. package/src/types/config.ts +0 -1
  154. package/src/types/image.ts +133 -29
  155. package/src/types/index.ts +0 -1
  156. package/src/types/page.ts +0 -1
  157. package/src/types/video.ts +1 -1
  158. package/templates/astro/starter-content/src/components/chrome/Footer.astro +5 -3
  159. package/templates/astro/starter-content/src/components/chrome/Header.astro +5 -3
  160. package/templates/astro/starter-content/src/components/elements/Button.astro +5 -2
  161. package/templates/astro/starter-content/src/components/elements/ButtonBlock.astro +5 -3
  162. package/templates/astro/starter-content/src/components/sections/ContainerSection.astro +4 -3
  163. package/templates/astro/starter-content/src/components/sections/FeatureCard.astro +4 -3
  164. package/templates/astro/starter-content/src/components/sections/FeatureGrid.astro +4 -3
  165. package/templates/astro/starter-content/src/components/sections/HomeHero.astro +5 -3
  166. package/templates/astro/starter-content/src/components/sections/PersonalizationChoice.astro +4 -3
  167. package/templates/astro/starter-content/src/components/sections/StatsBar.astro +4 -3
  168. package/templates/astro/starter-content/src/fixtures/atomicBlocks.ts +7 -6
  169. package/templates/astro/starter-content/src/fixtures/composition.ts +3 -2
  170. package/templates/astro/starter-content/src/fixtures/sections.ts +3 -3
  171. package/templates/astro/starter-content/src/stories/CompositionStoryFrame.astro +7 -2
  172. package/templates/astro/template/.aci.yaml.tmpl +0 -1
  173. package/templates/astro/template/package.json.tmpl +5 -5
  174. package/templates/astro/template/src/layouts/SiteLayout.astro +2 -2
  175. package/templates/common/.agents/skills/aci/SKILL.md +58 -1
  176. package/templates/common/.agents/skills/authoring/SKILL.md +203 -43
  177. package/templates/common/.agents/skills/authoring/references/block-registry.md +19 -3
  178. package/templates/common/.agents/skills/authoring/references/block-slots.md +3 -0
  179. package/templates/common/.agents/skills/authoring/references/contracts.md +9 -30
  180. package/templates/common/.agents/skills/authoring/references/repo-structure.md +5 -4
  181. package/templates/common/.agents/skills/authoring/references/sdk-server-functions.md +3 -3
  182. package/templates/common/.agents/skills/dam-delivery/SKILL.md +217 -0
  183. package/templates/common/.agents/skills/dam-delivery/references/permalink-grammar.md +167 -0
  184. package/templates/common/.agents/skills/migration/references/canon-migration.md +18 -67
  185. package/templates/common/.agents/skills/migration/references/selector-map.md +1 -1
  186. package/templates/common/.content/fragments/navbar/_index.json +24 -0
  187. package/templates/common/.content/fragments/site-footer/_index.json +61 -0
  188. package/templates/common/.content/pages/404/_index.json +4 -2
  189. package/templates/common/.content/pages/{home/_index.json → _index.json} +10 -1
  190. package/templates/common/.content/pages/error/_index.json +4 -2
  191. package/templates/common/.content/schemas/site.schema.json +11 -1
  192. package/templates/common/.content/templates/error.json +24 -0
  193. package/templates/common/.content/templates/home.json +28 -0
  194. package/templates/common/.content/templates/site.json +8 -0
  195. package/templates/common/.content/templates/standard.json +24 -0
  196. package/templates/common/.nvmrc +1 -1
  197. package/templates/common/starter-content/.content/.rules-baseline.json +8 -0
  198. package/templates/common/starter-content/.content/config/site.json +1 -1
  199. package/templates/common/starter-content/.content/content-rules/no-public-resource-paths.json +6 -0
  200. package/templates/common/starter-content/.content/dam/README.md +74 -0
  201. package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000101}/asset.json +1 -1
  202. package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000101}/governance.json +2 -1
  203. package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000102}/asset.json +1 -1
  204. package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000102}/governance.json +2 -1
  205. package/templates/common/starter-content/.content/fragments/navbar/_index.json +23 -20
  206. package/templates/common/starter-content/.content/fragments/site-footer/_index.json +59 -56
  207. package/templates/common/starter-content/.content/pages/404/_index.json +2 -2
  208. package/templates/common/starter-content/.content/pages/{home/_index.json → _index.json} +23 -3
  209. package/templates/common/starter-content/.content/pages/about/_index.json +5 -2
  210. package/templates/common/starter-content/.content/pages/error/_index.json +2 -2
  211. package/templates/common/starter-content/.content/patterns/components/button.json +55 -0
  212. package/templates/common/starter-content/.content/patterns/components/container.json +67 -0
  213. package/templates/common/starter-content/.content/patterns/components/feature_card.json +30 -0
  214. package/templates/common/starter-content/.content/patterns/components/feature_grid.json +59 -0
  215. package/templates/common/starter-content/.content/patterns/components/home_hero.json +151 -0
  216. package/templates/common/starter-content/.content/patterns/components/personalization_choice.json +42 -0
  217. package/templates/common/starter-content/.content/patterns/components/site-footer.json +203 -0
  218. package/templates/common/starter-content/.content/patterns/components/site-navigation.json +115 -0
  219. package/templates/common/starter-content/.content/patterns/components/stats_bar.json +45 -0
  220. package/templates/common/starter-content/.content/schemas/site.schema.json +11 -1
  221. package/templates/nextjs/starter-content/src/components/chrome/Footer.tsx +4 -3
  222. package/templates/nextjs/starter-content/src/components/chrome/Header.tsx +4 -3
  223. package/templates/nextjs/starter-content/src/components/elements/Button.tsx +4 -3
  224. package/templates/nextjs/starter-content/src/components/elements/ButtonBlock.tsx +4 -3
  225. package/templates/nextjs/starter-content/src/components/sections/ContainerSection.tsx +4 -2
  226. package/templates/nextjs/starter-content/src/components/sections/FeatureCard.tsx +4 -3
  227. package/templates/nextjs/starter-content/src/components/sections/FeatureGrid.tsx +4 -2
  228. package/templates/nextjs/starter-content/src/components/sections/HomeHero.tsx +4 -3
  229. package/templates/nextjs/starter-content/src/components/sections/PersonalizationChoice.tsx +4 -2
  230. package/templates/nextjs/starter-content/src/components/sections/StatsBar.tsx +4 -3
  231. package/templates/nextjs/template/.aci.yaml +9 -0
  232. package/templates/nextjs/template/.aci.yaml.tmpl +0 -1
  233. package/templates/nextjs/template/package.json.tmpl +4 -3
  234. package/templates/nextjs/template/src/app/_components/c15t-bridge.ts +30 -0
  235. package/templates/nextjs/template/src/app/_components/c15t-consent-ui.tsx +37 -0
  236. package/templates/nextjs/template/src/app/_components/consent-manager.css +63 -0
  237. package/templates/nextjs/template/src/app/_components/consent-manager.tsx +76 -0
  238. package/templates/nextjs/template/src/app/fonts/inter/OFL.txt +93 -0
  239. package/templates/nextjs/template/src/app/fonts/inter/inter-latin.woff2 +0 -0
  240. package/templates/nextjs/template/src/app/fonts/space-grotesk/OFL.txt +93 -0
  241. package/templates/nextjs/template/src/app/fonts/space-grotesk/space-grotesk-latin.woff2 +0 -0
  242. package/templates/nextjs/template/src/app/layout.tsx +12 -7
  243. package/templates/nextjs/template/tests/conformance.test.ts.tmpl +1 -0
  244. package/dist/define-layout.d.ts +0 -6
  245. package/dist/define-layout.js +0 -14
  246. package/dist/edge/personalization-core.d.ts +0 -11
  247. package/dist/edge/personalization-core.js +0 -269
  248. package/dist/next/collect-route.d.ts +0 -19
  249. package/dist/next/collect-route.js +0 -459
  250. package/dist/next/envelope-digest.d.ts +0 -21
  251. package/dist/next/envelope-digest.js +0 -58
  252. package/dist/next/middleware.d.ts +0 -40
  253. package/dist/next/middleware.js +0 -475
  254. package/dist/next/personalization-host.d.ts +0 -134
  255. package/dist/next/personalization-host.js +0 -270
  256. package/dist/next/root-layout.d.ts +0 -4
  257. package/dist/next/root-layout.js +0 -5
  258. package/dist/next/vercel-collect-sdk-route.d.ts +0 -27
  259. package/dist/next/vercel-collect-sdk-route.js +0 -181
  260. package/dist/next/vercel-personalization.d.ts +0 -4
  261. package/dist/next/vercel-personalization.js +0 -4
  262. package/dist/next/vercel-s3-personalization.d.ts +0 -79
  263. package/dist/next/vercel-s3-personalization.js +0 -570
  264. package/dist/types/layout.d.ts +0 -24
  265. package/src/types/layout.ts +0 -29
  266. package/templates/astro/starter-content/src/render/RenderPage.astro +0 -67
  267. package/templates/astro/template/src/cms/contracts/layouts/index.ts +0 -18
  268. package/templates/nextjs/starter-content/src/components/elements/AtomicBlock.tsx +0 -13
  269. package/templates/nextjs/template/src/cms/contracts/layouts/index.ts +0 -16
  270. /package/dist/{types/layout.js → cli/mintlify-render.d.mts} +0 -0
  271. /package/templates/common/.content/overlays/audience/preference-blue/pages/{home/_index.json → _index.json} +0 -0
  272. /package/templates/common/.content/overlays/audience/preference-red/pages/{home/_index.json → _index.json} +0 -0
  273. /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000101}/editorial.json +0 -0
  274. /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000101}/versions/v0001.json +0 -0
  275. /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000102}/editorial.json +0 -0
  276. /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000102}/versions/v0001.json +0 -0
@@ -0,0 +1,17 @@
1
+ import type { PersonalizationExperiment, PersonalizationRoute, PersonalizationVariant } from './types.js';
2
+ export interface AuthoredCandidate {
3
+ readonly key: string;
4
+ readonly variant: PersonalizationVariant;
5
+ readonly values: Record<string, string>;
6
+ readonly experiments: readonly PersonalizationExperiment[];
7
+ }
8
+ export interface PersonalizationSelection {
9
+ readonly sourceExperiments: Record<string, PersonalizationExperiment> | undefined;
10
+ readonly authored: readonly AuthoredCandidate[];
11
+ readonly experiments: readonly PersonalizationExperiment[];
12
+ readonly arms: Readonly<Record<string, Readonly<Record<string, PersonalizationVariant>>>>;
13
+ readonly tuples: Readonly<Record<string, PersonalizationVariant>>;
14
+ readonly legacyExperimentExclusions: number;
15
+ }
16
+ export declare function preparePersonalizationRoute(route: PersonalizationRoute, experiments?: Record<string, PersonalizationExperiment>): PersonalizationRoute;
17
+ export declare function personalizationSelection(route: PersonalizationRoute, experiments?: Record<string, PersonalizationExperiment>): PersonalizationSelection;
@@ -0,0 +1,56 @@
1
+ import { variantValuesFromKey } from './record/codec.js';
2
+ import { compareUTF8 } from './variant_key.js';
3
+ const preparedSelection = Symbol('prepared personalization selection');
4
+ // Call once when an immutable partition is decoded. The derived index is a
5
+ // non-enumerable symbol property, so it cannot alter any serialized record.
6
+ export function preparePersonalizationRoute(route, experiments) {
7
+ const existing = route[preparedSelection];
8
+ if (existing && existing.sourceExperiments === experiments)
9
+ return route;
10
+ return Object.freeze(Object.defineProperty({ ...route }, preparedSelection, { value: deriveSelection(route, experiments) }));
11
+ }
12
+ export function personalizationSelection(route, experiments) {
13
+ return preparePersonalizationRoute(route, experiments)[preparedSelection];
14
+ }
15
+ function deriveSelection(route, experiments) {
16
+ const authored = [];
17
+ const arms = Object.create(null);
18
+ const legacy = new Set();
19
+ const qualified = new Set();
20
+ for (const [key, variant] of Object.entries(route.variants || {})) {
21
+ const values = Object.freeze({ ...(variant.variantValues || variantValuesFromKey(key)) });
22
+ // DEBT(edge-functions): ADR-0045 bounded pair reader and counter. Remove
23
+ // only when every retained release in every tenant compiles under the
24
+ // post-removal compiler; pair entries then become malformed.
25
+ if (isPairVariant(key, values)) {
26
+ const id = values.experiment || key.split(';').find((part) => part.startsWith('experiment='))?.slice('experiment='.length);
27
+ if (id && experiments?.[id])
28
+ legacy.add(id);
29
+ continue;
30
+ }
31
+ const names = Object.keys(values);
32
+ const ids = names.filter((name) => name.startsWith('experiment.')).map((name) => name.slice('experiment.'.length));
33
+ for (const id of ids)
34
+ qualified.add(id);
35
+ if (ids.length === 1 && names.length === 1) {
36
+ const id = ids[0];
37
+ (arms[id] ||= Object.create(null))[values[`experiment.${id}`]] = variant;
38
+ }
39
+ const factors = ids.map((id) => experiments?.[id]);
40
+ if (factors.some((item) => !item || item.kind !== 'xt' || item.status !== 'running'))
41
+ continue;
42
+ authored.push(Object.freeze({ key, variant, values, experiments: Object.freeze(factors) }));
43
+ }
44
+ for (const id of qualified)
45
+ legacy.delete(id);
46
+ authored.sort((left, right) => (right.variant.priority || 0) - (left.variant.priority || 0) || compareUTF8(left.key, right.key));
47
+ const scoped = Object.keys(experiments || {}).sort(compareUTF8).map((id) => experiments[id])
48
+ .filter((item) => (item.kind === 'ab' || item.kind === 'abn') && item.status === 'running' && !legacy.has(item.id));
49
+ for (const entries of Object.values(arms))
50
+ Object.freeze(entries);
51
+ return Object.freeze({ sourceExperiments: experiments, authored: Object.freeze(authored), experiments: Object.freeze(scoped), arms: Object.freeze(arms), tuples: route.variants || {}, legacyExperimentExclusions: legacy.size });
52
+ }
53
+ function isPairVariant(key, values) {
54
+ const names = [...key.split(';').map((part) => part.split('=')[0]), ...Object.keys(values)];
55
+ return names.some((name) => name.toLowerCase() === 'experiment' || name.toLowerCase() === 'experimentarm');
56
+ }
@@ -1,4 +1,4 @@
1
- import type { EdgeRouteEntry, ClassificationData } from '../types.js';
1
+ import type { EdgeRouteEntry } from '../types.js';
2
2
  /**
3
3
  * Unique sentinel object returned by expand functions on failure.
4
4
  * Callers check `result === INVALID`. Never throws.
@@ -10,14 +10,17 @@ interface CompactDispatch {
10
10
  ap: string;
11
11
  }
12
12
  interface CompactCondition {
13
- f: string;
14
- o: string;
13
+ f?: string;
14
+ o?: string;
15
15
  w?: unknown;
16
+ a?: CompactCondition[];
17
+ n?: CompactCondition[];
16
18
  }
17
19
  interface CompactRule {
18
20
  a?: CompactCondition[];
19
21
  n?: CompactCondition[];
20
22
  }
23
+ export declare const COMPACT_MAX_DEPTH = 32;
21
24
  interface CompactVariant {
22
25
  pr?: number;
23
26
  r?: CompactRule;
@@ -34,35 +37,6 @@ export interface CompactRouteRecord {
34
37
  }
35
38
  export declare function projectRouteRecord(entry: EdgeRouteEntry): CompactRouteRecord;
36
39
  export declare function expandRouteRecord(raw: unknown): EdgeRouteEntry | Invalid;
37
- export interface CompactClassificationData {
38
- au?: Record<string, {
39
- r?: CompactRule;
40
- }>;
41
- sg?: Record<string, {
42
- r?: CompactRule;
43
- }>;
44
- x?: Record<string, CompactExperiment>;
45
- }
46
- interface CompactExperimentArm {
47
- id: string;
48
- ab?: number;
49
- vk?: string;
50
- ro?: string;
51
- }
52
- interface CompactExperiment {
53
- id: string;
54
- st?: string;
55
- k?: string;
56
- av?: string;
57
- sl?: string;
58
- pr?: number;
59
- ar?: CompactExperimentArm[];
60
- dn?: string;
61
- pg?: string;
62
- gl?: string[];
63
- }
64
- export declare function projectClassificationData(data: ClassificationData): CompactClassificationData;
65
- export declare function expandClassificationData(raw: unknown): ClassificationData | Invalid;
66
40
  export declare const MARKER = "{\"s\":1,\"e\":1}";
67
41
  export declare function isMarker(raw: string): boolean;
68
42
  export declare function canonicalSerialize(value: unknown): string;
@@ -1,4 +1,4 @@
1
- // Compact JSON codec for edge-decisioning route records and classification data.
1
+ // Compact JSON codec for edge-decisioning route records.
2
2
  //
3
3
  // project(): canonical → compact (short field names via alias table, omit defaults)
4
4
  // expand(): compact → canonical (reverse, never throws — returns INVALID sentinel on failure)
@@ -41,21 +41,13 @@ const DISPATCH_KIND_FROM_COMPACT = {
41
41
  };
42
42
  const OPERATOR_TO_COMPACT = {
43
43
  equals: 'eq', contains: 'ct', startsWith: 'sw', exists: 'ex',
44
+ greaterThan: 'gt', greaterThanOrEqual: 'ge', lessThan: 'lt', lessThanOrEqual: 'le',
45
+ before: 'bf', after: 'af', between: 'bt', in: 'in',
44
46
  };
45
47
  const OPERATOR_FROM_COMPACT = {
46
48
  eq: 'equals', ct: 'contains', sw: 'startsWith', ex: 'exists',
47
- };
48
- const EXPERIMENT_STATUS_TO_COMPACT = {
49
- running: 'r', paused: 'p', completed: 'd',
50
- };
51
- const EXPERIMENT_STATUS_FROM_COMPACT = {
52
- r: 'running', p: 'paused', d: 'completed',
53
- };
54
- const EXPERIMENT_KIND_TO_COMPACT = {
55
- ab: 'a', abn: 'n',
56
- };
57
- const EXPERIMENT_KIND_FROM_COMPACT = {
58
- a: 'ab', n: 'abn',
49
+ gt: 'greaterThan', ge: 'greaterThanOrEqual', lt: 'lessThan', le: 'lessThanOrEqual',
50
+ bf: 'before', af: 'after', bt: 'between', in: 'in',
59
51
  };
60
52
  // Compact type guard — reduces minified bytes vs repeated typeof+null+isArray checks
61
53
  function isObj(v) {
@@ -78,20 +70,89 @@ function expandDispatch(raw) {
78
70
  return INVALID;
79
71
  return { kind, artifactPath };
80
72
  }
81
- function projectCondition(cond) {
82
- if (!cond || !cond.field || !cond.operator)
83
- return null;
73
+ // Structural recursion guard, deliberately looser than the authored MaxDepth
74
+ // (5) the validators enforce. The codec's job is to bound adversarial
75
+ // recursion in a byte-constrained runtime; the authored contract is
76
+ // validation's. Keeping it looser is what lets an over-depth expression
77
+ // round-trip and be rejected by validation identically in every runtime,
78
+ // rather than being erased by the codec first (ADR 0040).
79
+ export const COMPACT_MAX_DEPTH = 32;
80
+ // A member carrying all/any is an envelope, not a condition — the same
81
+ // presence rule the evaluators apply, so the codec cannot disagree with them
82
+ // about what a member is.
83
+ function isGroupMember(cond) {
84
+ return !!cond && (cond.all !== undefined || cond.any !== undefined);
85
+ }
86
+ function projectCondition(cond, depth) {
87
+ // Projection runs at publish time in a trusted context behind write-time
88
+ // validation: a malformed condition or an operator with no compact token is
89
+ // vocabulary/codec drift, and silently dropping the condition would ship a
90
+ // rule missing a leaf — MORE permissive than authored (ADR 0038). The same
91
+ // reasoning covers a group node: dropping one publishes a rule the author
92
+ // did not write. Expansion stays fail-closed for already-deployed bundles.
93
+ if (!cond) {
94
+ throw new Error('edge rule condition must name a field and operator');
95
+ }
96
+ if (isGroupMember(cond)) {
97
+ if (depth > COMPACT_MAX_DEPTH) {
98
+ throw new Error('edge rule nests deeper than the codec can project');
99
+ }
100
+ if (cond.field !== undefined || cond.operator !== undefined || cond.value !== undefined) {
101
+ throw new Error('edge rule member mixes group and leaf keys');
102
+ }
103
+ const group = {};
104
+ if (cond.all && cond.all.length > 0)
105
+ group.a = cond.all.map((member) => projectCondition(member, depth + 1));
106
+ if (cond.any && cond.any.length > 0)
107
+ group.n = cond.any.map((member) => projectCondition(member, depth + 1));
108
+ if (!group.a && !group.n) {
109
+ throw new Error('edge rule group must include at least one member');
110
+ }
111
+ return group;
112
+ }
113
+ if (!cond.field || !cond.operator) {
114
+ throw new Error('edge rule condition must name a field and operator');
115
+ }
84
116
  const compactOp = OPERATOR_TO_COMPACT[cond.operator];
85
- if (!compactOp)
86
- return null;
117
+ if (!compactOp) {
118
+ throw new Error(`edge rule operator has no compact token: ${cond.operator}`);
119
+ }
87
120
  const result = { f: cond.field, o: compactOp };
88
- if (cond.operator !== 'exists' && cond.value !== undefined)
121
+ if (cond.value !== undefined)
89
122
  result.w = cond.value;
90
123
  return result;
91
124
  }
92
- function expandCondition(raw) {
125
+ function expandCondition(raw, depth) {
93
126
  if (!isObj(raw))
94
127
  return INVALID;
128
+ if (raw.a !== undefined || raw.n !== undefined) {
129
+ if (depth > COMPACT_MAX_DEPTH)
130
+ return INVALID;
131
+ // A member cannot be both: expanding a mixed record would hand the
132
+ // evaluator something neither a group nor a condition.
133
+ if (raw.f !== undefined || raw.o !== undefined || raw.w !== undefined)
134
+ return INVALID;
135
+ const group = {};
136
+ for (const [compact, key] of [['a', 'all'], ['n', 'any']]) {
137
+ if (raw[compact] === undefined)
138
+ continue;
139
+ if (!Array.isArray(raw[compact]))
140
+ return INVALID;
141
+ const members = [];
142
+ for (const member of raw[compact]) {
143
+ const expanded = expandCondition(member, depth + 1);
144
+ if (expanded === INVALID)
145
+ return INVALID;
146
+ members.push(expanded);
147
+ }
148
+ group[key] = members;
149
+ }
150
+ // Length, not truthiness: [] is truthy, so a group whose only list is
151
+ // empty would otherwise expand into a member with no predicate at all.
152
+ if ((group.all?.length || 0) + (group.any?.length || 0) === 0)
153
+ return INVALID;
154
+ return group;
155
+ }
95
156
  const f = raw.f;
96
157
  const co = raw.o;
97
158
  if (typeof f !== 'string')
@@ -100,7 +161,7 @@ function expandCondition(raw) {
100
161
  if (!op)
101
162
  return INVALID;
102
163
  const c = { field: f, operator: op };
103
- if (op !== 'exists' && raw.w !== undefined)
164
+ if (raw.w !== undefined)
104
165
  c.value = raw.w;
105
166
  return c;
106
167
  }
@@ -109,9 +170,9 @@ function projectRule(rule) {
109
170
  return undefined;
110
171
  const result = {};
111
172
  if (rule.all && rule.all.length > 0)
112
- result.a = rule.all.map(projectCondition).filter((c) => c !== null);
173
+ result.a = rule.all.map((cond) => projectCondition(cond, 1));
113
174
  if (rule.any && rule.any.length > 0)
114
- result.n = rule.any.map(projectCondition).filter((c) => c !== null);
175
+ result.n = rule.any.map((cond) => projectCondition(cond, 1));
115
176
  if (!result.a && !result.n)
116
177
  return undefined;
117
178
  return result;
@@ -124,7 +185,7 @@ function expandRule(raw) {
124
185
  const rule = {};
125
186
  if (Array.isArray(raw.a))
126
187
  for (const c of raw.a) {
127
- const r = expandCondition(c);
188
+ const r = expandCondition(c, 1);
128
189
  if (r === INVALID)
129
190
  return INVALID;
130
191
  if (r)
@@ -132,7 +193,7 @@ function expandRule(raw) {
132
193
  }
133
194
  if (Array.isArray(raw.n))
134
195
  for (const c of raw.n) {
135
- const r = expandCondition(c);
196
+ const r = expandCondition(c, 1);
136
197
  if (r === INVALID)
137
198
  return INVALID;
138
199
  if (r)
@@ -218,149 +279,6 @@ export function expandRouteRecord(raw) {
218
279
  }
219
280
  return entry;
220
281
  }
221
- export function projectClassificationData(data) {
222
- const result = {};
223
- if (data.audiences && Object.keys(data.audiences).length > 0) {
224
- result.au = {};
225
- for (const [key, def] of Object.entries(data.audiences)) {
226
- const entry = {};
227
- const rule = projectRule(def.rule);
228
- if (rule)
229
- entry.r = rule;
230
- result.au[key] = entry;
231
- }
232
- }
233
- if (data.segments && Object.keys(data.segments).length > 0) {
234
- result.sg = {};
235
- for (const [key, def] of Object.entries(data.segments)) {
236
- const entry = {};
237
- const rule = projectRule(def.rule);
238
- if (rule)
239
- entry.r = rule;
240
- result.sg[key] = entry;
241
- }
242
- }
243
- if (data.experiments && Object.keys(data.experiments).length > 0) {
244
- result.x = {};
245
- for (const [key, exp] of Object.entries(data.experiments))
246
- result.x[key] = projectExperiment(exp);
247
- }
248
- return result;
249
- }
250
- function projectExperiment(exp) {
251
- const result = { id: exp.id };
252
- if (exp.status) {
253
- const c = EXPERIMENT_STATUS_TO_COMPACT[exp.status];
254
- if (c)
255
- result.st = c;
256
- }
257
- if (exp.kind) {
258
- const c = EXPERIMENT_KIND_TO_COMPACT[exp.kind];
259
- if (c)
260
- result.k = c;
261
- }
262
- if (exp.allocationVersion)
263
- result.av = exp.allocationVersion;
264
- if (exp.salt)
265
- result.sl = exp.salt;
266
- if (exp.priority)
267
- result.pr = exp.priority;
268
- if (exp.arms && exp.arms.length > 0) {
269
- result.ar = exp.arms.map((arm) => {
270
- const ca = { id: arm.id };
271
- if (arm.allocationBasisPoints)
272
- ca.ab = arm.allocationBasisPoints;
273
- if (arm.variantKey)
274
- ca.vk = arm.variantKey;
275
- return ca;
276
- });
277
- }
278
- return result;
279
- }
280
- export function expandClassificationData(raw) {
281
- if (!isObj(raw))
282
- return INVALID;
283
- const obj = raw;
284
- const data = { audiences: {}, segments: {}, experiments: {} };
285
- if (obj.au !== undefined) {
286
- if (!isObj(obj.au))
287
- return INVALID;
288
- for (const [key, defRaw] of Object.entries(obj.au)) {
289
- if (!isObj(defRaw))
290
- return INVALID;
291
- const ruleResult = expandRule(defRaw.r);
292
- if (ruleResult === INVALID)
293
- return INVALID;
294
- data.audiences[key] = { rule: ruleResult || { all: [] } };
295
- }
296
- }
297
- if (obj.sg !== undefined) {
298
- if (!isObj(obj.sg))
299
- return INVALID;
300
- for (const [key, defRaw] of Object.entries(obj.sg)) {
301
- if (!isObj(defRaw))
302
- return INVALID;
303
- const ruleResult = expandRule(defRaw.r);
304
- if (ruleResult === INVALID)
305
- return INVALID;
306
- data.segments[key] = { rule: ruleResult || { all: [] } };
307
- }
308
- }
309
- if (obj.x !== undefined) {
310
- if (!isObj(obj.x))
311
- return INVALID;
312
- for (const [key, expRaw] of Object.entries(obj.x)) {
313
- const expResult = expandExperiment(expRaw);
314
- if (expResult === INVALID)
315
- return INVALID;
316
- data.experiments[key] = expResult;
317
- }
318
- }
319
- return data;
320
- }
321
- function expandExperiment(raw) {
322
- if (!isObj(raw))
323
- return INVALID;
324
- const obj = raw;
325
- const id = obj.id;
326
- if (typeof id !== 'string')
327
- return INVALID;
328
- const exp = { id, status: 'running', kind: 'ab', arms: [] };
329
- if (typeof obj.st === 'string') {
330
- const expanded = EXPERIMENT_STATUS_FROM_COMPACT[obj.st];
331
- if (!expanded)
332
- return INVALID;
333
- exp.status = expanded;
334
- }
335
- if (typeof obj.k === 'string') {
336
- const expanded = EXPERIMENT_KIND_FROM_COMPACT[obj.k];
337
- if (!expanded)
338
- return INVALID;
339
- exp.kind = expanded;
340
- }
341
- if (typeof obj.av === 'string')
342
- exp.allocationVersion = obj.av;
343
- if (typeof obj.sl === 'string')
344
- exp.salt = obj.sl;
345
- if (typeof obj.pr === 'number')
346
- exp.priority = obj.pr;
347
- if (Array.isArray(obj.ar)) {
348
- exp.arms = [];
349
- for (const armRaw of obj.ar) {
350
- if (!isObj(armRaw))
351
- return INVALID;
352
- const armObj = armRaw;
353
- if (typeof armObj.id !== 'string')
354
- return INVALID;
355
- exp.arms.push({
356
- id: armObj.id,
357
- allocationBasisPoints: typeof armObj.ab === 'number' ? armObj.ab : 0,
358
- variantKey: typeof armObj.vk === 'string' ? armObj.vk : '',
359
- });
360
- }
361
- }
362
- return exp;
363
- }
364
282
  // ── Marker (tri-state: record | marker | absent) ─────────────────────
365
283
  export const MARKER = '{"s":1,"e":1}';
366
284
  export function isMarker(raw) {
@@ -1,58 +1,91 @@
1
1
  // resolvePersonalizationRequest — the edge decisioning entry point.
2
2
  //
3
- // Reads cookies for classification but never writes them (R25: consent-gated
4
- // identity model). Identity minting happens in the collect/consent endpoint,
5
- // not here. Public personalized responses may be private while providers cache
6
- // the selected immutable artifact by release and exact artifact path.
3
+ // Reads cookies for classification but never writes them. It may issue a
4
+ // first-party identity in memory when the host permits (ADR 0048); persisting
5
+ // that identity is the host's job. Public personalized responses may be
6
+ // private while providers cache the selected immutable artifact by release and
7
+ // exact artifact path.
7
8
  import { resolvePersonalizationDecision, } from './personalization-core.js';
8
- import { consentSignals, verifyIdentityCookie, identityHashHex, verifyClaims, parseCookieHeader, } from './identity.js';
9
+ import { consentSignals, verifyIdentityCookie, identityHashHex, randomIdentity, verifyClaims, parseCookieHeader, } from './identity.js';
9
10
  export async function resolvePersonalizationRequest(request, config) {
10
11
  const cookies = parseCookieHeader(request.headers.get('cookie'));
11
12
  const consent = consentSignals(request, cookies);
12
13
  const now = (config.now ?? (() => new Date()))();
13
- // Consent-gated identity model (R25): static artifact selection NEVER mints
14
- // identity. It reads cookies for classification but never writes them.
15
- // Identity (aci_id) is minted by the collect/consent endpoint after
16
- // explicit consent. This keeps all content responses cacheable and is
17
- // GDPR-compliant (no non-essential cookie before consent).
14
+ // Identity model (ADR 0016 as amended by ADR 0048): experiment bucketing is
15
+ // measurement, keyed by the first-party aci_id. A verified cookie (or the
16
+ // provider bootstrap's identity) is used as presented. With none usable, and
17
+ // only when the host's issuance rule permits it for this request, resolve
18
+ // issues a fresh identity so the request that issues it is also bucketed —
19
+ // an unverifiable cookie is replaced the same way. Persisting the issued
20
+ // identity is the host's decision (page responses only, never shared-cached).
21
+ // Claims and memberships stay gated on the personalization grant.
18
22
  //
19
- // GPC/DNT deny fully: no read, no identity, no experiment bucketing.
20
- const rawIdentity = consent.privacyDenied
23
+ // GPC/DNT deny fully: no read, no identity, no issuance, no bucketing.
24
+ //
25
+ // Mimic (specs/features/audience-mimic): a validated mimicClaims input
26
+ // bypasses identity resolution entirely — the session reads no aci_id and
27
+ // no aci_claims (D-2/D-7), so identityHash stays empty and the experiment
28
+ // tier is structurally skipped (D-5). An ARMS-bearing token is the D-17
29
+ // exception: the experiment tier runs in forced mode — the token's named
30
+ // arm replaces the dice for each experiment the request selects through
31
+ // the ordinary gate — and identity still never exists (I-17).
32
+ const mimic = config.mimicClaims;
33
+ const verifiedVisitor = mimic || consent.privacyDenied ? undefined : config.verifiedVisitor;
34
+ const presentedIdentity = mimic || consent.privacyDenied
21
35
  ? null
22
- : await verifyIdentityCookie(cookies.get('aci_id') || '', config.identityKeys);
36
+ : verifiedVisitor
37
+ ? verifiedVisitor.rawIdentity
38
+ : await verifyIdentityCookie(cookies.get('aci_id') || '', config.identityKeys);
39
+ const issuedIdentity = !presentedIdentity && !mimic && !consent.privacyDenied && config.issueIdentity
40
+ ? randomIdentity(config.randomBytes)
41
+ : undefined;
42
+ const rawIdentity = presentedIdentity || issuedIdentity || null;
23
43
  // The identity hash feeds experiment bucketing for identified visitors.
24
- // Claims are a signed cookie written by /collect; the EdgeRouter
25
- // never reads the customer object store to refresh or revoke them.
26
- let signedClaims = cookies.get('aci_claims') || '';
44
+ // Claims are a signed cookie written by /collect or the provider identity
45
+ // bootstrap; the EdgeRouter never reads the customer object store to
46
+ // refresh or revoke them.
27
47
  let identityHash = '';
28
48
  if (rawIdentity) {
29
49
  identityHash = await identityHashHex('aci_id', rawIdentity);
30
50
  }
31
- if (rawIdentity && consent.allowsIdentityTier && signedClaims) {
32
- if (!await verifyClaims(signedClaims, config.claimsKeys || {}, now)) {
33
- signedClaims = '';
34
- }
35
- }
36
51
  const matchedRoute = config.route;
37
52
  let variantKey = '';
38
53
  if (matchedRoute) {
39
- const claims = consent.allowsIdentityTier
40
- ? await verifyClaims(signedClaims, config.claimsKeys || {}, now)
41
- : null;
42
- const decision = resolvePersonalizationDecision(toPersonalizationRequestContext(request), matchedRoute, claims, config.experiments, identityHash
54
+ const claims = mimic
55
+ ? { aud: mimic.aud, seg: mimic.seg, iat: 0, exp: 0 }
56
+ : consent.allowsIdentityTier
57
+ ? verifiedVisitor
58
+ ? verifiedVisitor.claims
59
+ : await verifyClaims(cookies.get('aci_claims') || '', config.claimsKeys || {}, now)
60
+ : null;
61
+ const decision = resolvePersonalizationDecision(toPersonalizationRequestContext(request, now, config.requestGeo, config.onRuleRejected), matchedRoute, claims, config.experiments, identityHash
43
62
  ? { usable: true, siteId: config.siteId, namespace: 'aci_id', identityHash }
44
- : undefined);
63
+ : undefined, mimic?.arms);
45
64
  if (decision.variant) {
46
65
  variantKey = decision.variant.variantKey;
47
66
  }
48
- const experiment = decision.experiment
49
- ? { id: decision.experiment.experimentId, arm: decision.experiment.armId, allocationVersion: decision.experiment.allocationVersion }
50
- : undefined;
51
- return { variantKey, experiment };
67
+ const experiments = decision.experiments.map((item) => ({
68
+ id: item.experimentId,
69
+ arm: item.armId,
70
+ allocationVersion: item.allocationVersion,
71
+ ...(item.forced ? { forced: true } : {}),
72
+ }));
73
+ return {
74
+ variantKey,
75
+ experiments,
76
+ ...(decision.legacyExperimentExclusions ? { legacyExperimentExclusions: decision.legacyExperimentExclusions } : {}),
77
+ ...(issuedIdentity ? { issuedIdentity } : {}),
78
+ };
52
79
  }
53
- return { variantKey };
80
+ return { variantKey, experiments: [], ...(issuedIdentity ? { issuedIdentity } : {}) };
54
81
  }
55
- function toPersonalizationRequestContext(request) {
82
+ // The return type is annotated rather than inferred so the contract is stated
83
+ // at the construction site: a misspelled property would then silently never
84
+ // fire at the sink, which is the exact failure mode this context exists to
85
+ // make visible. No tsconfig covers internal/domain/** today (esbuild/tsx strip
86
+ // types without checking), so the annotation is documentation now and becomes
87
+ // real protection under any future typecheck of these trees.
88
+ function toPersonalizationRequestContext(request, now, requestGeo, onRuleRejected) {
56
89
  const url = new URL(request.url);
57
90
  const cookies = parseCookieHeader(request.headers.get('cookie'));
58
91
  const query = {};
@@ -60,17 +93,21 @@ function toPersonalizationRequestContext(request) {
60
93
  (query[key] ||= []).push(value);
61
94
  });
62
95
  const headers = Object.fromEntries(request.headers.entries());
96
+ // geo.* facts come only from the host's trusted geo. Reading provider geo
97
+ // headers here trusted whatever the viewer sent on every lane whose
98
+ // provider does not stamp that exact header before the decision runs.
99
+ const geo = Object.fromEntries(Object.entries(requestGeo ?? {})
100
+ .filter((entry) => typeof entry[1] === 'string' && entry[1] !== ''));
63
101
  return {
64
102
  path: url.pathname,
65
103
  query,
66
104
  headers,
67
105
  cookies: Object.fromEntries(cookies.entries()),
68
- signals: {
69
- geo: {
70
- country: headers['x-vercel-ip-country'] || headers['cloudfront-viewer-country'] || '',
71
- region: headers['x-vercel-ip-country-region'] || headers['cloudfront-viewer-country-region'] || '',
72
- city: headers['x-vercel-ip-city'] || headers['cloudfront-viewer-city'] || '',
73
- },
74
- },
106
+ // The host's pinned per-request clock resolves the time.now fact
107
+ // (ADR 0038), so claims verification and window evaluation read one
108
+ // instant — and config.now-injected tests are deterministic.
109
+ now: now.getTime(),
110
+ ...(Object.keys(geo).length > 0 ? { signals: { geo } } : {}),
111
+ ...(onRuleRejected ? { onRuleRejected } : {}),
75
112
  };
76
113
  }
@@ -0,0 +1,10 @@
1
+ export interface FrozenExpressionDiagnostic {
2
+ code: string;
3
+ path: string;
4
+ scope: 'request';
5
+ message: string;
6
+ }
7
+ export declare function frozenValidateRequestExpression(rule: {
8
+ all?: unknown[];
9
+ any?: unknown[];
10
+ }): FrozenExpressionDiagnostic[];