@astrale-os/cli 1.0.0-beta.0 → 1.0.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -12
- package/dist/astrale.js +51494 -56307
- package/dist/public/connect-core.js +2028 -26846
- package/dist/public/keys/index.js +1755 -40694
- package/dist/public/paths/index.js +859 -39518
- package/dist/types/admin/binding.d.ts +19 -0
- package/dist/types/admin/instance/client.d.ts +22 -0
- package/dist/types/admin/instance/index.d.ts +2 -0
- package/dist/types/admin/instance/model.d.ts +5 -12
- package/dist/types/connection/auth.d.ts +3 -0
- package/dist/types/connection/call.d.ts +3 -0
- package/dist/types/connection/command.d.ts +27 -0
- package/dist/types/connection/credential.d.ts +14 -0
- package/dist/types/connection/errors.d.ts +1 -0
- package/dist/types/connection/exchange.d.ts +9 -0
- package/dist/types/connection/failure/classify.d.ts +2 -0
- package/dist/types/connection/failure/index.d.ts +5 -0
- package/dist/types/connection/failure/model.d.ts +25 -0
- package/dist/types/connection/failure/render.d.ts +3 -0
- package/dist/types/connection/index.d.ts +8 -0
- package/dist/types/connection/reasons.d.ts +37 -0
- package/dist/types/connection/self.d.ts +37 -0
- package/dist/types/connection/session.d.ts +31 -0
- package/dist/types/connection/target.d.ts +38 -0
- package/dist/types/errors.d.ts +1 -1
- package/dist/types/lib/admin-instance.d.ts +17 -0
- package/dist/types/lib/admin-target.d.ts +6 -2
- package/dist/types/lib/failure-debug.d.ts +1 -0
- package/dist/types/lib/idp.d.ts +7 -0
- package/dist/types/lib/instance-target.d.ts +1 -1
- package/dist/types/lib/instance.d.ts +10 -2
- package/dist/types/lib/log.d.ts +5 -3
- package/dist/types/lib/meta.d.ts +2 -2
- package/dist/types/lib/proc.d.ts +43 -0
- package/dist/types/lib/self.d.ts +9 -0
- package/dist/types/lib/update.d.ts +131 -0
- package/package.json +8 -10
- package/src/__tests__/fixtures/publication.ts +20 -0
- package/src/admin/__tests__/binding.test.ts +31 -0
- package/src/admin/__tests__/fixture.ts +101 -0
- package/src/admin/binding.ts +98 -0
- package/src/admin/catalog/.spec/api.d.ts +2 -2
- package/src/admin/catalog/__tests__/client.test.ts +20 -49
- package/src/admin/catalog/client.ts +36 -32
- package/src/admin/catalog/model.ts +3 -4
- package/src/admin/graph/.spec/api.d.ts +4 -10
- package/src/admin/graph/nodes.ts +1 -1
- package/src/admin/instance/.spec/api.d.ts +2 -2
- package/src/admin/instance/__tests__/client.test.ts +40 -163
- package/src/admin/instance/client.ts +35 -137
- package/src/admin/instance/index.ts +1 -2
- package/src/admin/instance/model.ts +11 -20
- package/src/commands/__tests__/admin-instance.test.ts +11 -8
- package/src/commands/__tests__/auth-login.test.ts +54 -1
- package/src/commands/__tests__/call-describe.test.ts +46 -33
- package/src/commands/__tests__/call.test.ts +5 -1
- package/src/commands/__tests__/domain-install-operation.test.ts +12 -7
- package/src/commands/__tests__/domain-install-owned.test.ts +6 -2
- package/src/commands/__tests__/domain-list.test.ts +63 -4
- package/src/commands/__tests__/install-identity-override.test.ts +19 -19
- package/src/commands/__tests__/instance-list-rows.test.ts +1 -1
- package/src/commands/__tests__/instance-status.test.ts +139 -0
- package/src/commands/__tests__/read-commands.test.ts +35 -10
- package/src/commands/__tests__/studio-descriptor.test.ts +22 -0
- package/src/commands/__tests__/update.test.ts +95 -0
- package/src/commands/call-describe.ts +60 -68
- package/src/commands/call.ts +43 -56
- package/src/commands/domain/install.ts +13 -17
- package/src/commands/domain/list.ts +18 -13
- package/src/commands/domain/publish.ts +14 -11
- package/src/commands/domain/uninstall.ts +2 -2
- package/src/commands/get.ts +14 -15
- package/src/commands/identity/__tests__/register.test.ts +3 -3
- package/src/commands/identity/register.ts +5 -4
- package/src/commands/instance/create.ts +8 -16
- package/src/commands/instance/delete.ts +12 -9
- package/src/commands/instance/list.ts +2 -2
- package/src/commands/instance/status.ts +66 -20
- package/src/commands/instance/use.ts +16 -12
- package/src/commands/introspect.ts +9 -16
- package/src/commands/logs.ts +24 -25
- package/src/commands/mutate.ts +6 -5
- package/src/commands/query.ts +27 -30
- package/src/commands/studio.ts +20 -0
- package/src/commands/token.ts +8 -7
- package/src/commands/update.ts +68 -22
- package/src/commands/view.ts +7 -6
- package/src/connection/.spec/api.d.ts +7 -8
- package/src/connection/.spec/architecture.md +5 -4
- package/src/connection/.spec/flows/session.ts +2 -2
- package/src/connection/.spec/laws/connection.ts +6 -2
- package/src/connection/.spec/layout.ts +1 -0
- package/src/connection/__tests__/credential.test.ts +20 -1
- package/src/connection/__tests__/errors.test.ts +43 -32
- package/src/connection/__tests__/exchange.test.ts +36 -6
- package/src/connection/__tests__/failure-fixtures.ts +39 -0
- package/src/connection/__tests__/failure-safety.test.ts +75 -0
- package/src/connection/__tests__/self.test.ts +31 -11
- package/src/connection/__tests__/session.test.ts +3 -3
- package/src/connection/__tests__/target.test.ts +1 -0
- package/src/connection/auth.ts +13 -0
- package/src/connection/call.ts +1 -1
- package/src/connection/credential.ts +2 -2
- package/src/connection/errors.ts +1 -355
- package/src/connection/exchange.ts +52 -27
- package/src/connection/failure/classify.ts +110 -0
- package/src/connection/failure/index.ts +18 -0
- package/src/connection/failure/model.ts +28 -0
- package/src/connection/failure/render.ts +116 -0
- package/src/connection/reasons.ts +16 -0
- package/src/connection/self.ts +39 -21
- package/src/connection/session.ts +19 -8
- package/src/errors.ts +3 -2
- package/src/graph/.spec/api.d.ts +12 -5
- package/src/graph/.spec/layout.ts +9 -1
- package/src/graph/__tests__/mutation.test.ts +2 -2
- package/src/graph/__tests__/query.test.ts +25 -6
- package/src/graph/class.ts +30 -0
- package/src/graph/index.ts +1 -0
- package/src/graph/query.ts +21 -32
- package/src/identity/.spec/api.d.ts +2 -2
- package/src/identity/__tests__/registration.test.ts +1 -1
- package/src/identity/registration.ts +3 -3
- package/src/keys/__tests__/keys.test.ts +4 -0
- package/src/keys/credential.ts +1 -0
- package/src/lib/__tests__/admin-target.test.ts +12 -0
- package/src/lib/__tests__/command-dx.test.ts +1 -1
- package/src/lib/__tests__/domain-publication.test.ts +138 -0
- package/src/lib/__tests__/idp-session.test.ts +22 -0
- package/src/lib/__tests__/idp.test.ts +36 -4
- package/src/lib/__tests__/instance-candidates.test.ts +1 -3
- package/src/lib/__tests__/instance-target.test.ts +7 -39
- package/src/lib/__tests__/instance.test.ts +6 -0
- package/src/lib/__tests__/log-errors.test.ts +64 -0
- package/src/lib/__tests__/studio-server-deps.test.ts +53 -16
- package/src/lib/__tests__/update.test.ts +113 -8
- package/src/lib/__tests__/view-open-intent.test.ts +0 -2
- package/src/lib/__tests__/view-server.test.ts +1 -1
- package/src/lib/__tests__/view-session.test.ts +1 -1
- package/src/lib/admin-instance.ts +14 -8
- package/src/lib/admin-target.ts +21 -2
- package/src/lib/command-dx.ts +9 -9
- package/src/lib/domain-publication.ts +104 -0
- package/src/lib/failure-debug.ts +26 -0
- package/src/lib/idp.ts +39 -4
- package/src/lib/instance-candidates.ts +2 -2
- package/src/lib/instance-target.ts +3 -14
- package/src/lib/instance.ts +22 -12
- package/src/lib/log.ts +16 -9
- package/src/lib/login-flow.ts +13 -3
- package/src/lib/meta.ts +2 -2
- package/src/lib/provision-instance.ts +34 -57
- package/src/lib/update.ts +124 -30
- package/src/lib/validation.ts +2 -2
- package/src/lib/view/resolve.ts +1 -1
- package/src/program/__tests__/program.test.ts +20 -4
- package/src/program/build.ts +2 -2
- package/src/setup/__tests__/instance-step.test.ts +27 -10
- package/src/setup/steps/instance.ts +22 -15
- package/studio/client/dist/assets/{elk-api-D2xgMJvi.js → elk-api-ByzoDZWH.js} +1 -1
- package/studio/client/dist/assets/index-B0RCgUOT.js +8 -0
- package/studio/client/dist/assets/index-BiGR8Oo9.css +1 -0
- package/studio/client/dist/assets/index-N8J8EKlB.js +81 -0
- package/studio/client/dist/index.html +2 -2
- package/studio/package.json +5 -10
- package/studio/server/agent/ask.test.ts +1 -1
- package/studio/server/agent/bridge/grant.test.ts +1 -1
- package/studio/server/agent/bridge/routes.test.ts +1 -1
- package/studio/server/agent/bridge/stdio.ts +8 -1
- package/studio/server/agent/conversation.test.ts +10 -5
- package/studio/server/agent/conversation.ts +56 -8
- package/studio/server/agent/harness/claude/adapter.test.ts +15 -5
- package/studio/server/agent/harness/codex/loadout.ts +18 -21
- package/studio/server/agent/harness/gateway/config.ts +20 -18
- package/studio/server/agent/harness/selection.ts +9 -1
- package/studio/server/agent/prompts/anchors.test.ts +32 -36
- package/studio/server/agent/prompts/anchors.ts +20 -49
- package/studio/server/agent/prompts/system.test.ts +3 -2
- package/studio/server/agent/prompts/system.ts +6 -5
- package/studio/server/agent/prompts/turn.ts +13 -4
- package/studio/server/agent/routes.test.ts +1 -1
- package/studio/server/agent/run/completion.ts +2 -2
- package/studio/server/agent/run/coordinator.test.ts +1 -1
- package/studio/server/agent/run/preparation.ts +6 -5
- package/studio/server/agent/run/transcript.test.ts +35 -1
- package/studio/server/agent/run/transcript.ts +169 -3
- package/studio/server/agent/run/usage.test.ts +24 -0
- package/studio/server/agent/run/usage.ts +26 -1
- package/studio/server/api/canvas.ts +43 -0
- package/studio/server/api/comments.ts +85 -0
- package/studio/server/api/context.ts +61 -0
- package/studio/server/api/deployment.ts +39 -0
- package/studio/server/api/documents.ts +55 -0
- package/studio/server/api/domain.ts +59 -0
- package/studio/server/api/http.ts +45 -0
- package/studio/server/api/project.ts +57 -0
- package/studio/server/api/schema.ts +12 -0
- package/studio/server/api/views.ts +57 -0
- package/studio/server/api/workspace.ts +60 -0
- package/studio/server/api-agent-loadout.test.ts +1 -1
- package/studio/server/api.test.ts +147 -0
- package/studio/server/api.ts +20 -422
- package/studio/server/cache.test.ts +122 -0
- package/studio/server/cache.ts +162 -11
- package/studio/server/cli-consumers.test.ts +494 -0
- package/studio/server/cli.test.ts +88 -0
- package/studio/server/cli.ts +240 -0
- package/studio/server/client-package.ts +25 -1
- package/studio/server/domain.test.ts +50 -40
- package/studio/server/domain.ts +83 -52
- package/studio/server/environment/dotenv-preview.test.ts +39 -0
- package/studio/server/environment/dotenv-preview.ts +27 -0
- package/studio/server/environment/files.test.ts +53 -0
- package/studio/server/{state/env.ts → environment/files.ts} +7 -48
- package/studio/server/{state → handoff}/copy.ts +21 -6
- package/studio/server/handoff/service.test.ts +22 -0
- package/studio/server/{state/handoff.ts → handoff/service.ts} +21 -14
- package/studio/server/index.ts +1 -1
- package/studio/server/instances/active.ts +72 -0
- package/studio/server/instances/deploy-record.test.ts +31 -0
- package/studio/server/instances/deploy-record.ts +37 -0
- package/studio/server/instances/deploy.ts +56 -0
- package/studio/server/{state/instance.test.ts → instances/probe.test.ts} +25 -21
- package/studio/server/instances/probe.ts +67 -0
- package/studio/server/instances/status.test.ts +12 -0
- package/studio/server/instances/status.ts +49 -0
- package/studio/server/introspect/anatomy/client-tree.ts +57 -0
- package/studio/server/introspect/anatomy/env-fields.ts +66 -0
- package/studio/server/introspect/anatomy/schema-definition.ts +53 -0
- package/studio/server/introspect/anatomy/source.ts +181 -0
- package/studio/server/introspect/anatomy/views/routes.ts +114 -0
- package/studio/server/introspect/anatomy/views.ts +53 -0
- package/studio/server/introspect/anatomy-extras.test.ts +106 -35
- package/studio/server/introspect/anatomy-extras.ts +7 -726
- package/studio/server/introspect/anatomy.test.ts +22 -14
- package/studio/server/introspect/anatomy.ts +52 -28
- package/studio/server/introspect/bundle.ts +15 -9
- package/studio/server/introspect/canonical-schema.test.ts +93 -309
- package/studio/server/introspect/canonical-schema.ts +257 -425
- package/studio/server/introspect/config-preview.test.ts +32 -0
- package/studio/server/introspect/config-preview.ts +119 -0
- package/studio/server/introspect/core-extractor.ts +18 -127
- package/studio/server/introspect/core.ts +1 -2
- package/studio/server/introspect/diff.test.ts +18 -18
- package/studio/server/introspect/diff.ts +44 -90
- package/studio/server/introspect/extractor.ts +23 -116
- package/studio/server/introspect/hash.ts +5 -2
- package/studio/server/introspect/overlay-tsmorph.test.ts +119 -240
- package/studio/server/introspect/overlay-tsmorph.ts +7 -1305
- package/studio/server/introspect/overlay.test.ts +26 -54
- package/studio/server/introspect/overlay.ts +10 -37
- package/studio/server/introspect/revision.test.ts +54 -0
- package/studio/server/introspect/revision.ts +49 -0
- package/studio/server/introspect/runtime.test.ts +83 -143
- package/studio/server/introspect/runtime.ts +40 -11
- package/studio/server/introspect/schema-ir-json.test.ts +70 -0
- package/studio/server/introspect/schema-ir-json.ts +151 -0
- package/studio/server/introspect/schema-refs.test.ts +43 -88
- package/studio/server/introspect/schema-refs.ts +14 -49
- package/studio/server/introspect/source-overlay/annotations.ts +14 -0
- package/studio/server/introspect/source-overlay/handlers.ts +161 -0
- package/studio/server/introspect/source-overlay/kernel-calls.ts +46 -0
- package/studio/server/introspect/source-overlay/project.ts +248 -0
- package/studio/server/introspect/source-overlay/spans.ts +330 -0
- package/studio/server/json.ts +46 -0
- package/studio/server/lifecycle.ts +5 -1
- package/studio/server/sse.test.ts +26 -0
- package/studio/server/sse.ts +4 -1
- package/studio/server/state/baseline.test.ts +223 -7
- package/studio/server/state/baseline.ts +148 -34
- package/studio/server/state/comments.test.ts +66 -1
- package/studio/server/state/comments.ts +173 -10
- package/studio/server/state/context.ts +34 -2
- package/studio/server/state/documents.ts +42 -1
- package/studio/server/state/integrations.ts +27 -1
- package/studio/server/state/layout.test.ts +34 -0
- package/studio/server/state/layout.ts +44 -17
- package/studio/server/state/settings.ts +29 -22
- package/studio/server/state/store.test.ts +122 -0
- package/studio/server/state/store.ts +66 -17
- package/studio/server/state/visibility.ts +22 -11
- package/studio/server/views/model.test.ts +57 -0
- package/studio/server/views/model.ts +66 -0
- package/studio/server/views/runtime.ts +40 -0
- package/studio/server/views/selection-repository.test.ts +31 -0
- package/studio/server/views/selection-repository.ts +60 -0
- package/studio/server/views/session.test.ts +73 -0
- package/studio/server/views/session.ts +166 -0
- package/studio/server/views/target.test.ts +78 -0
- package/studio/server/views/target.ts +222 -0
- package/studio/server/watch.test.ts +11 -11
- package/studio/server/watch.ts +9 -5
- package/studio/server/workspace/catalog.test.ts +17 -0
- package/studio/server/workspace/catalog.ts +43 -0
- package/studio/server/{state → workspace}/create.test.ts +1 -1
- package/studio/server/{state → workspace}/create.ts +1 -1
- package/studio/server/{state → workspace}/git.ts +1 -1
- package/studio/server/workspace/updates.ts +83 -0
- package/studio/server/workspace-state.ts +1 -1
- package/studio/server/workspace-watch.ts +2 -2
- package/studio/shared/contracts/README.md +16 -0
- package/studio/shared/contracts/agent.ts +270 -0
- package/studio/shared/contracts/runtime.ts +50 -0
- package/studio/shared/contracts/schema.ts +393 -0
- package/studio/shared/contracts/surface.test.ts +317 -0
- package/studio/shared/contracts/workspace.ts +265 -0
- package/studio/shared/layout.test.ts +116 -0
- package/studio/shared/schema/identity.test.ts +34 -0
- package/studio/shared/schema/identity.ts +68 -0
- package/studio/shared/types.ts +11 -1099
- package/studio/tsconfig.json +1 -1
- package/viewer/dist/main.js +40 -61
- package/.check-workspace.cjs +0 -40
- package/src/commands/__tests__/instance-create-hosts.test.ts +0 -29
- package/studio/client/dist/assets/index-BMdnsIJA.css +0 -1
- package/studio/client/dist/assets/index-D-vRV8w7.js +0 -8
- package/studio/client/dist/assets/index-LGSWRrk8.js +0 -81
- package/studio/server/state/catalog.ts +0 -117
- package/studio/server/state/instance.ts +0 -280
- package/studio/server/state/updates.ts +0 -63
- package/studio/server/state/views.test.ts +0 -286
- package/studio/server/state/views.ts +0 -535
|
@@ -3,6 +3,7 @@ import { describe, expect, test } from 'bun:test'
|
|
|
3
3
|
import type { AstraleConfig } from '../config'
|
|
4
4
|
import type { InstanceStore } from '../instance'
|
|
5
5
|
|
|
6
|
+
import { AdminInstanceNotFoundError } from '../../admin/instance/model'
|
|
6
7
|
import { AstraleError } from '../../errors'
|
|
7
8
|
import { DEFAULT_CONFIG } from '../config'
|
|
8
9
|
import {
|
|
@@ -112,6 +113,7 @@ describe('resolveInstanceTarget', () => {
|
|
|
112
113
|
id: 'node-1',
|
|
113
114
|
slug,
|
|
114
115
|
url: `https://${slug}.eu.astrale.ai`,
|
|
116
|
+
state: 'ready',
|
|
115
117
|
}),
|
|
116
118
|
},
|
|
117
119
|
),
|
|
@@ -124,9 +126,6 @@ describe('resolveInstanceTarget', () => {
|
|
|
124
126
|
})
|
|
125
127
|
|
|
126
128
|
test('unknown slugs surface the original instance-not-found error', async () => {
|
|
127
|
-
const notFound = new Error('Path not found: "/admin/instances/missing"')
|
|
128
|
-
notFound.name = 'NotFoundError'
|
|
129
|
-
|
|
130
129
|
await expect(
|
|
131
130
|
resolveInstanceTarget(
|
|
132
131
|
{ source: 'name', name: 'missing' },
|
|
@@ -134,7 +133,7 @@ describe('resolveInstanceTarget', () => {
|
|
|
134
133
|
config: DEFAULT_CONFIG,
|
|
135
134
|
instances: emptyStore,
|
|
136
135
|
managed: async () => {
|
|
137
|
-
throw
|
|
136
|
+
throw new AdminInstanceNotFoundError('missing')
|
|
138
137
|
},
|
|
139
138
|
},
|
|
140
139
|
),
|
|
@@ -168,14 +167,8 @@ describe('instance target helpers', () => {
|
|
|
168
167
|
expect(couldBeConfiguredAdminInstance('bryan', directAdminConfig)).toBe(false)
|
|
169
168
|
})
|
|
170
169
|
|
|
171
|
-
test('treats
|
|
172
|
-
|
|
173
|
-
data?: unknown
|
|
174
|
-
}
|
|
175
|
-
wrapped.name = 'KernelError'
|
|
176
|
-
wrapped.data = { type: 'NotFoundError' }
|
|
177
|
-
|
|
178
|
-
expect(isManagedInstanceNotFound(wrapped)).toBe(true)
|
|
170
|
+
test('treats the owner-scoped Admin error as managed lookup not-found', () => {
|
|
171
|
+
expect(isManagedInstanceNotFound(new AdminInstanceNotFoundError('admin'))).toBe(true)
|
|
179
172
|
})
|
|
180
173
|
|
|
181
174
|
test('does not hide non-not-found managed lookup failures', () => {
|
|
@@ -194,37 +187,12 @@ describe('instance target helpers', () => {
|
|
|
194
187
|
})
|
|
195
188
|
})
|
|
196
189
|
|
|
197
|
-
describe('isManagedInstanceNotFound:
|
|
198
|
-
test('
|
|
199
|
-
const e = new Error('NOT_FOUND: no instance node for "knowledge"')
|
|
200
|
-
e.name = 'InternalKernelError'
|
|
201
|
-
expect(isManagedInstanceNotFound(e)).toBe(true)
|
|
202
|
-
})
|
|
203
|
-
test('other InternalKernelError messages are not swallowed', () => {
|
|
190
|
+
describe('isManagedInstanceNotFound: unknown errors', () => {
|
|
191
|
+
test('does not infer a miss from an InternalKernelError message', () => {
|
|
204
192
|
const e = new Error('DISPATCH_FAILED: handler crashed')
|
|
205
193
|
e.name = 'InternalKernelError'
|
|
206
194
|
expect(isManagedInstanceNotFound(e)).toBe(false)
|
|
207
195
|
})
|
|
208
|
-
test('resolveNamedInstanceTarget maps the wrap to typed INSTANCE_NOT_FOUND', async () => {
|
|
209
|
-
const managed = async () => {
|
|
210
|
-
const e = new Error('NOT_FOUND: no instance node for "ghost"')
|
|
211
|
-
e.name = 'InternalKernelError'
|
|
212
|
-
throw e
|
|
213
|
-
}
|
|
214
|
-
const opts = {
|
|
215
|
-
config: DEFAULT_CONFIG,
|
|
216
|
-
instances: { instances: {} },
|
|
217
|
-
managed,
|
|
218
|
-
} as unknown as Parameters<typeof resolveInstanceTarget>[1]
|
|
219
|
-
let caught: unknown
|
|
220
|
-
try {
|
|
221
|
-
await resolveInstanceTarget({ source: 'name', name: 'ghost' }, opts)
|
|
222
|
-
} catch (e) {
|
|
223
|
-
caught = e
|
|
224
|
-
}
|
|
225
|
-
expect(caught).toBeInstanceOf(AstraleError)
|
|
226
|
-
expect((caught as AstraleError).code).toBe('INSTANCE_NOT_FOUND')
|
|
227
|
-
})
|
|
228
196
|
|
|
229
197
|
test('maps Admin token-exchange failure to INSTANCE_NOT_FOUND', async () => {
|
|
230
198
|
const managed = async () => {
|
|
@@ -74,6 +74,12 @@ describe('InstanceStoreSchema', () => {
|
|
|
74
74
|
expect(normalizeInstanceKernelUrl('https://testmarc.eu.astrale.ai/')).toBe(
|
|
75
75
|
'https://testmarc.eu.astrale.ai/api',
|
|
76
76
|
)
|
|
77
|
+
expect(normalizeInstanceKernelUrl('https://testmarc.eu.beta.astrale.ai')).toBe(
|
|
78
|
+
'https://testmarc.eu.beta.astrale.ai/api',
|
|
79
|
+
)
|
|
80
|
+
expect(normalizeInstanceKernelUrl('https://shell.beta.astrale.ai')).toBe(
|
|
81
|
+
'https://shell.beta.astrale.ai',
|
|
82
|
+
)
|
|
77
83
|
})
|
|
78
84
|
|
|
79
85
|
test('does not rewrite explicit kernel or non-managed URLs', () => {
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
import { AstraleError } from '../../errors'
|
|
4
|
+
import { failInput, fatal } from '../log'
|
|
5
|
+
|
|
6
|
+
class ExitError extends Error {}
|
|
7
|
+
|
|
8
|
+
let stderr = ''
|
|
9
|
+
let exit: typeof process.exit
|
|
10
|
+
let write: typeof process.stderr.write
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
stderr = ''
|
|
14
|
+
exit = process.exit
|
|
15
|
+
write = process.stderr.write
|
|
16
|
+
process.exit = (() => {
|
|
17
|
+
throw new ExitError()
|
|
18
|
+
}) as typeof process.exit
|
|
19
|
+
process.stderr.write = ((chunk: string | Uint8Array) => {
|
|
20
|
+
stderr += String(chunk)
|
|
21
|
+
return true
|
|
22
|
+
}) as typeof process.stderr.write
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
process.exit = exit
|
|
27
|
+
process.stderr.write = write
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
describe('terminal error safety', () => {
|
|
31
|
+
test('renders an empty aggregate as an honest non-blank unexpected failure', () => {
|
|
32
|
+
expect(() => fatal(new AggregateError([], ''), { json: true })).toThrow(ExitError)
|
|
33
|
+
expect(JSON.parse(stderr)).toEqual({
|
|
34
|
+
error: 'UNEXPECTED_ERROR',
|
|
35
|
+
message: 'The CLI encountered an unexpected internal failure.',
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('retains unknown failure evidence only under explicit debug output', () => {
|
|
40
|
+
const failure = new AggregateError([new Error('provider rejected organization scope')], '')
|
|
41
|
+
|
|
42
|
+
expect(() => fatal(failure, { json: true, debug: true })).toThrow(ExitError)
|
|
43
|
+
|
|
44
|
+
expect(stderr).toContain(
|
|
45
|
+
'{"error":"UNEXPECTED_ERROR","message":"The CLI encountered an unexpected internal failure."}',
|
|
46
|
+
)
|
|
47
|
+
expect(stderr).toContain('aggregate: Error: provider rejected organization scope')
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test('rejects blank admitted CLI diagnostics', () => {
|
|
51
|
+
expect(() => new AstraleError('INVALID_INPUT', ' ')).toThrow(TypeError)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('labels only expected admission failures as invalid input', () => {
|
|
55
|
+
expect(() => failInput(new TypeError('Authored value is invalid.'), { json: true })).toThrow(
|
|
56
|
+
ExitError,
|
|
57
|
+
)
|
|
58
|
+
expect(JSON.parse(stderr)).toMatchObject({ error: 'INVALID_INPUT' })
|
|
59
|
+
|
|
60
|
+
stderr = ''
|
|
61
|
+
expect(() => failInput(new AggregateError([], ''), { json: true })).toThrow(ExitError)
|
|
62
|
+
expect(JSON.parse(stderr)).toMatchObject({ error: 'UNEXPECTED_ERROR' })
|
|
63
|
+
})
|
|
64
|
+
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, expect, test } from 'bun:test'
|
|
2
|
-
import { readFileSync } from 'node:fs'
|
|
3
|
-
import { join } from 'node:path'
|
|
2
|
+
import { readFileSync, readdirSync, statSync } from 'node:fs'
|
|
3
|
+
import { join, relative } from 'node:path'
|
|
4
4
|
import { Project } from 'ts-morph'
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -19,6 +19,18 @@ import { Project } from 'ts-morph'
|
|
|
19
19
|
|
|
20
20
|
const CLI_ROOT = new URL('../../../', import.meta.url).pathname
|
|
21
21
|
|
|
22
|
+
interface PackageManifest {
|
|
23
|
+
dependencies?: Record<string, string>
|
|
24
|
+
scripts?: Record<string, string>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const cliPackage = JSON.parse(
|
|
28
|
+
readFileSync(join(CLI_ROOT, 'package.json'), 'utf8'),
|
|
29
|
+
) as PackageManifest
|
|
30
|
+
const studioPackage = JSON.parse(
|
|
31
|
+
readFileSync(join(CLI_ROOT, 'studio/package.json'), 'utf8'),
|
|
32
|
+
) as PackageManifest
|
|
33
|
+
|
|
22
34
|
/** Base package of a bare specifier: `@scope/pkg/sub` → `@scope/pkg`, `pkg/sub` → `pkg`. */
|
|
23
35
|
function basePackage(spec: string): string {
|
|
24
36
|
const parts = spec.split('/')
|
|
@@ -29,26 +41,33 @@ function isBuiltin(spec: string): boolean {
|
|
|
29
41
|
return spec.startsWith('node:') || spec === 'bun' || spec.startsWith('bun:')
|
|
30
42
|
}
|
|
31
43
|
|
|
44
|
+
function runtimeFiles(directory: string): string[] {
|
|
45
|
+
return readdirSync(directory).flatMap((entry) => {
|
|
46
|
+
const path = join(directory, entry)
|
|
47
|
+
if (statSync(path).isDirectory()) return runtimeFiles(path)
|
|
48
|
+
return /\.(?:ts|tsx)$/.test(path) && !/\.test\.(?:ts|tsx)$/.test(path) ? [path] : []
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const studioPath = (path: string) => relative(CLI_ROOT, path).replaceAll('\\', '/')
|
|
53
|
+
|
|
32
54
|
describe('studio server runtime deps', () => {
|
|
33
|
-
const deps = new Set(
|
|
34
|
-
Object.keys(
|
|
35
|
-
(
|
|
36
|
-
JSON.parse(readFileSync(join(CLI_ROOT, 'package.json'), 'utf8')) as {
|
|
37
|
-
dependencies?: Record<string, string>
|
|
38
|
-
}
|
|
39
|
-
).dependencies ?? {},
|
|
40
|
-
),
|
|
41
|
-
)
|
|
55
|
+
const deps = new Set(Object.keys(cliPackage.dependencies ?? {}))
|
|
42
56
|
|
|
43
57
|
const project = new Project({ skipAddingFilesFromTsConfig: true })
|
|
44
58
|
project.addSourceFilesAtPaths([
|
|
45
59
|
join(CLI_ROOT, 'studio/server/**/*.ts'),
|
|
60
|
+
join(CLI_ROOT, 'studio/server/**/*.tsx'),
|
|
46
61
|
join(CLI_ROOT, 'studio/shared/**/*.ts'),
|
|
62
|
+
join(CLI_ROOT, 'studio/shared/**/*.tsx'),
|
|
47
63
|
])
|
|
64
|
+
const runtimeSourceFiles = project
|
|
65
|
+
.getSourceFiles()
|
|
66
|
+
.filter((sourceFile) => !/\.test\.(?:ts|tsx)$/.test(sourceFile.getBaseName()))
|
|
48
67
|
|
|
49
68
|
// getImportStringLiterals covers static imports, re-exports, and dynamic import().
|
|
50
69
|
const offenders: Record<string, string[]> = {}
|
|
51
|
-
for (const sf of
|
|
70
|
+
for (const sf of runtimeSourceFiles) {
|
|
52
71
|
const specs = sf.getImportStringLiterals().map((l) => l.getLiteralValue())
|
|
53
72
|
for (const spec of specs) {
|
|
54
73
|
if (spec.startsWith('.') || spec.startsWith('/') || isBuiltin(spec)) continue
|
|
@@ -66,9 +85,27 @@ describe('studio server runtime deps', () => {
|
|
|
66
85
|
).toEqual({})
|
|
67
86
|
})
|
|
68
87
|
|
|
69
|
-
test('
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
88
|
+
test('parses every shipped Studio server and shared runtime source', () => {
|
|
89
|
+
const expected = [
|
|
90
|
+
...runtimeFiles(join(CLI_ROOT, 'studio/server')),
|
|
91
|
+
...runtimeFiles(join(CLI_ROOT, 'studio/shared')),
|
|
92
|
+
]
|
|
93
|
+
.map(studioPath)
|
|
94
|
+
.sort()
|
|
95
|
+
const parsed = runtimeSourceFiles
|
|
96
|
+
.map((sourceFile) => studioPath(sourceFile.getFilePath()))
|
|
97
|
+
.sort()
|
|
98
|
+
|
|
99
|
+
expect(parsed).toEqual(expected)
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
describe('studio test gate', () => {
|
|
104
|
+
test('the root and Studio suites include all client, server, and shared tests', () => {
|
|
105
|
+
expect(cliPackage.scripts?.test).toBe(
|
|
106
|
+
'node scripts/qualification/source-boundary.mjs --target && bun test src studio/client/src studio/server studio/shared && node --test scripts/*.test.mjs',
|
|
107
|
+
)
|
|
108
|
+
expect(cliPackage.scripts?.['test:studio']).toBe('pnpm --dir studio test')
|
|
109
|
+
expect(studioPackage.scripts?.test).toBe('bun test client/src server shared')
|
|
73
110
|
})
|
|
74
111
|
})
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
import { describe, expect, test } from 'bun:test'
|
|
2
|
-
import { chmod, mkdir, mkdtemp, readFile, writeFile } from 'node:fs/promises'
|
|
2
|
+
import { chmod, mkdir, mkdtemp, readFile, symlink, writeFile } from 'node:fs/promises'
|
|
3
3
|
import { tmpdir } from 'node:os'
|
|
4
4
|
import { join } from 'node:path'
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
+
admitScriptInstall,
|
|
8
|
+
classifyUpdateExecution,
|
|
9
|
+
DEFAULT_UPDATE_CHANNEL,
|
|
10
|
+
InstallMetadataSchema,
|
|
11
|
+
readInstallMetadata,
|
|
7
12
|
releaseBase,
|
|
8
13
|
shouldUpdate,
|
|
9
14
|
updateAstrale,
|
|
10
15
|
writeInstallMetadata,
|
|
11
16
|
type InstallMetadata,
|
|
17
|
+
type UpdateExecution,
|
|
12
18
|
} from '../update'
|
|
13
19
|
|
|
14
20
|
async function makeFakeRelease(
|
|
@@ -63,7 +69,7 @@ async function makeFakeRelease(
|
|
|
63
69
|
async function makeInstall(
|
|
64
70
|
root: string,
|
|
65
71
|
version: string,
|
|
66
|
-
): Promise<{ meta: InstallMetadata; path: string }> {
|
|
72
|
+
): Promise<{ meta: InstallMetadata; path: string; execution: UpdateExecution }> {
|
|
67
73
|
const bin = join(root, 'bin', 'astrale')
|
|
68
74
|
await mkdir(join(root, 'bin'), { recursive: true })
|
|
69
75
|
await writeFile(
|
|
@@ -80,10 +86,43 @@ async function makeInstall(
|
|
|
80
86
|
bin,
|
|
81
87
|
}
|
|
82
88
|
await writeInstallMetadata(meta, path)
|
|
83
|
-
return { meta, path }
|
|
89
|
+
return { meta, path, execution: { kind: 'standalone', executable: bin } }
|
|
84
90
|
}
|
|
85
91
|
|
|
86
92
|
describe('update helpers', () => {
|
|
93
|
+
test('classifies only a Bun-compiled executable as standalone', () => {
|
|
94
|
+
expect(
|
|
95
|
+
classifyUpdateExecution({
|
|
96
|
+
bunVersion: '1.3.14',
|
|
97
|
+
executable: '/tmp/astrale',
|
|
98
|
+
entry: '/$bunfs/root/astrale',
|
|
99
|
+
}),
|
|
100
|
+
).toEqual({ kind: 'standalone', executable: '/tmp/astrale' })
|
|
101
|
+
expect(
|
|
102
|
+
classifyUpdateExecution({
|
|
103
|
+
bunVersion: '1.3.14',
|
|
104
|
+
executable: '/opt/homebrew/bin/bun',
|
|
105
|
+
entry: '/tmp/astrale.ts',
|
|
106
|
+
}),
|
|
107
|
+
).toEqual({ kind: 'package-managed', executable: '/opt/homebrew/bin/bun' })
|
|
108
|
+
expect(
|
|
109
|
+
classifyUpdateExecution({
|
|
110
|
+
executable: '/opt/homebrew/bin/node',
|
|
111
|
+
entry: '/tmp/astrale.js',
|
|
112
|
+
}),
|
|
113
|
+
).toEqual({ kind: 'package-managed', executable: '/opt/homebrew/bin/node' })
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
test('defaults missing install metadata to the beta channel', () => {
|
|
117
|
+
expect(DEFAULT_UPDATE_CHANNEL).toBe('beta')
|
|
118
|
+
expect(
|
|
119
|
+
InstallMetadataSchema.parse({
|
|
120
|
+
method: 'script',
|
|
121
|
+
bin: '/tmp/astrale',
|
|
122
|
+
}).channel,
|
|
123
|
+
).toBe('beta')
|
|
124
|
+
})
|
|
125
|
+
|
|
87
126
|
test('releaseBase resolves exact versions and channels', () => {
|
|
88
127
|
const meta: InstallMetadata = {
|
|
89
128
|
method: 'script',
|
|
@@ -106,10 +145,70 @@ describe('update helpers', () => {
|
|
|
106
145
|
})
|
|
107
146
|
})
|
|
108
147
|
|
|
148
|
+
describe('script install admission', () => {
|
|
149
|
+
test('rejects malformed JSON with the stable metadata error', async () => {
|
|
150
|
+
const root = await mkdtemp(join(tmpdir(), 'astrale-update-test-'))
|
|
151
|
+
const path = join(root, 'install.json')
|
|
152
|
+
await writeFile(path, '{')
|
|
153
|
+
|
|
154
|
+
await expect(readInstallMetadata(path)).rejects.toMatchObject({
|
|
155
|
+
code: 'UPDATE_BAD_INSTALL_METADATA',
|
|
156
|
+
})
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
test('admits a symlink only when it resolves to the recorded binary', async () => {
|
|
160
|
+
const root = await mkdtemp(join(tmpdir(), 'astrale-update-test-'))
|
|
161
|
+
const { meta } = await makeInstall(root, '1.0.0')
|
|
162
|
+
const alias = join(root, 'astrale-alias')
|
|
163
|
+
await symlink(meta.bin, alias)
|
|
164
|
+
|
|
165
|
+
const admitted = await admitScriptInstall(meta, {
|
|
166
|
+
kind: 'standalone',
|
|
167
|
+
executable: alias,
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
expect(admitted.metadata).toEqual(meta)
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
test('rejects a standalone binary that does not own the recorded target', async () => {
|
|
174
|
+
const root = await mkdtemp(join(tmpdir(), 'astrale-update-test-'))
|
|
175
|
+
const { meta } = await makeInstall(root, '1.0.0')
|
|
176
|
+
const other = join(root, 'other-astrale')
|
|
177
|
+
await writeFile(other, '#!/bin/sh\n')
|
|
178
|
+
|
|
179
|
+
await expect(
|
|
180
|
+
admitScriptInstall(meta, { kind: 'standalone', executable: other }),
|
|
181
|
+
).rejects.toMatchObject({ code: 'UPDATE_INSTALL_MISMATCH' })
|
|
182
|
+
})
|
|
183
|
+
})
|
|
184
|
+
|
|
109
185
|
describe('updateAstrale', () => {
|
|
186
|
+
test('a package-managed process never consults or mutates a coexisting script install', async () => {
|
|
187
|
+
const root = await mkdtemp(join(tmpdir(), 'astrale-update-test-'))
|
|
188
|
+
const { path, meta } = await makeInstall(root, '1.0.0')
|
|
189
|
+
const before = await readFile(meta.bin, 'utf8')
|
|
190
|
+
process.env.ASTRALE_UPDATE_BASE = 'file:///definitely-not-a-release'
|
|
191
|
+
try {
|
|
192
|
+
const result = await updateAstrale({
|
|
193
|
+
currentVersion: '2.0.0',
|
|
194
|
+
installPath: path,
|
|
195
|
+
execution: { kind: 'package-managed', executable: '/opt/homebrew/bin/node' },
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
expect(result).toEqual({
|
|
199
|
+
status: 'managed',
|
|
200
|
+
currentVersion: '2.0.0',
|
|
201
|
+
executable: '/opt/homebrew/bin/node',
|
|
202
|
+
})
|
|
203
|
+
expect(await readFile(meta.bin, 'utf8')).toBe(before)
|
|
204
|
+
} finally {
|
|
205
|
+
delete process.env.ASTRALE_UPDATE_BASE
|
|
206
|
+
}
|
|
207
|
+
})
|
|
208
|
+
|
|
110
209
|
test('check compares the installed release identity from metadata', async () => {
|
|
111
210
|
const root = await mkdtemp(join(tmpdir(), 'astrale-update-test-'))
|
|
112
|
-
const { path } = await makeInstall(root, 'main-abc123')
|
|
211
|
+
const { path, execution } = await makeInstall(root, 'main-abc123')
|
|
113
212
|
const release = await makeFakeRelease(root, 'main-abc123', { binaryVersion: '1.0.0' })
|
|
114
213
|
process.env.ASTRALE_UPDATE_BASE = `file://${release}`
|
|
115
214
|
try {
|
|
@@ -118,6 +217,7 @@ describe('updateAstrale', () => {
|
|
|
118
217
|
currentVersion: '1.0.0',
|
|
119
218
|
platform: { os: 'darwin', arch: 'arm64' },
|
|
120
219
|
installPath: path,
|
|
220
|
+
execution,
|
|
121
221
|
})
|
|
122
222
|
|
|
123
223
|
expect(result).toMatchObject({
|
|
@@ -132,7 +232,7 @@ describe('updateAstrale', () => {
|
|
|
132
232
|
|
|
133
233
|
test('check reports available update without replacing the binary', async () => {
|
|
134
234
|
const root = await mkdtemp(join(tmpdir(), 'astrale-update-test-'))
|
|
135
|
-
const { path, meta } = await makeInstall(root, '1.0.0')
|
|
235
|
+
const { path, meta, execution } = await makeInstall(root, '1.0.0')
|
|
136
236
|
const release = await makeFakeRelease(root, '1.1.0')
|
|
137
237
|
process.env.ASTRALE_UPDATE_BASE = `file://${release}`
|
|
138
238
|
try {
|
|
@@ -141,6 +241,7 @@ describe('updateAstrale', () => {
|
|
|
141
241
|
currentVersion: '1.0.0',
|
|
142
242
|
platform: { os: 'darwin', arch: 'arm64' },
|
|
143
243
|
installPath: path,
|
|
244
|
+
execution,
|
|
144
245
|
})
|
|
145
246
|
|
|
146
247
|
expect(result).toMatchObject({
|
|
@@ -156,7 +257,7 @@ describe('updateAstrale', () => {
|
|
|
156
257
|
|
|
157
258
|
test('supports legacy string asset manifests', async () => {
|
|
158
259
|
const root = await mkdtemp(join(tmpdir(), 'astrale-update-test-'))
|
|
159
|
-
const { path, meta } = await makeInstall(root, '1.0.0')
|
|
260
|
+
const { path, meta, execution } = await makeInstall(root, '1.0.0')
|
|
160
261
|
const release = await makeFakeRelease(root, '1.1.0', { legacyManifest: true })
|
|
161
262
|
process.env.ASTRALE_UPDATE_BASE = `file://${release}`
|
|
162
263
|
try {
|
|
@@ -165,6 +266,7 @@ describe('updateAstrale', () => {
|
|
|
165
266
|
currentVersion: '1.0.0',
|
|
166
267
|
platform: { os: 'darwin', arch: 'arm64' },
|
|
167
268
|
installPath: path,
|
|
269
|
+
execution,
|
|
168
270
|
})
|
|
169
271
|
|
|
170
272
|
expect(check).toMatchObject({
|
|
@@ -176,6 +278,7 @@ describe('updateAstrale', () => {
|
|
|
176
278
|
currentVersion: '1.0.0',
|
|
177
279
|
platform: { os: 'darwin', arch: 'arm64' },
|
|
178
280
|
installPath: path,
|
|
281
|
+
execution,
|
|
179
282
|
})
|
|
180
283
|
|
|
181
284
|
expect(result).toMatchObject({
|
|
@@ -192,7 +295,7 @@ describe('updateAstrale', () => {
|
|
|
192
295
|
|
|
193
296
|
test('updates the binary and install metadata', async () => {
|
|
194
297
|
const root = await mkdtemp(join(tmpdir(), 'astrale-update-test-'))
|
|
195
|
-
const { path, meta } = await makeInstall(root, '1.0.0')
|
|
298
|
+
const { path, meta, execution } = await makeInstall(root, '1.0.0')
|
|
196
299
|
const release = await makeFakeRelease(root, '1.1.0')
|
|
197
300
|
process.env.ASTRALE_UPDATE_BASE = `file://${release}`
|
|
198
301
|
try {
|
|
@@ -200,6 +303,7 @@ describe('updateAstrale', () => {
|
|
|
200
303
|
currentVersion: '1.0.0',
|
|
201
304
|
platform: { os: 'darwin', arch: 'arm64' },
|
|
202
305
|
installPath: path,
|
|
306
|
+
execution,
|
|
203
307
|
})
|
|
204
308
|
|
|
205
309
|
expect(result).toMatchObject({
|
|
@@ -219,7 +323,7 @@ describe('updateAstrale', () => {
|
|
|
219
323
|
|
|
220
324
|
test('updates canary-style releases whose binary reports the package version', async () => {
|
|
221
325
|
const root = await mkdtemp(join(tmpdir(), 'astrale-update-test-'))
|
|
222
|
-
const { path, meta } = await makeInstall(root, 'main-old123')
|
|
326
|
+
const { path, meta, execution } = await makeInstall(root, 'main-old123')
|
|
223
327
|
const release = await makeFakeRelease(root, 'main-new456', { binaryVersion: '1.0.0' })
|
|
224
328
|
process.env.ASTRALE_UPDATE_BASE = `file://${release}`
|
|
225
329
|
try {
|
|
@@ -227,6 +331,7 @@ describe('updateAstrale', () => {
|
|
|
227
331
|
currentVersion: '1.0.0',
|
|
228
332
|
platform: { os: 'darwin', arch: 'arm64' },
|
|
229
333
|
installPath: path,
|
|
334
|
+
execution,
|
|
230
335
|
})
|
|
231
336
|
|
|
232
337
|
expect(result).toMatchObject({
|
|
@@ -23,7 +23,6 @@ const profile: ResolvedView = {
|
|
|
23
23
|
kind: 'definition',
|
|
24
24
|
definitions: [{ origin: 'shell.test', kind: 'class', name: 'Person' }],
|
|
25
25
|
},
|
|
26
|
-
auth: 'required',
|
|
27
26
|
},
|
|
28
27
|
href: 'https://shell.test/profile',
|
|
29
28
|
handshake: 'shell',
|
|
@@ -41,7 +40,6 @@ const card: ResolvedView = {
|
|
|
41
40
|
kind: 'definition',
|
|
42
41
|
definitions: [{ origin: 'shell.test', kind: 'class', name: 'Person' }],
|
|
43
42
|
},
|
|
44
|
-
auth: 'public',
|
|
45
43
|
},
|
|
46
44
|
href: 'https://shell.test/card',
|
|
47
45
|
handshake: 'none',
|
|
@@ -29,7 +29,7 @@ describe('view session server credentials', () => {
|
|
|
29
29
|
target: target('/:example.test'),
|
|
30
30
|
route: {
|
|
31
31
|
key: 'example.test:view.public',
|
|
32
|
-
declaration: { target: { kind: 'domain' }
|
|
32
|
+
declaration: { target: { kind: 'domain' } },
|
|
33
33
|
href: 'https://example.test/ui/public',
|
|
34
34
|
handshake: 'none',
|
|
35
35
|
issuer: issuer('https://example.test'),
|
|
@@ -58,7 +58,7 @@ describe('view session private state', () => {
|
|
|
58
58
|
issuer: issuer('https://example.test'),
|
|
59
59
|
etag: `sha256:${'a'.repeat(64)}`,
|
|
60
60
|
revision: revision('b'),
|
|
61
|
-
declaration: { target: { kind: 'domain' }
|
|
61
|
+
declaration: { target: { kind: 'domain' } },
|
|
62
62
|
},
|
|
63
63
|
},
|
|
64
64
|
createdAt: '2026-08-12T00:00:00.000Z',
|
|
@@ -6,7 +6,7 @@ import { withAdminClientSession } from '../connection'
|
|
|
6
6
|
export {
|
|
7
7
|
AdminInstanceNotFoundError,
|
|
8
8
|
findOwnedInstance,
|
|
9
|
-
|
|
9
|
+
formatInstanceState,
|
|
10
10
|
type InstanceInfo,
|
|
11
11
|
type InstanceState,
|
|
12
12
|
type OwnedInstanceInfo,
|
|
@@ -19,19 +19,25 @@ export function listOwnedInstances(options: AdminConnectionOptions) {
|
|
|
19
19
|
)
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/** Read caller-visible inventory together with the exact local identity used for the Admin call. */
|
|
23
|
+
export function listOwnedInstancesWithIdentity(options: AdminConnectionOptions) {
|
|
24
|
+
return withAdminClientSession(options, async (context) =>
|
|
25
|
+
Object.freeze({
|
|
26
|
+
instances: await (await connectAdminInstances(context)).list(),
|
|
27
|
+
...(context.identity === undefined ? {} : { identity: context.identity }),
|
|
28
|
+
}),
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
22
32
|
/** Reuse an already-open Admin session for a caller-visible Instance inventory. */
|
|
23
33
|
export async function listOwnedInstancesInContext(context: ConnectionContext) {
|
|
24
34
|
return (await connectAdminInstances(context)).list()
|
|
25
35
|
}
|
|
26
36
|
|
|
27
|
-
/**
|
|
28
|
-
export function createOwnedInstance(
|
|
29
|
-
options: AdminConnectionOptions,
|
|
30
|
-
slug: string,
|
|
31
|
-
hostId?: string,
|
|
32
|
-
) {
|
|
37
|
+
/** Request one managed Instance; Admin owns infrastructure placement. */
|
|
38
|
+
export function createOwnedInstance(options: AdminConnectionOptions, slug: string) {
|
|
33
39
|
return withAdminClientSession(options, async (context) =>
|
|
34
|
-
(await connectAdminInstances(context)).create(slug
|
|
40
|
+
(await connectAdminInstances(context)).create(slug),
|
|
35
41
|
)
|
|
36
42
|
}
|
|
37
43
|
|
package/src/lib/admin-target.ts
CHANGED
|
@@ -5,11 +5,30 @@ import type { InstanceStore } from './instance'
|
|
|
5
5
|
|
|
6
6
|
import { AstraleError } from '../errors'
|
|
7
7
|
import { readInstances, resolveInstanceKey } from './instance'
|
|
8
|
+
import { DEFAULT_UPDATE_CHANNEL } from './update'
|
|
8
9
|
import { isHttpUrl } from './validation'
|
|
9
10
|
|
|
10
11
|
export const DEFAULT_ADMIN_TARGET_NAME = 'admin'
|
|
11
|
-
|
|
12
|
-
export
|
|
12
|
+
|
|
13
|
+
export function defaultAdminTargetForChannel(channel: string): {
|
|
14
|
+
readonly url: string
|
|
15
|
+
readonly domainIssuer: string
|
|
16
|
+
} {
|
|
17
|
+
return channel === 'stable'
|
|
18
|
+
? {
|
|
19
|
+
url: 'https://admin.eu.astrale.ai/api',
|
|
20
|
+
domainIssuer: 'https://admin.astrale.ai',
|
|
21
|
+
}
|
|
22
|
+
: {
|
|
23
|
+
url: 'https://admin.eu.beta.astrale.ai/api',
|
|
24
|
+
domainIssuer: 'https://admin.beta.astrale.ai',
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const DEFAULT_ADMIN_TARGET = defaultAdminTargetForChannel(DEFAULT_UPDATE_CHANNEL)
|
|
29
|
+
|
|
30
|
+
export const DEFAULT_ADMIN_TARGET_URL = DEFAULT_ADMIN_TARGET.url
|
|
31
|
+
export const DEFAULT_ADMIN_DOMAIN_ISSUER = DEFAULT_ADMIN_TARGET.domainIssuer
|
|
13
32
|
|
|
14
33
|
export const DEFAULT_ADMIN_TARGET_CONFIG = {
|
|
15
34
|
name: DEFAULT_ADMIN_TARGET_NAME,
|