@astrale-os/cli 1.0.0-beta.4 → 1.0.0-beta.6

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 (173) hide show
  1. package/dist/astrale.js +55649 -59388
  2. package/dist/public/connect-core.js +1972 -26831
  3. package/dist/public/keys/index.js +1754 -40686
  4. package/dist/public/paths/index.js +859 -39511
  5. package/dist/types/admin/instance/model.d.ts +3 -4
  6. package/dist/types/errors.d.ts +1 -1
  7. package/dist/types/lib/idp.d.ts +1 -0
  8. package/dist/types/lib/instance-target.d.ts +1 -1
  9. package/dist/types/lib/log.d.ts +2 -2
  10. package/dist/types/lib/update.d.ts +30 -0
  11. package/package.json +4 -6
  12. package/src/__tests__/fixtures/publication.ts +20 -0
  13. package/src/admin/__tests__/binding.test.ts +14 -21
  14. package/src/admin/__tests__/fixture.ts +101 -0
  15. package/src/admin/binding.ts +86 -6
  16. package/src/admin/catalog/.spec/api.d.ts +2 -2
  17. package/src/admin/catalog/__tests__/client.test.ts +20 -49
  18. package/src/admin/catalog/client.ts +35 -26
  19. package/src/admin/catalog/model.ts +3 -4
  20. package/src/admin/graph/.spec/api.d.ts +4 -10
  21. package/src/admin/graph/nodes.ts +1 -1
  22. package/src/admin/instance/.spec/api.d.ts +2 -2
  23. package/src/admin/instance/__tests__/client.test.ts +58 -83
  24. package/src/admin/instance/client.ts +49 -39
  25. package/src/admin/instance/model.ts +9 -8
  26. package/src/commands/__tests__/call-describe.test.ts +46 -33
  27. package/src/commands/__tests__/domain-install-operation.test.ts +3 -14
  28. package/src/commands/__tests__/domain-install-owned.test.ts +1 -1
  29. package/src/commands/__tests__/domain-list.test.ts +5 -25
  30. package/src/commands/__tests__/install-identity-override.test.ts +3 -14
  31. package/src/commands/__tests__/read-commands.test.ts +35 -10
  32. package/src/commands/__tests__/update.test.ts +25 -3
  33. package/src/commands/call-describe.ts +59 -67
  34. package/src/commands/call.ts +41 -54
  35. package/src/commands/domain/install.ts +2 -2
  36. package/src/commands/domain/uninstall.ts +2 -2
  37. package/src/commands/get.ts +13 -14
  38. package/src/commands/identity/__tests__/register.test.ts +3 -3
  39. package/src/commands/identity/register.ts +5 -4
  40. package/src/commands/instance/delete.ts +5 -3
  41. package/src/commands/instance/status.ts +1 -9
  42. package/src/commands/introspect.ts +4 -11
  43. package/src/commands/logs.ts +24 -25
  44. package/src/commands/mutate.ts +6 -5
  45. package/src/commands/query.ts +27 -30
  46. package/src/commands/token.ts +8 -7
  47. package/src/commands/update.ts +31 -11
  48. package/src/commands/view.ts +4 -3
  49. package/src/connection/.spec/api.d.ts +7 -8
  50. package/src/connection/.spec/architecture.md +5 -4
  51. package/src/connection/.spec/flows/session.ts +2 -2
  52. package/src/connection/.spec/laws/connection.ts +6 -2
  53. package/src/connection/.spec/layout.ts +1 -0
  54. package/src/connection/__tests__/credential.test.ts +1 -1
  55. package/src/connection/__tests__/errors.test.ts +27 -20
  56. package/src/connection/__tests__/exchange.test.ts +30 -1
  57. package/src/connection/__tests__/failure-fixtures.ts +39 -0
  58. package/src/connection/__tests__/failure-safety.test.ts +75 -0
  59. package/src/connection/__tests__/self.test.ts +31 -11
  60. package/src/connection/__tests__/session.test.ts +3 -3
  61. package/src/connection/call.ts +1 -1
  62. package/src/connection/credential.ts +2 -2
  63. package/src/connection/errors.ts +1 -355
  64. package/src/connection/exchange.ts +47 -23
  65. package/src/connection/failure/classify.ts +110 -0
  66. package/src/connection/failure/debug.ts +26 -0
  67. package/src/connection/failure/index.ts +18 -0
  68. package/src/connection/failure/model.ts +28 -0
  69. package/src/connection/failure/render.ts +116 -0
  70. package/src/connection/reasons.ts +16 -0
  71. package/src/connection/self.ts +39 -21
  72. package/src/connection/session.ts +8 -8
  73. package/src/errors.ts +3 -2
  74. package/src/graph/.spec/api.d.ts +12 -5
  75. package/src/graph/.spec/layout.ts +9 -1
  76. package/src/graph/__tests__/mutation.test.ts +2 -2
  77. package/src/graph/__tests__/query.test.ts +25 -6
  78. package/src/graph/class.ts +30 -0
  79. package/src/graph/index.ts +1 -0
  80. package/src/graph/query.ts +21 -32
  81. package/src/identity/.spec/api.d.ts +2 -2
  82. package/src/identity/__tests__/registration.test.ts +1 -1
  83. package/src/identity/registration.ts +3 -3
  84. package/src/lib/__tests__/domain-publication.test.ts +4 -15
  85. package/src/lib/__tests__/idp.test.ts +25 -0
  86. package/src/lib/__tests__/instance-target.test.ts +6 -39
  87. package/src/lib/__tests__/log-errors.test.ts +53 -0
  88. package/src/lib/__tests__/studio-server-deps.test.ts +1 -1
  89. package/src/lib/__tests__/update.test.ts +101 -8
  90. package/src/lib/__tests__/view-open-intent.test.ts +0 -2
  91. package/src/lib/__tests__/view-server.test.ts +1 -1
  92. package/src/lib/__tests__/view-session.test.ts +1 -1
  93. package/src/lib/command-dx.ts +1 -4
  94. package/src/lib/domain-publication.ts +1 -1
  95. package/src/lib/idp.ts +29 -1
  96. package/src/lib/instance-target.ts +3 -14
  97. package/src/lib/log.ts +11 -6
  98. package/src/lib/update.ts +120 -26
  99. package/src/lib/validation.ts +2 -2
  100. package/src/lib/view/resolve.ts +1 -1
  101. package/src/program/__tests__/program.test.ts +1 -1
  102. package/studio/client/dist/assets/{elk-api-lwhFo7vB.js → elk-api-Di4OXGNH.js} +1 -1
  103. package/studio/client/dist/assets/index-BLm6J11H.js +81 -0
  104. package/studio/client/dist/assets/index-BiGR8Oo9.css +1 -0
  105. package/studio/client/dist/assets/index-DTjvkOUX.js +8 -0
  106. package/studio/client/dist/index.html +2 -2
  107. package/studio/package.json +2 -9
  108. package/studio/server/agent/ask.test.ts +1 -1
  109. package/studio/server/agent/bridge/grant.test.ts +1 -1
  110. package/studio/server/agent/bridge/routes.test.ts +1 -1
  111. package/studio/server/agent/harness/claude/adapter.test.ts +15 -5
  112. package/studio/server/agent/prompts/anchors.test.ts +32 -36
  113. package/studio/server/agent/prompts/anchors.ts +20 -49
  114. package/studio/server/agent/prompts/system.test.ts +3 -2
  115. package/studio/server/agent/prompts/system.ts +3 -3
  116. package/studio/server/agent/routes.test.ts +1 -1
  117. package/studio/server/agent/run/coordinator.test.ts +1 -1
  118. package/studio/server/api/canvas.ts +0 -1
  119. package/studio/server/api-agent-loadout.test.ts +1 -1
  120. package/studio/server/api.test.ts +1 -1
  121. package/studio/server/cache.test.ts +23 -12
  122. package/studio/server/cache.ts +12 -15
  123. package/studio/server/domain.test.ts +50 -68
  124. package/studio/server/domain.ts +82 -63
  125. package/studio/server/handoff/copy.ts +1 -1
  126. package/studio/server/index.ts +1 -1
  127. package/studio/server/instances/probe.test.ts +1 -1
  128. package/studio/server/introspect/anatomy/views/routes.ts +46 -37
  129. package/studio/server/introspect/anatomy/views.ts +9 -14
  130. package/studio/server/introspect/anatomy-extras.test.ts +26 -42
  131. package/studio/server/introspect/anatomy.test.ts +22 -14
  132. package/studio/server/introspect/anatomy.ts +6 -9
  133. package/studio/server/introspect/bundle.ts +0 -3
  134. package/studio/server/introspect/canonical-schema.test.ts +94 -389
  135. package/studio/server/introspect/canonical-schema.ts +227 -457
  136. package/studio/server/introspect/core-extractor.ts +18 -127
  137. package/studio/server/introspect/core.ts +1 -2
  138. package/studio/server/introspect/diff.test.ts +11 -7
  139. package/studio/server/introspect/diff.ts +18 -55
  140. package/studio/server/introspect/extractor.ts +22 -117
  141. package/studio/server/introspect/overlay-tsmorph.test.ts +119 -240
  142. package/studio/server/introspect/overlay.test.ts +26 -54
  143. package/studio/server/introspect/overlay.ts +10 -37
  144. package/studio/server/introspect/revision.test.ts +1 -1
  145. package/studio/server/introspect/revision.ts +1 -1
  146. package/studio/server/introspect/runtime.test.ts +65 -183
  147. package/studio/server/introspect/runtime.ts +8 -25
  148. package/studio/server/introspect/schema-ir-json.test.ts +70 -0
  149. package/studio/server/introspect/schema-ir-json.ts +38 -68
  150. package/studio/server/introspect/schema-refs.test.ts +43 -88
  151. package/studio/server/introspect/schema-refs.ts +14 -49
  152. package/studio/server/introspect/source-overlay/handlers.ts +116 -636
  153. package/studio/server/introspect/source-overlay/kernel-calls.ts +0 -3
  154. package/studio/server/introspect/source-overlay/spans.ts +15 -45
  155. package/studio/server/state/baseline.test.ts +14 -9
  156. package/studio/server/state/baseline.ts +3 -5
  157. package/studio/server/state/visibility.ts +1 -5
  158. package/studio/server/views/model.ts +3 -3
  159. package/studio/server/views/target.test.ts +17 -74
  160. package/studio/server/views/target.ts +24 -50
  161. package/studio/server/watch.test.ts +11 -11
  162. package/studio/server/watch.ts +8 -4
  163. package/studio/server/workspace-watch.ts +2 -2
  164. package/studio/shared/contracts/schema.ts +38 -107
  165. package/studio/shared/contracts/surface.test.ts +13 -15
  166. package/studio/shared/contracts/workspace.ts +2 -11
  167. package/studio/shared/schema/identity.test.ts +20 -44
  168. package/studio/shared/schema/identity.ts +9 -23
  169. package/viewer/dist/main.js +40 -61
  170. package/studio/client/dist/assets/index-B-c-smo9.js +0 -8
  171. package/studio/client/dist/assets/index-BckHuAWk.js +0 -81
  172. package/studio/client/dist/assets/index-C4aNQ6dz.css +0 -1
  173. package/studio/server/introspect/anatomy/views/legacy.ts +0 -232
