@gradial/aci 0.1.48 → 0.1.51-ssr.2

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 (109) hide show
  1. package/README.md +13 -20
  2. package/dist/astro/assets.d.ts +6 -6
  3. package/dist/astro/assets.js +6 -6
  4. package/dist/astro/index.d.ts +0 -2
  5. package/dist/astro/index.js +0 -4
  6. package/dist/cli/emit-error-pages.mjs +0 -1
  7. package/dist/cli/verify-next-cdn-routes.mjs +3 -4
  8. package/dist/collect/aci.js +1 -1
  9. package/dist/collect/aci.js.sha256 +1 -1
  10. package/dist/collect/webvitals.d.ts +0 -3
  11. package/dist/collect/webvitals.js +11 -21
  12. package/dist/content/cache.d.ts +1 -9
  13. package/dist/content/cache.js +2 -37
  14. package/dist/content/error-pages.d.ts +1 -2
  15. package/dist/content/index.d.ts +0 -1
  16. package/dist/content/index.js +0 -1
  17. package/dist/index.d.ts +0 -1
  18. package/dist/internal/domain/edge/identity.d.ts +14 -0
  19. package/dist/internal/domain/edge/identity.js +214 -0
  20. package/dist/internal/domain/edge/index.d.ts +4 -0
  21. package/dist/internal/domain/edge/index.js +6 -0
  22. package/dist/internal/domain/edge/personalization-core.d.ts +24 -0
  23. package/dist/{edge → internal/domain/edge}/personalization-core.js +165 -64
  24. package/dist/internal/domain/edge/record/codec.d.ts +71 -0
  25. package/dist/internal/domain/edge/record/codec.js +401 -0
  26. package/dist/internal/domain/edge/resolve.d.ts +2 -0
  27. package/dist/internal/domain/edge/resolve.js +76 -0
  28. package/dist/{next/personalization-host.d.ts → internal/domain/edge/types.d.ts} +110 -61
  29. package/dist/internal/domain/edge/types.js +7 -0
  30. package/dist/internal/platform/collectionstore/errors.d.ts +5 -0
  31. package/dist/internal/platform/collectionstore/errors.js +7 -0
  32. package/dist/next/config.d.ts +0 -8
  33. package/dist/next/config.js +3 -78
  34. package/dist/next/error-pages.d.ts +2 -3
  35. package/dist/next/error-pages.js +5 -5
  36. package/dist/next/error-seat.d.ts +2 -3
  37. package/dist/next/index.d.ts +2 -2
  38. package/dist/next/index.js +1 -2
  39. package/dist/next/page.d.ts +3 -13
  40. package/dist/next/page.js +39 -51
  41. package/dist/next/server.d.ts +12 -32
  42. package/dist/next/server.js +66 -295
  43. package/dist/providers/object.d.ts +24 -0
  44. package/dist/providers/object.js +105 -0
  45. package/dist/providers/vercel-object-reader.d.ts +20 -0
  46. package/dist/providers/vercel-object-reader.js +45 -0
  47. package/dist/testing/conformance/checks.d.ts +1 -1
  48. package/dist/testing/conformance/checks.js +14 -144
  49. package/dist/testing/conformance/index.d.ts +1 -1
  50. package/dist/testing/conformance/index.js +1 -1
  51. package/dist/testing/conformance/preset.js +1 -1
  52. package/dist/testing/conformance/types.d.ts +1 -1
  53. package/dist/types/config.d.ts +0 -4
  54. package/dist/types/index.d.ts +0 -2
  55. package/dist/types/index.js +0 -2
  56. package/dist/types/page.d.ts +0 -10
  57. package/package.json +11 -35
  58. package/src/cli/emit-error-pages.mjs +0 -1
  59. package/src/cli/verify-next-cdn-routes.mjs +8 -11
  60. package/src/types/config.ts +0 -5
  61. package/src/types/index.ts +0 -2
  62. package/src/types/page.ts +0 -11
  63. package/templates/astro/template/.aci.yaml.tmpl +0 -11
  64. package/templates/common/.agents/skills/aci/SKILL.md +8 -9
  65. package/templates/common/.agents/skills/authoring/SKILL.md +3 -4
  66. package/templates/common/.agents/skills/authoring/references/block-registry.md +13 -36
  67. package/templates/common/.agents/skills/authoring/references/contracts.md +10 -17
  68. package/templates/common/.agents/skills/authoring/references/repo-structure.md +2 -2
  69. package/templates/common/.agents/skills/authoring/references/sdk-server-functions.md +45 -95
  70. package/templates/common/.agents/skills/migration/references/canon-migration.md +17 -37
  71. package/templates/nextjs/template/.aci.yaml.tmpl +0 -11
  72. package/templates/nextjs/template/README.md.tmpl +0 -1
  73. package/templates/nextjs/template/src/app/[[...slug]]/page.tsx +1 -1
  74. package/dist/content/assets.d.ts +0 -18
  75. package/dist/content/assets.js +0 -66
  76. package/dist/edge/personalization-core.d.ts +0 -11
  77. package/dist/internal/render-proof.d.ts +0 -1
  78. package/dist/internal/render-proof.js +0 -197
  79. package/dist/next/asset-route.d.ts +0 -10
  80. package/dist/next/asset-route.js +0 -45
  81. package/dist/next/collect-route.d.ts +0 -19
  82. package/dist/next/collect-route.js +0 -422
  83. package/dist/next/edge-config.d.ts +0 -1
  84. package/dist/next/edge-config.js +0 -92
  85. package/dist/next/envelope-digest.d.ts +0 -21
  86. package/dist/next/envelope-digest.js +0 -58
  87. package/dist/next/middleware.d.ts +0 -40
  88. package/dist/next/middleware.js +0 -462
  89. package/dist/next/personalization-host.js +0 -257
  90. package/dist/next/vercel-collect-sdk-route.d.ts +0 -27
  91. package/dist/next/vercel-collect-sdk-route.js +0 -181
  92. package/dist/next/vercel-edge-projection-v1.d.ts +0 -24
  93. package/dist/next/vercel-edge-projection-v1.js +0 -880
  94. package/dist/next/vercel-personalization.d.ts +0 -4
  95. package/dist/next/vercel-personalization.js +0 -4
  96. package/dist/next/vercel-s3-personalization.d.ts +0 -79
  97. package/dist/next/vercel-s3-personalization.js +0 -570
  98. package/dist/providers/s3.d.ts +0 -47
  99. package/dist/providers/s3.js +0 -434
  100. package/dist/types/render-mode.d.ts +0 -2
  101. package/dist/types/render-mode.js +0 -1
  102. package/dist/types/renderer.d.ts +0 -71
  103. package/dist/types/renderer.js +0 -1
  104. package/src/types/render-mode.ts +0 -10
  105. package/src/types/renderer.ts +0 -83
  106. package/templates/nextjs/starter-content/src/middleware.ts +0 -41
  107. package/templates/nextjs/template/src/app/gradial/assets/[...path]/route.ts +0 -1
  108. package/templates/nextjs/template/src/middleware.ts +0 -41
  109. package/templates/nextjs/template/src/middleware.ts.tmpl +0 -40
