@astrale-os/cli 1.0.0-beta.1 → 1.0.0-beta.11

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 (329) hide show
  1. package/README.md +23 -12
  2. package/dist/astrale.js +48048 -56798
  3. package/dist/public/connect-core.js +2011 -30765
  4. package/dist/public/keys/index.js +884 -29483
  5. package/dist/public/paths/index.js +13101 -41459
  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 +11 -36
  28. package/dist/types/lib/config.d.ts +7 -59
  29. package/dist/types/lib/failure-debug.d.ts +1 -0
  30. package/dist/types/lib/idp.d.ts +26 -168
  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/meta.d.ts +2 -2
  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 +91 -0
  38. package/dist/types/lib/validation.d.ts +4 -1
  39. package/package.json +16 -19
  40. package/src/__tests__/fixtures/publication.ts +20 -0
  41. package/src/admin/__tests__/binding.test.ts +31 -0
  42. package/src/admin/__tests__/fixture.ts +101 -0
  43. package/src/admin/binding.ts +98 -0
  44. package/src/admin/catalog/.spec/api.d.ts +2 -2
  45. package/src/admin/catalog/__tests__/client.test.ts +20 -49
  46. package/src/admin/catalog/client.ts +36 -32
  47. package/src/admin/catalog/model.ts +3 -4
  48. package/src/admin/graph/.spec/api.d.ts +4 -10
  49. package/src/admin/graph/nodes.ts +1 -1
  50. package/src/admin/instance/.spec/api.d.ts +2 -2
  51. package/src/admin/instance/__tests__/client.test.ts +39 -164
  52. package/src/admin/instance/client.ts +35 -124
  53. package/src/admin/instance/index.ts +1 -2
  54. package/src/admin/instance/model.ts +11 -20
  55. package/src/commands/__tests__/admin-instance.test.ts +11 -8
  56. package/src/commands/__tests__/auth-login.test.ts +54 -1
  57. package/src/commands/__tests__/call-describe.test.ts +46 -33
  58. package/src/commands/__tests__/call.test.ts +5 -1
  59. package/src/commands/__tests__/domain-install-operation.test.ts +12 -7
  60. package/src/commands/__tests__/domain-install-owned.test.ts +6 -2
  61. package/src/commands/__tests__/domain-list.test.ts +63 -4
  62. package/src/commands/__tests__/install-identity-override.test.ts +19 -19
  63. package/src/commands/__tests__/instance-list-rows.test.ts +1 -1
  64. package/src/commands/__tests__/instance-status.test.ts +139 -0
  65. package/src/commands/__tests__/read-commands.test.ts +35 -10
  66. package/src/commands/__tests__/studio-descriptor.test.ts +22 -0
  67. package/src/commands/__tests__/update.test.ts +48 -19
  68. package/src/commands/call-describe.ts +60 -68
  69. package/src/commands/call.ts +43 -56
  70. package/src/commands/domain/install.ts +13 -17
  71. package/src/commands/domain/list.ts +18 -13
  72. package/src/commands/domain/publish.ts +14 -11
  73. package/src/commands/domain/uninstall.ts +2 -2
  74. package/src/commands/get.ts +14 -15
  75. package/src/commands/identity/__tests__/register.test.ts +3 -3
  76. package/src/commands/identity/register.ts +5 -4
  77. package/src/commands/instance/create.ts +8 -16
  78. package/src/commands/instance/delete.ts +12 -9
  79. package/src/commands/instance/list.ts +2 -2
  80. package/src/commands/instance/status.ts +66 -20
  81. package/src/commands/instance/use.ts +16 -12
  82. package/src/commands/introspect.ts +9 -16
  83. package/src/commands/logs.ts +24 -25
  84. package/src/commands/mutate.ts +6 -5
  85. package/src/commands/query.ts +27 -30
  86. package/src/commands/studio.ts +20 -0
  87. package/src/commands/token.ts +8 -7
  88. package/src/commands/update.ts +38 -14
  89. package/src/commands/view.ts +7 -6
  90. package/src/connection/.spec/api.d.ts +7 -8
  91. package/src/connection/.spec/architecture.md +5 -4
  92. package/src/connection/.spec/flows/session.ts +2 -2
  93. package/src/connection/.spec/laws/connection.ts +6 -2
  94. package/src/connection/.spec/layout.ts +1 -0
  95. package/src/connection/__tests__/credential.test.ts +20 -1
  96. package/src/connection/__tests__/errors.test.ts +43 -32
  97. package/src/connection/__tests__/exchange.test.ts +36 -6
  98. package/src/connection/__tests__/failure-fixtures.ts +39 -0
  99. package/src/connection/__tests__/failure-safety.test.ts +75 -0
  100. package/src/connection/__tests__/self.test.ts +31 -11
  101. package/src/connection/__tests__/session.test.ts +3 -3
  102. package/src/connection/__tests__/target.test.ts +1 -0
  103. package/src/connection/auth.ts +13 -0
  104. package/src/connection/call.ts +1 -1
  105. package/src/connection/credential.ts +2 -2
  106. package/src/connection/errors.ts +1 -355
  107. package/src/connection/exchange.ts +52 -27
  108. package/src/connection/failure/classify.ts +110 -0
  109. package/src/connection/failure/index.ts +18 -0
  110. package/src/connection/failure/model.ts +28 -0
  111. package/src/connection/failure/render.ts +116 -0
  112. package/src/connection/reasons.ts +16 -0
  113. package/src/connection/self.ts +39 -21
  114. package/src/connection/session.ts +19 -8
  115. package/src/errors.ts +3 -2
  116. package/src/graph/.spec/api.d.ts +12 -5
  117. package/src/graph/.spec/layout.ts +9 -1
  118. package/src/graph/__tests__/mutation.test.ts +2 -2
  119. package/src/graph/__tests__/query.test.ts +25 -6
  120. package/src/graph/class.ts +30 -0
  121. package/src/graph/index.ts +1 -0
  122. package/src/graph/query.ts +21 -32
  123. package/src/identity/.spec/api.d.ts +2 -2
  124. package/src/identity/__tests__/registration.test.ts +1 -1
  125. package/src/identity/registration.ts +3 -3
  126. package/src/keys/__tests__/keys.test.ts +4 -0
  127. package/src/keys/credential.ts +1 -0
  128. package/src/lib/__tests__/admin-target.test.ts +12 -0
  129. package/src/lib/__tests__/command-dx.test.ts +1 -1
  130. package/src/lib/__tests__/domain-publication.test.ts +138 -0
  131. package/src/lib/__tests__/idp-session.test.ts +22 -0
  132. package/src/lib/__tests__/idp.test.ts +36 -4
  133. package/src/lib/__tests__/instance-candidates.test.ts +1 -3
  134. package/src/lib/__tests__/instance-target.test.ts +7 -39
  135. package/src/lib/__tests__/instance.test.ts +6 -0
  136. package/src/lib/__tests__/log-errors.test.ts +64 -0
  137. package/src/lib/__tests__/studio-server-deps.test.ts +53 -16
  138. package/src/lib/__tests__/update.test.ts +113 -8
  139. package/src/lib/__tests__/view-open-intent.test.ts +0 -2
  140. package/src/lib/__tests__/view-server.test.ts +18 -3
  141. package/src/lib/__tests__/view-session.test.ts +1 -1
  142. package/src/lib/admin-instance.ts +14 -8
  143. package/src/lib/admin-target.ts +21 -2
  144. package/src/lib/command-dx.ts +9 -9
  145. package/src/lib/domain-publication.ts +104 -0
  146. package/src/lib/failure-debug.ts +26 -0
  147. package/src/lib/idp.ts +39 -4
  148. package/src/lib/instance-candidates.ts +2 -2
  149. package/src/lib/instance-target.ts +3 -14
  150. package/src/lib/instance.ts +22 -12
  151. package/src/lib/log.ts +16 -9
  152. package/src/lib/login-flow.ts +13 -3
  153. package/src/lib/meta.ts +2 -2
  154. package/src/lib/provision-instance.ts +34 -57
  155. package/src/lib/update.ts +124 -30
  156. package/src/lib/validation.ts +2 -2
  157. package/src/lib/view/resolve.ts +1 -1
  158. package/src/lib/view/server.ts +17 -3
  159. package/src/program/__tests__/program.test.ts +20 -4
  160. package/src/program/build.ts +2 -2
  161. package/src/setup/__tests__/instance-step.test.ts +27 -10
  162. package/src/setup/steps/instance.ts +22 -15
  163. package/studio/client/dist/assets/elk-api-DjmKsHXc.js +1 -0
  164. package/studio/client/dist/assets/index-7YHdeCxp.js +81 -0
  165. package/studio/client/dist/assets/index-C0FAnwNw.css +2 -0
  166. package/studio/client/dist/assets/rolldown-runtime-Dd_uD5pT.js +1 -0
  167. package/studio/client/dist/assets/schema-studio-BilUNb6Z.css +1 -0
  168. package/studio/client/dist/assets/schema-studio-CABpTfvH.js +8 -0
  169. package/studio/client/dist/index.html +3 -2
  170. package/studio/package.json +10 -14
  171. package/studio/server/agent/ask.test.ts +1 -1
  172. package/studio/server/agent/bridge/grant.test.ts +1 -1
  173. package/studio/server/agent/bridge/routes.test.ts +1 -1
  174. package/studio/server/agent/bridge/stdio.ts +8 -1
  175. package/studio/server/agent/conversation.test.ts +10 -5
  176. package/studio/server/agent/conversation.ts +56 -8
  177. package/studio/server/agent/harness/claude/adapter.test.ts +15 -5
  178. package/studio/server/agent/harness/codex/loadout.ts +18 -21
  179. package/studio/server/agent/harness/gateway/config.ts +20 -18
  180. package/studio/server/agent/harness/selection.ts +9 -1
  181. package/studio/server/agent/prompts/anchors.test.ts +32 -36
  182. package/studio/server/agent/prompts/anchors.ts +20 -49
  183. package/studio/server/agent/prompts/system.test.ts +3 -2
  184. package/studio/server/agent/prompts/system.ts +6 -5
  185. package/studio/server/agent/prompts/turn.ts +13 -4
  186. package/studio/server/agent/routes.test.ts +1 -1
  187. package/studio/server/agent/run/completion.ts +2 -2
  188. package/studio/server/agent/run/coordinator.test.ts +1 -1
  189. package/studio/server/agent/run/preparation.ts +6 -5
  190. package/studio/server/agent/run/transcript.test.ts +35 -1
  191. package/studio/server/agent/run/transcript.ts +169 -3
  192. package/studio/server/agent/run/usage.test.ts +24 -0
  193. package/studio/server/agent/run/usage.ts +26 -1
  194. package/studio/server/api/canvas.ts +43 -0
  195. package/studio/server/api/comments.ts +85 -0
  196. package/studio/server/api/context.ts +61 -0
  197. package/studio/server/api/deployment.ts +39 -0
  198. package/studio/server/api/documents.ts +55 -0
  199. package/studio/server/api/domain.ts +59 -0
  200. package/studio/server/api/http.ts +45 -0
  201. package/studio/server/api/project.ts +57 -0
  202. package/studio/server/api/schema.ts +12 -0
  203. package/studio/server/api/views.ts +57 -0
  204. package/studio/server/api/workspace.ts +60 -0
  205. package/studio/server/api-agent-loadout.test.ts +1 -1
  206. package/studio/server/api.test.ts +147 -0
  207. package/studio/server/api.ts +20 -422
  208. package/studio/server/cache.test.ts +122 -0
  209. package/studio/server/cache.ts +162 -11
  210. package/studio/server/cli-consumers.test.ts +494 -0
  211. package/studio/server/cli.test.ts +88 -0
  212. package/studio/server/cli.ts +240 -0
  213. package/studio/server/client-package.ts +25 -1
  214. package/studio/server/domain.test.ts +50 -40
  215. package/studio/server/domain.ts +83 -52
  216. package/studio/server/environment/dotenv-preview.test.ts +39 -0
  217. package/studio/server/environment/dotenv-preview.ts +27 -0
  218. package/studio/server/environment/files.test.ts +53 -0
  219. package/studio/server/{state/env.ts → environment/files.ts} +7 -48
  220. package/studio/server/{state → handoff}/copy.ts +21 -6
  221. package/studio/server/handoff/service.test.ts +22 -0
  222. package/studio/server/{state/handoff.ts → handoff/service.ts} +21 -14
  223. package/studio/server/index.ts +1 -1
  224. package/studio/server/instances/active.ts +72 -0
  225. package/studio/server/instances/deploy-record.test.ts +31 -0
  226. package/studio/server/instances/deploy-record.ts +37 -0
  227. package/studio/server/instances/deploy.ts +56 -0
  228. package/studio/server/{state/instance.test.ts → instances/probe.test.ts} +25 -21
  229. package/studio/server/instances/probe.ts +67 -0
  230. package/studio/server/instances/status.test.ts +12 -0
  231. package/studio/server/instances/status.ts +49 -0
  232. package/studio/server/introspect/anatomy/client-tree.ts +57 -0
  233. package/studio/server/introspect/anatomy/env-fields.ts +66 -0
  234. package/studio/server/introspect/anatomy/schema-definition.ts +53 -0
  235. package/studio/server/introspect/anatomy/source.ts +181 -0
  236. package/studio/server/introspect/anatomy/views/routes.ts +114 -0
  237. package/studio/server/introspect/anatomy/views.ts +53 -0
  238. package/studio/server/introspect/anatomy-extras.test.ts +106 -35
  239. package/studio/server/introspect/anatomy-extras.ts +7 -726
  240. package/studio/server/introspect/anatomy.test.ts +22 -14
  241. package/studio/server/introspect/anatomy.ts +52 -28
  242. package/studio/server/introspect/bundle.ts +15 -9
  243. package/studio/server/introspect/canonical-schema.test.ts +93 -309
  244. package/studio/server/introspect/canonical-schema.ts +257 -425
  245. package/studio/server/introspect/config-preview.test.ts +32 -0
  246. package/studio/server/introspect/config-preview.ts +119 -0
  247. package/studio/server/introspect/core-extractor.ts +18 -127
  248. package/studio/server/introspect/core.ts +1 -2
  249. package/studio/server/introspect/diff.test.ts +18 -18
  250. package/studio/server/introspect/diff.ts +44 -90
  251. package/studio/server/introspect/extractor.ts +23 -116
  252. package/studio/server/introspect/hash.ts +5 -2
  253. package/studio/server/introspect/overlay-tsmorph.test.ts +119 -240
  254. package/studio/server/introspect/overlay-tsmorph.ts +7 -1305
  255. package/studio/server/introspect/overlay.test.ts +26 -54
  256. package/studio/server/introspect/overlay.ts +10 -37
  257. package/studio/server/introspect/revision.test.ts +54 -0
  258. package/studio/server/introspect/revision.ts +49 -0
  259. package/studio/server/introspect/runtime.test.ts +83 -143
  260. package/studio/server/introspect/runtime.ts +40 -11
  261. package/studio/server/introspect/schema-ir-json.test.ts +70 -0
  262. package/studio/server/introspect/schema-ir-json.ts +151 -0
  263. package/studio/server/introspect/schema-refs.test.ts +43 -88
  264. package/studio/server/introspect/schema-refs.ts +14 -49
  265. package/studio/server/introspect/source-overlay/annotations.ts +14 -0
  266. package/studio/server/introspect/source-overlay/handlers.ts +161 -0
  267. package/studio/server/introspect/source-overlay/kernel-calls.ts +46 -0
  268. package/studio/server/introspect/source-overlay/project.ts +248 -0
  269. package/studio/server/introspect/source-overlay/spans.ts +330 -0
  270. package/studio/server/json.ts +46 -0
  271. package/studio/server/lifecycle.ts +5 -1
  272. package/studio/server/sse.test.ts +26 -0
  273. package/studio/server/sse.ts +4 -1
  274. package/studio/server/state/baseline.test.ts +223 -7
  275. package/studio/server/state/baseline.ts +148 -34
  276. package/studio/server/state/comments.test.ts +66 -1
  277. package/studio/server/state/comments.ts +173 -10
  278. package/studio/server/state/context.ts +34 -2
  279. package/studio/server/state/documents.ts +42 -1
  280. package/studio/server/state/integrations.ts +27 -1
  281. package/studio/server/state/layout.test.ts +34 -0
  282. package/studio/server/state/layout.ts +44 -17
  283. package/studio/server/state/settings.ts +29 -22
  284. package/studio/server/state/store.test.ts +122 -0
  285. package/studio/server/state/store.ts +66 -17
  286. package/studio/server/state/visibility.ts +22 -11
  287. package/studio/server/views/model.test.ts +57 -0
  288. package/studio/server/views/model.ts +66 -0
  289. package/studio/server/views/runtime.ts +40 -0
  290. package/studio/server/views/selection-repository.test.ts +31 -0
  291. package/studio/server/views/selection-repository.ts +60 -0
  292. package/studio/server/views/session.test.ts +73 -0
  293. package/studio/server/views/session.ts +166 -0
  294. package/studio/server/views/target.test.ts +78 -0
  295. package/studio/server/views/target.ts +222 -0
  296. package/studio/server/watch.test.ts +11 -11
  297. package/studio/server/watch.ts +9 -5
  298. package/studio/server/workspace/catalog.test.ts +17 -0
  299. package/studio/server/workspace/catalog.ts +43 -0
  300. package/studio/server/{state → workspace}/create.test.ts +1 -1
  301. package/studio/server/{state → workspace}/create.ts +1 -1
  302. package/studio/server/{state → workspace}/git.ts +1 -1
  303. package/studio/server/workspace/updates.ts +83 -0
  304. package/studio/server/workspace-state.ts +1 -1
  305. package/studio/server/workspace-watch.ts +2 -2
  306. package/studio/shared/contracts/README.md +16 -0
  307. package/studio/shared/contracts/agent.ts +270 -0
  308. package/studio/shared/contracts/runtime.ts +50 -0
  309. package/studio/shared/contracts/schema.ts +393 -0
  310. package/studio/shared/contracts/surface.test.ts +317 -0
  311. package/studio/shared/contracts/workspace.ts +265 -0
  312. package/studio/shared/layout.test.ts +116 -0
  313. package/studio/shared/schema/identity.test.ts +34 -0
  314. package/studio/shared/schema/identity.ts +68 -0
  315. package/studio/shared/types.ts +11 -1099
  316. package/studio/tsconfig.json +1 -1
  317. package/viewer/dist/main.js +40 -61
  318. package/.check-workspace.cjs +0 -40
  319. package/src/commands/__tests__/instance-create-hosts.test.ts +0 -29
  320. package/studio/client/dist/assets/elk-api-D2xgMJvi.js +0 -1
  321. package/studio/client/dist/assets/index-BMdnsIJA.css +0 -1
  322. package/studio/client/dist/assets/index-ChOr3yP0.css +0 -1
  323. package/studio/client/dist/assets/index-D-vRV8w7.js +0 -8
  324. package/studio/client/dist/assets/index-LGSWRrk8.js +0 -81
  325. package/studio/server/state/catalog.ts +0 -117
  326. package/studio/server/state/instance.ts +0 -280
  327. package/studio/server/state/updates.ts +0 -63
  328. package/studio/server/state/views.test.ts +0 -286
  329. package/studio/server/state/views.ts +0 -535