@@ -1,474 +1,179 @@
1
1
  import { describe, expect, test } from 'bun:test'
2
2
 
3
- import type { CanonicalDomainSchemaV1 } from './canonical-schema'
4
-
5
3
  import {
4
+ admitCanonicalSchemaFromSdk,
6
5
  closureFromSdk,
7
6
  findCanonicalDomainSchemaExport,
8
- normalizeLegacySchemaIR,
7
+ isCanonicalDomainSchemaV1,
9
8
  projectCanonicalCore,
10
9
  projectCanonicalSchema,
10
+ type CanonicalDomainSchemaV1,
11
11
  } from './canonical-schema'
12
12
 
13
- const emptyProperties = {
14
- type: 'object',
15
- properties: {},
16
- required: [],
17
- additionalProperties: false,
18
- }
13
+ const localRef = { origin: 'docs.example.dev', kind: 'class', name: 'Document' } as const
14
+ const baseRef = { origin: 'shared.example.dev', kind: 'class', name: 'Named' } as const
15
+ const edgeRef = { origin: 'docs.example.dev', kind: 'class', name: 'links' } as const
19
16
 
20
17
  const dependency = {
21
18
  format: 'astrale.dsl',
22
19
  version: 'v1',
23
- origin: 'directory.example.dev',
24
- dependencies: [],
25
- types: {},
26
- interfaces: {
20
+ origin: 'shared.example.dev',
21
+ classes: {
27
22
  Named: {
28
- family: 'node',
29
- extends: [],
30
- properties: {
31
- ...emptyProperties,
32
- properties: { name: { type: 'string' } },
33
- required: ['name'],
34
- },
35
- propertyMetadata: {},
23
+ kind: 'node',
24
+ properties: { title: { schema: { type: 'string' }, required: true } },
36
25
  methods: {},
37
26
  },
38
27
  },
39
- classes: {},
40
- functions: {},
41
- policies: {},
42
- views: {},
43
- core: { nodes: {}, edges: [] },
44
28
  } satisfies CanonicalDomainSchemaV1
45
29
 
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
57
-
58
30
  const root = {
59
31
  format: 'astrale.dsl',
60
32
  version: 'v1',
61
- origin: 'documents.example.dev',
33
+ origin: 'docs.example.dev',
62
34
  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
35
  classes: {
74
36
  Document: {
75
- family: 'node',
76
- implements: [{ origin: 'documents.example.dev', kind: 'interface', name: 'Publishable' }],
37
+ kind: 'node',
38
+ extends: [baseRef],
77
39
  properties: {
78
- ...emptyProperties,
79
- properties: {
80
- title: { type: 'string' },
81
- summary: { type: 'string' },
82
- note: { type: ['string', 'null'] },
83
- },
84
- required: ['title', 'note'],
40
+ slug: { schema: { type: 'string', minLength: 1 }, required: true },
85
41
  },
86
- propertyMetadata: {},
87
- data: { mediaType: 'application/json', indexed: true },
88
42
  methods: {
89
- watch: {
43
+ rename: {
90
44
  input: {
91
- ...emptyProperties,
92
- properties: { cursor: { type: 'string' }, limit: { type: 'integer' } },
93
- required: ['cursor'],
45
+ type: 'object',
46
+ properties: { title: { type: 'string' } },
47
+ required: ['title'],
94
48
  },
95
- output: { mode: 'stream', item: { type: 'string' } },
49
+ output: { mode: 'value', schema: { type: 'boolean' } },
96
50
  auth: 'authorized',
97
51
  static: false,
98
52
  inheritance: 'default',
99
53
  },
100
54
  },
101
- policies: {},
102
55
  },
103
- references: {
104
- family: 'edge',
105
- implements: [],
106
- properties: emptyProperties,
107
- propertyMetadata: {},
56
+ links: {
57
+ kind: 'edge',
108
58
  orientation: 'directed',
109
59
  endpoints: {
110
- source: { role: 'document', accepts: [documentRef], outgoing: '1..*' },
111
- target: { role: 'named', accepts: [namedRef], incoming: '0..1' },
60
+ source: { role: 'source', accepts: [localRef], outgoing: '1' },
61
+ target: { role: 'target', accepts: [baseRef], incoming: '0..*' },
112
62
  },
113
- policies: {},
114
- constraints: { noSelf: true },
63
+ properties: {},
64
+ methods: {},
115
65
  },
116
66
  },
117
67
  functions: {
118
- exportAll: {
119
- description: 'Export every document.',
120
- input: emptyProperties,
121
- output: { mode: 'binary' },
68
+ search: {
69
+ input: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'] },
70
+ output: { mode: 'stream', item: { type: 'string' } },
122
71
  auth: 'authenticated',
123
72
  },
124
73
  },
125
- policies: {},
126
74
  views: {
127
- editor: {
128
- description: 'Document editor',
129
- target: { kind: 'definition', definitions: [documentRef, namedRef] },
75
+ documents: {
76
+ target: { kind: 'definition', definitions: [localRef] },
130
77
  auth: 'optional',
131
78
  },
132
79
  },
133
80
  core: {
134
81
  nodes: {
135
- welcome: {
136
- class: documentRef,
137
- properties: {
138
- 'documents.example.dev:class.Document.property.title': 'Welcome',
139
- },
140
- },
82
+ primary: { class: localRef, properties: { slug: 'primary' } },
141
83
  },
142
84
  edges: [
143
85
  {
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 },
86
+ class: edgeRef,
87
+ source: { origin: 'docs.example.dev', kind: 'core', name: 'primary' },
88
+ target: { kind: 'domain', origin: 'docs.example.dev' },
148
89
  },
149
90
  ],
150
91
  },
151
92
  } satisfies CanonicalDomainSchemaV1
152
93
 
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
- })
173
-
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
- })
179
-
180
- test('keeps legacy fields and enriches refs, callables, views, and imported interfaces', () => {
181
- const projected = projectCanonicalSchema(root, [dependency])
182
- const ir = projected.ir
183
-
184
- expect(ir).toMatchObject({
185
- format: 'astrale.dsl',
186
- 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'],
209
- })
210
-
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' },
226
- },
227
- requiredParams: ['cursor'],
228
- output: { mode: 'stream', item: { type: 'string' } },
229
- returns: { type: 'string' },
230
- })
231
- expect(ir.classes.references.endpoints).toEqual([
232
- {
233
- name: 'document',
234
- types: ['Document'],
235
- refs: [documentRef],
236
- cardinality: { min: 1, max: null },
237
- },
238
- {
239
- name: 'named',
240
- types: ['Named'],
241
- refs: [namedRef],
242
- cardinality: { min: 0, max: 1 },
243
- },
244
- ])
245
- expect(ir.functions.exportAll).toMatchObject({
246
- name: 'exportAll',
247
- 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',
260
- })
261
- expect(ir.core).toEqual(root.core)
94
+ describe('canonical Schema projection', () => {
95
+ test('recognizes and selects only portable V1 schema roots', () => {
96
+ expect(isCanonicalDomainSchemaV1(root)).toBe(true)
97
+ expect(isCanonicalDomainSchemaV1({ ...root, version: 'v0' })).toBe(false)
98
+ expect(findCanonicalDomainSchemaExport({ other: dependency, schema: root })).toBe(root)
262
99
  })
263
100
 
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',
101
+ test('projects Classes, exact inheritance/imports, callables, Views, and edges', () => {
102
+ const { ir } = projectCanonicalSchema(root, [dependency])
103
+ expect(ir.classes.Document).toMatchObject({
104
+ extendsRefs: [baseRef],
105
+ properties: { slug: { type: 'string', minLength: 1 } },
106
+ required: ['slug'],
107
+ methods: {
108
+ rename: {
109
+ input: { required: ['title'] },
110
+ auth: 'authorized',
111
+ output: { mode: 'value', schema: { type: 'boolean' } },
316
112
  },
317
113
  },
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
114
  })
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',
115
+ expect(ir.importsByKey['shared.example.dev:class.Named']).toEqual({
116
+ origin: baseRef.origin,
117
+ ref: baseRef,
118
+ key: 'shared.example.dev:class.Named',
423
119
  })
120
+ expect(ir.importedClassesByKey['shared.example.dev:class.Named']?.properties.title).toEqual({
121
+ type: 'string',
122
+ })
123
+ expect(ir.classes.links.endpoints).toEqual([
124
+ { name: 'source', types: ['Document'], refs: [localRef], cardinality: { min: 1, max: 1 } },
125
+ { name: 'target', types: ['Named'], refs: [baseRef], cardinality: { min: 0, max: null } },
126
+ ])
127
+ expect(ir.functions.search).toMatchObject({ auth: 'authenticated', output: { mode: 'stream' } })
128
+ expect(ir.views?.documents.target).toEqual({ kind: 'definition', definitions: [localRef] })
424
129
  })
425
130
 
426
- test('projects canonical core paths and the owning Domain endpoint', () => {
131
+ test('projects canonical Core coordinates without importing Application or Runtime', () => {
427
132
  expect(projectCanonicalCore(root)).toEqual({
428
133
  domain: root.origin,
429
134
  nodes: [
430
135
  {
431
- path: '/:documents.example.dev:core.welcome',
136
+ path: '/:docs.example.dev:core.primary',
432
137
  className: 'Document',
433
- data: { 'documents.example.dev:class.Document.property.title': 'Welcome' },
138
+ data: { slug: 'primary' },
434
139
  },
435
140
  ],
436
141
  edges: [
437
142
  {
438
- from: '/:documents.example.dev:core.welcome',
439
- to: '/:documents.example.dev',
440
- edgeName: 'references',
441
- data: { weight: 1 },
143
+ from: '/:docs.example.dev:core.primary',
144
+ to: '/:docs.example.dev',
145
+ edgeName: 'links',
442
146
  },
443
147
  ],
444
148
  })
445
149
  })
446
150
 
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' },
462
- },
463
- },
151
+ test('uses the authored SDK for closure, admission, revision, and resolved-source proof', () => {
152
+ const accepted = { ...root }
153
+ const revision = `sha256:${'a'.repeat(64)}` as const
154
+ const sdk = {
155
+ bundle: { create: () => ({ root: accepted, closure: [dependency] }) },
156
+ schema: {
157
+ accept: (candidate: unknown) => candidate,
158
+ revision: () => revision,
159
+ resolve: (candidate: unknown) => ({ source: candidate, origin: root.origin }),
160
+ },
161
+ }
162
+ expect(closureFromSdk(sdk, accepted)).toEqual([dependency])
163
+ expect(admitCanonicalSchemaFromSdk(sdk, accepted)).toEqual({
164
+ status: 'admitted',
165
+ root: accepted,
166
+ closure: [dependency],
167
+ revision,
464
168
  })
465
- expect(ir.functions.legacy).toMatchObject({
466
- params: {
467
- required: { type: 'string' },
468
- maybe: { type: ['string', 'null'] },
469
- },
470
- requiredParams: ['required'],
471
- input: { required: ['required'] },
169
+ })
170
+
171
+ test('fails to preview when the SDK cannot prove admission', () => {
172
+ expect(admitCanonicalSchemaFromSdk({}, root)).toEqual({
173
+ status: 'preview',
174
+ root,
175
+ closure: [],
176
+ revision: null,
472
177
  })
473
178
  })
474
179
  })