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

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 (343) hide show
  1. package/README.md +80 -6
  2. package/dist/astrale.js +55471 -58674
  3. package/dist/public/connect-core.js +2158 -30706
  4. package/dist/public/keys/index.js +1016 -29541
  5. package/dist/public/paths/index.js +370 -28654
  6. package/dist/types/admin/contract.d.ts +26 -0
  7. package/dist/types/admin/instance/client.d.ts +20 -0
  8. package/dist/types/admin/instance/index.d.ts +2 -0
  9. package/dist/types/admin/instance/model.d.ts +6 -10
  10. package/dist/types/connection/auth.d.ts +3 -0
  11. package/dist/types/connection/call.d.ts +3 -0
  12. package/dist/types/connection/command.d.ts +27 -0
  13. package/dist/types/connection/credential.d.ts +14 -0
  14. package/dist/types/connection/errors.d.ts +1 -0
  15. package/dist/types/connection/exchange.d.ts +9 -0
  16. package/dist/types/connection/failure/classify.d.ts +2 -0
  17. package/dist/types/connection/failure/index.d.ts +5 -0
  18. package/dist/types/connection/failure/model.d.ts +25 -0
  19. package/dist/types/connection/failure/render.d.ts +3 -0
  20. package/dist/types/connection/index.d.ts +8 -0
  21. package/dist/types/connection/reasons.d.ts +37 -0
  22. package/dist/types/connection/self.d.ts +37 -0
  23. package/dist/types/connection/session.d.ts +31 -0
  24. package/dist/types/connection/target.d.ts +38 -0
  25. package/dist/types/errors.d.ts +1 -1
  26. package/dist/types/lib/admin-instance.d.ts +17 -0
  27. package/dist/types/lib/admin-target.d.ts +11 -36
  28. package/dist/types/lib/config.d.ts +13 -59
  29. package/dist/types/lib/failure-debug.d.ts +1 -0
  30. package/dist/types/lib/idp.d.ts +25 -173
  31. package/dist/types/lib/instance-target.d.ts +1 -1
  32. package/dist/types/lib/instance.d.ts +30 -88
  33. package/dist/types/lib/log.d.ts +5 -3
  34. package/dist/types/lib/output.d.ts +1 -1
  35. package/dist/types/lib/proc.d.ts +43 -0
  36. package/dist/types/lib/self.d.ts +9 -0
  37. package/dist/types/lib/update.d.ts +109 -0
  38. package/dist/types/lib/validation.d.ts +4 -1
  39. package/dist/types/state/exchange-credentials.d.ts +6 -2
  40. package/dist/types/state/files.d.ts +2 -0
  41. package/dist/types/state/index.d.ts +3 -2
  42. package/dist/types/state/paths.d.ts +2 -0
  43. package/dist/types/state/session-routes.d.ts +10 -0
  44. package/package.json +16 -19
  45. package/src/__tests__/fixtures/publication.ts +20 -0
  46. package/src/admin/.spec/architecture.md +12 -5
  47. package/src/admin/__tests__/fixture.ts +25 -0
  48. package/src/admin/catalog/.spec/api.d.ts +1 -3
  49. package/src/admin/catalog/.spec/architecture.md +5 -4
  50. package/src/admin/catalog/__tests__/client.test.ts +143 -69
  51. package/src/admin/catalog/client.ts +40 -54
  52. package/src/admin/catalog/model.ts +3 -4
  53. package/src/admin/contract.ts +47 -0
  54. package/src/admin/graph/.spec/api.d.ts +4 -10
  55. package/src/admin/graph/nodes.ts +1 -1
  56. package/src/admin/instance/.spec/api.d.ts +5 -9
  57. package/src/admin/instance/.spec/architecture.md +7 -7
  58. package/src/admin/instance/__tests__/client.test.ts +157 -175
  59. package/src/admin/instance/client.ts +39 -128
  60. package/src/admin/instance/index.ts +1 -2
  61. package/src/admin/instance/model.ts +12 -18
  62. package/src/commands/__tests__/admin-instance.test.ts +11 -8
  63. package/src/commands/__tests__/call-describe.test.ts +46 -33
  64. package/src/commands/__tests__/call.test.ts +34 -0
  65. package/src/commands/__tests__/domain-install-operation.test.ts +30 -22
  66. package/src/commands/__tests__/domain-install-owned.test.ts +1 -1
  67. package/src/commands/__tests__/domain-list.test.ts +5 -25
  68. package/src/commands/__tests__/install-direct.test.ts +115 -8
  69. package/src/commands/__tests__/install-identity-override.test.ts +6 -17
  70. package/src/commands/__tests__/instance-list-rows.test.ts +1 -1
  71. package/src/commands/__tests__/instance-status.test.ts +139 -0
  72. package/src/commands/__tests__/introspect-parse.test.ts +80 -1
  73. package/src/commands/__tests__/logs.test.ts +250 -2
  74. package/src/commands/__tests__/read-commands.test.ts +118 -10
  75. package/src/commands/__tests__/token-ttl.test.ts +49 -4
  76. package/src/commands/__tests__/update.test.ts +25 -3
  77. package/src/commands/__tests__/view.test.ts +50 -2
  78. package/src/commands/auth/logout.ts +2 -1
  79. package/src/commands/browser.ts +29 -0
  80. package/src/commands/call-describe.ts +60 -68
  81. package/src/commands/call.ts +71 -59
  82. package/src/commands/domain/install.ts +73 -46
  83. package/src/commands/domain/list.ts +1 -1
  84. package/src/commands/domain/publish.ts +14 -11
  85. package/src/commands/domain/uninstall.ts +2 -2
  86. package/src/commands/get.ts +15 -16
  87. package/src/commands/identity/__tests__/register.test.ts +3 -3
  88. package/src/commands/identity/register.ts +8 -8
  89. package/src/commands/instance/create.ts +8 -16
  90. package/src/commands/instance/delete.ts +12 -9
  91. package/src/commands/instance/list.ts +2 -2
  92. package/src/commands/instance/status.ts +66 -20
  93. package/src/commands/instance/use.ts +16 -12
  94. package/src/commands/introspect.ts +53 -41
  95. package/src/commands/logs.ts +123 -36
  96. package/src/commands/mutate.ts +6 -5
  97. package/src/commands/query.ts +35 -32
  98. package/src/commands/session/analyze.ts +26 -4
  99. package/src/commands/token.ts +42 -27
  100. package/src/commands/ui/__tests__/commands.test.ts +152 -0
  101. package/src/commands/ui/add.ts +51 -0
  102. package/src/commands/ui/doctor.ts +21 -0
  103. package/src/commands/ui/init.ts +38 -0
  104. package/src/commands/ui/list.ts +26 -0
  105. package/src/commands/ui/preset-apply.ts +19 -0
  106. package/src/commands/ui/preset-list.ts +12 -0
  107. package/src/commands/ui/shared.ts +25 -0
  108. package/src/commands/update.ts +89 -48
  109. package/src/commands/view.ts +82 -37
  110. package/src/connection/.spec/api.d.ts +7 -8
  111. package/src/connection/.spec/architecture.md +14 -5
  112. package/src/connection/.spec/flows/session.ts +2 -2
  113. package/src/connection/.spec/laws/connection.ts +6 -2
  114. package/src/connection/.spec/layout.ts +1 -0
  115. package/src/connection/__tests__/auth.test.ts +1 -0
  116. package/src/connection/__tests__/credential.test.ts +21 -1
  117. package/src/connection/__tests__/errors.test.ts +27 -20
  118. package/src/connection/__tests__/exchange.test.ts +64 -11
  119. package/src/connection/__tests__/failure-fixtures.ts +39 -0
  120. package/src/connection/__tests__/failure-safety.test.ts +75 -0
  121. package/src/connection/__tests__/self.test.ts +31 -11
  122. package/src/connection/__tests__/session.test.ts +8 -4
  123. package/src/connection/__tests__/target.test.ts +2 -0
  124. package/src/connection/auth.ts +13 -0
  125. package/src/connection/call.ts +1 -1
  126. package/src/connection/credential.ts +2 -2
  127. package/src/connection/errors.ts +1 -355
  128. package/src/connection/exchange.ts +110 -61
  129. package/src/connection/failure/classify.ts +110 -0
  130. package/src/connection/failure/index.ts +18 -0
  131. package/src/connection/failure/model.ts +28 -0
  132. package/src/connection/failure/render.ts +116 -0
  133. package/src/connection/reasons.ts +16 -0
  134. package/src/connection/self.ts +39 -21
  135. package/src/connection/session.ts +27 -9
  136. package/src/errors.ts +3 -2
  137. package/src/graph/.spec/api.d.ts +12 -5
  138. package/src/graph/.spec/layout.ts +9 -1
  139. package/src/graph/__tests__/mutation.test.ts +2 -2
  140. package/src/graph/__tests__/query.test.ts +25 -6
  141. package/src/graph/class.ts +30 -0
  142. package/src/graph/index.ts +1 -0
  143. package/src/graph/query.ts +21 -32
  144. package/src/identity/.spec/api.d.ts +2 -2
  145. package/src/identity/__tests__/fixtures/registry-journey.ts +13 -1
  146. package/src/identity/__tests__/registration.test.ts +1 -1
  147. package/src/identity/__tests__/registry.test.ts +4 -0
  148. package/src/identity/registration.ts +3 -3
  149. package/src/identity/registry.ts +2 -0
  150. package/src/keys/__tests__/keys.test.ts +4 -0
  151. package/src/keys/credential.ts +1 -0
  152. package/src/lib/__tests__/admin-target.test.ts +12 -0
  153. package/src/lib/__tests__/binary.test.ts +16 -1
  154. package/src/lib/__tests__/browser-retention.test.ts +212 -0
  155. package/src/lib/__tests__/command-dx.test.ts +1 -1
  156. package/src/lib/__tests__/config.test.ts +27 -0
  157. package/src/lib/__tests__/domain-publication.test.ts +10 -16
  158. package/src/lib/__tests__/idp.test.ts +34 -4
  159. package/src/lib/__tests__/instance-candidates.test.ts +1 -3
  160. package/src/lib/__tests__/instance-target.test.ts +7 -39
  161. package/src/lib/__tests__/log-errors.test.ts +64 -0
  162. package/src/lib/__tests__/skills.test.ts +809 -0
  163. package/src/lib/__tests__/studio-server-deps.test.ts +1 -1
  164. package/src/lib/__tests__/update.test.ts +264 -11
  165. package/src/lib/__tests__/view-assets.test.ts +25 -0
  166. package/src/lib/__tests__/view-external-open-intent.test.ts +150 -0
  167. package/src/lib/__tests__/view-external-open-origins.test.ts +27 -0
  168. package/src/lib/__tests__/view-open-intent.test.ts +0 -2
  169. package/src/lib/__tests__/view-server.test.ts +26 -3
  170. package/src/lib/__tests__/view-session.test.ts +2 -1
  171. package/src/lib/admin-instance.ts +14 -8
  172. package/src/lib/admin-target.ts +21 -2
  173. package/src/lib/binary.ts +22 -5
  174. package/src/lib/browser-retention.ts +210 -0
  175. package/src/lib/command-dx.ts +9 -9
  176. package/src/lib/config.ts +12 -1
  177. package/src/lib/domain-publication.ts +9 -7
  178. package/src/lib/failure-debug.ts +26 -0
  179. package/src/lib/idp.ts +34 -3
  180. package/src/lib/instance-candidates.ts +2 -2
  181. package/src/lib/instance-target.ts +3 -14
  182. package/src/lib/instance.ts +16 -11
  183. package/src/lib/log.ts +16 -9
  184. package/src/lib/output.ts +1 -1
  185. package/src/lib/proc.ts +7 -2
  186. package/src/lib/provision-instance.ts +34 -57
  187. package/src/lib/skills/lock.ts +117 -0
  188. package/src/lib/skills/sync.ts +814 -0
  189. package/src/lib/skills.ts +1 -52
  190. package/src/lib/update.ts +298 -45
  191. package/src/lib/validation.ts +2 -2
  192. package/src/lib/view/assets.ts +11 -2
  193. package/src/lib/view/external-open-intent.ts +41 -0
  194. package/src/lib/view/external-open-origins.ts +37 -0
  195. package/src/lib/view/host-capabilities.ts +17 -0
  196. package/src/lib/view/resolve.ts +1 -1
  197. package/src/lib/view/server.ts +18 -3
  198. package/src/lib/view/session.ts +2 -0
  199. package/src/program/.spec/api.d.ts +1 -0
  200. package/src/program/__tests__/program.test.ts +163 -6
  201. package/src/program/argv.ts +14 -0
  202. package/src/program/build.ts +26 -4
  203. package/src/program/command.ts +1 -0
  204. package/src/program/index.ts +1 -0
  205. package/src/program/registry.ts +2 -1
  206. package/src/setup/__tests__/instance-step.test.ts +27 -10
  207. package/src/setup/steps/instance.ts +22 -15
  208. package/src/setup/steps/skills.ts +40 -38
  209. package/src/state/.spec/api.d.ts +21 -2
  210. package/src/state/.spec/architecture.md +18 -4
  211. package/src/state/.spec/layout.ts +1 -0
  212. package/src/state/__tests__/exchange-credentials.test.ts +88 -42
  213. package/src/state/__tests__/files.test.ts +24 -1
  214. package/src/state/__tests__/fixtures/session-route-process.ts +93 -0
  215. package/src/state/__tests__/paths.test.ts +1 -0
  216. package/src/state/__tests__/session-routes.test.ts +138 -0
  217. package/src/state/exchange-credentials.ts +22 -9
  218. package/src/state/files.ts +41 -0
  219. package/src/state/index.ts +3 -1
  220. package/src/state/paths.ts +3 -0
  221. package/src/state/session-routes.ts +34 -0
  222. package/src/telemetry/__tests__/analyze-log.test.ts +38 -0
  223. package/src/telemetry/__tests__/recorder.test.ts +1 -0
  224. package/src/telemetry/__tests__/retention.test.ts +267 -0
  225. package/src/telemetry/__tests__/settings.test.ts +102 -0
  226. package/src/telemetry/__tests__/store-scan.test.ts +128 -0
  227. package/src/telemetry/__tests__/trigger.test.ts +33 -4
  228. package/src/telemetry/analyze.ts +24 -2
  229. package/src/telemetry/recorder.ts +15 -4
  230. package/src/telemetry/retention.ts +176 -0
  231. package/src/telemetry/session.ts +18 -12
  232. package/src/telemetry/settings.ts +64 -11
  233. package/src/telemetry/store.ts +92 -9
  234. package/src/telemetry/trigger.ts +16 -28
  235. package/src/ui/.spec/api.d.ts +14 -0
  236. package/src/ui/.spec/architecture.md +14 -0
  237. package/src/ui/.spec/laws.ts +50 -0
  238. package/src/ui/.spec/layout.ts +16 -0
  239. package/src/ui/__tests__/ui.test.ts +1742 -0
  240. package/src/ui/index.ts +13 -0
  241. package/src/ui/lock.ts +89 -0
  242. package/src/ui/model.ts +83 -0
  243. package/src/ui/operations.ts +1044 -0
  244. package/src/ui/project.ts +333 -0
  245. package/src/ui/release.ts +398 -0
  246. package/src/ui/runner.ts +18 -0
  247. package/studio/client/dist/assets/elk-api-DjmKsHXc.js +1 -0
  248. package/studio/client/dist/assets/index-BFVFs_8x.js +81 -0
  249. package/studio/client/dist/assets/index-DuB9iUdu.css +2 -0
  250. package/studio/client/dist/assets/rolldown-runtime-Dd_uD5pT.js +1 -0
  251. package/studio/client/dist/assets/schema-studio--a0kX3QU.css +1 -0
  252. package/studio/client/dist/assets/schema-studio-DH6oEWME.js +8 -0
  253. package/studio/client/dist/index.html +4 -3
  254. package/studio/package.json +8 -14
  255. package/studio/server/agent/ask.test.ts +1 -1
  256. package/studio/server/agent/bridge/grant.test.ts +1 -1
  257. package/studio/server/agent/bridge/routes.test.ts +1 -1
  258. package/studio/server/agent/harness/claude/adapter.test.ts +15 -5
  259. package/studio/server/agent/harness/gateway/token.test.ts +1 -1
  260. package/studio/server/agent/harness/gateway/token.ts +3 -3
  261. package/studio/server/agent/prompts/anchors.test.ts +41 -32
  262. package/studio/server/agent/prompts/anchors.ts +23 -51
  263. package/studio/server/agent/prompts/system.test.ts +4 -4
  264. package/studio/server/agent/prompts/system.ts +5 -5
  265. package/studio/server/agent/routes.test.ts +1 -1
  266. package/studio/server/agent/run/coordinator.test.ts +1 -1
  267. package/studio/server/agent/run/preparation.ts +1 -1
  268. package/studio/server/api/canvas.ts +0 -1
  269. package/studio/server/api/context.ts +1 -1
  270. package/studio/server/api/deployment.ts +1 -1
  271. package/studio/server/api/views.ts +2 -2
  272. package/studio/server/api/workspace.ts +1 -1
  273. package/studio/server/api-agent-loadout.test.ts +1 -1
  274. package/studio/server/api.test.ts +1 -1
  275. package/studio/server/cache.test.ts +24 -18
  276. package/studio/server/cache.ts +10 -54
  277. package/studio/server/cli-consumers.test.ts +31 -3
  278. package/studio/server/domain.test.ts +50 -68
  279. package/studio/server/domain.ts +82 -63
  280. package/studio/server/handoff/copy.ts +2 -2
  281. package/studio/server/index.ts +1 -1
  282. package/studio/server/instances/probe.test.ts +1 -1
  283. package/studio/server/introspect/anatomy/views/routes.ts +46 -37
  284. package/studio/server/introspect/anatomy/views.ts +10 -16
  285. package/studio/server/introspect/anatomy-extras.test.ts +29 -56
  286. package/studio/server/introspect/anatomy.test.ts +22 -14
  287. package/studio/server/introspect/anatomy.ts +6 -9
  288. package/studio/server/introspect/bundle.ts +0 -3
  289. package/studio/server/introspect/canonical-schema.test.ts +155 -424
  290. package/studio/server/introspect/canonical-schema.ts +248 -601
  291. package/studio/server/introspect/core.ts +14 -22
  292. package/studio/server/introspect/diff.test.ts +21 -9
  293. package/studio/server/introspect/diff.ts +19 -64
  294. package/studio/server/introspect/extractor.ts +23 -122
  295. package/studio/server/introspect/overlay-tsmorph.test.ts +116 -241
  296. package/studio/server/introspect/overlay-tsmorph.ts +0 -1
  297. package/studio/server/introspect/overlay.ts +3 -51
  298. package/studio/server/introspect/revision.test.ts +24 -28
  299. package/studio/server/introspect/revision.ts +11 -22
  300. package/studio/server/introspect/runtime.test.ts +77 -195
  301. package/studio/server/introspect/runtime.ts +5 -67
  302. package/studio/server/introspect/schema-ir-json.test.ts +81 -0
  303. package/studio/server/introspect/schema-ir-json.ts +39 -69
  304. package/studio/server/introspect/schema-refs.test.ts +43 -88
  305. package/studio/server/introspect/schema-refs.ts +14 -49
  306. package/studio/server/introspect/source-overlay/handlers.ts +116 -636
  307. package/studio/server/introspect/source-overlay/kernel-calls.ts +0 -3
  308. package/studio/server/introspect/source-overlay/spans.ts +15 -45
  309. package/studio/server/lifecycle.ts +4 -1
  310. package/studio/server/state/baseline.test.ts +14 -9
  311. package/studio/server/state/baseline.ts +3 -5
  312. package/studio/server/state/documents.test.ts +69 -0
  313. package/studio/server/state/documents.ts +57 -10
  314. package/studio/server/state/visibility.ts +1 -5
  315. package/studio/server/views/model.ts +3 -3
  316. package/studio/server/views/target.test.ts +18 -76
  317. package/studio/server/views/target.ts +24 -50
  318. package/studio/server/watch.test.ts +11 -11
  319. package/studio/server/watch.ts +8 -4
  320. package/studio/server/workspace/updates.ts +23 -1
  321. package/studio/server/workspace-watch.ts +2 -2
  322. package/studio/shared/contracts/runtime.ts +4 -0
  323. package/studio/shared/contracts/schema.ts +44 -131
  324. package/studio/shared/contracts/surface.test.ts +15 -17
  325. package/studio/shared/contracts/workspace.ts +5 -11
  326. package/studio/shared/schema/identity.test.ts +20 -44
  327. package/studio/shared/schema/identity.ts +9 -24
  328. package/studio/tsconfig.json +2 -1
  329. package/tsconfig.json +1 -1
  330. package/viewer/dist/index.html +21 -0
  331. package/viewer/dist/main.js +41 -62
  332. package/.check-workspace.cjs +0 -40
  333. package/src/admin/binding.ts +0 -168
  334. package/src/commands/__tests__/instance-create-hosts.test.ts +0 -29
  335. package/studio/client/dist/assets/elk-api-lwhFo7vB.js +0 -1
  336. package/studio/client/dist/assets/index-B-c-smo9.js +0 -8
  337. package/studio/client/dist/assets/index-BckHuAWk.js +0 -81
  338. package/studio/client/dist/assets/index-C4aNQ6dz.css +0 -1
  339. package/studio/client/dist/assets/index-ChOr3yP0.css +0 -1
  340. package/studio/server/introspect/anatomy/views/legacy.ts +0 -232
  341. package/studio/server/introspect/core-extractor.ts +0 -139
  342. package/studio/server/introspect/overlay.test.ts +0 -72
  343. package/studio/server/introspect/source-overlay/annotations.ts +0 -14