@@ -0,0 +1,20 @@
1
+ import type { schema } from '@astrale-os/sdk/schema'
2
+
3
+ import { defineApplication } from '@astrale-os/sdk/application'
4
+ import { compile } from '@astrale-os/sdk/deployment/build'
5
+ import { addressing, assemble } from '@astrale-os/sdk/deployment/release'
6
+ import { defineRuntime } from '@astrale-os/sdk/runtime'
7
+
8
+ /** Build a canonical empty-runtime Release for cross-boundary CLI tests. */
9
+ export function releaseFor<const Schema extends schema.DomainSchema>(
10
+ source: Schema,
11
+ issuer: string,
12
+ ) {
13
+ const runtime = defineRuntime<Schema>()({
14
+ integrations: {},
15
+ initialize: () => ({ providers: {} }),
16
+ actions: [],
17
+ workflows: [],
18
+ })
19
+ return assemble(compile(defineApplication({ schema: source, runtime })), addressing(issuer))
20
+ }
@@ -0,0 +1,31 @@
1
+ import type { ClientSession } from '@astrale-os/sdk/client/session'
2
+
3
+ import { bundle, defineSchema, schema as schemaApi } from '@astrale-os/sdk/schema'
4
+ import { expect, mock, test } from 'bun:test'
5
+
6
+ import { releaseFor } from '../../__tests__/fixtures/publication'
7
+ import { bindAdmin } from '../binding'
8
+
9
+ const schema = defineSchema('admin.astrale.ai', {})
10
+ const release = releaseFor(schema, 'https://admin.beta.astrale.ai')
11
+
12
+ test('binds the installed Admin Domain instead of the source Kernel publication', async () => {
13
+ const installation = mock(async () => ({
14
+ state: 'ready' as const,
15
+ target: 'sha256:admin-target' as const,
16
+ source: { kind: 'remote' as const, publication: release.publication },
17
+ bundle: bundle.create(schema),
18
+ readiness: 'sha256:admin-readiness' as const,
19
+ capabilities: { requested: [], materialized: [] },
20
+ }))
21
+ const session = {
22
+ installation,
23
+ bind: (domain: unknown) => ({ domain, graph: {} }),
24
+ } as unknown as ClientSession
25
+
26
+ const binding = await bindAdmin(session)
27
+
28
+ expect(installation).toHaveBeenCalledWith('admin.astrale.ai')
29
+ expect(binding.domain.origin).toBe('admin.astrale.ai')
30
+ expect(binding.domain.revision).toBe(schemaApi.revision(schema))
31
+ })
@@ -0,0 +1,101 @@
1
+ import type { ClientSession } from '@astrale-os/sdk/client/session'
2
+ import type { CallableReference } from '@astrale-os/sdk/client/session'
3
+
4
+ import {
5
+ callableAddress,
6
+ core,
7
+ defineSchema,
8
+ edgeClass,
9
+ method,
10
+ nodeClass,
11
+ property,
12
+ schema,
13
+ } from '@astrale-os/sdk/schema'
14
+ import { mock } from 'bun:test'
15
+
16
+ import type { AdminBinding } from '../binding'
17
+
18
+ const operation = () =>
19
+ method({
20
+ auth: 'authenticated',
21
+ input: { type: 'object', additionalProperties: true },
22
+ output: { type: 'object', additionalProperties: true },
23
+ })
24
+
25
+ const Domain = nodeClass({
26
+ properties: {
27
+ origin: property({ type: 'string' }, { required: true }),
28
+ name: property({ type: 'string' }, { required: true }),
29
+ discoveryUrl: property({ type: 'string' }, { required: true }),
30
+ description: property({ type: 'string' }),
31
+ createdAt: property({ type: 'string' }, { required: true }),
32
+ updatedAt: property({ type: 'string' }, { required: true }),
33
+ },
34
+ methods: { configureDefault: operation() },
35
+ })
36
+ const Fleet = nodeClass({
37
+ methods: {
38
+ publishDomain: operation(),
39
+ listInstances: operation(),
40
+ createInstance: operation(),
41
+ },
42
+ })
43
+ const Host = nodeClass({
44
+ properties: {
45
+ id: property({ type: 'string' }, { required: true }),
46
+ state: property({ type: 'string' }, { required: true }),
47
+ },
48
+ methods: { createInstance: operation() },
49
+ })
50
+ const Instance = nodeClass({
51
+ methods: {
52
+ status: operation(),
53
+ delete: operation(),
54
+ installDomain: operation(),
55
+ },
56
+ })
57
+ const fleet_installs_domain_by_default = edgeClass.directed({
58
+ source: { as: 'fleet', accepts: [Fleet], outgoing: '0..*' },
59
+ target: { as: 'domain', accepts: [Domain], incoming: '0..*' },
60
+ })
61
+ const fleet_reserves_admin_host = edgeClass.directed({
62
+ source: { as: 'fleet', accepts: [Fleet], outgoing: '0..1' },
63
+ target: { as: 'host', accepts: [Host], incoming: '0..1' },
64
+ })
65
+
66
+ export const AdminTestSchema = defineSchema('admin.astrale.ai', {
67
+ classes: {
68
+ Domain,
69
+ Fleet,
70
+ Host,
71
+ Instance,
72
+ fleet_installs_domain_by_default,
73
+ fleet_reserves_admin_host,
74
+ },
75
+ core: { nodes: { fleet: core.node(() => Fleet, {}) }, edges: [] },
76
+ })
77
+
78
+ export const AdminTestDomain = schema.resolve(AdminTestSchema)
79
+
80
+ export function adminBinding(): AdminBinding {
81
+ return { domain: AdminTestDomain, graph: {} } as unknown as AdminBinding
82
+ }
83
+
84
+ export function adminSession(
85
+ implementation?: (
86
+ method: { readonly owner: string; readonly name: string },
87
+ receiver: unknown,
88
+ input: unknown,
89
+ ) => unknown,
90
+ ) {
91
+ const invoke = mock(async (reference: CallableReference, input: unknown) => {
92
+ const address = callableAddress(reference.callable)
93
+ if (address.kind !== 'method') throw new Error('Expected an Admin Method.')
94
+ return implementation?.(
95
+ { owner: address.owner.name, name: address.name },
96
+ reference.target,
97
+ input,
98
+ )
99
+ })
100
+ return { invoke, session: { invoke } as unknown as ClientSession }
101
+ }
@@ -0,0 +1,98 @@
1
+ import type { Input } from '@astrale-os/sdk/client'
2
+ import type { ClientSession } from '@astrale-os/sdk/client/session'
3
+ import type {
4
+ ResolvedClass,
5
+ ResolvedCoreDefinition,
6
+ ResolvedMethod,
7
+ ResolvedProperty,
8
+ } from '@astrale-os/sdk/schema'
9
+ import type { DomainBinding } from '@astrale-os/shell'
10
+
11
+ import { reference } from '@astrale-os/sdk/client/session'
12
+ import { Path } from '@astrale-os/sdk/graph/path'
13
+ import { bindDomain } from '@astrale-os/shell'
14
+
15
+ const ADMIN_ORIGIN = 'admin.astrale.ai'
16
+
17
+ export type AdminBinding = DomainBinding
18
+
19
+ /** Bind the exact Admin revision installed on this source Kernel. */
20
+ export async function bindAdmin(session: ClientSession): Promise<AdminBinding> {
21
+ const installed = await session.installation(ADMIN_ORIGIN)
22
+ return requireAdminBinding(await bindDomain(session, installed.bundle.root))
23
+ }
24
+
25
+ /** Admit an injected dynamic binding as the Admin Domain. */
26
+ export function requireAdminBinding(binding: AdminBinding): AdminBinding {
27
+ if (binding.domain.origin !== ADMIN_ORIGIN) {
28
+ throw new TypeError('Configured Admin target does not serve the Admin Domain.')
29
+ }
30
+ return binding
31
+ }
32
+
33
+ /** Resolve one required Admin Class without rebuilding its schema contract. */
34
+ export function requireAdminClass(
35
+ binding: AdminBinding,
36
+ name: string,
37
+ kind: 'node',
38
+ ): ResolvedClass<'node'>
39
+ export function requireAdminClass(
40
+ binding: AdminBinding,
41
+ name: string,
42
+ kind: 'edge',
43
+ ): ResolvedClass<'edge'>
44
+ export function requireAdminClass(
45
+ binding: AdminBinding,
46
+ name: string,
47
+ kind: 'node' | 'edge',
48
+ ): ResolvedClass<'node'> | ResolvedClass<'edge'> {
49
+ const selected = binding.domain.classes[name]
50
+ if (selected?.kind !== kind) throw new TypeError(`Admin ${name} is not a ${kind} Class.`)
51
+ return selected
52
+ }
53
+
54
+ /** Resolve one required Admin Core Node as its canonical projection Path. */
55
+ export function requireAdminCore(binding: AdminBinding, name: string): Path {
56
+ const selected = binding.domain.core.nodes[name] as ResolvedCoreDefinition | undefined
57
+ if (selected === undefined) throw new TypeError(`Admin has no Core Node ${name}.`)
58
+ return Path.project(selected.ref)
59
+ }
60
+
61
+ /** Resolve one effective Property by unambiguous member name. */
62
+ export function requireAdminProperty(
63
+ owner: ResolvedClass,
64
+ name: string,
65
+ ): ResolvedProperty<unknown> {
66
+ const selected = [...owner.properties].find((property) => property.name === name)
67
+ if (selected === undefined) {
68
+ throw new TypeError(`Admin ${owner.ref.name}.${name} Property is absent.`)
69
+ }
70
+ return selected
71
+ }
72
+
73
+ /** Invoke one resolved executable instance Method through Kernel Client. */
74
+ export async function invokeAdminMethod(
75
+ session: ClientSession,
76
+ binding: AdminBinding,
77
+ owner: ResolvedClass<'node'>,
78
+ name: string,
79
+ receiver: Path,
80
+ input: Input,
81
+ ): Promise<unknown> {
82
+ const method = [...owner.methods].find((candidate) => candidate.name === name)
83
+ if (method === undefined || !isExecutableInstanceMethod(method)) {
84
+ throw new TypeError(`Admin ${owner.ref.name}.${name} is not an executable instance Method.`)
85
+ }
86
+ return session.invoke(reference(binding.domain, method)(receiver), input)
87
+ }
88
+
89
+ type ExecutableInstanceMethod = ResolvedMethod<
90
+ unknown,
91
+ unknown,
92
+ false,
93
+ Exclude<ResolvedMethod['inheritance'], 'abstract'>
94
+ >
95
+
96
+ function isExecutableInstanceMethod(method: ResolvedMethod): method is ExecutableInstanceMethod {
97
+ return method.static === false && method.inheritance !== 'abstract'
98
+ }
@@ -1,5 +1,5 @@
1
- import type { DomainBinding } from '@astrale-os/kernel-client/domain'
2
- import type { ClientSession } from '@astrale-os/kernel-client/session'
1
+ import type { ClientSession } from '@astrale-os/sdk/client/session'
2
+ import type { DomainBinding } from '@astrale-os/shell'
3
3
 
