@astrale-os/cli 0.8.0-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/README.md +4 -1
- package/dist/astrale.js +62968 -41240
- 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 +30 -8
- 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-D0cBetPW.js +1 -0
- package/studio/client/dist/assets/elk-worker.min-C9JGDOE-.js +6312 -0
- package/studio/client/dist/assets/index-BQnJ5sgd.css +1 -0
- package/studio/client/dist/assets/index-ChOr3yP0.css +1 -0
- package/studio/client/dist/assets/index-Dspir4w7.js +81 -0
- package/studio/client/dist/assets/index-bVD2KJgz.js +8 -0
- package/studio/client/dist/index.html +2 -2
- 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/studio/tsconfig.json +23 -0
- package/tsconfig.json +1 -1
- package/viewer/dist/main.js +65 -39
- package/viewer/tsconfig.json +13 -0
- 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-BaqEuIQJ.js +0 -109
- package/studio/client/dist/assets/index-jRdExahh.css +0 -1
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises'
|
|
2
|
+
import { z } from 'zod'
|
|
3
|
+
|
|
4
|
+
import type { FileLockOptions } from './files'
|
|
5
|
+
|
|
6
|
+
import { atomicWrite, withFileLock } from './files'
|
|
7
|
+
import { IDENTITIES_PATH } from './paths'
|
|
8
|
+
|
|
9
|
+
export type IdentitySource = 'key' | 'idp'
|
|
10
|
+
export type IdentityMode = 'local' | 'remote'
|
|
11
|
+
|
|
12
|
+
export interface Registration {
|
|
13
|
+
readonly iss: string
|
|
14
|
+
readonly sub: string
|
|
15
|
+
readonly registeredAt: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface Identity {
|
|
19
|
+
readonly subject: string
|
|
20
|
+
readonly createdAt: string
|
|
21
|
+
readonly source?: IdentitySource
|
|
22
|
+
readonly mode?: IdentityMode
|
|
23
|
+
readonly kid?: string
|
|
24
|
+
readonly idp?: string
|
|
25
|
+
readonly issuer?: string
|
|
26
|
+
readonly audience?: string
|
|
27
|
+
readonly claims?: Readonly<Record<string, unknown>>
|
|
28
|
+
readonly registrations?: Readonly<Record<string, Registration>>
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface IdentityStore {
|
|
32
|
+
readonly default: string
|
|
33
|
+
readonly identities: Readonly<Record<string, Identity>>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const IDENTITY_STORE_VERSION = 1 as const
|
|
37
|
+
|
|
38
|
+
export type IdentityStateErrorCode =
|
|
39
|
+
| 'IDENTITY_STATE_INVALID'
|
|
40
|
+
| 'IDENTITY_STATE_VERSION_UNSUPPORTED'
|
|
41
|
+
| 'IDENTITY_STATE_UNREADABLE'
|
|
42
|
+
| 'IDENTITY_STATE_BACKUP_CONFLICT'
|
|
43
|
+
|
|
44
|
+
export class IdentityStateError extends Error {
|
|
45
|
+
readonly code: IdentityStateErrorCode
|
|
46
|
+
readonly path: string
|
|
47
|
+
|
|
48
|
+
constructor(code: IdentityStateErrorCode, path: string, message: string, cause?: unknown) {
|
|
49
|
+
super(message, { cause })
|
|
50
|
+
this.name = 'IdentityStateError'
|
|
51
|
+
this.code = code
|
|
52
|
+
this.path = path
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface IdentityStoreOptions {
|
|
57
|
+
readonly path?: string
|
|
58
|
+
readonly now?: () => Date
|
|
59
|
+
readonly lock?: FileLockOptions
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface IdentityUpdate<Value> {
|
|
63
|
+
readonly next: IdentityStore
|
|
64
|
+
readonly value: Value
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const RegistrationSchema: z.ZodType<Registration> = z
|
|
68
|
+
.object({
|
|
69
|
+
iss: z.string(),
|
|
70
|
+
sub: z.string(),
|
|
71
|
+
registeredAt: z.string(),
|
|
72
|
+
})
|
|
73
|
+
.strict()
|
|
74
|
+
|
|
75
|
+
const IdentitySchema: z.ZodType<Identity> = z
|
|
76
|
+
.object({
|
|
77
|
+
subject: z.string(),
|
|
78
|
+
createdAt: z.string(),
|
|
79
|
+
source: z.enum(['key', 'idp']).optional(),
|
|
80
|
+
mode: z.enum(['local', 'remote']).optional(),
|
|
81
|
+
kid: z.string().optional(),
|
|
82
|
+
idp: z.string().optional(),
|
|
83
|
+
issuer: z.string().url().optional(),
|
|
84
|
+
audience: z.string().optional(),
|
|
85
|
+
claims: z.record(z.string(), z.unknown()).optional(),
|
|
86
|
+
registrations: z.record(z.string(), RegistrationSchema).optional(),
|
|
87
|
+
})
|
|
88
|
+
.strict()
|
|
89
|
+
|
|
90
|
+
const IdentityStoreFields = {
|
|
91
|
+
default: z.string(),
|
|
92
|
+
identities: z.record(z.string(), IdentitySchema),
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const IdentityStoreSchema: z.ZodType<IdentityStore> = z.object(IdentityStoreFields).strict()
|
|
96
|
+
|
|
97
|
+
const IdentityFileV1Schema = z
|
|
98
|
+
.object({ version: z.literal(IDENTITY_STORE_VERSION), ...IdentityStoreFields })
|
|
99
|
+
.strict()
|
|
100
|
+
|
|
101
|
+
interface DecodedIdentityStore {
|
|
102
|
+
readonly store: IdentityStore
|
|
103
|
+
readonly legacyBytes?: string
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export async function readIdentityStore(
|
|
107
|
+
options: IdentityStoreOptions = {},
|
|
108
|
+
): Promise<IdentityStore> {
|
|
109
|
+
return (await readDecoded(options)).store
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export async function updateIdentityStore<Value>(
|
|
113
|
+
transition: (current: IdentityStore) => IdentityUpdate<Value> | Promise<IdentityUpdate<Value>>,
|
|
114
|
+
options: IdentityStoreOptions = {},
|
|
115
|
+
): Promise<Value> {
|
|
116
|
+
const path = options.path ?? IDENTITIES_PATH
|
|
117
|
+
return withFileLock(
|
|
118
|
+
`${path}.lock`,
|
|
119
|
+
async () => {
|
|
120
|
+
const current = await readDecoded(options)
|
|
121
|
+
const update = await transition(current.store)
|
|
122
|
+
if (current.legacyBytes !== undefined) {
|
|
123
|
+
await preserveLegacyBackup(path, current.legacyBytes)
|
|
124
|
+
}
|
|
125
|
+
await atomicWrite(path, encodeV1(update.next))
|
|
126
|
+
return update.value
|
|
127
|
+
},
|
|
128
|
+
options.lock,
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async function readDecoded(options: IdentityStoreOptions): Promise<DecodedIdentityStore> {
|
|
133
|
+
const path = options.path ?? IDENTITIES_PATH
|
|
134
|
+
let raw: string
|
|
135
|
+
try {
|
|
136
|
+
raw = await readFile(path, 'utf-8')
|
|
137
|
+
} catch (error) {
|
|
138
|
+
if ((error as { code?: string }).code === 'ENOENT') {
|
|
139
|
+
return { store: seed(options.now?.() ?? new Date()) }
|
|
140
|
+
}
|
|
141
|
+
throw new IdentityStateError(
|
|
142
|
+
'IDENTITY_STATE_UNREADABLE',
|
|
143
|
+
path,
|
|
144
|
+
`Could not read identity state at ${path}`,
|
|
145
|
+
error,
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
let input: unknown
|
|
150
|
+
try {
|
|
151
|
+
input = JSON.parse(raw)
|
|
152
|
+
} catch (error) {
|
|
153
|
+
throw invalidState(path, error)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (hasVersion(input)) {
|
|
157
|
+
if (typeof input.version !== 'number' || !Number.isInteger(input.version)) {
|
|
158
|
+
throw invalidState(path)
|
|
159
|
+
}
|
|
160
|
+
if (input.version !== IDENTITY_STORE_VERSION) {
|
|
161
|
+
throw new IdentityStateError(
|
|
162
|
+
'IDENTITY_STATE_VERSION_UNSUPPORTED',
|
|
163
|
+
path,
|
|
164
|
+
`Identity state at ${path} uses unsupported version ${input.version}`,
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
const { version: _, ...store } = IdentityFileV1Schema.parse(input)
|
|
169
|
+
return { store }
|
|
170
|
+
} catch (error) {
|
|
171
|
+
throw invalidState(path, error)
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
try {
|
|
176
|
+
return { store: IdentityStoreSchema.parse(input), legacyBytes: raw }
|
|
177
|
+
} catch (error) {
|
|
178
|
+
throw invalidState(path, error)
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function hasVersion(input: unknown): input is { readonly version: unknown } {
|
|
183
|
+
return typeof input === 'object' && input !== null && Object.hasOwn(input, 'version')
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function seed(now: Date): IdentityStore {
|
|
187
|
+
return {
|
|
188
|
+
default: 'manager',
|
|
189
|
+
identities: {
|
|
190
|
+
manager: {
|
|
191
|
+
subject: 'manager',
|
|
192
|
+
createdAt: now.toISOString(),
|
|
193
|
+
source: 'key',
|
|
194
|
+
mode: 'local',
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function encodeV1(store: IdentityStore): string {
|
|
201
|
+
return `${JSON.stringify({ version: IDENTITY_STORE_VERSION, ...store }, null, 2)}\n`
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
async function preserveLegacyBackup(path: string, legacyBytes: string): Promise<void> {
|
|
205
|
+
const backupPath = `${path}.v0.bak`
|
|
206
|
+
try {
|
|
207
|
+
const existing = await readFile(backupPath, 'utf-8')
|
|
208
|
+
if (existing !== legacyBytes) {
|
|
209
|
+
throw new IdentityStateError(
|
|
210
|
+
'IDENTITY_STATE_BACKUP_CONFLICT',
|
|
211
|
+
backupPath,
|
|
212
|
+
`Legacy identity backup at ${backupPath} does not match the file being migrated`,
|
|
213
|
+
)
|
|
214
|
+
}
|
|
215
|
+
} catch (error) {
|
|
216
|
+
if (error instanceof IdentityStateError) throw error
|
|
217
|
+
if ((error as { code?: string }).code !== 'ENOENT') {
|
|
218
|
+
throw new IdentityStateError(
|
|
219
|
+
'IDENTITY_STATE_UNREADABLE',
|
|
220
|
+
backupPath,
|
|
221
|
+
`Could not read legacy identity backup at ${backupPath}`,
|
|
222
|
+
error,
|
|
223
|
+
)
|
|
224
|
+
}
|
|
225
|
+
await atomicWrite(backupPath, legacyBytes)
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function invalidState(path: string, cause?: unknown): IdentityStateError {
|
|
230
|
+
return new IdentityStateError(
|
|
231
|
+
'IDENTITY_STATE_INVALID',
|
|
232
|
+
path,
|
|
233
|
+
`Identity state at ${path} is malformed`,
|
|
234
|
+
cause,
|
|
235
|
+
)
|
|
236
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export { atomicWrite, withFileLock } from './files'
|
|
2
|
+
export type { FileLockOptions } from './files'
|
|
3
|
+
export { ExchangeCredentialCache } from './exchange-credentials'
|
|
4
|
+
export type { exchange } from './exchange-credentials'
|
|
5
|
+
export { IDENTITY_STORE_VERSION, readIdentityStore, updateIdentityStore } from './identities'
|
|
6
|
+
export type {
|
|
7
|
+
Identity,
|
|
8
|
+
IdentityMode,
|
|
9
|
+
IdentitySource,
|
|
10
|
+
IdentityStore,
|
|
11
|
+
IdentityStoreOptions,
|
|
12
|
+
IdentityUpdate,
|
|
13
|
+
Registration,
|
|
14
|
+
} from './identities'
|
|
15
|
+
export {
|
|
16
|
+
ASTRALE_HOME,
|
|
17
|
+
CONFIG_PATH,
|
|
18
|
+
DATA_DIR,
|
|
19
|
+
IDENTITIES_PATH,
|
|
20
|
+
IDPS_PATH,
|
|
21
|
+
IDP_SESSIONS_DIR,
|
|
22
|
+
EXCHANGE_CREDENTIALS_PATH,
|
|
23
|
+
INSTALL_PATH,
|
|
24
|
+
INSTANCES_PATH,
|
|
25
|
+
KEYS_DIR,
|
|
26
|
+
createPaths,
|
|
27
|
+
paths,
|
|
28
|
+
} from './paths'
|
|
29
|
+
export type { PathEnvironment, Paths } from './paths'
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { homedir } from 'node:os'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
|
|
4
|
+
export interface PathEnvironment {
|
|
5
|
+
readonly ASTRALE_HOME?: string
|
|
6
|
+
readonly ASTRALE_KEYS_DIR?: string
|
|
7
|
+
readonly ASTRALE_DATA_DIR?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface Paths {
|
|
11
|
+
readonly home: string
|
|
12
|
+
readonly keys: string
|
|
13
|
+
readonly data: string
|
|
14
|
+
readonly config: string
|
|
15
|
+
readonly install: string
|
|
16
|
+
readonly identities: string
|
|
17
|
+
readonly instances: string
|
|
18
|
+
readonly idps: string
|
|
19
|
+
readonly idpSessionsDir: string
|
|
20
|
+
readonly exchangeCredentials: string
|
|
21
|
+
idpDir(name: string): string
|
|
22
|
+
idpSession(identityName: string): string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Resolve every CLI state path once from explicit input and the captured environment. */
|
|
26
|
+
export function createPaths(home?: string, environment?: PathEnvironment): Paths {
|
|
27
|
+
const captured = environment ?? {
|
|
28
|
+
ASTRALE_HOME: process.env.ASTRALE_HOME,
|
|
29
|
+
ASTRALE_KEYS_DIR: process.env.ASTRALE_KEYS_DIR,
|
|
30
|
+
ASTRALE_DATA_DIR: process.env.ASTRALE_DATA_DIR,
|
|
31
|
+
}
|
|
32
|
+
const base = home ?? captured.ASTRALE_HOME ?? join(homedir(), '.astrale')
|
|
33
|
+
const idpsDir = join(base, 'idps')
|
|
34
|
+
const idpSessionsDir = join(base, 'idp-sessions')
|
|
35
|
+
return Object.freeze({
|
|
36
|
+
home: base,
|
|
37
|
+
keys: captured.ASTRALE_KEYS_DIR ?? join(base, 'keys'),
|
|
38
|
+
data: captured.ASTRALE_DATA_DIR ?? join(base, 'data'),
|
|
39
|
+
config: join(base, 'config.json'),
|
|
40
|
+
install: join(base, 'install.json'),
|
|
41
|
+
identities: join(base, 'identities.json'),
|
|
42
|
+
instances: join(base, 'instances.json'),
|
|
43
|
+
idps: join(idpsDir, 'index.json'),
|
|
44
|
+
idpSessionsDir,
|
|
45
|
+
exchangeCredentials: join(base, 'exchange', 'credentials.json'),
|
|
46
|
+
idpDir: (name: string) => join(idpsDir, name),
|
|
47
|
+
idpSession: (identityName: string) => join(idpSessionsDir, `${identityName}.json`),
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const paths: Paths = createPaths()
|
|
52
|
+
export const ASTRALE_HOME = paths.home
|
|
53
|
+
export const KEYS_DIR = paths.keys
|
|
54
|
+
export const DATA_DIR = paths.data
|
|
55
|
+
export const CONFIG_PATH = paths.config
|
|
56
|
+
export const INSTALL_PATH = paths.install
|
|
57
|
+
export const IDENTITIES_PATH = paths.identities
|
|
58
|
+
export const INSTANCES_PATH = paths.instances
|
|
59
|
+
export const IDPS_PATH = paths.idps
|
|
60
|
+
export const IDP_SESSIONS_DIR = paths.idpSessionsDir
|
|
61
|
+
export const EXCHANGE_CREDENTIALS_PATH = paths.exchangeCredentials
|
|
@@ -27,9 +27,9 @@ describe('redactArgv', () => {
|
|
|
27
27
|
})
|
|
28
28
|
|
|
29
29
|
test('leaves non-secret flags and their values intact', () => {
|
|
30
|
-
expect(redactArgv(['
|
|
31
|
-
'
|
|
32
|
-
'--
|
|
30
|
+
expect(redactArgv(['query', '--limit', '3', '--format=json'])).toEqual([
|
|
31
|
+
'query',
|
|
32
|
+
'--limit',
|
|
33
33
|
'3',
|
|
34
34
|
'--format=json',
|
|
35
35
|
])
|
|
@@ -16,7 +16,7 @@ beforeAll(async () => {
|
|
|
16
16
|
// leaves a telemetry-disabled config.json in the shared home) — own it here.
|
|
17
17
|
delete process.env.ASTRALE_TELEMETRY
|
|
18
18
|
delete process.env.ASTRALE_TELEMETRY_NO_TRIGGER
|
|
19
|
-
const { CONFIG_PATH } = await import('../../
|
|
19
|
+
const { CONFIG_PATH } = await import('../../state/index')
|
|
20
20
|
rmSync(CONFIG_PATH, { force: true })
|
|
21
21
|
})
|
|
22
22
|
|
package/src/telemetry/store.ts
CHANGED
package/src/test-utils.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { mkdtemp, mkdir } from 'node:fs/promises'
|
|
|
2
2
|
import { tmpdir } from 'node:os'
|
|
3
3
|
import { join } from 'node:path'
|
|
4
4
|
|
|
5
|
-
import { createPaths, type Paths } from './
|
|
5
|
+
import { createPaths, type Paths } from './state/index'
|
|
6
6
|
|
|
7
7
|
export type TestEnv = {
|
|
8
8
|
paths: Paths
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{m as L}from"./index-Dspir4w7.js";function S(y,b){for(var u=0;u<b.length;u++){const a=b[u];if(typeof a!="string"&&!Array.isArray(a)){for(const i in a)if(i!=="default"&&!(i in y)){const n=Object.getOwnPropertyDescriptor(a,i);n&&Object.defineProperty(y,i,n.get?n:{enumerable:!0,get:()=>a[i]})}}}return Object.freeze(Object.defineProperty(y,Symbol.toStringTag,{value:"Module"}))}function w(y){throw new Error('Could not dynamically require "'+y+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var O={exports:{}},j;function C(){return j||(j=1,(function(y,b){(function(u){y.exports=u()})(function(){return(function(){function u(a,i,n){function d(f,_){if(!i[f]){if(!a[f]){var h=typeof w=="function"&&w;if(!_&&h)return h(f,!0);if(g)return g(f,!0);var o=new Error("Cannot find module '"+f+"'");throw o.code="MODULE_NOT_FOUND",o}var e=i[f]={exports:{}};a[f][0].call(e.exports,function(r){var t=a[f][1][r];return d(t||r)},e,e.exports,u,a,i,n)}return i[f].exports}for(var g=typeof w=="function"&&w,m=0;m<n.length;m++)d(n[m]);return d}return u})()({1:[function(u,a,i){Object.defineProperty(i,"__esModule",{value:!0}),i.default=void 0;function n(o){"@babel/helpers - typeof";return n=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(e){return typeof e}:function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(o)}function d(o,e){if(!(o instanceof e))throw new TypeError("Cannot call a class as a function")}function g(o,e){for(var r=0;r<e.length;r++){var t=e[r];t.enumerable=t.enumerable||!1,t.configurable=!0,"value"in t&&(t.writable=!0),Object.defineProperty(o,f(t.key),t)}}function m(o,e,r){return e&&g(o.prototype,e),Object.defineProperty(o,"prototype",{writable:!1}),o}function f(o){var e=_(o,"string");return n(e)=="symbol"?e:e+""}function _(o,e){if(n(o)!="object"||!o)return o;var r=o[Symbol.toPrimitive];if(r!==void 0){var t=r.call(o,e);if(n(t)!="object")return t;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(o)}i.default=(function(){function o(){var e=this,r=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},t=r.defaultLayoutOptions,s=t===void 0?{}:t,l=r.algorithms,v=l===void 0?["layered","stress","mrtree","radial","force","disco","sporeOverlap","sporeCompaction","rectpacking"]:l,c=r.workerFactory,p=r.workerUrl;if(d(this,o),this.defaultLayoutOptions=s,this.initialized=!1,typeof p>"u"&&typeof c>"u")throw new Error("Cannot construct an ELK without both 'workerUrl' and 'workerFactory'.");var k=c;typeof p<"u"&&typeof c>"u"&&(k=function(M){return new Worker(M)});var E=k(p);if(typeof E.postMessage!="function")throw new TypeError("Created worker does not provide the required 'postMessage' function.");this.worker=new h(E),this.worker.postMessage({cmd:"register",algorithms:v}).then(function(P){return e.initialized=!0}).catch(console.err)}return m(o,[{key:"layout",value:function(r){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},s=t.layoutOptions,l=s===void 0?this.defaultLayoutOptions:s,v=t.logging,c=v===void 0?!1:v,p=t.measureExecutionTime,k=p===void 0?!1:p;return r?this.worker.postMessage({cmd:"layout",graph:r,layoutOptions:l,options:{logging:c,measureExecutionTime:k}}):Promise.reject(new Error("Missing mandatory parameter 'graph'."))}},{key:"knownLayoutAlgorithms",value:function(){return this.worker.postMessage({cmd:"algorithms"})}},{key:"knownLayoutOptions",value:function(){return this.worker.postMessage({cmd:"options"})}},{key:"knownLayoutCategories",value:function(){return this.worker.postMessage({cmd:"categories"})}},{key:"terminateWorker",value:function(){this.worker&&this.worker.terminate()}}])})();var h=(function(){function o(e){var r=this;if(d(this,o),e===void 0)throw new Error("Missing mandatory parameter 'worker'.");this.resolvers={},this.worker=e,this.worker.onmessage=function(t){setTimeout(function(){r.receive(r,t)},0)}}return m(o,[{key:"postMessage",value:function(r){var t=this.id||0;this.id=t+1,r.id=t;var s=this;return new Promise(function(l,v){s.resolvers[t]=function(c,p){c?(s.convertGwtStyleError(c),v(c)):l(p)},s.worker.postMessage(r)})}},{key:"receive",value:function(r,t){var s=t.data,l=r.resolvers[s.id];l&&(delete r.resolvers[s.id],s.error?l(s.error):l(null,s.data))}},{key:"terminate",value:function(){this.worker&&this.worker.terminate()}},{key:"convertGwtStyleError",value:function(r){if(r){var t=r.__java$exception;t&&(t.cause&&t.cause.backingJsObject&&(r.cause=t.cause.backingJsObject,this.convertGwtStyleError(r.cause)),delete r.__java$exception)}}}])})()},{}],2:[function(u,a,i){var n=u("./elk-api.js").default;Object.defineProperty(a.exports,"__esModule",{value:!0}),a.exports=n,n.default=n},{"./elk-api.js":1}]},{},[2])(2)})})(O)),O.exports}var x=C();const A=L(x),q=S({__proto__:null,default:A},[x]);export{q as e};
|