@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
@@ -45,13 +45,10 @@ The SDK provides `createPage(registry)` which owns param normalization, content
45
45
  loading, layout resolution, metadata generation, notFound handling, slot
46
46
  resolution (including fragment defaults), and block rendering.
47
47
 
48
- Path shape: `/__r/{releaseId}/routes/{...slug}`. The SDK extracts releaseId
49
- internally; middleware rewrites public URLs to `/__r/{releaseId}/routes/{path}`
50
- for the app-level route. The `routes` namespace leaves room for future siblings
51
- under the release prefix. The filesystem uses an **optional catch-all** `[[...slug]]`
52
- (not required `[...slug]`). Production middleware always rewrites to
53
- `/__r/{releaseId}/routes/{path}`, but file-provider local dev passes requests
54
- unrewritten so `/` arrives with an empty slug.
48
+ The filesystem uses an **optional catch-all** `[[...slug]]` (not required
49
+ `[...slug]`) so file-provider local development can render `/`. During publish,
50
+ the compiler invokes this route with an isolated render input; hosted CMS
51
+ traffic is served from the resulting immutable HTML and does not enter Next.
55
52
 
56
53
  Chrome (Header/Footer) is **not** in `layout.tsx`. It is CMS-managed via
57
54
  layout fragment defaults. The `layout.tsx` file is minimal and includes
@@ -197,41 +194,21 @@ the rewrite automatically.
197
194
  | Storybook | `.storybook/main.ts`, `.storybook/preview.ts` |
198
195
  | Assets | CloudFront function rewrite (automatic, no infrastructure changes needed) |
199
196
 
200
- ## Middleware
197
+ ## Hosted routing
201
198
 
202
- Middleware requires explicit `siteId`. The SDK exports a canonical matcher that
203
- repos re-export:
204
-
205
- ```ts
206
- // src/middleware.ts
207
- import { createGradialMiddleware } from '@gradial/aci/next/middleware';
208
- export { config } from '@gradial/aci/next/middleware';
209
- export default createGradialMiddleware({ siteId: 'your-tenant-id' });
210
- ```
211
-
212
- The middleware rewrites public URLs to `/__r/{releaseId}/routes/{path}` for
213
- the app-level route. The SDK extracts releaseId internally.
199
+ Do not add customer middleware for CMS routing. Provider edge bundles own
200
+ release/variant selection and protected immutable-artifact dispatch outside the
201
+ framework. Next receives neither the dispatch assertion nor a content reference.
214
202
 
215
203
  ## Asset Routes
216
204
 
217
- **Preferred: NO app-level asset route.** Assets are served via URL rewrite
218
- (Next.js `withAci()`) or CloudFront function rewrite (Astro/CloudFront) directly
219
- to S3.
205
+ Do not add an app-level asset route. Host adapters serve immutable browser and
206
+ DAM assets directly from S3/R2/CDN storage. Next's `withAci()` supports an
207
+ explicit direct asset-origin rewrite for local/custom builds.
220
208
 
221
209
  DAM derivative assets are content-addressed and globally shared — staged once at
222
- `{keyPrefix}/.gradial-dam/` and shared across all releases. The SDK's `withAci()`
223
- already injects a `/.gradial-dam/:path*` rewrite. For CloudFront, the existing
224
- CloudFront function handles the rewrite automatically.
225
-
226
- For transitional compatibility, the SDK still exports an asset route handler:
227
-
228
- ```ts
229
- // src/app/gradial/assets/[...path]/route.ts (transitional)
230
- export { GET, runtime, dynamic } from '@gradial/aci/next/asset-route';
231
- ```
232
-
233
- **Note**: Asset URLs do NOT include `[releaseId]` in the path. DAM assets are
234
- globally scoped and content-addressed via filename hashes.
210
+ `{keyPrefix}/.gradial-dam/` and shared across all releases. Asset URLs do not
211
+ need a release segment because their filenames bind content.
235
212
 
236
213
  ## Anti-Patterns
237
214
 
@@ -121,19 +121,11 @@ source:
121
121
  componentRegistry: ./src/cms/contracts/components/index.ts
