@astrale-domains/services 0.4.6 → 0.4.7

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 (76) hide show
  1. package/README.md +163 -6
  2. package/dist/schema/index.d.ts +2 -2
  3. package/dist/schema/index.js +1 -1
  4. package/dist/schema/modules/deployment/classes/cloudflare-deployment.d.ts +366 -0
  5. package/dist/schema/modules/deployment/classes/cloudflare-deployment.js +20 -0
  6. package/dist/schema/modules/deployment/classes/deployment.d.ts +93 -2
  7. package/dist/schema/modules/deployment/classes/deployment.js +27 -3
  8. package/dist/schema/modules/deployment/errors/deployment-hosting-unavailable.d.ts +7 -0
  9. package/dist/schema/modules/deployment/errors/deployment-hosting-unavailable.js +8 -0
  10. package/dist/schema/modules/deployment/errors/deployment-label-not-found.d.ts +12 -0
  11. package/dist/schema/modules/deployment/errors/deployment-label-not-found.js +11 -0
  12. package/dist/schema/modules/deployment/errors/deployment-not-found.d.ts +10 -0
  13. package/dist/schema/modules/deployment/errors/deployment-not-found.js +11 -0
  14. package/dist/schema/modules/deployment/errors/deployment-registry-only.d.ts +11 -0
  15. package/dist/schema/modules/deployment/errors/deployment-registry-only.js +12 -0
  16. package/dist/schema/modules/deployment/errors/index.d.ts +4 -0
  17. package/dist/schema/modules/deployment/errors/index.js +4 -0
  18. package/dist/schema/modules/deployment/functions/deploy-cloudflare-deployment.d.ts +170 -0
  19. package/dist/schema/modules/deployment/functions/deploy-cloudflare-deployment.js +14 -0
  20. package/dist/schema/modules/deployment/functions/describe-deployment-hosting.d.ts +8 -0
  21. package/dist/schema/modules/deployment/functions/describe-deployment-hosting.js +11 -0
  22. package/dist/schema/modules/deployment/functions/expire-deployment-previews.d.ts +16 -0
  23. package/dist/schema/modules/deployment/functions/expire-deployment-previews.js +14 -0
  24. package/dist/schema/modules/deployment/functions/index.d.ts +11 -0
  25. package/dist/schema/modules/deployment/functions/index.js +11 -0
  26. package/dist/schema/modules/deployment/functions/list-cloudflare-deployment-secret-names.d.ts +5 -0
  27. package/dist/schema/modules/deployment/functions/list-cloudflare-deployment-secret-names.js +4 -0
  28. package/dist/schema/modules/deployment/functions/list-cloudflare-deployments.d.ts +58 -0
  29. package/dist/schema/modules/deployment/functions/list-cloudflare-deployments.js +10 -0
  30. package/dist/schema/modules/deployment/functions/list-deployment-secret-names.d.ts +4 -0
  31. package/dist/schema/modules/deployment/functions/list-deployment-secret-names.js +6 -0
  32. package/dist/schema/modules/deployment/functions/read-deployment-last-calls.d.ts +10 -0
  33. package/dist/schema/modules/deployment/functions/read-deployment-last-calls.js +13 -0
  34. package/dist/schema/modules/deployment/functions/retain-deployment.d.ts +12 -0
  35. package/dist/schema/modules/deployment/functions/retain-deployment.js +13 -0
  36. package/dist/schema/modules/deployment/functions/retire-deployment.d.ts +23 -0
  37. package/dist/schema/modules/deployment/functions/retire-deployment.js +17 -0
  38. package/dist/schema/modules/deployment/functions/set-cloudflare-deployment-secret.d.ts +18 -0
  39. package/dist/schema/modules/deployment/functions/set-cloudflare-deployment-secret.js +7 -0
  40. package/dist/schema/modules/deployment/functions/set-deployment-secret.d.ts +14 -0
  41. package/dist/schema/modules/deployment/functions/set-deployment-secret.js +3 -0
  42. package/dist/schema/modules/deployment/index.d.ts +5 -3
  43. package/dist/schema/modules/deployment/index.js +4 -2
  44. package/dist/schema/modules/deployment/policies/act-for-organization.d.ts +6 -0
  45. package/dist/schema/modules/deployment/policies/act-for-organization.js +10 -0
  46. package/dist/schema/modules/deployment/policies/index.d.ts +1 -0
  47. package/dist/schema/modules/deployment/policies/index.js +1 -0
  48. package/dist/schema/modules/deployment/states/deployment-lifecycle.d.ts +6 -3
  49. package/dist/schema/modules/deployment/states/deployment-lifecycle.js +6 -4
  50. package/dist/schema/modules/deployment/types/deployment-hosting.d.ts +94 -0
  51. package/dist/schema/modules/deployment/types/deployment-hosting.js +19 -0
  52. package/dist/schema/modules/deployment/types/deployment-request.d.ts +161 -0
  53. package/dist/schema/modules/deployment/types/deployment-request.js +40 -0
  54. package/dist/schema/modules/deployment/types/deployment-response.d.ts +109 -0
  55. package/dist/schema/modules/deployment/types/deployment-response.js +36 -0
  56. package/dist/schema/modules/deployment/types/deployment-retention.d.ts +37 -1
  57. package/dist/schema/modules/deployment/types/deployment-retention.js +41 -1
  58. package/dist/schema/modules/deployment/types/deployment-retire.d.ts +30 -0
  59. package/dist/schema/modules/deployment/types/deployment-retire.js +18 -0
  60. package/dist/schema/modules/deployment/types/deployment-secret-digest.d.ts +17 -0
  61. package/dist/schema/modules/deployment/types/deployment-secret-digest.js +14 -0
  62. package/dist/schema/modules/deployment/types/deployment-secret.d.ts +59 -0
  63. package/dist/schema/modules/deployment/types/deployment-secret.js +52 -0
  64. package/dist/schema/modules/deployment/types/deployment-summary.d.ts +165 -0
  65. package/dist/schema/modules/deployment/types/deployment-summary.js +38 -0
  66. package/dist/schema/modules/deployment/types/frozen-configuration.d.ts +52 -0
  67. package/dist/schema/modules/deployment/types/frozen-configuration.js +55 -0
  68. package/dist/schema/modules/deployment/types/index.d.ts +18 -2
  69. package/dist/schema/modules/deployment/types/index.js +9 -1
  70. package/dist/schema/modules/service/classes/cloudflare-worker.d.ts +4 -4
  71. package/dist/schema/modules/service/classes/service.d.ts +2 -2
  72. package/dist/schema/modules/service/functions/set-worker-secret.d.ts +2 -2
  73. package/dist/schema/modules/service/types/legacy/service-deployment-content.js +8 -1
  74. package/dist/schema/schema.d.ts +456 -12
  75. package/dist/schema/schema.js +2 -1
  76. package/package.json +10 -5
