@astrale-os/sdk 0.5.0-beta.99 → 0.6.0-beta.0

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 (270) hide show
  1. package/README.md +165 -2
  2. package/dist/application/action/action.d.ts +7 -4
  3. package/dist/application/action/authoring.d.ts +2 -1
  4. package/dist/application/action/context.d.ts +18 -13
  5. package/dist/application/action/define.d.ts +5 -1
  6. package/dist/application/action/define.js +6 -1
  7. package/dist/application/action/index.d.ts +2 -1
  8. package/dist/application/dependency/index.d.ts +1 -0
  9. package/dist/application/dependency/invoker.d.ts +26 -0
  10. package/dist/application/error/error.d.ts +23 -0
  11. package/dist/application/error/error.js +87 -0
  12. package/dist/application/error/index.d.ts +2 -0
  13. package/dist/application/error/index.js +1 -0
  14. package/dist/application/index.d.ts +2 -2
  15. package/dist/application/integration/authentication.d.ts +10 -0
  16. package/dist/application/integration/authentication.typecheck.js +18 -0
  17. package/dist/application/integration/client.d.ts +2 -0
  18. package/dist/application/integration/client.js +19 -2
  19. package/dist/application/integration/index.d.ts +1 -0
  20. package/dist/application/integration/operation.d.ts +3 -0
  21. package/dist/application/mutation/authoring/builder.js +2 -2
  22. package/dist/application/mutation/authoring/endpoint.d.ts +3 -3
  23. package/dist/application/mutation/authoring/endpoint.js +9 -0
  24. package/dist/application/mutation/failure.js +13 -7
  25. package/dist/application/mutation/index.d.ts +1 -0
  26. package/dist/application/requirements/{profiles.d.ts → core.d.ts} +5 -3
  27. package/dist/application/requirements/{profiles.js → core.js} +6 -6
  28. package/dist/application/requirements/index.d.ts +4 -4
  29. package/dist/application/requirements/index.js +5 -5
  30. package/dist/application/requirements/requirement.d.ts +3 -2
  31. package/dist/application/runtime/authoring.d.ts +1 -0
  32. package/dist/application/runtime/callables.js +2 -2
  33. package/dist/application/runtime/declarations.d.ts +43 -0
  34. package/dist/application/runtime/define.d.ts +2 -1
  35. package/dist/application/view/index.d.ts +1 -1
  36. package/dist/application/view/route.d.ts +4 -0
  37. package/dist/application/view/route.js +5 -1
  38. package/dist/application/workflow/authoring.d.ts +1 -0
  39. package/dist/application/workflow/context.d.ts +2 -1
  40. package/dist/application/workflow/define.d.ts +5 -1
  41. package/dist/application/workflow/define.js +6 -1
  42. package/dist/application/workflow/index.d.ts +1 -0
  43. package/dist/application/workflow/runner/runner.d.ts +3 -2
  44. package/dist/application/workflow/workflow.d.ts +4 -3
  45. package/dist/deployment/adapter/adapter.d.ts +12 -7
  46. package/dist/deployment/adapter/define.d.ts +5 -2
  47. package/dist/deployment/adapter/define.js +15 -17
  48. package/dist/deployment/adapter/deploy/context.d.ts +6 -0
  49. package/dist/deployment/adapter/deploy/result.d.ts +2 -0
  50. package/dist/deployment/adapter/index.d.ts +2 -3
  51. package/dist/deployment/adapter/index.js +1 -1
  52. package/dist/deployment/adapter/prepare/context.d.ts +13 -5
  53. package/dist/deployment/authoring.d.ts +1 -1
  54. package/dist/deployment/build/compile.js +21 -19
  55. package/dist/deployment/build/frontend/compilation.d.ts +2 -1
  56. package/dist/deployment/build/frontend/compilation.js +1 -0
  57. package/dist/deployment/build/material.js +5 -5
  58. package/dist/deployment/deploy.d.ts +10 -4
  59. package/dist/deployment/deploy.js +5 -5
  60. package/dist/deployment/deployment.d.ts +8 -5
  61. package/dist/deployment/deployment.js +10 -1
  62. package/dist/deployment/index.d.ts +5 -4
  63. package/dist/deployment/index.js +3 -2
  64. package/dist/deployment/release/addressing.d.ts +6 -2
  65. package/dist/deployment/release/addressing.js +9 -4
  66. package/dist/deployment/release/publication/callables.js +1 -1
  67. package/dist/deployment/release/publication/index.d.ts +1 -1
  68. package/dist/deployment/release/publication/index.js +1 -1
  69. package/dist/deployment/release/publication/routes.js +1 -1
  70. package/dist/deployment/release/publication/seal.d.ts +0 -1
  71. package/dist/deployment/release/publication/seal.js +4 -5
  72. package/dist/deployment/release/publication/views.js +2 -1
  73. package/dist/deployment/verify/preflight/artifact.js +1 -1
  74. package/dist/deployment/verify/readiness/deployment.js +7 -3
  75. package/dist/deployment/verify/readiness/identity.js +1 -1
  76. package/dist/deployment/verify/readiness/publication.js +2 -2
  77. package/dist/execution/identity/authentication.js +0 -1
  78. package/dist/execution/identity/exchange.d.ts +1 -0
  79. package/dist/execution/identity/exchange.js +1 -1
  80. package/dist/execution/identity/jwks.js +1 -1
  81. package/dist/execution/invocation/admission/authentication.d.ts +6 -3
  82. package/dist/execution/invocation/admission/authentication.js +16 -6
  83. package/dist/execution/invocation/admission/authority.d.ts +2 -2
  84. package/dist/execution/invocation/dependency/bind.d.ts +5 -0
  85. package/dist/execution/invocation/dependency/bind.js +68 -0
  86. package/dist/execution/invocation/dependency/index.d.ts +1 -0
  87. package/dist/execution/invocation/dependency/index.js +1 -0
  88. package/dist/execution/invocation/dispatch/action.js +19 -2
  89. package/dist/execution/invocation/dispatch/context.d.ts +4 -4
  90. package/dist/execution/invocation/dispatch/context.js +29 -9
  91. package/dist/execution/invocation/dispatch/workflow.js +17 -4
  92. package/dist/execution/invocation/integration/authentication.d.ts +5 -0
  93. package/dist/execution/invocation/integration/authentication.js +53 -0
  94. package/dist/execution/invocation/integration/call.d.ts +7 -1
  95. package/dist/execution/invocation/integration/call.js +8 -3
  96. package/dist/execution/invocation/integration/clients.d.ts +2 -2
  97. package/dist/execution/invocation/integration/clients.js +2 -2
  98. package/dist/execution/invocation/lifecycle/active.js +30 -5
  99. package/dist/execution/invocation/result/errors.d.ts +1 -0
  100. package/dist/execution/invocation/result/errors.js +15 -10
  101. package/dist/execution/service/create.js +3 -1
  102. package/dist/execution/service/service.d.ts +1 -1
  103. package/dist/index.d.ts +3 -1
  104. package/dist/index.js +1 -0
  105. package/dist/platform/auth/index.d.ts +1 -1
  106. package/dist/platform/auth/index.js +0 -1
  107. package/dist/platform/graph/alias.d.ts +6 -0
  108. package/dist/platform/graph/alias.js +6 -0
  109. package/dist/platform/graph/document/index.d.ts +2 -1
  110. package/dist/platform/graph/document/index.js +2 -1
  111. package/dist/platform/graph/index.d.ts +2 -1
  112. package/dist/platform/graph/index.js +2 -1
  113. package/dist/platform/schema/class-authoring.d.ts +37 -0
  114. package/dist/platform/schema/class-authoring.js +20 -0
  115. package/dist/platform/schema/class-icon.d.ts +15 -0
  116. package/dist/platform/schema/class-icon.js +46 -0
  117. package/dist/platform/schema/error.d.ts +11 -0
  118. package/dist/platform/schema/error.js +34 -0
  119. package/dist/platform/schema/errors/index.d.ts +3 -0
  120. package/dist/platform/schema/errors/index.js +2 -0
  121. package/dist/platform/schema/icons/index.d.ts +2 -0
  122. package/dist/platform/schema/icons/index.js +2 -0
  123. package/dist/platform/schema/index.d.ts +20 -13
  124. package/dist/platform/schema/index.js +9 -4
  125. package/dist/platform/schema/kernel.d.ts +22 -0
  126. package/dist/platform/schema/kernel.js +5 -0
  127. package/dist/platform/schema/node-id.d.ts +3 -0
  128. package/dist/platform/schema/node-id.js +6 -0
  129. package/dist/platform/schema/property.d.ts +12 -0
  130. package/dist/platform/schema/property.js +3 -0
  131. package/dist/platform/schema/schema-authoring.d.ts +48 -0
  132. package/dist/platform/schema/schema-authoring.js +3 -0
  133. package/dist/platform/schema/state-property.d.ts +11 -0
  134. package/dist/platform/schema/state-property.js +3 -0
  135. package/dist/project/admit.d.ts +4 -0
  136. package/dist/project/admit.js +22 -0
  137. package/dist/project/define.d.ts +12 -0
  138. package/dist/project/define.js +106 -0
  139. package/dist/project/index.d.ts +4 -0
  140. package/dist/project/index.js +2 -0
  141. package/dist/project/project.d.ts +24 -0
  142. package/dist/project/project.js +1 -0
  143. package/dist/testing/dataset/admission.d.ts +13 -0
  144. package/dist/testing/dataset/admission.js +107 -0
  145. package/dist/testing/dataset/builder.d.ts +42 -0
  146. package/dist/testing/dataset/builder.js +127 -0
  147. package/dist/testing/dataset/codec.d.ts +6 -0
  148. package/dist/testing/dataset/codec.js +113 -0
  149. package/dist/testing/dataset/dataset.d.ts +58 -0
  150. package/dist/testing/dataset/dataset.js +2 -0
  151. package/dist/testing/dataset/define.d.ts +33 -0
  152. package/dist/testing/dataset/define.js +105 -0
  153. package/dist/testing/dataset/index.d.ts +8 -0
  154. package/dist/testing/dataset/index.js +4 -0
  155. package/dist/testing/dataset/references.d.ts +14 -0
  156. package/dist/testing/dataset/references.js +56 -0
  157. package/dist/testing/index.d.ts +9 -0
  158. package/dist/testing/index.js +5 -0
  159. package/dist/testing/load.d.ts +14 -0
  160. package/dist/testing/load.js +44 -0
  161. package/dist/testing/reference.d.ts +11 -0
  162. package/dist/testing/reference.js +19 -0
  163. package/dist/testing/tests.d.ts +12 -0
  164. package/dist/testing/tests.js +31 -0
  165. package/dist/tooling/cli/arguments.d.ts +7 -4
  166. package/dist/tooling/cli/arguments.js +82 -107
  167. package/dist/tooling/cli/astrale/authority.d.ts +5 -0
  168. package/dist/tooling/cli/astrale/authority.js +11 -0
  169. package/dist/tooling/cli/astrale/executable.d.ts +2 -0
  170. package/dist/tooling/cli/astrale/executable.js +47 -0
  171. package/dist/tooling/cli/astrale/failure.d.ts +6 -0
  172. package/dist/tooling/cli/astrale/failure.js +48 -0
  173. package/dist/tooling/cli/astrale/instance.d.ts +11 -0
  174. package/dist/tooling/cli/astrale/instance.js +52 -0
  175. package/dist/tooling/cli/astrale/process.d.ts +13 -0
  176. package/dist/tooling/cli/astrale/process.js +94 -0
  177. package/dist/tooling/cli/astrale/version.d.ts +18 -0
  178. package/dist/tooling/cli/astrale/version.js +55 -0
  179. package/dist/tooling/cli/bun.js +1 -1
  180. package/dist/tooling/cli/credential.d.ts +2 -0
  181. package/dist/tooling/cli/credential.js +57 -0
  182. package/dist/tooling/cli/development/candidate.d.ts +25 -0
  183. package/dist/tooling/cli/development/candidate.js +176 -0
  184. package/dist/tooling/cli/development/deployment.d.ts +16 -0
  185. package/dist/tooling/cli/development/deployment.js +39 -0
  186. package/dist/tooling/cli/development/develop.d.ts +4 -3
  187. package/dist/tooling/cli/development/develop.js +125 -289
  188. package/dist/tooling/cli/development/lease.d.ts +18 -0
  189. package/dist/tooling/cli/development/lease.js +163 -0
  190. package/dist/tooling/cli/development/lifecycle.js +4 -0
  191. package/dist/tooling/cli/development/project-imports.d.ts +22 -0
  192. package/dist/tooling/cli/development/project-imports.js +39 -0
  193. package/dist/tooling/cli/development/project-lock.d.ts +3 -4
  194. package/dist/tooling/cli/development/project-lock.js +14 -166
  195. package/dist/tooling/cli/development/release-evidence.d.ts +4 -0
  196. package/dist/tooling/cli/development/release-evidence.js +10 -0
  197. package/dist/tooling/cli/development/report.d.ts +6 -0
  198. package/dist/tooling/cli/development/report.js +14 -0
  199. package/dist/tooling/cli/development/source-watch.js +53 -5
  200. package/dist/tooling/cli/development/sources.d.ts +7 -0
  201. package/dist/tooling/cli/development/sources.js +48 -0
  202. package/dist/tooling/cli/development/target-lock.d.ts +16 -0
  203. package/dist/tooling/cli/development/target-lock.js +68 -0
  204. package/dist/tooling/cli/development/view.d.ts +28 -0
  205. package/dist/tooling/cli/development/view.js +151 -0
  206. package/dist/tooling/cli/environment-release.d.ts +21 -0
  207. package/dist/tooling/cli/environment-release.js +46 -0
  208. package/dist/tooling/cli/evidence.d.ts +11 -0
  209. package/dist/tooling/cli/evidence.js +53 -0
  210. package/dist/tooling/cli/help.js +78 -34
  211. package/dist/tooling/cli/index.d.ts +1 -1
  212. package/dist/tooling/cli/index.js +1 -1
  213. package/dist/tooling/cli/installation/index.d.ts +2 -0
  214. package/dist/tooling/cli/installation/index.js +1 -0
  215. package/dist/tooling/cli/installation/observation.d.ts +10 -0
  216. package/dist/tooling/cli/installation/observation.js +44 -0
  217. package/dist/tooling/cli/installation/reconcile.d.ts +32 -0
  218. package/dist/tooling/cli/installation/reconcile.js +122 -0
  219. package/dist/tooling/cli/orchestrate.js +84 -44
  220. package/dist/tooling/cli/project.d.ts +17 -0
  221. package/dist/tooling/cli/project.js +18 -0
  222. package/dist/tooling/cli/test.d.ts +12 -0
  223. package/dist/tooling/cli/test.js +47 -0
  224. package/dist/tooling/cli/upgrade/index.d.ts +6 -0
  225. package/dist/tooling/cli/upgrade/index.js +115 -0
  226. package/dist/tooling/cli/upgrade/manifest.d.ts +18 -0
  227. package/dist/tooling/cli/upgrade/manifest.js +77 -0
  228. package/dist/tooling/cli/upgrade/process.d.ts +2 -0
  229. package/dist/tooling/cli/upgrade/process.js +57 -0
  230. package/dist/tooling/linter/adapters/typescript/imports.js +2 -0
  231. package/dist/tooling/linter/adapters/typescript/index.d.ts +1 -0
  232. package/dist/tooling/linter/adapters/typescript/index.js +1 -0
  233. package/dist/tooling/linter/adapters/typescript/query-collection-type.js +4 -51
  234. package/dist/tooling/linter/adapters/typescript/type-analysis.d.ts +9 -0
  235. package/dist/tooling/linter/adapters/typescript/type-analysis.js +55 -0
  236. package/dist/tooling/linter/implementations/source/callable-requirements.d.ts +28 -0
  237. package/dist/tooling/linter/implementations/source/callable-requirements.js +234 -0
  238. package/dist/tooling/linter/implementations/source/dependencies.d.ts +2 -0
  239. package/dist/tooling/linter/implementations/source/dependencies.js +219 -0
  240. package/dist/tooling/linter/implementations/source/global.js +52 -2
  241. package/dist/tooling/linter/implementations/source/mutations.js +520 -38
  242. package/dist/tooling/linter/implementations/source/providers.js +19 -164
  243. package/dist/tooling/linter/implementations/source/schema.js +454 -2
  244. package/dist/tooling/linter/implementations/source/verifiers.js +2 -0
  245. package/dist/tooling/linter/implementations/source/workflows.js +8 -35
  246. package/dist/tooling/linter/policy/generated.js +2 -2
  247. package/dist/tooling/linter/requirements/registry.js +9 -3
  248. package/dist/tooling/packaging/declarations/normalize.js +3 -38
  249. package/dist/tooling/packaging/declarations/paths.d.ts +5 -0
  250. package/dist/tooling/packaging/declarations/paths.js +38 -0
  251. package/dist/tooling/packaging/finalize.d.ts +13 -0
  252. package/dist/tooling/packaging/finalize.js +62 -0
  253. package/dist/tooling/packaging/index.d.ts +2 -0
  254. package/dist/tooling/packaging/index.js +1 -0
  255. package/dist/tooling/packaging/javascript.d.ts +3 -0
  256. package/dist/tooling/packaging/javascript.js +45 -2
  257. package/dist/tooling/packaging/packaging.d.ts +2 -5
  258. package/dist/tooling/packaging/packaging.js +6 -30
  259. package/package.json +42 -12
  260. package/CHANGELOG.md +0 -1506
  261. package/dist/deployment/adapter/development/context.d.ts +0 -18
  262. package/dist/deployment/adapter/development/index.d.ts +0 -4
  263. package/dist/deployment/adapter/development/input.d.ts +0 -6
  264. package/dist/deployment/adapter/development/placement.d.ts +0 -15
  265. package/dist/deployment/adapter/development/session.d.ts +0 -9
  266. /package/dist/{deployment/adapter/development → application/dependency}/index.js +0 -0
  267. /package/dist/{deployment/adapter/development/context.js → application/dependency/invoker.js} +0 -0
  268. /package/dist/{deployment/adapter/development/input.js → application/integration/authentication.js} +0 -0
  269. /package/dist/{deployment/adapter/development/placement.js → application/integration/authentication.typecheck.d.ts} +0 -0
  270. /package/dist/{deployment/adapter/development/session.js → application/runtime/declarations.js} +0 -0