122
122
  layoutRegistry: ./src/cms/contracts/layouts/index.ts
123
123
 
124
- capabilities:
125
- staticRender: true
126
- ssr: true
127
- ssrIslands: true
128
- clientIslands: true
129
- fragmentRender: true
124
+ # Optional for custom renderers; Astro/Next use framework conventions.
125
+ # rendererEntry: ./src/cms/renderer.ts
130
126
 
131
127
  routes:
132
128
  cmsManaged: "/[[...slug]]"
133
- frameworkOwned:
134
- - "/api/*"
135
- - "/_next/*" # Next.js
136
- - "/.gradial-dam/*"
137
129
 
138
130
  rendererProtocol: stdio-json
139
131
  ```
@@ -150,20 +142,21 @@ rendererProtocol: stdio-json
150
142
  | `source.publicDir` | Public assets directory (Astro) |
151
143
  | `componentRegistry` | Path to component contract barrel |
152
144
  | `layoutRegistry` | Path to layout contract barrel |
153
- | `capabilities` | Render capabilities (static, SSR, islands, fragments) |
145
+ | `rendererEntry` | Optional renderer entry override; omit for framework conventions |
154
146
  | `routes.cmsManaged` | Catch-all route pattern for CMS pages |
155
- | `routes.frameworkOwned` | Route patterns excluded from CMS routing |
156
147
  | `rendererProtocol` | Renderer communication protocol |
157
148
 
158
- ### Removed fields
149
+ ### Retired fields
159
150
 
160
- - `rendererEntry` has been removed from `.aci.yaml`. Do not include it.
151
+ - `capabilities` is rejected. Deterministic CMS delivery always produces
152
+ complete static HTML.
153
+ - `routes.frameworkOwned` is rejected. Application-owned routes are a separate
154
+ hosting contract, not a fallback from CMS delivery.
161
155
 
162
156
  ### Rules
163
157
 
164
158
  - `componentRegistry` and `layoutRegistry` point to contract-only modules.
165
159
  - No secrets in `.aci.yaml`, docs, fixtures, or generated files.
166
160
  - The `cmsManaged` route pattern should match the filesystem: use `/[[...slug]]`
167
- (optional catch-all) for Next.js repos. Production middleware always rewrites
168
- to `/__r/{releaseId}/routes/{path}` so slug is non-empty, but file-provider
169
- local dev passes requests unrewritten so `/` arrives with an empty slug.
161
+ (optional catch-all) for Next.js repos so local `/` arrives with an empty
162
+ slug. Hosted routing selects already-rendered artifacts outside Next.
@@ -104,8 +104,8 @@ Only Next.js and Astro are supported. SvelteKit support has been removed.
104
104
  | Root layout | `src/app/layout.tsx` (minimal — imports CSS, includes `<DevRefresh />`, no chrome) |
105
105
  | Config | `next.config.ts` with bare `withAci()` |
106
106
  | Registry | `src/cms/registry.ts` (shared, `createRegistry` with `[contract, component]` tuples) |
107
- | Middleware | `src/middleware.ts` with `createGradialMiddleware({ siteId })` and SDK-exported matcher |
108
- | Asset route | `src/app/gradial/assets/[...path]/route.ts` — thin SDK re-export from `@gradial/aci/next/asset-route`. Serves CMS documents (robots.txt, sitemap.xml) via withAci rewrites and local-dev DAM assets. Hand-rolled asset routes and the legacy release-scoped `[releaseId]/[...path]` variant are banned. Astro has no route (CDN/global path). |
107
+ | Middleware | None for CMS routing; the provider host bundle selects immutable artifacts outside Next |
108
+ | Asset route | None; host gateways serve immutable browser/DAM assets directly and conformance rejects request-time Next asset routes |
109
109
 
110
110
  ### Astro
111
111
 
@@ -2,10 +2,11 @@
2
2
 
3
3
  ## `@gradial/aci/next` Exports
4
4
 
5
- The SDK provides server-side functions that handle content resolution
6
- across preview, local file, and deployed S3 modes. **Always use these
7
- functions instead of directly importing `FileContentProvider` or
8
- `S3ContentProvider`.** The SDK handles the resolution chain automatically.
5
+ The SDK provides server-side functions for the publish-time Next renderer and
6
+ local file-backed development. They resolve either a compiler-injected render
7
+ input or `.aci/compiled` content. Hosted CMS requests do not enter Next and
8
+ these functions never resolve a mutable provider pointer or fetch deployed page
9
+ content from S3.
9
10
 
10
11
  ### `createPage(registry, options?)`
11
12
 
@@ -14,11 +15,9 @@ normalization, content loading via render input, metadata generation,
14
15
  `notFound` handling, layout resolution, and block rendering via the
15
16
  registry.
16
17
 
17
- Path shape: in production, middleware rewrites to `/__r/{releaseId}/routes/{...slug}`.
18
- The SDK's `resolveRouteAndRelease` decomposes `['__r', releaseId, 'routes', ...pathSegments]`.
19
- In local dev (`ACI_CONTENT_PROVIDER=file`), requests pass through unrewritten, so `/`
20
- arrives with an empty/undefined slug. The filesystem uses an **optional catch-all**
21
- `[[...slug]]` to handle both shapes.
18
+ The filesystem uses an **optional catch-all** `[[...slug]]` so local `/`
19
+ requests arrive with an empty slug. During publish, the compiler invokes the
20
+ same route against an isolated render input and captures complete HTML.
22
21
 
23
22
  ```tsx
