@astrale-os/cli 1.0.0-beta.32 → 1.0.0-beta.43
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/CHANGELOG.md +928 -0
- package/README.md +53 -43
- package/THIRD-PARTY-NOTICES.md +37 -1
- package/dist/astrale.js +349631 -83669
- package/dist/public/connect-core.js +16 -47
- package/dist/public/keys/index.js +1 -1
- package/dist/types/admin/contract.d.ts +11 -0
- package/dist/types/admin/graph/index.d.ts +1 -0
- package/dist/types/admin/graph/nodes.d.ts +12 -0
- package/dist/types/admin/instance/client.d.ts +2 -0
- package/dist/types/connection/lifetime.d.ts +1 -1
- package/dist/types/errors.d.ts +3 -0
- package/dist/types/lib/proc.d.ts +1 -0
- package/dist/types/lib/update.d.ts +15 -7
- package/package.json +8 -6
- package/studio/client/dist/assets/index-5C1uT6ML.css +2 -0
- package/studio/client/dist/assets/index-C4kNlvwF.js +80 -0
- package/studio/client/dist/assets/schema-studio-BR9d0faB.js +8 -0
- package/studio/client/dist/index.html +13 -2
- package/studio/package.json +2 -1
- package/studio/server/agent/ask.test.ts +7 -1
- package/studio/server/agent/bridge/grant.ts +15 -3
- package/studio/server/agent/prompts/system.test.ts +5 -0
- package/studio/server/agent/prompts/system.ts +19 -4
- package/studio/server/agent/routes.test.ts +39 -1
- package/studio/server/agent/routes.ts +3 -0
- package/studio/server/agent/run/coordinator.test.ts +7 -1
- package/studio/server/agent/run/preparation.ts +1 -0
- package/studio/server/agent/run/transcript.test.ts +47 -2
- package/studio/server/agent/run/transcript.ts +32 -3
- package/studio/server/api/documents.test.ts +31 -0
- package/studio/server/api/documents.ts +35 -1
- package/studio/server/api-agent-loadout.test.ts +7 -1
- package/studio/server/api.test.ts +7 -1
- package/studio/server/cache.ts +4 -4
- package/studio/server/detect.ts +9 -12
- package/studio/server/domain.test.ts +83 -3
- package/studio/server/domain.ts +205 -27
- package/studio/server/handoff/service.ts +1 -1
- package/studio/server/index.ts +5 -8
- package/studio/server/introspect/extractor.ts +111 -17
- package/studio/server/introspect/overlay-tsmorph.test.ts +9 -9
- package/studio/server/introspect/overlay.ts +1 -1
- package/studio/server/introspect/runtime.ts +9 -1
- package/studio/server/introspect/source-overlay/spans.ts +2 -5
- package/studio/server/lifecycle.ts +1 -1
- package/studio/server/state/baseline.test.ts +14 -0
- package/studio/server/state/baseline.ts +16 -2
- package/studio/server/watch.test.ts +2 -1
- package/studio/server/watch.ts +5 -2
- package/studio/server/workspace/create.ts +9 -8
- package/studio/server/workspace-state.ts +4 -6
- package/studio/server/workspace-watch.ts +33 -22
- package/studio/shared/contracts/agent.ts +3 -0
- package/viewer/dist/main.js +12 -12
- package/src/__tests__/fixtures/publication.ts +0 -20
- package/src/admin/.spec/api.d.ts +0 -3
- package/src/admin/.spec/architecture.md +0 -22
- package/src/admin/.spec/icon.svg +0 -3
- package/src/admin/.spec/layout.ts +0 -6
- package/src/admin/__tests__/fixture.ts +0 -25
- package/src/admin/catalog/.spec/api.d.ts +0 -63
- package/src/admin/catalog/.spec/architecture.md +0 -7
- package/src/admin/catalog/.spec/icon.svg +0 -3
- package/src/admin/catalog/.spec/layout.ts +0 -6
- package/src/admin/catalog/__tests__/client.test.ts +0 -245
- package/src/admin/catalog/client.ts +0 -195
- package/src/admin/catalog/index.ts +0 -13
- package/src/admin/catalog/model.ts +0 -41
- package/src/admin/catalog/tsconfig.json +0 -8
- package/src/admin/contract.ts +0 -47
- package/src/admin/graph/.spec/api.d.ts +0 -22
- package/src/admin/graph/.spec/architecture.md +0 -5
- package/src/admin/graph/.spec/icon.svg +0 -3
- package/src/admin/graph/.spec/layout.ts +0 -3
- package/src/admin/graph/index.ts +0 -6
- package/src/admin/graph/nodes.ts +0 -56
- package/src/admin/index.ts +0 -2
- package/src/admin/instance/.spec/api.d.ts +0 -62
- package/src/admin/instance/.spec/architecture.md +0 -10
- package/src/admin/instance/.spec/icon.svg +0 -3
- package/src/admin/instance/.spec/layout.ts +0 -6
- package/src/admin/instance/__tests__/client.test.ts +0 -273
- package/src/admin/instance/client.ts +0 -191
- package/src/admin/instance/index.ts +0 -15
- package/src/admin/instance/model.ts +0 -59
- package/src/admin/instance/tsconfig.json +0 -8
- package/src/commands/__tests__/admin-instance.test.ts +0 -91
- package/src/commands/__tests__/auth-login.test.ts +0 -231
- package/src/commands/__tests__/auth-token.test.ts +0 -223
- package/src/commands/__tests__/call-describe.test.ts +0 -80
- package/src/commands/__tests__/call.test.ts +0 -63
- package/src/commands/__tests__/domain-install-operation.test.ts +0 -145
- package/src/commands/__tests__/domain-install-owned.test.ts +0 -191
- package/src/commands/__tests__/domain-list.test.ts +0 -133
- package/src/commands/__tests__/domain-uninstall.test.ts +0 -53
- package/src/commands/__tests__/install-direct.test.ts +0 -128
- package/src/commands/__tests__/install-identity-override.test.ts +0 -76
- package/src/commands/__tests__/instance-bookmark.test.ts +0 -166
- package/src/commands/__tests__/instance-list-admin.test.ts +0 -26
- package/src/commands/__tests__/instance-list-rows.test.ts +0 -64
- package/src/commands/__tests__/instance-status.test.ts +0 -139
- package/src/commands/__tests__/instance-use.test.ts +0 -67
- package/src/commands/__tests__/introspect-parse.test.ts +0 -100
- package/src/commands/__tests__/logs.test.ts +0 -345
- package/src/commands/__tests__/read-commands.test.ts +0 -377
- package/src/commands/__tests__/setup-plan.test.ts +0 -61
- package/src/commands/__tests__/studio-descriptor.test.ts +0 -22
- package/src/commands/__tests__/token-ttl.test.ts +0 -66
- package/src/commands/__tests__/update.test.ts +0 -95
- package/src/commands/__tests__/view-build.test.ts +0 -58
- package/src/commands/__tests__/view.test.ts +0 -197
- package/src/commands/admin/status.ts +0 -61
- package/src/commands/admin/use.ts +0 -100
- package/src/commands/auth/login.ts +0 -82
- package/src/commands/auth/logout.ts +0 -53
- package/src/commands/auth/status.ts +0 -86
- package/src/commands/auth/token.ts +0 -174
- package/src/commands/browser.ts +0 -236
- package/src/commands/call-describe.ts +0 -123
- package/src/commands/call.ts +0 -230
- package/src/commands/domain/install.ts +0 -575
- package/src/commands/domain/list.ts +0 -155
- package/src/commands/domain/publish.ts +0 -136
- package/src/commands/domain/uninstall.ts +0 -128
- package/src/commands/get.ts +0 -69
- package/src/commands/identity/__tests__/register.test.ts +0 -93
- package/src/commands/identity/create.ts +0 -35
- package/src/commands/identity/delete.ts +0 -24
- package/src/commands/identity/export.ts +0 -46
- package/src/commands/identity/import.ts +0 -61
- package/src/commands/identity/list.ts +0 -56
- package/src/commands/identity/register.ts +0 -195
- package/src/commands/identity/sync.ts +0 -38
- package/src/commands/identity/unsync.ts +0 -34
- package/src/commands/identity/use.ts +0 -24
- package/src/commands/identity/whoami.ts +0 -34
- package/src/commands/idp/add.ts +0 -150
- package/src/commands/idp/list.ts +0 -57
- package/src/commands/idp/refresh.ts +0 -38
- package/src/commands/idp/remove.ts +0 -36
- package/src/commands/idp/show.ts +0 -29
- package/src/commands/instance/active.ts +0 -73
- package/src/commands/instance/bookmark.ts +0 -101
- package/src/commands/instance/create.ts +0 -61
- package/src/commands/instance/delete.ts +0 -69
- package/src/commands/instance/forget.ts +0 -26
- package/src/commands/instance/list.ts +0 -197
- package/src/commands/instance/status.ts +0 -92
- package/src/commands/instance/use.ts +0 -263
- package/src/commands/introspect.ts +0 -129
- package/src/commands/logs.ts +0 -371
- package/src/commands/mutate.ts +0 -122
- package/src/commands/query.ts +0 -142
- package/src/commands/session/analyze.ts +0 -72
- package/src/commands/session/list.ts +0 -36
- package/src/commands/setup.ts +0 -54
- package/src/commands/status.ts +0 -60
- package/src/commands/studio.ts +0 -434
- package/src/commands/token.ts +0 -121
- package/src/commands/ui/__tests__/commands.test.ts +0 -152
- package/src/commands/ui/add.ts +0 -51
- package/src/commands/ui/doctor.ts +0 -21
- package/src/commands/ui/init.ts +0 -38
- package/src/commands/ui/list.ts +0 -26
- package/src/commands/ui/preset-apply.ts +0 -19
- package/src/commands/ui/preset-list.ts +0 -12
- package/src/commands/ui/shared.ts +0 -25
- package/src/commands/update.ts +0 -356
- package/src/commands/use.ts +0 -86
- package/src/commands/view-serve.ts +0 -26
- package/src/commands/view.ts +0 -658
- package/src/connect-core.test.ts +0 -38
- package/src/connect-core.ts +0 -42
- package/src/connection/.spec/api.d.ts +0 -110
- package/src/connection/.spec/architecture.md +0 -58
- package/src/connection/.spec/capabilities/connection.ts +0 -13
- package/src/connection/.spec/examples/call.ts +0 -7
- package/src/connection/.spec/flows/command.ts +0 -20
- package/src/connection/.spec/flows/session.ts +0 -62
- package/src/connection/.spec/laws/connection.ts +0 -213
- package/src/connection/.spec/layout.ts +0 -22
- package/src/connection/__tests__/auth.test.ts +0 -129
- package/src/connection/__tests__/ca-fetch.test.ts +0 -60
- package/src/connection/__tests__/call.test.ts +0 -17
- package/src/connection/__tests__/credential.test.ts +0 -254
- package/src/connection/__tests__/errors.test.ts +0 -577
- package/src/connection/__tests__/exchange.test.ts +0 -404
- package/src/connection/__tests__/failure-fixtures.ts +0 -39
- package/src/connection/__tests__/failure-safety.test.ts +0 -75
- package/src/connection/__tests__/fixtures/localhost-cert.pem +0 -19
- package/src/connection/__tests__/fixtures/localhost-key.base64 +0 -1
- package/src/connection/__tests__/managed.test.ts +0 -39
- package/src/connection/__tests__/reasons.test.ts +0 -78
- package/src/connection/__tests__/self.test.ts +0 -71
- package/src/connection/__tests__/session.test.ts +0 -144
- package/src/connection/__tests__/target.test.ts +0 -95
- package/src/connection/auth.ts +0 -265
- package/src/connection/call.ts +0 -7
- package/src/connection/command.ts +0 -67
- package/src/connection/credential.ts +0 -138
- package/src/connection/errors.ts +0 -1
- package/src/connection/exchange.ts +0 -394
- package/src/connection/failure/classify.ts +0 -110
- package/src/connection/failure/index.ts +0 -18
- package/src/connection/failure/model.ts +0 -28
- package/src/connection/failure/render.ts +0 -116
- package/src/connection/index.ts +0 -8
- package/src/connection/lifetime.ts +0 -25
- package/src/connection/reasons.ts +0 -209
- package/src/connection/self.ts +0 -138
- package/src/connection/session.ts +0 -203
- package/src/connection/target.ts +0 -112
- package/src/connection/tsconfig.json +0 -6
- package/src/errors.ts +0 -66
- package/src/graph/.spec/api.d.ts +0 -41
- package/src/graph/.spec/laws/documents.ts +0 -24
- package/src/graph/.spec/laws/projection.ts +0 -13
- package/src/graph/.spec/layout.ts +0 -14
- package/src/graph/__tests__/mutation.test.ts +0 -51
- package/src/graph/__tests__/projection.test.ts +0 -22
- package/src/graph/__tests__/query.test.ts +0 -180
- package/src/graph/class.ts +0 -30
- package/src/graph/index.ts +0 -4
- package/src/graph/mutation.ts +0 -46
- package/src/graph/projection.ts +0 -21
- package/src/graph/query.ts +0 -95
- package/src/graph/tsconfig.json +0 -6
- package/src/identity/.history/ard/bootstrap-root-transfer.md +0 -57
- package/src/identity/.history/ard/domain-mediated-registration.md +0 -36
- package/src/identity/.spec/api.d.ts +0 -124
- package/src/identity/.spec/architecture.md +0 -33
- package/src/identity/.spec/capabilities/identity.ts +0 -7
- package/src/identity/.spec/flows/bootstrap-root.ts +0 -79
- package/src/identity/.spec/flows/domain-mediated-registration.ts +0 -51
- package/src/identity/.spec/flows/import.ts +0 -29
- package/src/identity/.spec/laws/identity.ts +0 -56
- package/src/identity/.spec/layout.ts +0 -13
- package/src/identity/__tests__/fixtures/registry-journey.ts +0 -65
- package/src/identity/__tests__/registration.test.ts +0 -64
- package/src/identity/__tests__/registry.test.ts +0 -74
- package/src/identity/__tests__/transfer.test.ts +0 -198
- package/src/identity/index.ts +0 -23
- package/src/identity/registration.ts +0 -72
- package/src/identity/registry.ts +0 -181
- package/src/identity/transfer.ts +0 -187
- package/src/identity/tsconfig.json +0 -6
- package/src/index.ts +0 -1
- package/src/keys/.spec/api.d.ts +0 -74
- package/src/keys/.spec/architecture.md +0 -13
- package/src/keys/.spec/laws/keys.ts +0 -43
- package/src/keys/.spec/layout.ts +0 -6
- package/src/keys/__tests__/algorithm.test.ts +0 -39
- package/src/keys/__tests__/keys.test.ts +0 -172
- package/src/keys/algorithm.ts +0 -33
- package/src/keys/credential.ts +0 -113
- package/src/keys/index.ts +0 -14
- package/src/keys/pair.ts +0 -219
- package/src/keys/tsconfig.json +0 -6
- package/src/lib/__tests__/admin-target.test.ts +0 -184
- package/src/lib/__tests__/binary.test.ts +0 -70
- package/src/lib/__tests__/browser-retention.test.ts +0 -212
- package/src/lib/__tests__/command-dx.test.ts +0 -102
- package/src/lib/__tests__/concurrency.test.ts +0 -62
- package/src/lib/__tests__/config.test.ts +0 -81
- package/src/lib/__tests__/design.test.ts +0 -99
- package/src/lib/__tests__/domain-publication.test.ts +0 -138
- package/src/lib/__tests__/format.test.ts +0 -22
- package/src/lib/__tests__/idp-session.driver.ts +0 -60
- package/src/lib/__tests__/idp-session.test.ts +0 -404
- package/src/lib/__tests__/idp.test.ts +0 -415
- package/src/lib/__tests__/instance-candidates.test.ts +0 -146
- package/src/lib/__tests__/instance-target.test.ts +0 -213
- package/src/lib/__tests__/instance.test.ts +0 -192
- package/src/lib/__tests__/local-status.test.ts +0 -202
- package/src/lib/__tests__/log-errors.test.ts +0 -64
- package/src/lib/__tests__/log.test.ts +0 -31
- package/src/lib/__tests__/meta.test.ts +0 -55
- package/src/lib/__tests__/output.test.ts +0 -162
- package/src/lib/__tests__/panel.test.ts +0 -40
- package/src/lib/__tests__/port.test.ts +0 -44
- package/src/lib/__tests__/prompt.test.ts +0 -25
- package/src/lib/__tests__/sdk-deps.test.ts +0 -68
- package/src/lib/__tests__/self.test.ts +0 -50
- package/src/lib/__tests__/skills.test.ts +0 -834
- package/src/lib/__tests__/studio-server-deps.test.ts +0 -111
- package/src/lib/__tests__/table.test.ts +0 -53
- package/src/lib/__tests__/update.test.ts +0 -511
- package/src/lib/__tests__/use-target.test.ts +0 -56
- package/src/lib/__tests__/validation.test.ts +0 -34
- package/src/lib/__tests__/view-assets.test.ts +0 -171
- package/src/lib/__tests__/view-external-open-intent.test.ts +0 -150
- package/src/lib/__tests__/view-external-open-origins.test.ts +0 -27
- package/src/lib/__tests__/view-open-intent.test.ts +0 -280
- package/src/lib/__tests__/view-port-allocation.test.ts +0 -82
- package/src/lib/__tests__/view-server.test.ts +0 -91
- package/src/lib/__tests__/view-session.test.ts +0 -100
- package/src/lib/__tests__/view-snapshot.test.ts +0 -77
- package/src/lib/admin-domain.ts +0 -43
- package/src/lib/admin-instance.ts +0 -56
- package/src/lib/admin-target.ts +0 -290
- package/src/lib/binary.ts +0 -127
- package/src/lib/browser-retention.ts +0 -210
- package/src/lib/browser.ts +0 -150
- package/src/lib/ca-fetch.ts +0 -133
- package/src/lib/command-dx.ts +0 -191
- package/src/lib/concurrency.ts +0 -31
- package/src/lib/config.ts +0 -57
- package/src/lib/credential-lifetime.ts +0 -24
- package/src/lib/domain-publication.ts +0 -104
- package/src/lib/failure-debug.ts +0 -26
- package/src/lib/format.ts +0 -4
- package/src/lib/idp-session.ts +0 -156
- package/src/lib/idp.ts +0 -926
- package/src/lib/instance-candidates.ts +0 -49
- package/src/lib/instance-target.ts +0 -197
- package/src/lib/instance.ts +0 -468
- package/src/lib/invocation.ts +0 -11
- package/src/lib/local-status.ts +0 -152
- package/src/lib/log.ts +0 -143
- package/src/lib/login-flow.ts +0 -201
- package/src/lib/meta.ts +0 -90
- package/src/lib/output.ts +0 -238
- package/src/lib/panel.ts +0 -61
- package/src/lib/port.ts +0 -41
- package/src/lib/proc.ts +0 -87
- package/src/lib/prompt.ts +0 -136
- package/src/lib/provision-instance.ts +0 -139
- package/src/lib/sdk-deps.ts +0 -104
- package/src/lib/self.ts +0 -22
- package/src/lib/skills/lock.ts +0 -117
- package/src/lib/skills/sync.ts +0 -878
- package/src/lib/skills.ts +0 -120
- package/src/lib/table.ts +0 -62
- package/src/lib/update.ts +0 -568
- package/src/lib/use-target.ts +0 -24
- package/src/lib/validation.ts +0 -59
- package/src/lib/view/assets.ts +0 -87
- package/src/lib/view/external-open-intent.ts +0 -41
- package/src/lib/view/external-open-origins.ts +0 -37
- package/src/lib/view/host-capabilities.ts +0 -17
- package/src/lib/view/open-intent.ts +0 -67
- package/src/lib/view/port-allocation.ts +0 -19
- package/src/lib/view/resolve.ts +0 -111
- package/src/lib/view/server.ts +0 -259
- package/src/lib/view/session.ts +0 -154
- package/src/lib/view/snapshot.ts +0 -101
- package/src/paths/.spec/api.d.ts +0 -13
- package/src/paths/.spec/architecture.md +0 -5
- package/src/paths/.spec/layout.ts +0 -3
- package/src/paths/index.ts +0 -13
- package/src/program/.spec/api.d.ts +0 -43
- package/src/program/.spec/architecture.md +0 -18
- package/src/program/.spec/laws/program.ts +0 -29
- package/src/program/.spec/layout.ts +0 -14
- package/src/program/__tests__/program.test.ts +0 -556
- package/src/program/argv.ts +0 -14
- package/src/program/build.ts +0 -205
- package/src/program/command.ts +0 -43
- package/src/program/index.ts +0 -3
- package/src/program/options.ts +0 -41
- package/src/program/registry.ts +0 -64
- package/src/program/tsconfig.json +0 -6
- package/src/setup/__tests__/instance-step.test.ts +0 -256
- package/src/setup/__tests__/util.test.ts +0 -29
- package/src/setup/engine.ts +0 -83
- package/src/setup/render.ts +0 -107
- package/src/setup/steps/admin.ts +0 -93
- package/src/setup/steps/agent-browser.ts +0 -81
- package/src/setup/steps/auth.ts +0 -54
- package/src/setup/steps/domain.ts +0 -68
- package/src/setup/steps/index.ts +0 -18
- package/src/setup/steps/instance.ts +0 -206
- package/src/setup/steps/skills-bridge.ts +0 -70
- package/src/setup/steps/skills.ts +0 -61
- package/src/setup/types.ts +0 -61
- package/src/setup/util.ts +0 -34
- package/src/state/.spec/api.d.ts +0 -152
- package/src/state/.spec/architecture.md +0 -45
- package/src/state/.spec/capabilities/state.ts +0 -7
- package/src/state/.spec/flows/identity-update.ts +0 -22
- package/src/state/.spec/laws/state.ts +0 -73
- package/src/state/.spec/layout.ts +0 -15
- package/src/state/__tests__/exchange-credentials.test.ts +0 -341
- package/src/state/__tests__/files.test.ts +0 -136
- package/src/state/__tests__/fixtures/identity-transition.ts +0 -37
- package/src/state/__tests__/fixtures/session-route-process.ts +0 -93
- package/src/state/__tests__/identities.test.ts +0 -142
- package/src/state/__tests__/paths.test.ts +0 -28
- package/src/state/__tests__/session-routes.test.ts +0 -138
- package/src/state/exchange-credentials.ts +0 -250
- package/src/state/files.ts +0 -170
- package/src/state/identities.ts +0 -229
- package/src/state/index.ts +0 -31
- package/src/state/paths.ts +0 -64
- package/src/state/session-routes.ts +0 -34
- package/src/state/tsconfig.json +0 -6
- package/src/telemetry/__tests__/analyze-log.test.ts +0 -38
- package/src/telemetry/__tests__/gate.test.ts +0 -63
- package/src/telemetry/__tests__/recorder.test.ts +0 -111
- package/src/telemetry/__tests__/redact.test.ts +0 -79
- package/src/telemetry/__tests__/retention.test.ts +0 -267
- package/src/telemetry/__tests__/session.test.ts +0 -166
- package/src/telemetry/__tests__/settings.test.ts +0 -102
- package/src/telemetry/__tests__/store-scan.test.ts +0 -128
- package/src/telemetry/__tests__/trigger.test.ts +0 -78
- package/src/telemetry/adapters/__tests__/claude-code.test.ts +0 -89
- package/src/telemetry/adapters/__tests__/codex.test.ts +0 -138
- package/src/telemetry/adapters/__tests__/index.test.ts +0 -88
- package/src/telemetry/adapters/claude-code.ts +0 -90
- package/src/telemetry/adapters/codex.ts +0 -160
- package/src/telemetry/adapters/index.ts +0 -45
- package/src/telemetry/adapters/types.ts +0 -21
- package/src/telemetry/analyze.ts +0 -249
- package/src/telemetry/gate.ts +0 -79
- package/src/telemetry/recorder.ts +0 -68
- package/src/telemetry/redact.ts +0 -53
- package/src/telemetry/retention.ts +0 -176
- package/src/telemetry/session.ts +0 -94
- package/src/telemetry/settings.ts +0 -79
- package/src/telemetry/store.ts +0 -174
- package/src/telemetry/trigger.ts +0 -107
- package/src/telemetry/types.ts +0 -64
- package/src/test-utils.ts +0 -18
- package/src/ui/.spec/api.d.ts +0 -14
- package/src/ui/.spec/architecture.md +0 -14
- package/src/ui/.spec/laws.ts +0 -50
- package/src/ui/.spec/layout.ts +0 -16
- package/src/ui/__tests__/ui.test.ts +0 -1742
- package/src/ui/index.ts +0 -13
- package/src/ui/lock.ts +0 -89
- package/src/ui/model.ts +0 -83
- package/src/ui/operations.ts +0 -1044
- package/src/ui/project.ts +0 -333
- package/src/ui/release.ts +0 -398
- package/src/ui/runner.ts +0 -18
- package/studio/client/dist/assets/index-BFVFs_8x.js +0 -81
- package/studio/client/dist/assets/index-DuB9iUdu.css +0 -2
- package/studio/client/dist/assets/schema-studio-DH6oEWME.js +0 -8
- package/studio/tsconfig.json +0 -24
- package/viewer/tsconfig.json +0 -13
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import type { IdentityExport } from '../api.js'
|
|
2
|
-
|
|
3
|
-
interface Target {
|
|
4
|
-
readonly name: string
|
|
5
|
-
readonly url: string
|
|
6
|
-
readonly issuer: string
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface ReadyChild {
|
|
10
|
-
readonly target: Target
|
|
11
|
-
readonly operation: string
|
|
12
|
-
readonly instance: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface BootstrapAuthority {
|
|
16
|
-
/** Supported identity-import boundary; never a direct State or Keys write. */
|
|
17
|
-
importIdentity(input: {
|
|
18
|
-
readonly name: 'platform-root'
|
|
19
|
-
readonly envelope: IdentityExport
|
|
20
|
-
}): Promise<void>
|
|
21
|
-
bookmark(input: {
|
|
22
|
-
readonly target: Target
|
|
23
|
-
readonly defaultIdentity?: 'platform-root'
|
|
24
|
-
}): Promise<void>
|
|
25
|
-
/** Authenticated public Identity.whoami result on the selected target. */
|
|
26
|
-
whoami(input: {
|
|
27
|
-
readonly target: Target
|
|
28
|
-
readonly as?: 'platform-root'
|
|
29
|
-
readonly credential?: string
|
|
30
|
-
}): Promise<{ readonly id: string }>
|
|
31
|
-
/** Public manager createInstance call plus Operation and Instance status polling. */
|
|
32
|
-
callCreateChild(input: {
|
|
33
|
-
readonly manager: Target
|
|
34
|
-
readonly as: 'platform-root'
|
|
35
|
-
readonly operationId: string
|
|
36
|
-
readonly slug: string
|
|
37
|
-
}): Promise<ReadyChild>
|
|
38
|
-
/** Public Auth delegation invoked on the manager after authenticated whoami. */
|
|
39
|
-
delegateSelf(input: {
|
|
40
|
-
readonly manager: Target
|
|
41
|
-
readonly as: 'platform-root'
|
|
42
|
-
readonly principal: string
|
|
43
|
-
readonly audience: string
|
|
44
|
-
}): Promise<string>
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Bootstrap uses the imported root directly on the manager, then an unchanged
|
|
49
|
-
* manager-to-child Management carrier whose effective child principal is
|
|
50
|
-
* established only by the child's authenticated whoami result.
|
|
51
|
-
*/
|
|
52
|
-
export async function bootstrapRootAndChild(
|
|
53
|
-
authority: BootstrapAuthority,
|
|
54
|
-
input: {
|
|
55
|
-
readonly envelope: IdentityExport
|
|
56
|
-
readonly manager: Target & { readonly name: 'platform-manager' }
|
|
57
|
-
readonly childSlug: string
|
|
58
|
-
readonly operationId: string
|
|
59
|
-
},
|
|
60
|
-
): Promise<{ readonly managerId: string; readonly childId: string; readonly child: ReadyChild }> {
|
|
61
|
-
await authority.importIdentity({ name: 'platform-root', envelope: input.envelope })
|
|
62
|
-
await authority.bookmark({ target: input.manager, defaultIdentity: 'platform-root' })
|
|
63
|
-
const manager = await authority.whoami({ target: input.manager, as: 'platform-root' })
|
|
64
|
-
const child = await authority.callCreateChild({
|
|
65
|
-
manager: input.manager,
|
|
66
|
-
as: 'platform-root',
|
|
67
|
-
operationId: input.operationId,
|
|
68
|
-
slug: input.childSlug,
|
|
69
|
-
})
|
|
70
|
-
const credential = await authority.delegateSelf({
|
|
71
|
-
manager: input.manager,
|
|
72
|
-
as: 'platform-root',
|
|
73
|
-
principal: manager.id,
|
|
74
|
-
audience: child.target.issuer,
|
|
75
|
-
})
|
|
76
|
-
await authority.bookmark({ target: child.target })
|
|
77
|
-
const effectiveChild = await authority.whoami({ target: child.target, credential })
|
|
78
|
-
return { managerId: manager.id, childId: effectiveChild.id, child }
|
|
79
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import type { ProvisionRequest, ProvisionResult } from '@astrale-os/sdk/auth'
|
|
2
|
-
import type { LocalBinding } from '@astrale-os/sdk/mutation'
|
|
3
|
-
|
|
4
|
-
interface RegistrationAuthority {
|
|
5
|
-
prepareSelfProven(input: {
|
|
6
|
-
readonly identity: string
|
|
7
|
-
readonly classPath: string
|
|
8
|
-
readonly properties: Readonly<Record<string, unknown>>
|
|
9
|
-
readonly kernelIssuer: string
|
|
10
|
-
}): Promise<{ readonly binding: LocalBinding; readonly request: ProvisionRequest }>
|
|
11
|
-
call(input: {
|
|
12
|
-
readonly target: string
|
|
13
|
-
readonly request: ProvisionRequest
|
|
14
|
-
}): Promise<ProvisionResult>
|
|
15
|
-
persist(input: {
|
|
16
|
-
readonly identity: string
|
|
17
|
-
readonly targetKey: string
|
|
18
|
-
readonly issuer: string
|
|
19
|
-
readonly subject: string
|
|
20
|
-
}): Promise<void>
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/** Application Identity Classes are provisioned only through their explicit authority owner. */
|
|
24
|
-
export async function registerThroughDomain(
|
|
25
|
-
authority: RegistrationAuthority,
|
|
26
|
-
input: {
|
|
27
|
-
readonly identity: string
|
|
28
|
-
readonly classPath: string
|
|
29
|
-
readonly properties: Readonly<Record<string, unknown>>
|
|
30
|
-
readonly kernelIssuer: string
|
|
31
|
-
readonly targetKey: string
|
|
32
|
-
readonly callable: string
|
|
33
|
-
},
|
|
34
|
-
): Promise<{ readonly issuer: string; readonly subject: string; readonly nodeId?: string }> {
|
|
35
|
-
const prepared = await authority.prepareSelfProven(input)
|
|
36
|
-
const result = await authority.call({ target: input.callable, request: prepared.request })
|
|
37
|
-
const identity = result.identities[prepared.binding]
|
|
38
|
-
if (identity === undefined) throw new Error('Provision result omitted the prepared binding.')
|
|
39
|
-
await authority.persist({
|
|
40
|
-
identity: input.identity,
|
|
41
|
-
targetKey: input.targetKey,
|
|
42
|
-
issuer: identity.issuer,
|
|
43
|
-
subject: identity.subject,
|
|
44
|
-
})
|
|
45
|
-
const nodeId = result.createdNodes[prepared.binding]
|
|
46
|
-
return {
|
|
47
|
-
issuer: identity.issuer,
|
|
48
|
-
subject: identity.subject,
|
|
49
|
-
...(nodeId === undefined ? {} : { nodeId }),
|
|
50
|
-
}
|
|
51
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { Identity, IdentityExport, IdentityImportOptions, IdentityStore } from '../api.js'
|
|
2
|
-
|
|
3
|
-
declare const withIdentityLock: <Value>(transition: () => Promise<Value>) => Promise<Value>
|
|
4
|
-
declare const readLatest: () => Promise<IdentityStore>
|
|
5
|
-
declare const checkImportConflict: (
|
|
6
|
-
store: IdentityStore,
|
|
7
|
-
envelope: IdentityExport,
|
|
8
|
-
options: IdentityImportOptions,
|
|
9
|
-
) => string
|
|
10
|
-
declare const persistAdmittedKeypair: (envelope: IdentityExport) => Promise<void>
|
|
11
|
-
declare const publishIdentity: (
|
|
12
|
-
store: IdentityStore,
|
|
13
|
-
name: string,
|
|
14
|
-
envelope: IdentityExport,
|
|
15
|
-
options: IdentityImportOptions,
|
|
16
|
-
) => Promise<Identity>
|
|
17
|
-
|
|
18
|
-
/** Import performs all fallible admission before entering this ordered persistence flow. */
|
|
19
|
-
export function importIdentity(
|
|
20
|
-
envelope: IdentityExport,
|
|
21
|
-
options: IdentityImportOptions,
|
|
22
|
-
): Promise<Identity> {
|
|
23
|
-
return withIdentityLock(async () => {
|
|
24
|
-
const store = await readLatest()
|
|
25
|
-
const name = checkImportConflict(store, envelope, options)
|
|
26
|
-
await persistAdmittedKeypair(envelope)
|
|
27
|
-
return publishIdentity(store, name, envelope, options)
|
|
28
|
-
})
|
|
29
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { defineLaw } from '@astrale-os/spec/authoring'
|
|
2
|
-
|
|
3
|
-
export const CLI_IDENTITY_REGISTRY_TRANSITIONS = defineLaw({
|
|
4
|
-
id: 'CLI-IDENTITY-REGISTRY-TRANSITIONS',
|
|
5
|
-
statement:
|
|
6
|
-
'Create, selection, registration, mode change, and non-default deletion preserve one locked registry and isolated subject keypair; deleting the selected identity is rejected unchanged.',
|
|
7
|
-
tests: [{ file: '__tests__/registry.test.ts', id: 'TEST-CLI-IDENTITY-REGISTRY-JOURNEY' }],
|
|
8
|
-
})
|
|
9
|
-
|
|
10
|
-
export const CLI_IDENTITY_TRANSFER_ADMITTED = defineLaw({
|
|
11
|
-
id: 'CLI-IDENTITY-TRANSFER-ADMITTED',
|
|
12
|
-
statement:
|
|
13
|
-
'Malformed, unsupported-version, or cryptographically mismatched transfer content is rejected before either key files or registry state changes.',
|
|
14
|
-
tests: [{ file: '__tests__/transfer.test.ts', id: 'TEST-CLI-IDENTITY-TRANSFER-REJECTS' }],
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
export const CLI_IDENTITY_TRANSFER_ROUNDTRIP = defineLaw({
|
|
18
|
-
id: 'CLI-IDENTITY-TRANSFER-ROUNDTRIP',
|
|
19
|
-
statement:
|
|
20
|
-
'Legacy plaintext and V1 plaintext or compact-JWE content converge on one V1 envelope, and explicit exports are published atomically with mode 0600.',
|
|
21
|
-
tests: [
|
|
22
|
-
{ file: '__tests__/transfer.test.ts', id: 'TEST-CLI-IDENTITY-TRANSFER-ROUNDTRIP' },
|
|
23
|
-
{ file: '__tests__/transfer.test.ts', id: 'TEST-CLI-IDENTITY-EXPORT-PRIVATE' },
|
|
24
|
-
],
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
export const CLI_IDENTITY_TRANSFER_SCHEMA = defineLaw({
|
|
28
|
-
id: 'CLI-IDENTITY-TRANSFER-SCHEMA',
|
|
29
|
-
statement:
|
|
30
|
-
'Plaintext IdentityExport V1 has one independently versioned portable JSON Schema; decoding additionally proves the JWK pair before any durable mutation.',
|
|
31
|
-
tests: [
|
|
32
|
-
{
|
|
33
|
-
file: '__tests__/transfer.test.ts',
|
|
34
|
-
id: 'TEST-CLI-IDENTITY-TRANSFER-SCHEMA',
|
|
35
|
-
},
|
|
36
|
-
],
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
export const CLI_IDENTITY_IMPORT_ORDERED = defineLaw({
|
|
40
|
-
id: 'CLI-IDENTITY-IMPORT-ORDERED',
|
|
41
|
-
statement:
|
|
42
|
-
'Import checks name and identity-source conflicts under the registry lock before replacing keys, then publishes the registry only after the admitted pair is durable.',
|
|
43
|
-
tests: [{ file: '__tests__/transfer.test.ts', id: 'TEST-CLI-IDENTITY-IMPORT-ORDERED' }],
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
export const CLI_IDENTITY_REGISTRATION_AUTHORITY = defineLaw({
|
|
47
|
-
id: 'CLI-IDENTITY-REGISTRATION-AUTHORITY',
|
|
48
|
-
statement:
|
|
49
|
-
'Identity registration binds one self-proven Provision request to the selected Kernel; direct submission uses caller authority, while explicit Domain-mediated submission sends the same request to the named callable and persists only its admitted prepared binding.',
|
|
50
|
-
tests: [
|
|
51
|
-
{
|
|
52
|
-
file: '__tests__/registration.test.ts',
|
|
53
|
-
id: 'TEST-CLI-IDENTITY-REGISTER-DOMAIN-MEDIATED',
|
|
54
|
-
},
|
|
55
|
-
],
|
|
56
|
-
})
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { mkdir, readFile, writeFile } from 'node:fs/promises'
|
|
2
|
-
import { dirname } from 'node:path'
|
|
3
|
-
|
|
4
|
-
import { fileExists, keypairPaths } from '../../../keys/index'
|
|
5
|
-
import { EXCHANGE_CREDENTIALS_PATH, KEYS_DIR, SESSION_ROUTES_PATH } from '../../../state/index'
|
|
6
|
-
import {
|
|
7
|
-
createIdentity,
|
|
8
|
-
exportIdentity,
|
|
9
|
-
importIdentity,
|
|
10
|
-
deleteIdentity,
|
|
11
|
-
getDefault,
|
|
12
|
-
readIdentities,
|
|
13
|
-
setDefault,
|
|
14
|
-
setIdentityMode,
|
|
15
|
-
setRegistration,
|
|
16
|
-
upsertIdpIdentity,
|
|
17
|
-
} from '../../index'
|
|
18
|
-
|
|
19
|
-
await createIdentity('alice')
|
|
20
|
-
await createIdentity('bob', { mode: 'remote' })
|
|
21
|
-
await importIdentity(await exportIdentity('alice'), { name: 'alice-alias' })
|
|
22
|
-
await setDefault('alice')
|
|
23
|
-
await setIdentityMode('bob', 'local')
|
|
24
|
-
await setRegistration('alice', 'production', {
|
|
25
|
-
iss: 'https://kernel.example',
|
|
26
|
-
sub: 'node-alice',
|
|
27
|
-
registeredAt: '2026-08-11T12:00:00.000Z',
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
let selectedDeletion = ''
|
|
31
|
-
try {
|
|
32
|
-
await deleteIdentity('alice')
|
|
33
|
-
} catch (error) {
|
|
34
|
-
selectedDeletion = error instanceof Error ? error.message : String(error)
|
|
35
|
-
}
|
|
36
|
-
await mkdir(dirname(SESSION_ROUTES_PATH), { recursive: true })
|
|
37
|
-
await mkdir(dirname(EXCHANGE_CREDENTIALS_PATH), { recursive: true })
|
|
38
|
-
await writeFile(SESSION_ROUTES_PATH, '{"version":1,"entries":{"confidential":{}}}\n')
|
|
39
|
-
await writeFile(
|
|
40
|
-
EXCHANGE_CREDENTIALS_PATH,
|
|
41
|
-
'{"version":2,"entries":{"confidential":{"credential":"bearer"}}}\n',
|
|
42
|
-
)
|
|
43
|
-
await deleteIdentity('bob')
|
|
44
|
-
await deleteIdentity('alice-alias')
|
|
45
|
-
await upsertIdpIdentity('workos', {
|
|
46
|
-
subject: 'user_123',
|
|
47
|
-
idp: 'workos',
|
|
48
|
-
issuer: 'https://idp.example',
|
|
49
|
-
audience: 'https://kernel.example',
|
|
50
|
-
use: false,
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
const store = await readIdentities()
|
|
54
|
-
const selected = await getDefault()
|
|
55
|
-
console.log(
|
|
56
|
-
JSON.stringify({
|
|
57
|
-
store,
|
|
58
|
-
selected,
|
|
59
|
-
selectedDeletion,
|
|
60
|
-
aliceKey: await fileExists(keypairPaths('alice', KEYS_DIR).privatePath),
|
|
61
|
-
bobKey: await fileExists(keypairPaths('bob', KEYS_DIR).privatePath),
|
|
62
|
-
routeCache: await fileExists(SESSION_ROUTES_PATH),
|
|
63
|
-
exchangeCache: JSON.parse(await readFile(EXCHANGE_CREDENTIALS_PATH, 'utf8')),
|
|
64
|
-
}),
|
|
65
|
-
)
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import type { ProvisionRequest } from '@astrale-os/sdk/auth'
|
|
2
|
-
|
|
3
|
-
import { LocalBinding } from '@astrale-os/sdk/graph'
|
|
4
|
-
import { expect, test } from 'bun:test'
|
|
5
|
-
|
|
6
|
-
import { submitIdentityProvision } from '../registration'
|
|
7
|
-
|
|
8
|
-
/** @evidence TEST-CLI-IDENTITY-REGISTER-DOMAIN-MEDIATED */
|
|
9
|
-
test('submits the exact self-proven request through an explicit Domain callable', async () => {
|
|
10
|
-
const binding = LocalBinding('identity')
|
|
11
|
-
const request = {
|
|
12
|
-
idempotencyKey: 'identity-register:operator',
|
|
13
|
-
mutation: {
|
|
14
|
-
format: 'astrale.graph.mutation',
|
|
15
|
-
version: 'v2',
|
|
16
|
-
preconditions: [],
|
|
17
|
-
operations: [],
|
|
18
|
-
},
|
|
19
|
-
identities: {
|
|
20
|
-
identity: {
|
|
21
|
-
credentials: {
|
|
22
|
-
publicKey: { kty: 'EC', crv: 'P-256', x: 'x', y: 'y', alg: 'ES256' },
|
|
23
|
-
proof: 'self-proven-request.jwt.signature',
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
} as unknown as ProvisionRequest
|
|
28
|
-
const calls: unknown[] = []
|
|
29
|
-
let directCalls = 0
|
|
30
|
-
const result = await submitIdentityProvision({
|
|
31
|
-
binding,
|
|
32
|
-
request,
|
|
33
|
-
via: '/:ops.example:function.provisionOperator',
|
|
34
|
-
direct: {
|
|
35
|
-
async provision() {
|
|
36
|
-
directCalls += 1
|
|
37
|
-
throw new Error('direct provision must not run')
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
callable: {
|
|
41
|
-
async call(call) {
|
|
42
|
-
calls.push(call)
|
|
43
|
-
return {
|
|
44
|
-
createdNodes: { identity: 'operator-node' },
|
|
45
|
-
identities: {
|
|
46
|
-
identity: { issuer: 'https://identity.example', subject: 'operator-node' },
|
|
47
|
-
},
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
expect(directCalls).toBe(0)
|
|
54
|
-
expect(calls).toHaveLength(1)
|
|
55
|
-
expect(JSON.parse(JSON.stringify(calls[0]))).toEqual({
|
|
56
|
-
target: '/:ops.example:function.provisionOperator',
|
|
57
|
-
input: JSON.parse(JSON.stringify(request)),
|
|
58
|
-
})
|
|
59
|
-
expect(result).toEqual({
|
|
60
|
-
iss: 'https://identity.example',
|
|
61
|
-
sub: 'operator-node',
|
|
62
|
-
nodeId: 'operator-node',
|
|
63
|
-
})
|
|
64
|
-
})
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
|
|
2
|
-
import { mkdtemp, readFile, rm } from 'node:fs/promises'
|
|
3
|
-
import { tmpdir } from 'node:os'
|
|
4
|
-
import { join } from 'node:path'
|
|
5
|
-
|
|
6
|
-
describe('identity registry journey', () => {
|
|
7
|
-
let root = ''
|
|
8
|
-
|
|
9
|
-
beforeEach(async () => {
|
|
10
|
-
root = await mkdtemp(join(tmpdir(), 'astrale-identity-registry-'))
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
afterEach(async () => {
|
|
14
|
-
await rm(root, { recursive: true, force: true })
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
/** @evidence TEST-CLI-IDENTITY-REGISTRY-JOURNEY */
|
|
18
|
-
test('runs create, selection, registration, mode, IdP, and deletion in a real process', async () => {
|
|
19
|
-
const child = Bun.spawn(
|
|
20
|
-
[process.execPath, join(import.meta.dir, 'fixtures', 'registry-journey.ts')],
|
|
21
|
-
{
|
|
22
|
-
env: { ...process.env, ASTRALE_HOME: root },
|
|
23
|
-
stdout: 'pipe',
|
|
24
|
-
stderr: 'pipe',
|
|
25
|
-
},
|
|
26
|
-
)
|
|
27
|
-
const [exitCode, stdout, stderr] = await Promise.all([
|
|
28
|
-
child.exited,
|
|
29
|
-
new Response(child.stdout).text(),
|
|
30
|
-
new Response(child.stderr).text(),
|
|
31
|
-
])
|
|
32
|
-
expect(exitCode, stderr).toBe(0)
|
|
33
|
-
|
|
34
|
-
const result = JSON.parse(stdout) as {
|
|
35
|
-
store: {
|
|
36
|
-
default: string
|
|
37
|
-
identities: Record<
|
|
38
|
-
string,
|
|
39
|
-
{
|
|
40
|
-
source?: string
|
|
41
|
-
mode?: string
|
|
42
|
-
registrations?: Record<string, { iss: string; sub: string; registeredAt: string }>
|
|
43
|
-
}
|
|
44
|
-
>
|
|
45
|
-
}
|
|
46
|
-
selected: { name: string; subject: string }
|
|
47
|
-
selectedDeletion: string
|
|
48
|
-
aliceKey: boolean
|
|
49
|
-
bobKey: boolean
|
|
50
|
-
routeCache: boolean
|
|
51
|
-
exchangeCache: unknown
|
|
52
|
-
}
|
|
53
|
-
expect(result.store.default).toBe('alice')
|
|
54
|
-
expect(Object.keys(result.store.identities).sort()).toEqual(['alice', 'workos'])
|
|
55
|
-
expect(result.store.identities.alice.registrations?.production).toEqual({
|
|
56
|
-
iss: 'https://kernel.example',
|
|
57
|
-
sub: 'node-alice',
|
|
58
|
-
registeredAt: '2026-08-11T12:00:00.000Z',
|
|
59
|
-
})
|
|
60
|
-
expect(result.store.identities.workos).toMatchObject({ source: 'idp', mode: 'remote' })
|
|
61
|
-
expect(result.selected).toMatchObject({ name: 'alice', subject: 'alice' })
|
|
62
|
-
expect(result.selectedDeletion).toContain('Cannot delete the default identity')
|
|
63
|
-
expect(result.aliceKey).toBe(true)
|
|
64
|
-
expect(result.bobKey).toBe(false)
|
|
65
|
-
expect(result.routeCache).toBe(false)
|
|
66
|
-
expect(result.exchangeCache).toEqual({ version: 2, entries: {} })
|
|
67
|
-
|
|
68
|
-
const persisted = JSON.parse(await readFile(join(root, 'identities.json'), 'utf-8')) as {
|
|
69
|
-
version?: unknown
|
|
70
|
-
}
|
|
71
|
-
expect(persisted.version).toBe(1)
|
|
72
|
-
expect(stdout).not.toContain('"d":')
|
|
73
|
-
})
|
|
74
|
-
})
|
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
|
|
2
|
-
import { access, mkdtemp, readFile, readdir, rm, stat } from 'node:fs/promises'
|
|
3
|
-
import { tmpdir } from 'node:os'
|
|
4
|
-
import { join } from 'node:path'
|
|
5
|
-
import { fileURLToPath } from 'node:url'
|
|
6
|
-
|
|
7
|
-
import { keypairPaths, persistKeypair, readKeypair } from '../../keys/index'
|
|
8
|
-
import { readIdentityStore, updateIdentityStore } from '../../state/index'
|
|
9
|
-
import {
|
|
10
|
-
decodeIdentityExport,
|
|
11
|
-
encodeIdentityExport,
|
|
12
|
-
exportIdentity,
|
|
13
|
-
importIdentity,
|
|
14
|
-
isEncryptedIdentityExport,
|
|
15
|
-
writeIdentityExport,
|
|
16
|
-
type IdentityExport,
|
|
17
|
-
} from '../index'
|
|
18
|
-
|
|
19
|
-
describe('identity transfer', () => {
|
|
20
|
-
let root = ''
|
|
21
|
-
let statePath = ''
|
|
22
|
-
let keysDir = ''
|
|
23
|
-
const now = () => new Date('2026-08-11T12:00:00.000Z')
|
|
24
|
-
|
|
25
|
-
beforeEach(async () => {
|
|
26
|
-
root = await mkdtemp(join(tmpdir(), 'astrale-identity-transfer-'))
|
|
27
|
-
statePath = join(root, 'identities.json')
|
|
28
|
-
keysDir = join(root, 'keys')
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
afterEach(async () => {
|
|
32
|
-
await rm(root, { recursive: true, force: true })
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
async function envelope(subject: string, suffix: string): Promise<IdentityExport> {
|
|
36
|
-
const pair = await persistKeypair(subject, {
|
|
37
|
-
keysDir: join(root, `source-${suffix}`),
|
|
38
|
-
kid: `${subject}-${suffix}`,
|
|
39
|
-
})
|
|
40
|
-
return decodeIdentityExport(
|
|
41
|
-
JSON.stringify({
|
|
42
|
-
version: 1,
|
|
43
|
-
subject,
|
|
44
|
-
mode: 'local',
|
|
45
|
-
kid: pair.kid,
|
|
46
|
-
issuer: 'https://identity.example',
|
|
47
|
-
privateJwk: pair.privateJwk,
|
|
48
|
-
publicJwk: pair.publicJwk,
|
|
49
|
-
}),
|
|
50
|
-
)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/** @evidence TEST-CLI-IDENTITY-TRANSFER-REJECTS */
|
|
54
|
-
test('rejects malformed, newer, and mismatched content before durable mutation', async () => {
|
|
55
|
-
await expect(decodeIdentityExport('{')).rejects.toThrow(/not valid JSON/)
|
|
56
|
-
await expect(
|
|
57
|
-
decodeIdentityExport(
|
|
58
|
-
JSON.stringify({
|
|
59
|
-
version: 2,
|
|
60
|
-
subject: 'alice',
|
|
61
|
-
mode: 'local',
|
|
62
|
-
privateJwk: {},
|
|
63
|
-
publicJwk: {},
|
|
64
|
-
}),
|
|
65
|
-
),
|
|
66
|
-
).rejects.toThrow(/invalid or unsupported shape/)
|
|
67
|
-
|
|
68
|
-
const alice = await envelope('alice', 'a')
|
|
69
|
-
const bob = await envelope('bob', 'b')
|
|
70
|
-
const forged = {
|
|
71
|
-
...alice,
|
|
72
|
-
publicJwk: { ...bob.publicJwk, kid: alice.kid },
|
|
73
|
-
} as IdentityExport
|
|
74
|
-
const mismatch = await importIdentity(forged, {
|
|
75
|
-
state: { path: statePath, now },
|
|
76
|
-
keysDir,
|
|
77
|
-
}).catch((error) => error)
|
|
78
|
-
expect(mismatch).toBeInstanceOf(Error)
|
|
79
|
-
expect((mismatch as Error).message).toMatch(/do not form a valid matching pair/)
|
|
80
|
-
expect((mismatch as Error).message).not.toContain(String(alice.privateJwk.d))
|
|
81
|
-
|
|
82
|
-
await expect(access(statePath)).rejects.toThrow()
|
|
83
|
-
await expect(access(keypairPaths('alice', keysDir).privatePath)).rejects.toThrow()
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
/** @evidence TEST-CLI-IDENTITY-TRANSFER-ROUNDTRIP */
|
|
87
|
-
test('converges legacy, V1, and encrypted representations on one envelope', async () => {
|
|
88
|
-
const current = await envelope('alice', 'roundtrip')
|
|
89
|
-
const { version: _, ...legacy } = current
|
|
90
|
-
expect(await decodeIdentityExport(JSON.stringify(legacy))).toEqual(current)
|
|
91
|
-
|
|
92
|
-
const plaintext = await encodeIdentityExport(current)
|
|
93
|
-
expect(isEncryptedIdentityExport(plaintext)).toBe(false)
|
|
94
|
-
expect(await decodeIdentityExport(plaintext)).toEqual(current)
|
|
95
|
-
|
|
96
|
-
const encrypted = await encodeIdentityExport(current, 'correct-horse-battery')
|
|
97
|
-
expect(isEncryptedIdentityExport(encrypted)).toBe(true)
|
|
98
|
-
expect(await decodeIdentityExport(encrypted, 'correct-horse-battery')).toEqual(current)
|
|
99
|
-
await expect(decodeIdentityExport(encrypted, 'wrong')).rejects.toThrow(/Could not decrypt/)
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
/** @evidence TEST-CLI-IDENTITY-TRANSFER-SCHEMA */
|
|
103
|
-
test('keeps the portable V1 JSON Schema aligned with the admitted identity envelope', async () => {
|
|
104
|
-
const schemaPath = fileURLToPath(
|
|
105
|
-
new URL('../.spec/schemas/identity-export-v1.schema.json', import.meta.url),
|
|
106
|
-
)
|
|
107
|
-
const schema = JSON.parse(await readFile(schemaPath, 'utf8')) as {
|
|
108
|
-
readonly $id: string
|
|
109
|
-
readonly additionalProperties: boolean
|
|
110
|
-
readonly required: readonly string[]
|
|
111
|
-
readonly properties: Readonly<Record<string, unknown>>
|
|
112
|
-
}
|
|
113
|
-
const identityEnvelope = await envelope('manager-principal', 'host-bootstrap')
|
|
114
|
-
|
|
115
|
-
expect(schema.$id).toBe('https://schemas.astrale.ai/cli/identity-export/1')
|
|
116
|
-
expect(schema.additionalProperties).toBe(false)
|
|
117
|
-
expect(schema.required).toEqual(['version', 'subject', 'privateJwk', 'publicJwk'])
|
|
118
|
-
expect(Object.keys(schema.properties).sort()).toEqual(
|
|
119
|
-
['issuer', 'kid', 'mode', 'privateJwk', 'publicJwk', 'subject', 'version'].sort(),
|
|
120
|
-
)
|
|
121
|
-
await expect(decodeIdentityExport(JSON.stringify(identityEnvelope))).resolves.toEqual(
|
|
122
|
-
identityEnvelope,
|
|
123
|
-
)
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
/** @evidence TEST-CLI-IDENTITY-IMPORT-ORDERED */
|
|
127
|
-
test('checks conflicts before key replacement and publishes registry after keys', async () => {
|
|
128
|
-
const first = await envelope('alice', 'first')
|
|
129
|
-
const imported = await importIdentity(first, {
|
|
130
|
-
name: 'operator',
|
|
131
|
-
state: { path: statePath, now },
|
|
132
|
-
keysDir,
|
|
133
|
-
})
|
|
134
|
-
expect(imported.subject).toBe('alice')
|
|
135
|
-
expect((await readKeypair('alice', keysDir)).kid).toBe(first.kid)
|
|
136
|
-
expect((await readIdentityStore({ path: statePath })).identities.operator).toEqual(imported)
|
|
137
|
-
|
|
138
|
-
const privatePath = keypairPaths('alice', keysDir).privatePath
|
|
139
|
-
const originalPrivate = await readFile(privatePath, 'utf-8')
|
|
140
|
-
const replacement = await envelope('alice', 'replacement')
|
|
141
|
-
await expect(
|
|
142
|
-
importIdentity(replacement, {
|
|
143
|
-
name: 'operator',
|
|
144
|
-
state: { path: statePath, now },
|
|
145
|
-
keysDir,
|
|
146
|
-
}),
|
|
147
|
-
).rejects.toThrow('already exists')
|
|
148
|
-
expect(await readFile(privatePath, 'utf-8')).toBe(originalPrivate)
|
|
149
|
-
|
|
150
|
-
await updateIdentityStore(
|
|
151
|
-
(store) => ({
|
|
152
|
-
next: {
|
|
153
|
-
...store,
|
|
154
|
-
identities: {
|
|
155
|
-
...store.identities,
|
|
156
|
-
remote: {
|
|
157
|
-
subject: 'remote-user',
|
|
158
|
-
createdAt: now().toISOString(),
|
|
159
|
-
source: 'idp',
|
|
160
|
-
mode: 'remote',
|
|
161
|
-
idp: 'workos',
|
|
162
|
-
issuer: 'https://idp.example',
|
|
163
|
-
},
|
|
164
|
-
},
|
|
165
|
-
},
|
|
166
|
-
value: undefined,
|
|
167
|
-
}),
|
|
168
|
-
{ path: statePath, now },
|
|
169
|
-
)
|
|
170
|
-
await expect(
|
|
171
|
-
importIdentity(await envelope('remote-user', 'remote'), {
|
|
172
|
-
name: 'remote',
|
|
173
|
-
replace: true,
|
|
174
|
-
state: { path: statePath, now },
|
|
175
|
-
keysDir,
|
|
176
|
-
}),
|
|
177
|
-
).rejects.toThrow(/IdP-backed/)
|
|
178
|
-
await expect(access(keypairPaths('remote-user', keysDir).privatePath)).rejects.toThrow()
|
|
179
|
-
})
|
|
180
|
-
|
|
181
|
-
/** @evidence TEST-CLI-IDENTITY-EXPORT-PRIVATE */
|
|
182
|
-
test('exports a proven pair through one atomic mode-0600 file', async () => {
|
|
183
|
-
await importIdentity(await envelope('alice', 'export'), {
|
|
184
|
-
state: { path: statePath, now },
|
|
185
|
-
keysDir,
|
|
186
|
-
})
|
|
187
|
-
const exported = await exportIdentity('alice', {
|
|
188
|
-
state: { path: statePath, now },
|
|
189
|
-
keysDir,
|
|
190
|
-
})
|
|
191
|
-
const path = join(root, 'alice.identity.json')
|
|
192
|
-
await writeIdentityExport(path, await encodeIdentityExport(exported))
|
|
193
|
-
|
|
194
|
-
expect((await stat(path)).mode & 0o777).toBe(0o600)
|
|
195
|
-
expect(await decodeIdentityExport(await readFile(path, 'utf-8'))).toEqual(exported)
|
|
196
|
-
expect((await readdir(root)).some((entry) => entry.endsWith('.tmp'))).toBe(false)
|
|
197
|
-
})
|
|
198
|
-
})
|
package/src/identity/index.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export {
|
|
2
|
-
createIdentity,
|
|
3
|
-
deleteIdentity,
|
|
4
|
-
getDefault,
|
|
5
|
-
getIdentity,
|
|
6
|
-
readIdentities,
|
|
7
|
-
setDefault,
|
|
8
|
-
setIdentityMode,
|
|
9
|
-
setRegistration,
|
|
10
|
-
upsertIdpIdentity,
|
|
11
|
-
} from './registry'
|
|
12
|
-
export {
|
|
13
|
-
decodeIdentityExport,
|
|
14
|
-
encodeIdentityExport,
|
|
15
|
-
exportIdentity,
|
|
16
|
-
importIdentity,
|
|
17
|
-
isEncryptedIdentityExport,
|
|
18
|
-
writeIdentityExport,
|
|
19
|
-
} from './transfer'
|
|
20
|
-
export { acceptProvisionedIdentity, submitIdentityProvision } from './registration'
|
|
21
|
-
export type { IdentityProvisionSubmission, IdentityRegistrationResult } from './registration'
|
|
22
|
-
export type { Identity, IdentityStore, Registration } from './registry'
|
|
23
|
-
export type { IdentityExport, IdentityFileOptions, IdentityImportOptions } from './transfer'
|