@@ -1,197 +0,0 @@
1
- const RENDER_PROOF_VERSION = 'gradial.aci.renderProof.v1';
2
- const RENDER_PROOF_KEYS = [
3
- 'version',
4
- 'releaseId',
5
- 'route',
6
- 'contentRef',
7
- 'contentSha256',
8
- 'variantKey',
9
- ];
10
- const MAX_RENDER_PROOF_CONTENT_BYTES = 4096;
11
- const receiptBrand = Symbol('aci.verified-page-receipt');
12
- const renderProofReceipts = new WeakMap();
13
- /** @internal */
14
- export const selectVerifiedPage = Symbol('aci.select-verified-page');
15
- /** @internal */
16
- export function createVerifiedPageReceipt(value) {
17
- // Selection itself must fail if the coupled marker cannot be emitted.
18
- // `getPage` also uses this capability and intentionally discards the
19
- // receipt, so deferring the size check to React would permit markerless
20
- // success on that public server loader.
21
- validateVerifiedPageReceipt(value);
22
- return Object.freeze({
23
- ...value,
24
- [receiptBrand]: true,
25
- });
26
- }
27
- /** @internal */
28
- export function validateVerifiedPageReceipt(value) {
29
- encodeRenderProofContent(toRenderProof(value));
30
- }
31
- /** @internal */
32
- export function attachRenderProofReceipt(input, receipt) {
33
- if (receipt[receiptBrand] !== true) {
34
- throw new Error('ACI render proof integrity error: unverified receipt');
35
- }
36
- renderProofReceipts.set(input, receipt);
37
- }
38
- /** @internal */
39
- export function renderProofContentFor(input) {
40
- const receipt = renderProofReceipts.get(input);
41
- return receipt ? encodeRenderProofContent(toRenderProof(receipt)) : null;
42
- }
43
- /** @internal */
44
- export function encodeRenderProofContent(proof) {
45
- validateRenderProof(proof);
46
- const canonicalJSON = JSON.stringify({
47
- version: proof.version,
48
- releaseId: proof.releaseId,
49
- route: proof.route,
50
- contentRef: proof.contentRef,
51
- contentSha256: proof.contentSha256,
52
- variantKey: proof.variantKey,
53
- });
54
- const content = Buffer.from(canonicalJSON, 'utf8').toString('base64url');
55
- if (content.length < 1 || content.length > MAX_RENDER_PROOF_CONTENT_BYTES) {
56
- throw new Error(`ACI render proof integrity error: marker content is ${content.length} bytes`);
57
- }
58
- return content;
59
- }
60
- /** @internal */
61
- export function decodeRenderProofContent(content) {
62
- if (content.length < 1
63
- || content.length > MAX_RENDER_PROOF_CONTENT_BYTES
64
- || !/^[A-Za-z0-9_-]+$/.test(content)) {
65
- throw new Error('ACI render proof integrity error: invalid marker encoding');
66
- }
67
- const bytes = Buffer.from(content, 'base64url');
68
- if (bytes.toString('base64url') !== content) {
69
- throw new Error('ACI render proof integrity error: non-canonical base64url');
70
- }
71
- let canonicalJSON = '';
72
- try {
73
- canonicalJSON = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
74
- }
75
- catch (cause) {
76
- throw integrityError('marker is not valid UTF-8', cause);
77
- }
78
- let decoded;
79
- try {
80
- decoded = JSON.parse(canonicalJSON);
81
- }
82
- catch (cause) {
83
- throw integrityError('marker is not valid JSON', cause);
84
- }
85
- if (!isRecord(decoded)) {
86
- throw new Error('ACI render proof integrity error: marker must be an object');
87
- }
88
- if (!sameKeys(Object.keys(decoded), RENDER_PROOF_KEYS)) {
89
- throw new Error('ACI render proof integrity error: marker keys are not canonical');
90
- }
91
- const proof = {
92
- version: decoded.version,
93
- releaseId: decoded.releaseId,
94
- route: decoded.route,
95
- contentRef: decoded.contentRef,
96
- contentSha256: decoded.contentSha256,
97
- variantKey: decoded.variantKey,
98
- };
99
- validateRenderProof(proof);
100
- if (JSON.stringify(proof) !== canonicalJSON) {
101
- throw new Error('ACI render proof integrity error: marker JSON is not canonical');
102
- }
103
- return Object.freeze(proof);
104
- }
105
- function toRenderProof(receipt) {
106
- return {
107
- version: RENDER_PROOF_VERSION,
108
- releaseId: receipt.releaseId,
109
- route: receipt.route,
110
- contentRef: receipt.contentRef,
111
- contentSha256: receipt.contentSha256,
112
- variantKey: receipt.variantKey,
113
- };
114
- }
115
- function validateRenderProof(proof) {
116
- if (!isRecord(proof)) {
117
- throw new Error('ACI render proof integrity error: proof must be an object');
118
- }
119
- for (const key of RENDER_PROOF_KEYS) {
120
- if (typeof proof[key] !== 'string') {
121
- throw new Error(`ACI render proof integrity error: ${key} must be a string`);
122
- }
123
- if (hasUnpairedSurrogate(proof[key])) {
124
- throw new Error(`ACI render proof integrity error: ${key} has invalid Unicode`);
125
- }
126
- }
127
- if (proof.version !== RENDER_PROOF_VERSION) {
128
- throw new Error('ACI render proof integrity error: unsupported version');
129
- }
130
- if (Buffer.byteLength(proof.releaseId, 'ascii') > 128
131
- || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(proof.releaseId)) {
132
- throw new Error('ACI render proof integrity error: invalid releaseId');
133
- }
134
- if (Buffer.byteLength(proof.route, 'utf8') > 2048
135
- || !isCanonicalRoute(proof.route)) {
136
- throw new Error('ACI render proof integrity error: invalid route');
137
- }
138
- if (Buffer.byteLength(proof.contentRef, 'utf8') > 2048
139
- || !isCleanContentRef(proof.contentRef)) {
140
- throw new Error('ACI render proof integrity error: invalid contentRef');
141
- }
142
- if (!/^[0-9a-f]{64}$/.test(proof.contentSha256)) {
143
- throw new Error('ACI render proof integrity error: invalid contentSha256');
144
- }
145
- if (Buffer.byteLength(proof.variantKey, 'utf8') > 1024
146
- || /[\u0000-\u001f\u007f]/.test(proof.variantKey)) {
147
- throw new Error('ACI render proof integrity error: invalid variantKey');
148
- }
149
- }
150
- function isCanonicalRoute(route) {
151
- if (route === '/')
152
- return true;
153
- if (!route.startsWith('/')
154
- || route.startsWith('//')
155
- || route.endsWith('/')
156
- || /[\u0000-\u001f\u007f]/.test(route)) {
157
- return false;
158
- }
159
- return route.slice(1).split('/').every((segment) => (segment !== '' && segment !== '.' && segment !== '..'));
160
- }
161
- function isCleanContentRef(ref) {
162
- if (!ref
163
- || ref.startsWith('/')
164
- || ref.endsWith('/')
165
- || ref.includes('\\')
166
- || /[\u0000-\u001f\u007f]/.test(ref)) {
167
- return false;
168
- }
169
- return ref.split('/').every((segment) => (segment !== '' && segment !== '.' && segment !== '..'));
170
- }
171
- function isRecord(value) {
172
- return value !== null && typeof value === 'object' && !Array.isArray(value);
173
- }
174
- function sameKeys(actual, expected) {
175
- return actual.length === expected.length
176
- && actual.every((key, index) => key === expected[index]);
177
- }
178
- function hasUnpairedSurrogate(value) {
179
- for (let index = 0; index < value.length; index += 1) {
180
- const code = value.charCodeAt(index);
181
- if (code >= 0xd800 && code <= 0xdbff) {
182
- const next = value.charCodeAt(index + 1);
183
- if (!(next >= 0xdc00 && next <= 0xdfff))
184
- return true;
185
- index += 1;
186
- }
187
- else if (code >= 0xdc00 && code <= 0xdfff) {
188
- return true;
189
- }
190
- }
191
- return false;
192
- }
193
- function integrityError(message, cause) {
194
- const error = new Error(`ACI render proof integrity error: ${message}`);
195
- error.cause = cause;
196
- return error;
197
- }
@@ -1,10 +0,0 @@
1
- type AssetRouteContext = {
2
- params: Promise<AssetRouteParams>;
3
- };
4
- type AssetRouteParams = {
5
- path?: string[];
6
- };
7
- export declare const runtime = "nodejs";
8
- export declare const dynamic = "force-dynamic";
9
- export declare function GET(_request: Request, { params }: AssetRouteContext): Promise<Response>;
10
- export {};
@@ -1,45 +0,0 @@
1
- import { FileContentProvider } from '../providers/file.js';
2
- import { getDamAssetResponse, getReleaseAssetResponse, isDamAssetPath, resolveReleaseId, } from './server.js';
3
- export const runtime = 'nodejs';
4
- export const dynamic = 'force-dynamic';
5
- export async function GET(_request, { params }) {
6
- const resolvedParams = await params;
7
- const assetPath = '/' + (resolvedParams.path || []).join('/');
8
- if (assetPath === '/') {
9
- return new Response('asset not found', { status: 404 });
10
- }
11
- const local = await localAssetResponse(assetPath);
12
- if (local) {
13
- return local;
14
- }
15
- // DAM assets are global (not release-scoped): serve them from the hosting
16
- // bucket root without resolving a release.
17
- if (isDamAssetPath(assetPath)) {
18
- try {
19
- return await getDamAssetResponse(assetPath);
20
- }
21
- catch {
22
- return new Response('dam asset not found', { status: 404 });
23
- }
24
- }
25
- try {
26
- const releaseId = await resolveReleaseId();
27
- return await getReleaseAssetResponse(releaseId, assetPath);
28
- }
29
- catch {
30
- return new Response('asset not found', { status: 404 });
31
- }
32
- }
33
- async function localAssetResponse(assetPath) {
34
- const localRoot = process.env.ACI_LOCAL_ASSET_ROOT;
35
- if (localRoot) {
36
- const response = await new FileContentProvider(localRoot).fetchRaw(assetPath);
37
- if (response.ok)
38
- return response;
39
- }
40
- if (process.env.ACI_CONTENT_PROVIDER !== 'file') {
41
- return null;
42
- }
43
- const response = await new FileContentProvider().fetchRaw(assetPath);
44
- return response.ok ? response : null;
45
- }
@@ -1,19 +0,0 @@
1
- import { type IdentitySigningKeys, type PersonalizationCollectionStore } from './personalization-host.js';
2
- export interface PersonalizationCollectRouteConfig {
3
- siteId: string;
4
- store: PersonalizationCollectionStore;
5
- identityKeys: IdentitySigningKeys;
6
- /**
7
- * Claims verify keys (kid -> secret) for withdrawal EVIDENCE
8
- * (anonymous-experiments REQ-6): suppression fires only when the request
9
- * presents a signature-verified aci_claims cookie — presence alone is
10
- * spoofable, and under universal minting an unverified trigger would
11
- * suppress every reject-all visitor. Empty = evidence never verifies =
12
- * suppression disabled (fails safe).
13
- */
14
- claimsKeys?: Record<string, string>;
15
- retentionSeconds?: number;
16
- secureCookies?: boolean;
17
- now?: () => Date;
18
- }
19
- export declare function createPersonalizationCollectRoute(config: PersonalizationCollectRouteConfig): (request: Request) => Promise<Response>;