24
23
  // src/app/[[...slug]]/page.tsx
@@ -38,11 +37,10 @@ fragments.
38
37
 
39
38
  ### `withAci(nextConfig?, options?)`
40
39
 
41
- Next.js config wrapper. Owns all canonical SDK behavior: output mode,
42
- outputFileTracingRoot, base-path/build-mode/dist-dir env injection, CDN
43
- headers, asset rewrites (`/.gradial-dam` prefix), content-watch plugin,
44
- and public-path scanning. Repos should pass a bare `withAci()` call and
45
- rely on SDK defaults.
40
+ Next.js config wrapper for the local-dev and publish-time renderer capsule. It
41
+ owns standalone output, `outputFileTracingRoot`, optional direct asset-origin
42
+ rewrites, content watching, and error-page build payloads. Repos should pass a
43
+ bare `withAci()` call unless they have an explicit CDN asset origin.
46
44
 
47
45
  ```ts
48
46
  // next.config.ts
@@ -51,22 +49,15 @@ import { withAci } from '@gradial/aci/next/config';
51
49
  export default withAci();
52
50
  ```
53
51
 
54
- For site-specific non-CMS routes, pass `passthroughRoutes`:
55
-
56
- ```ts
57
- export default withAci({
58
- passthroughRoutes: ['/api/*', '/admin/*'],
59
- });
60
- ```
61
-
62
- Do not manually configure outputFileTracing, base-path, build-mode, dist-dir,
63
- or custom rewrites/redirects for ACI concerns. The SDK handles these.
52
+ Do not add routing middleware or request-time content rewrites for CMS routes.
53
+ Provider hosting bundles own public route selection and immutable artifact
54
+ delivery outside the Next application.
64
55
 
65
56
  ### `getSiteConfig<T>()`
66
57
 
67
- Loads the site configuration. Checks the render input header first
68
- (preview mode), then falls back to file or S3 provider. **MUST be used
69
- in `layout.tsx` instead of `new FileContentProvider()`.**
58
+ Loads the site configuration from the current compiler render input, then from
59
+ the local file provider. **MUST be used in `layout.tsx` instead of constructing
60
+ a provider directly.**
70
61
 
