@astrale-os/cli 0.8.1-alpha.0 → 0.8.1-alpha.2

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 (310) hide show
  1. package/dist/astrale.js +62959 -41238
  2. package/dist/public/connect-core.js +55030 -0
  3. package/dist/public/keys/index.js +45631 -0
  4. package/dist/public/paths/index.js +43990 -0
  5. package/dist/types/admin/instance/model.d.ts +40 -0
  6. package/dist/types/connect-core.d.ts +22 -0
  7. package/dist/types/connection/auth.d.ts +33 -0
  8. package/dist/types/errors.d.ts +23 -0
  9. package/dist/types/identity/registry.d.ts +25 -0
  10. package/dist/types/keys/algorithm.d.ts +6 -0
  11. package/dist/types/keys/credential.d.ts +21 -0
  12. package/dist/types/keys/index.d.ts +4 -0
  13. package/dist/types/keys/pair.d.ts +34 -0
  14. package/dist/types/lib/admin-target.d.ts +74 -0
  15. package/dist/types/lib/ca-fetch.d.ts +2 -0
  16. package/dist/types/lib/config.d.ts +71 -0
  17. package/dist/types/lib/format.d.ts +1 -0
  18. package/dist/types/lib/idp-session.d.ts +33 -0
  19. package/dist/types/lib/idp.d.ts +397 -0
  20. package/dist/types/lib/instance-target.d.ts +36 -0
  21. package/dist/types/lib/instance.d.ts +186 -0
  22. package/dist/types/lib/log.d.ts +30 -0
  23. package/dist/types/lib/login-flow.d.ts +49 -0
  24. package/dist/types/lib/meta.d.ts +36 -0
  25. package/dist/types/lib/output.d.ts +83 -0
  26. package/dist/types/lib/table.d.ts +18 -0
  27. package/dist/types/lib/validation.d.ts +11 -0
  28. package/dist/types/paths/index.d.ts +2 -0
  29. package/dist/types/state/exchange-credentials.d.ts +25 -0
  30. package/dist/types/state/files.d.ts +9 -0
  31. package/dist/types/state/identities.d.ts +42 -0
  32. package/dist/types/state/index.d.ts +8 -0
  33. package/dist/types/state/paths.d.ts +32 -0
  34. package/package.json +22 -7
  35. package/src/admin/.spec/api.d.ts +3 -0
  36. package/src/admin/.spec/architecture.md +15 -0
  37. package/src/admin/.spec/icon.svg +3 -0
  38. package/src/admin/.spec/layout.ts +6 -0
  39. package/src/admin/catalog/.spec/api.d.ts +65 -0
  40. package/src/admin/catalog/.spec/architecture.md +6 -0
  41. package/src/admin/catalog/.spec/icon.svg +3 -0
  42. package/src/admin/catalog/.spec/layout.ts +6 -0
  43. package/src/admin/catalog/__tests__/client.test.ts +171 -0
  44. package/src/admin/catalog/client.ts +214 -0
  45. package/src/admin/catalog/index.ts +13 -0
  46. package/src/admin/catalog/model.ts +42 -0
  47. package/src/admin/catalog/tsconfig.json +8 -0
  48. package/src/admin/graph/.spec/api.d.ts +28 -0
  49. package/src/admin/graph/.spec/architecture.md +5 -0
  50. package/src/admin/graph/.spec/icon.svg +3 -0
  51. package/src/admin/graph/.spec/layout.ts +3 -0
  52. package/src/admin/graph/index.ts +6 -0
  53. package/src/admin/graph/nodes.ts +56 -0
  54. package/src/admin/index.ts +2 -0
  55. package/src/admin/instance/.spec/api.d.ts +66 -0
  56. package/src/admin/instance/.spec/architecture.md +10 -0
  57. package/src/admin/instance/.spec/icon.svg +3 -0
  58. package/src/admin/instance/.spec/layout.ts +6 -0
  59. package/src/admin/instance/__tests__/client.test.ts +289 -0
  60. package/src/admin/instance/client.ts +298 -0
  61. package/src/admin/instance/index.ts +16 -0
  62. package/src/admin/instance/model.ts +65 -0
  63. package/src/admin/instance/tsconfig.json +8 -0
  64. package/src/commands/__tests__/admin-instance.test.ts +3 -36
  65. package/src/commands/__tests__/call.test.ts +21 -68
  66. package/src/commands/__tests__/domain-install-owned.test.ts +26 -27
  67. package/src/commands/__tests__/domain-list.test.ts +2 -6
  68. package/src/commands/__tests__/logs.test.ts +50 -98
  69. package/src/commands/__tests__/ls.test.ts +21 -17
  70. package/src/commands/__tests__/read-commands.test.ts +171 -101
  71. package/src/commands/__tests__/view.test.ts +100 -51
  72. package/src/commands/admin/status.ts +3 -3
  73. package/src/commands/admin/use.ts +29 -6
  74. package/src/commands/auth/login.ts +1 -1
  75. package/src/commands/auth/logout.ts +4 -2
  76. package/src/commands/auth/status.ts +2 -2
  77. package/src/commands/auth/token.ts +2 -2
  78. package/src/commands/browser.ts +1 -1
  79. package/src/commands/call.ts +55 -91
  80. package/src/commands/describe.ts +52 -147
  81. package/src/commands/domain/install.ts +81 -50
  82. package/src/commands/domain/list.ts +4 -8
  83. package/src/commands/domain/publish.ts +9 -31
  84. package/src/commands/get.ts +32 -65
  85. package/src/commands/identity/__tests__/register.test.ts +93 -0
  86. package/src/commands/identity/create.ts +2 -2
  87. package/src/commands/identity/delete.ts +2 -2
  88. package/src/commands/identity/export.ts +7 -33
  89. package/src/commands/identity/import.ts +21 -70
  90. package/src/commands/identity/list.ts +2 -2
  91. package/src/commands/identity/register.ts +148 -117
  92. package/src/commands/identity/sync.ts +2 -2
  93. package/src/commands/identity/unsync.ts +2 -2
  94. package/src/commands/identity/use.ts +2 -2
  95. package/src/commands/identity/whoami.ts +2 -2
  96. package/src/commands/idp/add.ts +1 -1
  97. package/src/commands/idp/list.ts +1 -1
  98. package/src/commands/idp/refresh.ts +1 -1
  99. package/src/commands/idp/remove.ts +2 -2
  100. package/src/commands/idp/show.ts +1 -1
  101. package/src/commands/instance/active.ts +2 -2
  102. package/src/commands/instance/bookmark.ts +8 -2
  103. package/src/commands/instance/create.ts +1 -1
  104. package/src/commands/instance/delete.ts +4 -10
  105. package/src/commands/instance/forget.ts +1 -1
  106. package/src/commands/instance/list.ts +3 -3
  107. package/src/commands/instance/status.ts +5 -7
  108. package/src/commands/instance/use.ts +3 -3
  109. package/src/commands/logs.ts +152 -279
  110. package/src/commands/ls.ts +78 -204
  111. package/src/commands/mutate.ts +70 -139
  112. package/src/commands/query.ts +100 -278
  113. package/src/commands/session/analyze.ts +1 -1
  114. package/src/commands/session/list.ts +1 -1
  115. package/src/commands/setup.ts +1 -1
  116. package/src/commands/status.ts +1 -1
  117. package/src/commands/studio.ts +1 -1
  118. package/src/commands/token.ts +26 -21
  119. package/src/commands/update.ts +1 -1
  120. package/src/commands/use.ts +2 -3
  121. package/src/commands/view-serve.ts +1 -1
  122. package/src/commands/view.ts +67 -109
  123. package/src/connect-core.test.ts +38 -0
  124. package/src/connect-core.ts +42 -0
  125. package/src/connection/.spec/api.d.ts +111 -0
  126. package/src/connection/.spec/architecture.md +41 -0
  127. package/src/connection/.spec/capabilities/connection.ts +13 -0
  128. package/src/connection/.spec/examples/call.ts +7 -0
  129. package/src/connection/.spec/flows/command.ts +20 -0
  130. package/src/connection/.spec/flows/session.ts +61 -0
  131. package/src/connection/.spec/laws/connection.ts +181 -0
  132. package/src/connection/.spec/layout.ts +19 -0
  133. package/src/{kernel → connection}/__tests__/auth.test.ts +26 -2
  134. package/src/connection/__tests__/ca-fetch.test.ts +53 -0
  135. package/src/connection/__tests__/call.test.ts +17 -0
  136. package/src/connection/__tests__/credential.test.ts +109 -0
  137. package/src/connection/__tests__/errors.test.ts +96 -0
  138. package/src/connection/__tests__/exchange.test.ts +224 -0
  139. package/src/connection/__tests__/fixtures/localhost-cert.pem +19 -0
  140. package/src/connection/__tests__/fixtures/localhost-key.base64 +1 -0
  141. package/src/connection/__tests__/managed.test.ts +39 -0
  142. package/src/connection/__tests__/self.test.ts +51 -0
  143. package/src/connection/__tests__/session.test.ts +140 -0
  144. package/src/connection/__tests__/target.test.ts +93 -0
  145. package/src/{kernel → connection}/auth.ts +8 -8
  146. package/src/connection/call.ts +7 -0
  147. package/src/{kernel/run.ts → connection/command.ts} +22 -13
  148. package/src/connection/credential.ts +114 -0
  149. package/src/{kernel → connection}/errors.ts +32 -9
  150. package/src/connection/exchange.ts +274 -0
  151. package/src/connection/index.ts +8 -0
  152. package/src/connection/self.ts +120 -0
  153. package/src/connection/session.ts +176 -0
  154. package/src/connection/target.ts +111 -0
  155. package/src/connection/tsconfig.json +6 -0
  156. package/src/graph/.spec/api.d.ts +34 -0
  157. package/src/graph/.spec/laws/documents.ts +24 -0
  158. package/src/graph/.spec/laws/projection.ts +13 -0
  159. package/src/graph/.spec/layout.ts +6 -0
  160. package/src/graph/__tests__/mutation.test.ts +43 -0
  161. package/src/graph/__tests__/projection.test.ts +22 -0
  162. package/src/graph/__tests__/query.test.ts +154 -0
  163. package/src/graph/index.ts +3 -0
  164. package/src/graph/mutation.ts +18 -0
  165. package/src/graph/projection.ts +21 -0
  166. package/src/graph/query.ts +108 -0
  167. package/src/graph/tsconfig.json +6 -0
  168. package/src/identity/.history/ard/bootstrap-root-transfer.md +57 -0
  169. package/src/identity/.history/ard/domain-mediated-registration.md +36 -0
  170. package/src/identity/.spec/api.d.ts +124 -0
  171. package/src/identity/.spec/architecture.md +33 -0
  172. package/src/identity/.spec/capabilities/identity.ts +7 -0
  173. package/src/identity/.spec/flows/bootstrap-root.ts +79 -0
  174. package/src/identity/.spec/flows/domain-mediated-registration.ts +51 -0
  175. package/src/identity/.spec/flows/import.ts +29 -0
  176. package/src/identity/.spec/laws/identity.ts +56 -0
  177. package/src/identity/.spec/layout.ts +13 -0
  178. package/src/identity/.spec/schemas/identity-export-v1.schema.json +25 -0
  179. package/src/identity/__tests__/fixtures/registry-journey.ts +53 -0
  180. package/src/identity/__tests__/registration.test.ts +64 -0
  181. package/src/identity/__tests__/registry.test.ts +70 -0
  182. package/src/identity/__tests__/transfer.test.ts +198 -0
  183. package/src/identity/index.ts +23 -0
  184. package/src/identity/registration.ts +72 -0
  185. package/src/identity/registry.ts +172 -0
  186. package/src/identity/transfer.ts +187 -0
  187. package/src/identity/tsconfig.json +6 -0
  188. package/src/index.ts +1 -0
  189. package/src/keys/.spec/api.d.ts +74 -0
  190. package/src/keys/.spec/architecture.md +13 -0
  191. package/src/keys/.spec/laws/keys.ts +43 -0
  192. package/src/keys/.spec/layout.ts +6 -0
  193. package/src/keys/__tests__/algorithm.test.ts +39 -0
  194. package/src/keys/__tests__/keys.test.ts +168 -0
  195. package/src/keys/algorithm.ts +33 -0
  196. package/src/keys/credential.ts +112 -0
  197. package/src/keys/index.ts +14 -0
  198. package/src/keys/pair.ts +219 -0
  199. package/src/keys/tsconfig.json +6 -0
  200. package/src/lib/__tests__/admin-target.test.ts +67 -7
  201. package/src/lib/__tests__/binary.test.ts +2 -3
  202. package/src/lib/__tests__/command-dx.test.ts +2 -2
  203. package/src/lib/__tests__/config.test.ts +3 -2
  204. package/src/lib/__tests__/idp.test.ts +4 -6
  205. package/src/lib/__tests__/instance-target.test.ts +7 -4
  206. package/src/lib/__tests__/local-status.test.ts +1 -1
  207. package/src/lib/__tests__/log.test.ts +31 -0
  208. package/src/lib/__tests__/meta.test.ts +55 -0
  209. package/src/lib/__tests__/sdk-deps.test.ts +1 -1
  210. package/src/lib/__tests__/self.test.ts +8 -230
  211. package/src/lib/__tests__/use-target.test.ts +1 -1
  212. package/src/lib/__tests__/view-open-intent.test.ts +78 -104
  213. package/src/lib/__tests__/view-session.test.ts +99 -0
  214. package/src/lib/admin-domain.ts +39 -25
  215. package/src/lib/admin-instance.ts +38 -43
  216. package/src/lib/admin-target.ts +67 -13
  217. package/src/lib/binary.ts +13 -34
  218. package/src/lib/browser.ts +1 -1
  219. package/src/{kernel → lib}/ca-fetch.ts +35 -27
  220. package/src/lib/config.ts +1 -1
  221. package/src/lib/idp-session.ts +1 -1
  222. package/src/lib/idp.ts +3 -8
  223. package/src/lib/instance-target.ts +12 -8
  224. package/src/lib/instance.ts +34 -2
  225. package/src/lib/local-status.ts +2 -2
  226. package/src/lib/log.ts +3 -1
  227. package/src/lib/login-flow.ts +32 -5
  228. package/src/lib/meta.ts +15 -11
  229. package/src/lib/provision-instance.ts +4 -12
  230. package/src/lib/self.ts +5 -147
  231. package/src/lib/update.ts +1 -1
  232. package/src/lib/use-target.ts +1 -1
  233. package/src/lib/validation.ts +2 -2
  234. package/src/lib/view/open-intent.ts +7 -37
  235. package/src/lib/view/port-allocation.ts +1 -1
  236. package/src/lib/view/resolve.ts +52 -45
  237. package/src/lib/view/server.ts +16 -33
  238. package/src/lib/view/session.ts +51 -22
  239. package/src/paths/.spec/api.d.ts +13 -0
  240. package/src/paths/.spec/architecture.md +5 -0
  241. package/src/paths/.spec/layout.ts +3 -0
  242. package/src/paths/index.ts +13 -0
  243. package/src/program/.spec/api.d.ts +42 -0
  244. package/src/program/.spec/architecture.md +18 -0
  245. package/src/program/.spec/laws/program.ts +29 -0
  246. package/src/program/.spec/layout.ts +14 -0
  247. package/src/program/__tests__/program.test.ts +359 -0
  248. package/src/program/build.ts +190 -0
  249. package/src/program/command.ts +42 -0
  250. package/src/program/index.ts +2 -0
  251. package/src/program/options.ts +40 -0
  252. package/src/{registry.ts → program/registry.ts} +5 -1
  253. package/src/program/tsconfig.json +6 -0
  254. package/src/setup/steps/admin.ts +18 -3
  255. package/src/setup/steps/instance.ts +1 -1
  256. package/src/state/.spec/api.d.ts +133 -0
  257. package/src/state/.spec/architecture.md +31 -0
  258. package/src/state/.spec/capabilities/state.ts +7 -0
  259. package/src/state/.spec/flows/identity-update.ts +22 -0
  260. package/src/state/.spec/laws/state.ts +73 -0
  261. package/src/state/.spec/layout.ts +14 -0
  262. package/src/state/__tests__/exchange-credentials.test.ts +188 -0
  263. package/src/state/__tests__/files.test.ts +113 -0
  264. package/src/state/__tests__/fixtures/identity-transition.ts +37 -0
  265. package/src/state/__tests__/identities.test.ts +142 -0
  266. package/src/state/__tests__/paths.test.ts +27 -0
  267. package/src/state/exchange-credentials.ts +219 -0
  268. package/src/state/files.ts +129 -0
  269. package/src/state/identities.ts +236 -0
  270. package/src/state/index.ts +29 -0
  271. package/src/state/paths.ts +61 -0
  272. package/src/state/tsconfig.json +6 -0
  273. package/src/telemetry/__tests__/redact.test.ts +3 -3
  274. package/src/telemetry/__tests__/trigger.test.ts +1 -1
  275. package/src/telemetry/settings.ts +1 -1
  276. package/src/telemetry/store.ts +1 -1
  277. package/src/test-utils.ts +1 -1
  278. package/studio/client/dist/assets/{elk-api-DVw5WDTH.js → elk-api-D0cBetPW.js} +1 -1
  279. package/studio/client/dist/assets/index-Dspir4w7.js +81 -0
  280. package/studio/client/dist/assets/{index-Dl709Ra1.js → index-bVD2KJgz.js} +4 -4
  281. package/studio/client/dist/index.html +1 -1
  282. package/studio/package.json +10 -1
  283. package/studio/server/introspect/extractor.ts +1 -1
  284. package/studio/server/state/views.test.ts +3 -7
  285. package/studio/server/state/views.ts +23 -30
  286. package/tsconfig.json +1 -1
  287. package/viewer/dist/main.js +65 -39
  288. package/src/command.ts +0 -42
  289. package/src/commands/__tests__/help-contract.test.ts +0 -164
  290. package/src/kernel/__tests__/client-owned-lookup.test.ts +0 -51
  291. package/src/kernel/__tests__/errors.test.ts +0 -43
  292. package/src/kernel/__tests__/expand.test.ts +0 -123
  293. package/src/kernel/client.ts +0 -214
  294. package/src/kernel/expand.ts +0 -192
  295. package/src/kernel/graph.ts +0 -96
  296. package/src/kernel/index.ts +0 -29
  297. package/src/kernel/options.ts +0 -22
  298. package/src/kernel/types.ts +0 -14
  299. package/src/lib/__tests__/domain-identity.test.ts +0 -60
  300. package/src/lib/__tests__/fs-atomic.test.ts +0 -104
  301. package/src/lib/__tests__/identity.test.ts +0 -79
  302. package/src/lib/__tests__/keys.test.ts +0 -129
  303. package/src/lib/domain-identity.ts +0 -49
  304. package/src/lib/env.ts +0 -49
  305. package/src/lib/fs-atomic.ts +0 -126
  306. package/src/lib/identity.ts +0 -256
  307. package/src/lib/keys.ts +0 -294
  308. package/src/lib/paths.ts +0 -11
  309. package/src/program.ts +0 -213
  310. package/studio/client/dist/assets/index-CTbkDp3z.js +0 -81
