@astrale-os/adapter-cloudflare 0.5.0-beta.16 → 0.5.0-beta.161

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 (201) hide show
  1. package/README.md +93 -2
  2. package/dist/adapter.d.ts +14 -0
  3. package/dist/adapter.js +82 -0
  4. package/dist/build/artifact.d.ts +7 -0
  5. package/dist/build/artifact.js +170 -0
  6. package/dist/build/bundle/admit.d.ts +1 -0
  7. package/dist/build/bundle/admit.js +9 -0
  8. package/dist/build/closure.d.ts +2 -0
  9. package/dist/build/closure.js +22 -0
  10. package/dist/build/codegen/execution.d.ts +3 -0
  11. package/dist/build/codegen/execution.js +2 -0
  12. package/dist/build/codegen/merge.d.ts +0 -1
  13. package/dist/build/codegen/merge.js +0 -1
  14. package/dist/build/codegen/wrangler.d.ts +12 -3
  15. package/dist/build/codegen/wrangler.js +26 -18
  16. package/dist/build/configuration/addressing.d.ts +2 -0
  17. package/dist/build/configuration/addressing.js +17 -0
  18. package/dist/build/configuration/invocation-timeout.d.ts +2 -0
  19. package/dist/build/configuration/invocation-timeout.js +9 -0
  20. package/dist/build/configuration/request-limit.d.ts +2 -0
  21. package/dist/build/configuration/request-limit.js +9 -0
  22. package/dist/build/configuration/router.d.ts +7 -0
  23. package/dist/build/configuration/router.js +11 -0
  24. package/dist/build/configuration/worker-name.d.ts +2 -0
  25. package/dist/build/configuration/worker-name.js +18 -0
  26. package/dist/build/configuration.d.ts +5 -0
  27. package/dist/build/configuration.js +5 -0
  28. package/dist/build/direct.d.ts +4 -0
  29. package/dist/build/direct.js +90 -0
  30. package/dist/build/frontend/files.d.ts +19 -0
  31. package/dist/build/frontend/files.js +99 -0
  32. package/dist/build/frontend/readiness.d.ts +10 -0
  33. package/dist/build/frontend/readiness.js +21 -0
  34. package/dist/build/frontend/revision.d.ts +5 -0
  35. package/dist/build/frontend/revision.js +14 -0
  36. package/dist/build/frontend/vite.d.ts +14 -0
  37. package/dist/build/frontend/vite.js +42 -0
  38. package/dist/build/frontend/vite.process.d.ts +7 -0
  39. package/dist/build/frontend/vite.process.js +65 -0
  40. package/dist/build/frontend/vite.runner.d.ts +1 -0
  41. package/dist/build/frontend/vite.runner.js +155 -0
  42. package/dist/build/index.d.ts +10 -16
  43. package/dist/build/index.js +9 -16
  44. package/dist/build/material.d.ts +10 -0
  45. package/dist/build/material.js +25 -0
  46. package/dist/build/materialize.d.ts +4 -0
  47. package/dist/build/materialize.js +10 -0
  48. package/dist/build/metafile.d.ts +5 -0
  49. package/dist/build/metafile.js +14 -0
  50. package/dist/build/qualification.d.ts +5 -0
  51. package/dist/build/qualification.js +7 -0
  52. package/dist/build/roots.d.ts +2 -0
  53. package/dist/build/roots.js +34 -0
  54. package/dist/build/worker/artifact.d.ts +40 -0
  55. package/dist/build/worker/artifact.js +1 -0
  56. package/dist/build/worker/artifact.load.d.ts +3 -0
  57. package/dist/build/worker/artifact.load.js +308 -0
  58. package/dist/build/worker/artifact.manifest.d.ts +48 -0
  59. package/dist/build/worker/artifact.manifest.js +87 -0
  60. package/dist/build/worker/artifact.paths.d.ts +4 -0
  61. package/dist/build/worker/artifact.paths.js +25 -0
  62. package/dist/build/worker/codegen/entry.d.ts +11 -0
  63. package/dist/build/worker/codegen/entry.js +68 -0
  64. package/dist/build/worker/codegen/literal.d.ts +28 -0
  65. package/dist/build/worker/codegen/literal.js +136 -0
  66. package/dist/build/worker/codegen/service.d.ts +21 -0
  67. package/dist/build/worker/codegen/service.js +63 -0
  68. package/dist/build/worker/execution.prepare.d.ts +20 -0
  69. package/dist/build/worker/execution.prepare.js +134 -0
  70. package/dist/build/worker/index.d.ts +2 -0
  71. package/dist/build/worker/index.js +1 -0
  72. package/dist/build/worker/modules.d.ts +11 -0
  73. package/dist/build/worker/modules.js +26 -0
  74. package/dist/build/worker/runtime.d.ts +10 -0
  75. package/dist/build/worker/runtime.js +35 -0
  76. package/dist/build/worker/specifier.d.ts +3 -0
  77. package/dist/build/worker/specifier.js +10 -0
  78. package/dist/cloudflare.d.ts +1 -45
  79. package/dist/cloudflare.js +1 -202
  80. package/dist/deploy/deploy.d.ts +17 -0
  81. package/dist/deploy/deploy.js +229 -0
  82. package/dist/deploy/index.d.ts +1 -0
  83. package/dist/deploy/index.js +1 -0
  84. package/dist/deploy/output.d.ts +2 -0
  85. package/dist/deploy/output.js +10 -0
  86. package/dist/deploy/readiness.d.ts +5 -0
  87. package/dist/deploy/readiness.js +21 -0
  88. package/dist/identity/binding.d.ts +2 -0
  89. package/dist/identity/binding.js +2 -0
  90. package/dist/identity/index.d.ts +3 -0
  91. package/dist/identity/index.js +3 -0
  92. package/dist/identity/material.d.ts +7 -0
  93. package/dist/identity/material.js +42 -0
  94. package/dist/identity/secret.d.ts +3 -0
  95. package/dist/identity/secret.js +7 -0
  96. package/dist/identity/source.d.ts +26 -0
  97. package/dist/identity/source.js +127 -0
  98. package/dist/index.d.ts +10 -9
  99. package/dist/index.js +10 -9
  100. package/dist/params.d.ts +43 -36
  101. package/dist/params.js +0 -1
  102. package/dist/release/deployment.d.ts +44 -0
  103. package/dist/release/deployment.js +141 -0
  104. package/dist/release/index.d.ts +2 -0
  105. package/dist/release/index.js +2 -0
  106. package/dist/release/staged-worker-name.d.ts +3 -0
  107. package/dist/release/staged-worker-name.js +10 -0
  108. package/dist/worker/entry.d.ts +31 -0
  109. package/dist/worker/entry.js +105 -0
  110. package/dist/worker/fetch.d.ts +0 -1
  111. package/dist/worker/fetch.js +0 -1
  112. package/dist/worker/front.d.ts +49 -0
  113. package/dist/worker/front.js +75 -0
  114. package/dist/worker/frontend.d.ts +4 -0
  115. package/dist/worker/frontend.js +83 -0
  116. package/dist/worker/identity.d.ts +7 -0
  117. package/dist/worker/identity.js +23 -0
  118. package/dist/worker/index.d.ts +2 -61
  119. package/dist/worker/index.js +2 -221
  120. package/dist/wrangler/bundle.d.ts +10 -0
  121. package/dist/wrangler/bundle.js +28 -0
  122. package/dist/wrangler/deploy.d.ts +24 -0
  123. package/dist/wrangler/deploy.js +44 -0
  124. package/dist/wrangler/index.d.ts +5 -0
  125. package/dist/wrangler/index.js +5 -0
  126. package/dist/wrangler/process.d.ts +15 -0
  127. package/dist/wrangler/process.js +102 -0
  128. package/dist/wrangler/rollout.d.ts +27 -0
  129. package/dist/wrangler/rollout.js +75 -0
  130. package/dist/wrangler/secrets.d.ts +2 -0
  131. package/dist/wrangler/secrets.js +24 -0
  132. package/dist/wrangler/status.d.ts +18 -0
  133. package/dist/wrangler/status.js +75 -0
  134. package/dist/wrangler/triggers.d.ts +5 -0
  135. package/dist/wrangler/triggers.js +12 -0
  136. package/dist/wrangler/type-generation.d.ts +6 -0
  137. package/dist/wrangler/type-generation.js +19 -0
  138. package/dist/wrangler/versions.d.ts +13 -0
  139. package/dist/wrangler/versions.js +38 -0
  140. package/package.json +39 -19
  141. package/template/astrale.config.ts +30 -31
  142. package/dist/build/codegen/identity.d.ts +0 -10
  143. package/dist/build/codegen/identity.d.ts.map +0 -1
  144. package/dist/build/codegen/identity.js +0 -32
  145. package/dist/build/codegen/identity.js.map +0 -1
  146. package/dist/build/codegen/merge.d.ts.map +0 -1
  147. package/dist/build/codegen/merge.js.map +0 -1
  148. package/dist/build/codegen/worker.d.ts +0 -12
  149. package/dist/build/codegen/worker.d.ts.map +0 -1
  150. package/dist/build/codegen/worker.js +0 -40
  151. package/dist/build/codegen/worker.js.map +0 -1
  152. package/dist/build/codegen/wrangler.d.ts.map +0 -1
  153. package/dist/build/codegen/wrangler.js.map +0 -1
  154. package/dist/build/frontend.d.ts +0 -27
  155. package/dist/build/frontend.d.ts.map +0 -1
  156. package/dist/build/frontend.js +0 -252
  157. package/dist/build/frontend.js.map +0 -1
  158. package/dist/build/index.d.ts.map +0 -1
  159. package/dist/build/index.js.map +0 -1
  160. package/dist/build/parse-output.d.ts +0 -27
  161. package/dist/build/parse-output.d.ts.map +0 -1
  162. package/dist/build/parse-output.js +0 -58
  163. package/dist/build/parse-output.js.map +0 -1
  164. package/dist/build/prepare.d.ts +0 -18
  165. package/dist/build/prepare.d.ts.map +0 -1
  166. package/dist/build/prepare.js +0 -138
  167. package/dist/build/prepare.js.map +0 -1
  168. package/dist/build/worker.d.ts +0 -15
  169. package/dist/build/worker.d.ts.map +0 -1
  170. package/dist/build/worker.js +0 -21
  171. package/dist/build/worker.js.map +0 -1
  172. package/dist/build/wrangler-cli.d.ts +0 -88
  173. package/dist/build/wrangler-cli.d.ts.map +0 -1
  174. package/dist/build/wrangler-cli.js +0 -283
  175. package/dist/build/wrangler-cli.js.map +0 -1
  176. package/dist/cloudflare.d.ts.map +0 -1
  177. package/dist/cloudflare.js.map +0 -1
  178. package/dist/index.d.ts.map +0 -1
  179. package/dist/index.js.map +0 -1
  180. package/dist/params.d.ts.map +0 -1
  181. package/dist/params.js.map +0 -1
  182. package/dist/worker/fetch.d.ts.map +0 -1
  183. package/dist/worker/fetch.js.map +0 -1
  184. package/dist/worker/index.d.ts.map +0 -1
  185. package/dist/worker/index.js.map +0 -1
  186. package/src/build/codegen/identity.ts +0 -40
  187. package/src/build/codegen/merge.ts +0 -92
  188. package/src/build/codegen/worker.ts +0 -53
  189. package/src/build/codegen/wrangler.ts +0 -128
  190. package/src/build/frontend.ts +0 -298
  191. package/src/build/index.ts +0 -29
  192. package/src/build/parse-output.ts +0 -60
  193. package/src/build/prepare.ts +0 -189
  194. package/src/build/worker.ts +0 -37
  195. package/src/build/wrangler-cli.ts +0 -372
  196. package/src/cloudflare.ts +0 -275
  197. package/src/index.ts +0 -21
  198. package/src/params.ts +0 -92
  199. package/src/worker/fetch.ts +0 -46
  200. package/src/worker/index.ts +0 -335
  201. package/src/worker/tsconfig.json +0 -10