71
62
  ```tsx
72
63
  import { getSiteConfig } from '@gradial/aci/next';
@@ -79,23 +70,21 @@ Generic: pass your site config interface for typed access:
79
70
 
80
71
  ### `getFragment(name)`
81
72
 
82
- Loads a fragment by name. Checks render input first (preview mode), then
83
- provider fallback.
73
+ Loads a fragment by name from the compiler render input or local files.
84
74
 
85
75
  ### `getLayout(name)`
86
76
 
87
- Loads a layout by name. Checks render input first (preview mode), then
88
- provider fallback.
77
+ Loads a layout by name from the compiler render input or local files.
89
78
 
90
79
  ### `getPage(route)`
91
80
 
92
- Loads page content for a specific route. Checks render input first
93
- (preview mode), then provider fallback.
81
+ Loads page content for a specific route from the compiler render input or local
82
+ files.
94
83
 
95
84
  ### `getRenderInput(route)`
96
85
 
97
86
  Loads the full render input (page + siteConfig + domain + locale). Used
98
- internally by `createPage`. Available for custom server composition when
87
+ internally by `createPage`. Available for custom publish-time rendering when
99
88
  you need the full render context.
100
89
 
101
90
  ### `routeFromNextParams(params)`
@@ -113,37 +102,13 @@ const previewRelease = await isPreviewMode();
113
102
  if (previewRelease) { /* preview-specific logic */ }
114
103
  ```
115
104
 
116
- ### `createGradialMiddleware(config)`
117
-
118
- Creates Next.js middleware for ACI sites. Requires explicit `siteId`.
119
-
120
- ```ts
121
- // src/middleware.ts
122
- import { createGradialMiddleware } from '@gradial/aci/next/middleware';
123
-
124
- export default createGradialMiddleware({ siteId: 'your-tenant-id' });
125
- export { config } from '@gradial/aci/next/middleware';
126
- ```
127
-
128
- The SDK exports a canonical middleware matcher via the `config` export. Repos
129
- should re-export it verbatim. Do not hand-roll custom matcher patterns unless
130
- site-specific static paths require exclusions.
105
+ ### Provider-owned routing
131
106
 
132
- **Config interface:**
133
-
134
- ```ts
135
- export interface GradialMiddlewareConfig {
136
- siteId: string; // REQUIRED
137
- edgeConfig?: string;
138
- previewSignKey?: string;
139
- deploymentId?: string;
140
- deploymentProtectionBypass?: string;
141
- }
142
- ```
143
-
144
- The middleware rewrites public URLs to `/__r/{releaseId}/routes/{path}` for
145
- the app-level route. The SDK extracts releaseId and resolves the content route
146
- internally.
107
+ Do not add `src/middleware.ts` for CMS routing. Vercel's composed Build Output
108
+ contains host-owned middleware and a protected static gateway; CloudFront and
109
+ Cloudflare have equivalent provider adapters. They select and serve an
110
+ immutable artifact without passing a release selector, content reference, or
111
+ dispatch assertion into Next.
147
112
 
148
113
  ### `DevRefresh`
149
114
 
@@ -172,50 +137,35 @@ import { DevRefresh } from '@gradial/aci/next';
172
137
  `createPage` catches `PageNotFoundError` and calls `notFound()`
173
138
  automatically.
174
139
 
175
- ## Three-Tier Content Resolution
140
+ ## Two Build-Time Content Inputs
176
141
 
177
- Every SDK server function follows the same resolution chain:
142
+ Every SDK server function follows the same local/publish-time resolution chain:
178
143
 
179
- ### Tier 1: Render Input (Preview Mode)
144
+ ### Tier 1: Compiler Render Input
180
145
 
181
146
  When the Go harness sends a render request, it sets the
182
147
  `x-gradial-render-input-id` header. The SDK checks the
183
148
  `pendingRenderInputs` in-process map for a matching render input and
184
- returns page data directly from the Go harness's render payload. This
185
- is how preview works — the harness pushes content into the Next.js
186
- process without touching S3 or disk.
149
+ returns page data directly from the Go harness's render payload. This is how
150
+ preview and publish render a finite content snapshot without giving the
151
+ framework live storage authority.
187
152
 
188
153
  ### Tier 2: File Provider (`ACI_CONTENT_PROVIDER=file`)
189
154
 
