@astrale-os/cli 1.0.0-beta.3 → 1.0.0-beta.31

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 (345) hide show
  1. package/README.md +84 -6
  2. package/dist/astrale.js +57586 -60753
  3. package/dist/public/connect-core.js +2158 -30706
  4. package/dist/public/keys/index.js +1016 -29541
  5. package/dist/public/paths/index.js +370 -28654
  6. package/dist/types/admin/contract.d.ts +26 -0
  7. package/dist/types/admin/instance/client.d.ts +20 -0
  8. package/dist/types/admin/instance/index.d.ts +2 -0
  9. package/dist/types/admin/instance/model.d.ts +6 -10
  10. package/dist/types/connection/auth.d.ts +3 -0
  11. package/dist/types/connection/call.d.ts +3 -0
  12. package/dist/types/connection/command.d.ts +27 -0
  13. package/dist/types/connection/credential.d.ts +14 -0
  14. package/dist/types/connection/errors.d.ts +1 -0
  15. package/dist/types/connection/exchange.d.ts +9 -0
  16. package/dist/types/connection/failure/classify.d.ts +2 -0
  17. package/dist/types/connection/failure/index.d.ts +5 -0
  18. package/dist/types/connection/failure/model.d.ts +25 -0
  19. package/dist/types/connection/failure/render.d.ts +3 -0
  20. package/dist/types/connection/index.d.ts +8 -0
  21. package/dist/types/connection/reasons.d.ts +37 -0
  22. package/dist/types/connection/self.d.ts +37 -0
  23. package/dist/types/connection/session.d.ts +31 -0
  24. package/dist/types/connection/target.d.ts +38 -0
  25. package/dist/types/errors.d.ts +1 -1
  26. package/dist/types/lib/admin-instance.d.ts +17 -0
  27. package/dist/types/lib/admin-target.d.ts +11 -36
  28. package/dist/types/lib/config.d.ts +13 -59
  29. package/dist/types/lib/failure-debug.d.ts +1 -0
  30. package/dist/types/lib/idp.d.ts +25 -173
  31. package/dist/types/lib/instance-target.d.ts +1 -1
  32. package/dist/types/lib/instance.d.ts +30 -88
  33. package/dist/types/lib/log.d.ts +5 -3
  34. package/dist/types/lib/output.d.ts +1 -1
  35. package/dist/types/lib/proc.d.ts +43 -0
  36. package/dist/types/lib/self.d.ts +9 -0
  37. package/dist/types/lib/update.d.ts +109 -0
  38. package/dist/types/lib/validation.d.ts +4 -1
  39. package/dist/types/state/exchange-credentials.d.ts +6 -2
  40. package/dist/types/state/files.d.ts +2 -0
  41. package/dist/types/state/index.d.ts +3 -2
  42. package/dist/types/state/paths.d.ts +2 -0
  43. package/dist/types/state/session-routes.d.ts +10 -0
  44. package/package.json +16 -19
  45. package/src/__tests__/fixtures/publication.ts +20 -0
  46. package/src/admin/.spec/architecture.md +12 -5
  47. package/src/admin/__tests__/fixture.ts +25 -0
  48. package/src/admin/catalog/.spec/api.d.ts +1 -3
  49. package/src/admin/catalog/.spec/architecture.md +5 -4
  50. package/src/admin/catalog/__tests__/client.test.ts +143 -69
  51. package/src/admin/catalog/client.ts +40 -54
  52. package/src/admin/catalog/model.ts +3 -4
  53. package/src/admin/contract.ts +47 -0
  54. package/src/admin/graph/.spec/api.d.ts +4 -10
  55. package/src/admin/graph/nodes.ts +1 -1
  56. package/src/admin/instance/.spec/api.d.ts +5 -9
  57. package/src/admin/instance/.spec/architecture.md +7 -7
  58. package/src/admin/instance/__tests__/client.test.ts +157 -175
  59. package/src/admin/instance/client.ts +39 -128
  60. package/src/admin/instance/index.ts +1 -2
  61. package/src/admin/instance/model.ts +12 -18
  62. package/src/commands/__tests__/admin-instance.test.ts +11 -8
  63. package/src/commands/__tests__/call-describe.test.ts +46 -33
  64. package/src/commands/__tests__/call.test.ts +34 -0
  65. package/src/commands/__tests__/domain-install-operation.test.ts +30 -22
  66. package/src/commands/__tests__/domain-install-owned.test.ts +1 -1
  67. package/src/commands/__tests__/domain-list.test.ts +5 -25
  68. package/src/commands/__tests__/install-direct.test.ts +115 -8
  69. package/src/commands/__tests__/install-identity-override.test.ts +6 -17
  70. package/src/commands/__tests__/instance-list-rows.test.ts +1 -1
  71. package/src/commands/__tests__/instance-status.test.ts +139 -0
  72. package/src/commands/__tests__/introspect-parse.test.ts +80 -1
  73. package/src/commands/__tests__/logs.test.ts +250 -2
  74. package/src/commands/__tests__/read-commands.test.ts +119 -11
  75. package/src/commands/__tests__/token-ttl.test.ts +49 -4
  76. package/src/commands/__tests__/update.test.ts +25 -3
  77. package/src/commands/__tests__/view.test.ts +50 -2
  78. package/src/commands/auth/logout.ts +2 -1
  79. package/src/commands/browser.ts +29 -0
  80. package/src/commands/call-describe.ts +60 -68
  81. package/src/commands/call.ts +71 -59
  82. package/src/commands/domain/install.ts +73 -46
  83. package/src/commands/domain/list.ts +1 -1
  84. package/src/commands/domain/publish.ts +14 -11
  85. package/src/commands/domain/uninstall.ts +2 -2
  86. package/src/commands/get.ts +15 -16
  87. package/src/commands/identity/__tests__/register.test.ts +3 -3
  88. package/src/commands/identity/register.ts +8 -8
  89. package/src/commands/instance/create.ts +8 -16
  90. package/src/commands/instance/delete.ts +12 -9
  91. package/src/commands/instance/list.ts +2 -2
  92. package/src/commands/instance/status.ts +66 -20
  93. package/src/commands/instance/use.ts +16 -12
  94. package/src/commands/introspect.ts +53 -41
  95. package/src/commands/logs.ts +123 -36
  96. package/src/commands/mutate.ts +6 -5
  97. package/src/commands/query.ts +39 -36
  98. package/src/commands/session/analyze.ts +26 -4
  99. package/src/commands/token.ts +42 -27
  100. package/src/commands/ui/__tests__/commands.test.ts +152 -0
  101. package/src/commands/ui/add.ts +51 -0
  102. package/src/commands/ui/doctor.ts +21 -0
  103. package/src/commands/ui/init.ts +38 -0
  104. package/src/commands/ui/list.ts +26 -0
  105. package/src/commands/ui/preset-apply.ts +19 -0
  106. package/src/commands/ui/preset-list.ts +12 -0
  107. package/src/commands/ui/shared.ts +25 -0
  108. package/src/commands/update.ts +90 -48
  109. package/src/commands/view.ts +82 -37
  110. package/src/connection/.spec/api.d.ts +7 -8
  111. package/src/connection/.spec/architecture.md +14 -5
  112. package/src/connection/.spec/flows/session.ts +2 -2
  113. package/src/connection/.spec/laws/connection.ts +6 -2
  114. package/src/connection/.spec/layout.ts +1 -0
  115. package/src/connection/__tests__/auth.test.ts +1 -0
  116. package/src/connection/__tests__/credential.test.ts +21 -1
  117. package/src/connection/__tests__/errors.test.ts +27 -20
  118. package/src/connection/__tests__/exchange.test.ts +64 -11
  119. package/src/connection/__tests__/failure-fixtures.ts +39 -0
  120. package/src/connection/__tests__/failure-safety.test.ts +75 -0
  121. package/src/connection/__tests__/self.test.ts +31 -11
  122. package/src/connection/__tests__/session.test.ts +8 -4
  123. package/src/connection/__tests__/target.test.ts +2 -0
  124. package/src/connection/auth.ts +13 -0
  125. package/src/connection/call.ts +1 -1
  126. package/src/connection/credential.ts +2 -2
  127. package/src/connection/errors.ts +1 -355
  128. package/src/connection/exchange.ts +110 -61
  129. package/src/connection/failure/classify.ts +110 -0
  130. package/src/connection/failure/index.ts +18 -0
  131. package/src/connection/failure/model.ts +28 -0
  132. package/src/connection/failure/render.ts +116 -0
  133. package/src/connection/reasons.ts +16 -0
  134. package/src/connection/self.ts +39 -21
  135. package/src/connection/session.ts +27 -9
  136. package/src/errors.ts +3 -2
  137. package/src/graph/.spec/api.d.ts +13 -6
  138. package/src/graph/.spec/laws/documents.ts +7 -7
  139. package/src/graph/.spec/layout.ts +9 -1
  140. package/src/graph/__tests__/mutation.test.ts +2 -2
  141. package/src/graph/__tests__/query.test.ts +35 -9
  142. package/src/graph/class.ts +30 -0
  143. package/src/graph/index.ts +1 -0
  144. package/src/graph/query.ts +27 -40
  145. package/src/identity/.spec/api.d.ts +2 -2
  146. package/src/identity/__tests__/fixtures/registry-journey.ts +13 -1
  147. package/src/identity/__tests__/registration.test.ts +1 -1
  148. package/src/identity/__tests__/registry.test.ts +4 -0
  149. package/src/identity/registration.ts +3 -3
  150. package/src/identity/registry.ts +2 -0
  151. package/src/keys/__tests__/keys.test.ts +4 -0
  152. package/src/keys/credential.ts +1 -0
  153. package/src/lib/__tests__/admin-target.test.ts +12 -0
  154. package/src/lib/__tests__/binary.test.ts +16 -1
  155. package/src/lib/__tests__/browser-retention.test.ts +212 -0
  156. package/src/lib/__tests__/command-dx.test.ts +1 -1
  157. package/src/lib/__tests__/config.test.ts +27 -0
  158. package/src/lib/__tests__/domain-publication.test.ts +10 -16
  159. package/src/lib/__tests__/idp.test.ts +34 -4
  160. package/src/lib/__tests__/instance-candidates.test.ts +1 -3
  161. package/src/lib/__tests__/instance-target.test.ts +7 -39
  162. package/src/lib/__tests__/log-errors.test.ts +64 -0
  163. package/src/lib/__tests__/skills.test.ts +834 -0
  164. package/src/lib/__tests__/studio-server-deps.test.ts +1 -1
  165. package/src/lib/__tests__/update.test.ts +264 -11
  166. package/src/lib/__tests__/view-assets.test.ts +25 -0
  167. package/src/lib/__tests__/view-external-open-intent.test.ts +150 -0
  168. package/src/lib/__tests__/view-external-open-origins.test.ts +27 -0
  169. package/src/lib/__tests__/view-open-intent.test.ts +0 -2
  170. package/src/lib/__tests__/view-server.test.ts +26 -3
  171. package/src/lib/__tests__/view-session.test.ts +2 -1
  172. package/src/lib/admin-instance.ts +14 -8
  173. package/src/lib/admin-target.ts +21 -2
  174. package/src/lib/binary.ts +22 -5
  175. package/src/lib/browser-retention.ts +210 -0
  176. package/src/lib/command-dx.ts +9 -9
  177. package/src/lib/config.ts +12 -1
  178. package/src/lib/domain-publication.ts +9 -7
  179. package/src/lib/failure-debug.ts +26 -0
  180. package/src/lib/idp.ts +34 -3
  181. package/src/lib/instance-candidates.ts +2 -2
  182. package/src/lib/instance-target.ts +3 -14
  183. package/src/lib/instance.ts +16 -11
  184. package/src/lib/log.ts +16 -9
  185. package/src/lib/output.ts +1 -1
  186. package/src/lib/proc.ts +7 -2
  187. package/src/lib/provision-instance.ts +34 -57
  188. package/src/lib/skills/lock.ts +117 -0
  189. package/src/lib/skills/sync.ts +878 -0
  190. package/src/lib/skills.ts +1 -52
  191. package/src/lib/update.ts +298 -45
  192. package/src/lib/validation.ts +2 -2
  193. package/src/lib/view/assets.ts +11 -2
  194. package/src/lib/view/external-open-intent.ts +41 -0
  195. package/src/lib/view/external-open-origins.ts +37 -0
  196. package/src/lib/view/host-capabilities.ts +17 -0
  197. package/src/lib/view/resolve.ts +1 -1
  198. package/src/lib/view/server.ts +18 -3
  199. package/src/lib/view/session.ts +2 -0
  200. package/src/program/.spec/api.d.ts +1 -0
  201. package/src/program/__tests__/program.test.ts +201 -7
  202. package/src/program/argv.ts +14 -0
  203. package/src/program/build.ts +26 -4
  204. package/src/program/command.ts +1 -0
  205. package/src/program/index.ts +1 -0
  206. package/src/program/registry.ts +2 -1
  207. package/src/setup/__tests__/instance-step.test.ts +27 -10
  208. package/src/setup/steps/instance.ts +22 -15
  209. package/src/setup/steps/skills.ts +40 -38
  210. package/src/state/.spec/api.d.ts +21 -2
  211. package/src/state/.spec/architecture.md +18 -4
  212. package/src/state/.spec/layout.ts +1 -0
  213. package/src/state/__tests__/exchange-credentials.test.ts +88 -42
  214. package/src/state/__tests__/files.test.ts +24 -1
  215. package/src/state/__tests__/fixtures/session-route-process.ts +93 -0
  216. package/src/state/__tests__/paths.test.ts +1 -0
  217. package/src/state/__tests__/session-routes.test.ts +138 -0
  218. package/src/state/exchange-credentials.ts +22 -9
  219. package/src/state/files.ts +41 -0
  220. package/src/state/index.ts +3 -1
  221. package/src/state/paths.ts +3 -0
  222. package/src/state/session-routes.ts +34 -0
  223. package/src/telemetry/__tests__/analyze-log.test.ts +38 -0
  224. package/src/telemetry/__tests__/recorder.test.ts +1 -0
  225. package/src/telemetry/__tests__/retention.test.ts +267 -0
  226. package/src/telemetry/__tests__/settings.test.ts +102 -0
  227. package/src/telemetry/__tests__/store-scan.test.ts +128 -0
  228. package/src/telemetry/__tests__/trigger.test.ts +33 -4
  229. package/src/telemetry/analyze.ts +24 -2
  230. package/src/telemetry/recorder.ts +15 -4
  231. package/src/telemetry/retention.ts +176 -0
  232. package/src/telemetry/session.ts +18 -12
  233. package/src/telemetry/settings.ts +64 -11
  234. package/src/telemetry/store.ts +92 -9
  235. package/src/telemetry/trigger.ts +16 -28
  236. package/src/ui/.spec/api.d.ts +14 -0
  237. package/src/ui/.spec/architecture.md +14 -0
  238. package/src/ui/.spec/laws.ts +50 -0
  239. package/src/ui/.spec/layout.ts +16 -0
  240. package/src/ui/__tests__/ui.test.ts +1742 -0
  241. package/src/ui/index.ts +13 -0
  242. package/src/ui/lock.ts +89 -0
  243. package/src/ui/model.ts +83 -0
  244. package/src/ui/operations.ts +1044 -0
  245. package/src/ui/project.ts +333 -0
  246. package/src/ui/release.ts +398 -0
  247. package/src/ui/runner.ts +18 -0
  248. package/studio/client/dist/assets/elk-api-DjmKsHXc.js +1 -0
  249. package/studio/client/dist/assets/index-BFVFs_8x.js +81 -0
  250. package/studio/client/dist/assets/index-DuB9iUdu.css +2 -0
  251. package/studio/client/dist/assets/rolldown-runtime-Dd_uD5pT.js +1 -0
  252. package/studio/client/dist/assets/schema-studio--a0kX3QU.css +1 -0
  253. package/studio/client/dist/assets/schema-studio-DH6oEWME.js +8 -0
  254. package/studio/client/dist/index.html +4 -3
  255. package/studio/package.json +8 -14
  256. package/studio/server/agent/ask.test.ts +1 -1
  257. package/studio/server/agent/bridge/grant.test.ts +1 -1
  258. package/studio/server/agent/bridge/routes.test.ts +1 -1
  259. package/studio/server/agent/harness/claude/adapter.test.ts +15 -5
  260. package/studio/server/agent/harness/gateway/token.test.ts +1 -1
  261. package/studio/server/agent/harness/gateway/token.ts +3 -3
  262. package/studio/server/agent/prompts/anchors.test.ts +41 -32
  263. package/studio/server/agent/prompts/anchors.ts +23 -51
  264. package/studio/server/agent/prompts/system.test.ts +4 -4
  265. package/studio/server/agent/prompts/system.ts +5 -5
  266. package/studio/server/agent/routes.test.ts +1 -1
  267. package/studio/server/agent/run/coordinator.test.ts +1 -1
  268. package/studio/server/agent/run/preparation.ts +1 -1
  269. package/studio/server/api/canvas.ts +0 -1
  270. package/studio/server/api/context.ts +1 -1
  271. package/studio/server/api/deployment.ts +1 -1
  272. package/studio/server/api/views.ts +2 -2
  273. package/studio/server/api/workspace.ts +1 -1
  274. package/studio/server/api-agent-loadout.test.ts +1 -1
  275. package/studio/server/api.test.ts +1 -1
  276. package/studio/server/cache.test.ts +24 -18
  277. package/studio/server/cache.ts +10 -54
  278. package/studio/server/cli-consumers.test.ts +32 -4
  279. package/studio/server/cli.test.ts +2 -2
  280. package/studio/server/domain.test.ts +50 -68
  281. package/studio/server/domain.ts +82 -63
  282. package/studio/server/handoff/copy.ts +2 -2
  283. package/studio/server/index.ts +1 -1
  284. package/studio/server/instances/probe.test.ts +1 -1
  285. package/studio/server/introspect/anatomy/views/routes.ts +46 -37
  286. package/studio/server/introspect/anatomy/views.ts +10 -16
  287. package/studio/server/introspect/anatomy-extras.test.ts +29 -56
  288. package/studio/server/introspect/anatomy.test.ts +22 -14
  289. package/studio/server/introspect/anatomy.ts +6 -9
  290. package/studio/server/introspect/bundle.ts +0 -3
  291. package/studio/server/introspect/canonical-schema.test.ts +155 -424
  292. package/studio/server/introspect/canonical-schema.ts +248 -601
  293. package/studio/server/introspect/core.ts +14 -22
  294. package/studio/server/introspect/diff.test.ts +21 -9
  295. package/studio/server/introspect/diff.ts +19 -64
  296. package/studio/server/introspect/extractor.ts +23 -122
  297. package/studio/server/introspect/overlay-tsmorph.test.ts +116 -241
  298. package/studio/server/introspect/overlay-tsmorph.ts +0 -1
  299. package/studio/server/introspect/overlay.ts +3 -51
  300. package/studio/server/introspect/revision.test.ts +24 -28
  301. package/studio/server/introspect/revision.ts +11 -22
  302. package/studio/server/introspect/runtime.test.ts +77 -195
  303. package/studio/server/introspect/runtime.ts +5 -67
  304. package/studio/server/introspect/schema-ir-json.test.ts +81 -0
  305. package/studio/server/introspect/schema-ir-json.ts +39 -69
  306. package/studio/server/introspect/schema-refs.test.ts +43 -88
  307. package/studio/server/introspect/schema-refs.ts +14 -49
  308. package/studio/server/introspect/source-overlay/handlers.ts +116 -636
  309. package/studio/server/introspect/source-overlay/kernel-calls.ts +0 -3
  310. package/studio/server/introspect/source-overlay/spans.ts +15 -45
  311. package/studio/server/lifecycle.ts +4 -1
  312. package/studio/server/state/baseline.test.ts +14 -9
  313. package/studio/server/state/baseline.ts +3 -5
  314. package/studio/server/state/documents.test.ts +69 -0
  315. package/studio/server/state/documents.ts +57 -10
  316. package/studio/server/state/visibility.ts +1 -5
  317. package/studio/server/views/model.ts +3 -3
  318. package/studio/server/views/target.test.ts +18 -76
  319. package/studio/server/views/target.ts +25 -51
  320. package/studio/server/watch.test.ts +11 -11
  321. package/studio/server/watch.ts +8 -4
  322. package/studio/server/workspace/updates.ts +23 -1
  323. package/studio/server/workspace-watch.ts +2 -2
  324. package/studio/shared/contracts/runtime.ts +4 -0
  325. package/studio/shared/contracts/schema.ts +44 -131
  326. package/studio/shared/contracts/surface.test.ts +15 -17
  327. package/studio/shared/contracts/workspace.ts +5 -11
  328. package/studio/shared/schema/identity.test.ts +20 -44
  329. package/studio/shared/schema/identity.ts +9 -24
  330. package/studio/tsconfig.json +2 -1
  331. package/tsconfig.json +1 -1
  332. package/viewer/dist/index.html +21 -0
  333. package/viewer/dist/main.js +41 -62
  334. package/.check-workspace.cjs +0 -40
  335. package/src/admin/binding.ts +0 -168
  336. package/src/commands/__tests__/instance-create-hosts.test.ts +0 -29
  337. package/studio/client/dist/assets/elk-api-lwhFo7vB.js +0 -1
  338. package/studio/client/dist/assets/index-B-c-smo9.js +0 -8
  339. package/studio/client/dist/assets/index-BckHuAWk.js +0 -81
  340. package/studio/client/dist/assets/index-C4aNQ6dz.css +0 -1
  341. package/studio/client/dist/assets/index-ChOr3yP0.css +0 -1
  342. package/studio/server/introspect/anatomy/views/legacy.ts +0 -232
  343. package/studio/server/introspect/core-extractor.ts +0 -139
  344. package/studio/server/introspect/overlay.test.ts +0 -72
  345. package/studio/server/introspect/source-overlay/annotations.ts +0 -14
