@astrale-os/cli 1.0.0-beta.0 → 1.0.0-beta.10

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 (322) hide show
  1. package/README.md +23 -12
  2. package/dist/astrale.js +51494 -56307
  3. package/dist/public/connect-core.js +2028 -26846
  4. package/dist/public/keys/index.js +1755 -40694
  5. package/dist/public/paths/index.js +859 -39518
  6. package/dist/types/admin/binding.d.ts +19 -0
  7. package/dist/types/admin/instance/client.d.ts +22 -0
  8. package/dist/types/admin/instance/index.d.ts +2 -0
  9. package/dist/types/admin/instance/model.d.ts +5 -12
  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 +6 -2
  28. package/dist/types/lib/failure-debug.d.ts +1 -0
  29. package/dist/types/lib/idp.d.ts +7 -0
  30. package/dist/types/lib/instance-target.d.ts +1 -1
  31. package/dist/types/lib/instance.d.ts +10 -2
  32. package/dist/types/lib/log.d.ts +5 -3
  33. package/dist/types/lib/meta.d.ts +2 -2
  34. package/dist/types/lib/proc.d.ts +43 -0
  35. package/dist/types/lib/self.d.ts +9 -0
  36. package/dist/types/lib/update.d.ts +131 -0
  37. package/package.json +8 -10
  38. package/src/__tests__/fixtures/publication.ts +20 -0
  39. package/src/admin/__tests__/binding.test.ts +31 -0
  40. package/src/admin/__tests__/fixture.ts +101 -0
  41. package/src/admin/binding.ts +98 -0
  42. package/src/admin/catalog/.spec/api.d.ts +2 -2
  43. package/src/admin/catalog/__tests__/client.test.ts +20 -49
  44. package/src/admin/catalog/client.ts +36 -32
  45. package/src/admin/catalog/model.ts +3 -4
  46. package/src/admin/graph/.spec/api.d.ts +4 -10
  47. package/src/admin/graph/nodes.ts +1 -1
  48. package/src/admin/instance/.spec/api.d.ts +2 -2
  49. package/src/admin/instance/__tests__/client.test.ts +40 -163
  50. package/src/admin/instance/client.ts +35 -137
  51. package/src/admin/instance/index.ts +1 -2
  52. package/src/admin/instance/model.ts +11 -20
  53. package/src/commands/__tests__/admin-instance.test.ts +11 -8
  54. package/src/commands/__tests__/auth-login.test.ts +54 -1
  55. package/src/commands/__tests__/call-describe.test.ts +46 -33
  56. package/src/commands/__tests__/call.test.ts +5 -1
  57. package/src/commands/__tests__/domain-install-operation.test.ts +12 -7
  58. package/src/commands/__tests__/domain-install-owned.test.ts +6 -2
  59. package/src/commands/__tests__/domain-list.test.ts +63 -4
  60. package/src/commands/__tests__/install-identity-override.test.ts +19 -19
  61. package/src/commands/__tests__/instance-list-rows.test.ts +1 -1
  62. package/src/commands/__tests__/instance-status.test.ts +139 -0
  63. package/src/commands/__tests__/read-commands.test.ts +35 -10
  64. package/src/commands/__tests__/studio-descriptor.test.ts +22 -0
  65. package/src/commands/__tests__/update.test.ts +95 -0
  66. package/src/commands/call-describe.ts +60 -68
  67. package/src/commands/call.ts +43 -56
  68. package/src/commands/domain/install.ts +13 -17
  69. package/src/commands/domain/list.ts +18 -13
  70. package/src/commands/domain/publish.ts +14 -11
  71. package/src/commands/domain/uninstall.ts +2 -2
  72. package/src/commands/get.ts +14 -15
  73. package/src/commands/identity/__tests__/register.test.ts +3 -3
  74. package/src/commands/identity/register.ts +5 -4
  75. package/src/commands/instance/create.ts +8 -16
  76. package/src/commands/instance/delete.ts +12 -9
  77. package/src/commands/instance/list.ts +2 -2
  78. package/src/commands/instance/status.ts +66 -20
  79. package/src/commands/instance/use.ts +16 -12
  80. package/src/commands/introspect.ts +9 -16
  81. package/src/commands/logs.ts +24 -25
  82. package/src/commands/mutate.ts +6 -5
  83. package/src/commands/query.ts +27 -30
  84. package/src/commands/studio.ts +20 -0
  85. package/src/commands/token.ts +8 -7
  86. package/src/commands/update.ts +68 -22
  87. package/src/commands/view.ts +7 -6
  88. package/src/connection/.spec/api.d.ts +7 -8
  89. package/src/connection/.spec/architecture.md +5 -4
  90. package/src/connection/.spec/flows/session.ts +2 -2
  91. package/src/connection/.spec/laws/connection.ts +6 -2
  92. package/src/connection/.spec/layout.ts +1 -0
  93. package/src/connection/__tests__/credential.test.ts +20 -1
  94. package/src/connection/__tests__/errors.test.ts +43 -32
  95. package/src/connection/__tests__/exchange.test.ts +36 -6
  96. package/src/connection/__tests__/failure-fixtures.ts +39 -0
  97. package/src/connection/__tests__/failure-safety.test.ts +75 -0
  98. package/src/connection/__tests__/self.test.ts +31 -11
  99. package/src/connection/__tests__/session.test.ts +3 -3
  100. package/src/connection/__tests__/target.test.ts +1 -0
  101. package/src/connection/auth.ts +13 -0
  102. package/src/connection/call.ts +1 -1
  103. package/src/connection/credential.ts +2 -2
  104. package/src/connection/errors.ts +1 -355
  105. package/src/connection/exchange.ts +52 -27
  106. package/src/connection/failure/classify.ts +110 -0
  107. package/src/connection/failure/index.ts +18 -0
  108. package/src/connection/failure/model.ts +28 -0
  109. package/src/connection/failure/render.ts +116 -0
  110. package/src/connection/reasons.ts +16 -0
  111. package/src/connection/self.ts +39 -21
  112. package/src/connection/session.ts +19 -8
  113. package/src/errors.ts +3 -2
  114. package/src/graph/.spec/api.d.ts +12 -5
  115. package/src/graph/.spec/layout.ts +9 -1
  116. package/src/graph/__tests__/mutation.test.ts +2 -2
  117. package/src/graph/__tests__/query.test.ts +25 -6
  118. package/src/graph/class.ts +30 -0
  119. package/src/graph/index.ts +1 -0
  120. package/src/graph/query.ts +21 -32
  121. package/src/identity/.spec/api.d.ts +2 -2
  122. package/src/identity/__tests__/registration.test.ts +1 -1
  123. package/src/identity/registration.ts +3 -3
  124. package/src/keys/__tests__/keys.test.ts +4 -0
  125. package/src/keys/credential.ts +1 -0
  126. package/src/lib/__tests__/admin-target.test.ts +12 -0
  127. package/src/lib/__tests__/command-dx.test.ts +1 -1
  128. package/src/lib/__tests__/domain-publication.test.ts +138 -0
  129. package/src/lib/__tests__/idp-session.test.ts +22 -0
  130. package/src/lib/__tests__/idp.test.ts +36 -4
  131. package/src/lib/__tests__/instance-candidates.test.ts +1 -3
  132. package/src/lib/__tests__/instance-target.test.ts +7 -39
  133. package/src/lib/__tests__/instance.test.ts +6 -0
  134. package/src/lib/__tests__/log-errors.test.ts +64 -0
  135. package/src/lib/__tests__/studio-server-deps.test.ts +53 -16
  136. package/src/lib/__tests__/update.test.ts +113 -8
  137. package/src/lib/__tests__/view-open-intent.test.ts +0 -2
  138. package/src/lib/__tests__/view-server.test.ts +1 -1
  139. package/src/lib/__tests__/view-session.test.ts +1 -1
  140. package/src/lib/admin-instance.ts +14 -8
  141. package/src/lib/admin-target.ts +21 -2
  142. package/src/lib/command-dx.ts +9 -9
  143. package/src/lib/domain-publication.ts +104 -0
  144. package/src/lib/failure-debug.ts +26 -0
  145. package/src/lib/idp.ts +39 -4
  146. package/src/lib/instance-candidates.ts +2 -2
  147. package/src/lib/instance-target.ts +3 -14
  148. package/src/lib/instance.ts +22 -12
  149. package/src/lib/log.ts +16 -9
  150. package/src/lib/login-flow.ts +13 -3
  151. package/src/lib/meta.ts +2 -2
  152. package/src/lib/provision-instance.ts +34 -57
  153. package/src/lib/update.ts +124 -30
  154. package/src/lib/validation.ts +2 -2
  155. package/src/lib/view/resolve.ts +1 -1
  156. package/src/program/__tests__/program.test.ts +20 -4
  157. package/src/program/build.ts +2 -2
  158. package/src/setup/__tests__/instance-step.test.ts +27 -10
  159. package/src/setup/steps/instance.ts +22 -15
  160. package/studio/client/dist/assets/{elk-api-D2xgMJvi.js → elk-api-ByzoDZWH.js} +1 -1
  161. package/studio/client/dist/assets/index-B0RCgUOT.js +8 -0
  162. package/studio/client/dist/assets/index-BiGR8Oo9.css +1 -0
  163. package/studio/client/dist/assets/index-N8J8EKlB.js +81 -0
  164. package/studio/client/dist/index.html +2 -2
  165. package/studio/package.json +5 -10
  166. package/studio/server/agent/ask.test.ts +1 -1
  167. package/studio/server/agent/bridge/grant.test.ts +1 -1
  168. package/studio/server/agent/bridge/routes.test.ts +1 -1
  169. package/studio/server/agent/bridge/stdio.ts +8 -1
  170. package/studio/server/agent/conversation.test.ts +10 -5
  171. package/studio/server/agent/conversation.ts +56 -8
  172. package/studio/server/agent/harness/claude/adapter.test.ts +15 -5
  173. package/studio/server/agent/harness/codex/loadout.ts +18 -21
  174. package/studio/server/agent/harness/gateway/config.ts +20 -18
  175. package/studio/server/agent/harness/selection.ts +9 -1
  176. package/studio/server/agent/prompts/anchors.test.ts +32 -36
  177. package/studio/server/agent/prompts/anchors.ts +20 -49
  178. package/studio/server/agent/prompts/system.test.ts +3 -2
  179. package/studio/server/agent/prompts/system.ts +6 -5
  180. package/studio/server/agent/prompts/turn.ts +13 -4
  181. package/studio/server/agent/routes.test.ts +1 -1
  182. package/studio/server/agent/run/completion.ts +2 -2
  183. package/studio/server/agent/run/coordinator.test.ts +1 -1
  184. package/studio/server/agent/run/preparation.ts +6 -5
  185. package/studio/server/agent/run/transcript.test.ts +35 -1
  186. package/studio/server/agent/run/transcript.ts +169 -3
  187. package/studio/server/agent/run/usage.test.ts +24 -0
  188. package/studio/server/agent/run/usage.ts +26 -1
  189. package/studio/server/api/canvas.ts +43 -0
  190. package/studio/server/api/comments.ts +85 -0
  191. package/studio/server/api/context.ts +61 -0
  192. package/studio/server/api/deployment.ts +39 -0
  193. package/studio/server/api/documents.ts +55 -0
  194. package/studio/server/api/domain.ts +59 -0
  195. package/studio/server/api/http.ts +45 -0
  196. package/studio/server/api/project.ts +57 -0
  197. package/studio/server/api/schema.ts +12 -0
  198. package/studio/server/api/views.ts +57 -0
  199. package/studio/server/api/workspace.ts +60 -0
  200. package/studio/server/api-agent-loadout.test.ts +1 -1
  201. package/studio/server/api.test.ts +147 -0
  202. package/studio/server/api.ts +20 -422
  203. package/studio/server/cache.test.ts +122 -0
  204. package/studio/server/cache.ts +162 -11
  205. package/studio/server/cli-consumers.test.ts +494 -0
  206. package/studio/server/cli.test.ts +88 -0
  207. package/studio/server/cli.ts +240 -0
  208. package/studio/server/client-package.ts +25 -1
  209. package/studio/server/domain.test.ts +50 -40
  210. package/studio/server/domain.ts +83 -52
  211. package/studio/server/environment/dotenv-preview.test.ts +39 -0
  212. package/studio/server/environment/dotenv-preview.ts +27 -0
  213. package/studio/server/environment/files.test.ts +53 -0
  214. package/studio/server/{state/env.ts → environment/files.ts} +7 -48
  215. package/studio/server/{state → handoff}/copy.ts +21 -6
  216. package/studio/server/handoff/service.test.ts +22 -0
  217. package/studio/server/{state/handoff.ts → handoff/service.ts} +21 -14
  218. package/studio/server/index.ts +1 -1
  219. package/studio/server/instances/active.ts +72 -0
  220. package/studio/server/instances/deploy-record.test.ts +31 -0
  221. package/studio/server/instances/deploy-record.ts +37 -0
  222. package/studio/server/instances/deploy.ts +56 -0
  223. package/studio/server/{state/instance.test.ts → instances/probe.test.ts} +25 -21
  224. package/studio/server/instances/probe.ts +67 -0
  225. package/studio/server/instances/status.test.ts +12 -0
  226. package/studio/server/instances/status.ts +49 -0
  227. package/studio/server/introspect/anatomy/client-tree.ts +57 -0
  228. package/studio/server/introspect/anatomy/env-fields.ts +66 -0
  229. package/studio/server/introspect/anatomy/schema-definition.ts +53 -0
  230. package/studio/server/introspect/anatomy/source.ts +181 -0
  231. package/studio/server/introspect/anatomy/views/routes.ts +114 -0
  232. package/studio/server/introspect/anatomy/views.ts +53 -0
  233. package/studio/server/introspect/anatomy-extras.test.ts +106 -35
  234. package/studio/server/introspect/anatomy-extras.ts +7 -726
  235. package/studio/server/introspect/anatomy.test.ts +22 -14
  236. package/studio/server/introspect/anatomy.ts +52 -28
  237. package/studio/server/introspect/bundle.ts +15 -9
  238. package/studio/server/introspect/canonical-schema.test.ts +93 -309
  239. package/studio/server/introspect/canonical-schema.ts +257 -425
  240. package/studio/server/introspect/config-preview.test.ts +32 -0
  241. package/studio/server/introspect/config-preview.ts +119 -0
  242. package/studio/server/introspect/core-extractor.ts +18 -127
  243. package/studio/server/introspect/core.ts +1 -2
  244. package/studio/server/introspect/diff.test.ts +18 -18
  245. package/studio/server/introspect/diff.ts +44 -90
  246. package/studio/server/introspect/extractor.ts +23 -116
  247. package/studio/server/introspect/hash.ts +5 -2
  248. package/studio/server/introspect/overlay-tsmorph.test.ts +119 -240
  249. package/studio/server/introspect/overlay-tsmorph.ts +7 -1305
  250. package/studio/server/introspect/overlay.test.ts +26 -54
  251. package/studio/server/introspect/overlay.ts +10 -37
  252. package/studio/server/introspect/revision.test.ts +54 -0
  253. package/studio/server/introspect/revision.ts +49 -0
  254. package/studio/server/introspect/runtime.test.ts +83 -143
  255. package/studio/server/introspect/runtime.ts +40 -11
  256. package/studio/server/introspect/schema-ir-json.test.ts +70 -0
  257. package/studio/server/introspect/schema-ir-json.ts +151 -0
  258. package/studio/server/introspect/schema-refs.test.ts +43 -88
  259. package/studio/server/introspect/schema-refs.ts +14 -49
  260. package/studio/server/introspect/source-overlay/annotations.ts +14 -0
  261. package/studio/server/introspect/source-overlay/handlers.ts +161 -0
  262. package/studio/server/introspect/source-overlay/kernel-calls.ts +46 -0
  263. package/studio/server/introspect/source-overlay/project.ts +248 -0
  264. package/studio/server/introspect/source-overlay/spans.ts +330 -0
  265. package/studio/server/json.ts +46 -0
  266. package/studio/server/lifecycle.ts +5 -1
  267. package/studio/server/sse.test.ts +26 -0
  268. package/studio/server/sse.ts +4 -1
  269. package/studio/server/state/baseline.test.ts +223 -7
  270. package/studio/server/state/baseline.ts +148 -34
  271. package/studio/server/state/comments.test.ts +66 -1
  272. package/studio/server/state/comments.ts +173 -10
  273. package/studio/server/state/context.ts +34 -2
  274. package/studio/server/state/documents.ts +42 -1
  275. package/studio/server/state/integrations.ts +27 -1
  276. package/studio/server/state/layout.test.ts +34 -0
  277. package/studio/server/state/layout.ts +44 -17
  278. package/studio/server/state/settings.ts +29 -22
  279. package/studio/server/state/store.test.ts +122 -0
  280. package/studio/server/state/store.ts +66 -17
  281. package/studio/server/state/visibility.ts +22 -11
  282. package/studio/server/views/model.test.ts +57 -0
  283. package/studio/server/views/model.ts +66 -0
  284. package/studio/server/views/runtime.ts +40 -0
  285. package/studio/server/views/selection-repository.test.ts +31 -0
  286. package/studio/server/views/selection-repository.ts +60 -0
  287. package/studio/server/views/session.test.ts +73 -0
  288. package/studio/server/views/session.ts +166 -0
  289. package/studio/server/views/target.test.ts +78 -0
  290. package/studio/server/views/target.ts +222 -0
  291. package/studio/server/watch.test.ts +11 -11
  292. package/studio/server/watch.ts +9 -5
  293. package/studio/server/workspace/catalog.test.ts +17 -0
  294. package/studio/server/workspace/catalog.ts +43 -0
  295. package/studio/server/{state → workspace}/create.test.ts +1 -1
  296. package/studio/server/{state → workspace}/create.ts +1 -1
  297. package/studio/server/{state → workspace}/git.ts +1 -1
  298. package/studio/server/workspace/updates.ts +83 -0
  299. package/studio/server/workspace-state.ts +1 -1
  300. package/studio/server/workspace-watch.ts +2 -2
  301. package/studio/shared/contracts/README.md +16 -0
  302. package/studio/shared/contracts/agent.ts +270 -0
  303. package/studio/shared/contracts/runtime.ts +50 -0
  304. package/studio/shared/contracts/schema.ts +393 -0
  305. package/studio/shared/contracts/surface.test.ts +317 -0
  306. package/studio/shared/contracts/workspace.ts +265 -0
  307. package/studio/shared/layout.test.ts +116 -0
  308. package/studio/shared/schema/identity.test.ts +34 -0
  309. package/studio/shared/schema/identity.ts +68 -0
  310. package/studio/shared/types.ts +11 -1099
  311. package/studio/tsconfig.json +1 -1
  312. package/viewer/dist/main.js +40 -61
  313. package/.check-workspace.cjs +0 -40
  314. package/src/commands/__tests__/instance-create-hosts.test.ts +0 -29
  315. package/studio/client/dist/assets/index-BMdnsIJA.css +0 -1
  316. package/studio/client/dist/assets/index-D-vRV8w7.js +0 -8
  317. package/studio/client/dist/assets/index-LGSWRrk8.js +0 -81
  318. package/studio/server/state/catalog.ts +0 -117
  319. package/studio/server/state/instance.ts +0 -280
  320. package/studio/server/state/updates.ts +0 -63
  321. package/studio/server/state/views.test.ts +0 -286
  322. package/studio/server/state/views.ts +0 -535