190
- When the `ACI_CONTENT_PROVIDER` environment variable is set to `file`,
191
- the SDK reads compiled content from `.aci/compiled/` on disk. This is
192
- the local development path. Also used as a fallback in preview mode when
193
- no render input header is present.
194
-
195
- ### Tier 3: S3 Provider (Deployed SSR)
196
-
197
- When neither render input nor file provider is active, the SDK reads
198
- from S3. The release ID is resolved from (in order):
199
-
200
- 1. `x-gradial-release-id` header (set by middleware)
201
- 2. `ACI_RELEASE_ID` environment variable
202
- 3. Vercel Edge Config active release pointer
155
+ Without a compiler render input, the SDK reads compiled content from
156
+ `.aci/compiled/` on disk. This is the local development path. There is no third
157
+ request-time S3 or Edge Config tier.
203
158
 
204
159
  ## Critical Rule
205
160
 
206
- **NEVER import `FileContentProvider` or `S3ContentProvider` directly in
207
- app code.** Always use `getPage()`, `getSiteConfig()`, `getFragment()`,
161
+ **NEVER construct a content provider directly in app code.** Always use
162
+ `getPage()`, `getSiteConfig()`, `getFragment()`,
208
163
  `getLayout()`, or `getRenderInput()` from `@gradial/aci/next`. The SDK
209
- handles the resolution chain automatically.
210
-
211
- The only exception is the transitional asset route handler
212
- (`src/app/gradial/assets/[...path]/route.ts`), which directly
213
- uses `FileContentProvider` for local asset serving and
214
- `getReleaseAssetResponse` for S3 assets. The preferred path is to use no
215
- app-level asset route at all (`withAci()` handles rewrites for Next.js;
216
- CloudFront function rewrite for Astro). DAM derivative assets are
217
- content-addressed and globally shared — staged once at `{keyPrefix}/.gradial-dam/`
218
- and shared across all releases.
164
+ keeps the compiler-input and local-file boundary explicit.
165
+
166
+ Do not add an app-level asset route. Host gateways serve immutable browser and
167
+ DAM assets directly; `withAci()` may rewrite to an explicitly configured asset
168
+ origin for local/custom builds.
219
169
 
220
170
  ## Layout.tsx Pattern
221
171
 