@@ -1,474 +1,205 @@
1
+ import * as sdk from '@astrale-os/sdk/schema'
2
+ import {
3
+ core,
4
+ defineSchema,
5
+ edgeClass,
6
+ func,
7
+ method,
8
+ nodeClass,
9
+ output,
10
+ property,
11
+ valueSchema,
12
+ view,
13
+ } from '@astrale-os/sdk/schema'
1
14
  import { describe, expect, test } from 'bun:test'
2
15
 
3
- import type { CanonicalDomainSchemaV1 } from './canonical-schema'
4
-
5
16
  import {
6
- closureFromSdk,
17
+ extractCanonicalSchemaFromSdk,
7
18
  findCanonicalDomainSchemaExport,
8
- normalizeLegacySchemaIR,
19
+ isCanonicalDomainSchemaV1,
9
20
  projectCanonicalCore,
10
- projectCanonicalSchema,
21
+ type CanonicalDomainSchemaV1,
11
22
  } from './canonical-schema'
12
23
 
13
- const emptyProperties = {
14
- type: 'object',
15
- properties: {},
16
- required: [],
17
- additionalProperties: false,
18
- }
19
-
20
- const dependency = {
21
- format: 'astrale.dsl',
22
- version: 'v1',
23
- origin: 'directory.example.dev',
24
- dependencies: [],
25
- types: {},
26
- interfaces: {
27
- Named: {
28
- family: 'node',
29
- extends: [],
30
- properties: {
31
- ...emptyProperties,
32
- properties: { name: { type: 'string' } },
33
- required: ['name'],
34
- },
35
- propertyMetadata: {},
36
- methods: {},
37
- },
38
- },
39
- classes: {},
40
- functions: {},
41
- policies: {},
42
- views: {},
43
- core: { nodes: {}, edges: [] },
44
- } satisfies CanonicalDomainSchemaV1
45
-
46
- const namedRef = {
47
- origin: dependency.origin,
48
- kind: 'interface',
49
- name: 'Named',
50
- } as const
51
- const namedKey = `${dependency.origin}:interface.Named` as const
52
- const documentRef = {
53
- origin: 'documents.example.dev',
54
- kind: 'class',
55
- name: 'Document',
56
- } as const
24
+ const string = valueSchema<string>()({ type: 'string' })
25
+ const boolean = valueSchema<boolean>()({ type: 'boolean' })
26
+ const rename = method({
27
+ input: valueSchema<{ title: string }>()({
28
+ type: 'object',
29
+ properties: { title: { type: 'string' } },
30
+ required: ['title'],
31
+ additionalProperties: false,
32
+ }),
33
+ output: boolean,
34
+ auth: 'authorized',
35
+ })
57
36
 
