@astrale-os/sdk 0.6.0-beta.14 → 0.6.0-beta.15
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/dist/deployment/adapter/adapter.d.ts +8 -5
- package/dist/deployment/adapter/legacy/index.d.ts +6 -8
- package/dist/deployment/adapter/release/context.d.ts +7 -1
- package/dist/deployment/adapter/release/index.d.ts +1 -0
- package/dist/deployment/adapter/release/list.d.ts +41 -0
- package/dist/deployment/adapter/release/list.js +1 -0
- package/dist/deployment/address/summary.d.ts +1 -1
- package/dist/deployment/index.d.ts +1 -1
- package/dist/deployment/release/legacy/index.d.ts +2 -2
- package/dist/deployment/release/legacy/index.js +2 -2
- package/dist/deployment/verify/readiness/legacy/publication.d.ts +1 -1
- package/dist/deployment/verify/readiness/legacy/publication.js +1 -1
- package/dist/execution/identity/authentication.d.ts +7 -3
- package/dist/execution/identity/authentication.js +9 -6
- package/dist/execution/identity/callback.d.ts +5 -2
- package/dist/execution/identity/callback.js +11 -5
- package/dist/execution/identity/identity.d.ts +5 -3
- package/dist/execution/identity/identity.js +1 -1
- package/dist/execution/workflows/run.js +1 -1
- package/dist/platform/versioning/name.d.ts +4 -3
- package/dist/platform/versioning/name.js +4 -3
- package/dist/project/define.js +12 -11
- package/dist/tooling/cli/arguments.d.ts +1 -1
- package/dist/tooling/cli/arguments.js +31 -9
- package/dist/tooling/cli/deploy-mode.d.ts +8 -12
- package/dist/tooling/cli/deploy-mode.js +39 -12
- package/dist/tooling/cli/dotenv.d.ts +2 -2
- package/dist/tooling/cli/dotenv.js +3 -33
- package/dist/tooling/cli/help.js +50 -8
- package/dist/tooling/cli/index.d.ts +3 -2
- package/dist/tooling/cli/index.js +2 -2
- package/dist/tooling/cli/{development → legacy/development}/candidate.d.ts +2 -2
- package/dist/tooling/cli/{development → legacy/development}/candidate.js +5 -5
- package/dist/tooling/cli/{development → legacy/development}/deployment.d.ts +1 -1
- package/dist/tooling/cli/{development → legacy/development}/deployment.js +1 -1
- package/dist/tooling/cli/legacy/development/deprecation.d.ts +11 -0
- package/dist/tooling/cli/legacy/development/deprecation.js +13 -0
- package/dist/tooling/cli/{development → legacy/development}/develop.d.ts +3 -0
- package/dist/tooling/cli/{development → legacy/development}/develop.js +7 -4
- package/dist/tooling/cli/legacy/development/index.d.ts +21 -0
- package/dist/tooling/cli/legacy/development/index.js +21 -0
- package/dist/tooling/cli/{development → legacy/development}/report.d.ts +1 -1
- package/dist/tooling/cli/{development → legacy/development}/report.js +1 -1
- package/dist/tooling/cli/legacy/development/secrets-file.d.ts +2 -0
- package/dist/tooling/cli/legacy/development/secrets-file.js +33 -0
- package/dist/tooling/cli/legacy/stable-target-deploy.d.ts +3 -5
- package/dist/tooling/cli/legacy/stable-target-deploy.js +3 -5
- package/dist/tooling/cli/list.d.ts +114 -0
- package/dist/tooling/cli/list.js +297 -0
- package/dist/tooling/cli/orchestrate.d.ts +1 -1
- package/dist/tooling/cli/orchestrate.js +49 -2
- package/package.json +7 -7
- /package/dist/tooling/cli/{credential.d.ts → legacy/development/credential.d.ts} +0 -0
- /package/dist/tooling/cli/{credential.js → legacy/development/credential.js} +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/lease.d.ts +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/lease.js +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/lifecycle.d.ts +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/lifecycle.js +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/project-imports.d.ts +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/project-imports.js +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/project-lock.d.ts +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/project-lock.js +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/rebuild.d.ts +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/rebuild.js +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/source-watch.d.ts +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/source-watch.js +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/sources.d.ts +0 -0
- /package/dist/tooling/cli/{development → legacy/development}/sources.js +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FrozenConfigurationV1 } from '../address/index.js';
|
|
2
2
|
import type { Bundler } from './bundle/index.js';
|
|
3
3
|
import type { ArtifactSource, DeployContext, DeployResult, PrepareContext } from './legacy/index.js';
|
|
4
|
-
import type { ConfigureContext, ListContext, Placement, PlacementContext, ReleaseDeployContext, ReleaseDeployResult, RetainContext } from './release/index.js';
|
|
4
|
+
import type { ConfigureContext, ListContext, ListedDeployment, Placement, PlacementContext, ReleaseDeployContext, ReleaseDeployResult, RetainContext } from './release/index.js';
|
|
5
5
|
/** What `admit` receives when `defineProject` binds an adapter to one Environment. */
|
|
6
6
|
export interface AdapterEnvironmentContext {
|
|
7
7
|
readonly environment: string;
|
|
@@ -32,8 +32,11 @@ export interface Adapter<Parameters extends object = object> {
|
|
|
32
32
|
placement(parameters: Parameters, context: PlacementContext): Promise<Placement>;
|
|
33
33
|
/** Create, or reuse, the immutable deployment of one sealed release. */
|
|
34
34
|
deployRelease(parameters: Parameters, context: ReleaseDeployContext): Promise<ReleaseDeployResult>;
|
|
35
|
-
/**
|
|
36
|
-
|
|
35
|
+
/**
|
|
36
|
+
* The deployments of one Environment of one origin the host keeps for the caller, each with
|
|
37
|
+
* where it is called. No effect at the host.
|
|
38
|
+
*/
|
|
39
|
+
list?(parameters: Parameters, context: ListContext): Promise<readonly ListedDeployment[]>;
|
|
37
40
|
/**
|
|
38
41
|
* Keep one published deployment where the host has no registry principal to mark it (a platform
|
|
39
42
|
* namespace). Called only after its Publication commits. Absent: the registry marks it (Admin's
|
|
@@ -61,7 +64,7 @@ export interface AdapterInput<Parameters extends object> {
|
|
|
61
64
|
configure(parameters: Parameters, context: ConfigureContext): FrozenConfigurationV1;
|
|
62
65
|
placement(parameters: Parameters, context: PlacementContext): Promise<Placement>;
|
|
63
66
|
deployRelease(parameters: Parameters, context: ReleaseDeployContext): Promise<ReleaseDeployResult>;
|
|
64
|
-
list?(parameters: Parameters, context: ListContext): Promise<readonly
|
|
67
|
+
list?(parameters: Parameters, context: ListContext): Promise<readonly ListedDeployment[]>;
|
|
65
68
|
retain?(parameters: Parameters, context: RetainContext): Promise<void>;
|
|
66
69
|
/** @deprecated Legacy direct-mode path (CT33) only. Replacement: `configure`, `placement`. */
|
|
67
70
|
prepare?(parameters: Parameters, context: PrepareContext): Promise<ArtifactSource>;
|
|
@@ -8,14 +8,12 @@
|
|
|
8
8
|
* created or reused, and installs nothing.
|
|
9
9
|
*
|
|
10
10
|
* Short-term consumers: the legacy direct-mode path (CT33), which `astrale-domain deploy` and
|
|
11
|
-
* `astrale-domain dev` run through these operations:
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* (until D22), and ui:domain (until UI1);
|
|
18
|
-
* - adapter-astrale, until S8 gives it `deployRelease`.
|
|
11
|
+
* `astrale-domain dev` run through these operations: adapter-cloudflare direct mode (`route`,
|
|
12
|
+
* `workerName`, `identityIssuer`, `addressing`, `signingIdentity`, or no `namespace`), which serves
|
|
13
|
+
* the configurations of domains ai-gateway, closing, grc, integrations and issues (until SV15),
|
|
14
|
+
* domains organization (until it leaves direct mode, AM-147), the Services `beta` and `prod` (until
|
|
15
|
+
* SV12), `development` (until SV9) and frozen `admin-beta` (until D19) environments, shell (until
|
|
16
|
+
* SH2) and its frozen `legacy-v3` (until D22), and ui:domain (until UI1).
|
|
19
17
|
*
|
|
20
18
|
* Removal: D10, once no configuration on any repository's main selects the direct-mode path
|
|
21
19
|
* (CT33, AM-147); it deletes these types with `prepare`/`deploy`, `src/deployment/release/legacy`
|
|
@@ -75,10 +75,16 @@ export interface ReleaseDeployContext {
|
|
|
75
75
|
/** Parent-owned lifecycle cancellation shared by every provider effect. */
|
|
76
76
|
readonly signal: AbortSignal;
|
|
77
77
|
}
|
|
78
|
-
/**
|
|
78
|
+
/**
|
|
79
|
+
* What `list` receives: the origin and the Environment whose deployments the host lists for the
|
|
80
|
+
* caller. It answers without any effect at the host.
|
|
81
|
+
*/
|
|
79
82
|
export interface ListContext {
|
|
80
83
|
readonly origin: string;
|
|
84
|
+
readonly environment: string;
|
|
85
|
+
/** Parent-owned lifecycle cancellation. */
|
|
81
86
|
readonly signal: AbortSignal;
|
|
87
|
+
/** Optional command-scoped identity override (`--as`). */
|
|
82
88
|
readonly identity?: string;
|
|
83
89
|
}
|
|
84
90
|
/** What `retain` receives: the label of the published deployment to keep. */
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export type { ConfigureContext, ListContext, Placement, PlacementContext, ReleaseDeployContext, RetainContext, } from './context.js';
|
|
2
|
+
export type { DeploymentCallTarget, ListedDeployment } from './list.js';
|
|
2
3
|
export type { DeploymentSecretsState, FailedReleaseDeployResult, MutationKnowledge, ReadyReleaseDeployResult, ReleaseDeploymentPhase, ReleaseDeployResult, } from './result.js';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { DeploymentSummaryV1 } from '../../address/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Where one listed deployment is called on its host, so that an operator can act on that
|
|
4
|
+
* deployment alone, such as rotating one of its secrets in place (AM-4'):
|
|
5
|
+
*
|
|
6
|
+
* - `services`: a deployment Admin's Services hosts, called on the Admin instance with
|
|
7
|
+
* `astrale call "<path>.method.setSecret" --admin` (`--admin=<admin>` when `admin` names the
|
|
8
|
+
* Admin bookmark). `path` is the deployment's node, `@<id>`, qualified by its class:
|
|
9
|
+
* `@<id>::services.astrale.ai:class.CloudflareDeployment`.
|
|
10
|
+
* - `namespace`: a deployment of a platform dispatch namespace, which has no Services node: the
|
|
11
|
+
* namespace and the script the per-script tooling of that namespace takes.
|
|
12
|
+
*/
|
|
13
|
+
export type DeploymentCallTarget = {
|
|
14
|
+
readonly kind: 'services';
|
|
15
|
+
readonly path: string;
|
|
16
|
+
/** The Admin bookmark the deployment is reached through; the CLI's own Admin target when absent. */
|
|
17
|
+
readonly admin?: string;
|
|
18
|
+
} | {
|
|
19
|
+
readonly kind: 'namespace';
|
|
20
|
+
readonly namespace: string;
|
|
21
|
+
readonly script: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* One deployment as an adapter's `list` returns it: what its host knows of it, its record as the
|
|
25
|
+
* host stores it, and where it is called. `lastCallAt`, and a preview's `expiresAt`, are as of the
|
|
26
|
+
* listing: an adapter whose host records calls only now and then reads the calls counted since, and
|
|
27
|
+
* one that cannot read them for want of a permission omits both rather than print stale values.
|
|
28
|
+
*
|
|
29
|
+
* The adapter does not admit the record. The listing admits it with `acceptDeploymentRecord`, and a
|
|
30
|
+
* record it refuses (one a host on an older SDK still admits, say) never fails the listing: that
|
|
31
|
+
* deployment is listed from the facts its host owns.
|
|
32
|
+
*/
|
|
33
|
+
export interface ListedDeployment extends Omit<DeploymentSummaryV1, 'record'> {
|
|
34
|
+
/**
|
|
35
|
+
* The record as the host stores it, unadmitted, whatever value that is (JSON `null` included).
|
|
36
|
+
* Absent when the host keeps no record of the deployment: a platform namespace keeps none until
|
|
37
|
+
* it activates the deployment.
|
|
38
|
+
*/
|
|
39
|
+
readonly record?: unknown;
|
|
40
|
+
readonly callTarget: DeploymentCallTarget;
|
|
41
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -17,7 +17,7 @@ export interface DeploymentSummaryV1 {
|
|
|
17
17
|
readonly retention: 'preview' | 'published';
|
|
18
18
|
readonly createdAt: string;
|
|
19
19
|
readonly lastCallAt?: string;
|
|
20
|
-
/** A preview's: 30 days after its
|
|
20
|
+
/** A preview's: 30 days after its activation or its last call, whichever is later (AM-123). */
|
|
21
21
|
readonly expiresAt?: string;
|
|
22
22
|
readonly retiredAt?: string;
|
|
23
23
|
readonly retirement?: 'expired' | 'withdrawn';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { defineAdapter, defineDeployment, isAdapter } from './adapter/index.js';
|
|
2
|
-
export type { Adapter, AdapterEnvironmentContext, AdapterInput, AddressingPlan, ArtifactFile, ArtifactSource, Bundle, BundleContext, Bundler, BundleSource, ConfigureContext, DeployContext, DeploymentPhase, DeploymentProgress, DeploymentSecretsState, DeployResult, FailedDeployResult, FailedReleaseDeployResult, LegacyAdapter, LegacyAdapterInput, ListContext, MutationKnowledge, Placement, PlacementContext, PreparedArtifact, PreparedArtifactFile, PrepareContext, ReadyDeployResult, ReadyReleaseDeployResult, ReleaseDeployContext, ReleaseDeploymentPhase, ReleaseDeployResult, RetainContext, } from './adapter/index.js';
|
|
2
|
+
export type { Adapter, AdapterEnvironmentContext, AdapterInput, AddressingPlan, ArtifactFile, ArtifactSource, Bundle, BundleContext, Bundler, BundleSource, ConfigureContext, DeployContext, DeploymentCallTarget, DeploymentPhase, DeploymentProgress, DeploymentSecretsState, DeployResult, FailedDeployResult, FailedReleaseDeployResult, LegacyAdapter, LegacyAdapterInput, ListContext, ListedDeployment, MutationKnowledge, Placement, PlacementContext, PreparedArtifact, PreparedArtifactFile, PrepareContext, ReadyDeployResult, ReadyReleaseDeployResult, ReleaseDeployContext, ReleaseDeploymentPhase, ReleaseDeployResult, RetainContext, } from './adapter/index.js';
|
|
3
3
|
export { compile, isBuild } from './build/index.js';
|
|
4
4
|
export type { Build, BuildBundle, BuildDigest, BuildManifestV1, BuildSchema, } from './build/index.js';
|
|
5
5
|
export { deploy } from './deploy.js';
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* seal the `DomainRelease` v4 of an immutable deployment from its build digest and URL.
|
|
9
9
|
*
|
|
10
10
|
* Short-term consumers:
|
|
11
|
-
* - the direct-mode deploy path (`prepare`/`deploy` of adapter-cloudflare
|
|
12
|
-
*
|
|
11
|
+
* - the direct-mode deploy path (`prepare`/`deploy` of adapter-cloudflare, whose
|
|
12
|
+
* `DeployResult.release` is this Release) and the stable Worker that assembles its Release
|
|
13
13
|
* at runtime, which serve the direct-mode configurations of domains ai-gateway, closing, grc,
|
|
14
14
|
* integrations and issues (until SV15), domains organization (until it leaves direct mode,
|
|
15
15
|
* AM-147), the Services `beta` and `prod` (until SV12), `development` (until SV9) and frozen
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* seal the `DomainRelease` v4 of an immutable deployment from its build digest and URL.
|
|
9
9
|
*
|
|
10
10
|
* Short-term consumers:
|
|
11
|
-
* - the direct-mode deploy path (`prepare`/`deploy` of adapter-cloudflare
|
|
12
|
-
*
|
|
11
|
+
* - the direct-mode deploy path (`prepare`/`deploy` of adapter-cloudflare, whose
|
|
12
|
+
* `DeployResult.release` is this Release) and the stable Worker that assembles its Release
|
|
13
13
|
* at runtime, which serve the direct-mode configurations of domains ai-gateway, closing, grc,
|
|
14
14
|
* integrations and issues (until SV15), domains organization (until it leaves direct mode,
|
|
15
15
|
* AM-147), the Services `beta` and `prod` (until SV12), `development` (until SV9) and frozen
|
|
@@ -6,7 +6,7 @@ import type { ReadinessOptions } from '../fetch.js';
|
|
|
6
6
|
*
|
|
7
7
|
* @deprecated Replacement: `verifyRelease`, the readiness of an immutable deployment at
|
|
8
8
|
* `release.json` (release digest and build digest). Consumer: the direct-mode deploy path of
|
|
9
|
-
* adapter-cloudflare
|
|
9
|
+
* adapter-cloudflare (the consumers of `deployment/release/legacy/index.ts`).
|
|
10
10
|
* Removal: D10, with that path.
|
|
11
11
|
*/
|
|
12
12
|
export declare function verifyPublication(release: legacy.Release, options?: ReadinessOptions): Promise<publication.Publication>;
|
|
@@ -5,7 +5,7 @@ import { bounded, fetchRequired, MAXIMUM_BUNDLE_BYTES, MAXIMUM_DOCUMENT_BYTES, t
|
|
|
5
5
|
*
|
|
6
6
|
* @deprecated Replacement: `verifyRelease`, the readiness of an immutable deployment at
|
|
7
7
|
* `release.json` (release digest and build digest). Consumer: the direct-mode deploy path of
|
|
8
|
-
* adapter-cloudflare
|
|
8
|
+
* adapter-cloudflare (the consumers of `deployment/release/legacy/index.ts`).
|
|
9
9
|
* Removal: D10, with that path.
|
|
10
10
|
*/
|
|
11
11
|
export async function verifyPublication(release, options = {}) {
|
|
@@ -5,6 +5,7 @@ import type { InvocationAdmissionInput } from '../invocation/index.js';
|
|
|
5
5
|
import type { IdentityNetworkPolicy, VerificationBasis, VerificationBasisResolver } from './jwks.js';
|
|
6
6
|
import type { SigningMaterial } from './signing.js';
|
|
7
7
|
import { ClientSession } from '../../platform/client/session/index.js';
|
|
8
|
+
import { NodeId } from '../../platform/graph/node/index.js';
|
|
8
9
|
/**
|
|
9
10
|
* How long a callback Session reuses a learned route. It stays at most the Kernel's in-flight
|
|
10
11
|
* issuer window (`KERNEL_INFLIGHT_ISSUER_MS`, Host default 300 s; CT11): a route learned to a
|
|
@@ -26,10 +27,13 @@ export declare function authenticate(credentialInput: CredentialInput, expectedK
|
|
|
26
27
|
readonly signal: AbortSignal;
|
|
27
28
|
}, configuration: AuthenticationConfiguration): Promise<AuthenticatedInvocation>;
|
|
28
29
|
/**
|
|
29
|
-
* The Domain's own authority toward one Kernel
|
|
30
|
-
* run acts as its executor, never as its initiator.
|
|
30
|
+
* The Domain's own authority toward one Kernel for a step of the durable Execution `executionId`,
|
|
31
|
+
* which no caller credential carries: the run acts as its executor, never as its initiator. Every
|
|
32
|
+
* credential names `executionId` in `EXECUTION_CLAIM`, so the Kernel can accept a replaced issuer
|
|
33
|
+
* for the steps of a run in flight at a consented issuer change. The caller owns the returned
|
|
34
|
+
* Session.
|
|
31
35
|
*/
|
|
32
|
-
export declare function executorSession(kernel: IssuerId, execution: {
|
|
36
|
+
export declare function executorSession(kernel: IssuerId, executionId: NodeId, execution: {
|
|
33
37
|
readonly deadline: number;
|
|
34
38
|
readonly signal: AbortSignal;
|
|
35
39
|
}, configuration: AuthenticationConfiguration): ClientSession;
|
|
@@ -79,16 +79,19 @@ export async function authenticate(credentialInput, expectedKernel, execution, c
|
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
81
|
/**
|
|
82
|
-
* The Domain's own authority toward one Kernel
|
|
83
|
-
* run acts as its executor, never as its initiator.
|
|
82
|
+
* The Domain's own authority toward one Kernel for a step of the durable Execution `executionId`,
|
|
83
|
+
* which no caller credential carries: the run acts as its executor, never as its initiator. Every
|
|
84
|
+
* credential names `executionId` in `EXECUTION_CLAIM`, so the Kernel can accept a replaced issuer
|
|
85
|
+
* for the steps of a run in flight at a consented issuer change. The caller owns the returned
|
|
86
|
+
* Session.
|
|
84
87
|
*/
|
|
85
|
-
export function executorSession(kernel, execution, configuration) {
|
|
88
|
+
export function executorSession(kernel, executionId, execution, configuration) {
|
|
86
89
|
const admitted = httpIssuer(kernel, configuration.policy.allowInsecureHttp === true);
|
|
87
90
|
admitEndpoint(invocationUrl(admitted), configuration.policy);
|
|
88
|
-
return callbackSession(admitted, selfIdentity, undefined, execution, configuration);
|
|
91
|
+
return callbackSession(admitted, selfIdentity, undefined, execution, configuration, executionId);
|
|
89
92
|
}
|
|
90
|
-
function callbackSession(kernel, expression, carrier, execution, configuration) {
|
|
91
|
-
const resolveCallback = createCallbackCredentialResolver(configuration.signing, configuration.issuer, configuration.subject, kernel, expression, carrier, execution);
|
|
93
|
+
function callbackSession(kernel, expression, carrier, execution, configuration, executionId) {
|
|
94
|
+
const resolveCallback = createCallbackCredentialResolver(configuration.signing, configuration.issuer, configuration.subject, kernel, expression, carrier, execution, executionId);
|
|
92
95
|
return new ClientSession({
|
|
93
96
|
kernel,
|
|
94
97
|
fetch: boundedFetch(configuration.fetch, execution.signal),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { IssuerId, UnresolvedIdentityExpr, VerifiedCredential } from '../../platform/auth/index.js';
|
|
2
|
+
import type { NodeId } from '../../platform/graph/node/index.js';
|
|
2
3
|
import type { SigningMaterial } from './signing.js';
|
|
3
4
|
export declare const maximumCallbackTtlSeconds = 120;
|
|
4
5
|
export declare const maximumCallbackDelegationTtlSeconds = 60;
|
|
@@ -34,9 +35,11 @@ export declare function signCallback(signing: SigningMaterial, issuer: IssuerId,
|
|
|
34
35
|
}): Promise<string>;
|
|
35
36
|
/**
|
|
36
37
|
* Reuse one exact callback authority partition, refreshing only near its bounded expiry. Without a
|
|
37
|
-
* carrier the callback is the Domain's own authority, bounded by the execution alone.
|
|
38
|
+
* carrier the callback is the Domain's own authority, bounded by the execution alone. An
|
|
39
|
+
* `executionId` is the durable Execution a step's executor credential names in `EXECUTION_CLAIM`;
|
|
40
|
+
* no caller-bound callback names one.
|
|
38
41
|
*/
|
|
39
42
|
export declare function createCallbackCredentialResolver(signing: SigningMaterial, issuer: IssuerId, subject: string, audience: IssuerId, expression: UnresolvedIdentityExpr, carrier: VerifiedCredential | undefined, execution: {
|
|
40
43
|
readonly deadline: number;
|
|
41
44
|
readonly signal: AbortSignal;
|
|
42
|
-
}): (signal: AbortSignal) => Promise<SignedCallback>;
|
|
45
|
+
}, executionId?: NodeId): (signal: AbortSignal) => Promise<SignedCallback>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EXECUTION_CLAIM } from '@astrale-os/kernel-protocol/issuer/claims';
|
|
1
2
|
import { SignJWT } from 'jose';
|
|
2
3
|
import { protocolError } from '../invocation/result/index.js';
|
|
3
4
|
import { requireLive } from './errors.js';
|
|
@@ -22,9 +23,11 @@ export async function signCallback(signing, issuer, subject, audience, expressio
|
|
|
22
23
|
}
|
|
23
24
|
/**
|
|
24
25
|
* Reuse one exact callback authority partition, refreshing only near its bounded expiry. Without a
|
|
25
|
-
* carrier the callback is the Domain's own authority, bounded by the execution alone.
|
|
26
|
+
* carrier the callback is the Domain's own authority, bounded by the execution alone. An
|
|
27
|
+
* `executionId` is the durable Execution a step's executor credential names in `EXECUTION_CLAIM`;
|
|
28
|
+
* no caller-bound callback names one.
|
|
26
29
|
*/
|
|
27
|
-
export function createCallbackCredentialResolver(signing, issuer, subject, audience, expression, carrier, execution) {
|
|
30
|
+
export function createCallbackCredentialResolver(signing, issuer, subject, audience, expression, carrier, execution, executionId) {
|
|
28
31
|
const maximum = carrier?.exp ?? Number.POSITIVE_INFINITY;
|
|
29
32
|
let cached;
|
|
30
33
|
let pending;
|
|
@@ -37,7 +40,7 @@ export function createCallbackCredentialResolver(signing, issuer, subject, audie
|
|
|
37
40
|
return cached;
|
|
38
41
|
}
|
|
39
42
|
if (pending === undefined) {
|
|
40
|
-
const current = sign(signing, issuer, subject, audience, expression, execution, maximum).then((signed) => {
|
|
43
|
+
const current = sign(signing, issuer, subject, audience, expression, execution, maximum, executionId).then((signed) => {
|
|
41
44
|
const delegateTtlSeconds = Math.min(maximumCallbackDelegationTtlSeconds, signed.expiresAt - signed.issuedAt - CALLBACK_DELEGATION_SKEW_SECONDS);
|
|
42
45
|
if (delegateTtlSeconds < 1) {
|
|
43
46
|
throw protocolError('AUTH_INVALID', 'Credential is invalid.');
|
|
@@ -60,7 +63,7 @@ export function createCallbackCredentialResolver(signing, issuer, subject, audie
|
|
|
60
63
|
return withSignal(pending, signal);
|
|
61
64
|
};
|
|
62
65
|
}
|
|
63
|
-
async function sign(signing, issuer, subject, audience, expression, execution, maximum = Number.POSITIVE_INFINITY) {
|
|
66
|
+
async function sign(signing, issuer, subject, audience, expression, execution, maximum = Number.POSITIVE_INFINITY, executionId) {
|
|
64
67
|
requireLive(execution);
|
|
65
68
|
const privateKey = await withSignal(signing.privateKey, execution.signal);
|
|
66
69
|
requireLive(execution);
|
|
@@ -69,7 +72,10 @@ async function sign(signing, issuer, subject, audience, expression, execution, m
|
|
|
69
72
|
if (!Number.isFinite(expiresAt) || expiresAt <= now) {
|
|
70
73
|
throw protocolError('AUTH_INVALID', 'Credential is invalid.');
|
|
71
74
|
}
|
|
72
|
-
const credential = await withSignal(new SignJWT({
|
|
75
|
+
const credential = await withSignal(new SignJWT({
|
|
76
|
+
grant: { v: 1, expr: expression },
|
|
77
|
+
...(executionId === undefined ? {} : { [EXECUTION_CLAIM]: executionId }),
|
|
78
|
+
})
|
|
73
79
|
.setProtectedHeader({
|
|
74
80
|
alg: signing.algorithm,
|
|
75
81
|
...(signing.keyId === undefined ? {} : { kid: signing.keyId }),
|
|
@@ -3,6 +3,7 @@ import type * as releaseProtocol from '@astrale-os/kernel-protocol/release';
|
|
|
3
3
|
import type { Issuer, exchange, release } from '@astrale-os/kernel-server';
|
|
4
4
|
import type { IssuerId, JsonWebKey } from '../../platform/auth/index.js';
|
|
5
5
|
import type { ClientSession } from '../../platform/client/session/index.js';
|
|
6
|
+
import type { NodeId } from '../../platform/graph/node/index.js';
|
|
6
7
|
import type { InvocationAuthority } from '../invocation/index.js';
|
|
7
8
|
import type { ExchangeOptions } from './exchange.js';
|
|
8
9
|
import type { IdentityNetworkPolicy } from './jwks.js';
|
|
@@ -16,10 +17,11 @@ export interface Identity extends Issuer, InvocationAuthority {
|
|
|
16
17
|
*/
|
|
17
18
|
delivery(served: releaseProtocol.DomainRelease | releaseProtocol.legacy.Publication): release.delivery.Provider;
|
|
18
19
|
/**
|
|
19
|
-
* The Domain's own authority toward one Kernel for
|
|
20
|
-
*
|
|
20
|
+
* The Domain's own authority toward one Kernel for a step of the durable Execution `executionId`
|
|
21
|
+
* (`ctx.execution.id`), which no caller credential carries; its credentials name `executionId` in
|
|
22
|
+
* `EXECUTION_CLAIM`. Required to serve durable Workflows; the caller closes the Session.
|
|
21
23
|
*/
|
|
22
|
-
executor?(kernel: IssuerId, execution: {
|
|
24
|
+
executor?(kernel: IssuerId, executionId: NodeId, execution: {
|
|
23
25
|
readonly deadline: number;
|
|
24
26
|
readonly signal: AbortSignal;
|
|
25
27
|
}): ClientSession;
|
|
@@ -51,7 +51,7 @@ export function createIdentity(input) {
|
|
|
51
51
|
...(exchangeProvider === undefined ? {} : { tokenExchange: exchangeProvider }),
|
|
52
52
|
delivery: (served) => releaseDelivery(material, issuer, input.subject, served),
|
|
53
53
|
admit: (request) => admit(request, configuration),
|
|
54
|
-
executor: (kernel, execution) => executorSession(kernel, execution, configuration),
|
|
54
|
+
executor: (kernel, executionId, execution) => executorSession(kernel, executionId, execution, configuration),
|
|
55
55
|
authenticate: (request) => authenticate(request.credential, request.via.issuer, request.context.execution, configuration),
|
|
56
56
|
});
|
|
57
57
|
}
|
|
@@ -84,7 +84,7 @@ function durableContext(input, context, envelope) {
|
|
|
84
84
|
/** One journaled unit of work acting as the Domain, with keys derived from its name. */
|
|
85
85
|
const journal = (name, execute) => Promise.resolve(context.run(name, async () => {
|
|
86
86
|
const deadline = Date.now() + serving.stepTimeoutMs;
|
|
87
|
-
const session = input.executor(execution.kernel, { deadline, signal });
|
|
87
|
+
const session = input.executor(execution.kernel, execution.id, { deadline, signal });
|
|
88
88
|
try {
|
|
89
89
|
const kernel = keyed(bindSessionOf(session, deadline, signal), await keySequence(execution.id, name));
|
|
90
90
|
const output = await execute(Object.freeze({
|
|
@@ -15,12 +15,13 @@ import type { Digest } from '@astrale-os/kernel-protocol/artifact';
|
|
|
15
15
|
* hexadecimal digits names a plain preview, and the commit token is always printed in lower case,
|
|
16
16
|
* like `git describe`. An environment outside the `defineProject` grammar is rendered as `?`, so no
|
|
17
17
|
* record can put control characters or a ` · ` of its own in the name. Likewise only canonical
|
|
18
|
-
* published versions name a deployment.
|
|
18
|
+
* published versions name a deployment. A deployment named without its digests (one whose record
|
|
19
|
+
* is not admitted) is never named by a published version.
|
|
19
20
|
*/
|
|
20
21
|
export declare function deploymentName(deployment: {
|
|
21
22
|
readonly environment: string;
|
|
22
|
-
readonly releaseDigest
|
|
23
|
-
readonly buildDigest
|
|
23
|
+
readonly releaseDigest?: Digest;
|
|
24
|
+
readonly buildDigest?: Digest;
|
|
24
25
|
readonly commit: {
|
|
25
26
|
readonly sha: string;
|
|
26
27
|
readonly dirty: boolean;
|
|
@@ -21,17 +21,18 @@ const UNKNOWN_ENVIRONMENT = '?';
|
|
|
21
21
|
* hexadecimal digits names a plain preview, and the commit token is always printed in lower case,
|
|
22
22
|
* like `git describe`. An environment outside the `defineProject` grammar is rendered as `?`, so no
|
|
23
23
|
* record can put control characters or a ` · ` of its own in the name. Likewise only canonical
|
|
24
|
-
* published versions name a deployment.
|
|
24
|
+
* published versions name a deployment. A deployment named without its digests (one whose record
|
|
25
|
+
* is not admitted) is never named by a published version.
|
|
25
26
|
*/
|
|
26
27
|
export function deploymentName(deployment, publications) {
|
|
27
28
|
const { commit } = deployment;
|
|
28
29
|
const environment = typeof deployment.environment === 'string' && ENVIRONMENT_NAME.test(deployment.environment)
|
|
29
30
|
? deployment.environment
|
|
30
31
|
: UNKNOWN_ENVIRONMENT;
|
|
31
|
-
const release = highest(publications.filter(({ releaseDigest }) => releaseDigest === deployment.releaseDigest));
|
|
32
|
+
const release = highest(publications.filter(({ releaseDigest }) => deployment.releaseDigest !== undefined && releaseDigest === deployment.releaseDigest));
|
|
32
33
|
if (release !== undefined)
|
|
33
34
|
return release;
|
|
34
|
-
const build = highest(publications.filter(({ buildDigest }) => buildDigest === deployment.buildDigest));
|
|
35
|
+
const build = highest(publications.filter(({ buildDigest }) => deployment.buildDigest !== undefined && buildDigest === deployment.buildDigest));
|
|
35
36
|
if (build !== undefined)
|
|
36
37
|
return `${build} · ${environment}`;
|
|
37
38
|
if (commit === null || typeof commit.sha !== 'string' || !SHA.test(commit.sha)) {
|
package/dist/project/define.js
CHANGED
|
@@ -4,8 +4,10 @@ import { ENVIRONMENT_NAME } from '../deployment/environment.js';
|
|
|
4
4
|
import { isTests } from '../testing/index.js';
|
|
5
5
|
import { installCommand } from './install-command.js';
|
|
6
6
|
const admittedProjects = new WeakSet();
|
|
7
|
-
/** The adapter name of adapter-astrale, whose instance mode once read `installation`. */
|
|
7
|
+
/** The adapter name of adapter-astrale, whose removed instance mode once read `installation`. */
|
|
8
8
|
const ASTRALE_ADAPTER = 'astrale';
|
|
9
|
+
/** The one Environment adapter-astrale deploys without an explicit organisation (AM-7). */
|
|
10
|
+
const ASTRALE_DEFAULT_ORGANIZATION_ENVIRONMENT = 'development';
|
|
9
11
|
/** Capture one inert Project definition without loading entrypoints or performing effects. */
|
|
10
12
|
export function defineProject(input) {
|
|
11
13
|
const value = record(input, 'Project definition');
|
|
@@ -80,10 +82,10 @@ function admitEntrypoints(input) {
|
|
|
80
82
|
* `installation` is refused before any effect, with the commands that replace it. Its only
|
|
81
83
|
* consumer pins an SDK older than this refusal.
|
|
82
84
|
*
|
|
83
|
-
* adapter-astrale
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
85
|
+
* adapter-astrale deploys on Admin's Services, never through the installation's instance: outside
|
|
86
|
+
* development its Environment also names the organisation that holds its deployment line (AM-7),
|
|
87
|
+
* which the guidance adds when the adapter names none. The installation's instance and identity
|
|
88
|
+
* move to the install command.
|
|
87
89
|
*/
|
|
88
90
|
function installationRefusal(environment, name) {
|
|
89
91
|
const declared = environment.installation;
|
|
@@ -97,15 +99,14 @@ function installationRefusal(environment, name) {
|
|
|
97
99
|
const instance = stable(installation.instance);
|
|
98
100
|
const identity = stable(installation.identity);
|
|
99
101
|
const deployment = environment.deployment;
|
|
100
|
-
const
|
|
102
|
+
const organization = isDeployment(deployment) &&
|
|
101
103
|
deployment.adapter.name === ASTRALE_ADAPTER &&
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
?
|
|
104
|
+
name !== ASTRALE_DEFAULT_ORGANIZATION_ENVIRONMENT &&
|
|
105
|
+
deployment.parameters.organization === undefined
|
|
106
|
+
? ", name the organisation that holds its deployment line in `astrale({ organization: '<Identity id>' })`"
|
|
105
107
|
: '';
|
|
106
|
-
const deployIdentity = astrale && identity !== undefined ? ` --as ${identity}` : '';
|
|
107
108
|
return (`Project Environment ${name} declares installation, and a deploy no longer installs. ` +
|
|
108
|
-
`Remove \`installation\`${
|
|
109
|
+
`Remove \`installation\`${organization}, run \`astrale-domain deploy ${name}\`, ` +
|
|
109
110
|
`then install the URL it prints with \`${installCommand(instance, identity)}\`.`);
|
|
110
111
|
}
|
|
111
112
|
/** A declared coordinate worth repeating in guidance: a non-empty single-line trimmed string. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { LintReportFormat } from '../linter/index.js';
|
|
2
|
-
export declare const COMMANDS: readonly ['dev', 'build', 'deploy', 'test', 'lint', 'package', 'upgrade'];
|
|
2
|
+
export declare const COMMANDS: readonly ['dev', 'build', 'deploy', 'list', 'test', 'lint', 'package', 'upgrade'];
|
|
3
3
|
export type Command = (typeof COMMANDS)[number];
|
|
4
4
|
export interface ParsedArgs {
|
|
5
5
|
readonly command: Command;
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { isAbsolute, normalize } from 'node:path';
|
|
2
2
|
import { installCommand } from '../../project/install-command.js';
|
|
3
|
-
export const COMMANDS = [
|
|
3
|
+
export const COMMANDS = [
|
|
4
|
+
'dev',
|
|
5
|
+
'build',
|
|
6
|
+
'deploy',
|
|
7
|
+
'list',
|
|
8
|
+
'test',
|
|
9
|
+
'lint',
|
|
10
|
+
'package',
|
|
11
|
+
'upgrade',
|
|
12
|
+
];
|
|
4
13
|
/** Parse the frozen `astrale-domain` command grammar without performing effects. */
|
|
5
14
|
export function parseArgs(argv) {
|
|
6
15
|
const [command, ...rest] = argv;
|
|
@@ -66,8 +75,8 @@ export function parseArgs(argv) {
|
|
|
66
75
|
}
|
|
67
76
|
if (fix && command !== 'lint')
|
|
68
77
|
throw new Error('`--fix` is only valid for `lint`.');
|
|
69
|
-
if (json && command !== 'build' && command !== 'deploy') {
|
|
70
|
-
throw new Error('`--json` is only valid for `build` or `
|
|
78
|
+
if (json && command !== 'build' && command !== 'deploy' && command !== 'list') {
|
|
79
|
+
throw new Error('`--json` is only valid for `build`, `deploy` or `list`.');
|
|
71
80
|
}
|
|
72
81
|
if (format !== undefined && command !== 'lint') {
|
|
73
82
|
throw new Error('`--format` is only valid for `lint`.');
|
|
@@ -80,13 +89,15 @@ export function parseArgs(argv) {
|
|
|
80
89
|
}
|
|
81
90
|
if (deployOnly && command !== 'dev' && command !== 'deploy')
|
|
82
91
|
refuseDeployOnly(undefined);
|
|
83
|
-
if (identity !== undefined && command !== 'dev' && command !== 'deploy') {
|
|
84
|
-
throw new Error('`--as` is only valid for `dev` or `
|
|
92
|
+
if (identity !== undefined && command !== 'dev' && command !== 'deploy' && command !== 'list') {
|
|
93
|
+
throw new Error('`--as` is only valid for `dev`, `deploy` or `list`.');
|
|
85
94
|
}
|
|
86
|
-
if (environment !== undefined &&
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
95
|
+
if (environment !== undefined &&
|
|
96
|
+
command !== 'dev' &&
|
|
97
|
+
command !== 'deploy' &&
|
|
98
|
+
command !== 'list' &&
|
|
99
|
+
command !== 'test') {
|
|
100
|
+
throw new Error('`--environment` is only valid for `dev`, `deploy`, `list` or `test`.');
|
|
90
101
|
}
|
|
91
102
|
if (suite !== undefined && command !== 'test') {
|
|
92
103
|
throw new Error('`--suite` is only valid for `test`.');
|
|
@@ -116,6 +127,17 @@ export function parseArgs(argv) {
|
|
|
116
127
|
...(secretsFile === undefined ? {} : { secretsFile }),
|
|
117
128
|
};
|
|
118
129
|
}
|
|
130
|
+
case 'list':
|
|
131
|
+
// Every Environment of the Project, or the one `--environment` names.
|
|
132
|
+
if (positionals.length > 0) {
|
|
133
|
+
throw new Error('`list` does not accept positional arguments; use `--environment`.');
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
command: 'list',
|
|
137
|
+
env: environment ?? '',
|
|
138
|
+
...(json ? { json: true } : {}),
|
|
139
|
+
...(identity === undefined ? {} : { identity }),
|
|
140
|
+
};
|
|
119
141
|
case 'build':
|
|
120
142
|
case 'package':
|
|
121
143
|
if (positionals.length > 0) {
|
|
@@ -5,7 +5,7 @@ import type { LoadedEnvironment } from './project.js';
|
|
|
5
5
|
* that mode still has a consumer (AM-16, AM-72).
|
|
6
6
|
*
|
|
7
7
|
* - `canonical`: an immutable deployment of one sealed release through the adapter's
|
|
8
|
-
* `deployRelease`, with a key generated for it, and
|
|
8
|
+
* `deployRelease`, with a key generated for it, and no call to any instance.
|
|
9
9
|
* - `legacy-direct`: today's stable target, replaced in place through `prepare` and `deploy`, which
|
|
10
10
|
* serves a v3 Publication only. Its `reasons` name what selected it.
|
|
11
11
|
* - `refused`: a shape no deploy of this SDK serves, refused before any effect. Each refusal
|
|
@@ -35,10 +35,7 @@ export type LegacyDirectReason =
|
|
|
35
35
|
| {
|
|
36
36
|
readonly reason: 'no-namespace';
|
|
37
37
|
}
|
|
38
|
-
/**
|
|
39
|
-
* An adapter that declares no `deployRelease` (the contract before adapter interface v2),
|
|
40
|
-
* adapter-astrale's instance mode among them until adapter-astrale implements it.
|
|
41
|
-
*/
|
|
38
|
+
/** An adapter that declares no `deployRelease`: the contract before adapter interface v2. */
|
|
42
39
|
| {
|
|
43
40
|
readonly reason: 'no-deploy-release';
|
|
44
41
|
};
|
|
@@ -54,13 +51,12 @@ export type DeployModeCommand = 'deploy' | 'dev';
|
|
|
54
51
|
* Select the deploy mode of one Environment (CT33). It reads the configuration and the command
|
|
55
52
|
* only, and has no effect.
|
|
56
53
|
*
|
|
57
|
-
* A refusal wins over every other reason.
|
|
58
|
-
* (`deployRelease`)
|
|
59
|
-
* consumer pins an older SDK (AM-72).
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* which serves the legacy direct-mode path only.
|
|
54
|
+
* A refusal wins over every other reason. adapter-astrale deploys immutable deployments only
|
|
55
|
+
* (`deployRelease`): its removed instance mode's `instance` and `signingIdentity` are refused
|
|
56
|
+
* before any effect, since their one consumer pins an older SDK (AM-72). Otherwise the Environment
|
|
57
|
+
* is on the legacy direct-mode path when adapter-cloudflare names a direct-mode parameter or no
|
|
58
|
+
* `namespace`, or when its adapter declares no `deployRelease`. Everything else is canonical,
|
|
59
|
+
* except under `dev`, which serves the legacy direct-mode path only.
|
|
64
60
|
*
|
|
65
61
|
* Within canonical adapter-cloudflare (with `namespace`), a direct-mode parameter is refused
|
|
66
62
|
* rather than silently selecting either mode, and so is `wrangler.triggers`: an immutable
|