@astrale-os/cli 0.8.1-alpha.0 → 0.8.1-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/astrale.js +62959 -41238
- package/dist/public/connect-core.js +55030 -0
- package/dist/public/keys/index.js +45631 -0
- package/dist/public/paths/index.js +43990 -0
- package/dist/types/admin/instance/model.d.ts +40 -0
- package/dist/types/connect-core.d.ts +22 -0
- package/dist/types/connection/auth.d.ts +33 -0
- package/dist/types/errors.d.ts +23 -0
- package/dist/types/identity/registry.d.ts +25 -0
- package/dist/types/keys/algorithm.d.ts +6 -0
- package/dist/types/keys/credential.d.ts +21 -0
- package/dist/types/keys/index.d.ts +4 -0
- package/dist/types/keys/pair.d.ts +34 -0
- package/dist/types/lib/admin-target.d.ts +74 -0
- package/dist/types/lib/ca-fetch.d.ts +2 -0
- package/dist/types/lib/config.d.ts +71 -0
- package/dist/types/lib/format.d.ts +1 -0
- package/dist/types/lib/idp-session.d.ts +33 -0
- package/dist/types/lib/idp.d.ts +397 -0
- package/dist/types/lib/instance-target.d.ts +36 -0
- package/dist/types/lib/instance.d.ts +186 -0
- package/dist/types/lib/log.d.ts +30 -0
- package/dist/types/lib/login-flow.d.ts +49 -0
- package/dist/types/lib/meta.d.ts +36 -0
- package/dist/types/lib/output.d.ts +83 -0
- package/dist/types/lib/table.d.ts +18 -0
- package/dist/types/lib/validation.d.ts +11 -0
- package/dist/types/paths/index.d.ts +2 -0
- package/dist/types/state/exchange-credentials.d.ts +25 -0
- package/dist/types/state/files.d.ts +9 -0
- package/dist/types/state/identities.d.ts +42 -0
- package/dist/types/state/index.d.ts +8 -0
- package/dist/types/state/paths.d.ts +32 -0
- package/package.json +22 -7
- package/src/admin/.spec/api.d.ts +3 -0
- package/src/admin/.spec/architecture.md +15 -0
- package/src/admin/.spec/icon.svg +3 -0
- package/src/admin/.spec/layout.ts +6 -0
- package/src/admin/catalog/.spec/api.d.ts +65 -0
- package/src/admin/catalog/.spec/architecture.md +6 -0
- package/src/admin/catalog/.spec/icon.svg +3 -0
- package/src/admin/catalog/.spec/layout.ts +6 -0
- package/src/admin/catalog/__tests__/client.test.ts +171 -0
- package/src/admin/catalog/client.ts +214 -0
- package/src/admin/catalog/index.ts +13 -0
- package/src/admin/catalog/model.ts +42 -0
- package/src/admin/catalog/tsconfig.json +8 -0
- package/src/admin/graph/.spec/api.d.ts +28 -0
- package/src/admin/graph/.spec/architecture.md +5 -0
- package/src/admin/graph/.spec/icon.svg +3 -0
- package/src/admin/graph/.spec/layout.ts +3 -0
- package/src/admin/graph/index.ts +6 -0
- package/src/admin/graph/nodes.ts +56 -0
- package/src/admin/index.ts +2 -0
- package/src/admin/instance/.spec/api.d.ts +66 -0
- package/src/admin/instance/.spec/architecture.md +10 -0
- package/src/admin/instance/.spec/icon.svg +3 -0
- package/src/admin/instance/.spec/layout.ts +6 -0
- package/src/admin/instance/__tests__/client.test.ts +289 -0
- package/src/admin/instance/client.ts +298 -0
- package/src/admin/instance/index.ts +16 -0
- package/src/admin/instance/model.ts +65 -0
- package/src/admin/instance/tsconfig.json +8 -0
- package/src/commands/__tests__/admin-instance.test.ts +3 -36
- package/src/commands/__tests__/call.test.ts +21 -68
- package/src/commands/__tests__/domain-install-owned.test.ts +26 -27
- package/src/commands/__tests__/domain-list.test.ts +2 -6
- package/src/commands/__tests__/logs.test.ts +50 -98
- package/src/commands/__tests__/ls.test.ts +21 -17
- package/src/commands/__tests__/read-commands.test.ts +171 -101
- package/src/commands/__tests__/view.test.ts +100 -51
- package/src/commands/admin/status.ts +3 -3
- package/src/commands/admin/use.ts +29 -6
- package/src/commands/auth/login.ts +1 -1
- package/src/commands/auth/logout.ts +4 -2
- package/src/commands/auth/status.ts +2 -2
- package/src/commands/auth/token.ts +2 -2
- package/src/commands/browser.ts +1 -1
- package/src/commands/call.ts +55 -91
- package/src/commands/describe.ts +52 -147
- package/src/commands/domain/install.ts +81 -50
- package/src/commands/domain/list.ts +4 -8
- package/src/commands/domain/publish.ts +9 -31
- package/src/commands/get.ts +32 -65
- package/src/commands/identity/__tests__/register.test.ts +93 -0
- package/src/commands/identity/create.ts +2 -2
- package/src/commands/identity/delete.ts +2 -2
- package/src/commands/identity/export.ts +7 -33
- package/src/commands/identity/import.ts +21 -70
- package/src/commands/identity/list.ts +2 -2
- package/src/commands/identity/register.ts +148 -117
- package/src/commands/identity/sync.ts +2 -2
- package/src/commands/identity/unsync.ts +2 -2
- package/src/commands/identity/use.ts +2 -2
- package/src/commands/identity/whoami.ts +2 -2
- package/src/commands/idp/add.ts +1 -1
- package/src/commands/idp/list.ts +1 -1
- package/src/commands/idp/refresh.ts +1 -1
- package/src/commands/idp/remove.ts +2 -2
- package/src/commands/idp/show.ts +1 -1
- package/src/commands/instance/active.ts +2 -2
- package/src/commands/instance/bookmark.ts +8 -2
- package/src/commands/instance/create.ts +1 -1
- package/src/commands/instance/delete.ts +4 -10
- package/src/commands/instance/forget.ts +1 -1
- package/src/commands/instance/list.ts +3 -3
- package/src/commands/instance/status.ts +5 -7
- package/src/commands/instance/use.ts +3 -3
- package/src/commands/logs.ts +152 -279
- package/src/commands/ls.ts +78 -204
- package/src/commands/mutate.ts +70 -139
- package/src/commands/query.ts +100 -278
- package/src/commands/session/analyze.ts +1 -1
- package/src/commands/session/list.ts +1 -1
- package/src/commands/setup.ts +1 -1
- package/src/commands/status.ts +1 -1
- package/src/commands/studio.ts +1 -1
- package/src/commands/token.ts +26 -21
- package/src/commands/update.ts +1 -1
- package/src/commands/use.ts +2 -3
- package/src/commands/view-serve.ts +1 -1
- package/src/commands/view.ts +67 -109
- package/src/connect-core.test.ts +38 -0
- package/src/connect-core.ts +42 -0
- package/src/connection/.spec/api.d.ts +111 -0
- package/src/connection/.spec/architecture.md +41 -0
- package/src/connection/.spec/capabilities/connection.ts +13 -0
- package/src/connection/.spec/examples/call.ts +7 -0
- package/src/connection/.spec/flows/command.ts +20 -0
- package/src/connection/.spec/flows/session.ts +61 -0
- package/src/connection/.spec/laws/connection.ts +181 -0
- package/src/connection/.spec/layout.ts +19 -0
- package/src/{kernel → connection}/__tests__/auth.test.ts +26 -2
- package/src/connection/__tests__/ca-fetch.test.ts +53 -0
- package/src/connection/__tests__/call.test.ts +17 -0
- package/src/connection/__tests__/credential.test.ts +109 -0
- package/src/connection/__tests__/errors.test.ts +96 -0
- package/src/connection/__tests__/exchange.test.ts +224 -0
- package/src/connection/__tests__/fixtures/localhost-cert.pem +19 -0
- package/src/connection/__tests__/fixtures/localhost-key.base64 +1 -0
- package/src/connection/__tests__/managed.test.ts +39 -0
- package/src/connection/__tests__/self.test.ts +51 -0
- package/src/connection/__tests__/session.test.ts +140 -0
- package/src/connection/__tests__/target.test.ts +93 -0
- package/src/{kernel → connection}/auth.ts +8 -8
- package/src/connection/call.ts +7 -0
- package/src/{kernel/run.ts → connection/command.ts} +22 -13
- package/src/connection/credential.ts +114 -0
- package/src/{kernel → connection}/errors.ts +32 -9
- package/src/connection/exchange.ts +274 -0
- package/src/connection/index.ts +8 -0
- package/src/connection/self.ts +120 -0
- package/src/connection/session.ts +176 -0
- package/src/connection/target.ts +111 -0
- package/src/connection/tsconfig.json +6 -0
- package/src/graph/.spec/api.d.ts +34 -0
- package/src/graph/.spec/laws/documents.ts +24 -0
- package/src/graph/.spec/laws/projection.ts +13 -0
- package/src/graph/.spec/layout.ts +6 -0
- package/src/graph/__tests__/mutation.test.ts +43 -0
- package/src/graph/__tests__/projection.test.ts +22 -0
- package/src/graph/__tests__/query.test.ts +154 -0
- package/src/graph/index.ts +3 -0
- package/src/graph/mutation.ts +18 -0
- package/src/graph/projection.ts +21 -0
- package/src/graph/query.ts +108 -0
- package/src/graph/tsconfig.json +6 -0
- package/src/identity/.history/ard/bootstrap-root-transfer.md +57 -0
- package/src/identity/.history/ard/domain-mediated-registration.md +36 -0
- package/src/identity/.spec/api.d.ts +124 -0
- package/src/identity/.spec/architecture.md +33 -0
- package/src/identity/.spec/capabilities/identity.ts +7 -0
- package/src/identity/.spec/flows/bootstrap-root.ts +79 -0
- package/src/identity/.spec/flows/domain-mediated-registration.ts +51 -0
- package/src/identity/.spec/flows/import.ts +29 -0
- package/src/identity/.spec/laws/identity.ts +56 -0
- package/src/identity/.spec/layout.ts +13 -0
- package/src/identity/.spec/schemas/identity-export-v1.schema.json +25 -0
- package/src/identity/__tests__/fixtures/registry-journey.ts +53 -0
- package/src/identity/__tests__/registration.test.ts +64 -0
- package/src/identity/__tests__/registry.test.ts +70 -0
- package/src/identity/__tests__/transfer.test.ts +198 -0
- package/src/identity/index.ts +23 -0
- package/src/identity/registration.ts +72 -0
- package/src/identity/registry.ts +172 -0
- package/src/identity/transfer.ts +187 -0
- package/src/identity/tsconfig.json +6 -0
- package/src/index.ts +1 -0
- package/src/keys/.spec/api.d.ts +74 -0
- package/src/keys/.spec/architecture.md +13 -0
- package/src/keys/.spec/laws/keys.ts +43 -0
- package/src/keys/.spec/layout.ts +6 -0
- package/src/keys/__tests__/algorithm.test.ts +39 -0
- package/src/keys/__tests__/keys.test.ts +168 -0
- package/src/keys/algorithm.ts +33 -0
- package/src/keys/credential.ts +112 -0
- package/src/keys/index.ts +14 -0
- package/src/keys/pair.ts +219 -0
- package/src/keys/tsconfig.json +6 -0
- package/src/lib/__tests__/admin-target.test.ts +67 -7
- package/src/lib/__tests__/binary.test.ts +2 -3
- package/src/lib/__tests__/command-dx.test.ts +2 -2
- package/src/lib/__tests__/config.test.ts +3 -2
- package/src/lib/__tests__/idp.test.ts +4 -6
- package/src/lib/__tests__/instance-target.test.ts +7 -4
- package/src/lib/__tests__/local-status.test.ts +1 -1
- package/src/lib/__tests__/log.test.ts +31 -0
- package/src/lib/__tests__/meta.test.ts +55 -0
- package/src/lib/__tests__/sdk-deps.test.ts +1 -1
- package/src/lib/__tests__/self.test.ts +8 -230
- package/src/lib/__tests__/use-target.test.ts +1 -1
- package/src/lib/__tests__/view-open-intent.test.ts +78 -104
- package/src/lib/__tests__/view-session.test.ts +99 -0
- package/src/lib/admin-domain.ts +39 -25
- package/src/lib/admin-instance.ts +38 -43
- package/src/lib/admin-target.ts +67 -13
- package/src/lib/binary.ts +13 -34
- package/src/lib/browser.ts +1 -1
- package/src/{kernel → lib}/ca-fetch.ts +35 -27
- package/src/lib/config.ts +1 -1
- package/src/lib/idp-session.ts +1 -1
- package/src/lib/idp.ts +3 -8
- package/src/lib/instance-target.ts +12 -8
- package/src/lib/instance.ts +34 -2
- package/src/lib/local-status.ts +2 -2
- package/src/lib/log.ts +3 -1
- package/src/lib/login-flow.ts +32 -5
- package/src/lib/meta.ts +15 -11
- package/src/lib/provision-instance.ts +4 -12
- package/src/lib/self.ts +5 -147
- package/src/lib/update.ts +1 -1
- package/src/lib/use-target.ts +1 -1
- package/src/lib/validation.ts +2 -2
- package/src/lib/view/open-intent.ts +7 -37
- package/src/lib/view/port-allocation.ts +1 -1
- package/src/lib/view/resolve.ts +52 -45
- package/src/lib/view/server.ts +16 -33
- package/src/lib/view/session.ts +51 -22
- package/src/paths/.spec/api.d.ts +13 -0
- package/src/paths/.spec/architecture.md +5 -0
- package/src/paths/.spec/layout.ts +3 -0
- package/src/paths/index.ts +13 -0
- package/src/program/.spec/api.d.ts +42 -0
- package/src/program/.spec/architecture.md +18 -0
- package/src/program/.spec/laws/program.ts +29 -0
- package/src/program/.spec/layout.ts +14 -0
- package/src/program/__tests__/program.test.ts +359 -0
- package/src/program/build.ts +190 -0
- package/src/program/command.ts +42 -0
- package/src/program/index.ts +2 -0
- package/src/program/options.ts +40 -0
- package/src/{registry.ts → program/registry.ts} +5 -1
- package/src/program/tsconfig.json +6 -0
- package/src/setup/steps/admin.ts +18 -3
- package/src/setup/steps/instance.ts +1 -1
- package/src/state/.spec/api.d.ts +133 -0
- package/src/state/.spec/architecture.md +31 -0
- package/src/state/.spec/capabilities/state.ts +7 -0
- package/src/state/.spec/flows/identity-update.ts +22 -0
- package/src/state/.spec/laws/state.ts +73 -0
- package/src/state/.spec/layout.ts +14 -0
- package/src/state/__tests__/exchange-credentials.test.ts +188 -0
- package/src/state/__tests__/files.test.ts +113 -0
- package/src/state/__tests__/fixtures/identity-transition.ts +37 -0
- package/src/state/__tests__/identities.test.ts +142 -0
- package/src/state/__tests__/paths.test.ts +27 -0
- package/src/state/exchange-credentials.ts +219 -0
- package/src/state/files.ts +129 -0
- package/src/state/identities.ts +236 -0
- package/src/state/index.ts +29 -0
- package/src/state/paths.ts +61 -0
- package/src/state/tsconfig.json +6 -0
- package/src/telemetry/__tests__/redact.test.ts +3 -3
- package/src/telemetry/__tests__/trigger.test.ts +1 -1
- package/src/telemetry/settings.ts +1 -1
- package/src/telemetry/store.ts +1 -1
- package/src/test-utils.ts +1 -1
- package/studio/client/dist/assets/{elk-api-DVw5WDTH.js → elk-api-D0cBetPW.js} +1 -1
- package/studio/client/dist/assets/index-Dspir4w7.js +81 -0
- package/studio/client/dist/assets/{index-Dl709Ra1.js → index-bVD2KJgz.js} +4 -4
- package/studio/client/dist/index.html +1 -1
- package/studio/package.json +10 -1
- package/studio/server/introspect/extractor.ts +1 -1
- package/studio/server/state/views.test.ts +3 -7
- package/studio/server/state/views.ts +23 -30
- package/tsconfig.json +1 -1
- package/viewer/dist/main.js +65 -39
- package/src/command.ts +0 -42
- package/src/commands/__tests__/help-contract.test.ts +0 -164
- package/src/kernel/__tests__/client-owned-lookup.test.ts +0 -51
- package/src/kernel/__tests__/errors.test.ts +0 -43
- package/src/kernel/__tests__/expand.test.ts +0 -123
- package/src/kernel/client.ts +0 -214
- package/src/kernel/expand.ts +0 -192
- package/src/kernel/graph.ts +0 -96
- package/src/kernel/index.ts +0 -29
- package/src/kernel/options.ts +0 -22
- package/src/kernel/types.ts +0 -14
- package/src/lib/__tests__/domain-identity.test.ts +0 -60
- package/src/lib/__tests__/fs-atomic.test.ts +0 -104
- package/src/lib/__tests__/identity.test.ts +0 -79
- package/src/lib/__tests__/keys.test.ts +0 -129
- package/src/lib/domain-identity.ts +0 -49
- package/src/lib/env.ts +0 -49
- package/src/lib/fs-atomic.ts +0 -126
- package/src/lib/identity.ts +0 -256
- package/src/lib/keys.ts +0 -294
- package/src/lib/paths.ts +0 -11
- package/src/program.ts +0 -213
- package/studio/client/dist/assets/index-CTbkDp3z.js +0 -81
|
@@ -1,30 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { readFile, writeFile, mkdir } from 'node:fs/promises'
|
|
3
|
-
import { dirname } from 'node:path'
|
|
1
|
+
import { readFile } from 'node:fs/promises'
|
|
4
2
|
|
|
5
|
-
import type { CommandDefinition } from '../../
|
|
6
|
-
import type { RegistryMode } from '../../lib/validation'
|
|
3
|
+
import type { CommandDefinition } from '../../program/index'
|
|
7
4
|
|
|
8
|
-
import {
|
|
9
|
-
|
|
5
|
+
import {
|
|
6
|
+
decodeIdentityExport,
|
|
7
|
+
importIdentity,
|
|
8
|
+
isEncryptedIdentityExport,
|
|
9
|
+
} from '../../identity/index'
|
|
10
10
|
import { fatal, log } from '../../lib/log'
|
|
11
11
|
import { readPassphrase } from '../../lib/prompt'
|
|
12
12
|
|
|
13
|
-
type ExportEnvelope = {
|
|
14
|
-
version?: number
|
|
15
|
-
subject: string
|
|
16
|
-
mode?: RegistryMode
|
|
17
|
-
kid?: string
|
|
18
|
-
issuer?: string
|
|
19
|
-
privateJwk: Record<string, unknown>
|
|
20
|
-
publicJwk: Record<string, unknown>
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function looksEncrypted(raw: string): boolean {
|
|
24
|
-
// JOSE compact JWE is 5 base64 segments separated by `.`.
|
|
25
|
-
return raw.trim().split('.').length === 5 && !raw.trim().startsWith('{')
|
|
26
|
-
}
|
|
27
|
-
|
|
28
13
|
export default {
|
|
29
14
|
name: 'import',
|
|
30
15
|
description: 'Import an identity keypair envelope (auto-detects JWE)',
|
|
@@ -46,54 +31,20 @@ export default {
|
|
|
46
31
|
action: async (path: string, opts: { name?: string; issuer?: string; replace?: boolean }) => {
|
|
47
32
|
try {
|
|
48
33
|
const raw = await readFile(path, 'utf-8')
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const env = JSON.parse(envelopeJson) as ExportEnvelope
|
|
66
|
-
if (!env?.subject || !env?.privateJwk || !env?.publicJwk) {
|
|
67
|
-
fatal(new Error('Invalid envelope: missing subject / privateJwk / publicJwk'))
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Validate the keypair parses before touching the registry.
|
|
71
|
-
await importJWK(env.privateJwk as never, 'ES256')
|
|
72
|
-
|
|
73
|
-
const name = opts.name ?? env.subject
|
|
74
|
-
// Create registry entry (without regenerating keys — we'll write the imported ones).
|
|
75
|
-
if (opts.replace) {
|
|
76
|
-
await upsertKeyIdentity(name, {
|
|
77
|
-
subject: env.subject,
|
|
78
|
-
mode: env.mode ?? 'local',
|
|
79
|
-
issuer: opts.issuer ?? env.issuer,
|
|
80
|
-
kid: env.kid,
|
|
81
|
-
})
|
|
82
|
-
} else {
|
|
83
|
-
await createIdentity(name, {
|
|
84
|
-
subject: env.subject,
|
|
85
|
-
mode: env.mode ?? 'local',
|
|
86
|
-
issuer: opts.issuer ?? env.issuer,
|
|
87
|
-
kid: env.kid,
|
|
88
|
-
skipKeygen: true,
|
|
89
|
-
})
|
|
90
|
-
}
|
|
91
|
-
const { privatePath, publicPath } = keypairPaths(env.subject)
|
|
92
|
-
await mkdir(dirname(privatePath), { recursive: true })
|
|
93
|
-
await writeFile(privatePath, JSON.stringify(env.privateJwk, null, 2), { mode: 0o600 })
|
|
94
|
-
await writeFile(publicPath, JSON.stringify(env.publicJwk, null, 2), { mode: 0o600 })
|
|
95
|
-
|
|
96
|
-
log.success(`Imported identity "${name}" (subject=${env.subject}, kid=${env.kid ?? '?'})`)
|
|
34
|
+
const passphrase = isEncryptedIdentityExport(raw)
|
|
35
|
+
? await readPassphrase('Passphrase: ')
|
|
36
|
+
: undefined
|
|
37
|
+
const envelope = await decodeIdentityExport(raw, passphrase)
|
|
38
|
+
const name = opts.name ?? envelope.subject
|
|
39
|
+
const identity = await importIdentity(envelope, {
|
|
40
|
+
name,
|
|
41
|
+
issuer: opts.issuer,
|
|
42
|
+
replace: opts.replace,
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
log.success(
|
|
46
|
+
`Imported identity "${name}" (subject=${identity.subject}, kid=${identity.kid ?? '?'})`,
|
|
47
|
+
)
|
|
97
48
|
} catch (e) {
|
|
98
49
|
fatal(e)
|
|
99
50
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import chalk from 'chalk'
|
|
2
2
|
|
|
3
|
-
import type { CommandDefinition } from '../../command'
|
|
4
3
|
import type { ListOpts, ListProjection } from '../../lib/output'
|
|
4
|
+
import type { CommandDefinition } from '../../program/index'
|
|
5
5
|
|
|
6
|
-
import { readIdentities } from '../../
|
|
6
|
+
import { readIdentities } from '../../identity/index'
|
|
7
7
|
import { log } from '../../lib/log'
|
|
8
8
|
import { isMachine, presentList, RAW_OUTPUT_OPTIONS } from '../../lib/output'
|
|
9
9
|
|
|
@@ -1,164 +1,195 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { IssuerId, JsonWebKey, ProvisionRequest } from '@astrale-os/sdk/auth'
|
|
2
|
+
import type { JWK } from 'jose'
|
|
3
|
+
|
|
4
|
+
import { provision, jwk } from '@astrale-os/sdk/auth'
|
|
5
|
+
import { ClassPath } from '@astrale-os/sdk/graph/class'
|
|
6
|
+
import { LocalBinding } from '@astrale-os/sdk/graph/model'
|
|
7
|
+
import { normalizeProperties } from '@astrale-os/sdk/graph/properties'
|
|
8
|
+
import { MutationAST } from '@astrale-os/sdk/mutation'
|
|
9
|
+
import { importJWK, SignJWT } from 'jose'
|
|
2
10
|
import { readFile } from 'node:fs/promises'
|
|
3
11
|
|
|
4
|
-
import type {
|
|
5
|
-
import type {
|
|
12
|
+
import type { KernelCommandOpts } from '../../connection'
|
|
13
|
+
import type { IdentityRegistrationResult } from '../../identity/index'
|
|
14
|
+
import type { CommandDefinition } from '../../program/index'
|
|
6
15
|
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { getActive } from '../../lib/instance'
|
|
11
|
-
import { fileExists, keypairPaths } from '../../lib/keys'
|
|
16
|
+
import { registrationKeyForTarget, runKernelCommand } from '../../connection'
|
|
17
|
+
import { getIdentity, setRegistration, submitIdentityProvision } from '../../identity/index'
|
|
18
|
+
import { fileExists, keypairPaths } from '../../keys/index'
|
|
12
19
|
import { fatal, log } from '../../lib/log'
|
|
13
20
|
import { output } from '../../lib/output'
|
|
14
21
|
|
|
15
|
-
type RegisterIdentityResult = { iss: string; sub: string }
|
|
16
|
-
|
|
17
22
|
type RegisterOpts = KernelCommandOpts & {
|
|
18
23
|
class?: string
|
|
19
|
-
path?: string
|
|
20
24
|
props?: string
|
|
25
|
+
via?: string
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
async function readJwk(path: string): Promise<JWK> {
|
|
24
|
-
|
|
25
|
-
return JSON.parse(raw) as JWK
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Discover the identity-bearer class on the target instance: find the
|
|
30
|
-
* installed domain that owns a `User` class (workspace on managed instances)
|
|
31
|
-
* and address it semantically.
|
|
32
|
-
* The bearer class must exist before a non-root identity can be registered;
|
|
33
|
-
* failing here names the real problem instead of surfacing as a confusing
|
|
34
|
-
* permission error on a hardcoded origin.
|
|
35
|
-
*/
|
|
36
|
-
async function resolveUserClassPath(ctx: ClientContext): Promise<string> {
|
|
37
|
-
const graph = bindGraph(ctx)
|
|
38
|
-
// Root's direct children are the installed Domain nodes.
|
|
39
|
-
const result = await graph.children('/')
|
|
40
|
-
const domains = result.nodes
|
|
41
|
-
.filter((n) => n.class.className === 'Domain')
|
|
42
|
-
.map((n) => n.path.raw.replace(/^\//, ''))
|
|
43
|
-
.filter(Boolean)
|
|
44
|
-
for (const origin of domains) {
|
|
45
|
-
// The class materializes as a `class.User` Folder under the domain mount;
|
|
46
|
-
// a resolving node means the domain declares it (null when absent).
|
|
47
|
-
if (await graph.get(`/${origin}/class.User`)) {
|
|
48
|
-
return `/:${origin}:class.User`
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
throw new Error(
|
|
52
|
-
'No installed domain declares a `User` class on this instance — registering a ' +
|
|
53
|
-
'non-root identity needs an identity-bearer class (install workspace or another ' +
|
|
54
|
-
'domain, or pass --class <classPath> explicitly).',
|
|
55
|
-
)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async function mintBootstrapJwt(privateJwk: JWK): Promise<string> {
|
|
59
|
-
const kid = (privateJwk.kid as string | undefined) ?? 'bootstrap'
|
|
60
|
-
const key = await importJWK(privateJwk, 'ES256')
|
|
61
|
-
return new SignJWT({})
|
|
62
|
-
.setProtectedHeader({ alg: 'ES256', kid })
|
|
63
|
-
.setIssuer('self')
|
|
64
|
-
.setSubject('bootstrap')
|
|
65
|
-
.setAudience('bootstrap')
|
|
66
|
-
.setIssuedAt()
|
|
67
|
-
.setExpirationTime('5m')
|
|
68
|
-
.sign(key)
|
|
29
|
+
return JSON.parse(await readFile(path, 'utf8')) as JWK
|
|
69
30
|
}
|
|
70
31
|
|
|
71
32
|
export default {
|
|
72
33
|
name: 'register',
|
|
73
|
-
description:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
34
|
+
description: 'Atomically provision a local key identity and its V2 graph Node',
|
|
35
|
+
afterHelpText: `
|
|
36
|
+
Behavior:
|
|
37
|
+
Creates one Node through Mutation V3 and designates it as a self-proven
|
|
38
|
+
Identity in the same atomic Auth.provision request. --class is required;
|
|
39
|
+
--props must use fully-qualified Property keys owned by that Class.
|
|
40
|
+
|
|
41
|
+
By default the authenticated caller submits the request directly to Kernel
|
|
42
|
+
Auth.provision. Use --via for an application-owned identity Class: the CLI
|
|
43
|
+
sends the exact self-proven request through that Domain callable, then admits
|
|
44
|
+
its result and stores the same target-bound registration. The callable owns
|
|
45
|
+
authorization; the CLI never receives installed Domain authority.
|
|
46
|
+
|
|
47
|
+
Kernel V2 Nodes have opaque identity and no caller-assigned storage path, so
|
|
48
|
+
the historical --path option no longer exists. The CLI binds the key proof
|
|
49
|
+
to the exact provision fingerprint and target Kernel audience, then caches
|
|
50
|
+
the returned (issuer, subject) for subsequent calls.
|
|
51
|
+
|
|
52
|
+
Example:
|
|
53
|
+
$ astrale identity register alice --class /:accounts.example:class.User \
|
|
54
|
+
--props '{"accounts.example:class.User.property.name":"Alice"}' -i staging
|
|
55
|
+
$ astrale identity register responder --class /:ops.example:class.Operator \
|
|
56
|
+
--via /:ops.example:function.provisionOperator -i staging
|
|
57
|
+
`,
|
|
58
|
+
arguments: [{ name: 'name', description: 'Local identity name', required: true }],
|
|
77
59
|
options: [
|
|
78
60
|
{
|
|
79
61
|
flags: '--class <classPath>',
|
|
80
|
-
description:
|
|
81
|
-
'Class path of the identity node to create (default: the installed domain that declares class.User)',
|
|
62
|
+
description: 'Exact Class of the identity-bearing Node (required)',
|
|
82
63
|
},
|
|
83
64
|
{
|
|
84
|
-
flags: '--
|
|
85
|
-
description: '
|
|
65
|
+
flags: '--props <json>',
|
|
66
|
+
description: 'Fully-qualified canonical properties for the new Node',
|
|
86
67
|
},
|
|
87
68
|
{
|
|
88
|
-
flags: '--
|
|
89
|
-
description:
|
|
90
|
-
'Extra props for the identity node (JSON). A User-class node defaults ' +
|
|
91
|
-
'firstName/lastName to the identity name when omitted.',
|
|
69
|
+
flags: '--via <callablePath>',
|
|
70
|
+
description: 'Submit the self-proven request through an authorizing Domain callable',
|
|
92
71
|
},
|
|
93
|
-
...KERNEL_PASSTHROUGH_OPTIONS,
|
|
94
72
|
],
|
|
95
73
|
action: async (name: string, opts: RegisterOpts) => {
|
|
96
74
|
try {
|
|
75
|
+
if (!opts.class) throw new TypeError('Missing required flag: --class <classPath>')
|
|
97
76
|
const identity = await getIdentity(name)
|
|
98
77
|
const { privatePath, publicPath } = keypairPaths(identity.subject)
|
|
99
78
|
if (!(await fileExists(privatePath)) || !(await fileExists(publicPath))) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
`No keypair on disk for "${name}" (expected ${privatePath}). Recreate via \`astrale identity create ${name}\`.`,
|
|
103
|
-
),
|
|
79
|
+
throw new Error(
|
|
80
|
+
`No keypair on disk for "${name}" (expected ${privatePath}). Recreate it with \`astrale identity create ${name}\`.`,
|
|
104
81
|
)
|
|
105
82
|
}
|
|
106
|
-
const privateJwk = await readJwk(privatePath)
|
|
107
|
-
const publicJwk = await readJwk(publicPath)
|
|
108
|
-
const nodePath = opts.path ?? `/workspace/users/${name}`
|
|
109
83
|
|
|
110
|
-
await
|
|
84
|
+
const privateKey = await readJwk(privatePath)
|
|
85
|
+
const publicKey = jwk.acceptPublic(await readJwk(publicPath))
|
|
86
|
+
const classPath = ClassPath.parse(opts.class)
|
|
87
|
+
const properties = normalizeProperties(opts.props ? JSON.parse(opts.props) : {})
|
|
88
|
+
|
|
89
|
+
await runKernelCommand<IdentityRegistrationResult>({
|
|
111
90
|
opts,
|
|
112
91
|
label: `Register "${name}"`,
|
|
113
|
-
fn: async (
|
|
114
|
-
const
|
|
115
|
-
const existing = identity.registrations?.[
|
|
92
|
+
fn: async ({ auth, session, target }) => {
|
|
93
|
+
const registrationKey = registrationKeyForTarget(target)
|
|
94
|
+
const existing = identity.registrations?.[registrationKey]
|
|
116
95
|
if (existing) {
|
|
117
|
-
log.warn(`"${name}" already registered on "${
|
|
96
|
+
log.warn(`"${name}" is already registered on "${registrationKey}"`)
|
|
118
97
|
return existing
|
|
119
98
|
}
|
|
120
99
|
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
? { firstName: name, lastName: name }
|
|
129
|
-
: {}
|
|
130
|
-
|
|
131
|
-
// One-arm create through function.mutate; the minted node id comes
|
|
132
|
-
// back in createdNodes (keyed by the `at` path).
|
|
133
|
-
const nodeId = await bindGraph(ctx).createNode(classPath, nodePath, {
|
|
134
|
-
'Statused.status': 'creating',
|
|
135
|
-
...userDefaults,
|
|
136
|
-
...extraProps,
|
|
100
|
+
const prepared = await prepareIdentityProvision({
|
|
101
|
+
name,
|
|
102
|
+
classPath,
|
|
103
|
+
properties,
|
|
104
|
+
privateKey,
|
|
105
|
+
publicKey,
|
|
106
|
+
kernelIssuer: target.kernelIssuer,
|
|
137
107
|
})
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
iss: result.iss,
|
|
149
|
-
sub: result.sub,
|
|
108
|
+
const registered = await submitIdentityProvision({
|
|
109
|
+
request: prepared.request,
|
|
110
|
+
binding: prepared.binding,
|
|
111
|
+
...(opts.via === undefined ? {} : { via: opts.via }),
|
|
112
|
+
direct: auth,
|
|
113
|
+
callable: session,
|
|
114
|
+
})
|
|
115
|
+
await setRegistration(name, registrationKey, {
|
|
116
|
+
iss: registered.iss,
|
|
117
|
+
sub: registered.sub,
|
|
150
118
|
registeredAt: new Date().toISOString(),
|
|
151
119
|
})
|
|
152
|
-
return
|
|
153
|
-
},
|
|
154
|
-
format: (result, fmtOpts) => {
|
|
155
|
-
output(result, fmtOpts)
|
|
156
|
-
log.dim(` iss=${result.iss}`)
|
|
157
|
-
log.dim(` sub=${result.sub}`)
|
|
120
|
+
return registered
|
|
158
121
|
},
|
|
122
|
+
format: formatIdentityRegistration,
|
|
159
123
|
})
|
|
160
|
-
} catch (
|
|
161
|
-
fatal(
|
|
124
|
+
} catch (error) {
|
|
125
|
+
fatal(error, opts)
|
|
162
126
|
}
|
|
163
127
|
},
|
|
164
128
|
} satisfies CommandDefinition
|
|
129
|
+
|
|
130
|
+
/** Preserve one structured stdout value while retaining useful detail in the human view. */
|
|
131
|
+
export function formatIdentityRegistration(
|
|
132
|
+
result: IdentityRegistrationResult,
|
|
133
|
+
format: KernelCommandOpts,
|
|
134
|
+
machine: boolean,
|
|
135
|
+
): void {
|
|
136
|
+
output(result, format)
|
|
137
|
+
if (machine) return
|
|
138
|
+
log.dim(` iss=${result.iss}`)
|
|
139
|
+
log.dim(` sub=${result.sub}`)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Build and self-prove one exact canonical provision request for the target Kernel. */
|
|
143
|
+
export async function prepareIdentityProvision(input: {
|
|
144
|
+
readonly name: string
|
|
145
|
+
readonly classPath: ReturnType<typeof ClassPath.parse>
|
|
146
|
+
readonly properties: ReturnType<typeof normalizeProperties>
|
|
147
|
+
readonly privateKey: JWK
|
|
148
|
+
readonly publicKey: JsonWebKey
|
|
149
|
+
readonly kernelIssuer: IssuerId
|
|
150
|
+
}): Promise<{
|
|
151
|
+
readonly binding: ReturnType<typeof LocalBinding>
|
|
152
|
+
readonly request: ProvisionRequest
|
|
153
|
+
}> {
|
|
154
|
+
const binding = LocalBinding('identity')
|
|
155
|
+
const mutation = MutationAST.build((builder) => {
|
|
156
|
+
builder.createNode({ as: binding, class: input.classPath, props: input.properties })
|
|
157
|
+
return undefined
|
|
158
|
+
})
|
|
159
|
+
const idempotencyKey = `identity-register:${input.name}`
|
|
160
|
+
const unsigned = provision.accept({
|
|
161
|
+
idempotencyKey,
|
|
162
|
+
mutation,
|
|
163
|
+
identities: {
|
|
164
|
+
[binding]: { credentials: { publicKey: input.publicKey, proof: 'pending-proof' } },
|
|
165
|
+
},
|
|
166
|
+
})
|
|
167
|
+
const fingerprint = await provision.fingerprint(unsigned)
|
|
168
|
+
const issuer = await provision.selfIssuer(input.kernelIssuer, input.publicKey)
|
|
169
|
+
const proof = await mintProvisionProof(input.privateKey, issuer, input.kernelIssuer, fingerprint)
|
|
170
|
+
return {
|
|
171
|
+
binding,
|
|
172
|
+
request: provision.accept({
|
|
173
|
+
idempotencyKey,
|
|
174
|
+
mutation,
|
|
175
|
+
identities: { [binding]: { credentials: { publicKey: input.publicKey, proof } } },
|
|
176
|
+
}),
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async function mintProvisionProof(
|
|
181
|
+
privateKey: JWK,
|
|
182
|
+
issuer: string,
|
|
183
|
+
audience: string,
|
|
184
|
+
fingerprint: string,
|
|
185
|
+
): Promise<string> {
|
|
186
|
+
const key = await importJWK(privateKey, 'ES256')
|
|
187
|
+
return new SignJWT({ provision: fingerprint })
|
|
188
|
+
.setProtectedHeader({ alg: 'ES256', ...(privateKey.kid ? { kid: privateKey.kid } : {}) })
|
|
189
|
+
.setIssuer(issuer)
|
|
190
|
+
.setSubject('self')
|
|
191
|
+
.setAudience(audience)
|
|
192
|
+
.setIssuedAt()
|
|
193
|
+
.setExpirationTime('5m')
|
|
194
|
+
.sign(key)
|
|
195
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { CommandDefinition } from '../../
|
|
1
|
+
import type { CommandDefinition } from '../../program/index'
|
|
2
2
|
|
|
3
|
-
import { getIdentity, setIdentityMode } from '../../
|
|
3
|
+
import { getIdentity, setIdentityMode } from '../../identity/index'
|
|
4
4
|
import { fatal, fatalNotImplemented, log } from '../../lib/log'
|
|
5
5
|
|
|
6
6
|
export default {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { CommandDefinition } from '../../
|
|
1
|
+
import type { CommandDefinition } from '../../program/index'
|
|
2
2
|
|
|
3
|
-
import { getIdentity, setIdentityMode } from '../../
|
|
3
|
+
import { getIdentity, setIdentityMode } from '../../identity/index'
|
|
4
4
|
import { fatal, log } from '../../lib/log'
|
|
5
5
|
|
|
6
6
|
/** Metadata-only flip remote → local until cloud sync ships (§2.7). */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { CommandDefinition } from '../../
|
|
1
|
+
import type { CommandDefinition } from '../../program/index'
|
|
2
2
|
|
|
3
|
-
import { setDefault } from '../../
|
|
3
|
+
import { setDefault } from '../../identity/index'
|
|
4
4
|
import { fatal, log } from '../../lib/log'
|
|
5
5
|
|
|
6
6
|
export default {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import chalk from 'chalk'
|
|
2
2
|
|
|
3
|
-
import type { CommandDefinition } from '../../
|
|
3
|
+
import type { CommandDefinition } from '../../program/index'
|
|
4
4
|
|
|
5
|
-
import { getDefault } from '../../
|
|
5
|
+
import { getDefault } from '../../identity/index'
|
|
6
6
|
import { fatal } from '../../lib/log'
|
|
7
7
|
import { isMachine, output, RAW_OUTPUT_OPTIONS, type RawOutputOpts } from '../../lib/output'
|
|
8
8
|
|
package/src/commands/idp/add.ts
CHANGED
package/src/commands/idp/list.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk'
|
|
2
2
|
|
|
3
|
-
import type { CommandDefinition } from '../../command'
|
|
4
3
|
import type { ListOpts, ListProjection } from '../../lib/output'
|
|
4
|
+
import type { CommandDefinition } from '../../program/index'
|
|
5
5
|
|
|
6
6
|
import { listIdpConfigs } from '../../lib/idp'
|
|
7
7
|
import { log } from '../../lib/log'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { CommandDefinition } from '../../
|
|
1
|
+
import type { CommandDefinition } from '../../program/index'
|
|
2
2
|
|
|
3
|
-
import { readIdentities } from '../../
|
|
3
|
+
import { readIdentities } from '../../identity/index'
|
|
4
4
|
import { removeIdpConfig } from '../../lib/idp'
|
|
5
5
|
import { log } from '../../lib/log'
|
|
6
6
|
import { output, RAW_OUTPUT_OPTIONS } from '../../lib/output'
|
package/src/commands/idp/show.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import chalk from 'chalk'
|
|
2
2
|
|
|
3
|
-
import type { CommandDefinition } from '../../
|
|
3
|
+
import type { CommandDefinition } from '../../program/index'
|
|
4
4
|
|
|
5
|
-
import { listOwnedInstances } from '../../
|
|
5
|
+
import { listOwnedInstances } from '../../lib/admin-instance'
|
|
6
6
|
import { findOwnedInstance } from '../../lib/admin-instance'
|
|
7
7
|
import { getActive, normalizeInstanceKernelUrl } from '../../lib/instance'
|
|
8
8
|
import { log } from '../../lib/log'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { CommandDefinition } from '../../
|
|
1
|
+
import type { CommandDefinition } from '../../program/index'
|
|
2
2
|
|
|
3
|
-
import { fetchWithCaFile } from '../../
|
|
3
|
+
import { fetchWithCaFile } from '../../lib/ca-fetch'
|
|
4
4
|
import { normalizeInstanceKernelUrl, setActive, upsertInstance } from '../../lib/instance'
|
|
5
5
|
import { fatal, log } from '../../lib/log'
|
|
6
6
|
import { checkIssuerReachability } from '../../lib/meta'
|
|
@@ -12,6 +12,10 @@ export default {
|
|
|
12
12
|
options: [
|
|
13
13
|
{ flags: '--url <url>', description: 'URL of the remote instance (required)' },
|
|
14
14
|
{ flags: '--issuer <url>', description: 'Kernel issuer/audience if different from URL' },
|
|
15
|
+
{
|
|
16
|
+
flags: '--domain-issuer <url>',
|
|
17
|
+
description: 'Product Domain issuer for standard token exchange',
|
|
18
|
+
},
|
|
15
19
|
{ flags: '--ca <path>', description: 'CA certificate file to trust for this bookmark' },
|
|
16
20
|
{
|
|
17
21
|
flags: '--as <identity>',
|
|
@@ -25,6 +29,7 @@ export default {
|
|
|
25
29
|
opts: {
|
|
26
30
|
url?: string
|
|
27
31
|
issuer?: string
|
|
32
|
+
domainIssuer?: string
|
|
28
33
|
ca?: string
|
|
29
34
|
as?: string
|
|
30
35
|
use?: boolean
|
|
@@ -53,6 +58,7 @@ export default {
|
|
|
53
58
|
const { entry, created } = await upsertInstance(name, {
|
|
54
59
|
url,
|
|
55
60
|
issuer: expectedIssuer,
|
|
61
|
+
domainIssuer: opts.domainIssuer,
|
|
56
62
|
caFile: opts.ca,
|
|
57
63
|
name,
|
|
58
64
|
kind: 'bookmark',
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { KernelCommandOpts } from '../../connection'
|
|
2
|
+
import type { CommandDefinition } from '../../program/index'
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import { adminInstanceMethod, type InstanceInfo } from '../../lib/admin-instance'
|
|
4
|
+
import { deleteOwnedInstance } from '../../lib/admin-instance'
|
|
6
5
|
import { ADMIN_TARGET_OPTIONS, type AdminTargetCommandOpts } from '../../lib/admin-target'
|
|
7
6
|
import { clearActive, readInstances, removeInstance, resolveInstanceKey } from '../../lib/instance'
|
|
8
7
|
import { fatal, log, withSpinner } from '../../lib/log'
|
|
@@ -36,12 +35,7 @@ Behavior:
|
|
|
36
35
|
const result = await withSpinner(
|
|
37
36
|
`Deleting instance ${id}`,
|
|
38
37
|
!isMachine(opts),
|
|
39
|
-
() =>
|
|
40
|
-
withAdminKernelClient(
|
|
41
|
-
opts,
|
|
42
|
-
async (ctx) =>
|
|
43
|
-
(await ctx.client.call(adminInstanceMethod('delete'), { id })) as InstanceInfo,
|
|
44
|
-
),
|
|
38
|
+
() => deleteOwnedInstance(opts, id),
|
|
45
39
|
{ success: (deleted) => `Deleted instance: ${deleted.slug}` },
|
|
46
40
|
)
|
|
47
41
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import chalk from 'chalk'
|
|
2
2
|
|
|
3
|
-
import type {
|
|
4
|
-
import type { KernelCommandOpts } from '../../kernel'
|
|
3
|
+
import type { KernelCommandOpts } from '../../connection'
|
|
5
4
|
import type { Column } from '../../lib/output'
|
|
5
|
+
import type { CommandDefinition } from '../../program/index'
|
|
6
6
|
|
|
7
|
-
import { listOwnedInstances } from '../../
|
|
7
|
+
import { listOwnedInstances } from '../../lib/admin-instance'
|
|
8
8
|
import {
|
|
9
9
|
formatInstanceLocation,
|
|
10
10
|
type InstanceInfo,
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import chalk from 'chalk'
|
|
2
2
|
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
3
|
+
import type { KernelCommandOpts } from '../../connection'
|
|
4
|
+
import type { CommandDefinition } from '../../program/index'
|
|
5
5
|
|
|
6
6
|
import { AstraleError } from '../../errors'
|
|
7
|
-
import {
|
|
8
|
-
import { findOwnedInstance } from '../../lib/admin-instance'
|
|
7
|
+
import { statusOwnedInstance } from '../../lib/admin-instance'
|
|
9
8
|
import { ADMIN_TARGET_OPTIONS, type AdminTargetCommandOpts } from '../../lib/admin-target'
|
|
10
9
|
import { fatal, log, withSpinner } from '../../lib/log'
|
|
11
10
|
import { isMachine, output, type RawOutputOpts } from '../../lib/output'
|
|
@@ -20,9 +19,8 @@ export default {
|
|
|
20
19
|
action: async (id: string, opts: StatusOpts) => {
|
|
21
20
|
try {
|
|
22
21
|
const result = await withSpinner(`Fetching instance ${id}`, !isMachine(opts), () =>
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (match) return match
|
|
22
|
+
statusOwnedInstance(opts, id).catch((error) => {
|
|
23
|
+
if (!(error instanceof Error) || error.name !== 'NotFoundError') throw error
|
|
26
24
|
throw new AstraleError(
|
|
27
25
|
'INSTANCE_NOT_FOUND',
|
|
28
26
|
`No owned instance matches "${id}".`,
|