package/README.md CHANGED
@@ -46,6 +46,154 @@ protocols behind neutral SDK Integrations and stores only admitted lifecycle evi
46
46
  never by its author, so Services refuses it as a caller variable or secret on every deployment
47
47
  path and in secret management.
48
48
 
49
+ ## Immutable deployments
50
+
51
+ The Admin-hosted Services runtime hosts publishers' releases as immutable deployments, one per
52
+ label, on the publisher's line. Three static `CloudflareDeployment` Methods serve them, and two
53
+ instance Methods rotate one deployment's secrets; any authenticated identity of the Admin instance
54
+ may call them. A Domain Worker serves every Kernel that
55
+ installs it, but deployments are hosted for the Admin instance's Kernel alone
56
+ (`SERVICES_DEPLOYMENT_KERNEL`): its graph is the line registry, while the deployments namespace and
57
+ the routing KV are shared. Any other Kernel finds hosting unavailable before anything is read.
58
+
59
+ - `deploy` takes a `DeploymentRequestV1`: the release's origin, environment, addressing, label,
60
+ build digest, frozen configuration, record fields, Worker bundle and the environment's current
61
+ secrets. It is a non-durable Action, never a Workflow, so no Execution, step result or journal
62
+ entry holds its input. Before any read it recomputes the build digest and the label, admits the
63
+ record with the SDK, and refuses a service binding, a router other than the logical
64
+ `admin-router`, a reserved binding name, or secrets other than exactly the declared ones. Only
65
+ the platform organisation (`SERVICES_PLATFORM_OWNER`) deploys on readable lines.
66
+ - `deploy` then observes the line under the Services Domain credential and proves, on the caller's
67
+ own session, that the caller acts for the organisation it names (`OwnLine` on a held line,
68
+ `ActForOrganization` for a new one) before any Mutation. A new label is created under a graph
69
+ lease. The provider uploads it create-only, with `ASTRALE_BUILD_DIGEST`, `ASTRALE_SETTINGS` (router
70
+ binding `ROUTER`), a signing key Services generates for this deployment alone, and the request's
71
+ secrets. It adopts a script only when resuming a deployment the graph already held from an earlier
72
+ attempt, and only when the script's tags name the same artifact, line and key and this Kernel's
73
+ installation; any other script under the label is another deployment's, refused
74
+ `deployment-conflict`, and its secrets are never written. It checks that the uploaded version
75
+ itself serves before it activates the label through the routing KV `record:<label>`. The graph then records the deployment active with its key id, script etag and
76
+ a keyed HMAC-SHA256 digest of its secrets; no value, private key or version id is stored.
77
+ - the same release again is the same label: `deploy` answers `reused`. Its secrets are the
78
+ environment's current values: when they match the recorded digests it answers `unchanged` and
79
+ writes nothing; otherwise it rewrites the changed values in place on that deployment alone and
80
+ answers `updated` (same script, URL, issuer and key, no new release). Every other deployment of
81
+ the line keeps its own secrets.
82
+ - `setSecret({ name, value })` and `secrets({})` are instance Methods of one `CloudflareDeployment`.
83
+ `setSecret` rewrites one secret in place on that deployment only, and only a name its frozen
84
+ configuration declares (`secret-undeclared` otherwise); there is no `deleteSecret`, since a bound
85
+ name is part of the release, and the signing key never rotates. `secrets` lists the names its
86
+ script binds, never a value. Like `deploy`, any authenticated identity may call them, because a
87
+ publisher holds no `can_use` on Services' Functions and an `authorized` Method requires it of
88
+ every non-Root caller: before anything is read, the Kernel answers `OwnDeployment` for the caller
89
+ on its own session, and any other caller finds no such deployment (`DEPLOYMENT_NOT_FOUND`). If the
90
+ Admin instance ever grants publishers `can_use` on these Methods, they become `authorized` with
91
+ the `OwnDeployment` Policy instead. Both are non-durable Actions, so no Execution, step result or
92
+ journal entry holds a value.
93
+ - a `setSecret` refusal is `{ kind: 'rejected', reason, message, retryAfter? }`.
94
+ `service-unavailable` with `retryAfter` (the deployment is being created, another operation
95
+ holds it, or the provider failed) is retried then; without `retryAfter` the deployment cannot be
96
+ rotated in place (its creation failed, it is retiring or retired, or the script under its label is
97
+ not the recorded one, which is the operator's to inspect), and the message says what can.
98
+ - an in-place rewrite, by `deploy` or `setSecret`, runs under the deployment's graph lease. It
99
+ compares the values with the keyed digests and writes only the changed ones; it first forgets the
100
+ digests of the names it writes and records the new digests only once every write succeeded, so a
101
+ recorded digest always names the value last written. A provider failure answers
102
+ `service-unavailable` with `retryAfter`, and a rerun, with any values, converges. The script is
103
+ first checked to be the recorded one (code hash, artifact tag, key tag, installation tag); a
104
+ rewrite never touches another script. Workers for Platforms keeps the script's name, code hash,
105
+ tags and bindings across a secret write and mints a new provider version, which serves the new
106
+ value a few seconds later (OPS-2 X1): propagation is eventually consistent, and nothing records a
107
+ version id.
108
+ - `hosting` returns the routing domain and how the caller's lines read (readable for the platform
109
+ organisation, opaque otherwise). `list` returns the deployments of the lines the caller holds. It
110
+ reads the held lines under the Services Domain credential, narrowed in the Query to the origin
111
+ and environment asked for, and keeps the lines a batched `Identity.can(OwnLine)` grants the
112
+ caller: a caller-mode read sees none of the lines a caller holds through `extends_with`
113
+ ([kernel#1138](https://github.com/astrale-os/kernel/issues/1138), the removal trigger of this
114
+ filter). One listing reads at most 16,384 matching held lines and fails beyond, so a listing
115
+ without an origin is bounded by the platform's held lines. A deployment whose stored record or
116
+ configuration this Services SDK no longer admits, for instance after a stricter decoder, is
117
+ still listed, from the facts Services owns, with its record exactly as stored (typed as JSON for
118
+ that row): the listing never fails on it, and the consumer admits the record itself. Deploy,
119
+ retain, retire, `setSecret`, `secrets` and `expirePreviews` fail closed on such a deployment
120
+ with an undeclared internal error (5000) and write nothing; `lastCalls` answers from its facts.
121
+ - deleting a Service, or an instance and its Services, never addresses a publisher's deployment.
122
+
123
+ Only a runtime whose Environment vars set `SERVICES_DEPLOYMENT_HOST` (the deployments' routing
124
+ domain) hosts deployments; every other runtime answers `hosting-unavailable`. Such a runtime refuses
125
+ to boot without `SERVICES_DEPLOYMENT_KERNEL` (the Admin Kernel's issuer URL),
126
+ `SERVICES_SECRET_DIGEST_KEY` (at least 32 characters, kept for the life of the environment: the
127
+ recorded digests depend on it), the `SERVICE_DEPLOYMENTS` dispatch binding to the environment's
128
+ deployments namespace, and `CLOUDFLARE_SCHEDULE_KV_ID`, the routing KV that activates a label, and
129
+ refuses a `SERVICES_PLATFORM_OWNER` that is not an Identity id. Hosting is declared once, by the
130
+ Environment's `vars` in `astrale.config.ts`: the same vars decide the `SERVICE_DEPLOYMENTS` binding,
131
+ and the configuration refuses a secrets file that sets a hosting var. [Real-Kernel
132
+ proof](tests/kernel/README.md).
133
+
134
+ ### Retention and retirement
135
+
136
+ A deployment is a `preview` until the registry Domain marks it `published`; only a preview expires.
137
+ Four more `CloudflareDeployment` Methods manage what stays served. Retirement, retention and
138
+ revival name a deployment by its label, script etag, artifact tag and configuration digest, never
139
+ by a provider version id.
140
+
141
+ - `retire` is the instance Method of the line holder's emergency stop. Any authenticated identity
142
+ may call it, because a publisher holds no `can_use` on Services' Functions and an `authorized`
143
+ Method requires it of every non-Root caller: before anything is read, the Kernel answers
144
+ `OwnDeployment` for the caller on its own session, and any other caller finds no such deployment
145
+ (`DEPLOYMENT_NOT_FOUND`). If the Admin instance ever grants publishers `can_use` on it, it becomes
146
+ `authorized` with the `OwnDeployment` Policy instead. It withdraws the deployment for good in two
147
+ phases. The graph records it `retiring` first, so no deploy reuses it; the same Mutation evicts
148
+ the operation lease of any operation writing the script, such as an in-place rewrite of its
149
+ secrets, which then records nothing. Then the routing KV gets the tombstone
150
+ `retirement:<label>` = `withdrawn`. The dispatcher
151
+ answers a label with a tombstone `DEPLOYMENT_RETIRED` (`410`) and keeps serving its
152
+ `deployment.json` from `record:<label>`, which stays. The first call answers `retiring` with
153
+ `retryAfterMs`. A call 65 seconds after the tombstone, once the dispatcher's retirement probe
154
+ answers `DEPLOYMENT_RETIRED`, deletes the script and its signing key and answers `retired`. A
155
+ withdrawn label is never served again: deploying the same release is refused
156
+ `deployment-retired`.
157
+ - `retain` marks one preview `published`. Only the registry Domain's principal calls it, acting as
158
+ itself; it is the installed, unfrozen Domain whose origin is `SERVICES_REGISTRY_ORIGIN`. Services
159
+ reads the caller's Domain node by id under its own credential, which is why it requires read on
160
+ the Kernel's `Domain` Class; nothing the caller presents decides it. An authenticated caller
161
+ carries Identity ids but no Domain origin, and read on `Identity` does not reach a Domain's node.
162
+ Every instance that installs this Services version grants that read, so Services can read the
163
+ origin and frozen flag of each Domain installed there; only the Admin instance's hosting runtime
164
+ uses it. The requirement goes once the Kernel gives a handler its caller's Domain origin. A line
165
+ holder, or an identity acting for the registry, is refused `DEPLOYMENT_REGISTRY_ONLY`. The mark
166
+ is monotonic and idempotent, and it never undoes a retirement in progress: a preview marked after
167
+ its expiry started still retires, and a redeploy of the same release revives it.
168
+ - `lastCalls` returns the last call of up to 100 labels the caller holds (as the Kernel answers
169
+ `OwnDeployment` on the caller's session), or any labels for the registry; an unknown label and
170
+ another organisation's both answer `DEPLOYMENT_LABEL_NOT_FOUND`. It reads the data points the dispatcher writes per admitted call, through the Analytics
171
+ Engine SQL API, and the last call recorded in the graph. A label nobody called reads `null`. It
172
+ reads only the facts Services recorded, so it answers for a listed deployment whose stored
173
+ record this SDK no longer admits.
174
+ - `expirePreviews` is the registry's pass. A preview expires 30 days after its activation (its
175
+ creation, or its revival) or its last call, whichever is later; every activation records its
176
+ instant, and a pass refuses an active preview without one rather than expire it on its creation. The pass is a plan unless the runtime sets
177
+ `SERVICES_PREVIEW_EXPIRY=enforce` and the caller passes `apply: true`: it answers the `planned`
178
+ labels and retires none. Applied, it retires them in two phases with the tombstone `expired` and
179
+ answers `retired` and `pending` labels; the next pass completes the pending ones. Either way it
180
+ records later calls, so each preview's `expiresAt` follows its traffic. `limit` bounds the
181
+ deployment writes of one pass (64 by default), and retirements come first.
182
+
183
+ An expired label revives. When the same owner deploys the same release (same label, so same
184
+ artifact and configuration) again, the deployment resumes from `retired`. It is uploaded
185
+ create-only with a new signing key, and the activation republishes the same `record:<label>`
186
+ before it removes the `expired` tombstone. An instance that pins the label is served the same
187
+ release digest at the same URL. A `withdrawn` tombstone is never removed.
188
+
189
+ `SERVICES_REGISTRY_ORIGIN` and `SERVICES_PREVIEW_EXPIRY` (`plan`, the default, or `enforce`) are
190
+ Environment vars of a hosting runtime, refused in a secrets file and refused without
191
+ `SERVICES_DEPLOYMENT_HOST`. Without a registry origin no caller is the registry, and `retain` and
192
+ `expirePreviews` are refused. `admin-beta` names `admin.astrale.ai` and keeps expiry a plan.
193
+ Reading last calls needs the API token's Account Analytics Read permission. `pnpm
194
+ provider:deployment-audit` lists the deployments namespace read-only
195
+ ([operator](providers/cloudflare/operator/README.md)).
196
+
49
197
  The View, CLI, and agent consumers read the named Service Queries directly; there is intentionally
50
198
  no list Function wrapping `listServicesQuery`. Deployment, secrets, schedules, logs, and deletion
51
199
  are Workflows because they coordinate admitted caller intent with external effects. Receiver Methods
@@ -114,11 +262,17 @@ publishers' deployments outside the instances that install them. It is a Worker
114
262
  `services-domain-admin-beta` at `https://services-admin.beta.astrale.ai`, on the beta data plane the
115
263
  Admin instance's Services already manage. Its plain vars name the router Worker
116
264
  (`ASTRALE_ROUTER_WORKER`), the routing domain under which deployments are addressed
117
- (`SERVICES_DEPLOYMENT_HOST`, served by the Services dispatcher) and the registry Domain
118
- (`SERVICES_REGISTRY_ORIGIN`). `.env.admin-beta` must set `SERVICES_SECRET_DIGEST_KEY`, the key of
119
- each hosted deployment's secret digest. The runtime keys HMAC-SHA256 with the UTF-8 bytes of the value
120
- as written, never base64-decoded, so the configuration refuses, before any deployment effect, a file
121
- without it or with a value shorter than 32 UTF-8 bytes.
265
+ (`SERVICES_DEPLOYMENT_HOST`, served by the Services dispatcher), the Admin instance's Kernel, the
266
+ only one it hosts deployments for (`SERVICES_DEPLOYMENT_KERNEL`, `https://admin.eu.beta.astrale.ai/api`),
267
+ and the registry Domain (`SERVICES_REGISTRY_ORIGIN`). These vars are the only declaration of
268
+ hosting: they also bind `SERVICE_DEPLOYMENTS`. `.env.admin-beta` must set
269
+ `SERVICES_SECRET_DIGEST_KEY`, the key of each hosted deployment's secret digest, and the dispatch
270
+ namespace and routing KV the runtime boots with. The runtime keys HMAC-SHA256 with the UTF-8 bytes
271
+ of the digest key as written, never base64-decoded, so the configuration refuses, before any
272
+ deployment effect, a file without them, a digest key shorter than 32 UTF-8 bytes, or a file that
273
+ sets a hosting var. `SERVICES_PLATFORM_OWNER` is not set yet: until it names the platform
274
+ organisation's Identity id on the Admin instance, every line is opaque and a readable deploy is
275
+ refused.
122
276
 
123
277
  It retains the issuer `https://services.beta.astrale.ai` and its signing key, as services-v2 does.
124
278
  The Admin instance's Services are bound to that issuer, and the Kernel refuses an issuer change when
@@ -137,7 +291,10 @@ The operator sets it up once:
137
291
  `publication.identity.issuer`, and the frozen runtime whose `/.well-known/astrale/domain.json`
138
292
  declares that revision: it is the rollback URL. Go on only if the issuer is
139
293
  `https://services.beta.astrale.ai`; any other issuer makes step 6 an issuer change, which the
140
- Kernel refuses.
294
+ Kernel refuses. Check as well that the Admin instance's Kernel issuer is admin-beta's
295
+ `SERVICES_DEPLOYMENT_KERNEL`; otherwise every deploy answers `hosting-unavailable`. Before the
296
+ first readable deploy, read the platform organisation's Identity id there and set it as
297
+ admin-beta's `SERVICES_PLATFORM_OWNER` var in a reviewed change to `astrale.config.ts`.
141
298
  2. Create `.env.admin-beta` (mode 600) from `.env.example` with the beta data-plane coordinates the
142
299
  Admin instance's Services manage today (account, token, dispatch namespace, routing domain
143
300
  `svc.eu.beta.astrale.ai`, schedule KV, dispatcher, zone, Admin target) and a new
@@ -3,5 +3,5 @@ export type { ServicesDomain, ServicesSchema } from './schema.js';
3
3
  export { artifact, artifactModule, assetBundle, assetFile, deployServiceInput, deployServiceOutput, resourceLimits, revisionedDeployment, } from './modules/service/index.js';
4
4
  export type { ArtifactModule, AssetBundle, DeployServiceInput, DeployServiceOutput, ResourceLimits, } from './modules/service/index.js';
5
5
  export { CloudflareWorker, OwnService, Service, TraverseOwnedService, service_owned_by, } from './modules/service/index.js';
6
- export { CloudflareDeployment, Deployment, DeploymentLine, OwnDeployment, OwnLine, TraverseOwnedLine, TraverseOwnedLineDeployment, deploymentCommit, deploymentLifecycle, deploymentRecord, deploymentRetention, deploymentRetirement, deployment_on_line, line_owned_by, } from './modules/deployment/index.js';
7
- export type { DeploymentLifecycle, DeploymentLifecycleEvent, DeploymentRecord, DeploymentRetention, DeploymentRetirement, } from './modules/deployment/index.js';
6
+ export { ActForOrganization, CloudflareDeployment, Deployment, DeploymentLine, OwnDeployment, OwnLine, TraverseOwnedLine, TraverseOwnedLineDeployment, deploymentCommit, deploymentHosting, deploymentLabel, deploymentLifecycle, deploymentRecord, deploymentRejection, deploymentRequest, deploymentResponse, deploymentRetention, deploymentRetirement, deploymentSecretDigests, deploymentSecretRejection, deploymentSummary, deployment_on_line, expirePreviewsOutput, frozenConfiguration, lastCallsOutput, listedDeploymentSummary, line_owned_by, MAXIMUM_LAST_CALL_LABELS, MAXIMUM_PREVIEW_EXPIRY_WRITES, retireDeploymentOutput, unadmittedDeploymentSummary, } from './modules/deployment/index.js';
7
+ export type { DeploymentHosting, DeploymentLifecycle, DeploymentLifecycleEvent, DeploymentRecord, DeploymentRejection, DeploymentRejectionReason, DeploymentRequest, DeploymentResponse, DeploymentRetention, DeploymentRetirement, DeploymentSecretDigest, DeploymentSecretRejection, DeploymentSummary, ExpirePreviewsResult, FrozenConfiguration, ListedDeploymentSummary, RetireDeploymentResult, UnadmittedDeploymentSummary, } from './modules/deployment/index.js';
@@ -1,4 +1,4 @@
1
1
  export { schema } from './schema.js';
2
2
  export { artifact, artifactModule, assetBundle, assetFile, deployServiceInput, deployServiceOutput, resourceLimits, revisionedDeployment, } from './modules/service/index.js';
3
3
  export { CloudflareWorker, OwnService, Service, TraverseOwnedService, service_owned_by, } from './modules/service/index.js';
4
- export { CloudflareDeployment, Deployment, DeploymentLine, OwnDeployment, OwnLine, TraverseOwnedLine, TraverseOwnedLineDeployment, deploymentCommit, deploymentLifecycle, deploymentRecord, deploymentRetention, deploymentRetirement, deployment_on_line, line_owned_by, } from './modules/deployment/index.js';
4
+ export { ActForOrganization, CloudflareDeployment, Deployment, DeploymentLine, OwnDeployment, OwnLine, TraverseOwnedLine, TraverseOwnedLineDeployment, deploymentCommit, deploymentHosting, deploymentLabel, deploymentLifecycle, deploymentRecord, deploymentRejection, deploymentRequest, deploymentResponse, deploymentRetention, deploymentRetirement, deploymentSecretDigests, deploymentSecretRejection, deploymentSummary, deployment_on_line, expirePreviewsOutput, frozenConfiguration, lastCallsOutput, listedDeploymentSummary, line_owned_by, MAXIMUM_LAST_CALL_LABELS, MAXIMUM_PREVIEW_EXPIRY_WRITES, retireDeploymentOutput, unadmittedDeploymentSummary, } from './modules/deployment/index.js';
@@ -25,6 +25,7 @@ export declare const CloudflareDeployment: import("@astrale-os/sdk/schema").Auth
25
25
  };