58
- const root = {
59
- format: 'astrale.dsl',
60
- version: 'v1',
61
- origin: 'documents.example.dev',
62
- dependencies: [{ origin: dependency.origin, revision: `sha256:${'1'.repeat(64)}` }],
63
- types: { State: { type: 'string', enum: ['draft', 'published'] } },
64
- interfaces: {
65
- Publishable: {
66
- family: 'node',
67
- extends: [namedRef],
68
- properties: emptyProperties,
69
- propertyMetadata: {},
70
- methods: {},
71
- },
72
- },
73
- classes: {
74
- Document: {
75
- family: 'node',
76
- implements: [{ origin: 'documents.example.dev', kind: 'interface', name: 'Publishable' }],
77
- properties: {
78
- ...emptyProperties,
79
- properties: {
80
- title: { type: 'string' },
81
- summary: { type: 'string' },
82
- note: { type: ['string', 'null'] },
83
- },
84
- required: ['title', 'note'],
85
- },
86
- propertyMetadata: {},
87
- data: { mediaType: 'application/json', indexed: true },
88
- methods: {
89
- watch: {
90
- input: {
91
- ...emptyProperties,
92
- properties: { cursor: { type: 'string' }, limit: { type: 'integer' } },
93
- required: ['cursor'],
94
- },
95
- output: { mode: 'stream', item: { type: 'string' } },
96
- auth: 'authorized',
97
- static: false,
98
- inheritance: 'default',
99
- },
100
- },
101
- policies: {},
102
- },
103
- references: {
104
- family: 'edge',
105
- implements: [],
106
- properties: emptyProperties,
107
- propertyMetadata: {},
108
- orientation: 'directed',
109
- endpoints: {
110
- source: { role: 'document', accepts: [documentRef], outgoing: '1..*' },
111
- target: { role: 'named', accepts: [namedRef], incoming: '0..1' },
112
- },
113
- policies: {},
114
- constraints: { noSelf: true },
115
- },
116
- },
37
+ const Named = nodeClass({ properties: { title: string } })
38
+ const dependency = defineSchema('shared.example.dev', { classes: { Named } })
39
+ const Document = nodeClass({
40
+ description: 'A document.',
41
+ icon: '<svg />',
42
+ extends: [Named],
43
+ properties: { slug: property(string, { description: 'Stable slug.' }) },
44
+ methods: { rename },
45
+ })
46
+ const links = edgeClass.directed({
47
+ source: { as: 'source', accepts: [Document], outgoing: '1' },
48
+ target: { as: 'target', accepts: [Named], incoming: '0..*' },
49
+ })
50
+ const primary = core.node(Document, { slug: 'primary', title: 'Primary' })
51
+ const primaryLink = core.edge(primary, links, primary, {})
52
+ const schema = defineSchema('docs.example.dev', {
53
+ dependencies: { shared: dependency },
54
+ classes: { Document, links },
117
55
  functions: {
118
- exportAll: {
119
- description: 'Export every document.',
120
- input: emptyProperties,
121
- output: { mode: 'binary' },
122
- auth: 'authenticated',
123
- },
124
- },
125
- policies: {},
126
- views: {
127
- editor: {
128
- description: 'Document editor',
129
- target: { kind: 'definition', definitions: [documentRef, namedRef] },
130
- auth: 'optional',
131
- },
132
- },
133
- core: {
134
- nodes: {
135
- welcome: {
136
- class: documentRef,
137
- properties: {
138
- 'documents.example.dev:class.Document.property.title': 'Welcome',
139
- },
140
- },
141
- },
142
- edges: [
143
- {
144
- class: { origin: 'documents.example.dev', kind: 'class', name: 'references' },
145
- source: { origin: 'documents.example.dev', kind: 'core', name: 'welcome' },
146
- target: { kind: 'domain' },
147
- properties: { weight: 1 },
148
- },
149
- ],
56
+ search: func({ input: string, output: output.stream(string), auth: 'authenticated' }),
150
57
  },
151
- } satisfies CanonicalDomainSchemaV1
152
-
153
- describe('canonical DomainSchema V1 projection', () => {
154
- test('admits only an SDK-verified, exact dependency closure', () => {
155
- expect(
156
- closureFromSdk({ bundle: { create: () => ({ root, closure: [dependency] }) } }, root),
157
- ).toEqual([dependency])
158
-
159
- expect(
160
- closureFromSdk(
161
- {
162
- bundle: { create: () => ({ root: dependency, closure: [dependency] }) },
163
- schema: { resolve: () => ({ $: { schema: root, closure: [dependency] } }) },
164
- },
165
- root,
166
- ),
167
- ).toEqual([dependency])
168
-
169
- expect(
170
- closureFromSdk({ bundle: { create: () => ({ root, closure: [root, dependency] }) } }, root),
171
- ).toEqual([])
172
- })
58
+ views: { documents: view({ target: Document }) },
59
+ core: { nodes: { primary }, edges: [primaryLink] },
60
+ })
61
+ const namedRef = { origin: dependency.origin, kind: 'class', name: 'Named' } as const
62
+ const documentRef = { origin: schema.origin, kind: 'class', name: 'Document' } as const
173
63
 
174
- test('finds any directly exported V1 root while preferring `schema`', () => {
175
- expect(findCanonicalDomainSchemaExport({ Other: dependency, schema: root })).toBe(root)
176
- expect(findCanonicalDomainSchemaExport({ Current: root })).toBe(root)
177
- expect(findCanonicalDomainSchemaExport({ schema: { kind: 'legacy' } })).toBeNull()
178
- })
64
+ const sdkModule = sdk
179
65
 
180
- test('keeps legacy fields and enriches refs, callables, views, and imported interfaces', () => {
181
- const projected = projectCanonicalSchema(root, [dependency])
182
- const ir = projected.ir
66
+ describe('canonical Schema projection', () => {
67
+ test('recognizes exported V1 roots and preserves an invalid root as a preview', () => {
68
+ expect(isCanonicalDomainSchemaV1(schema)).toBe(true)
69
+ expect(findCanonicalDomainSchemaExport({ other: dependency, schema })).toBe(schema)
183
70
 
184
- expect(ir).toMatchObject({
71
+ const invalid = {
185
72
  format: 'astrale.dsl',
186
73
  version: 'v1',
187
- domain: root.origin,
188
- dependencies: root.dependencies,
189
- })
190
- expect(ir.interfaces.Publishable.extends).toEqual(['Named'])
191
- expect(ir.interfaces.Publishable.extendsRefs).toEqual([namedRef])
192
- expect(ir.imports.Named).toEqual({
193
- origin: dependency.origin,
194
- definition: 'interface',
195
- ref: namedRef,
196
- key: namedKey,
197
- })
198
- expect(ir.importsByKey?.[namedKey]).toEqual(ir.imports.Named)
199
- expect(ir.importedInterfacesByKey?.[namedKey]).toMatchObject({
200
- name: 'Named',
201
- origin: dependency.origin,
202
- })
203
- expect(projected.importedInterfaces.Named).toMatchObject({
204
- name: 'Named',
205
- origin: dependency.origin,
206
- family: 'node',
207
- properties: { name: { type: 'string' } },
208
- required: ['name'],
74
+ origin: 'not an origin',
75
+ dependencies: {},
76
+ classes: {},
77
+ functions: {},
78
+ policies: {},
79
+ views: {},
80
+ core: { nodes: {}, edges: [] },
81
+ } as CanonicalDomainSchemaV1
82
+ expect(extractCanonicalSchemaFromSdk(sdkModule, invalid)).toMatchObject({
83
+ status: 'preview',
84
+ revision: null,
85
+ ir: { domain: 'not an origin' },
209
86
  })
87
+ })
210
88
 
211
- expect(ir.classes.Document.properties).toEqual({
212
- title: { type: 'string' },
213
- summary: { type: 'string' },
214
- note: { type: ['string', 'null'] },
215
- })
216
- expect(ir.classes.Document.required).toEqual(['title', 'note'])
217
- expect(ir.classes.Document.data).toEqual({ mediaType: 'application/json', indexed: true })
218
- expect(ir.classes.Document.methods.watch).toMatchObject({
219
- name: 'watch',
220
- auth: 'authorized',
221
- static: false,
222
- inheritance: 'default',
223
- params: {
224
- cursor: { type: 'string' },
225
- limit: { type: 'integer' },
89
+ test('uses the resolved Domain for Classes, dependency footprint, callables, and Views', () => {
90
+ const extraction = extractCanonicalSchemaFromSdk(sdkModule, schema)
91
+ expect(extraction.status).toBe('admitted')
92
+ expect(extraction.revision).toMatch(/^sha256:[0-9a-f]{64}$/)
93
+ expect(extraction.ir.classes.Document).toMatchObject({
94
+ icon: '<svg />',
95
+ extendsRefs: [namedRef],
96
+ properties: { slug: { type: 'string' } },
97
+ required: ['slug'],
98
+ propertyMetadata: {
99
+ slug: { required: true, visibility: 'public', description: 'Stable slug.' },
226
100
  },
227
- requiredParams: ['cursor'],
228
- output: { mode: 'stream', item: { type: 'string' } },
229
- returns: { type: 'string' },
101
+ methods: {
102
+ rename: {
103
+ input: { required: ['title'] },
104
+ auth: 'authorized',
105
+ output: { mode: 'value', schema: { type: 'boolean' } },
106
+ },
107
+ },
108
+ })
109
+ expect(extraction.ir.importsByKey['shared.example.dev:class.Named']).toEqual({
110
+ origin: namedRef.origin,
111
+ ref: namedRef,
112
+ key: 'shared.example.dev:class.Named',
230
113
  })
231
- expect(ir.classes.references.endpoints).toEqual([
114
+ expect(
115
+ extraction.ir.importedClassesByKey['shared.example.dev:class.Named']?.properties.title,
116
+ ).toEqual({ type: 'string' })
117
+ expect(extraction.ir.classes.links.endpoints).toEqual([
232
118
  {
233
- name: 'document',
119
+ name: 'source',
234
120
  types: ['Document'],
235
121
  refs: [documentRef],
236
- cardinality: { min: 1, max: null },
122
+ cardinality: { min: 1, max: 1 },
237
123
  },
238
124
  {
239
- name: 'named',
125
+ name: 'target',
240
126
  types: ['Named'],
241
127
  refs: [namedRef],
242
- cardinality: { min: 0, max: 1 },
128
+ cardinality: { min: 0, max: null },
243
129
  },
244
130
  ])
245
- expect(ir.functions.exportAll).toMatchObject({
246
- name: 'exportAll',
131
+ expect(extraction.ir.functions.search).toMatchObject({
247
132
  auth: 'authenticated',
248
- static: true,
249
- inheritance: 'default',
250
- params: {},
251
- requiredParams: [],
252
- output: { mode: 'binary' },
253
- returns: {},
254
- })
255
- expect(ir.views?.editor).toEqual({
256
- name: 'editor',
257
- description: 'Document editor',
258
- target: { kind: 'definition', definitions: [documentRef, namedRef] },
259
- auth: 'optional',
133
+ output: { mode: 'stream' },
260
134
  })
261
- expect(ir.core).toEqual(root.core)
262
- })
263
-
264
- test('keeps colliding imported definitions under exact DSL Keys only', () => {
265
- const alternate = {
266
- ...dependency,
267
- origin: 'people.example.dev',
268
- } satisfies CanonicalDomainSchemaV1
269
- const classOwner = {
270
- ...dependency,
271
- origin: 'catalog.example.dev',
272
- interfaces: {},
273
- classes: {
274
- Named: {
275
- family: 'node',
276
- implements: [],
277
- properties: emptyProperties,
278
- propertyMetadata: {},
279
- methods: {},
280
- policies: {},
281
- },
282
- },
283
- } satisfies CanonicalDomainSchemaV1
284
- const alternateRef = {
285
- origin: alternate.origin,
286
- kind: 'interface',
287
- name: 'Named',
288
- } as const
289
- const classRef = {
290
- origin: classOwner.origin,
291
- kind: 'class',
292
- name: 'Named',
293
- } as const
294
- const collisionRoot = {
295
- format: 'astrale.dsl',
296
- version: 'v1',
297
- origin: 'collisions.example.dev',
298
- dependencies: [],
299
- types: {},
300
- interfaces: {
301
- Local: {
302
- family: 'node',
303
- extends: [namedRef, alternateRef],
304
- properties: emptyProperties,
305
- propertyMetadata: {},
306
- methods: {},
307
- },
308
- },
309
- classes: {},
310
- functions: {},
311
- policies: {},
312
- views: {
313
- everything: {
314
- target: { kind: 'definition', definitions: [namedRef, alternateRef, classRef] },
315
- auth: 'required',
316
- },
317
- },
318
- core: { nodes: {}, edges: [] },
319
- } satisfies CanonicalDomainSchemaV1
320
-
321
- const projected = projectCanonicalSchema(collisionRoot, [dependency, alternate, classOwner])
322
- const keys = [
323
- 'directory.example.dev:interface.Named',
324
- 'people.example.dev:interface.Named',
325
- 'catalog.example.dev:class.Named',
326
- ]
327
-
328
- expect(Object.keys(projected.ir.importsByKey ?? {}).sort()).toEqual(keys.sort())
329
- expect(Object.keys(projected.ir.importedInterfacesByKey ?? {}).sort()).toEqual(
330
- keys.filter((key) => key.includes(':interface.')).sort(),
331
- )
332
- expect(
333
- projected.ir.importedInterfacesByKey?.['directory.example.dev:interface.Named']?.origin,
334
- ).toBe('directory.example.dev')
335
- expect(
336
- projected.ir.importedInterfacesByKey?.['people.example.dev:interface.Named']?.origin,
337
- ).toBe('people.example.dev')
338
- expect(projected.ir.importsByKey?.['catalog.example.dev:class.Named']).toMatchObject({
339
- definition: 'class',
340
- key: 'catalog.example.dev:class.Named',
341
- ref: classRef,
342
- })
343
- expect(projected.ir.imports.Named).toBeUndefined()
344
- expect(projected.importedInterfaces.Named).toBeUndefined()
345
- })
346
-
347
- test('collects an exact external Definition referenced only by a top-level Policy', () => {
348
- const policyOrigin = 'authorization.example.dev'
349
- const subjectRef = { origin: policyOrigin, kind: 'class', name: 'Subject' } as const
350
- const objectRef = { origin: policyOrigin, kind: 'class', name: 'Object' } as const
351
- const policyOnlyRef = { origin: policyOrigin, kind: 'class', name: 'may_access' } as const
352
- const policyDependency = {
353
- format: 'astrale.dsl',
354
- version: 'v1',
355
- origin: policyOrigin,
356
- dependencies: [],
357
- types: {},
358
- interfaces: {},
359
- classes: {
360
- Subject: {
361
- family: 'node',
362
- implements: [],
363
- properties: emptyProperties,
364
- propertyMetadata: {},
365
- methods: {},
366
- policies: {},
367
- },
368
- Object: {
369
- family: 'node',
370
- implements: [],
371
- properties: emptyProperties,
372
- propertyMetadata: {},
373
- methods: {},
374
- policies: {},
375
- },
376
- may_access: {
377
- family: 'edge',
378
- implements: [],
379
- properties: emptyProperties,
380
- propertyMetadata: {},
381
- orientation: 'directed',
382
- endpoints: {
383
- source: { role: 'subject', accepts: [subjectRef], outgoing: '0..*' },
384
- target: { role: 'object', accepts: [objectRef], incoming: '0..*' },
385
- },
386
- policies: {},
387
- constraints: {},
388
- },
389
- },
390
- functions: {},
391
- policies: {},
392
- views: {},
393
- core: { nodes: {}, edges: [] },
394
- } satisfies CanonicalDomainSchemaV1
395
- const policyOnlyRoot = {
396
- format: 'astrale.dsl',
397
- version: 'v1',
398
- origin: 'policy-consumer.example.dev',
399
- dependencies: [{ origin: policyDependency.origin, revision: `sha256:${'2'.repeat(64)}` }],
400
- types: {},
401
- interfaces: {},
402
- classes: {},
403
- functions: {},
404
- policies: {
405
- canRead: {
406
- match: {
407
- source: { kind: 'subject' },
408
- class: policyOnlyRef,
409
- target: { kind: 'object' },
410
- },
411
- },
412
- },
413
- views: {},
414
- core: { nodes: {}, edges: [] },
415
- } satisfies CanonicalDomainSchemaV1
416
-
417
- const projected = projectCanonicalSchema(policyOnlyRoot, [policyDependency])
418
- expect(projected.ir.importsByKey?.['authorization.example.dev:class.may_access']).toEqual({
419
- origin: policyDependency.origin,
420
- definition: 'class',
421
- ref: policyOnlyRef,
422
- key: 'authorization.example.dev:class.may_access',
135
+ expect(extraction.ir.views.documents.target).toEqual({
136
+ kind: 'definition',
137
+ definitions: [documentRef],
423
138
  })
139
+ expect(extraction.ir.dependencies).toEqual([
140
+ { origin: dependency.origin, revision: sdk.schema.revision(dependency) },
141
+ ])
424
142
  })
425
143
 
426
- test('projects canonical core paths and the owning Domain endpoint', () => {
427
- expect(projectCanonicalCore(root)).toEqual({
428
- domain: root.origin,
144
+ test('projects Core from the same admitted root without a second Schema import', () => {
145
+ const extraction = extractCanonicalSchemaFromSdk(sdkModule, schema)
146
+ expect(projectCanonicalCore(extraction.root)).toEqual({
147
+ domain: schema.origin,
429
148
  nodes: [
430
149
  {
431
- path: '/:documents.example.dev:core.welcome',
150
+ path: '/:docs.example.dev:core.primary',
432
151
  className: 'Document',
433
- data: { 'documents.example.dev:class.Document.property.title': 'Welcome' },
152
+ data: {
153
+ 'docs.example.dev:class.Document.property.slug': 'primary',
154
+ 'shared.example.dev:class.Named.property.title': 'Primary',
155
+ },
434
156
  },
435
157
  ],
436
158
  edges: [
437
159
  {
438
- from: '/:documents.example.dev:core.welcome',
439
- to: '/:documents.example.dev',
440
- edgeName: 'references',
441
- data: { weight: 1 },
160
+ from: '/:docs.example.dev:core.primary',
161
+ to: '/:docs.example.dev:core.primary',
162
+ edgeName: 'links',
163
+ data: {},
442
164
  },
443
165
  ],
444
166
  })
445
167
  })
446
168
 
447
- test('normalizes a legacy IR to the required standalone-function shape', () => {
448
- const ir = normalizeLegacySchemaIR({
449
- version: '1.0',
450
- domain: 'legacy.example.dev',
451
- types: {},
452
- interfaces: {},
453
- classes: {},
454
- imports: {},
455
- functions: {
456
- legacy: {
457
- params: {
458
- required: { type: 'string' },
459
- maybe: { type: ['string', 'null'] },
460
- },
461
- returns: { type: 'boolean' },
169
+ test('delegates admission, resolution, and dependency reachability to the DSL', () => {
170
+ const calls: string[] = []
171
+ const wrapped = {
172
+ ...sdk,
173
+ bundle: {
174
+ ...sdk.bundle,
175
+ create(value: typeof schema) {
176
+ calls.push('bundle.create')
177
+ return sdk.bundle.create(value)
178
+ },
179
+ accept(value: unknown) {
180
+ calls.push('bundle.accept')
181
+ return sdk.bundle.accept(value)
462
182
  },
463
183
  },
464
- })
465
- expect(ir.functions.legacy).toMatchObject({
466
- params: {
467
- required: { type: 'string' },
468
- maybe: { type: ['string', 'null'] },
184
+ schema: {
185
+ ...sdk.schema,
186
+ resolve(value: typeof schema) {
187
+ calls.push('schema.resolve')
188
+ return sdk.schema.resolve(value)
189
+ },
190
+ compareDependencyMeaning(source: typeof schema, target: typeof dependency) {
191
+ calls.push('schema.compareDependencyMeaning')
192
+ return sdk.schema.compareDependencyMeaning(source, target)
193
+ },
469
194
  },
470
- requiredParams: ['required'],
471
- input: { required: ['required'] },
472
- })
195
+ } as unknown as typeof sdk
196
+
197
+ expect(extractCanonicalSchemaFromSdk(wrapped, schema).status).toBe('admitted')
198
+ expect(calls).toEqual([
199
+ 'bundle.create',
200
+ 'bundle.accept',
201
+ 'schema.resolve',
202
+ 'schema.compareDependencyMeaning',
203
+ ])
473
204
  })
474
205
  })