@@ -1,319 +1,141 @@
1
- import { getInputSchema, K } from '@astrale-os/kernel-core'
2
- import chalk from 'chalk'
1
+ import type { QueryDirection } from '@astrale-os/sdk/query'
3
2
 
4
- import type { CommandDefinition } from '../command'
5
- import type { GetResultWire, KernelCommandOpts, QueryASTInput, SelfExpansionMeta } from '../kernel'
3
+ import { readFile } from 'node:fs/promises'
6
4
 
7
- import { bindGraph, expandSelfInPath, runKernelCommand, withSelfHint } from '../kernel'
5
+ import type { KernelCommandOpts, SelfExpansionMeta } from '../connection'
6
+ import type { CommandDefinition } from '../program/index'
7
+
8
+ import { expandSelfInPath, runKernelCommand, withSelfHint } from '../connection'
9
+ import { prepareQuery, type QueryCommandInput } from '../graph/index'
8
10
  import { log } from '../lib/log'
9
11
  import { isMachine, output } from '../lib/output'
10
12
 
11
13
  type QueryOpts = KernelCommandOpts & {
12
- depth?: string
13
- children?: string
14
- edges?: string
15
14
  ast?: string
16
- cypher?: string
15
+ file?: string
16
+ definition?: string
17
+ edge?: string
18
+ direction?: QueryDirection
19
+ limit?: string
20
+ cursor?: string
17
21
  }