26
26
  readonly failed: {
27
27
  readonly retry: "deploying";
28
+ readonly retire: "retiring";
28
29
  };
29
30
  }, "deploying">, {
30
31
  required?: boolean;
@@ -53,9 +54,65 @@ export declare const CloudflareDeployment: import("@astrale-os/sdk/schema").Auth
53
54
  }, import("zod/v4/core").$strict>>;
54
55
  }, import("zod/v4/core").$strict>>;
55
56
  }, import("zod/v4/core").$strict>;
57
+ configuration: import("zod").ZodObject<{
58
+ format: import("zod").ZodLiteral<"astrale.deployment.configuration">;
59
+ version: import("zod").ZodLiteral<1>;
60
+ vars: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodString>;
61
+ settings: import("zod").ZodObject<{
62
+ maximumRequestBytes: import("zod").ZodNumber;
63
+ invocationTimeoutMs: import("zod").ZodNumber;
64
+ tokenExchange: import("zod").ZodUnion<readonly [import("zod").ZodLiteral<false>, import("zod").ZodObject<{
65
+ maximumLifetimeSeconds: import("zod").ZodNumber;
66
+ }, import("zod/v4/core").$strict>]>;
67
+ durableOptions: import("zod").ZodOptional<import("zod").ZodObject<{
68
+ retentionMs: import("zod").ZodOptional<import("zod").ZodNumber>;
69
+ retry: import("zod").ZodOptional<import("zod").ZodObject<{
70
+ initialIntervalMs: import("zod").ZodOptional<import("zod").ZodNumber>;
71
+ maxAttempts: import("zod").ZodOptional<import("zod").ZodNumber>;
72
+ maxIntervalMs: import("zod").ZodOptional<import("zod").ZodNumber>;
73
+ }, import("zod/v4/core").$strict>>;
74
+ stepTimeoutMs: import("zod").ZodOptional<import("zod").ZodNumber>;
75
+ }, import("zod/v4/core").$strict>>;
76
+ }, import("zod/v4/core").$strict>;
77
+ runtime: import("zod").ZodObject<{
78
+ compatibilityDate: import("zod").ZodString;
79
+ compatibilityFlags: import("zod").ZodArray<import("zod").ZodString>;
80
+ }, import("zod/v4/core").$strict>;
81
+ bindings: import("zod").ZodObject<{
82
+ services: import("zod").ZodArray<import("zod").ZodObject<{
83
+ name: import("zod").ZodString;
84
+ service: import("zod").ZodString;
85
+ }, import("zod/v4/core").$strict>>;
86
+ dispatchNamespaces: import("zod").ZodArray<import("zod").ZodObject<{
87
+ name: import("zod").ZodString;
88
+ namespace: import("zod").ZodString;
89
+ }, import("zod/v4/core").$strict>>;
90
+ secrets: import("zod").ZodArray<import("zod").ZodString>;
91
+ }, import("zod/v4/core").$strict>;
92
+ router: import("zod").ZodUnion<readonly [import("zod").ZodLiteral<false>, import("zod").ZodObject<{
93
+ service: import("zod").ZodString;
94
+ hostSuffix: import("zod").ZodString;
95
+ minLabels: import("zod").ZodNumber;
96
+ }, import("zod/v4/core").$strict>]>;
97
+ }, import("zod/v4/core").$strict>;
98
+ secretDigests: import("@astrale-os/sdk/schema").AuthoredProperty<import("zod").ZodArray<import("zod").ZodObject<{
99
+ name: import("zod").ZodString;
100
+ digest: import("zod").ZodString;
101
+ }, import("zod/v4/core").$strict>>, {
102
+ readonly required: false;
103
+ }>;
104
+ scriptEtag: import("@astrale-os/sdk/schema").AuthoredProperty<import("zod").ZodString, {
105
+ readonly required: false;
106
+ }>;
56
107
  signingKeyId: import("@astrale-os/sdk/schema").AuthoredProperty<import("zod").ZodString, {
57
108
  readonly required: false;
58
109
  }>;
