@astrale-os/sdk 0.5.0-beta.143 → 0.5.0-beta.144
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.
- package/README.md +25 -0
- package/dist/deployment/release/addressing.d.ts +6 -2
- package/dist/deployment/release/addressing.js +9 -4
- package/dist/deployment/release/publication/callables.js +1 -1
- package/dist/deployment/release/publication/routes.js +1 -1
- package/dist/deployment/release/publication/seal.js +3 -3
- package/dist/deployment/release/publication/views.js +1 -1
- package/dist/deployment/verify/preflight/artifact.js +1 -1
- package/dist/deployment/verify/readiness/deployment.js +2 -1
- package/dist/deployment/verify/readiness/publication.js +1 -1
- package/dist/execution/service/create.js +2 -0
- package/dist/execution/service/service.d.ts +1 -1
- package/dist/tooling/cli/development/report.js +1 -1
- package/dist/tooling/cli/evidence.js +1 -0
- package/dist/tooling/cli/installation/reconcile.js +1 -1
- package/dist/tooling/cli/orchestrate.js +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -46,6 +46,31 @@ Stop development watchers first, then run the project's checks and validate on d
|
|
|
46
46
|
Nothing is committed or deployed. A Shell update also requires checking the installed Shell revision.
|
|
47
47
|
Rerunning an upgrade synchronizes installation even when the manifest versions are already current.
|
|
48
48
|
|
|
49
|
+
## Move a runtime without changing its Domain identity
|
|
50
|
+
|
|
51
|
+
A Domain issuer is retained across installation upgrades. To deploy a new Cloudflare runtime for
|
|
52
|
+
selected instances, keep the existing signing identity and issuer while selecting a new public origin:
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
cloudflare({
|
|
56
|
+
route: 'services-v2.example.com',
|
|
57
|
+
workerName: 'services-v2',
|
|
58
|
+
identityIssuer: 'https://services.example.com',
|
|
59
|
+
signingIdentity: '.astrale/identity.json',
|
|
60
|
+
})
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The new Publication places its Bundle, Delivery, callables, Views and routes at the new origin.
|
|
64
|
+
Install that public URL on each intended instance. The Kernel verifies its Delivery against the
|
|
65
|
+
retained issuer's keys and preserves the Domain installation identity and owned data. Keep the
|
|
66
|
+
original issuer discovery endpoints and keys available; unadopted instances continue to use their
|
|
67
|
+
previous bindings. Deployment readiness checks the exact new Worker version separately from issuer
|
|
68
|
+
discovery. No uninstall or identity rotation is involved.
|
|
69
|
+
|
|
70
|
+
At the provider-neutral release boundary, use
|
|
71
|
+
`addressing('https://services.example.com', { publicUrl: 'https://services-v2.example.com' })`.
|
|
72
|
+
The one-argument form continues to use the issuer as the public URL.
|
|
73
|
+
|
|
49
74
|
## Handler authority and dependencies
|
|
50
75
|
|
|
51
76
|
Authenticated handlers use Domain self authority for `kernel`, `graph`, `query`, and `mutate`.
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { IssuerId } from '../../platform/auth/index.js';
|
|
2
|
-
/**
|
|
2
|
+
/** Stable Domain identity and public placement, independent of how a provider obtains them. */
|
|
3
3
|
export interface Addressing {
|
|
4
4
|
readonly issuer: IssuerId;
|
|
5
|
+
/** Public origin serving this Release; the issuer can remain on an older deployment. */
|
|
6
|
+
readonly publicUrl: IssuerId;
|
|
5
7
|
}
|
|
6
|
-
export declare function addressing(input: string
|
|
8
|
+
export declare function addressing(input: string, options?: {
|
|
9
|
+
readonly publicUrl?: string;
|
|
10
|
+
}): Addressing;
|
|
7
11
|
export declare function isAddressing(input: unknown): input is Addressing;
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { issuer } from '../../platform/auth/index.js';
|
|
2
2
|
const admittedAddressing = new WeakSet();
|
|
3
|
-
export function addressing(input) {
|
|
3
|
+
export function addressing(input, options = {}) {
|
|
4
|
+
const admitted = origin(input);
|
|
5
|
+
const publicUrl = options.publicUrl === undefined ? admitted : origin(options.publicUrl);
|
|
6
|
+
const value = Object.freeze({ issuer: admitted, publicUrl });
|
|
7
|
+
admittedAddressing.add(value);
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
function origin(input) {
|
|
4
11
|
let admitted;
|
|
5
12
|
let url;
|
|
6
13
|
try {
|
|
@@ -18,9 +25,7 @@ export function addressing(input) {
|
|
|
18
25
|
url.hash !== '') {
|
|
19
26
|
throw new TypeError('Addressing issuer must be an origin-only absolute HTTP(S) issuer.');
|
|
20
27
|
}
|
|
21
|
-
|
|
22
|
-
admittedAddressing.add(value);
|
|
23
|
-
return value;
|
|
28
|
+
return admitted;
|
|
24
29
|
}
|
|
25
30
|
export function isAddressing(input) {
|
|
26
31
|
return input !== null && typeof input === 'object' && admittedAddressing.has(input);
|
|
@@ -2,7 +2,7 @@ import * as publication from '@astrale-os/kernel-protocol/publication';
|
|
|
2
2
|
import { invocationPath } from '../invocation.js';
|
|
3
3
|
export function callables(build, addressing) {
|
|
4
4
|
const endpoint = publication.acceptInvocationEndpoints({
|
|
5
|
-
http: new URL(invocationPath(), addressing.
|
|
5
|
+
http: new URL(invocationPath(), addressing.publicUrl).href,
|
|
6
6
|
});
|
|
7
7
|
return Object.freeze(build.callables.map((callable) => Object.freeze({ callable, endpoint })));
|
|
8
8
|
}
|
|
@@ -18,7 +18,7 @@ export function seal(build, addressing) {
|
|
|
18
18
|
schema: {
|
|
19
19
|
revision: root.revision,
|
|
20
20
|
bundle: {
|
|
21
|
-
href: publication.bundleUrl(addressing.
|
|
21
|
+
href: publication.bundleUrl(addressing.publicUrl, build.schema.bundle.ref),
|
|
22
22
|
ref: build.schema.bundle.ref,
|
|
23
23
|
},
|
|
24
24
|
},
|
|
@@ -28,12 +28,12 @@ export function seal(build, addressing) {
|
|
|
28
28
|
callables: callables(build, addressing),
|
|
29
29
|
views: views(build, addressing),
|
|
30
30
|
},
|
|
31
|
-
delivery: publication.placeDelivery({ path: DELIVERY_PATH, authentication: { kind: 'public' } }, addressing.
|
|
31
|
+
delivery: publication.placeDelivery({ path: DELIVERY_PATH, authentication: { kind: 'public' } }, addressing.publicUrl, publication.bundleUrl(addressing.publicUrl, build.schema.bundle.ref)),
|
|
32
32
|
routes: routes(build, addressing),
|
|
33
33
|
});
|
|
34
34
|
const { domain } = evidenceOf(build);
|
|
35
35
|
return Object.freeze({
|
|
36
36
|
publication: sealed,
|
|
37
|
-
routes: protocolRoutes.bind(build.routes, sealed, domain),
|
|
37
|
+
routes: protocolRoutes.bind(build.routes, sealed, domain, addressing.publicUrl),
|
|
38
38
|
});
|
|
39
39
|
}
|
|
@@ -3,7 +3,7 @@ export function views(build, addressing) {
|
|
|
3
3
|
return Object.freeze([]);
|
|
4
4
|
const base = build.frontend.source.kind === 'external'
|
|
5
5
|
? `${build.frontend.source.origin}/`
|
|
6
|
-
: `${addressing.
|
|
6
|
+
: `${addressing.publicUrl.replace(/\/+$/u, '')}/`;
|
|
7
7
|
return Object.freeze(build.frontend.routes.map((route) => Object.freeze({
|
|
8
8
|
view: route.view,
|
|
9
9
|
href: new URL(route.path.replace(/^\//u, ''), base).href,
|
|
@@ -89,7 +89,7 @@ function evidenceBytes(build, source) {
|
|
|
89
89
|
bundle: build.schema.bundle.ref.digest,
|
|
90
90
|
entrypoint: source.entrypoint,
|
|
91
91
|
addressing: source.addressing.kind === 'configured'
|
|
92
|
-
? { kind: 'configured',
|
|
92
|
+
? { kind: 'configured', ...source.addressing.addressing }
|
|
93
93
|
: source.addressing,
|
|
94
94
|
})),
|
|
95
95
|
];
|
|
@@ -50,7 +50,8 @@ function verifyRelease(artifact, release) {
|
|
|
50
50
|
throw new TypeError('DeployResult Release differs from the PreparedArtifact Build.');
|
|
51
51
|
}
|
|
52
52
|
if (artifact.addressing.kind === 'configured' &&
|
|
53
|
-
release.addressing.issuer !== artifact.addressing.addressing.issuer
|
|
53
|
+
(release.addressing.issuer !== artifact.addressing.addressing.issuer ||
|
|
54
|
+
release.addressing.publicUrl !== artifact.addressing.addressing.publicUrl)) {
|
|
54
55
|
throw new TypeError('DeployResult Release differs from configured Addressing.');
|
|
55
56
|
}
|
|
56
57
|
return release;
|
|
@@ -4,7 +4,7 @@ const MAXIMUM_BUNDLE_BYTES = 16 * 1024 * 1024;
|
|
|
4
4
|
/** Fetch and verify the exact live Publication and Bundle for one Release. */
|
|
5
5
|
export async function verifyPublication(release, options = {}) {
|
|
6
6
|
const fetcher = options.fetch ?? globalThis.fetch;
|
|
7
|
-
const publicationUrl = publication.url(release.addressing.
|
|
7
|
+
const publicationUrl = publication.url(release.addressing.publicUrl);
|
|
8
8
|
const response = await fetchRequired(fetcher, publicationUrl, options.signal);
|
|
9
9
|
const deployed = publication.accept(JSON.parse(await text(response, publicationUrl, MAXIMUM_PUBLICATION_BYTES)));
|
|
10
10
|
if (!publication.matchesReference(deployed, publication.reference(release.publication))) {
|
|
@@ -33,6 +33,7 @@ export function createService(input) {
|
|
|
33
33
|
const prepared = prepareServer({
|
|
34
34
|
...serverOptions(input.server),
|
|
35
35
|
path: invocationPath(),
|
|
36
|
+
publicOrigin: release.addressing.publicUrl,
|
|
36
37
|
invocation: {
|
|
37
38
|
source: selectedIdentity.issuer,
|
|
38
39
|
next: () => crypto.randomUUID(),
|
|
@@ -92,6 +93,7 @@ function serverOptions(input) {
|
|
|
92
93
|
'path',
|
|
93
94
|
'invocation',
|
|
94
95
|
'issuer',
|
|
96
|
+
'publicOrigin',
|
|
95
97
|
'tokenExchange',
|
|
96
98
|
'publication',
|
|
97
99
|
'delivery',
|
|
@@ -5,7 +5,7 @@ import type { WorkflowRunner } from '../../application/workflow/runner/index.js'
|
|
|
5
5
|
import type { Release } from '../../deployment/release/index.js';
|
|
6
6
|
import type { Identity } from '../identity/index.js';
|
|
7
7
|
import type { ReleaseLoader } from './release.js';
|
|
8
|
-
export type ServiceServerOptions = Omit<ServerOptions, 'path' | 'invocation' | 'issuer' | 'tokenExchange' | 'publication' | 'delivery'>;
|
|
8
|
+
export type ServiceServerOptions = Omit<ServerOptions, 'path' | 'invocation' | 'issuer' | 'publicOrigin' | 'tokenExchange' | 'publication' | 'delivery'>;
|
|
9
9
|
export interface ServiceInput<Environment, RuntimeValue extends Runtime = Runtime> {
|
|
10
10
|
readonly runtime: RuntimeValue;
|
|
11
11
|
readonly environment: Environment;
|
|
@@ -6,7 +6,7 @@ export function reportDevelopmentDeployment(deployed, installation, adapter, inp
|
|
|
6
6
|
if (deployed.progress.provider.evidence.preflight !== undefined) {
|
|
7
7
|
info(`Preflight: ${deployed.progress.provider.evidence.preflight}; public readiness verified`);
|
|
8
8
|
}
|
|
9
|
-
info(`Public: ${deployed.release.addressing.
|
|
9
|
+
info(`Public: ${deployed.release.addressing.publicUrl}`);
|
|
10
10
|
info(`Publication: ${deployed.release.publication.schema.revision} · ${deployed.release.publication.etag}`);
|
|
11
11
|
info(installation === undefined
|
|
12
12
|
? `Installation: skipped${input.deployOnly ? ' (--deploy-only)' : ''}`
|
|
@@ -17,6 +17,7 @@ export async function writeDeploymentEvidence(input) {
|
|
|
17
17
|
id: provider.deployment,
|
|
18
18
|
artifact: provider.artifact,
|
|
19
19
|
issuer: input.deployment.release.addressing.issuer,
|
|
20
|
+
publicUrl: input.deployment.release.addressing.publicUrl,
|
|
20
21
|
origin: input.deployment.release.publication.origin,
|
|
21
22
|
revision: input.deployment.release.publication.schema.revision,
|
|
22
23
|
etag: input.deployment.release.publication.etag,
|
|
@@ -113,7 +113,7 @@ export async function run(argv) {
|
|
|
113
113
|
if (result.progress.provider.evidence.preflight !== undefined) {
|
|
114
114
|
info(`Preflight: ${result.progress.provider.evidence.preflight}; public readiness verified`);
|
|
115
115
|
}
|
|
116
|
-
info(`Public: ${result.release.addressing.
|
|
116
|
+
info(`Public: ${result.release.addressing.publicUrl}`);
|
|
117
117
|
info(`Publication: ${result.release.publication.schema.revision} · ${result.release.publication.etag}`);
|
|
118
118
|
const installed = await reconcileEnvironmentRelease({
|
|
119
119
|
projectDir,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrale-os/sdk",
|
|
3
|
-
"version": "0.5.0-beta.
|
|
3
|
+
"version": "0.5.0-beta.144",
|
|
4
4
|
"description": "Schema-first SDK for defining, composing, and deploying Astrale domains",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astrale",
|
|
@@ -237,11 +237,11 @@
|
|
|
237
237
|
"registry": "https://registry.npmjs.org/"
|
|
238
238
|
},
|
|
239
239
|
"dependencies": {
|
|
240
|
-
"@astrale-os/kernel-client": "0.6.0-beta.
|
|
241
|
-
"@astrale-os/kernel-core": "0.9.0-beta.
|
|
242
|
-
"@astrale-os/kernel-dsl": "0.2.0-beta.
|
|
243
|
-
"@astrale-os/kernel-protocol": "0.5.0-beta.
|
|
244
|
-
"@astrale-os/kernel-server": "0.5.0-beta.
|
|
240
|
+
"@astrale-os/kernel-client": "0.6.0-beta.64",
|
|
241
|
+
"@astrale-os/kernel-core": "0.9.0-beta.49",
|
|
242
|
+
"@astrale-os/kernel-dsl": "0.2.0-beta.34",
|
|
243
|
+
"@astrale-os/kernel-protocol": "0.5.0-beta.55",
|
|
244
|
+
"@astrale-os/kernel-server": "0.5.0-beta.57",
|
|
245
245
|
"@lucide/icons": "1.34.0",
|
|
246
246
|
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
|
247
247
|
"cross-spawn": "7.0.6",
|