4
4
  import type { AdminGraphApi } from '../../graph/.spec/api.js'
5
5
 
@@ -1,41 +1,25 @@
1
- import type { DomainBinding } from '@astrale-os/kernel-client/domain'
2
1
  import type { Node } from '@astrale-os/sdk/graph/node'
3
2
  import type { QueryAST } from '@astrale-os/sdk/query'
4
3
 
5
- import { ClassPath } from '@astrale-os/sdk/graph/class'
6
4
  import { NodeId } from '@astrale-os/sdk/graph/node'
7
- import { Path } from '@astrale-os/sdk/graph/path'
8
5
  import { describe, expect, mock, test } from 'bun:test'
9
6
 
10
7
  import type { AdminGraphApi } from '../../graph'
11
8
 
9
+ import { AdminTestDomain, adminBinding, adminSession } from '../../__tests__/fixture'
12
10
  import { connectAdminCatalog } from '../client'
13
11
 
14
- function definition(name: string) {
15
- return {
16
- name,
17
- $: {
18
- method(method: string) {
19
- return { owner: name, name: method }
20
- },
21
- property(property: string) {
22
- return { key: property }
23
- },
24
- },
25
- }
26
- }
27
-
28
12
  function domainNode(id: string, origin: string): Node {
29
13
  return {
30
14
  id: NodeId(id),
31
- class: ClassPath.from('admin.astrale.ai', 'Domain'),
32
- props: {
15
+ class: AdminTestDomain.classes.Domain.key,
16
+ props: AdminTestDomain.classes.Domain.properties.from({
33
17
  origin,
34
18
  name: origin.split('.')[0]!,
35
19
  discoveryUrl: `https://${origin}`,
36
20
  createdAt: '2026-08-12T00:00:00.000Z',
37
21
  updatedAt: '2026-08-12T00:00:00.000Z',
38
- } as never,
22
+ }),
39
23
  }
40
24
  }