110
+ activatedAt: import("@astrale-os/sdk/schema").AuthoredProperty<Readonly<{
111
+ readonly type: 'string';
112
+ readonly 'x-astrale-value-kind': 'instant';
113
+ }>, {
114
+ readonly required: false;
115
+ }>;
59
116
  lastCallAt: import("@astrale-os/sdk/schema").AuthoredProperty<Readonly<{
60
117
  readonly type: 'string';
61
118
  readonly 'x-astrale-value-kind': 'instant';
@@ -90,7 +147,316 @@ export declare const CloudflareDeployment: import("@astrale-os/sdk/schema").Auth
90
147
  readonly required: false;
91
148
  }>;
92
149
  };
150
+ readonly methods: {
151
+ setSecret: import("@astrale-os/sdk/schema").Method<import("@astrale-os/sdk/schema").CallableProjection<{
152
+ name: string;
153
+ value: string;
154
+ }, {
155
+ readonly mode: 'value';
156
+ readonly value: {
157
+ name: string;
158
+ } | {
159
+ kind: "rejected";
160
+ reason: "secret-undeclared" | "service-unavailable";
161
+ message: string;
162
+ retryAfter?: string | undefined;
163
+ };
164
+ }, "authenticated", false, true, undefined>>;
165
+ secrets: import("@astrale-os/sdk/schema").Method<import("@astrale-os/sdk/schema").CallableProjection<Record<string, never>, {
166
+ readonly mode: 'value';
167
+ readonly value: string[];
168
+ }, "authenticated", false, true, undefined>>;
169
+ };
93
170
  }>];