@@ -5,10 +5,9 @@ export {
5
5
  type AdminInstanceDependencies,
6
6
  } from './client'
7
7
  export {
8
- AdminHostNotFoundError,
9
8
  AdminInstanceNotFoundError,
10
9
  findOwnedInstance,
11
- formatInstanceLocation,
10
+ formatInstanceState,
12
11
  type DomainInstallReceipt,
13
12
  type InstanceInfo,
14
13
  type InstanceState,
@@ -7,10 +7,11 @@ export interface InstanceInfo {
7
7
  readonly url: string
8
8
  readonly hostId?: string
9
9
  readonly region?: string
10
- readonly state?: InstanceState
10
+ readonly state: InstanceState
11
11
  readonly phase?: string
12
12
  readonly error?: string | null
13
13
  readonly createdAt?: string
14
+ readonly updatedAt?: string
14
15
  readonly organizationId?: string
15
16
  }
16
17
 
@@ -28,19 +29,13 @@ export interface DomainInstallReceipt {
28
29
  readonly error?: string
29
30
  }
30
31
 
31
- export class AdminInstanceNotFoundError extends Error {
32
- readonly name = 'NotFoundError'
33
-
34
- constructor(readonly identifier: string) {
35
- super(`No owned Admin Instance matches ${JSON.stringify(identifier)}.`)
36
- }
37
- }
38
-
39
- export class AdminHostNotFoundError extends Error {
40
- readonly name = 'NotFoundError'
41
-
32
+ export class AdminInstanceNotFoundError extends AstraleError {
42
33
  constructor(readonly identifier: string) {
43
- super(`No caller-usable Admin Host matches ${JSON.stringify(identifier)}.`)
34
+ super(
35
+ 'INSTANCE_NOT_FOUND',
36
+ `No owned Admin Instance matches ${JSON.stringify(identifier)}.`,
37
+ 'Run `astrale instance list` to see your instances.',
38
+ )
44
39
  }
45
40
  }
46
41
 
@@ -57,9 +52,8 @@ export function findOwnedInstance(
57
52
  )
58
53
  }
59
54
 
60
- /** Human-readable location of an Instance (state, region, and Host Path). */
61
- export function formatInstanceLocation(info: InstanceInfo): string {
62
- return [info.state && info.state !== 'ready' ? info.state : undefined, info.region, info.hostId]
63
- .filter(Boolean)
64
- .join(' · ')
55
+ /** Human-readable non-ready lifecycle state for one Instance. */
56
+ export function formatInstanceState(info: InstanceInfo): string {
57
+ return info.state === 'ready' ? '' : `${info.state}${info.phase ? ` (${info.phase})` : ''}`
65
58
  }
59
+ import { AstraleError } from '../../errors'
@@ -4,7 +4,10 @@ import type { IdentityStore } from '../../identity/index'
4
4
 
5
5
  import { AuthError } from '../../errors'
6
6
  import { findOwnedInstance, type OwnedInstanceInfo } from '../../lib/admin-instance'
7
- import { assertAlphaCreateIdentity } from '../instance/create'
7
+ import {
8
+ assertInstanceCreateIdentity,
9
+ selectInstanceCreateIdentity,
10
+ } from '../../lib/provision-instance'
8
11
 
9
12
  describe('admin-backed instance commands', () => {
10
13
  test('findOwnedInstance matches owner inventory by slug or stable node id', () => {
@@ -14,8 +17,6 @@ describe('admin-backed instance commands', () => {
14
17
  url: 'https://demo.eu.astrale.ai',
15
18
  state: 'failed',
16
19
  organizationId: 'org_123',
17
- hostId: 'host-1',
18
- region: 'eu',
19
20
  phase: 'installing:default-domains',
20
21
  error: 'postInstall failed',
21
22
  createdAt: '2026-07-16T00:00:00.000Z',
@@ -39,8 +40,8 @@ describe('admin-backed instance commands', () => {
39
40
  },
40
41
  }
41
42
 
42
- expect(() => assertAlphaCreateIdentity(store)).toThrow(AuthError)
43
- expect(() => assertAlphaCreateIdentity(store)).toThrow('WorkOS login required')
43
+ expect(() => assertInstanceCreateIdentity(store)).toThrow(AuthError)
44
+ expect(() => assertInstanceCreateIdentity(store)).toThrow('WorkOS login required')
44
45
  })
45
46
 
46
47
  test('instance create preflight accepts IdP-backed identities', () => {
@@ -58,7 +59,8 @@ describe('admin-backed instance commands', () => {
58
59
  },
59
60
  }
60
61
 
61
- expect(() => assertAlphaCreateIdentity(store)).not.toThrow()
62
+ expect(() => assertInstanceCreateIdentity(store)).not.toThrow()
63
+ expect(selectInstanceCreateIdentity(store)).toBe('bryan')
62
64
  })
63
65
 
64
66
  test('--as selection must also be IdP-backed', () => {
@@ -82,7 +84,8 @@ describe('admin-backed instance commands', () => {
82
84
  },
83
85
  }
84
86
 
85
- expect(() => assertAlphaCreateIdentity(store, { as: 'local' })).toThrow(AuthError)
86
- expect(() => assertAlphaCreateIdentity(store, { as: 'workos' })).not.toThrow()
87
+ expect(() => assertInstanceCreateIdentity(store, { as: 'local' })).toThrow(AuthError)
88
+ expect(() => assertInstanceCreateIdentity(store, { as: 'workos' })).not.toThrow()
89
+ expect(selectInstanceCreateIdentity(store, { as: 'workos' })).toBe('workos')
87
90
  })
88
91
  })
@@ -1,34 +1,47 @@
1
1
  import { Path } from '@astrale-os/sdk/graph/path'
2
+ import { bundle, defineSchema, func, method, nodeClass } from '@astrale-os/sdk/schema'
2
3
  import { describe, expect, test } from 'bun:test'
3
4
 
4
- import { describeCallableFromSchema } from '../call-describe'
5
+ import { describeCallableFromBundle } from '../call-describe'
5
6
 
6
- const schema = {
7
- classes: {
8
- Manager: {
9
- methods: {
10
- createInstance: {
11
- auth: 'authorized',
12
- description: 'Create one child Instance.',
13
- input: { type: 'object', required: ['operationId', 'slug'] },
14
- output: { mode: 'value' },
15
- },
16
- },
17
- },
7
+ const createInstance = method({
8
+ auth: 'authenticated',
9
+ description: 'Create one child Instance.',
10
+ input: {
11
+ type: 'object',
12
+ properties: { operationId: { type: 'string' }, slug: { type: 'string' } },
13
+ required: ['operationId', 'slug'],
14
+ additionalProperties: false,
18
15
  },
19
- functions: {
20
- journal: {
21
- description: 'Read the authorized Kernel journal.',
22
- input: { type: 'object' },
23
- },
16
+ output: { type: 'object', additionalProperties: true },
17
+ static: true,
18
+ })
19
+ const inspectInstance = method({
20
+ auth: 'authenticated',
21
+ description: 'Inspect one child Instance.',
22
+ input: { type: 'object', properties: {}, additionalProperties: false },
23
+ output: { type: 'object', additionalProperties: true },
24
+ })
25
+ const journal = func({
26
+ auth: 'authenticated',
27
+ description: 'Read the authorized Kernel journal.',
28
+ input: { type: 'object', properties: {}, additionalProperties: false },
29
+ output: { type: 'object', additionalProperties: true },
30
+ })
31
+ const source = defineSchema('host.astrale.ai', {
32
+ classes: {
33
+ Manager: nodeClass({ methods: { createInstance } }),
34
+ Instance: nodeClass({ methods: { inspectInstance } }),
24
35
  },
25
- }
36
+ functions: { journal },
37
+ })
38
+ const installed = bundle.create(source)
26
39
 
27
- describe('describeCallableFromSchema', () => {
28
- test('reads a static Class method from the Domain schema', () => {
29
- const described = describeCallableFromSchema(
40
+ describe('describeCallableFromBundle', () => {
41
+ test('reads a static Class method from the resolved Domain', () => {
42
+ const described = describeCallableFromBundle(
30
43
  Path.parse('/:host.astrale.ai:class.Manager:createInstance'),
31
- schema,
44
+ installed,
32
45
  )
33
46
  expect(described).toMatchObject({
34
47
  origin: 'host.astrale.ai',
@@ -36,30 +49,30 @@ describe('describeCallableFromSchema', () => {
36
49
  method: 'createInstance',
37
50
  dispatch: 'static',
38
51
  description: 'Create one child Instance.',
39
- auth: 'authorized',
52
+ auth: 'authenticated',
40
53
  })
41
54
  expect(described?.input).toMatchObject({ required: ['operationId', 'slug'] })
42
55
  })
43
56
 
44
- test('finds an instance method when the receiver Path is not a Class projection', () => {
57
+ test('finds one instance method when the receiver Path is not a Class projection', () => {
45
58
  expect(
46
- describeCallableFromSchema(
47
- Path.parse('/:host.astrale.ai:core.manager::createInstance'),
48
- schema,
59
+ describeCallableFromBundle(
60
+ Path.parse('/:host.astrale.ai:core.manager::inspectInstance'),
61
+ installed,
49
62
  ),
50
63
  ).toMatchObject({
51
64
  origin: 'host.astrale.ai',
52
- class: 'Manager',
53
- method: 'createInstance',
65
+ class: 'Instance',
66
+ method: 'inspectInstance',
54
67
  dispatch: 'instance',
55
68
  })
56
69
  })
57
70
 
58
- test('reads a standalone Function from the Domain schema', () => {
71
+ test('reads a standalone Function from the resolved Domain', () => {
59
72
  expect(
60
- describeCallableFromSchema(Path.parse('/:kernel.astrale.ai:function.journal'), schema),
73
+ describeCallableFromBundle(Path.parse('/:host.astrale.ai:function.journal'), installed),
61
74
  ).toMatchObject({
62
- origin: 'kernel.astrale.ai',
75
+ origin: 'host.astrale.ai',
63
76
  function: 'journal',
64
77
  description: 'Read the authorized Kernel journal.',
65
78
  })
@@ -26,4 +26,38 @@ describe('call command result lifetime', () => {
26
26
  if (materialized.kind !== 'stream') throw new Error('expected a materialized stream')
27
27
  expect(Object.isFrozen(materialized.values)).toBe(true)
28
28
  })
29
+
30
+ test('drains streaming binary bytes before the command session closes', async () => {
31
+ let sessionOpen = true
32
+ async function* body() {
33
+ for (const chunk of [new Uint8Array([1, 2]), new Uint8Array([3])]) {
34
+ if (!sessionOpen) throw new Error('session closed before binary consumption')
35
+ yield chunk
36
+ }
37
+ }
38
+
39
+ const materialized = await materializeCallResult({
40
+ kind: 'binary',
41
+ invocation: { source: 'https://kernel.test' as never, id: 'test-binary' },
42
+ value: {
43
+ body: body(),
44
+ mediaType: 'application/octet-stream',
45
+ status: 206,
46
+ headers: { 'content-range': 'bytes 0-2/3' },
47
+ },
48
+ })
49
+ sessionOpen = false
50
+
51
+ expect(materialized).toMatchObject({
52
+ kind: 'binary',
53
+ value: {
54
+ mediaType: 'application/octet-stream',
55
+ status: 206,
56
+ headers: { 'content-range': 'bytes 0-2/3' },
57
+ },
58
+ })
59
+ if (materialized.kind !== 'binary') throw new Error('expected materialized binary')
60
+ expect([...materialized.value.body]).toEqual([1, 2, 3])
61
+ expect(Object.isFrozen(materialized.value)).toBe(true)
62
+ })
29
63
  })
@@ -1,9 +1,7 @@
1
- import { defineDomain } from '@astrale-os/sdk'
2
- import { issuer } from '@astrale-os/sdk/auth'
3
- import { createDeployment } from '@astrale-os/sdk/deployment'
4
- import { defineSchema } from '@astrale-os/sdk/schema/v1'
1
+ import { defineSchema } from '@astrale-os/sdk/schema'
5
2
  import { afterEach, describe, expect, mock, test } from 'bun:test'
6
3
 
4
+ import { releaseFor } from '../../__tests__/fixtures/publication'
7
5
  import { installDirect } from '../domain/install'
8
6
 
9
7
  const GENERATED = '4a4c9a18-50f6-4d84-a7b7-2d83e3e45dc8'
@@ -12,16 +10,7 @@ const RETRY = '139137b5-af47-47ce-92b2-b64a2b0c63d7'
12
10
  const originalFetch = globalThis.fetch
13
11
 
14
12
  const schema = defineSchema('crm.test', {})
15
- const definition = defineDomain({
16
- schema,
17
- handlers: { functions: {}, classes: {}, interfaces: {} },
18
- })
19
- const deployed = createDeployment({
20
- definition,
21
- issuer: issuer.accept('https://crm.test'),
22
- bundleHref: 'https://crm.test/domain.bundle.json',
23
- bindings: { callables: [] },
24
- }).publication
13
+ const deployed = releaseFor(schema, 'https://crm.test').publication
25
14
 
26
15
  function publicationResponse(): Response {
27
16
  return Response.json(deployed)
@@ -49,9 +38,7 @@ describe('direct domain install operation identity', () => {
49
38
  recovery = input.recovery
50
39
  requests.push(
51
40
  await input.fn({
52
- session: {
53
- call: async (call: { input: unknown }) => call.input,
54
- },
41
+ session: { schema: { install: async (input: unknown) => input } },
55
42
  } as never),
56
43
  )
57
44
  },
@@ -62,7 +49,7 @@ describe('direct domain install operation identity', () => {
62
49
  expect(requests).toEqual([
63
50
  {
64
51
  operation: GENERATED,
65
- domains: [{ source: { kind: 'remote', url: 'https://crm.test' } }],
52
+ domains: [{ publication: { url: 'https://crm.test' } }],
66
53
  },
67
54
  ])
68
55
  expect(recovery).toEqual({
@@ -89,9 +76,7 @@ describe('direct domain install operation identity', () => {
89
76
  runKernelCommand: async (input) => {
90
77
  requests.push(
91
78
  await input.fn({
92
- session: {
93
- call: async (call: { input: unknown }) => call.input,
94
- },
79
+ session: { schema: { install: async (input: unknown) => input } },
95
80
  } as never),
96
81
  )
97
82
  },
@@ -103,11 +88,34 @@ describe('direct domain install operation identity', () => {
103
88
  expect(requests).toEqual([
104
89
  {
105
90
  operation: RETRY,
106
- domains: [{ source: { kind: 'remote', url: 'https://crm.test' } }],
91
+ domains: [{ publication: { url: 'https://crm.test' } }],
107
92
  },
108
93
  ])
109
94
  })
110
95
 
96
+ test('keeps identity-override consent warnings out of machine output', async () => {
97
+ globalThis.fetch = mock(async () => publicationResponse()) as unknown as typeof fetch
98
+ const originalError = console.error
99
+ const warnings: unknown[][] = []
100
+ console.error = (...args: unknown[]) => {
101
+ warnings.push(args)
102
+ }
103
+ try {
104
+ await installDirect(
105
+ 'https://alias.test',
106
+ { direct: true, json: true, allowIdentityOverride: true },
107
+ {
108
+ createOperationId: () => GENERATED,
109
+ runKernelCommand: async () => undefined,
110
+ },
111
+ )
112
+ } finally {
113
+ console.error = originalError
114
+ }
115
+
116
+ expect(warnings).toEqual([])
117
+ })
118
+
111
119
  test('rejects a non-UUID operation before metadata or Kernel transport', async () => {
112
120
  const originalExit = process.exit
113
121
  const originalWrite = process.stderr.write
@@ -1,4 +1,4 @@
1
- import { ResponseError } from '@astrale-os/kernel-client'
1
+ import { ResponseError } from '@astrale-os/sdk/client'
2
2
  import { afterEach, beforeEach, describe, expect, mock, test } from 'bun:test'
3
3
 
4
4
  import type { OwnedInstanceInfo } from '../../lib/admin-instance'
@@ -1,11 +1,9 @@
1
- import { defineDomain } from '@astrale-os/sdk'
2
- import { issuer } from '@astrale-os/sdk/auth'
3
- import { createDeployment } from '@astrale-os/sdk/deployment'
4
- import { defineSchema } from '@astrale-os/sdk/schema/v1'
1
+ import { defineSchema, schema as schemaApi } from '@astrale-os/sdk/schema'
5
2
  import { afterAll, describe, expect, test } from 'bun:test'
6
3
 
7
4
  import type { DomainInfo } from '../../lib/admin-domain'
8
5
 
6
+ import { releaseFor } from '../../__tests__/fixtures/publication'
9
7
  import { byDefaultThenName, domainProjection, probe, type DomainRow } from '../domain/list'
10
8
 
11
9
  const strip = (s: string): string => s.replace(/\[[0-9;]*m/g, '')
@@ -85,16 +83,7 @@ describe('domain list — canonical Publication check', () => {
85
83
 
86
84
  test('reports the admitted schema revision in machine data', async () => {
87
85
  const schema = defineSchema('catalog-check.example.dev', {})
88
- const definition = defineDomain({
89
- schema,
90
- handlers: { functions: {}, classes: {}, interfaces: {} },
91
- })
92
- const deployed = createDeployment({
93
- definition,
94
- issuer: issuer.accept('https://catalog-check.example.dev'),
95
- bundleHref: 'https://catalog-check.example.dev/domain.bundle.json',
96
- bindings: { callables: [] },
97
- }).publication
86
+ const deployed = releaseFor(schema, 'https://catalog-check.example.dev').publication
98
87
  const server = Bun.serve({
99
88
  port: 0,
100
89
  fetch(request) {
@@ -114,23 +103,14 @@ describe('domain list — canonical Publication check', () => {
114
103
  ),
115
104
  ).resolves.toMatchObject({
116
105
  reachable: true,
117
- schemaRevision: definition.domain.$.revision,
106
+ schemaRevision: schemaApi.revision(schema),
118
107
  checkError: null,
119
108
  })
120
109
  })
121
110
 
122
111
  test('rejects a Publication whose origin differs from the catalog entry', async () => {
123
112
  const schema = defineSchema('deployed.example.dev', {})
124
- const definition = defineDomain({
125
- schema,
126
- handlers: { functions: {}, classes: {}, interfaces: {} },
127
- })
128
- const deployed = createDeployment({
129
- definition,
130
- issuer: issuer.accept('https://deployed.example.dev'),
131
- bundleHref: 'https://deployed.example.dev/domain.bundle.json',
132
- bindings: { callables: [] },
133
- }).publication
113
+ const deployed = releaseFor(schema, 'https://deployed.example.dev').publication
134
114
  const server = Bun.serve({
135
115
  port: 0,
136
116
  fetch: () => Response.json(deployed),
@@ -1,21 +1,128 @@
1
+ import type { InstallResult } from '@astrale-os/sdk/client/schema'
2
+
3
+ import { defineSchema, schema } from '@astrale-os/sdk/schema'
1
4
  import { describe, expect, test } from 'bun:test'
2
5
 
3
- import { directInstallCallInput } from '../domain/install'
6
+ import { directInstallCallInput, directInstallPresentation } from '../domain/install'
7
+
8
+ const currentRevision = schema.revision(defineSchema('tasks.astrale.ai', {}))
4
9
 
5
10
  describe('directInstallCallInput', () => {
6
11
  test('sends the current remote install syscall, not a legacy url list', () => {
7
12
  const operation = '4a4c9a18-50f6-4d84-a7b7-2d83e3e45dc8'
8
- expect(directInstallCallInput('https://tasks.example.test', operation, 'secret')).toEqual({
9
- operation,
13
+ const input = directInstallCallInput('https://tasks.example.test', operation, 'secret')
14
+
15
+ expect(String(input.operation)).toBe(operation)
16
+ expect(input.domains).toEqual([
17
+ {
18
+ publication: {
19
+ url: 'https://tasks.example.test',
20
+ token: 'secret',
21
+ },
22
+ },
23
+ ])
24
+ })
25
+
26
+ test('presents a committed install from its receipt', () => {
27
+ const operation = directInstallCallInput(
28
+ 'https://tasks.example.test',
29
+ '4a4c9a18-50f6-4d84-a7b7-2d83e3e45dc8',
30
+ ).operation
31
+ const result = {
32
+ changed: true,
33
+ receipt: {
34
+ operation,
35
+ transitions: [
36
+ {
37
+ intent: {
38
+ transition: 'transition-1',
39
+ operation,
40
+ origin: 'tasks.astrale.ai',
41
+ previous: null,
42
+ generation: {
43
+ origin: 'tasks.astrale.ai',
44
+ revision: currentRevision,
45
+ generation: 'sha256:generation',
46
+ },
47
+ },
48
+ phase: 'cutover',
49
+ state: 'committed',
50
+ },
51
+ ],
52
+ },
53
+ } satisfies InstallResult
54
+
55
+ expect(directInstallPresentation(result, 'ignored')).toEqual({
56
+ operation: '4a4c9a18-50f6-4d84-a7b7-2d83e3e45dc8',
57
+ origin: 'tasks.astrale.ai',
58
+ revision: currentRevision,
59
+ status: 'installed',
60
+ })
61
+ })
62
+
63
+ test('presents an idempotent install from the current Domain observation', () => {
64
+ const operation = '4a4c9a18-50f6-4d84-a7b7-2d83e3e45dc8'
65
+ const result = {
66
+ changed: false,
10
67
  domains: [
11
68
  {
12
- source: {
13
- kind: 'remote',
14
- url: 'https://tasks.example.test',
15
- token: 'secret',
16
- },
69
+ origin: 'tasks.astrale.ai',
70
+ revision: currentRevision,
71
+ generation: 'sha256:generation',
72
+ publication: null,
73
+ readiness: 'sha256:readiness',
74
+ capabilities: { requested: {}, materialized: {} },
75
+ bindings: { callables: [], views: [] },
17
76
  },
18
77
  ],
78
+ } satisfies InstallResult
79
+
80
+ expect(directInstallPresentation(result, operation)).toEqual({
81
+ operation,
82
+ origin: 'tasks.astrale.ai',
83
+ revision: currentRevision,
84
+ status: 'already current',
19
85
  })
20
86
  })
87
+
88
+ test('rejects a changed result without a committed transition', () => {
89
+ const result = {
90
+ changed: true,
91
+ receipt: { operation: '4a4c9a18-50f6-4d84-a7b7-2d83e3e45dc8', transitions: [] },
92
+ } as unknown as InstallResult
93
+
94
+ expect(() => directInstallPresentation(result, 'ignored')).toThrow(
95
+ 'Kernel install returned no committed Domain transition.',
96
+ )
97
+ })
98
+
99
+ test('rejects a committed transition without an installed generation', () => {
100
+ const operation = directInstallCallInput(
101
+ 'https://tasks.example.test',
102
+ '4a4c9a18-50f6-4d84-a7b7-2d83e3e45dc8',
103
+ ).operation
104
+ const result = {
105
+ changed: true,
106
+ receipt: {
107
+ operation,
108
+ transitions: [
109
+ {
110
+ intent: {
111
+ transition: 'transition-1',
112
+ operation,
113
+ origin: 'tasks.astrale.ai',
114
+ previous: null,
115
+ generation: null,
116
+ },
117
+ phase: 'cutover',
118
+ state: 'committed',
119
+ },
120
+ ],
121
+ },
122
+ } satisfies InstallResult
123
+
124
+ expect(() => directInstallPresentation(result, 'ignored')).toThrow(
125
+ 'Kernel install returned a committed transition without a Domain generation.',
126
+ )
127
+ })
21
128
  })
@@ -1,9 +1,7 @@
1
- import { defineDomain } from '@astrale-os/sdk'
2
- import { issuer } from '@astrale-os/sdk/auth'
3
- import { createDeployment } from '@astrale-os/sdk/deployment'
4
- import { defineSchema } from '@astrale-os/sdk/schema/v1'
1
+ import { defineSchema } from '@astrale-os/sdk/schema'
5
2
  import { afterAll, describe, expect, test } from 'bun:test'
6
3
 
4
+ import { releaseFor } from '../../__tests__/fixtures/publication'
7
5
  import { domainRefFromTarget, isIdentityOverride, probeDeclaredOrigin } from '../domain/install'
8
6
 
9
7
  describe('admin-path target classification', () => {
@@ -47,16 +45,7 @@ describe('declared-origin Publication probe', () => {
47
45
 
48
46
  test('reads origin from a well-formed canonical Publication', async () => {
49
47
  const schema = defineSchema('crm.acme.dev', {})
50
- const definition = defineDomain({
51
- schema,
52
- handlers: { functions: {}, classes: {}, interfaces: {} },
53
- })
54
- const deployed = createDeployment({
55
- definition,
56
- issuer: issuer.accept('https://crm.acme.dev'),
57
- bundleHref: 'https://crm.acme.dev/domain.bundle.json',
58
- bindings: { callables: [] },
59
- }).publication
48
+ const deployed = releaseFor(schema, 'https://crm.acme.dev').publication
60
49
  const url = servePublication((req) =>
61
50
  new URL(req.url).pathname === '/.well-known/astrale/domain.json'
62
51
  ? Response.json(deployed)
@@ -65,11 +54,11 @@ describe('declared-origin Publication probe', () => {
65
54
  expect(await probeDeclaredOrigin(url)).toBe('crm.acme.dev')
66
55
  })
67
56
 
68
- test('does not accept the removed pre-Kernel-V2 domainName shape', async () => {
69
- const legacy = servePublication(() =>
57
+ test('does not accept a Publication without the canonical origin field', async () => {
58
+ const invalid = servePublication(() =>
70
59
  Response.json({ iss: 'https://x', domainName: 'crm.acme.dev' }),
71
60
  )
72
- expect(await probeDeclaredOrigin(legacy)).toBeUndefined()
61
+ expect(await probeDeclaredOrigin(invalid)).toBeUndefined()
73
62
  })
74
63
 
75
64
  test('degrades to undefined on invalid Publication, non-200, bad JSON, or dead host', async () => {
@@ -5,7 +5,7 @@ import type { InstanceInfo } from '../../lib/admin-instance'
5
5
  import { buildInstanceRows, type Bookmark } from '../instance/list'
6
6
 
7
7
  const managed: InstanceInfo[] = [
8
- { id: 'demo', slug: 'demo', url: 'https://demo.eu.astrale.ai', region: 'eu' },
8
+ { id: 'demo', slug: 'demo', url: 'https://demo.eu.astrale.ai', state: 'ready' },
9
9
  ]
10
10
 
11
11
  function bookmark(overrides: Partial<Bookmark> = {}): Bookmark {