@@ -0,0 +1,68 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { mkdir, rmdir } from 'node:fs/promises';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { acquireDevelopmentLease, DevelopmentLeaseError } from './lease.js';
6
+ export class DevelopmentTargetLockError extends Error {
7
+ code;
8
+ name = 'DevelopmentTargetLockError';
9
+ constructor(code, message, options) {
10
+ super(message, options);
11
+ this.code = code;
12
+ }
13
+ }
14
+ /** Exclude local sessions targeting one installed Domain across separate checkouts. */
15
+ export async function acquireDevelopmentTargetLock(input, dependencies = {}) {
16
+ const coordinate = `${input.issuer}#${input.origin}`;
17
+ const root = dependencies.root ?? join(tmpdir(), 'astrale-domain-development-targets');
18
+ const key = createHash('sha256')
19
+ .update(input.issuer)
20
+ .update('\0')
21
+ .update(input.origin)
22
+ .digest('hex');
23
+ const directory = join(root, key);
24
+ await mkdir(root, { recursive: true, mode: 0o700 });
25
+ let lease;
26
+ try {
27
+ lease = await acquireDevelopmentLease({
28
+ directory,
29
+ coordinate,
30
+ ...(dependencies.pid === undefined ? {} : { pid: dependencies.pid }),
31
+ ...(dependencies.sessionId === undefined ? {} : { sessionId: dependencies.sessionId }),
32
+ ...(dependencies.processAlive === undefined
33
+ ? {}
34
+ : { processAlive: dependencies.processAlive }),
35
+ });
36
+ }
37
+ catch (cause) {
38
+ if (cause instanceof DevelopmentLeaseError) {
39
+ throw new DevelopmentTargetLockError('DEVELOPMENT_TARGET_LOCKED', cause.message, { cause });
40
+ }
41
+ throw cause;
42
+ }
43
+ return Object.freeze({
44
+ ...lease,
45
+ async release() {
46
+ try {
47
+ await lease.release();
48
+ }
49
+ catch (cause) {
50
+ if (cause instanceof DevelopmentLeaseError) {
51
+ throw new DevelopmentTargetLockError('DEVELOPMENT_TARGET_LOCK_LOST', cause.message, {
52
+ cause,
53
+ });
54
+ }
55
+ throw cause;
56
+ }
57
+ await rmdir(directory).catch(ignoreNonEmpty);
58
+ await rmdir(root).catch(ignoreNonEmpty);
59
+ },
60
+ });
61
+ }
62
+ function ignoreNonEmpty(cause) {
63
+ const code = cause !== null && typeof cause === 'object' && 'code' in cause
64
+ ? String(Reflect.get(cause, 'code'))
65
+ : undefined;
66
+ if (!['ENOENT', 'ENOTEMPTY', 'EEXIST'].includes(code ?? ''))
67
+ throw cause;
68
+ }
@@ -0,0 +1,28 @@
1
+ import type { Release } from '../../../deployment/release/index.js';
2
+ import type { AstraleProcessResult } from '../astrale/process.js';
3
+ export interface DevelopmentViewDependencies {
4
+ run(input: {
5
+ readonly executable: string;
6
+ readonly args: readonly string[];
7
+ readonly projectDir: string;
8
+ readonly signal: AbortSignal;
9
+ readonly timeoutMs: number;
10
+ }): Promise<AstraleProcessResult>;
11
+ }
12
+ /** Keep one browser tab alive across successful remote deployments. */
13
+ export declare class DevelopmentView {
14
+ #private;
15
+ constructor(input: {
16
+ readonly executable: string;
17
+ readonly projectDir: string;
18
+ readonly instance: string;
19
+ readonly identity?: string;
20
+ readonly credential?: string;
21
+ readonly dependencies?: DevelopmentViewDependencies;
22
+ });
23
+ /** Require in-place refresh before publishing anything that depends on this CLI feature. */
24
+ prepare(signal: AbortSignal): Promise<void>;
25
+ /** Called after each committed deployment; the development loop owns candidate deduplication. */
26
+ refresh(release: Release, signal: AbortSignal): Promise<string | undefined>;
27
+ close(signal: AbortSignal): Promise<void>;
28
+ }
@@ -0,0 +1,151 @@
1
+ import { astraleAuthorityArguments } from '../astrale/authority.js';
2
+ import { runAstrale } from '../astrale/process.js';
3
+ /** Keep one browser tab alive across successful remote deployments. */
4
+ export class DevelopmentView {
5
+ #executable;
6
+ #projectDir;
7
+ #instance;
8
+ #authority;
9
+ #dependencies;
10
+ #current;
11
+ #prepared = false;
12
+ constructor(input) {
13
+ this.#executable = input.executable;
14
+ this.#projectDir = input.projectDir;
15
+ this.#instance = input.instance;
16
+ this.#authority = astraleAuthorityArguments({
17
+ ...(input.identity === undefined ? {} : { identity: input.identity }),
18
+ ...(input.credential === undefined ? {} : { credential: input.credential }),
19
+ });
20
+ this.#dependencies = input.dependencies ?? { run: runAstrale };
21
+ }
22
+ /** Require in-place refresh before publishing anything that depends on this CLI feature. */
23
+ async prepare(signal) {
24
+ if (this.#prepared)
25
+ return;
26
+ const result = await this.#dependencies.run({
27
+ executable: this.#executable,
28
+ projectDir: this.#projectDir,
29
+ signal,
30
+ timeoutMs: 10_000,
31
+ args: ['view', '--help'],
32
+ });
33
+ if (result.code !== 0 || !result.stdout.includes('--refresh <id>')) {
34
+ throw new Error('This Astrale CLI cannot refresh development Views. Run astrale update before pnpm dev.');
35
+ }
36
+ this.#prepared = true;
37
+ }
38
+ /** Called after each committed deployment; the development loop owns candidate deduplication. */
39
+ async refresh(release, signal) {
40
+ const frontend = release.build.frontend;
41
+ if (frontend === undefined) {
42
+ await this.close(AbortSignal.timeout(30_000));
43
+ return undefined;
44
+ }
45
+ const path = `/:${frontend.entrypoint.origin}:view.${frontend.entrypoint.name}`;
46
+ const previous = this.#current;
47
+ if (previous?.path === path) {
48
+ const refreshed = await this.#dependencies.run({
49
+ executable: this.#executable,
50
+ projectDir: this.#projectDir,
51
+ signal,
52
+ timeoutMs: 60_000,
53
+ args: ['--ci', '--no-prompt', 'view', '--refresh', previous.id, '--json'],
54
+ });
55
+ if (refreshed.code !== 0)
56
+ throw new Error('Astrale CLI could not refresh the development View.');
57
+ return previous.pageUrl;
58
+ }
59
+ const next = await this.#open(path, signal);
60
+ if (previous !== undefined) {
61
+ try {
62
+ await this.#close(previous.id, AbortSignal.timeout(30_000));
63
+ }
64
+ catch (cause) {
65
+ try {
66
+ await this.#close(next.id, AbortSignal.timeout(30_000));
67
+ }
68
+ catch (rollback) {
69
+ throw new AggregateError([cause, rollback], 'Astrale View replacement and rollback cleanup failed.');
70
+ }
71
+ throw cause;
72
+ }
73
+ }
74
+ this.#current = next;
75
+ return next.pageUrl;
76
+ }
77
+ async close(signal) {
78
+ const current = this.#current;
79
+ if (current === undefined)
80
+ return;
81
+ await this.#close(current.id, signal);
82
+ if (this.#current === current) {
83
+ this.#current = undefined;
84
+ }
85
+ }
86
+ async #open(path, signal) {
87
+ const result = await this.#dependencies.run({
88
+ executable: this.#executable,
89
+ projectDir: this.#projectDir,
90
+ signal,
91
+ timeoutMs: 60_000,
92
+ args: [
93
+ '--ci',
94
+ '--no-prompt',
95
+ 'view',
96
+ path,
97
+ '--browser',
98
+ '--instance',
99
+ this.#instance,
100
+ '--json',
101
+ ...this.#authority,
102
+ ],
103
+ });
104
+ if (result.code !== 0)
105
+ throw new Error('Astrale CLI could not open the development View.');
106
+ return { ...decodeOpenedView(result.stdout), path };
107
+ }
108
+ async #close(id, signal) {
109
+ const result = await this.#dependencies.run({
110
+ executable: this.#executable,
111
+ projectDir: this.#projectDir,
112
+ signal,
113
+ timeoutMs: 30_000,
114
+ args: ['--ci', '--no-prompt', 'view', '--close', id, '--json'],
115
+ });
116
+ if (result.code !== 0)
117
+ throw new Error('Astrale CLI could not close the development View.');
118
+ }
119
+ }
120
+ function decodeOpenedView(input) {
121
+ let value;
122
+ try {
123
+ value = JSON.parse(input);
124
+ }
125
+ catch (cause) {
126
+ throw new TypeError('Astrale View output is invalid.', { cause });
127
+ }
128
+ const session = record(value) ? value.session : undefined;
129
+ const id = record(session) ? session.id : undefined;
130
+ const pageUrl = record(session) ? session.pageUrl : undefined;
131
+ if (typeof id !== 'string' || id.length === 0 || !webUrl(pageUrl)) {
132
+ throw new TypeError('Astrale View output is invalid.');
133
+ }
134
+ return Object.freeze({ id, pageUrl });
135
+ }
136
+ function webUrl(input) {
137
+ if (typeof input !== 'string' || input.length === 0 || input.length > 2_048)
138
+ return false;
139
+ try {
140
+ const value = new URL(input);
141
+ return ((value.protocol === 'http:' || value.protocol === 'https:') &&
142
+ value.username === '' &&
143
+ value.password === '');
144
+ }
145
+ catch {
146
+ return false;
147
+ }
148
+ }
149
+ function record(input) {
150
+ return input !== null && typeof input === 'object' && !Array.isArray(input);
151
+ }
@@ -0,0 +1,21 @@
1
+ import type { Adapter, InstallationTarget, ReadyDeployResult } from '../../deployment/adapter/index.js';
2
+ import type { InstallationEvidence } from './installation/index.js';
3
+ import { writeDeploymentEvidence } from './evidence.js';
4
+ import { reconcileInstallation } from './installation/index.js';
5
+ export interface EnvironmentReleaseDependencies {
6
+ readonly writeEvidence: typeof writeDeploymentEvidence;
7
+ readonly reconcileInstallation: typeof reconcileInstallation;
8
+ }
9
+ /** Retain verified provider evidence and reconcile one optional durable Kernel installation. */
10
+ export declare function reconcileEnvironmentRelease(input: {
11
+ readonly projectDir: string;
12
+ readonly environment: string;
13
+ readonly adapter: Adapter<object>;
14
+ readonly deployment: ReadyDeployResult;
15
+ readonly installation?: InstallationTarget;
16
+ readonly deployOnly: boolean;
17
+ readonly identity?: string;
18
+ readonly credential?: string;
19
+ readonly installationExecutable?: string;
20
+ readonly signal: AbortSignal;
21
+ }, dependencies?: EnvironmentReleaseDependencies): Promise<InstallationEvidence | undefined>;
@@ -0,0 +1,46 @@
1
+ import { writeDeploymentEvidence } from './evidence.js';
2
+ import { reconcileInstallation } from './installation/index.js';
3
+ /** Retain verified provider evidence and reconcile one optional durable Kernel installation. */
4
+ export async function reconcileEnvironmentRelease(input, dependencies = {
5
+ writeEvidence: writeDeploymentEvidence,
6
+ reconcileInstallation,
7
+ }) {
8
+ try {
9
+ await dependencies.writeEvidence({
10
+ projectDir: input.projectDir,
11
+ environment: input.environment,
12
+ adapter: input.adapter,
13
+ deployment: input.deployment,
14
+ });
15
+ }
16
+ catch (cause) {
17
+ throw new TypeError(`Domain ${input.deployment.release.publication.origin} remains deployed, but its local evidence could not be saved. Kernel installation was not attempted.`, { cause });
18
+ }
19
+ if (input.installation === undefined || input.deployOnly)
20
+ return undefined;
21
+ if (input.installationExecutable === undefined) {
22
+ throw new TypeError('A compatible Astrale CLI must be pinned before deploying an installed Environment.');
23
+ }
24
+ const installation = await dependencies.reconcileInstallation({
25
+ projectDir: input.projectDir,
26
+ target: input.installation,
27
+ executable: input.installationExecutable,
28
+ ...(input.identity === undefined ? {} : { identity: input.identity }),
29
+ ...(input.credential === undefined ? {} : { credential: input.credential }),
30
+ release: input.deployment.release,
31
+ signal: input.signal,
32
+ });
33
+ try {
34
+ await dependencies.writeEvidence({
35
+ projectDir: input.projectDir,
36
+ environment: input.environment,
37
+ adapter: input.adapter,
38
+ deployment: input.deployment,
39
+ installation,
40
+ });
41
+ }
42
+ catch (cause) {
43
+ throw new TypeError(`Domain ${installation.origin} remains installed on ${installation.instance}, but its local evidence could not be saved. The installation was not rolled back.`, { cause });
44
+ }
45
+ return installation;
46
+ }
@@ -0,0 +1,11 @@
1
+ import type { Adapter, ReadyDeployResult } from '../../deployment/adapter/index.js';
2
+ import type { InstallationEvidence } from './installation/index.js';
3
+ export declare const DEPLOYMENT_EVIDENCE_VERSION: 1;
4
+ /** Persist one non-secret, non-authoritative continuity observation atomically. */
5
+ export declare function writeDeploymentEvidence(input: {
6
+ readonly projectDir: string;
7
+ readonly environment: string;
8
+ readonly adapter: Adapter<object>;
9
+ readonly deployment: ReadyDeployResult;
10
+ readonly installation?: InstallationEvidence;
11
+ }): Promise<string>;
@@ -0,0 +1,53 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { mkdir, rename, unlink, writeFile } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ export const DEPLOYMENT_EVIDENCE_VERSION = 1;
5
+ /** Persist one non-secret, non-authoritative continuity observation atomically. */
6
+ export async function writeDeploymentEvidence(input) {
7
+ const directory = join(input.projectDir, '.astrale', 'environments', input.environment);
8
+ const path = join(directory, 'deployment.json');
9
+ await mkdir(directory, { recursive: true });
10
+ const provider = input.deployment.progress.provider.evidence;
11
+ const value = Object.freeze({
12
+ version: DEPLOYMENT_EVIDENCE_VERSION,
13
+ environment: input.environment,
14
+ adapter: Object.freeze({ name: input.adapter.name, version: input.adapter.version }),
15
+ deployment: Object.freeze({
16
+ provider: provider.provider,
17
+ id: provider.deployment,
18
+ artifact: provider.artifact,
19
+ issuer: input.deployment.release.addressing.issuer,
20
+ publicUrl: input.deployment.release.addressing.publicUrl,
21
+ origin: input.deployment.release.publication.origin,
22
+ revision: input.deployment.release.publication.schema.revision,
23
+ etag: input.deployment.release.publication.etag,
24
+ readiness: 'ready',
25
+ ...(provider.preflight === undefined ? {} : { preflight: provider.preflight }),
26
+ }),
27
+ ...(input.installation === undefined
28
+ ? {}
29
+ : {
30
+ installation: Object.freeze({
31
+ instance: input.installation.instance,
32
+ origin: input.installation.origin,
33
+ issuer: input.installation.issuer,
34
+ revision: input.installation.revision,
35
+ etag: input.installation.etag,
36
+ generation: input.installation.generation,
37
+ status: input.installation.status,
38
+ }),
39
+ }),
40
+ });
41
+ const staging = join(directory, `.deployment-${randomUUID()}.json`);
42
+ await writeFile(staging, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600, flag: 'wx' });
43
+ try {
44
+ await rename(staging, path);
45
+ }
46
+ finally {
47
+ await unlink(staging).catch((cause) => {
48
+ if (cause.code !== 'ENOENT')
49
+ throw cause;
50
+ });
51
+ }
52
+ return path;
53
+ }
@@ -12,17 +12,19 @@ export function helpText(command) {
12
12
  export const ERROR_USAGE = `Usage: astrale-domain <command> [options]
13
13
  Run "astrale-domain --help" for available commands.
14
14
  `;
15
- const GLOBAL_HELP = `Build, develop, deploy, lint, and package Astrale Domains.
15
+ const GLOBAL_HELP = `Build, develop, deploy, test, lint, and package Astrale Domains.
16
16
 
17
17
  Usage:
18
18
  astrale-domain <command> [options]
19
19
 
20
20
  Commands:
21
- dev [environment] Build and run a watched development session.
21
+ dev [environment] Remotely deploy and watch one Project Environment.
22
22
  build Build and verify without deploying.
23
- deploy <environment> Deploy through the configured adapter.
23
+ deploy <environment> Deploy and optionally install one Environment.
24
+ test Run Project tests, optionally against one Environment.
24
25
  lint Check Domain source and architecture.
25
26
  package Prepare public declarations for publication.
27
+ upgrade Update Astrale dependencies through pnpm (default: beta).
26
28
 
27
29
  Options:
28
30
  -h, --help Show help.
@@ -30,51 +32,73 @@ Options:
30
32
  Run "astrale-domain <command> --help" for command-specific help.
31
33
  `;
32
34
  const COMMAND_HELP = Object.freeze({
33
- dev: `Build, verify, and run a watched Domain development session.
35
+ upgrade: `Update existing Astrale dependencies in a pnpm project or workspace.
36
+
37
+ Usage:
38
+ astrale-domain upgrade [--channel <tag>] [--check]
39
+
40
+ Options:
41
+ --channel <tag> Registry dist-tag to select (default: beta).
42
+ --check Show changes without modifying project files or installing.
43
+ -h, --help Show help for upgrade.
44
+
45
+ Behavior:
46
+ Updates dependencies, devDependencies, and optionalDependencies under @astrale-os/
47
+ and @astrale-domains/, including the workspace root. Writes exact versions and
48
+ runs pnpm install once. The selected tag is authoritative, even if older than
49
+ the current version. Installation is synchronized even when versions are unchanged,
50
+ so retrying can finish a previously failed install. Packages without that tag remain
51
+ unchanged with a warning.
52
+ Local links, catalogs, aliases, peers, and overrides are not rewritten.
53
+ Does not load astrale.config.ts, require Bun, run project checks, commit, or deploy.
54
+ Stop development watchers before upgrading. Review changes and run your project's
55
+ checks afterwards. Failed installations leave local changes available for repair.
56
+ For an older SDK without this command: pnpm dlx @astrale-os/sdk@beta upgrade.
57
+ `,
58
+ dev: `Build, verify, remotely deploy, and watch one Project Environment.
34
59
 
35
60
  Usage:
36
61
  astrale-domain dev [environment] [options]
37
62
 
38
63
  Arguments:
39
- environment Adapter environment key (default: dev).
64
+ environment Project Environment name; defaults to development.
40
65
 
41
66
  Options:
42
67
  --environment <name> Select the environment without a positional argument.
43
- --port <port> Use a strict local Worker port (default: OS-allocated).
44
- --host <url> Use an externally managed public origin; requires a strict port
45
- from --port or adapter configuration.
68
+ --deploy-only Suppress this run's configured Kernel installation.
69
+ --as <identity> Select the Astrale identity for Services and installation calls.
46
70
  --session-file <path> Write one retained DevelopmentSessionFileV1 snapshot at an
47
71
  absolute path in a caller-owned private directory.
48
72
  --credential-file <path>
49
- Use one private operator credential for adapter-owned Kernel
50
- calls without exposing it in project configuration.
73
+ Use one private operator credential for provider and Kernel
74
+ calls without exposing it in Project configuration.
51
75
  --secrets-file <path> Load one private, absolute secrets file for this development
52
76
  session instead of the adapter-declared secrets file.
53
77
  -h, --help Show help for dev.
54
78
 
55
79
  Behavior:
56
- Builds and verifies the Application, Runtime, and adapter-prepared artifact.
57
- Serves the generated Worker and an optional Vite frontend. Vite uses its own
58
- OS-allocated loopback port.
59
- Watches imported authored sources and declared secrets. Configuration changes
60
- require restarting the command.
80
+ The selected Environment must exist; no other Environment is chosen as a fallback.
81
+ Builds and verifies the Application, Runtime, frontend, and adapter artifact, then
82
+ deploys it through the selected Environment. It never starts a local Worker,
83
+ Vite server, or tunnel. Imported source changes produce serialized remote updates;
84
+ configuration changes require restarting the command.
85
+ A shared direct-provider target additionally requires an external single-writer
86
+ boundary such as a CI/CD concurrency group.
61
87
  The session file is machine-readable and authoritative when requested; human
62
88
  stdout/stderr remains diagnostic. It requires an adapter that reports exact
63
- installed Release evidence.
64
- A credential file is read only by the installation-owning adapter. Its value is
65
- never forwarded to the Domain runtime or written to the session file.
89
+ installed Release evidence, so it is rejected for an Environment without an
90
+ installation and when --deploy-only suppresses installation.
91
+ A credential file is admitted and read once. Its value is passed only to the
92
+ deployment adapter, configured Kernel installation, and default View; it never
93
+ enters Domain Runtime secrets, diagnostics, deployment evidence, or the session
94
+ file. It is currently unavailable on Windows because private no-reparse file
95
+ admission is absent.
66
96
  A secrets-file override is read once, passed to the Domain runtime as secrets,
67
97
  never mutates the authored project, and is not watched for later changes. It is
68
- currently unavailable on Windows because private no-reparse admission is absent.
69
-
70
- Adapters:
71
- cloudflare Runs the local Worker and optional Vite frontend only;
72
- it owns no public ingress or Kernel installation.
73
- astrale Also owns a Quick Tunnel when no public host is configured,
74
- reconciles each verified Release on the configured or
75
- CLI-active instance, and starts a local View host when
76
- a View is declared. The installation remains after the
77
- development session stops.
98
+ also unavailable on Windows because private no-reparse admission is absent.
99
+
100
+ Stopping the watcher stops only local build orchestration. The remote deployment
101
+ and optional Kernel installation remain available.
78
102
  `,
79
103
  build: `Build and verify a Domain without deploying it.
80
104
 
@@ -85,9 +109,9 @@ Options:
85
109
  -h, --help Show help for build.
86
110
 
87
111
  Behavior:
88
- Compiles the Application and Runtime, runs adapter preparation, and verifies
89
- the resulting artifact. It does not load declared secrets, deploy, or install
90
- the Domain.
112
+ Compiles the Application and verifies that the conventional or configured Runtime
113
+ module exports the exact Runtime owned by it. It does not select an Environment,
114
+ load secrets, deploy, or install the Domain.
91
115
  `,
92
116
  deploy: `Build, verify, and deploy a Domain through its configured adapter.
93
117
 
@@ -100,12 +124,32 @@ Arguments:
100
124
 
101
125
  Options:
102
126
  --environment <name> Select the environment without a positional argument.
127
+ --deploy-only Suppress this run's configured Kernel installation.
128
+ --as <identity> Select the Astrale identity for Services and installation calls.
103
129
  -h, --help Show help for deploy.
104
130
 
105
131
  Behavior:
106
- Builds and verifies the Release, loads declared secrets, and invokes the
107
- adapter deployment. Deployment does not install the deployed Domain on a
108
- Kernel instance.
132
+ Builds and verifies the Application, Runtime, and provider artifact, loads declared
133
+ secrets, and invokes the selected adapter. It then verifies the resulting Release.
134
+ When the Environment declares installation, reconciles it after provider readiness.
135
+ An Environment without installation performs zero Kernel calls.
136
+ `,
137
+ test: `Run Project tests locally or against one selected Environment.
138
+
139
+ Usage:
140
+ astrale-domain test [options]
141
+
142
+ Options:
143
+ --environment <name> Select the committed Project Environment exposed to tests as
144
+ ASTRALE_PROJECT_ENVIRONMENT.
145
+ --suite <name> Select a named Vitest project from vitest.config.ts.
146
+ -h, --help Show help for test.
147
+
148
+ Behavior:
149
+ Without an Environment, runs the Project-local Vitest suite once. With an
150
+ Environment, first validates the name against astrale.config.ts, then exposes
151
+ that exact name to the selected suite. Test definitions remain Project-level;
152
+ environments never duplicate or override them.
109
153
  `,
110
154
  lint: `Check Domain source and architecture.
111
155
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * `@astrale-os/sdk/cli` — the `astrale-domain` CLI
3
- * (dev | build | deploy | lint | package), explicit dotenv boundary, and admitted
3
+ * (dev | build | deploy | test | lint | package), explicit dotenv boundary, and admitted
4
4
  * development-session file representation.
5
5
  *
6
6
  * Node-only: the CLI imports `node:fs`/`node:module`/`node:url` and runs under
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * `@astrale-os/sdk/cli` — the `astrale-domain` CLI
3
- * (dev | build | deploy | lint | package), explicit dotenv boundary, and admitted
3
+ * (dev | build | deploy | test | lint | package), explicit dotenv boundary, and admitted
4
4
  * development-session file representation.
5
5
  *
6
6
  * Node-only: the CLI imports `node:fs`/`node:module`/`node:url` and runs under
@@ -0,0 +1,2 @@
1
+ export { reconcileInstallation } from './reconcile.js';
2
+ export type { AstraleCommandResult, InstallationDependencies, InstallationEvidence, } from './reconcile.js';
@@ -0,0 +1 @@
1
+ export { reconcileInstallation } from './reconcile.js';
@@ -0,0 +1,10 @@
1
+ export interface InstallationObservation {
2
+ readonly origin: string;
3
+ readonly revision: string;
4
+ readonly issuer: string;
5
+ readonly generation: string;
6
+ readonly etag: string;
7
+ }
8
+ /** Admit exact installed Release evidence returned by Kernel introspection. */
9
+ export declare function decodeInstallationObservation(input: string): InstallationObservation;
10
+ export declare function canonicalIssuer(input: string): string;
@@ -0,0 +1,44 @@
1
+ /** Admit exact installed Release evidence returned by Kernel introspection. */
2
+ export function decodeInstallationObservation(input) {
3
+ let decoded;
4
+ try {
5
+ decoded = JSON.parse(input);
6
+ }
7
+ catch (cause) {
8
+ throw new TypeError('Astrale introspection did not return one JSON value.', { cause });
9
+ }
10
+ const root = record(decoded);
11
+ const publication = record(root.publication);
12
+ const identity = record(publication.identity);
13
+ if (typeof root.origin !== 'string' ||
14
+ typeof root.revision !== 'string' ||
15
+ typeof root.generation !== 'string' ||
16
+ !/^sha256:[0-9a-f]{64}$/u.test(root.generation) ||
17
+ publication.origin !== root.origin ||
18
+ publication.revision !== root.revision ||
19
+ typeof identity.issuer !== 'string' ||
20
+ typeof publication.etag !== 'string' ||
21
+ !/^sha256:[0-9a-f]{64}$/u.test(publication.etag)) {
22
+ throw new TypeError('Astrale introspection returned invalid installed Domain evidence.');
23
+ }
24
+ return Object.freeze({
25
+ origin: root.origin,
26
+ revision: root.revision,
27
+ issuer: canonicalIssuer(identity.issuer),
28
+ generation: root.generation,
29
+ etag: publication.etag,
30
+ });
31
+ }
32
+ export function canonicalIssuer(input) {
33
+ const url = new URL(input);
34
+ if (url.href !== url.origin && url.href !== `${url.origin}/`) {
35
+ throw new TypeError('Release issuer must be one canonical origin.');
36
+ }
37
+ return url.origin;
38
+ }
39
+ function record(input) {
40
+ if (input === null || typeof input !== 'object' || Array.isArray(input)) {
41
+ throw new TypeError('Astrale introspection returned invalid installed Domain evidence.');
42
+ }
43
+ return input;
44
+ }