171
+ readonly methods: {
172
+ deploy: import("@astrale-os/sdk/schema").Method<import("@astrale-os/sdk/schema").CallableProjection<{
173
+ format: "astrale.services.deployment-request";
174
+ version: 1;
175
+ organization?: string | undefined;
176
+ origin: string;
177
+ environment: string;
178
+ addressing: "opaque" | "readable";
179
+ label: string;
180
+ buildDigest: string;
181
+ configuration: {
182
+ format: "astrale.deployment.configuration";
183
+ version: 1;
184
+ vars: Record<string, string>;
185
+ settings: {
186
+ maximumRequestBytes: number;
187
+ invocationTimeoutMs: number;
188
+ tokenExchange: false | {
189
+ maximumLifetimeSeconds: number;
190
+ };
191
+ durableOptions?: {
192
+ retentionMs?: number | undefined;
193
+ retry?: {
194
+ initialIntervalMs?: number | undefined;
195
+ maxAttempts?: number | undefined;
196
+ maxIntervalMs?: number | undefined;
197
+ } | undefined;
198
+ stepTimeoutMs?: number | undefined;
199
+ } | undefined;
200
+ };
201
+ runtime: {
202
+ compatibilityDate: string;
203
+ compatibilityFlags: string[];
204
+ };
205
+ bindings: {
206
+ services: {
207
+ name: string;
208
+ service: string;
209
+ }[];
210
+ dispatchNamespaces: {
211
+ name: string;
212
+ namespace: string;
213
+ }[];
214
+ secrets: string[];
215
+ };
216
+ router: false | {
217
+ service: string;
218
+ hostSuffix: string;
219
+ minLabels: number;
220
+ };
221
+ };
222
+ record: {
223
+ releaseDigest: string;
224
+ schemaRevision: string;
225
+ schemaBundle: string;
226
+ commit: {
227
+ sha: string;
228
+ dirty: boolean;
229
+ base?: {
230
+ version: string;
231
+ distance: number;
232
+ } | undefined;
233
+ } | null;
234
+ };
235
+ bundle: {
236
+ entrypoint: string;
237
+ modules: ({
238
+ name: string;
239
+ kind?: "data" | "esm" | "text" | "wasm" | undefined;
240
+ content: {
241
+ encoding: "gzip" | "identity";
242
+ decodedSize: number;
243
+ contentBase64: string;
244
+ } | {
245
+ encoding: "gzip" | "identity";
246
+ decodedSize: number;
247
+ contentBase64Chunks: string[];
248
+ };
249
+ } | {
250
+ contentBase64: string;
251
+ name: string;
252
+ kind?: "data" | "esm" | "text" | "wasm" | undefined;
253
+ } | {
254
+ contentBase64Chunks: string[];
255
+ name: string;
256
+ kind?: "data" | "esm" | "text" | "wasm" | undefined;
257
+ })[];
258
+ assets?: {
259
+ files: ({
260
+ path: string;
261
+ contentType?: string | undefined;
262
+ content: {
263
+ encoding: "gzip" | "identity";
264
+ decodedSize: number;
265
+ contentBase64: string;
266
+ } | {
267
+ encoding: "gzip" | "identity";
268
+ decodedSize: number;
269
+ contentBase64Chunks: string[];
270
+ };
271
+ } | {
272
+ contentBase64: string;
273
+ path: string;
274
+ contentType?: string | undefined;
275
+ } | {
276
+ contentBase64Chunks: string[];
277
+ path: string;
278
+ contentType?: string | undefined;
279
+ })[];
280
+ notFound?: "404-page" | "none" | "single-page-application" | undefined;
281
+ runWorkerFirst?: boolean | undefined;
282
+ htmlHandling?: "none" | undefined;
283
+ } | undefined;
284
+ };
285
+ secrets: Record<string, string>;
286
+ readiness?: {
287
+ paths: string[];
288
+ } | undefined;
289
+ }, {
290
+ readonly mode: 'value';
291
+ readonly value: {
292
+ kind: "rejected";
293
+ reason: "address-mismatch" | "build-mismatch" | "deployment-conflict" | "deployment-retired" | "hosting-unavailable" | "invalid-deployment" | "line-owned-elsewhere" | "service-unavailable";
294
+ message: string;
295
+ retryAfter?: string | undefined;
296
+ } | {
297
+ kind: "deployed";
298
+ state: "created" | "reused";
299
+ secrets: {
300
+ state: "bound" | "unchanged" | "updated";
301
+ };
302
+ deployment: {
303
+ id: string;
304
+ url: string;
305
+ label: string;
306
+ line: string;
307
+ owner: string;
308
+ state: "active" | "deploying" | "failed" | "retired" | "retiring";
309
+ retention: "preview" | "published";
310
+ createdAt: string;
311
+ lastCallAt?: string | undefined;
312
+ expiresAt?: string | undefined;
313
+ retiredAt?: string | undefined;
314
+ retirement?: "expired" | "withdrawn" | undefined;
315
+ signingKeyId: string;
316
+ record: {
317
+ format: "astrale.deployment-record";
318
+ version: 1;
319
+ origin: string;
320
+ environment: string;
321
+ releaseDigest: string;
322
+ buildDigest: string;
323
+ schemaRevision: string;
324
+ configuration: string;
325
+ providerScript: string;
326
+ commit: {
327
+ sha: string;
328
+ dirty: boolean;
329
+ base?: {
330
+ version: string;
331
+ distance: number;
332
+ } | undefined;
333
+ } | null;
334
+ };
335
+ };
336
+ };
337
+ }, "authenticated", true, false, undefined>>;
338
+ hosting: import("@astrale-os/sdk/schema").Method<import("@astrale-os/sdk/schema").CallableProjection<Record<string, never>, {
339
+ readonly mode: 'value';
340
+ readonly value: {
341
+ routingDomain: string;
342
+ addressing: "opaque" | "readable";
343
+ };
344
+ }, "authenticated", true, false, undefined>>;
345
+ list: import("@astrale-os/sdk/schema").Method<import("@astrale-os/sdk/schema").CallableProjection<{
346
+ origin?: string | undefined;
347
+ environment?: string | undefined;
348
+ }, {
349
+ readonly mode: 'value';
350
+ readonly value: {
351
+ deployments: ({
352
+ id: string;
353
+ url: string;
354
+ label: string;
355
+ line: string;
356
+ owner: string;
357
+ state: "active" | "deploying" | "failed" | "retired" | "retiring";
358
+ retention: "preview" | "published";
359
+ createdAt: string;
360
+ lastCallAt?: string | undefined;
361
+ expiresAt?: string | undefined;
362
+ retiredAt?: string | undefined;
363
+ retirement?: "expired" | "withdrawn" | undefined;
364
+ signingKeyId: string;
365
+ record: {
366
+ format: "astrale.deployment-record";
367
+ version: 1;
368
+ origin: string;
369
+ environment: string;
370
+ releaseDigest: string;
371
+ buildDigest: string;
372
+ schemaRevision: string;
373
+ configuration: string;
374
+ providerScript: string;
375
+ commit: {
376
+ sha: string;
377
+ dirty: boolean;
378
+ base?: {
379
+ version: string;
380
+ distance: number;
381
+ } | undefined;
382
+ } | null;
383
+ };
384
+ } | {
385
+ id: string;
386
+ url: string;
387
+ label: string;
388
+ line: string;
389
+ owner: string;
390
+ state: "active" | "deploying" | "failed" | "retired" | "retiring";
391
+ retention: "preview" | "published";
392
+ createdAt: string;
393
+ lastCallAt?: string | undefined;
394
+ expiresAt?: string | undefined;
395
+ retiredAt?: string | undefined;
396
+ retirement?: "expired" | "withdrawn" | undefined;
397
+ signingKeyId: string;
398
+ record: unknown;
399
+ })[];
400
+ };
401
+ }, "authenticated", true, false, undefined>>;
402
+ setSecret: import("@astrale-os/sdk/schema").Method<import("@astrale-os/sdk/schema").CallableProjection<{
403
+ name: string;
404
+ value: string;
405
+ }, {
406
+ readonly mode: 'value';
407
+ readonly value: {
408
+ name: string;
409
+ } | {
410
+ kind: "rejected";
411
+ reason: "secret-undeclared" | "service-unavailable";
412
+ message: string;
413
+ retryAfter?: string | undefined;
414
+ };
415
+ }, "authenticated", false, false, undefined>>;
416
+ secrets: import("@astrale-os/sdk/schema").Method<import("@astrale-os/sdk/schema").CallableProjection<Record<string, never>, {
417
+ readonly mode: 'value';
418
+ readonly value: string[];
419
+ }, "authenticated", false, false, undefined>>;
420
+ lastCalls: import("@astrale-os/sdk/schema").Method<import("@astrale-os/sdk/schema").CallableProjection<{
421
+ labels: string[];
422
+ }, {
423
+ readonly mode: 'value';
424
+ readonly value: Record<string, string | null>;
425
+ }, "authenticated", true, false, undefined>>;
426
+ expirePreviews: import("@astrale-os/sdk/schema").Method<import("@astrale-os/sdk/schema").CallableProjection<{
427
+ limit?: number | undefined;
428
+ apply?: boolean | undefined;
429
+ }, {
430
+ readonly mode: 'value';
431
+ readonly value: {
432
+ planned: string[];
433
+ retired: string[];
434
+ pending: string[];
435
+ };
436
+ }, "authenticated", true, false, undefined>>;
437
+ retain: import("@astrale-os/sdk/schema").Method<import("@astrale-os/sdk/schema").CallableProjection<{
438
+ label: string;
439
+ }, {
440
+ readonly mode: 'value';
441
+ readonly value: {
442
+ retention: "published";
443
+ };
444
+ }, "authenticated", true, false, undefined>>;
445
+ retire: import("@astrale-os/sdk/schema").Method<import("@astrale-os/sdk/schema").CallableProjection<Record<string, never>, {
446
+ readonly mode: 'value';
447
+ readonly value: {
448
+ kind: "retired";
449
+ } | {
450
+ kind: "retiring";
451
+ retryAfterMs: number;
452
+ } | {
453
+ kind: "rejected";
454
+ reason: "address-mismatch" | "build-mismatch" | "deployment-conflict" | "deployment-retired" | "hosting-unavailable" | "invalid-deployment" | "line-owned-elsewhere" | "service-unavailable";
455
+ message: string;
456
+ retryAfter?: string | undefined;
457
+ };
458
+ }, "authenticated", false, false, undefined>>;
459
+ };
94
460
  readonly policies: {
95
461
  read: () => import("@astrale-os/sdk/schema").Policy;
96
462
  };