package/README.md CHANGED
@@ -2,10 +2,101 @@
2
2
 
3
3
  Cloudflare Worker deployment adapter for Astrale Domains.
4
4
 
5
- During the SDK beta program, install the beta cohort explicitly:
5
+ During the SDK beta program, install the beta package set explicitly:
6
6
 
7
7
  ```bash
8
8
  npm install @astrale-os/sdk@beta @astrale-os/adapter-cloudflare@beta
9
9
  ```
10
10
 
11
- Bare installs return to stable releases when the cohort is promoted and npm `latest` advances.
11
+ Bare installs return to stable releases when the package set is promoted and npm `latest` advances.
12
+
13
+ One `cloudflare()` value configures one Project Environment. `astrale-domain dev <environment>`
14
+ builds locally and deploys each admitted Worker and frontend update remotely through the same path
15
+ as `deploy`; it starts no local Worker, Vite server, or tunnel. Omitting `route` uses the observed
16
+ stable `*.workers.dev` issuer. Add `installation: { instance: '...' }` to the Project Environment
17
+ when generic tooling should reconcile the ready Release onto an Astrale Kernel.
18
+
19
+ One watcher serializes its own updates. For an existing Worker, it uploads a candidate, reconciles
20
+ configured triggers, and stages the candidate at 0% while the previous version retains 100% of normal
21
+ HTTP traffic. Exact-version probes verify Publication, Bundle, and serving identity before promotion;
22
+ serving the Publication also initializes the Application Runtime. After promotion, normal requests
23
+ must prove that exact version again. A failed candidate remains at 0% and can be replaced on retry.
24
+ Bundled View routes must also serve the prepared browser-file generation before readiness passes.
25
+ This covers frontend-only changes without changing the Schema or reinstalling the Domain. HTML is
26
+ revalidated on every use and transient asset misses are not cached; ordinary successful asset
27
+ responses keep their cache policy. Frontend files are answered by the Worker's small startup module
28
+ without loading the execution Service, which each such file starts loading in the background for the
29
+ calls the View makes next.
30
+ The first deployment uses ordinary Worker provisioning because no previous version exists to retain.
31
+ An existing traffic-split rollout must be resolved before this single-version workflow can continue.
32
+
33
+ A direct Cloudflare target shared across machines must still have one external writer, normally a
34
+ CI/CD concurrency group. Live deployment checks detect competing changes but are not an atomic
35
+ compare-and-swap or distributed lock. Use separate Worker targets for uncoordinated development.
36
+ Routes, custom domains, schedules, and other non-versioned provider settings are reconciled through
37
+ Wrangler before candidate probing; they can remain changed after a failed attempt. Candidate readiness
38
+ protects the HTTP implementation, not an atomic rollback of external resources or trigger settings.
39
+
40
+ When an Environment also declares `installation`, the SDK excludes another local checkout that
41
+ targets the same resolved `Kernel issuer + Domain origin` (including bookmark aliases), reconciles
42
+ exact installed Release evidence, and opens
43
+ the default View when the Application has a frontend. These are Project-tooling behaviors rather
44
+ than Cloudflare adapter responsibilities.
45
+
46
+ ## Frontend files
47
+
48
+ The Worker runs before Workers Static Assets on every request and owns frontend response headers
49
+ and routing, for `cloudflare()` and `astrale()` deployments alike. Frontend preparation therefore
50
+ refuses a built frontend whose root contains `_headers`, `_redirects`, or `.assetsignore`, in any
51
+ letter case, as a file or a directory. Wrangler would apply them as asset configuration in a direct
52
+ deployment, while a managed deployment would serve them as public files. The refusal happens while
53
+ the artifact is prepared, before any provider change. Vite copies its public directory (`public/`
54
+ by default) to that root: remove them there, or stop the plugin that emits them. The same names
55
+ below the root, such as `docs/_headers`, remain ordinary files.
56
+
57
+ The Worker is also the only server-side code, so preparation likewise refuses a root name starting
58
+ with `_worker.js`, the name of a Cloudflare Pages worker script: a `_worker.js` file or directory,
59
+ or a sibling such as `_worker.js.map`. Wrangler refuses to upload these as assets, since they may
60
+ hold server-side code, so a direct deployment would fail at upload, while a managed deployment would
61
+ publish them. Unlike the names above, the match is case-sensitive, as Wrangler's is: `_Worker.js`
62
+ and a nested `docs/_worker.js` remain ordinary files. Remove such a file from the public directory,
63
+ or rename it if it is a browser script.
64
+
65
+ ## Provider-local staging
66
+
67
+ Managed Cloudflare providers may stage immutable implementation candidates without exposing their
68
+ identity to Publications or installed Kernels:
69
+
70
+ ```ts
71
+ import { stagedWorkerName } from '@astrale-os/adapter-cloudflare/release'
72
+ ```
73
+
74
+ This subpath is runtime-safe. `stagedWorkerName(providerDeployment)` addresses one private staged
75
+ candidate. The public Worker name and `/invoke` endpoint remain stable across compatible
76
+ implementation and Schema updates. Provider staging identity never enters Release, Publication,
77
+ Kernel routing, or graph identity.
78
+
79
+ ## Material for a custom Worker entrypoint
80
+
81
+ Workers with provider-specific routes or environment initialization can reuse the adapter's
82
+ material emission without adopting the entire generated entrypoint:
83
+
84
+ ```ts
85
+ import { generateBuildMaterialModule } from '@astrale-os/adapter-cloudflare/build'
86
+ import { writeFile } from 'node:fs/promises'
87
+
88
+ // build is an admitted Build returned by compile(application).
89
+ await writeFile('src/build-material.gen.ts', generateBuildMaterialModule(build))
90
+ ```
91
+
92
+ The generated TypeScript module exports `loadBuildMaterial()`. Call it from the
93
+ `load` callback of `generatedCloudflareWorkerEntry` alongside the application's Runtime.
94
+ It constructs the same verified, deduplicated material as the adapter's generated Service;
95
+ allocation is deferred until the factory is called and the SDK deep-freezes it before use.
96
+ The generated file needs only a type import from the SDK. Keep its compiler and runtime SDK
97
+ versions aligned, and regenerate it when either the Application or that SDK version changes.
98
+
99
+ Such an entrypoint can keep the same fast frontend path by answering from
100
+ `cloudflareFrontDoor()` (`@astrale-os/adapter-cloudflare/worker/front`, which reaches no SDK
101
+ runtime module) before importing its Service, and calling that Service's `prepare()` through
102
+ `waitUntil` when the front door served a frontend file.
@@ -0,0 +1,14 @@
1
+ import type { Deployment } from '@astrale-os/sdk/deployment';
2
+ import type { Release } from '@astrale-os/sdk/deployment/release';
3
+ import { verifyReadiness } from '@astrale-os/sdk/deployment/verify';
4
+ import type { CloudflareParams } from './params.js';
5
+ import { artifact } from './build/artifact.js';
6
+ import { type CloudflareDeployDependencies } from './deploy/index.js';
7
+ import { signingIdentity } from './identity/source.js';
8
+ export interface CloudflareDependencies extends CloudflareDeployDependencies {
9
+ readonly artifact: typeof artifact;
10
+ readonly signingIdentity: typeof signingIdentity;
11
+ }
12
+ export declare function cloudflare(parameters?: CloudflareParams): Deployment<CloudflareParams>;
13
+ export declare function cloudflareWithDependencies(parameters: CloudflareParams, dependencies: CloudflareDependencies): Deployment<CloudflareParams>;
14
+ export declare function waitForReadiness(verify: typeof verifyReadiness, release: Release, signal?: AbortSignal): Promise<void>;
@@ -0,0 +1,82 @@
1
+ import { defineAdapter, defineDeployment } from '@astrale-os/sdk/deployment/adapter';
2
+ import { verifyReadiness } from '@astrale-os/sdk/deployment/verify';
3
+ import { createRequire } from 'node:module';
4
+ import { artifact, materialize } from './build/artifact.js';
5
+ import { verifyWorkerFrontend } from './build/frontend/readiness.js';
6
+ import { deployCloudflare } from './deploy/index.js';
7
+ import { versionReadinessFetch } from './deploy/readiness.js';
8
+ import { signingIdentity } from './identity/source.js';
9
+ import { runWranglerRollout } from './wrangler/rollout.js';
10
+ import { runWranglerDeploymentStatus } from './wrangler/status.js';
11
+ const packageVersion = createRequire(import.meta.url)('../package.json')
12
+ .version;
13
+ export function cloudflare(parameters = {}) {
14
+ return cloudflareWithDependencies(parameters, {
15
+ artifact,
16
+ materialize,
17
+ runWranglerRollout,
18
+ runWranglerDeploymentStatus,
19
+ signingIdentity,
20
+ waitForReadiness: (release, signal, version, worker, workerName) => waitForReadiness(async (release, options) => {
21
+ const checks = {
22
+ ...options,
23
+ fetch: versionReadinessFetch(release.addressing.publicUrl, version, globalThis.fetch, workerName, release.addressing.issuer),
24
+ };
25
+ await verifyReadiness(release, checks);
26
+ await verifyWorkerFrontend(release, worker, checks);
27
+ }, release, signal),
28
+ });
29
+ }
30
+ export function cloudflareWithDependencies(parameters, dependencies) {
31
+ const adapter = defineAdapter({
32
+ name: 'cloudflare',
33
+ version: packageVersion,
34
+ prepare: dependencies.artifact,
35
+ deploy: (parameters, context) => deployCloudflare(parameters, context, dependencies),
36
+ secretsFile: (parameters) => parameters.secrets,
37
+ });
38
+ return defineDeployment(adapter, parameters);
39
+ }
40
+ export async function waitForReadiness(verify, release, signal) {
41
+ const deadline = Date.now() + 90_000;
42
+ let last;
43
+ while (Date.now() < deadline) {
44
+ throwIfAborted(signal);
45
+ try {
46
+ await verify(release, {
47
+ signal: signal === undefined
48
+ ? AbortSignal.timeout(5_000)
49
+ : AbortSignal.any([signal, AbortSignal.timeout(5_000)]),
50
+ });
51
+ return;
52
+ }
53
+ catch (cause) {
54
+ throwIfAborted(signal);
55
+ last = cause;
56
+ await pause(signal);
57
+ }
58
+ }
59
+ throw last instanceof Error ? last : new Error('Cloudflare Release did not become ready.');
60
+ }
61
+ function pause(signal) {
62
+ return new Promise((resolve, reject) => {
63
+ const timer = setTimeout(done, 1_000);
64
+ const abort = () => done(abortError(signal));
65
+ signal?.addEventListener('abort', abort, { once: true });
66
+ function done(cause) {
67
+ clearTimeout(timer);
68
+ signal?.removeEventListener('abort', abort);
69
+ if (cause === undefined)
70
+ resolve();
71
+ else
72
+ reject(cause);
73
+ }
74
+ });
75
+ }
76
+ function throwIfAborted(signal) {
77
+ if (signal?.aborted)
78
+ throw abortError(signal);
79
+ }
80
+ function abortError(signal) {
81
+ return signal?.reason instanceof Error ? signal.reason : new Error('Deployment interrupted.');
82
+ }
@@ -0,0 +1,7 @@
1
+ import type { ArtifactSource, PrepareContext } from '@astrale-os/sdk/deployment/adapter';
2
+ import type { CloudflareParams } from '../params.js';
3
+ export { materialize } from './materialize.js';
4
+ /** Prepare one portable Worker whose public provider address remains stable across builds. */
5
+ export declare function artifact(params: CloudflareParams, context: PrepareContext): Promise<ArtifactSource>;
6
+ /** Prepare the complete portable Cloudflare Worker without direct Wrangler placement files. */
7
+ export declare function prepareWorkerArtifact(params: CloudflareParams, context: PrepareContext): Promise<ArtifactSource>;
@@ -0,0 +1,170 @@
1
+ import { addressing } from '@astrale-os/sdk/deployment/release';
2
+ import { mkdir, mkdtemp, rm } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { SIGNING_IDENTITY_BINDING } from '../identity/binding.js';
5
+ import { workerDeployment } from '../release/index.js';
6
+ import { generateWranglerConfig } from './codegen/wrangler.js';
7
+ import { deploymentAddressing, resolveRouter, workerName } from './configuration.js';
8
+ import { frontendFiles } from './frontend/files.js';
9
+ import { frontendRevision } from './frontend/revision.js';
10
+ import { encodeWorkerArtifactManifest, inferMediaType, workerContentDigest, WORKER_MANIFEST_PATH, } from './worker/artifact.manifest.js';
11
+ import { prepareExecution, RELEASE_ENTRY, RELEASE_SERVICE, runtimeVars, } from './worker/execution.prepare.js';
12
+ import { admitWorkerRuntimeConfiguration } from './worker/runtime.js';
13
+ export { materialize } from './materialize.js';
14
+ const encoder = new TextEncoder();
15
+ /** Prepare one portable Worker whose public provider address remains stable across builds. */
16
+ export async function artifact(params, context) {
17
+ return prepare(params, context, true);
18
+ }
19
+ /** Prepare the complete portable Cloudflare Worker without direct Wrangler placement files. */
20
+ export async function prepareWorkerArtifact(params, context) {
21
+ return prepare(params, context, false);
22
+ }
23
+ async function prepare(params, context, direct) {
24
+ const stateDirectory = join(context.projectDir, '.astrale');
25
+ await mkdir(stateDirectory, { recursive: true });
26
+ const directory = await mkdtemp(join(stateDirectory, 'prepare-'));
27
+ try {
28
+ const router = resolveRouter(params.router);
29
+ const name = workerName(params, context.build.schema.compiled.root.origin, context.environment);
30
+ const revision = context.build.schema.compiled.root.revision;
31
+ const configuredIssuer = deploymentAddressing(params);
32
+ // `frontend` stays the served file list every branch below already reads; `addressed` rides
33
+ // alongside it into the Worker, where it decides which of those files a browser may retain.
34
+ const { files: frontend, addressed } = await frontendFiles({
35
+ frontend: context.build.frontend,
36
+ projectDir: context.projectDir,
37
+ output: join(directory, 'frontend'),
38
+ recordSource: context.recordSource,
39
+ signal: context.signal,
40
+ });
41
+ const modules = await prepareExecution({
42
+ params,
43
+ context,
44
+ directory,
45
+ name,
46
+ direct,
47
+ configuredIssuer,
48
+ router,
49
+ ...(frontend.length === 0 ? {} : { frontendRevision: frontendRevision(frontend) }),
50
+ ...(addressed.length === 0 ? {} : { frontendAddressed: addressed }),
51
+ });
52
+ const releaseConfig = generateWranglerConfig({
53
+ workerName: name,
54
+ main: `./${RELEASE_ENTRY}`,
55
+ ...(params.route === undefined ? {} : { route: params.route }),
56
+ vars: runtimeVars(params, configuredIssuer),
57
+ secretBindings: [SIGNING_IDENTITY_BINDING],
58
+ modules: { baseDir: './bundle', rules: [{ type: 'ESModule', globs: ['service.mjs'] }] },
59
+ ...(context.build.frontend?.source.kind === 'vite'
60
+ ? {
61
+ frontend: {
62
+ directory: './frontend',
63
+ },
64
+ }
65
+ : {}),
66
+ ...(router === undefined
67
+ ? {}
68
+ : { router: { binding: router.binding, service: router.service } }),
69
+ ...(params.wrangler === undefined ? {} : { wrangler: params.wrangler }),
70
+ selfBinding: false,
71
+ });
72
+ const runtime = admitWorkerRuntimeConfiguration(releaseConfig);
73
+ const deployment = workerDeployment({
74
+ release: {
75
+ entrypoint: RELEASE_ENTRY,
76
+ modules: [
77
+ { path: RELEASE_ENTRY, kind: 'esm', content: modules.entry },
78
+ { path: RELEASE_SERVICE, kind: 'esm', content: modules.service },
79
+ ],
80
+ },
81
+ runtime,
82
+ bindings: {
83
+ vars: runtime.vars,
84
+ services: runtime.services,
85
+ requiredSecrets: [SIGNING_IDENTITY_BINDING],
86
+ },
87
+ ...(frontend.length === 0
88
+ ? {}
89
+ : {
90
+ assets: {
91
+ files: frontend.map((file) => {
92
+ const contentType = file.mediaType ?? inferMediaType(file.path);
93
+ return {
94
+ path: `/${file.path}`,
95
+ content: file.bytes(),
96
+ ...(contentType === undefined ? {} : { contentType }),
97
+ };
98
+ }),
99
+ notFound: 'none',
100
+ runWorkerFirst: true,
101
+ htmlHandling: 'none',
102
+ },
103
+ }),
104
+ });
105
+ const manifest = encodeWorkerArtifactManifest({
106
+ origin: context.build.schema.compiled.root.origin,
107
+ revision,
108
+ deployment,
109
+ release: {
110
+ entrypoint: RELEASE_ENTRY,
111
+ modules: [
112
+ { path: RELEASE_ENTRY, kind: 'esm', digest: workerContentDigest(modules.entry) },
113
+ { path: RELEASE_SERVICE, kind: 'esm', digest: workerContentDigest(modules.service) },
114
+ ],
115
+ },
116
+ runtime: {
117
+ compatibilityDate: runtime.compatibilityDate,
118
+ compatibilityFlags: runtime.compatibilityFlags,
119
+ },
120
+ bindings: {
121
+ vars: runtime.vars,
122
+ services: runtime.services,
123
+ requiredSecrets: [SIGNING_IDENTITY_BINDING],
124
+ },
125
+ ...(frontend.length === 0
126
+ ? {}
127
+ : {
128
+ assets: {
129
+ files: frontend.map((file) => {
130
+ const contentType = file.mediaType ?? inferMediaType(file.path);
131
+ return {
132
+ path: `/${file.path}`,
133
+ artifactPath: `frontend/${file.path}`,
134
+ digest: workerContentDigest(file.bytes()),
135
+ ...(contentType === undefined ? {} : { contentType }),
136
+ };
137
+ }),
138
+ notFound: 'none',
139
+ runWorkerFirst: true,
140
+ htmlHandling: 'none',
141
+ },
142
+ }),
143
+ });
144
+ const files = [
145
+ { path: RELEASE_ENTRY, content: modules.entry },
146
+ { path: RELEASE_SERVICE, content: modules.service },
147
+ { path: WORKER_MANIFEST_PATH, content: manifest },
148
+ ...frontend.map((file) => ({
149
+ path: `frontend/${file.path}`,
150
+ content: file.bytes(),
151
+ })),
152
+ ...(direct ? [{ path: 'wrangler.jsonc', content: encoder.encode(releaseConfig) }] : []),
153
+ ];
154
+ return Object.freeze({
155
+ entrypoint: RELEASE_ENTRY,
156
+ files: Object.freeze(files),
157
+ addressing: configuredIssuer === undefined
158
+ ? Object.freeze({ kind: 'provider-assigned', claim: name })
159
+ : Object.freeze({
160
+ kind: 'configured',
161
+ addressing: addressing(params.identityIssuer ?? configuredIssuer, {
162
+ publicUrl: configuredIssuer,
163
+ }),
164
+ }),
165
+ });
166
+ }
167
+ finally {
168
+ await rm(directory, { recursive: true, force: true });
169
+ }
170
+ }
@@ -0,0 +1 @@
1
+ export declare function admitWorkerBundle(path: string): Promise<void>;
@@ -0,0 +1,9 @@
1
+ import { pathToFileURL } from 'node:url';
2
+ export async function admitWorkerBundle(path) {
3
+ const loaded = (await import(`${pathToFileURL(path).href}?admit=${Date.now()}`));
4
+ if (loaded.default === null ||
5
+ typeof loaded.default !== 'object' ||
6
+ typeof Reflect.get(loaded.default, 'fetch') !== 'function') {
7
+ throw new TypeError('Generated Worker bundle does not export a Fetch handler.');
8
+ }
9
+ }
@@ -0,0 +1,2 @@
1
+ /** Prove emitted Worker reachability excludes authoring, compilation, and broad Core Schema owners. */
2
+ export declare function assertRuntimeClosure(metafilePath: string): Promise<void>;
@@ -0,0 +1,22 @@
1
+ import { readWranglerMetafile } from './metafile.js';
2
+ const FORBIDDEN_RUNTIME_INPUTS = [
3
+ '/v1/builder/',
4
+ '/v1/compiled/compiler/',
5
+ '/node_modules/ajv/',
6
+ '/node_modules/re2js/',
7
+ '/kernel-core/domain/',
8
+ '/core/domain/',
9
+ '/kernel-core/schema/index.',
10
+ '/core/schema/index.',
11
+ ];
12
+ /** Prove emitted Worker reachability excludes authoring, compilation, and broad Core Schema owners. */
13
+ export async function assertRuntimeClosure(metafilePath) {
14
+ const metafile = await readWranglerMetafile(metafilePath);
15
+ const forbidden = Object.keys(metafile.inputs).filter((input) => {
16
+ const normalized = `/${input.replaceAll('\\', '/')}`.replace(/(\/node_modules\/@astrale-os\/kernel-[^/]+)\/dist\//gu, '$1/');
17
+ return FORBIDDEN_RUNTIME_INPUTS.some((fragment) => normalized.includes(fragment));
18
+ });
19
+ if (forbidden.length > 0) {
20
+ throw new Error(`Cloudflare Worker reaches build-side modules: ${forbidden.sort().join(', ')}.`);
21
+ }
22
+ }
@@ -0,0 +1,3 @@
1
+ export { generateExecutionEntry } from '../worker/codegen/entry.js';
2
+ export { generateExecutionService } from '../worker/codegen/service.js';
3
+ export type { ExecutionCodegenOptions } from '../worker/codegen/service.js';
@@ -0,0 +1,2 @@
1
+ export { generateExecutionEntry } from '../worker/codegen/entry.js';
2
+ export { generateExecutionService } from '../worker/codegen/service.js';
@@ -17,4 +17,3 @@
17
17
  * the caller (`generateWranglerConfig`), not here — this stays a generic merge.
18
18
  */
19
19
  export declare function deepMergeConfig(base: Record<string, unknown>, overlay: Record<string, unknown>): Record<string, unknown>;
20
- //# sourceMappingURL=merge.d.ts.map
@@ -88,4 +88,3 @@ function isPlainObject(v) {
88
88
  function isPrimitive(v) {
89
89
  return v === null || (typeof v !== 'object' && typeof v !== 'function');
90
90
  }
91
- //# sourceMappingURL=merge.js.map
@@ -13,16 +13,26 @@
13
13
  */
14
14
  export interface WranglerCodegenOptions {
15
15
  workerName: string;
16
+ /** Provider-ready entrypoint relative to the generated config. */
17
+ main?: string;
16
18
  /** Full custom hostname for a routed deploy (e.g. 'crm.acme.dev'). */
17
19
  route?: string;
18
20
  /** Exact materialized local frontend; absence means no ASSETS binding. */
19
21
  frontend?: {
20
22
  readonly directory: string;
21
- readonly routes: readonly string[];
22
- readonly dev: boolean;
23
23
  };
24
24
  /** Plain (non-secret) vars to bake in. */
25
25
  vars?: Record<string, string>;
26
+ /** Secret binding names required by generated Worker code. */
27
+ secretBindings?: readonly string[];
28
+ /** Modules retained outside the startup entry and loaded on demand. */
29
+ modules?: {
30
+ readonly baseDir: string;
31
+ readonly rules: readonly {
32
+ readonly type: 'ESModule' | 'CompiledWasm' | 'Text' | 'Data';
33
+ readonly globs: readonly string[];
34
+ }[];
35
+ };
26
36
  /** Add the SELF service binding (autobinding). */
27
37
  selfBinding: boolean;
28
38
  /**
@@ -44,4 +54,3 @@ export interface WranglerCodegenOptions {
44
54
  wrangler?: Record<string, unknown>;
45
55
  }
46
56
  export declare function generateWranglerConfig(opts: WranglerCodegenOptions): string;
47
- //# sourceMappingURL=wrangler.d.ts.map
@@ -12,15 +12,17 @@
12
12
  * (extra bindings: KV, R2, D1, queues, …) — see `mergeUserConfig`.
13
13
  */
14
14
  import { deepMergeConfig } from './merge.js';
15
- // Wrangler 4.121.0's pinned workerd accepts dates through 2026-08-11.
15
+ // Keep the generated date on the runtime baseline qualified with Wrangler 4.123.0.
16
16
  const COMPATIBILITY_DATE = '2026-08-11';
17
17
  export function generateWranglerConfig(opts) {
18
18
  const config = {
19
19
  name: opts.workerName,
20
- main: './worker.gen.ts',
20
+ main: opts.main ?? './worker.gen.ts',
21
21
  compatibility_date: COMPATIBILITY_DATE,
22
- compatibility_flags: ['nodejs_compat'],
23
- workers_dev: true,
22
+ // Domain execution calls its Kernel through the invocation's public issuer. Cloudflare must
23
+ // route same-zone callbacks through the public front door instead of bypassing Worker routes.
24
+ compatibility_flags: ['nodejs_compat', 'global_fetch_strictly_public'],
25
+ workers_dev: opts.route === undefined,
24
26
  version_metadata: { binding: 'ASTRALE_VERSION_METADATA' },
25
27
  observability: { enabled: true },
26
28
  };
@@ -31,19 +33,10 @@ export function generateWranglerConfig(opts) {
31
33
  config.assets = {
32
34
  directory: opts.frontend.directory,
33
35
  binding: 'ASSETS',
34
- run_worker_first: opts.frontend.dev
35
- ? true
36
- : [
37
- '/invoke',
38
- '/invoke/*',
39
- '/install',
40
- '/install/*',
41
- '/health',
42
- '/health/*',
43
- '/.well-known',
44
- '/.well-known/*',
45
- ...opts.frontend.routes,
46
- ],
36
+ html_handling: 'none',
37
+ // Match the portable Worker artifact: frontend routing and sandbox-safe asset
38
+ // response headers are owned by the Worker for both deployment adapters.
39
+ run_worker_first: true,
47
40
  };
48
41
  }
49
42
  const services = [];
@@ -57,6 +50,18 @@ export function generateWranglerConfig(opts) {
57
50
  if (opts.vars && Object.keys(opts.vars).length > 0) {
58
51
  config.vars = opts.vars;
59
52
  }
53
+ if (opts.secretBindings && opts.secretBindings.length > 0) {
54
+ config.secrets = { required: [...opts.secretBindings] };
55
+ }
56
+ if (opts.modules !== undefined) {
57
+ config.find_additional_modules = true;
58
+ config.base_dir = opts.modules.baseDir;
59
+ config.rules = opts.modules.rules.map((rule) => ({
60
+ type: rule.type,
61
+ globs: [...rule.globs],
62
+ fallthrough: true,
63
+ }));
64
+ }
60
65
  const merged = opts.wrangler ? mergeUserConfig(config, opts.wrangler) : config;
61
66
  return JSON.stringify(merged, null, 2) + '\n';
62
67
  }
@@ -67,7 +72,11 @@ const ADAPTER_OWNED_KEYS = [
67
72
  'assets',
68
73
  'routes',
69
74
  'compatibility_date',
75
+ 'workers_dev',
70
76
  'version_metadata',
77
+ 'secrets',
78
+ 'find_additional_modules',
79
+ 'base_dir',
71
80
  ];
72
81
  /**
73
82
  * Deep-merge the dev's raw wrangler overlay over the generated config, after
@@ -83,4 +92,3 @@ function mergeUserConfig(base, user) {
83
92
  }
84
93
  return deepMergeConfig(base, user);
85
94
  }
86
- //# sourceMappingURL=wrangler.js.map
@@ -0,0 +1,2 @@
1
+ import type { CloudflareParams } from '../../params.js';
2
+ export declare function deploymentAddressing(parameters: CloudflareParams): string | undefined;
@@ -0,0 +1,17 @@
1
+ import { addressing } from '@astrale-os/sdk/deployment/release';
2
+ export function deploymentAddressing(parameters) {
3
+ if (parameters.identityIssuer !== undefined) {
4
+ addressing(parameters.identityIssuer);
5
+ if (parameters.route === undefined && parameters.addressing === undefined) {
6
+ throw new TypeError('A stable Cloudflare identityIssuer requires explicit public addressing.');
7
+ }
8
+ }
9
+ const routed = parameters.route === undefined ? undefined : addressing(`https://${parameters.route}`).issuer;
10
+ if (parameters.addressing === undefined)
11
+ return routed;
12
+ const configured = addressing(parameters.addressing).issuer;
13
+ if (routed !== undefined && configured !== routed) {
14
+ throw new TypeError('Cloudflare route and addressing identify different origins.');
15
+ }
16
+ return configured;
17
+ }
@@ -0,0 +1,2 @@
1
+ import type { CloudflareParams } from '../../params.js';
2
+ export declare function workerInvocationTimeout(value: CloudflareParams['invocationTimeoutMs']): number | undefined;
@@ -0,0 +1,9 @@
1
+ const MAXIMUM_TIMER_MS = 2_147_483_647;
2
+ export function workerInvocationTimeout(value) {
3
+ if (value === undefined)
4
+ return undefined;
5
+ if (!Number.isSafeInteger(value) || value <= 0 || value > MAXIMUM_TIMER_MS) {
6
+ throw new TypeError('Cloudflare invocationTimeoutMs must be a positive integer within the platform timer range.');
7
+ }
8
+ return value;
9
+ }
@@ -0,0 +1,2 @@
1
+ import type { CloudflareParams } from '../../params.js';
2
+ export declare function workerRequestLimit(value: CloudflareParams['maximumRequestBytes']): number | undefined;
@@ -0,0 +1,9 @@
1
+ const MAXIMUM_REQUEST_BYTES = 16 * 1024 * 1024;
2
+ export function workerRequestLimit(value) {
3
+ if (value === undefined)
4
+ return undefined;
5
+ if (!Number.isSafeInteger(value) || value <= 0 || value > MAXIMUM_REQUEST_BYTES) {
6
+ throw new TypeError('Cloudflare maximumRequestBytes must be a positive integer at most 16 MiB.');
7
+ }
8
+ return value;
9
+ }
@@ -0,0 +1,7 @@
1
+ import type { CloudflareParams } from '../../params.js';
2
+ export declare function resolveRouter(input: CloudflareParams['router']): {
3
+ readonly binding: string;
4
+ readonly service: string;
5
+ readonly hostSuffix: string;
6
+ readonly minLabels: number;
7
+ } | undefined;
@@ -0,0 +1,11 @@
1
+ export function resolveRouter(input) {
2
+ if (input === false || input === undefined)
3
+ return undefined;
4
+ const value = input;
5
+ return Object.freeze({
6
+ binding: value.binding ?? 'ROUTER',
7
+ service: value.service ?? 'admin-router',
8
+ hostSuffix: value.hostSuffix ?? '.astrale.ai',
9
+ minLabels: value.minLabels ?? 4,
10
+ });
11
+ }
@@ -0,0 +1,2 @@
1
+ import type { CloudflareParams } from '../../params.js';
2
+ export declare function workerName(parameters: CloudflareParams, origin: string, environment?: string): string;