18
22
 
19
- type QueryMode =
20
- | { kind: 'cypher'; cypher: string }
21
- | { kind: 'ast'; ast: QueryASTInput }
22
- | { kind: 'roots'; roots: string[]; meta: SelfExpansionMeta | undefined; query: BuiltQuery }
23
-
24
- export async function queryCommand(paths: string[], opts: QueryOpts): Promise<void> {
25
- let mode: QueryMode
23
+ export async function queryCommand(sources: string[], opts: QueryOpts): Promise<void> {
24
+ let input: QueryCommandInput
25
+ let meta: SelfExpansionMeta | undefined
26
26
  try {
27
- mode = await parseMode(paths, opts)
28
- } catch (e) {
29
- log.error(e instanceof Error ? e.message : 'Invalid arguments')
27
+ const ast = await readAst(opts)
28
+ if (ast === undefined) {
29
+ const expanded = await Promise.all(sources.map((source) => expandSelfInPath(source, opts)))
30
+ input = {
31
+ sources: expanded.map(({ path }) => path),
32
+ definition: opts.definition,
33
+ edge: opts.edge,
34
+ direction: opts.direction,
35
+ limit: opts.limit,
36
+ cursor: opts.cursor,
37
+ }
38
+ meta = expanded.find((entry) => entry.meta !== undefined)?.meta
39
+ } else {
40
+ input = {
41
+ sources,
42
+ ast,
43
+ definition: opts.definition,
44
+ edge: opts.edge,
45
+ direction: opts.direction,
46
+ limit: opts.limit,
47
+ cursor: opts.cursor,
48
+ }
49
+ }
50
+ } catch (error) {
51
+ log.error(error instanceof Error ? error.message : 'Invalid query')
30
52
  process.exit(1)
31
- return
32
53
  }
33
54
 
34
- if (mode.kind === 'cypher') {
35
- await runKernelCommand({
36
- opts,
37
- label: 'Query',
38
- fn: (ctx) => ctx.client.call(K.$.f('query').path.domain.raw, { cypher: mode.cypher }),
39
- format: (result, fmtOpts) => output(result, fmtOpts),
40
- })
41
- return
55
+ let prepared
56
+ try {
57
+ prepared = prepareQuery(input)
58
+ } catch (error) {
59
+ log.error(error instanceof Error ? error.message : 'Invalid Query V6 document')
60
+ process.exit(1)
42
61
  }
43
62
 
44
- await runKernelCommand<GetResultWire>({
63
+ await runKernelCommand({
45
64
  opts,
46
- label: mode.kind === 'roots' ? 'Query ' + mode.roots.join(' ') : 'Query',
47
- fn: async (ctx) => {
48
- const read = () => bindGraph(ctx).query(mode.kind === 'roots' ? mode.query.ast : mode.ast)
49
- const result = mode.kind === 'roots' ? await withSelfHint(read, mode.meta) : await read()
50
- return result.wire
51
- },
52
- format: (result, fmtOpts) => {
53
- output(result, fmtOpts)
54
- if (result.next && !isMachine(fmtOpts)) printCursorFooter(result.next)
65
+ label: 'Query',
66
+ fn: ({ graph }) => withSelfHint(() => graph.query(prepared.ast, { page: prepared.page }), meta),
67
+ format: (response, format) => {
68
+ output(response.result, format)
69
+ if (response.page.next && !isMachine(format)) {
70
+ process.stderr.write(` cursor: ${response.page.next}\n`)
71
+ }
55
72
  },
56
73
  })
57
74
  }
58
75
 
59
- async function parseMode(paths: string[], opts: QueryOpts): Promise<QueryMode> {
60
- const rootsInput = paths ?? []
61
- const hasRoots = rootsInput.length > 0
62
- const hasAst = opts.ast !== undefined
63
- const hasCypher = opts.cypher !== undefined
64
- const hasSelectors =
65
- opts.depth !== undefined || opts.children !== undefined || opts.edges !== undefined
66
-
67
- if (hasCypher) {
68
- if (hasAst || hasRoots || hasSelectors) {
69
- throw new Error('--cypher cannot be used with roots, --ast, --depth, --children, or --edges')
70
- }
71
- return { kind: 'cypher', cypher: opts.cypher as string }
72
- }
73
-
74
- if (hasAst) {
75
- if (hasRoots || hasSelectors) {
76
- throw new Error('--ast cannot be used with positional roots or --depth/--children/--edges')
77
- }
78
- return { kind: 'ast', ast: parseAst(opts.ast as string) }
76
+ async function readAst(opts: QueryOpts): Promise<unknown | undefined> {
77
+ if (opts.ast !== undefined && opts.file !== undefined) {
78
+ throw new TypeError('--ast and --file are mutually exclusive')
79
79
  }
80
-
81
- if (!hasRoots) {
80
+ if (opts.ast !== undefined) return parseJson(opts.ast, '--ast')
81
+ if (opts.file === undefined) return undefined
82
+ let raw: string
83
+ try {
84
+ raw = await readFile(opts.file, 'utf8')
85
+ } catch (error) {
82
86
  throw new Error(
83
- 'Usage: astrale query <paths...> [--depth <n>] [--children <json>] [--edges <json>] | --ast <json> | --cypher <query>',
87
+ `Cannot read --file ${opts.file}: ${error instanceof Error ? error.message : error}`,
84
88
  )
85
89
  }
86
-
87
- const { roots, meta } = await expandRoots(rootsInput, opts)
88
- return { kind: 'roots', roots, meta, query: buildQuery(roots, opts) }
89
- }
90
-
91
- function parseAst(raw: string): QueryASTInput {
92
- let parsed: unknown
93
- try {
94
- parsed = JSON.parse(raw)
95
- } catch {
96
- throw new Error('--ast must be JSON: ' + raw)
97
- }
98
- if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
99
- throw new Error('--ast must be a JSON object')
100
- }
101
- return parsed as QueryASTInput
102
- }
103
-
104
- async function expandRoots(
105
- paths: string[],
106
- opts: QueryOpts,
107
- ): Promise<{ roots: string[]; meta: SelfExpansionMeta | undefined }> {
108
- const roots: string[] = []
109
- let meta: SelfExpansionMeta | undefined
110
- for (const p of paths) {
111
- const expanded = await expandSelfInPath(p, opts)
112
- roots.push(expanded.path)
113
- if (!meta && expanded.meta) meta = expanded.meta
114
- }
115
- return { roots, meta }
116
- }
117
-
118
- type QueryDir = 'in' | 'out' | 'both'
119
- type QueryOrder = { by: string; dir: 'asc' | 'desc' }
120
- type ChildrenSelector = { classes?: string[]; limit?: number; cursor?: string; order?: QueryOrder }
121
- type EdgeSelector = {
122
- as?: string
123
- classes?: string[]
124
- direction?: QueryDir
125
- limit?: number
126
- cursor?: string
127
- order?: QueryOrder
128
- }
129
- type BuiltQuery = { ast: QueryASTInput; depth: number; hasEdges: boolean }
130
-
131
- function buildQuery(roots: string[], opts: QueryOpts): BuiltQuery {
132
- const depth = opts.depth !== undefined ? parseRange('--depth', opts.depth, 0, 5) : 0
133
- const children =
134
- opts.children !== undefined
135
- ? parseSelector<ChildrenSelector>('--children', opts.children, getInputSchema.shape.children)
136
- : undefined
137
- const edges =
138
- opts.edges !== undefined
139
- ? parseSelector<EdgeSelector | EdgeSelector[]>(
140
- '--edges',
141
- opts.edges,
142
- getInputSchema.shape.edges,
143
- )
144
- : undefined
145
-
146
- const steps: NonNullable<QueryASTInput['steps']> = []
147
- if (depth > 0) steps.push({ expand: childExpand(depth, children) })
148
- edgeSelectors(edges).forEach((selector, index) => {
149
- steps.push({ expand: edgeExpand(selector, index) })
150
- })
151
-
152
- return {
153
- ast: { version: 1, from: roots, ...(steps.length > 0 ? { steps } : {}) },
154
- depth,
155
- hasEdges: edges !== undefined,
156
- }
157
- }
158
-
159
- function childExpand(depth: number, children: ChildrenSelector | undefined) {
160
- return {
161
- edge: 'has_parent',
162
- dir: 'in' as const,
163
- depth,
164
- ...(children?.classes !== undefined ? { filter: { class: children.classes } } : {}),
165
- ...pageFields(children),
166
- ...(children?.order !== undefined ? { order: children.order } : {}),
167
- }
168
- }
169
-
170
- function edgeExpand(selector: EdgeSelector, index: number) {
171
- return {
172
- ...(selector.classes !== undefined ? { edge: selector.classes } : {}),
173
- dir: selector.direction ?? 'both',
174
- as: selector.as ?? 'e' + index,
175
- ...pageFields(selector),
176
- ...(selector.order !== undefined ? { order: selector.order } : {}),
177
- }
178
- }
179
-
180
- function pageFields(selector: { limit?: number; cursor?: string } | undefined) {
181
- if (selector?.limit === undefined && selector?.cursor === undefined) return {}
182
- return {
183
- page: {
184
- ...(selector.limit !== undefined ? { limit: selector.limit } : {}),
185
- ...(selector.cursor !== undefined ? { cursor: selector.cursor } : {}),
186
- },
187
- }
188
- }
189
-
190
- function edgeSelectors(edges: EdgeSelector | EdgeSelector[] | undefined): EdgeSelector[] {
191
- if (edges === undefined) return []
192
- return Array.isArray(edges) ? edges : [edges]
193
- }
194
-
195
- function parseRange(flag: string, raw: string, min: number, max: number): number {
196
- const n = Number(raw)
197
- if (!Number.isInteger(n) || n < min || n > max) {
198
- throw new Error(flag + ' needs an integer in [' + min + ', ' + max + '], got "' + raw + '"')
199
- }
200
- return n
90
+ return parseJson(raw, opts.file)
201
91
  }
202
92
 
203
- type SelectorIssue = { readonly path: readonly PropertyKey[]; readonly message: string }
204
- type SelectorSchema = {
205
- safeParse(
206
- value: unknown,
207
- ): { success: true } | { success: false; error: { issues: readonly SelectorIssue[] } }
208
- }
209
-
210
- function parseSelector<T>(flag: string, raw: string, schema: SelectorSchema): T {
211
- let parsed: unknown
93
+ function parseJson(raw: string, source: string): unknown {
212
94
  try {
213
- parsed = JSON.parse(raw)
95
+ return JSON.parse(raw)
214
96
  } catch {
215
- throw new Error(flag + ' must be JSON: ' + raw)
216
- }
217
- if (parsed === null || typeof parsed !== 'object') {
218
- throw new Error(
219
- flag + ' must be a JSON selector object' + (flag === '--edges' ? ' or array' : ''),
220
- )
221
- }
222
- const check = schema.safeParse(parsed)
223
- if (!check.success) {
224
- const detail = check.error.issues
225
- .map((i) => (i.path.join('.') || '(root)') + ': ' + i.message)
226
- .join('; ')
227
- throw new Error(flag + ' invalid selector: ' + detail)
228
- }
229
- return parsed as T
230
- }
231
-
232
- function printCursorFooter(next: NonNullable<GetResultWire['next']>): void {
233
- const entries = Object.entries(next)
234
- if (entries.length === 1) {
235
- const cursors = entries[0]?.[1]
236
- if (cursors?.children) {
237
- process.stdout.write(
238
- chalk.dim(' more: --children \'{"cursor":"' + cursors.children + '"}\'\n'),
239
- )
240
- }
241
- for (const [alias, cursor] of Object.entries(cursors?.edges ?? {})) {
242
- process.stdout.write(
243
- chalk.dim(
244
- ' more edges[' +
245
- alias +
246
- ']: --edges \'{"as":"' +
247
- alias +
248
- '","cursor":"' +
249
- cursor +
250
- '"}\'\n',
251
- ),
252
- )
253
- }
254
- return
97
+ throw new TypeError(`${source} must contain valid JSON`)
255
98
  }
256
- process.stdout.write(
257
- chalk.dim(' more results - per-root cursors in .next (page each root by --cursor)\n'),
258
- )
259
99
  }
260
100
 
261
101
  export default {
262
102
  name: 'query',
263
- description: 'Run a structured graph read',
264
- afterHelpText: [
265
- '',
266
- 'Behavior:',
267
- ' Structured read door for the query AST. Positional roots build a v1 AST',
268
- ' with optional child and edge expansion, then lower through function.get',
269
- ' today. A true query syscall may back this command later.',
270
- '',
271
- ' Output is always the full GraphData envelope { nodes, edges, aliases }',
272
- ' with .roots and .next when returned. On a TTY, cursor footers are printed',
273
- ' when .next has more pages.',
274
- '',
275
- ' --children takes { classes?, limit?, cursor?, order? } and shapes the',
276
- ' depth-1 children page (needs --depth >= 1 to bite). --edges takes an edge',
277
- ' selector, or a JSON array of selectors.',
278
- '',
279
- ' --ast (experimental) accepts a raw QueryASTInput JSON object. The AST shape',
280
- ' is not a stable contract yet — prefer the flags above. @self is not expanded',
281
- ' inside --ast JSON.',
282
- '',
283
- ' --cypher is a read-only escape hatch. The kernel rejects write keywords',
284
- ' such as CREATE, DELETE, SET, MERGE, REMOVE, and DETACH.',
285
- '',
286
- 'Examples:',
287
- ' $ astrale query / --depth 1',
288
- ' $ astrale query /a /b --edges \'{"direction":"both"}\'',
289
- ' $ astrale query /kernel.astrale.ai --depth 2 --children \'{"classes":["/:kernel.astrale.ai:class.Folder"]}\'',
290
- " $ astrale query --cypher 'MATCH (n) RETURN count(n) AS total'",
291
- '',
292
- ].join('\n'),
293
- arguments: [
294
- {
295
- name: 'paths...',
296
- description: 'One or more root paths (/domain/Class) or IDs (@nodeId)',
297
- required: false,
298
- },
299
- ],
103
+ description: 'Run one canonical Query V6 graph read',
104
+ afterHelpText: `
105
+ Behavior:
106
+ Positional Paths and --definition author a finite Query V6 read. --edge adds
107
+ one exact Edge-Class expansion; --direction defaults to outgoing. --ast and
108
+ --file accept a complete canonical astrale.graph.query/v6 document, including
109
+ Property ordering and Node or Edge reference/value projections. --cursor resumes
110
+ one caller-bound query scope.
111
+
112
+ Legacy depth/children selector JSON and raw Cypher are not portable Kernel
113
+ V2 query contracts and are not accepted.
114
+
115
+ Examples:
116
+ $ astrale query /:notes.example.dev:class.Note --limit 50
117
+ $ astrale query --definition /:notes.example.dev:class.Note --limit 50
118
+ $ astrale query @note --edge /:notes.example.dev:class.references --direction outgoing --limit 25
119
+ $ astrale query --file query.v6.json --cursor "$CURSOR"
120
+ `,
121
+ arguments: [{ name: 'sources...', description: 'Canonical source Paths', required: false }],
300
122
  options: [
301
- { flags: '--depth <n>', description: 'Subtree depth to fetch (0-5, default 0)' },
302
- {
303
- flags: '--children <json>',
304
- description: 'Children selector { classes?, limit?, cursor?, order? } (needs --depth >= 1)',
305
- },
123
+ { flags: '--ast <json>', description: 'Canonical Query V6 JSON document' },
124
+ { flags: '-f, --file <path>', description: 'Read a canonical Query V6 document from a file' },
306
125
  {
307
- flags: '--edges <json>',
308
- description: 'Edge selector (or JSON array of selectors) to include',
126
+ flags: '--definition <path>',
127
+ description: 'Select Nodes implementing one exact Class or Interface',
309
128
  },
129
+ { flags: '--edge <class>', description: 'Expand one exact Edge Class' },
310
130
  {
311
- flags: '--ast <json>',
312
- description: 'Raw QueryASTInput JSON object (experimental, unstable shape)',
131
+ flags: '--direction <direction>',
132
+ description: 'Edge direction (requires --edge)',
133
+ choices: ['outgoing', 'incoming', 'incident'],
313
134
  },
314
- { flags: '--cypher <query>', description: 'Read-only Cypher escape hatch' },
135
+ { flags: '--limit <n>', description: 'Finite selected binding limit (default: 100)' },
136
+ { flags: '--cursor <token>', description: 'Resume one live query scope' },
315
137
  ],
316
- action: async (paths, opts) => {
317
- await queryCommand(Array.isArray(paths) ? paths : [], opts as QueryOpts)
138
+ action: async (sources, opts) => {
139
+ await queryCommand((sources as string[] | undefined) ?? [], opts as QueryOpts)
318
140
  },
319
141
  } satisfies CommandDefinition
@@ -1,6 +1,6 @@
1
1
  import chalk from 'chalk'
2
2
 
3
- import type { CommandDefinition } from '../../command'
3
+ import type { CommandDefinition } from '../../program/index'
4
4
 
5
5
  import { log } from '../../lib/log'
6
6
  import { analyzeSession } from '../../telemetry/analyze'
@@ -1,6 +1,6 @@
1
1
  import chalk from 'chalk'
2
2
 
3
- import type { CommandDefinition } from '../../command'
3
+ import type { CommandDefinition } from '../../program/index'
4
4
 
5
5
  import { log } from '../../lib/log'
6
6
  import { isMachine, output, RAW_OUTPUT_OPTIONS } from '../../lib/output'
@@ -1,4 +1,4 @@
1
- import type { CommandDefinition } from '../command'
1
+ import type { CommandDefinition } from '../program/index'
2
2
 
3
3
  import { ADMIN_TARGET_OPTIONS } from '../lib/admin-target'
4
4
  import { fatal } from '../lib/log'
@@ -1,6 +1,6 @@
1
1
  import chalk from 'chalk'
2
2
 
3
- import type { CommandDefinition } from '../command'
3
+ import type { CommandDefinition } from '../program/index'
4
4
 
5
5
  import { readLocalStatus } from '../lib/local-status'
6
6
  import { log } from '../lib/log'
@@ -3,7 +3,7 @@ import type { ChildProcess } from 'node:child_process'
3
3
  import { existsSync, realpathSync } from 'node:fs'
4
4
  import { dirname, join, resolve } from 'node:path'
5
5
 
6
- import type { CommandDefinition } from '../command'
6
+ import type { CommandDefinition } from '../program/index'
7
7
 
8
8
  import { fatal, log } from '../lib/log'
9
9
  import { isMachine, output, RAW_OUTPUT_OPTIONS, type RawOutputOpts } from '../lib/output'
@@ -1,7 +1,9 @@
1
- import type { CommandDefinition } from '../command'
2
- import type { KernelCommandOpts } from '../kernel'
1
+ import { issuer } from '@astrale-os/sdk/auth'
3
2
 
4
- import { runKernelCommand } from '../kernel'
3
+ import type { KernelCommandOpts } from '../connection'
4
+ import type { CommandDefinition } from '../program/index'
5
+
6
+ import { runKernelCommand } from '../connection'
5
7
  import { log } from '../lib/log'
6
8
 
7
9
  /**
@@ -17,19 +19,23 @@ export type TokenOpts = KernelCommandOpts & {
17
19
  }
18
20
 
19
21
  export async function tokenCommand(opts: TokenOpts): Promise<void> {
20
- if (opts.for && !opts.as) opts.as = opts.for
22
+ const commandOpts: TokenOpts = opts.for && !opts.as ? { ...opts, as: opts.for } : opts
21
23
  await runKernelCommand<string>({
22
- opts,
24
+ opts: commandOpts,
23
25
  label: 'Minting delegation token',
24
26
  fn: async (ctx) => {
25
- const audience = opts.audience ?? ''
26
- const parsedTtl = Number(opts.ttl)
27
+ const audience =
28
+ commandOpts.audience === undefined
29
+ ? ctx.target.kernelIssuer
30
+ : issuer.accept(commandOpts.audience)
31
+ const parsedTtl = Number(commandOpts.ttl)
27
32
  const ttl = Number.isFinite(parsedTtl) && parsedTtl > 0 ? parsedTtl : 3600
28
- const result = await ctx.client.as(ctx.credential).auth.delegate({
33
+ const self = await ctx.auth.whoami()
34
+ return ctx.auth.delegate(self.id, {
29
35
  audience,
30
- ttl,
36
+ ttlSeconds: ttl,
37
+ attenuation: { kind: 'identity', self: true },
31
38
  })
32
- return result
33
39
  },
34
40
  format: (token, fmtOpts, isRaw) => {
35
41
  if (isRaw) {
@@ -47,24 +53,23 @@ export default {
47
53
  description: 'Mint a fresh delegation token for the active instance + identity',
48
54
  afterHelpText: `
49
55
  Behavior:
50
- Default ttl 3600s, audience empty. The result is a two-layer
51
- envelope: an outer JWT signed by the kernel system key
52
- (sub __system__) wrapping an inner ES256 delegation credential for
53
- the identity. The token aud must match the worker's expected
54
- audience or the worker rejects it. --for is an alias of --as.
56
+ Delegates the selected authenticated identity for 3600 seconds by default.
57
+ The default audience is the target Kernel issuer; choose --audience when the
58
+ credential is intended for another service. --for is an alias of --as.
55
59
 
56
- What this token is FOR — worker-direct HTTP calls:
57
- Use it as a Bearer token against a domain worker's own URL
58
- (curl/fetch to its remote functions). It carries NO .grant claim,
59
- so it CANNOT drive a raw kernel ClientSession — for kernel calls
60
- use 'astrale call' (which signs per-call) instead.
60
+ The receiver must admit the exact token audience. A Kernel-audience token can
61
+ be reused with --creds; a service-audience token can be sent as a Bearer token
62
+ to that service's authenticated endpoint.
61
63
 
62
64
  Examples:
63
65
  $ export TOKEN=$(astrale token --audience shell.astrale.ai --raw)
64
66
  $ astrale token --audience worker.example.com --for alice -i staging
65
67
  `,
66
68
  options: [
67
- { flags: '--audience <aud>', description: 'Token audience (defaults to empty)' },
69
+ {
70
+ flags: '--audience <aud>',
71
+ description: 'Token audience (default: target Kernel issuer)',
72
+ },
68
73
  { flags: '--ttl <sec>', description: 'TTL in seconds (default: 3600)' },
69
74
  { flags: '--for <identity>', description: 'Mint the token for this identity (alias of --as)' },
70
75
  ],
@@ -1,4 +1,4 @@
1
- import type { CommandDefinition } from '../command'
1
+ import type { CommandDefinition } from '../program/index'
2
2
 
3
3
  import pkg from '../../package.json' with { type: 'json' }
4
4
  import { fatal, log } from '../lib/log'
@@ -1,7 +1,6 @@
1
- import type { CommandDefinition } from '../command'
1
+ import type { CommandDefinition } from '../program/index'
2
2
 
3
- import { setDefault } from '../lib/identity'
4
- import { readIdentities } from '../lib/identity'
3
+ import { readIdentities, setDefault } from '../identity/index'
5
4
  import { readInstances } from '../lib/instance'
6
5
  import { fatal, log } from '../lib/log'
7
6
  import { resolveUseTarget } from '../lib/use-target'
@@ -1,7 +1,7 @@
1
1
  import { readFile } from 'node:fs/promises'
2
2
 
3
- import type { CommandDefinition } from '../command'
4
3
  import type { ViewServeConfig } from '../lib/view/session'
4
+ import type { CommandDefinition } from '../program/index'
5
5
 
6
6
  import { startViewServer } from '../lib/view/server'
7
7