@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.
- package/README.md +80 -6
- package/dist/astrale.js +55471 -58674
- package/dist/public/connect-core.js +2158 -30706
- package/dist/public/keys/index.js +1016 -29541
- package/dist/public/paths/index.js +370 -28654
- package/dist/types/admin/contract.d.ts +26 -0
- package/dist/types/admin/instance/client.d.ts +20 -0
- package/dist/types/admin/instance/index.d.ts +2 -0
- package/dist/types/admin/instance/model.d.ts +6 -10
- 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 +11 -36
- package/dist/types/lib/config.d.ts +13 -59
- package/dist/types/lib/failure-debug.d.ts +1 -0
- package/dist/types/lib/idp.d.ts +25 -173
- package/dist/types/lib/instance-target.d.ts +1 -1
- package/dist/types/lib/instance.d.ts +30 -88
- package/dist/types/lib/log.d.ts +5 -3
- package/dist/types/lib/output.d.ts +1 -1
- 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 +109 -0
- package/dist/types/lib/validation.d.ts +4 -1
- package/dist/types/state/exchange-credentials.d.ts +6 -2
- package/dist/types/state/files.d.ts +2 -0
- package/dist/types/state/index.d.ts +3 -2
- package/dist/types/state/paths.d.ts +2 -0
- package/dist/types/state/session-routes.d.ts +10 -0
- package/package.json +16 -19
- package/src/__tests__/fixtures/publication.ts +20 -0
- package/src/admin/.spec/architecture.md +12 -5
- package/src/admin/__tests__/fixture.ts +25 -0
- package/src/admin/catalog/.spec/api.d.ts +1 -3
- package/src/admin/catalog/.spec/architecture.md +5 -4
- package/src/admin/catalog/__tests__/client.test.ts +143 -69
- package/src/admin/catalog/client.ts +40 -54
- package/src/admin/catalog/model.ts +3 -4
- package/src/admin/contract.ts +47 -0
- 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 +5 -9
- package/src/admin/instance/.spec/architecture.md +7 -7
- package/src/admin/instance/__tests__/client.test.ts +157 -175
- package/src/admin/instance/client.ts +39 -128
- package/src/admin/instance/index.ts +1 -2
- package/src/admin/instance/model.ts +12 -18
- package/src/commands/__tests__/admin-instance.test.ts +11 -8
- package/src/commands/__tests__/call-describe.test.ts +46 -33
- package/src/commands/__tests__/call.test.ts +34 -0
- package/src/commands/__tests__/domain-install-operation.test.ts +30 -22
- package/src/commands/__tests__/domain-install-owned.test.ts +1 -1
- package/src/commands/__tests__/domain-list.test.ts +5 -25
- package/src/commands/__tests__/install-direct.test.ts +115 -8
- package/src/commands/__tests__/install-identity-override.test.ts +6 -17
- 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__/introspect-parse.test.ts +80 -1
- package/src/commands/__tests__/logs.test.ts +250 -2
- package/src/commands/__tests__/read-commands.test.ts +118 -10
- package/src/commands/__tests__/token-ttl.test.ts +49 -4
- package/src/commands/__tests__/update.test.ts +25 -3
- package/src/commands/__tests__/view.test.ts +50 -2
- package/src/commands/auth/logout.ts +2 -1
- package/src/commands/browser.ts +29 -0
- package/src/commands/call-describe.ts +60 -68
- package/src/commands/call.ts +71 -59
- package/src/commands/domain/install.ts +73 -46
- package/src/commands/domain/list.ts +1 -1
- package/src/commands/domain/publish.ts +14 -11
- package/src/commands/domain/uninstall.ts +2 -2
- package/src/commands/get.ts +15 -16
- package/src/commands/identity/__tests__/register.test.ts +3 -3
- package/src/commands/identity/register.ts +8 -8
- 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 +53 -41
- package/src/commands/logs.ts +123 -36
- package/src/commands/mutate.ts +6 -5
- package/src/commands/query.ts +35 -32
- package/src/commands/session/analyze.ts +26 -4
- package/src/commands/token.ts +42 -27
- package/src/commands/ui/__tests__/commands.test.ts +152 -0
- package/src/commands/ui/add.ts +51 -0
- package/src/commands/ui/doctor.ts +21 -0
- package/src/commands/ui/init.ts +38 -0
- package/src/commands/ui/list.ts +26 -0
- package/src/commands/ui/preset-apply.ts +19 -0
- package/src/commands/ui/preset-list.ts +12 -0
- package/src/commands/ui/shared.ts +25 -0
- package/src/commands/update.ts +89 -48
- package/src/commands/view.ts +82 -37
- package/src/connection/.spec/api.d.ts +7 -8
- package/src/connection/.spec/architecture.md +14 -5
- 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__/auth.test.ts +1 -0
- package/src/connection/__tests__/credential.test.ts +21 -1
- package/src/connection/__tests__/errors.test.ts +27 -20
- package/src/connection/__tests__/exchange.test.ts +64 -11
- 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 +8 -4
- package/src/connection/__tests__/target.test.ts +2 -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 +110 -61
- 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 +27 -9
- 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__/fixtures/registry-journey.ts +13 -1
- package/src/identity/__tests__/registration.test.ts +1 -1
- package/src/identity/__tests__/registry.test.ts +4 -0
- package/src/identity/registration.ts +3 -3
- package/src/identity/registry.ts +2 -0
- 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__/binary.test.ts +16 -1
- package/src/lib/__tests__/browser-retention.test.ts +212 -0
- package/src/lib/__tests__/command-dx.test.ts +1 -1
- package/src/lib/__tests__/config.test.ts +27 -0
- package/src/lib/__tests__/domain-publication.test.ts +10 -16
- package/src/lib/__tests__/idp.test.ts +34 -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__/log-errors.test.ts +64 -0
- package/src/lib/__tests__/skills.test.ts +809 -0
- package/src/lib/__tests__/studio-server-deps.test.ts +1 -1
- package/src/lib/__tests__/update.test.ts +264 -11
- package/src/lib/__tests__/view-assets.test.ts +25 -0
- package/src/lib/__tests__/view-external-open-intent.test.ts +150 -0
- package/src/lib/__tests__/view-external-open-origins.test.ts +27 -0
- package/src/lib/__tests__/view-open-intent.test.ts +0 -2
- package/src/lib/__tests__/view-server.test.ts +26 -3
- package/src/lib/__tests__/view-session.test.ts +2 -1
- package/src/lib/admin-instance.ts +14 -8
- package/src/lib/admin-target.ts +21 -2
- package/src/lib/binary.ts +22 -5
- package/src/lib/browser-retention.ts +210 -0
- package/src/lib/command-dx.ts +9 -9
- package/src/lib/config.ts +12 -1
- package/src/lib/domain-publication.ts +9 -7
- package/src/lib/failure-debug.ts +26 -0
- package/src/lib/idp.ts +34 -3
- package/src/lib/instance-candidates.ts +2 -2
- package/src/lib/instance-target.ts +3 -14
- package/src/lib/instance.ts +16 -11
- package/src/lib/log.ts +16 -9
- package/src/lib/output.ts +1 -1
- package/src/lib/proc.ts +7 -2
- package/src/lib/provision-instance.ts +34 -57
- package/src/lib/skills/lock.ts +117 -0
- package/src/lib/skills/sync.ts +814 -0
- package/src/lib/skills.ts +1 -52
- package/src/lib/update.ts +298 -45
- package/src/lib/validation.ts +2 -2
- package/src/lib/view/assets.ts +11 -2
- package/src/lib/view/external-open-intent.ts +41 -0
- package/src/lib/view/external-open-origins.ts +37 -0
- package/src/lib/view/host-capabilities.ts +17 -0
- package/src/lib/view/resolve.ts +1 -1
- package/src/lib/view/server.ts +18 -3
- package/src/lib/view/session.ts +2 -0
- package/src/program/.spec/api.d.ts +1 -0
- package/src/program/__tests__/program.test.ts +163 -6
- package/src/program/argv.ts +14 -0
- package/src/program/build.ts +26 -4
- package/src/program/command.ts +1 -0
- package/src/program/index.ts +1 -0
- package/src/program/registry.ts +2 -1
- package/src/setup/__tests__/instance-step.test.ts +27 -10
- package/src/setup/steps/instance.ts +22 -15
- package/src/setup/steps/skills.ts +40 -38
- package/src/state/.spec/api.d.ts +21 -2
- package/src/state/.spec/architecture.md +18 -4
- package/src/state/.spec/layout.ts +1 -0
- package/src/state/__tests__/exchange-credentials.test.ts +88 -42
- package/src/state/__tests__/files.test.ts +24 -1
- package/src/state/__tests__/fixtures/session-route-process.ts +93 -0
- package/src/state/__tests__/paths.test.ts +1 -0
- package/src/state/__tests__/session-routes.test.ts +138 -0
- package/src/state/exchange-credentials.ts +22 -9
- package/src/state/files.ts +41 -0
- package/src/state/index.ts +3 -1
- package/src/state/paths.ts +3 -0
- package/src/state/session-routes.ts +34 -0
- package/src/telemetry/__tests__/analyze-log.test.ts +38 -0
- package/src/telemetry/__tests__/recorder.test.ts +1 -0
- package/src/telemetry/__tests__/retention.test.ts +267 -0
- package/src/telemetry/__tests__/settings.test.ts +102 -0
- package/src/telemetry/__tests__/store-scan.test.ts +128 -0
- package/src/telemetry/__tests__/trigger.test.ts +33 -4
- package/src/telemetry/analyze.ts +24 -2
- package/src/telemetry/recorder.ts +15 -4
- package/src/telemetry/retention.ts +176 -0
- package/src/telemetry/session.ts +18 -12
- package/src/telemetry/settings.ts +64 -11
- package/src/telemetry/store.ts +92 -9
- package/src/telemetry/trigger.ts +16 -28
- package/src/ui/.spec/api.d.ts +14 -0
- package/src/ui/.spec/architecture.md +14 -0
- package/src/ui/.spec/laws.ts +50 -0
- package/src/ui/.spec/layout.ts +16 -0
- package/src/ui/__tests__/ui.test.ts +1742 -0
- package/src/ui/index.ts +13 -0
- package/src/ui/lock.ts +89 -0
- package/src/ui/model.ts +83 -0
- package/src/ui/operations.ts +1044 -0
- package/src/ui/project.ts +333 -0
- package/src/ui/release.ts +398 -0
- package/src/ui/runner.ts +18 -0
- package/studio/client/dist/assets/elk-api-DjmKsHXc.js +1 -0
- package/studio/client/dist/assets/index-BFVFs_8x.js +81 -0
- package/studio/client/dist/assets/index-DuB9iUdu.css +2 -0
- package/studio/client/dist/assets/rolldown-runtime-Dd_uD5pT.js +1 -0
- package/studio/client/dist/assets/schema-studio--a0kX3QU.css +1 -0
- package/studio/client/dist/assets/schema-studio-DH6oEWME.js +8 -0
- package/studio/client/dist/index.html +4 -3
- package/studio/package.json +8 -14
- 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/harness/claude/adapter.test.ts +15 -5
- package/studio/server/agent/harness/gateway/token.test.ts +1 -1
- package/studio/server/agent/harness/gateway/token.ts +3 -3
- package/studio/server/agent/prompts/anchors.test.ts +41 -32
- package/studio/server/agent/prompts/anchors.ts +23 -51
- package/studio/server/agent/prompts/system.test.ts +4 -4
- package/studio/server/agent/prompts/system.ts +5 -5
- package/studio/server/agent/routes.test.ts +1 -1
- package/studio/server/agent/run/coordinator.test.ts +1 -1
- package/studio/server/agent/run/preparation.ts +1 -1
- package/studio/server/api/canvas.ts +0 -1
- package/studio/server/api/context.ts +1 -1
- package/studio/server/api/deployment.ts +1 -1
- package/studio/server/api/views.ts +2 -2
- package/studio/server/api/workspace.ts +1 -1
- package/studio/server/api-agent-loadout.test.ts +1 -1
- package/studio/server/api.test.ts +1 -1
- package/studio/server/cache.test.ts +24 -18
- package/studio/server/cache.ts +10 -54
- package/studio/server/cli-consumers.test.ts +31 -3
- package/studio/server/domain.test.ts +50 -68
- package/studio/server/domain.ts +82 -63
- package/studio/server/handoff/copy.ts +2 -2
- package/studio/server/index.ts +1 -1
- package/studio/server/instances/probe.test.ts +1 -1
- package/studio/server/introspect/anatomy/views/routes.ts +46 -37
- package/studio/server/introspect/anatomy/views.ts +10 -16
- package/studio/server/introspect/anatomy-extras.test.ts +29 -56
- package/studio/server/introspect/anatomy.test.ts +22 -14
- package/studio/server/introspect/anatomy.ts +6 -9
- package/studio/server/introspect/bundle.ts +0 -3
- package/studio/server/introspect/canonical-schema.test.ts +155 -424
- package/studio/server/introspect/canonical-schema.ts +248 -601
- package/studio/server/introspect/core.ts +14 -22
- package/studio/server/introspect/diff.test.ts +21 -9
- package/studio/server/introspect/diff.ts +19 -64
- package/studio/server/introspect/extractor.ts +23 -122
- package/studio/server/introspect/overlay-tsmorph.test.ts +116 -241
- package/studio/server/introspect/overlay-tsmorph.ts +0 -1
- package/studio/server/introspect/overlay.ts +3 -51
- package/studio/server/introspect/revision.test.ts +24 -28
- package/studio/server/introspect/revision.ts +11 -22
- package/studio/server/introspect/runtime.test.ts +77 -195
- package/studio/server/introspect/runtime.ts +5 -67
- package/studio/server/introspect/schema-ir-json.test.ts +81 -0
- package/studio/server/introspect/schema-ir-json.ts +39 -69
- 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/handlers.ts +116 -636
- package/studio/server/introspect/source-overlay/kernel-calls.ts +0 -3
- package/studio/server/introspect/source-overlay/spans.ts +15 -45
- package/studio/server/lifecycle.ts +4 -1
- package/studio/server/state/baseline.test.ts +14 -9
- package/studio/server/state/baseline.ts +3 -5
- package/studio/server/state/documents.test.ts +69 -0
- package/studio/server/state/documents.ts +57 -10
- package/studio/server/state/visibility.ts +1 -5
- package/studio/server/views/model.ts +3 -3
- package/studio/server/views/target.test.ts +18 -76
- package/studio/server/views/target.ts +24 -50
- package/studio/server/watch.test.ts +11 -11
- package/studio/server/watch.ts +8 -4
- package/studio/server/workspace/updates.ts +23 -1
- package/studio/server/workspace-watch.ts +2 -2
- package/studio/shared/contracts/runtime.ts +4 -0
- package/studio/shared/contracts/schema.ts +44 -131
- package/studio/shared/contracts/surface.test.ts +15 -17
- package/studio/shared/contracts/workspace.ts +5 -11
- package/studio/shared/schema/identity.test.ts +20 -44
- package/studio/shared/schema/identity.ts +9 -24
- package/studio/tsconfig.json +2 -1
- package/tsconfig.json +1 -1
- package/viewer/dist/index.html +21 -0
- package/viewer/dist/main.js +41 -62
- package/.check-workspace.cjs +0 -40
- package/src/admin/binding.ts +0 -168
- package/src/commands/__tests__/instance-create-hosts.test.ts +0 -29
- package/studio/client/dist/assets/elk-api-lwhFo7vB.js +0 -1
- package/studio/client/dist/assets/index-B-c-smo9.js +0 -8
- package/studio/client/dist/assets/index-BckHuAWk.js +0 -81
- package/studio/client/dist/assets/index-C4aNQ6dz.css +0 -1
- package/studio/client/dist/assets/index-ChOr3yP0.css +0 -1
- package/studio/server/introspect/anatomy/views/legacy.ts +0 -232
- package/studio/server/introspect/core-extractor.ts +0 -139
- package/studio/server/introspect/overlay.test.ts +0 -72
- package/studio/server/introspect/source-overlay/annotations.ts +0 -14
|
@@ -5,10 +5,9 @@ export {
|
|
|
5
5
|
type AdminInstanceDependencies,
|
|
6
6
|
} from './client'
|
|
7
7
|
export {
|
|
8
|
-
AdminHostNotFoundError,
|
|
9
8
|
AdminInstanceNotFoundError,
|
|
10
9
|
findOwnedInstance,
|
|
11
|
-
|
|
10
|
+
formatInstanceState,
|
|
12
11
|
type DomainInstallReceipt,
|
|
13
12
|
type InstanceInfo,
|
|
14
13
|
type InstanceState,
|
|
@@ -7,10 +7,11 @@ export interface InstanceInfo {
|
|
|
7
7
|
readonly url: string
|
|
8
8
|
readonly hostId?: string
|
|
9
9
|
readonly region?: string
|
|
10
|
-
readonly state
|
|
10
|
+
readonly state: InstanceState
|
|
11
11
|
readonly phase?: string
|
|
12
12
|
readonly error?: string | null
|
|
13
13
|
readonly createdAt?: string
|
|
14
|
+
readonly updatedAt?: string
|
|
14
15
|
readonly organizationId?: string
|
|
15
16
|
}
|
|
16
17
|
|
|
@@ -28,19 +29,13 @@ export interface DomainInstallReceipt {
|
|
|
28
29
|
readonly error?: string
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
export class AdminInstanceNotFoundError extends
|
|
32
|
-
readonly name = 'NotFoundError'
|
|
33
|
-
|
|
34
|
-
constructor(readonly identifier: string) {
|
|
35
|
-
super(`No owned Admin Instance matches ${JSON.stringify(identifier)}.`)
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export class AdminHostNotFoundError extends Error {
|
|
40
|
-
readonly name = 'NotFoundError'
|
|
41
|
-
|
|
32
|
+
export class AdminInstanceNotFoundError extends AstraleError {
|
|
42
33
|
constructor(readonly identifier: string) {
|
|
43
|
-
super(
|
|
34
|
+
super(
|
|
35
|
+
'INSTANCE_NOT_FOUND',
|
|
36
|
+
`No owned Admin Instance matches ${JSON.stringify(identifier)}.`,
|
|
37
|
+
'Run `astrale instance list` to see your instances.',
|
|
38
|
+
)
|
|
44
39
|
}
|
|
45
40
|
}
|
|
46
41
|
|
|
@@ -57,9 +52,8 @@ export function findOwnedInstance(
|
|
|
57
52
|
)
|
|
58
53
|
}
|
|
59
54
|
|
|
60
|
-
/** Human-readable
|
|
61
|
-
export function
|
|
62
|
-
return
|
|
63
|
-
.filter(Boolean)
|
|
64
|
-
.join(' · ')
|
|
55
|
+
/** Human-readable non-ready lifecycle state for one Instance. */
|
|
56
|
+
export function formatInstanceState(info: InstanceInfo): string {
|
|
57
|
+
return info.state === 'ready' ? '' : `${info.state}${info.phase ? ` (${info.phase})` : ''}`
|
|
65
58
|
}
|
|
59
|
+
import { AstraleError } from '../../errors'
|
|
@@ -4,7 +4,10 @@ import type { IdentityStore } from '../../identity/index'
|
|
|
4
4
|
|
|
5
5
|
import { AuthError } from '../../errors'
|
|
6
6
|
import { findOwnedInstance, type OwnedInstanceInfo } from '../../lib/admin-instance'
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
assertInstanceCreateIdentity,
|
|
9
|
+
selectInstanceCreateIdentity,
|
|
10
|
+
} from '../../lib/provision-instance'
|
|
8
11
|
|
|
9
12
|
describe('admin-backed instance commands', () => {
|
|
10
13
|
test('findOwnedInstance matches owner inventory by slug or stable node id', () => {
|
|
@@ -14,8 +17,6 @@ describe('admin-backed instance commands', () => {
|
|
|
14
17
|
url: 'https://demo.eu.astrale.ai',
|
|
15
18
|
state: 'failed',
|
|
16
19
|
organizationId: 'org_123',
|
|
17
|
-
hostId: 'host-1',
|
|
18
|
-
region: 'eu',
|
|
19
20
|
phase: 'installing:default-domains',
|
|
20
21
|
error: 'postInstall failed',
|
|
21
22
|
createdAt: '2026-07-16T00:00:00.000Z',
|
|
@@ -39,8 +40,8 @@ describe('admin-backed instance commands', () => {
|
|
|
39
40
|
},
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
expect(() =>
|
|
43
|
-
expect(() =>
|
|
43
|
+
expect(() => assertInstanceCreateIdentity(store)).toThrow(AuthError)
|
|
44
|
+
expect(() => assertInstanceCreateIdentity(store)).toThrow('WorkOS login required')
|
|
44
45
|
})
|
|
45
46
|
|
|
46
47
|
test('instance create preflight accepts IdP-backed identities', () => {
|
|
@@ -58,7 +59,8 @@ describe('admin-backed instance commands', () => {
|
|
|
58
59
|
},
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
expect(() =>
|
|
62
|
+
expect(() => assertInstanceCreateIdentity(store)).not.toThrow()
|
|
63
|
+
expect(selectInstanceCreateIdentity(store)).toBe('bryan')
|
|
62
64
|
})
|
|
63
65
|
|
|
64
66
|
test('--as selection must also be IdP-backed', () => {
|
|
@@ -82,7 +84,8 @@ describe('admin-backed instance commands', () => {
|
|
|
82
84
|
},
|
|
83
85
|
}
|
|
84
86
|
|
|
85
|
-
expect(() =>
|
|
86
|
-
expect(() =>
|
|
87
|
+
expect(() => assertInstanceCreateIdentity(store, { as: 'local' })).toThrow(AuthError)
|
|
88
|
+
expect(() => assertInstanceCreateIdentity(store, { as: 'workos' })).not.toThrow()
|
|
89
|
+
expect(selectInstanceCreateIdentity(store, { as: 'workos' })).toBe('workos')
|
|
87
90
|
})
|
|
88
91
|
})
|
|
@@ -1,34 +1,47 @@
|
|
|
1
1
|
import { Path } from '@astrale-os/sdk/graph/path'
|
|
2
|
+
import { bundle, defineSchema, func, method, nodeClass } from '@astrale-os/sdk/schema'
|
|
2
3
|
import { describe, expect, test } from 'bun:test'
|
|
3
4
|
|
|
4
|
-
import {
|
|
5
|
+
import { describeCallableFromBundle } from '../call-describe'
|
|
5
6
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
output: { mode: 'value' },
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
},
|
|
7
|
+
const createInstance = method({
|
|
8
|
+
auth: 'authenticated',
|
|
9
|
+
description: 'Create one child Instance.',
|
|
10
|
+
input: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: { operationId: { type: 'string' }, slug: { type: 'string' } },
|
|
13
|
+
required: ['operationId', 'slug'],
|
|
14
|
+
additionalProperties: false,
|
|
18
15
|
},
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
output: { type: 'object', additionalProperties: true },
|
|
17
|
+
static: true,
|
|
18
|
+
})
|
|
19
|
+
const inspectInstance = method({
|
|
20
|
+
auth: 'authenticated',
|
|
21
|
+
description: 'Inspect one child Instance.',
|
|
22
|
+
input: { type: 'object', properties: {}, additionalProperties: false },
|
|
23
|
+
output: { type: 'object', additionalProperties: true },
|
|
24
|
+
})
|
|
25
|
+
const journal = func({
|
|
26
|
+
auth: 'authenticated',
|
|
27
|
+
description: 'Read the authorized Kernel journal.',
|
|
28
|
+
input: { type: 'object', properties: {}, additionalProperties: false },
|
|
29
|
+
output: { type: 'object', additionalProperties: true },
|
|
30
|
+
})
|
|
31
|
+
const source = defineSchema('host.astrale.ai', {
|
|
32
|
+
classes: {
|
|
33
|
+
Manager: nodeClass({ methods: { createInstance } }),
|
|
34
|
+
Instance: nodeClass({ methods: { inspectInstance } }),
|
|
24
35
|
},
|
|
25
|
-
}
|
|
36
|
+
functions: { journal },
|
|
37
|
+
})
|
|
38
|
+
const installed = bundle.create(source)
|
|
26
39
|
|
|
27
|
-
describe('
|
|
28
|
-
test('reads a static Class method from the Domain
|
|
29
|
-
const described =
|
|
40
|
+
describe('describeCallableFromBundle', () => {
|
|
41
|
+
test('reads a static Class method from the resolved Domain', () => {
|
|
42
|
+
const described = describeCallableFromBundle(
|
|
30
43
|
Path.parse('/:host.astrale.ai:class.Manager:createInstance'),
|
|
31
|
-
|
|
44
|
+
installed,
|
|
32
45
|
)
|
|
33
46
|
expect(described).toMatchObject({
|
|
34
47
|
origin: 'host.astrale.ai',
|
|
@@ -36,30 +49,30 @@ describe('describeCallableFromSchema', () => {
|
|
|
36
49
|
method: 'createInstance',
|
|
37
50
|
dispatch: 'static',
|
|
38
51
|
description: 'Create one child Instance.',
|
|
39
|
-
auth: '
|
|
52
|
+
auth: 'authenticated',
|
|
40
53
|
})
|
|
41
54
|
expect(described?.input).toMatchObject({ required: ['operationId', 'slug'] })
|
|
42
55
|
})
|
|
43
56
|
|
|
44
|
-
test('finds
|
|
57
|
+
test('finds one instance method when the receiver Path is not a Class projection', () => {
|
|
45
58
|
expect(
|
|
46
|
-
|
|
47
|
-
Path.parse('/:host.astrale.ai:core.manager::
|
|
48
|
-
|
|
59
|
+
describeCallableFromBundle(
|
|
60
|
+
Path.parse('/:host.astrale.ai:core.manager::inspectInstance'),
|
|
61
|
+
installed,
|
|
49
62
|
),
|
|
50
63
|
).toMatchObject({
|
|
51
64
|
origin: 'host.astrale.ai',
|
|
52
|
-
class: '
|
|
53
|
-
method: '
|
|
65
|
+
class: 'Instance',
|
|
66
|
+
method: 'inspectInstance',
|
|
54
67
|
dispatch: 'instance',
|
|
55
68
|
})
|
|
56
69
|
})
|
|
57
70
|
|
|
58
|
-
test('reads a standalone Function from the Domain
|
|
71
|
+
test('reads a standalone Function from the resolved Domain', () => {
|
|
59
72
|
expect(
|
|
60
|
-
|
|
73
|
+
describeCallableFromBundle(Path.parse('/:host.astrale.ai:function.journal'), installed),
|
|
61
74
|
).toMatchObject({
|
|
62
|
-
origin: '
|
|
75
|
+
origin: 'host.astrale.ai',
|
|
63
76
|
function: 'journal',
|
|
64
77
|
description: 'Read the authorized Kernel journal.',
|
|
65
78
|
})
|
|
@@ -26,4 +26,38 @@ describe('call command result lifetime', () => {
|
|
|
26
26
|
if (materialized.kind !== 'stream') throw new Error('expected a materialized stream')
|
|
27
27
|
expect(Object.isFrozen(materialized.values)).toBe(true)
|
|
28
28
|
})
|
|
29
|
+
|
|
30
|
+
test('drains streaming binary bytes before the command session closes', async () => {
|
|
31
|
+
let sessionOpen = true
|
|
32
|
+
async function* body() {
|
|
33
|
+
for (const chunk of [new Uint8Array([1, 2]), new Uint8Array([3])]) {
|
|
34
|
+
if (!sessionOpen) throw new Error('session closed before binary consumption')
|
|
35
|
+
yield chunk
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const materialized = await materializeCallResult({
|
|
40
|
+
kind: 'binary',
|
|
41
|
+
invocation: { source: 'https://kernel.test' as never, id: 'test-binary' },
|
|
42
|
+
value: {
|
|
43
|
+
body: body(),
|
|
44
|
+
mediaType: 'application/octet-stream',
|
|
45
|
+
status: 206,
|
|
46
|
+
headers: { 'content-range': 'bytes 0-2/3' },
|
|
47
|
+
},
|
|
48
|
+
})
|
|
49
|
+
sessionOpen = false
|
|
50
|
+
|
|
51
|
+
expect(materialized).toMatchObject({
|
|
52
|
+
kind: 'binary',
|
|
53
|
+
value: {
|
|
54
|
+
mediaType: 'application/octet-stream',
|
|
55
|
+
status: 206,
|
|
56
|
+
headers: { 'content-range': 'bytes 0-2/3' },
|
|
57
|
+
},
|
|
58
|
+
})
|
|
59
|
+
if (materialized.kind !== 'binary') throw new Error('expected materialized binary')
|
|
60
|
+
expect([...materialized.value.body]).toEqual([1, 2, 3])
|
|
61
|
+
expect(Object.isFrozen(materialized.value)).toBe(true)
|
|
62
|
+
})
|
|
29
63
|
})
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { issuer } from '@astrale-os/sdk/auth'
|
|
3
|
-
import { createDeployment } from '@astrale-os/sdk/deployment'
|
|
4
|
-
import { defineSchema } from '@astrale-os/sdk/schema/v1'
|
|
1
|
+
import { defineSchema } from '@astrale-os/sdk/schema'
|
|
5
2
|
import { afterEach, describe, expect, mock, test } from 'bun:test'
|
|
6
3
|
|
|
4
|
+
import { releaseFor } from '../../__tests__/fixtures/publication'
|
|
7
5
|
import { installDirect } from '../domain/install'
|
|
8
6
|
|
|
9
7
|
const GENERATED = '4a4c9a18-50f6-4d84-a7b7-2d83e3e45dc8'
|
|
@@ -12,16 +10,7 @@ const RETRY = '139137b5-af47-47ce-92b2-b64a2b0c63d7'
|
|
|
12
10
|
const originalFetch = globalThis.fetch
|
|
13
11
|
|
|
14
12
|
const schema = defineSchema('crm.test', {})
|
|
15
|
-
const
|
|
16
|
-
schema,
|
|
17
|
-
handlers: { functions: {}, classes: {}, interfaces: {} },
|
|
18
|
-
})
|
|
19
|
-
const deployed = createDeployment({
|
|
20
|
-
definition,
|
|
21
|
-
issuer: issuer.accept('https://crm.test'),
|
|
22
|
-
bundleHref: 'https://crm.test/domain.bundle.json',
|
|
23
|
-
bindings: { callables: [] },
|
|
24
|
-
}).publication
|
|
13
|
+
const deployed = releaseFor(schema, 'https://crm.test').publication
|
|
25
14
|
|
|
26
15
|
function publicationResponse(): Response {
|
|
27
16
|
return Response.json(deployed)
|
|
@@ -49,9 +38,7 @@ describe('direct domain install operation identity', () => {
|
|
|
49
38
|
recovery = input.recovery
|
|
50
39
|
requests.push(
|
|
51
40
|
await input.fn({
|
|
52
|
-
session: {
|
|
53
|
-
call: async (call: { input: unknown }) => call.input,
|
|
54
|
-
},
|
|
41
|
+
session: { schema: { install: async (input: unknown) => input } },
|
|
55
42
|
} as never),
|
|
56
43
|
)
|
|
57
44
|
},
|
|
@@ -62,7 +49,7 @@ describe('direct domain install operation identity', () => {
|
|
|
62
49
|
expect(requests).toEqual([
|
|
63
50
|
{
|
|
64
51
|
operation: GENERATED,
|
|
65
|
-
domains: [{
|
|
52
|
+
domains: [{ publication: { url: 'https://crm.test' } }],
|
|
66
53
|
},
|
|
67
54
|
])
|
|
68
55
|
expect(recovery).toEqual({
|
|
@@ -89,9 +76,7 @@ describe('direct domain install operation identity', () => {
|
|
|
89
76
|
runKernelCommand: async (input) => {
|
|
90
77
|
requests.push(
|
|
91
78
|
await input.fn({
|
|
92
|
-
session: {
|
|
93
|
-
call: async (call: { input: unknown }) => call.input,
|
|
94
|
-
},
|
|
79
|
+
session: { schema: { install: async (input: unknown) => input } },
|
|
95
80
|
} as never),
|
|
96
81
|
)
|
|
97
82
|
},
|
|
@@ -103,11 +88,34 @@ describe('direct domain install operation identity', () => {
|
|
|
103
88
|
expect(requests).toEqual([
|
|
104
89
|
{
|
|
105
90
|
operation: RETRY,
|
|
106
|
-
domains: [{
|
|
91
|
+
domains: [{ publication: { url: 'https://crm.test' } }],
|
|
107
92
|
},
|
|
108
93
|
])
|
|
109
94
|
})
|
|
110
95
|
|
|
96
|
+
test('keeps identity-override consent warnings out of machine output', async () => {
|
|
97
|
+
globalThis.fetch = mock(async () => publicationResponse()) as unknown as typeof fetch
|
|
98
|
+
const originalError = console.error
|
|
99
|
+
const warnings: unknown[][] = []
|
|
100
|
+
console.error = (...args: unknown[]) => {
|
|
101
|
+
warnings.push(args)
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
await installDirect(
|
|
105
|
+
'https://alias.test',
|
|
106
|
+
{ direct: true, json: true, allowIdentityOverride: true },
|
|
107
|
+
{
|
|
108
|
+
createOperationId: () => GENERATED,
|
|
109
|
+
runKernelCommand: async () => undefined,
|
|
110
|
+
},
|
|
111
|
+
)
|
|
112
|
+
} finally {
|
|
113
|
+
console.error = originalError
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
expect(warnings).toEqual([])
|
|
117
|
+
})
|
|
118
|
+
|
|
111
119
|
test('rejects a non-UUID operation before metadata or Kernel transport', async () => {
|
|
112
120
|
const originalExit = process.exit
|
|
113
121
|
const originalWrite = process.stderr.write
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { issuer } from '@astrale-os/sdk/auth'
|
|
3
|
-
import { createDeployment } from '@astrale-os/sdk/deployment'
|
|
4
|
-
import { defineSchema } from '@astrale-os/sdk/schema/v1'
|
|
1
|
+
import { defineSchema, schema as schemaApi } from '@astrale-os/sdk/schema'
|
|
5
2
|
import { afterAll, describe, expect, test } from 'bun:test'
|
|
6
3
|
|
|
7
4
|
import type { DomainInfo } from '../../lib/admin-domain'
|
|
8
5
|
|
|
6
|
+
import { releaseFor } from '../../__tests__/fixtures/publication'
|
|
9
7
|
import { byDefaultThenName, domainProjection, probe, type DomainRow } from '../domain/list'
|
|
10
8
|
|
|
11
9
|
const strip = (s: string): string => s.replace(/\[[0-9;]*m/g, '')
|
|
@@ -85,16 +83,7 @@ describe('domain list — canonical Publication check', () => {
|
|
|
85
83
|
|
|
86
84
|
test('reports the admitted schema revision in machine data', async () => {
|
|
87
85
|
const schema = defineSchema('catalog-check.example.dev', {})
|
|
88
|
-
const
|
|
89
|
-
schema,
|
|
90
|
-
handlers: { functions: {}, classes: {}, interfaces: {} },
|
|
91
|
-
})
|
|
92
|
-
const deployed = createDeployment({
|
|
93
|
-
definition,
|
|
94
|
-
issuer: issuer.accept('https://catalog-check.example.dev'),
|
|
95
|
-
bundleHref: 'https://catalog-check.example.dev/domain.bundle.json',
|
|
96
|
-
bindings: { callables: [] },
|
|
97
|
-
}).publication
|
|
86
|
+
const deployed = releaseFor(schema, 'https://catalog-check.example.dev').publication
|
|
98
87
|
const server = Bun.serve({
|
|
99
88
|
port: 0,
|
|
100
89
|
fetch(request) {
|
|
@@ -114,23 +103,14 @@ describe('domain list — canonical Publication check', () => {
|
|
|
114
103
|
),
|
|
115
104
|
).resolves.toMatchObject({
|
|
116
105
|
reachable: true,
|
|
117
|
-
schemaRevision:
|
|
106
|
+
schemaRevision: schemaApi.revision(schema),
|
|
118
107
|
checkError: null,
|
|
119
108
|
})
|
|
120
109
|
})
|
|
121
110
|
|
|
122
111
|
test('rejects a Publication whose origin differs from the catalog entry', async () => {
|
|
123
112
|
const schema = defineSchema('deployed.example.dev', {})
|
|
124
|
-
const
|
|
125
|
-
schema,
|
|
126
|
-
handlers: { functions: {}, classes: {}, interfaces: {} },
|
|
127
|
-
})
|
|
128
|
-
const deployed = createDeployment({
|
|
129
|
-
definition,
|
|
130
|
-
issuer: issuer.accept('https://deployed.example.dev'),
|
|
131
|
-
bundleHref: 'https://deployed.example.dev/domain.bundle.json',
|
|
132
|
-
bindings: { callables: [] },
|
|
133
|
-
}).publication
|
|
113
|
+
const deployed = releaseFor(schema, 'https://deployed.example.dev').publication
|
|
134
114
|
const server = Bun.serve({
|
|
135
115
|
port: 0,
|
|
136
116
|
fetch: () => Response.json(deployed),
|
|
@@ -1,21 +1,128 @@
|
|
|
1
|
+
import type { InstallResult } from '@astrale-os/sdk/client/schema'
|
|
2
|
+
|
|
3
|
+
import { defineSchema, schema } from '@astrale-os/sdk/schema'
|
|
1
4
|
import { describe, expect, test } from 'bun:test'
|
|
2
5
|
|
|
3
|
-
import { directInstallCallInput } from '../domain/install'
|
|
6
|
+
import { directInstallCallInput, directInstallPresentation } from '../domain/install'
|
|
7
|
+
|
|
8
|
+
const currentRevision = schema.revision(defineSchema('tasks.astrale.ai', {}))
|
|
4
9
|
|
|
5
10
|
describe('directInstallCallInput', () => {
|
|
6
11
|
test('sends the current remote install syscall, not a legacy url list', () => {
|
|
7
12
|
const operation = '4a4c9a18-50f6-4d84-a7b7-2d83e3e45dc8'
|
|
8
|
-
|
|
9
|
-
|
|
13
|
+
const input = directInstallCallInput('https://tasks.example.test', operation, 'secret')
|
|
14
|
+
|
|
15
|
+
expect(String(input.operation)).toBe(operation)
|
|
16
|
+
expect(input.domains).toEqual([
|
|
17
|
+
{
|
|
18
|
+
publication: {
|
|
19
|
+
url: 'https://tasks.example.test',
|
|
20
|
+
token: 'secret',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
])
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
test('presents a committed install from its receipt', () => {
|
|
27
|
+
const operation = directInstallCallInput(
|
|
28
|
+
'https://tasks.example.test',
|
|
29
|
+
'4a4c9a18-50f6-4d84-a7b7-2d83e3e45dc8',
|
|
30
|
+
).operation
|
|
31
|
+
const result = {
|
|
32
|
+
changed: true,
|
|
33
|
+
receipt: {
|
|
34
|
+
operation,
|
|
35
|
+
transitions: [
|
|
36
|
+
{
|
|
37
|
+
intent: {
|
|
38
|
+
transition: 'transition-1',
|
|
39
|
+
operation,
|
|
40
|
+
origin: 'tasks.astrale.ai',
|
|
41
|
+
previous: null,
|
|
42
|
+
generation: {
|
|
43
|
+
origin: 'tasks.astrale.ai',
|
|
44
|
+
revision: currentRevision,
|
|
45
|
+
generation: 'sha256:generation',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
phase: 'cutover',
|
|
49
|
+
state: 'committed',
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
} satisfies InstallResult
|
|
54
|
+
|
|
55
|
+
expect(directInstallPresentation(result, 'ignored')).toEqual({
|
|
56
|
+
operation: '4a4c9a18-50f6-4d84-a7b7-2d83e3e45dc8',
|
|
57
|
+
origin: 'tasks.astrale.ai',
|
|
58
|
+
revision: currentRevision,
|
|
59
|
+
status: 'installed',
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('presents an idempotent install from the current Domain observation', () => {
|
|
64
|
+
const operation = '4a4c9a18-50f6-4d84-a7b7-2d83e3e45dc8'
|
|
65
|
+
const result = {
|
|
66
|
+
changed: false,
|
|
10
67
|
domains: [
|
|
11
68
|
{
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
69
|
+
origin: 'tasks.astrale.ai',
|
|
70
|
+
revision: currentRevision,
|
|
71
|
+
generation: 'sha256:generation',
|
|
72
|
+
publication: null,
|
|
73
|
+
readiness: 'sha256:readiness',
|
|
74
|
+
capabilities: { requested: {}, materialized: {} },
|
|
75
|
+
bindings: { callables: [], views: [] },
|
|
17
76
|
},
|
|
18
77
|
],
|
|
78
|
+
} satisfies InstallResult
|
|
79
|
+
|
|
80
|
+
expect(directInstallPresentation(result, operation)).toEqual({
|
|
81
|
+
operation,
|
|
82
|
+
origin: 'tasks.astrale.ai',
|
|
83
|
+
revision: currentRevision,
|
|
84
|
+
status: 'already current',
|
|
19
85
|
})
|
|
20
86
|
})
|
|
87
|
+
|
|
88
|
+
test('rejects a changed result without a committed transition', () => {
|
|
89
|
+
const result = {
|
|
90
|
+
changed: true,
|
|
91
|
+
receipt: { operation: '4a4c9a18-50f6-4d84-a7b7-2d83e3e45dc8', transitions: [] },
|
|
92
|
+
} as unknown as InstallResult
|
|
93
|
+
|
|
94
|
+
expect(() => directInstallPresentation(result, 'ignored')).toThrow(
|
|
95
|
+
'Kernel install returned no committed Domain transition.',
|
|
96
|
+
)
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
test('rejects a committed transition without an installed generation', () => {
|
|
100
|
+
const operation = directInstallCallInput(
|
|
101
|
+
'https://tasks.example.test',
|
|
102
|
+
'4a4c9a18-50f6-4d84-a7b7-2d83e3e45dc8',
|
|
103
|
+
).operation
|
|
104
|
+
const result = {
|
|
105
|
+
changed: true,
|
|
106
|
+
receipt: {
|
|
107
|
+
operation,
|
|
108
|
+
transitions: [
|
|
109
|
+
{
|
|
110
|
+
intent: {
|
|
111
|
+
transition: 'transition-1',
|
|
112
|
+
operation,
|
|
113
|
+
origin: 'tasks.astrale.ai',
|
|
114
|
+
previous: null,
|
|
115
|
+
generation: null,
|
|
116
|
+
},
|
|
117
|
+
phase: 'cutover',
|
|
118
|
+
state: 'committed',
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
},
|
|
122
|
+
} satisfies InstallResult
|
|
123
|
+
|
|
124
|
+
expect(() => directInstallPresentation(result, 'ignored')).toThrow(
|
|
125
|
+
'Kernel install returned a committed transition without a Domain generation.',
|
|
126
|
+
)
|
|
127
|
+
})
|
|
21
128
|
})
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { issuer } from '@astrale-os/sdk/auth'
|
|
3
|
-
import { createDeployment } from '@astrale-os/sdk/deployment'
|
|
4
|
-
import { defineSchema } from '@astrale-os/sdk/schema/v1'
|
|
1
|
+
import { defineSchema } from '@astrale-os/sdk/schema'
|
|
5
2
|
import { afterAll, describe, expect, test } from 'bun:test'
|
|
6
3
|
|
|
4
|
+
import { releaseFor } from '../../__tests__/fixtures/publication'
|
|
7
5
|
import { domainRefFromTarget, isIdentityOverride, probeDeclaredOrigin } from '../domain/install'
|
|
8
6
|
|
|
9
7
|
describe('admin-path target classification', () => {
|
|
@@ -47,16 +45,7 @@ describe('declared-origin Publication probe', () => {
|
|
|
47
45
|
|
|
48
46
|
test('reads origin from a well-formed canonical Publication', async () => {
|
|
49
47
|
const schema = defineSchema('crm.acme.dev', {})
|
|
50
|
-
const
|
|
51
|
-
schema,
|
|
52
|
-
handlers: { functions: {}, classes: {}, interfaces: {} },
|
|
53
|
-
})
|
|
54
|
-
const deployed = createDeployment({
|
|
55
|
-
definition,
|
|
56
|
-
issuer: issuer.accept('https://crm.acme.dev'),
|
|
57
|
-
bundleHref: 'https://crm.acme.dev/domain.bundle.json',
|
|
58
|
-
bindings: { callables: [] },
|
|
59
|
-
}).publication
|
|
48
|
+
const deployed = releaseFor(schema, 'https://crm.acme.dev').publication
|
|
60
49
|
const url = servePublication((req) =>
|
|
61
50
|
new URL(req.url).pathname === '/.well-known/astrale/domain.json'
|
|
62
51
|
? Response.json(deployed)
|
|
@@ -65,11 +54,11 @@ describe('declared-origin Publication probe', () => {
|
|
|
65
54
|
expect(await probeDeclaredOrigin(url)).toBe('crm.acme.dev')
|
|
66
55
|
})
|
|
67
56
|
|
|
68
|
-
test('does not accept the
|
|
69
|
-
const
|
|
57
|
+
test('does not accept a Publication without the canonical origin field', async () => {
|
|
58
|
+
const invalid = servePublication(() =>
|
|
70
59
|
Response.json({ iss: 'https://x', domainName: 'crm.acme.dev' }),
|
|
71
60
|
)
|
|
72
|
-
expect(await probeDeclaredOrigin(
|
|
61
|
+
expect(await probeDeclaredOrigin(invalid)).toBeUndefined()
|
|
73
62
|
})
|
|
74
63
|
|
|
75
64
|
test('degrades to undefined on invalid Publication, non-200, bad JSON, or dead host', async () => {
|
|
@@ -5,7 +5,7 @@ import type { InstanceInfo } from '../../lib/admin-instance'
|
|
|
5
5
|
import { buildInstanceRows, type Bookmark } from '../instance/list'
|
|
6
6
|
|
|
7
7
|
const managed: InstanceInfo[] = [
|
|
8
|
-
{ id: 'demo', slug: 'demo', url: 'https://demo.eu.astrale.ai',
|
|
8
|
+
{ id: 'demo', slug: 'demo', url: 'https://demo.eu.astrale.ai', state: 'ready' },
|
|
9
9
|
]
|
|
10
10
|
|
|
11
11
|
function bookmark(overrides: Partial<Bookmark> = {}): Bookmark {
|