@@ -1,14 +1,16 @@
1
- import type { DomainBinding } from '@astrale-os/kernel-client/domain'
2
- import type { ClientSession } from '@astrale-os/kernel-client/session'
3
- import type { Node } from '@astrale-os/sdk/graph/node'
1
+ import type { ClientSession } from '@astrale-os/sdk/client/session'
4
2
 
5
- import { bind } from '@astrale-os/kernel-client/domain'
6
3
  import { Path } from '@astrale-os/sdk/graph/path'
7
- import { Query } from '@astrale-os/sdk/query'
8
4
 
9
- import { readAllNodes, type AdminGraphApi } from '../graph'
10
5
  import {
11
- AdminHostNotFoundError,
6
+ bindAdmin,
7
+ invokeAdminMethod,
8
+ requireAdminBinding,
9
+ requireAdminClass,
10
+ requireAdminCore,
11
+ type AdminBinding,
12
+ } from '../binding'
13
+ import {
12
14
  AdminInstanceNotFoundError,
13
15
  findOwnedInstance,
14
16
  type DomainInstallReceipt,
@@ -17,33 +19,20 @@ import {
17
19
  type OwnedInstanceInfo,
18
20
  } from './model'
19
21
 
20
- const ADMIN_ORIGIN = 'admin.astrale.ai'
21
- const PAGE_SIZE = 256
22
- const MAXIMUM_INSTANCES = 10_000
23
- const MAXIMUM_PAGES = Math.ceil(MAXIMUM_INSTANCES / PAGE_SIZE) + 1
24
-
25
- const HostRef = Object.freeze({ origin: ADMIN_ORIGIN, kind: 'class' as const, name: 'Host' })
26
- const fleetReservesAdminHost = Object.freeze({
27
- origin: ADMIN_ORIGIN,
28
- kind: 'class' as const,
29
- name: 'fleet_reserves_admin_host',
30
- })
31
-
32
22
  export interface AdminInstanceContext {
33
23
  readonly session: ClientSession
34
- readonly graph: AdminGraphApi
35
24
  }
36
25
 
37
26
  export interface AdminInstanceApi {
38
27
  list(): Promise<OwnedInstanceInfo[]>
39
- create(slug: string, hostId?: string): Promise<InstanceInfo>
28
+ create(slug: string): Promise<InstanceInfo>
40
29
  status(identifier: string): Promise<InstanceInfo>
41
30
  delete(identifier: string): Promise<InstanceInfo>
42
31
  installDomain(identifier: string, domain: string): Promise<DomainInstallReceipt>
43
32
  }
44
33
 
45
34
  export interface AdminInstanceDependencies {
46
- readonly bind?: (session: ClientSession) => Promise<DomainBinding>
35
+ readonly bind?: (session: ClientSession) => Promise<AdminBinding>
47
36
  readonly operationId?: (kind: 'create' | 'status' | 'delete' | 'install-domain') => string
48
37
  }
49
38
 
@@ -55,24 +44,22 @@ export async function connectAdminInstances(
55
44
  context: AdminInstanceContext,
56
45
  dependencies: AdminInstanceDependencies = {},
57
46
  ): Promise<AdminInstanceApi> {
58
- const binding = await (dependencies.bind ?? bindInstalledAdmin)(context.session)
59
- if (binding.$.publication?.origin !== ADMIN_ORIGIN || binding.$.origin !== ADMIN_ORIGIN) {
60
- throw new TypeError('Configured Admin target does not serve the Admin Domain.')
61
- }
47
+ const binding = requireAdminBinding(await (dependencies.bind ?? bindAdmin)(context.session))
62
48
 
63
- const Instance = binding.$.class('Instance')
64
- const Host = binding.$.class('Host')
65
- const Fleet = binding.$.class('Fleet')
66
- const fleet = binding.$.core.nodes.fleet?.path
67
- if (fleet === undefined) throw new TypeError('Admin Domain has no singleton Fleet receiver.')
49
+ const Instance = requireAdminClass(binding, 'Instance', 'node')
50
+ const Fleet = requireAdminClass(binding, 'Fleet', 'node')
51
+ const fleet = requireAdminCore(binding, 'fleet')
68
52
 
69
53
  const operationId = dependencies.operationId ?? defaultOperationId
70
54
 
71
55
  const list = async (): Promise<OwnedInstanceInfo[]> => {
72
- const result: unknown = await binding.$.invoke(
73
- Fleet.$.method('listInstances') as never,
56
+ const result: unknown = await invokeAdminMethod(
57
+ context.session,
58
+ binding,
59
+ Fleet,
60
+ 'listInstances',
74
61
  fleet,
75
- {} as never,
62
+ {},
76
63
  )
77
64
  if (!Array.isArray(result)) throw new TypeError('Admin Instance inventory is invalid.')
78
65
  return result.map((value) => instanceFromSummary(value) as OwnedInstanceInfo)
@@ -89,126 +76,48 @@ export async function connectAdminInstances(
89
76
  identifier: string,
90
77
  ): Promise<InstanceInfo> => {
91
78
  const instance = await requireInstance(identifier)
92
- const output = await binding.$.invoke(
93
- Instance.$.method(method) as never,
79
+ const output = await invokeAdminMethod(
80
+ context.session,
81
+ binding,
82
+ Instance,
83
+ method,
94
84
  Path.parse(instance.id),
95
- { operationId: operationId(method) } as never,
85
+ { operationId: operationId(method) },
96
86
  )
97
87
  return instanceFromSummary(output)
98
88
  }
99
89
 
100
90
  return Object.freeze({
101
91
  list,
102
- async create(slug: string, hostId?: string) {
92
+ async create(slug: string) {
103
93
  const input = Object.freeze({
104
94
  operationId: operationId('create'),
105
95
  slug,
106
96
  })
107
- if (hostId !== undefined) {
108
- const selected = await hostInventory(context.graph, binding, Host, fleet)
109
- const host = selected.hosts.find(
110
- (item) => item.id === hostId && item.state === 'ready' && item.path !== selected.reserved,
111
- )
112
- if (host === undefined) throw new AdminHostNotFoundError(hostId)
113
- return instanceFromSummary(
114
- await binding.$.invoke(
115
- Host.$.method('createInstance') as never,
116
- Path.parse(host.path),
117
- input as never,
118
- ),
119
- )
120
- }
121
-
122
- // Preserve the existing interactive multi-Host picker without accepting a
123
- // doomed operation first. Graph read policy exposes only caller-usable
124
- // Hosts; the reserved Admin Host is excluded explicitly.
125
- const inventory = await hostInventory(context.graph, binding, Host, fleet)
126
- const eligible = inventory.hosts.filter(
127
- (host) => host.state === 'ready' && host.path !== inventory.reserved,
128
- )
129
- if (eligible.length > 1) throw hostSelectionRequired(eligible.map((host) => host.id))
130
-
131
97
  return instanceFromSummary(
132
- await binding.$.invoke(Fleet.$.method('createInstance') as never, fleet, input as never),
98
+ await invokeAdminMethod(context.session, binding, Fleet, 'createInstance', fleet, input),
133
99
  )
134
100
  },
135
101
  status: (identifier: string) => invokeInstance('status', identifier),
136
102
  delete: (identifier: string) => invokeInstance('delete', identifier),
137
103
  async installDomain(identifier: string, domain: string): Promise<DomainInstallReceipt> {
138
104
  const instance = await requireInstance(identifier)
139
- const output = await binding.$.invoke(
140
- Instance.$.method('installDomain') as never,
105
+ const output = await invokeAdminMethod(
106
+ context.session,
107
+ binding,
108
+ Instance,
109
+ 'installDomain',
141
110
  Path.parse(instance.id),
142
111
  {
143
112
  operationId: operationId('install-domain'),
144
113
  domain: Path.parse(domain).raw,
145
- } as never,
114
+ },
146
115
  )
147
116
  return domainInstallReceipt(output)
148
117
  },
149
118
  })
150
119
  }
151
120
 
152
- async function bindInstalledAdmin(session: ClientSession): Promise<DomainBinding> {
153
- return bind(session, await session.installed(ADMIN_ORIGIN))
154
- }
155
-
156
- interface HostInventoryItem {
157
- readonly id: string
158
- readonly nodeId: string
159
- readonly path: string
160
- readonly state: string
161
- }
162
-
163
- async function hostInventory(
164
- graph: AdminGraphApi,
165
- binding: DomainBinding,
166
- Host: ReturnType<DomainBinding['$']['class']>,
167
- fleet: Path,
168
- ): Promise<{ readonly hosts: readonly HostInventoryItem[]; readonly reserved?: string }> {
169
- const [nodes, reservedPage] = await Promise.all([
170
- readAllNodes(
171
- graph,
172
- Query.from({ kind: 'node', definitions: [HostRef] }).select({
173
- kind: 'nodes',
174
- projection: { kind: 'value' },
175
- }),
176
- {
177
- label: 'Admin Host inventory',
178
- maximum: MAXIMUM_INSTANCES,
179
- maximumPages: MAXIMUM_PAGES,
180
- },
181
- ),
182
- graph.neighbors(fleet, fleetReservesAdminHost, {
183
- direction: 'outgoing',
184
- page: { size: 1 },
185
- }),
186
- ])
187
- const reserved = reservedPage.first === null ? undefined : Path.id(reservedPage.first.id).raw
188
- return Object.freeze({
189
- hosts: Object.freeze(
190
- nodes.map((node) =>
191
- Object.freeze({
192
- id: requiredStringProperty(Host, node, 'id'),
193
- nodeId: String(node.id),
194
- path: Path.id(node.id).raw,
195
- state: requiredStringProperty(Host, node, 'state'),
196
- }),
197
- ),
198
- ),
199
- ...(reserved === undefined ? {} : { reserved }),
200
- })
201
- }
202
-
203
- function hostSelectionRequired(ids: readonly string[]): Error {
204
- return new Error(
205
- `alphaCreate could not choose a host: ${ids.length} ready hosts are assigned (${[...ids].sort().join(', ')}). ` +
206
- 'Specify host_id once multi-host placement is enabled.',
207
- )
208
- }
209
-
210
- type DynamicDefinition = ReturnType<DomainBinding['$']['class']>
211
-
212
121
  function instanceFromSummary(input: unknown): InstanceInfo {
213
122
  const value = record(input, 'Admin Instance summary')
214
123
  const failure = value.failure === undefined ? undefined : record(value.failure, 'Admin failure')
@@ -217,10 +126,6 @@ function instanceFromSummary(input: unknown): InstanceInfo {
217
126
  slug: requiredString(value.slug, 'Admin Instance slug'),
218
127
  url: optionalStringValue(value.url) ?? '',
219
128
  state: instanceState(value.state),
220
- ...(value.hostId === undefined
221
- ? {}
222
- : { hostId: requiredString(value.hostId, 'Admin Host id') }),
223
- ...(value.region === undefined ? {} : { region: requiredString(value.region, 'Admin region') }),
224
129
  ...(value.phase === undefined
225
130
  ? {}
226
131
  : { phase: requiredString(value.phase, 'Admin Instance phase') }),
@@ -256,13 +161,6 @@ function domainInstallReceipt(input: unknown): DomainInstallReceipt {
256
161
  })
257
162
  }
258
163
 
259
- function requiredStringProperty(definition: DynamicDefinition, node: Node, name: string): string {
260
- return requiredString(
261
- node.props[definition.$.property(name).key],
262
- `Admin ${definition.name}.${name}`,
263
- )
264
- }
265
-
266
164
  function instanceState(input: unknown): InstanceState {
267
165
  if (
268
166
  input === 'provisioning' ||
@@ -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,
@@ -5,9 +5,7 @@ export interface InstanceInfo {
5
5
  readonly id: string
6
6
  readonly slug: string
7
7
  readonly url: string
8
- readonly hostId?: string
9
- readonly region?: string
10
- readonly state?: InstanceState
8
+ readonly state: InstanceState
11
9
  readonly phase?: string
12
10
  readonly error?: string | null
13
11
  readonly createdAt?: string
@@ -28,19 +26,13 @@ export interface DomainInstallReceipt {
28
26
  readonly error?: string
29
27
  }
30
28
 
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
-
29
+ export class AdminInstanceNotFoundError extends AstraleError {
42
30
  constructor(readonly identifier: string) {
43
- super(`No caller-usable Admin Host matches ${JSON.stringify(identifier)}.`)
31
+ super(
32
+ 'INSTANCE_NOT_FOUND',
33
+ `No owned Admin Instance matches ${JSON.stringify(identifier)}.`,
34
+ 'Run `astrale instance list` to see your instances.',
35
+ )
44
36
  }
45
37
  }
46
38
 
@@ -57,9 +49,8 @@ export function findOwnedInstance(
57
49
  )
58
50
  }
59
51
 
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(' · ')
52
+ /** Human-readable non-ready lifecycle state for one Instance. */
53
+ export function formatInstanceState(info: InstanceInfo): string {
54
+ return info.state === 'ready' ? '' : `${info.state}${info.phase ? ` (${info.phase})` : ''}`
65
55
  }
56
+ 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
  })
@@ -81,11 +81,56 @@ describe('auth login command', () => {
81
81
  expect(result.exitCode).toBe(0)
82
82
  const session = JSON.parse(await readFile(join(tmp, 'idp-sessions', 'alice.json'), 'utf-8'))
83
83
  expect(session.audience).toBe('https://kernel.example.com')
84
+ expect(session.clientId).toBe('client_123')
84
85
  expect(session.subject).toBe('user_123')
85
86
  } finally {
86
87
  await server.stop()
87
88
  }
88
89
  })
90
+
91
+ test('persists an explicit client id and reuses it for a named login', async () => {
92
+ const server = oauthServer({
93
+ accessToken: unsignedJwt({
94
+ iss: 'http://127.0.0.1',
95
+ sub: 'user_123',
96
+ exp: 1893456000,
97
+ }),
98
+ })
99
+ try {
100
+ await writeIdpConfig(server.url)
101
+
102
+ const explicit = await runAuthLogin(
103
+ '--idp',
104
+ 'test',
105
+ '--name',
106
+ 'alice',
107
+ '--client-id',
108
+ 'client_override',
109
+ '--client-credentials',
110
+ '--client-secret-env',
111
+ 'TEST_CLIENT_SECRET',
112
+ '--raw',
113
+ )
114
+ const reused = await runAuthLogin(
115
+ '--idp',
116
+ 'test',
117
+ '--name',
118
+ 'alice',
119
+ '--client-credentials',
120
+ '--client-secret-env',
121
+ 'TEST_CLIENT_SECRET',
122
+ '--raw',
123
+ )
124
+
125
+ expect(explicit.exitCode).toBe(0)
126
+ expect(reused.exitCode).toBe(0)
127
+ expect(server.clientIds()).toEqual(['client_override', 'client_override'])
128
+ const session = JSON.parse(await readFile(join(tmp, 'idp-sessions', 'alice.json'), 'utf-8'))
129
+ expect(session.clientId).toBe('client_override')
130
+ } finally {
131
+ await server.stop()
132
+ }
133
+ })
89
134
  })
90
135
 
91
136
  async function writeIdpConfig(baseUrl: string): Promise<void> {
@@ -131,12 +176,19 @@ async function writeIdpConfig(baseUrl: string): Promise<void> {
131
176
  )
132
177
  }
133
178
 
134
- function oauthServer(args: { accessToken: string }): { url: string; stop: () => Promise<void> } {
179
+ function oauthServer(args: { accessToken: string }): {
180
+ url: string
181
+ clientIds: () => Array<string | null>
182
+ stop: () => Promise<void>
183
+ } {
184
+ const clientIds: Array<string | null> = []
135
185
  const server = Bun.serve({
136
186
  port: 0,
137
187
  fetch: async (request) => {
138
188
  const url = new URL(request.url)
139
189
  if (url.pathname !== '/token') return new Response('not found', { status: 404 })
190
+ const form = new URLSearchParams(await request.text())
191
+ clientIds.push(form.get('client_id'))
140
192
  return Response.json({
141
193
  access_token: args.accessToken,
142
194
  token_type: 'Bearer',
@@ -146,6 +198,7 @@ function oauthServer(args: { accessToken: string }): { url: string; stop: () =>
146
198
  })
147
199
  return {
148
200
  url: `http://${server.hostname}:${server.port}`,
201
+ clientIds: () => clientIds,
149
202
  stop: () => server.stop(true),
150
203
  }
151
204
  }
@@ -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
  })
@@ -14,7 +14,11 @@ describe('call command result lifetime', () => {
14
14
  }
15
15
 
16
16
  const sessionStream = Object.assign(stream(), { async cancel() {} })
17
- const materialized = await materializeCallResult({ kind: 'stream', stream: sessionStream })
17
+ const materialized = await materializeCallResult({
18
+ kind: 'stream',
19
+ invocation: { source: 'https://kernel.test' as never, id: 'test-stream' },
20
+ stream: sessionStream,
21
+ })
18
22
  sessionOpen = false
19
23
 
20
24
  expect(materialized).toEqual({ kind: 'stream', values: ['first', 'second'] })
@@ -1,5 +1,7 @@
1
+ import { defineSchema } from '@astrale-os/sdk/schema'
1
2
  import { afterEach, describe, expect, mock, test } from 'bun:test'
2
3
 
4
+ import { releaseFor } from '../../__tests__/fixtures/publication'
3
5
  import { installDirect } from '../domain/install'
4
6
 
5
7
  const GENERATED = '4a4c9a18-50f6-4d84-a7b7-2d83e3e45dc8'
@@ -7,6 +9,13 @@ const RETRY = '139137b5-af47-47ce-92b2-b64a2b0c63d7'
7
9
 
8
10
  const originalFetch = globalThis.fetch
9
11
 
12
+ const schema = defineSchema('crm.test', {})
13
+ const deployed = releaseFor(schema, 'https://crm.test').publication
14
+
15
+ function publicationResponse(): Response {
16
+ return Response.json(deployed)
17
+ }
18
+
10
19
  class ExitError extends Error {}
11
20
 
12
21
  afterEach(() => {
@@ -15,9 +24,7 @@ afterEach(() => {
15
24
 
16
25
  describe('direct domain install operation identity', () => {
17
26
  test('generates one operation before transport and exposes it for recovery', async () => {
18
- globalThis.fetch = mock(async () =>
19
- Response.json({ domainName: 'crm.test' }),
20
- ) as unknown as typeof fetch
27
+ globalThis.fetch = mock(async () => publicationResponse()) as unknown as typeof fetch
21
28
  const create = mock(() => GENERATED)
22
29
  const requests: unknown[] = []
23
30
  let recovery: unknown
@@ -54,9 +61,7 @@ describe('direct domain install operation identity', () => {
54
61
  })
55
62
 
56
63
  test('accepts an explicit operation only as the exact retry identity', async () => {
57
- globalThis.fetch = mock(async () =>
58
- Response.json({ domainName: 'crm.test' }),
59
- ) as unknown as typeof fetch
64
+ globalThis.fetch = mock(async () => publicationResponse()) as unknown as typeof fetch
60
65
  const create = mock(() => GENERATED)
61
66
  const accepted: string[] = []
62
67
  const requests: unknown[] = []
@@ -95,7 +100,7 @@ describe('direct domain install operation identity', () => {
95
100
  test('rejects a non-UUID operation before metadata or Kernel transport', async () => {
96
101
  const originalExit = process.exit
97
102
  const originalWrite = process.stderr.write
98
- const fetch = mock(async () => Response.json({ domainName: 'crm.test' }))
103
+ const fetch = mock(async () => publicationResponse())
99
104
  const run = mock(async () => undefined)
100
105
  globalThis.fetch = fetch as unknown as typeof globalThis.fetch
101
106
  process.exit = (() => {
@@ -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'
@@ -11,6 +11,10 @@ class ExitError extends Error {
11
11
 
12
12
  const calls: Array<{ path: string; params: unknown }> = []
13
13
  let inventory: OwnedInstanceInfo[] = []
14
+ const TEST_INVOCATION = {
15
+ source: 'https://kernel.test',
16
+ id: 'domain-install-owned',
17
+ } as ConstructorParameters<typeof ResponseError>[2]
14
18
 
15
19
  const hostCall = mock(async (call: { target: string; input: unknown }): Promise<unknown> => {
16
20
  const path = call.target
@@ -137,7 +141,7 @@ describe('admin domain install owner boundary', () => {
137
141
  createdAt: '2026-08-20T00:00:00.000Z',
138
142
  updatedAt: '2026-08-20T00:00:00.000Z',
139
143
  }
140
- const failure = new ResponseError(5001, 'Schema operation is not supported.', {
144
+ const failure = new ResponseError(5001, 'Schema operation is not supported.', TEST_INVOCATION, {
141
145
  code: 'SCHEMA_UPGRADE_INCOMPATIBLE',
142
146
  details: {
143
147
  phase: 'upgrade',