41
25
 
@@ -44,24 +28,16 @@ function fixture(input: {
44
28
  defaults?: readonly Node[]
45
29
  invoke?: (method: { owner: string; name: string }, receiver: unknown, value: unknown) => unknown
46
30
  }) {
47
- const Domain = definition('Domain')
48
- const Fleet = definition('Fleet')
49
- const invoke = mock(async (method: unknown, receiver: unknown, value: unknown) =>
50
- input.invoke?.(method as { owner: string; name: string }, receiver, value),
51
- )
52
- const binding = {
53
- $: {
54
- publication: { origin: 'admin.astrale.ai' },
55
- origin: 'admin.astrale.ai',
56
- class(name: string) {
57
- if (name === 'Domain') return Domain
58
- if (name === 'Fleet') return Fleet
59
- throw new Error(`Unexpected class ${name}`)
60
- },
61
- core: { nodes: { fleet: { path: Path.id(NodeId('fleet')) } } },
62
- invoke,
63
- },
64
- } as unknown as DomainBinding
31
+ const calls: Array<{
32
+ method: { owner: string; name: string }
33
+ receiver: string
34
+ value: unknown
35
+ }> = []
36
+ const remote = adminSession((method, receiver, value) => {
37
+ calls.push({ method, receiver: String(receiver), value })
38
+ return input.invoke?.(method, receiver, value)
39
+ })
40
+ const binding = adminBinding()
65
41
  const query = mock(async (_ast: QueryAST) => ({
66
42
  result: {
67
43
  kind: 'nodes' as const,
@@ -79,10 +55,11 @@ function fixture(input: {
79
55
  }))
80
56
  const graph = { query, neighbors } as unknown as AdminGraphApi
81
57
  return {
82
- invoke,
58
+ invoke: remote.invoke,
59
+ calls,
83
60
  connect: () =>
84
61
  connectAdminCatalog(
85
- { session: {} as never, graph },
62
+ { session: remote.session, graph },
86
63
  {
87
64
  bind: async () => binding,
88
65
  operationId: (kind) => `cli.domain.${kind}:test`,
@@ -130,16 +107,10 @@ describe('V2 Admin Domain catalog adapter', () => {
130
107
  installByDefault: true,
131
108
  }),
132
109
  ).resolves.toMatchObject({ changed: true, isNew: true, entry: { installByDefault: true } })
133
- expect(
134
- contract.invoke.mock.calls.map(([method, receiver, value]) => ({
135
- method,
136
- receiver: String(receiver),
137
- value,
138
- })),
139
- ).toEqual([
110
+ expect(contract.calls).toEqual([
140
111
  {
141
112
  method: { owner: 'Fleet', name: 'publishDomain' },
142
- receiver: '@fleet',
113
+ receiver: '/:admin.astrale.ai:core.fleet::publishDomain',
143
114
  value: {
144
115
  operationId: 'cli.domain.publish:test',
145
116
  origin: 'crm.acme.dev',
@@ -149,7 +120,7 @@ describe('V2 Admin Domain catalog adapter', () => {
149
120
  },
150
121
  {
151
122
  method: { owner: 'Domain', name: 'configureDefault' },
152
- receiver: '@crm-domain',
123
+ receiver: '@crm-domain::configureDefault',
153
124
  value: {
154
125
  operationId: 'cli.domain.configure-default:test',
155
126
  enabled: true,
@@ -1,11 +1,19 @@
1
- import type { DomainBinding } from '@astrale-os/kernel-client/domain'
2
- import type { ClientSession } from '@astrale-os/kernel-client/session'
1
+ import type { ClientSession } from '@astrale-os/sdk/client/session'
3
2
  import type { Node } from '@astrale-os/sdk/graph/node'
3
+ import type { ResolvedClass } from '@astrale-os/sdk/schema'
4
4
 
5
- import { bind } from '@astrale-os/kernel-client/domain'
6
5
  import { Path } from '@astrale-os/sdk/graph/path'
7
6
  import { Query } from '@astrale-os/sdk/query'
8
7
 
8
+ import {
9
+ bindAdmin,
10
+ invokeAdminMethod,
11
+ requireAdminBinding,
12
+ requireAdminClass,
13
+ requireAdminCore,
14
+ requireAdminProperty,
15
+ type AdminBinding,
16
+ } from '../binding'
9
17
  import { readAllNodes, type AdminGraphApi } from '../graph'
10
18
  import {
11
19
  AdminDomainNotFoundError,
@@ -14,16 +22,9 @@ import {
14
22
  type PublishDomainResult,
15
23
  } from './model'
16
24
 
17
- const ADMIN_ORIGIN = 'admin.astrale.ai'
18
25
  const PAGE_SIZE = 256
19
26
  const MAXIMUM_DOMAINS = 10_000
20
27
  const MAXIMUM_PAGES = Math.ceil(MAXIMUM_DOMAINS / PAGE_SIZE) + 1
21
- const DomainRef = Object.freeze({ origin: ADMIN_ORIGIN, kind: 'class' as const, name: 'Domain' })
22
- const fleetInstallsByDefault = Object.freeze({
23
- origin: ADMIN_ORIGIN,
24
- kind: 'class' as const,
25
- name: 'fleet_installs_domain_by_default',
26
- })
27
28
 
28
29
  export interface AdminCatalogContext {
29
30
  readonly session: ClientSession
@@ -37,7 +38,7 @@ export interface AdminCatalogApi {
37
38
  }
38
39
 
39
40
  export interface AdminCatalogDependencies {
40
- readonly bind?: (session: ClientSession) => Promise<DomainBinding>
41
+ readonly bind?: (session: ClientSession) => Promise<AdminBinding>
41
42
  readonly operationId?: (kind: 'publish' | 'configure-default') => string
42
43
  }
43
44
 
@@ -46,21 +47,22 @@ export async function connectAdminCatalog(
46
47
  context: AdminCatalogContext,
47
48
  dependencies: AdminCatalogDependencies = {},
48
49
  ): Promise<AdminCatalogApi> {
49
- const binding = await (dependencies.bind ?? bindInstalledAdmin)(context.session)
50
- if (binding.$.publication?.origin !== ADMIN_ORIGIN || binding.$.origin !== ADMIN_ORIGIN) {
51
- throw new TypeError('Configured Admin target does not serve the Admin Domain.')
52
- }
53
- const Domain = binding.$.class('Domain')
54
- const Fleet = binding.$.class('Fleet')
55
- const fleet = binding.$.core.nodes.fleet?.path
56
- if (fleet === undefined) throw new TypeError('Admin Domain has no singleton Fleet receiver.')
50
+ const binding = requireAdminBinding(await (dependencies.bind ?? bindAdmin)(context.session))
51
+ const Domain = requireAdminClass(binding, 'Domain', 'node')
52
+ const Fleet = requireAdminClass(binding, 'Fleet', 'node')
53
+ const fleetInstallsByDefault = requireAdminClass(
54
+ binding,
55
+ 'fleet_installs_domain_by_default',
56
+ 'edge',
57
+ )
58
+ const fleet = requireAdminCore(binding, 'fleet')
57
59
  const operationId = dependencies.operationId ?? defaultOperationId
58
60
 
59
61
  const list = async (): Promise<DomainInfo[]> => {
60
62
  const [nodes, defaultsPage] = await Promise.all([
61
63
  readAllNodes(
62
64
  context.graph,
63
- Query.from({ kind: 'node', definitions: [DomainRef] }).select({
65
+ Query.from({ nodes: [Domain] }).select({
64
66
  kind: 'nodes',
65
67
  projection: { kind: 'value' },
66
68
  }),
@@ -108,13 +110,13 @@ export async function connectAdminCatalog(
108
110
  let entry = existing
109
111
  if (registryChanged) {
110
112
  entry = domainFromSummary(
111
- await binding.$.invoke(Fleet.$.method('publishDomain') as never, fleet, {
113
+ await invokeAdminMethod(context.session, binding, Fleet, 'publishDomain', fleet, {
112
114
  operationId: operationId('publish'),
113
115
  origin: input.origin,
114
116
  name: input.name,
115
117
  discoveryUrl: input.url,
116
118
  ...(description === undefined ? {} : { description }),
117
- } as never),
119
+ }),
118
120
  existing?.installByDefault === true,
119
121
  )
120
122
  }
@@ -125,13 +127,16 @@ export async function connectAdminCatalog(
125
127
  (entry.installByDefault ?? false) !== input.installByDefault
126
128
  if (defaultChanged) {
127
129
  entry = domainFromSummary(
128
- await binding.$.invoke(
129
- Domain.$.method('configureDefault') as never,
130
+ await invokeAdminMethod(
131
+ context.session,
132
+ binding,
133
+ Domain,
134
+ 'configureDefault',
130
135
  Path.parse(entry.id),
131
136
  {
132
137
  operationId: operationId('configure-default'),
133
138
  enabled: input.installByDefault,
134
- } as never,
139
+ },
135
140
  ),
136
141
  input.installByDefault === true,
137
142
  )
@@ -145,11 +150,7 @@ export async function connectAdminCatalog(
145
150
  })
146
151
  }
147
152
 
148
- async function bindInstalledAdmin(session: ClientSession): Promise<DomainBinding> {
149
- return bind(session, await session.installed(ADMIN_ORIGIN))
150
- }
151
-
152
- type DynamicDefinition = ReturnType<DomainBinding['$']['class']>
153
+ type DynamicDefinition = ResolvedClass<'node'>
153
154
 
154
155
  function domainFromNode(
155
156
  definition: DynamicDefinition,
@@ -185,7 +186,10 @@ function domainFromSummary(input: unknown, installByDefault: boolean): DomainInf
185
186
  }
186
187
 
187
188
  function requiredProperty(definition: DynamicDefinition, node: Node, name: string): string {
188
- return requiredString(node.props[definition.$.property(name).key], `Admin Domain.${name}`)
189
+ return requiredString(
190
+ node.props[requireAdminProperty(definition, name).key],
191
+ `Admin Domain.${name}`,
192
+ )
189
193
  }
190
194
 
191
195
  function optionalProperty(
@@ -193,7 +197,7 @@ function optionalProperty(
193
197
  node: Node,
194
198
  name: string,
195
199
  ): Readonly<Record<string, string>> {
196
- const value = node.props[definition.$.property(name).key]
200
+ const value = node.props[requireAdminProperty(definition, name).key]
197
201
  return value === undefined ? {} : { [name]: requiredString(value, `Admin Domain.${name}`) }
198
202
  }
199
203
 
@@ -33,10 +33,9 @@ export interface InstallDomainResult {
33
33
  readonly error?: string | null
34
34
  }
35
35
 
36
- export class AdminDomainNotFoundError extends Error {
37
- readonly name = 'NotFoundError'
38
-
36
+ export class AdminDomainNotFoundError extends AstraleError {
39
37
  constructor(readonly identifier: string) {
40
- super(`No visible Admin Domain matches ${JSON.stringify(identifier)}.`)
38
+ super('DOMAIN_NOT_FOUND', `No visible Admin Domain matches ${JSON.stringify(identifier)}.`)
41
39
  }
42
40
  }
41
+ import { AstraleError } from '../../errors'
@@ -1,18 +1,12 @@
1
- import type { GraphQueryOptions, NeighborsOptions, NodePage } from '@astrale-os/kernel-client/graph'
2
- import type { ClassPath } from '@astrale-os/sdk/graph/class'
1
+ import type { GraphApi } from '@astrale-os/sdk/client'
3
2
  import type { Node } from '@astrale-os/sdk/graph/node'
4
- import type { PathLike } from '@astrale-os/sdk/graph/path'
5
- import type { QueryAST, QueryResult } from '@astrale-os/sdk/query'
3
+ import type { QueryAST } from '@astrale-os/sdk/query'
6
4
 
7
5
  /** Smallest Kernel graph capability needed by bounded Admin graph reads. */
8
- export interface AdminGraphQueryApi {
9
- query(ast: QueryAST, options?: GraphQueryOptions): Promise<QueryResult>
10
- }
6
+ export type AdminGraphQueryApi = Pick<GraphApi, 'query'>
11
7
 
12
8
  /** Caller-scoped graph reads shared by the Admin catalog and Instance journeys. */
13
- export interface AdminGraphApi extends AdminGraphQueryApi {
14
- neighbors(source: PathLike, edge: ClassPath, options: NeighborsOptions): Promise<NodePage>
15
- }
9
+ export type AdminGraphApi = Pick<GraphApi, 'query' | 'neighbors'>
16
10
 
17
11
  export interface ReadAllNodesOptions {
18
12
  readonly label: string
@@ -1,4 +1,4 @@
1
- import type { GraphApi } from '@astrale-os/kernel-client/graph'
1
+ import type { GraphApi } from '@astrale-os/sdk/client'
2
2
  import type { Node } from '@astrale-os/sdk/graph/node'
3
3
  import type { QueryAST } from '@astrale-os/sdk/query'
4
4
 
@@ -1,5 +1,5 @@
1
- import type { DomainBinding } from '@astrale-os/kernel-client/domain'
2
- import type { ClientSession } from '@astrale-os/kernel-client/session'
1
+ import type { ClientSession } from '@astrale-os/sdk/client/session'
2
+ import type { DomainBinding } from '@astrale-os/shell'
3
3
 
4
4
  import type { AdminGraphApi } from '../../graph/.spec/api.js'
5
5