@@ -47,19 +47,11 @@ export default defineConfig({
47
47
  Delete manual env-var plumbing, outputFileTracing, custom rewrites/redirects
48
48
  for ACI concerns.
49
49
 
50
- ### 4. Middleware: Require `siteId`
50
+ ### 4. Middleware: Remove Customer Ownership
51
51
 
52
- Update middleware to pass explicit `siteId`:
53
-
54
- ```ts
55
- // src/middleware.ts
56
- import { createGradialMiddleware } from '@gradial/aci/next/middleware';
57
- export { config } from '@gradial/aci/next/middleware';
58
- export default createGradialMiddleware({ siteId: 'your-tenant-id' });
59
- ```
60
-
61
- Re-export the SDK's canonical matcher via `config`. Delete custom matchers
62
- unless site-specific static paths require exclusions.
52
+ Delete `src/middleware.ts` when it performs CMS routing. The provider host bundle
53
+ owns release/variant selection and protected immutable-artifact delivery outside
54
+ the framework; customer code must not implement a second decision path.
63
55
 
64
56
  ### 5. Path Shape: `[[...slug]]` (Optional Catch-All)
65
57
 
@@ -76,10 +68,9 @@ routes:
76
68
  cmsManaged: "/[[...slug]]"
77
69
  ```
78
70
 
79
- Production middleware always rewrites to `/__r/{releaseId}/routes/{path}` so
80
- slug is non-empty there, but file-provider local dev passes requests
81
- unrewritten so `/` arrives with an empty slug. A required catch-all 404s
82
- the dev homepage.
71
+ File-provider local development sends `/` to the framework with an empty slug,
72
+ so a required catch-all 404s the dev homepage. Hosted CMS requests use the
73
+ provider's immutable artifact path and do not enter this Next route.
83
74
 
84
75
  ### 6. DevRefresh Mandated
85
76
 
@@ -235,22 +226,14 @@ conformancePreset({
235
226
 
236
227
  4. **Remove Custom Asset Route**
237
228
 
238
- Delete `src/app/gradial/assets/[releaseId]/[...path]/route.ts` (with extra
239
- `[releaseId]` segment). Replace with standard path:
240
-
241
- ```ts
242
- // src/app/gradial/assets/[...path]/route.ts
243
- export { GET, runtime, dynamic } from '@gradial/aci/next/asset-route';
244
- ```
245
-
246
- The SDK asset-route handler resolves releaseId internally. No need for an
247
- explicit path segment.
229
+ Delete every `src/app/gradial/assets/**/route.ts` form. Do not replace it;
230
+ provider gateways serve immutable browser and DAM assets directly.
248
231
 
249
232
  5. **Delete `content-assets` Route and `.gradial-dam` Rewrite**
250
233
 
251
- Delete `src/app/content-assets/[...key]/route.ts` and remove the
252
- `.gradial-dam` rewrite from `next.config.ts`. The SDK asset route handles
253
- both dev-mode file serving and deployed S3 serving.
234
+ Delete `src/app/content-assets/[...key]/route.ts` and any hand-written
235
+ request-time `.gradial-dam` rewrite. The SDK adapter owns local development;
236
+ provider gateways own deployed asset delivery.
254
237
 
255
238
  6. **Delete Runtime `layouts.ts`**
256
239
 
@@ -313,13 +296,10 @@ conformancePreset({
313
296
  ];
314
297
  ```
315
298
 
316
- 2. **Add `siteId` to Middleware**
317
-
318
- Update middleware to pass explicit `siteId`:
299
+ 2. **Remove Customer Middleware**
319
300
 
320
- ```ts
321
- export default createGradialMiddleware({ siteId: 'bnc' });
322
- ```
301
+ Delete `src/middleware.ts` when it implements CMS release or variant
302
+ selection. Provider routing occurs outside the framework.
323
303
 
324
304
  3. **General Migration Steps**
325
305
 
@@ -444,10 +424,10 @@ The preset validates (default checks):
444
424
  - `config` -- `withAci()` present in config
445
425
  - `registry` -- `createRegistry()` usage (no hand-rolled maps)
446
426
  - `pageEntry` -- `createPage(registry)` usage in catch-all route
447
- - `middleware` -- `createGradialMiddleware({ siteId })` with correct siteId
427
+ - `middleware` -- no customer middleware implementing a second CMS decision path
448
428
  - `noFileContentProvider` -- no direct `FileContentProvider` imports in app code
449
429
  - `noCustomContent` -- no `src/lib/content.ts` shim
450
- - `noLegacyAssetRoute` -- no `[releaseId]` segment in asset route path
430
+ - `noRequestTimeAssetRoute` -- no Next asset-delivery route
451
431
  - `sdkVersion` -- SDK version >= 0.1.31
452
432
 
453
433
  Optional (disabled by default, shell out):
@@ -9,18 +9,7 @@ source:
9
9
  componentRegistry: ./src/cms/contracts/components/index.ts
10
10
  layoutRegistry: ./src/cms/contracts/layouts/index.ts
11
11
 
12
- capabilities:
13
- staticRender: true
14
- ssr: true
15
- ssrIslands: true
16
- clientIslands: true
17
- fragmentRender: true
18
-
19
12
  routes:
20
13
  cmsManaged: "/[...slug]"
21
- frameworkOwned:
22
- - "/api/*"
23
- - "/_next/*"
24
- - "/.gradial-dam/*"
25
14
 
26
15
  rendererProtocol: stdio-json
@@ -47,6 +47,5 @@ src/cms/ Contracts and component registry
47
47
  src/components/ Runtime React components
48
48
  src/design-system/ Design tokens and global styles
49
49
  src/app/ Next.js App Router pages and routes
50
- src/middleware.ts ACI middleware (siteId, release routing)
51
50
  .agents/skills/ Skills for humans and agents
52
51
  ```
@@ -5,4 +5,4 @@ const page = createPage(registry);
5
5
 
6
6
  export const dynamic = 'force-dynamic';
7
7
  export const generateMetadata = page.generateMetadata;
8
- export default page.default;
8
+ export default page.default;
@@ -1,18 +0,0 @@
1
- export interface ReleaseAssetConfig {
2
- bucket?: string;
3
- keyPrefix?: string;
4
- region?: string;
5
- accessKeyId?: string;
6
- secretAccessKey?: string;
7
- sessionToken?: string;
8
- roleArn?: string;
9
- endpoint?: string;
10
- }
11
- export declare class ReleaseAssetNotFoundError extends Error {
12
- constructor(releaseId: string, assetPath: string, cause?: unknown);
13
- }
14
- export declare function getReleaseAssetResponse(input: {
15
- releaseId: string;
16
- assetPath: string;
17
- config?: ReleaseAssetConfig;
18
- }): Promise<Response>;
@@ -1,66 +0,0 @@
1
- import { S3ContentProvider } from '../providers/s3.js';
2
- export class ReleaseAssetNotFoundError extends Error {
3
- constructor(releaseId, assetPath, cause) {
4
- super(`ACI release asset not found: ${releaseId}/${assetPath}`);
5
- this.name = 'ReleaseAssetNotFoundError';
6
- this.cause = cause;
7
- }
8
- }
9
- export async function getReleaseAssetResponse(input) {
10
- const clean = cleanAssetPath(input.assetPath);
11
- if (!input.releaseId || !clean) {
12
- throw new ReleaseAssetNotFoundError(input.releaseId, input.assetPath);
13
- }
14
- const config = input.config ?? {};
15
- const provider = new S3ContentProvider({
16
- bucket: config.bucket,
17
- keyPrefix: releaseKey(config, input.releaseId),
18
- region: config.region,
19
- accessKeyId: config.accessKeyId,
20
- secretAccessKey: config.secretAccessKey,
21
- sessionToken: config.sessionToken,
22
- roleArn: config.roleArn,
23
- endpoint: config.endpoint,
24
- });
25
- const key = joinKey(provider.config.keyPrefix, 'assets', clean);
26
- const res = await provider.fetchRaw(key);
27
- if (!res.ok || !res.body) {
28
- throw new ReleaseAssetNotFoundError(input.releaseId, clean, await safeResponseText(res));
29
- }
30
- const headers = new Headers();
31
- copyHeader(res.headers, headers, 'content-type');
32
- copyHeader(res.headers, headers, 'content-length');
33
- copyHeader(res.headers, headers, 'etag');
34
- copyHeader(res.headers, headers, 'last-modified');
35
- headers.set('cache-control', 'public, max-age=300, must-revalidate');
36
- return new Response(res.body, { status: 200, headers });
37
- }
38
- function cleanAssetPath(value) {
39
- const clean = value.replace(/^\/+|\/+$/g, '').replace(/\/+/g, '/');
40
- if (!clean || clean.split('/').some((segment) => segment === '..' || segment === '.'))
41
- return '';
42
- return clean;
43
- }
44
- function copyHeader(from, to, name) {
45
- const value = from.get(name);
46
- if (value)
47
- to.set(name, value);
48
- }
49
- async function safeResponseText(res) {
50
- try {
51
- return await res.text();
52
- }
53
- catch {
54
- return '';
55
- }
56
- }
57
- function releaseKey(config, releaseId) {
58
- return joinKey(config.keyPrefix || process.env.ACI_S3_KEY_PREFIX || '', 'releases', releaseId);
59
- }
60
- function joinKey(...parts) {
61
- return parts
62
- .filter(Boolean)
63
- .map((part) => part.replace(/^\/+|\/+$/g, ''))
64
- .filter(Boolean)
65
- .join('/');
66
- }
@@ -1,11 +0,0 @@
1
- export function selectPersonalizationVariant(request: any, route: any, claims: any, experiments: any, identity: any): any;
2
- export function resolvePersonalizationDecision(request: any, route: any, claims: any, experiments: any, identity: any): {
3
- variant: any;
4
- experiment: {
5
- experimentId: any;
6
- armId: any;
7
- allocationVersion: string;
8
- variantKey: any;
9
- bucket: number;
10
- } | null;
11
- };
@@ -1 +0,0 @@
1
- export {};