@@ -1,10 +1,30 @@
1
1
  import { classIcon, nodeClass } from '@astrale-os/sdk/schema';
2
2
  import { CloudUpload } from '@astrale-os/sdk/schema/icons';
3
+ import { deployCloudflareDeployment } from '../functions/deploy-cloudflare-deployment.js';
4
+ import { describeDeploymentHosting } from '../functions/describe-deployment-hosting.js';
5
+ import { expireDeploymentPreviews } from '../functions/expire-deployment-previews.js';
6
+ import { listCloudflareDeploymentSecretNames } from '../functions/list-cloudflare-deployment-secret-names.js';
7
+ import { listCloudflareDeployments } from '../functions/list-cloudflare-deployments.js';
8
+ import { readDeploymentLastCalls } from '../functions/read-deployment-last-calls.js';
9
+ import { retainDeployment } from '../functions/retain-deployment.js';
10
+ import { retireDeployment } from '../functions/retire-deployment.js';
11
+ import { setCloudflareDeploymentSecret } from '../functions/set-cloudflare-deployment-secret.js';
3
12
  import { OwnDeployment } from '../policies/own-deployment.js';
4
13
  import { Deployment } from './deployment.js';
5
14
  export const CloudflareDeployment = nodeClass({
6
15
  description: 'One Deployment uploaded as the Workers for Platforms script its label names.',
7
16
  icon: classIcon.lucide(CloudUpload),
8
17
  extends: [Deployment],
18
+ methods: {
19
+ deploy: deployCloudflareDeployment,
20
+ hosting: describeDeploymentHosting,
21
+ list: listCloudflareDeployments,
22
+ setSecret: setCloudflareDeploymentSecret,
23
+ secrets: listCloudflareDeploymentSecretNames,
24
+ lastCalls: readDeploymentLastCalls,
25
+ expirePreviews: expireDeploymentPreviews,
26
+ retain: retainDeployment,
27
+ retire: retireDeployment,
28
+ },
9
29
  policies: { read: () => OwnDeployment },
10
30
  });