@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,191 +0,0 @@
|
|
|
1
|
-
import type { ClientSession } from '@astrale-os/sdk/client/session'
|
|
2
|
-
|
|
3
|
-
import { Path } from '@astrale-os/sdk/graph/path'
|
|
4
|
-
|
|
5
|
-
import { AdminContract, callAdminMethod } from '../contract'
|
|
6
|
-
import {
|
|
7
|
-
AdminInstanceNotFoundError,
|
|
8
|
-
findOwnedInstance,
|
|
9
|
-
type DomainInstallReceipt,
|
|
10
|
-
type InstanceInfo,
|
|
11
|
-
type InstanceState,
|
|
12
|
-
type OwnedInstanceInfo,
|
|
13
|
-
} from './model'
|
|
14
|
-
|
|
15
|
-
export interface AdminInstanceContext {
|
|
16
|
-
readonly session: ClientSession
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface AdminInstanceApi {
|
|
20
|
-
list(): Promise<OwnedInstanceInfo[]>
|
|
21
|
-
create(slug: string): Promise<InstanceInfo>
|
|
22
|
-
status(identifier: string): Promise<InstanceInfo>
|
|
23
|
-
delete(identifier: string): Promise<InstanceInfo>
|
|
24
|
-
installDomain(identifier: string, domain: string): Promise<DomainInstallReceipt>
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface AdminInstanceDependencies {
|
|
28
|
-
readonly operationId?: (kind: 'create' | 'status' | 'delete' | 'install-domain') => string
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Connect the public Instance journey through stable Admin call paths. Routine
|
|
33
|
-
* operations perform no schema discovery. No Host lifecycle method is present.
|
|
34
|
-
*/
|
|
35
|
-
export async function connectAdminInstances(
|
|
36
|
-
context: AdminInstanceContext,
|
|
37
|
-
dependencies: AdminInstanceDependencies = {},
|
|
38
|
-
): Promise<AdminInstanceApi> {
|
|
39
|
-
const operationId = dependencies.operationId ?? defaultOperationId
|
|
40
|
-
|
|
41
|
-
const list = async (): Promise<OwnedInstanceInfo[]> => {
|
|
42
|
-
const result: unknown = await callAdminMethod(
|
|
43
|
-
context.session,
|
|
44
|
-
AdminContract.fleet,
|
|
45
|
-
'listInstances',
|
|
46
|
-
{},
|
|
47
|
-
)
|
|
48
|
-
if (!Array.isArray(result)) throw new TypeError('Admin Instance inventory is invalid.')
|
|
49
|
-
return result.map((value) => instanceFromSummary(value) as OwnedInstanceInfo)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const requireInstance = async (identifier: string): Promise<OwnedInstanceInfo> => {
|
|
53
|
-
const found = findOwnedInstance(await list(), identifier)
|
|
54
|
-
if (found === undefined) throw new AdminInstanceNotFoundError(identifier)
|
|
55
|
-
return found
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const invokeInstance = async (
|
|
59
|
-
method: 'status' | 'delete',
|
|
60
|
-
identifier: string,
|
|
61
|
-
): Promise<InstanceInfo> => {
|
|
62
|
-
const instance = await requireInstance(identifier)
|
|
63
|
-
const output = await callAdminMethod(context.session, Path.parse(instance.id), method, {
|
|
64
|
-
operationId: operationId(method),
|
|
65
|
-
})
|
|
66
|
-
return instanceFromSummary(output)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return Object.freeze({
|
|
70
|
-
list,
|
|
71
|
-
async create(slug: string) {
|
|
72
|
-
const input = Object.freeze({
|
|
73
|
-
operationId: operationId('create'),
|
|
74
|
-
slug,
|
|
75
|
-
})
|
|
76
|
-
return instanceFromSummary(
|
|
77
|
-
await callAdminMethod(context.session, AdminContract.fleet, 'createInstance', input),
|
|
78
|
-
)
|
|
79
|
-
},
|
|
80
|
-
status: (identifier: string) => invokeInstance('status', identifier),
|
|
81
|
-
delete: (identifier: string) => invokeInstance('delete', identifier),
|
|
82
|
-
async installDomain(identifier: string, domain: string): Promise<DomainInstallReceipt> {
|
|
83
|
-
const instance = await requireInstance(identifier)
|
|
84
|
-
const output = await callAdminMethod(
|
|
85
|
-
context.session,
|
|
86
|
-
Path.parse(instance.id),
|
|
87
|
-
'installDomain',
|
|
88
|
-
{
|
|
89
|
-
operationId: operationId('install-domain'),
|
|
90
|
-
domain: Path.parse(domain).raw,
|
|
91
|
-
},
|
|
92
|
-
)
|
|
93
|
-
return domainInstallReceipt(output)
|
|
94
|
-
},
|
|
95
|
-
})
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function instanceFromSummary(input: unknown): InstanceInfo {
|
|
99
|
-
const value = record(input, 'Admin Instance summary')
|
|
100
|
-
const failure = value.failure === undefined ? undefined : record(value.failure, 'Admin failure')
|
|
101
|
-
return Object.freeze({
|
|
102
|
-
id: requiredNodePath(value.id, 'Admin Instance id'),
|
|
103
|
-
slug: requiredString(value.slug, 'Admin Instance slug'),
|
|
104
|
-
url: optionalStringValue(value.url) ?? '',
|
|
105
|
-
...(value.hostId === undefined
|
|
106
|
-
? {}
|
|
107
|
-
: { hostId: requiredNodePath(value.hostId, 'Admin Host id') }),
|
|
108
|
-
...(value.region === undefined
|
|
109
|
-
? {}
|
|
110
|
-
: { region: requiredString(value.region, 'Admin Host region') }),
|
|
111
|
-
state: instanceState(value.state),
|
|
112
|
-
...(value.phase === undefined
|
|
113
|
-
? {}
|
|
114
|
-
: { phase: requiredString(value.phase, 'Admin Instance phase') }),
|
|
115
|
-
...(failure === undefined
|
|
116
|
-
? {}
|
|
117
|
-
: { error: requiredString(failure.message, 'Admin failure message') }),
|
|
118
|
-
...(value.createdAt === undefined
|
|
119
|
-
? {}
|
|
120
|
-
: { createdAt: requiredString(value.createdAt, 'Admin Instance creation time') }),
|
|
121
|
-
...(value.updatedAt === undefined
|
|
122
|
-
? {}
|
|
123
|
-
: { updatedAt: requiredString(value.updatedAt, 'Admin Instance update time') }),
|
|
124
|
-
...(value.organizationId === undefined
|
|
125
|
-
? {}
|
|
126
|
-
: { organizationId: requiredString(value.organizationId, 'Admin organization id') }),
|
|
127
|
-
})
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function domainInstallReceipt(input: unknown): DomainInstallReceipt {
|
|
131
|
-
const value = record(input, 'Admin Domain install receipt')
|
|
132
|
-
const failure = value.failure === undefined ? undefined : record(value.failure, 'Admin failure')
|
|
133
|
-
if (typeof value.ok !== 'boolean') throw new TypeError('Admin Domain install outcome is invalid.')
|
|
134
|
-
return Object.freeze({
|
|
135
|
-
domain: requiredNodePath(value.domain, 'Admin Domain reference'),
|
|
136
|
-
instance: requiredNodePath(value.instance, 'Admin Instance reference'),
|
|
137
|
-
origin: requiredString(value.origin, 'Installed Domain origin'),
|
|
138
|
-
ok: value.ok,
|
|
139
|
-
...(value.installedRevision === undefined
|
|
140
|
-
? {}
|
|
141
|
-
: {
|
|
142
|
-
installedRevision: requiredString(value.installedRevision, 'Installed Domain revision'),
|
|
143
|
-
}),
|
|
144
|
-
...(failure === undefined
|
|
145
|
-
? {}
|
|
146
|
-
: { error: requiredString(failure.message, 'Admin Domain install failure') }),
|
|
147
|
-
})
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function instanceState(input: unknown): InstanceState {
|
|
151
|
-
if (
|
|
152
|
-
input === 'provisioning' ||
|
|
153
|
-
input === 'ready' ||
|
|
154
|
-
input === 'deleting' ||
|
|
155
|
-
input === 'failed' ||
|
|
156
|
-
input === 'deleted'
|
|
157
|
-
) {
|
|
158
|
-
return input
|
|
159
|
-
}
|
|
160
|
-
throw new TypeError('Admin Instance state is invalid.')
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function requiredString(input: unknown, label: string): string {
|
|
164
|
-
if (typeof input !== 'string' || input.length === 0) throw new TypeError(`${label} is invalid.`)
|
|
165
|
-
return input
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function requiredNodePath(input: unknown, label: string): string {
|
|
169
|
-
const value = requiredString(input, label)
|
|
170
|
-
try {
|
|
171
|
-
return Path.parse(value).raw
|
|
172
|
-
} catch {
|
|
173
|
-
throw new TypeError(`${label} is invalid.`)
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
function optionalStringValue(input: unknown): string | undefined {
|
|
178
|
-
if (input === undefined) return undefined
|
|
179
|
-
return requiredString(input, 'Admin string value')
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
function record(input: unknown, label: string): Readonly<Record<string, unknown>> {
|
|
183
|
-
if (typeof input !== 'object' || input === null || Array.isArray(input)) {
|
|
184
|
-
throw new TypeError(`${label} is invalid.`)
|
|
185
|
-
}
|
|
186
|
-
return input as Readonly<Record<string, unknown>>
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
function defaultOperationId(kind: 'create' | 'status' | 'delete' | 'install-domain'): string {
|
|
190
|
-
return `cli.instance.${kind}:${globalThis.crypto.randomUUID()}`
|
|
191
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export {
|
|
2
|
-
connectAdminInstances,
|
|
3
|
-
type AdminInstanceApi,
|
|
4
|
-
type AdminInstanceContext,
|
|
5
|
-
type AdminInstanceDependencies,
|
|
6
|
-
} from './client'
|
|
7
|
-
export {
|
|
8
|
-
AdminInstanceNotFoundError,
|
|
9
|
-
findOwnedInstance,
|
|
10
|
-
formatInstanceState,
|
|
11
|
-
type DomainInstallReceipt,
|
|
12
|
-
type InstanceInfo,
|
|
13
|
-
type InstanceState,
|
|
14
|
-
type OwnedInstanceInfo,
|
|
15
|
-
} from './model'
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/** CLI-stable projection of one caller-visible Admin Instance. */
|
|
2
|
-
export type InstanceState = 'provisioning' | 'ready' | 'deleting' | 'failed' | 'deleted'
|
|
3
|
-
|
|
4
|
-
export interface InstanceInfo {
|
|
5
|
-
readonly id: string
|
|
6
|
-
readonly slug: string
|
|
7
|
-
readonly url: string
|
|
8
|
-
readonly hostId?: string
|
|
9
|
-
readonly region?: string
|
|
10
|
-
readonly state: InstanceState
|
|
11
|
-
readonly phase?: string
|
|
12
|
-
readonly error?: string | null
|
|
13
|
-
readonly createdAt?: string
|
|
14
|
-
readonly updatedAt?: string
|
|
15
|
-
readonly organizationId?: string
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/** An Instance returned through the caller-scoped Admin graph inventory. */
|
|
19
|
-
export interface OwnedInstanceInfo extends InstanceInfo {
|
|
20
|
-
readonly state: InstanceState
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface DomainInstallReceipt {
|
|
24
|
-
readonly domain: string
|
|
25
|
-
readonly instance: string
|
|
26
|
-
readonly origin: string
|
|
27
|
-
readonly ok: boolean
|
|
28
|
-
readonly installedRevision?: string
|
|
29
|
-
readonly error?: string
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export class AdminInstanceNotFoundError extends AstraleError {
|
|
33
|
-
constructor(readonly identifier: string) {
|
|
34
|
-
super(
|
|
35
|
-
'INSTANCE_NOT_FOUND',
|
|
36
|
-
`No owned Admin Instance matches ${JSON.stringify(identifier)}.`,
|
|
37
|
-
'Run `astrale instance list` to see your instances.',
|
|
38
|
-
)
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/** Match an owner-scoped Instance by slug, canonical Node Path, or bare Node id. */
|
|
43
|
-
export function findOwnedInstance(
|
|
44
|
-
instances: readonly OwnedInstanceInfo[],
|
|
45
|
-
identifier: string,
|
|
46
|
-
): OwnedInstanceInfo | undefined {
|
|
47
|
-
return instances.find(
|
|
48
|
-
(instance) =>
|
|
49
|
-
instance.slug === identifier ||
|
|
50
|
-
instance.id === identifier ||
|
|
51
|
-
(instance.id.startsWith('@') && instance.id.slice(1) === identifier),
|
|
52
|
-
)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/** Human-readable non-ready lifecycle state for one Instance. */
|
|
56
|
-
export function formatInstanceState(info: InstanceInfo): string {
|
|
57
|
-
return info.state === 'ready' ? '' : `${info.state}${info.phase ? ` (${info.phase})` : ''}`
|
|
58
|
-
}
|
|
59
|
-
import { AstraleError } from '../../errors'
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from 'bun:test'
|
|
2
|
-
|
|
3
|
-
import type { IdentityStore } from '../../identity/index'
|
|
4
|
-
|
|
5
|
-
import { AuthError } from '../../errors'
|
|
6
|
-
import { findOwnedInstance, type OwnedInstanceInfo } from '../../lib/admin-instance'
|
|
7
|
-
import {
|
|
8
|
-
assertInstanceCreateIdentity,
|
|
9
|
-
selectInstanceCreateIdentity,
|
|
10
|
-
} from '../../lib/provision-instance'
|
|
11
|
-
|
|
12
|
-
describe('admin-backed instance commands', () => {
|
|
13
|
-
test('findOwnedInstance matches owner inventory by slug or stable node id', () => {
|
|
14
|
-
const owned = {
|
|
15
|
-
id: 'instance-node',
|
|
16
|
-
slug: 'demo',
|
|
17
|
-
url: 'https://demo.eu.astrale.ai',
|
|
18
|
-
state: 'failed',
|
|
19
|
-
organizationId: 'org_123',
|
|
20
|
-
phase: 'installing:default-domains',
|
|
21
|
-
error: 'postInstall failed',
|
|
22
|
-
createdAt: '2026-07-16T00:00:00.000Z',
|
|
23
|
-
} satisfies OwnedInstanceInfo
|
|
24
|
-
|
|
25
|
-
expect(findOwnedInstance([owned], 'demo')).toBe(owned)
|
|
26
|
-
expect(findOwnedInstance([owned], 'instance-node')).toBe(owned)
|
|
27
|
-
expect(findOwnedInstance([owned], 'other')).toBeUndefined()
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
test('instance create preflight points fresh installs at WorkOS login', () => {
|
|
31
|
-
const store: IdentityStore = {
|
|
32
|
-
default: 'manager',
|
|
33
|
-
identities: {
|
|
34
|
-
manager: {
|
|
35
|
-
subject: 'manager',
|
|
36
|
-
createdAt: '2026-06-08T00:00:00.000Z',
|
|
37
|
-
source: 'key',
|
|
38
|
-
mode: 'local',
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
expect(() => assertInstanceCreateIdentity(store)).toThrow(AuthError)
|
|
44
|
-
expect(() => assertInstanceCreateIdentity(store)).toThrow('WorkOS login required')
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
test('instance create preflight accepts IdP-backed identities', () => {
|
|
48
|
-
const store: IdentityStore = {
|
|
49
|
-
default: 'bryan',
|
|
50
|
-
identities: {
|
|
51
|
-
bryan: {
|
|
52
|
-
subject: 'user_123',
|
|
53
|
-
createdAt: '2026-06-08T00:00:00.000Z',
|
|
54
|
-
source: 'idp',
|
|
55
|
-
mode: 'remote',
|
|
56
|
-
idp: 'workos',
|
|
57
|
-
issuer: 'https://auth.example.com',
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
expect(() => assertInstanceCreateIdentity(store)).not.toThrow()
|
|
63
|
-
expect(selectInstanceCreateIdentity(store)).toBe('bryan')
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
test('--as selection must also be IdP-backed', () => {
|
|
67
|
-
const store: IdentityStore = {
|
|
68
|
-
default: 'local',
|
|
69
|
-
identities: {
|
|
70
|
-
local: {
|
|
71
|
-
subject: 'local',
|
|
72
|
-
createdAt: '2026-06-08T00:00:00.000Z',
|
|
73
|
-
source: 'key',
|
|
74
|
-
mode: 'local',
|
|
75
|
-
},
|
|
76
|
-
workos: {
|
|
77
|
-
subject: 'user_123',
|
|
78
|
-
createdAt: '2026-06-08T00:00:00.000Z',
|
|
79
|
-
source: 'idp',
|
|
80
|
-
mode: 'remote',
|
|
81
|
-
idp: 'workos',
|
|
82
|
-
issuer: 'https://auth.example.com',
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
expect(() => assertInstanceCreateIdentity(store, { as: 'local' })).toThrow(AuthError)
|
|
88
|
-
expect(() => assertInstanceCreateIdentity(store, { as: 'workos' })).not.toThrow()
|
|
89
|
-
expect(selectInstanceCreateIdentity(store, { as: 'workos' })).toBe('workos')
|
|
90
|
-
})
|
|
91
|
-
})
|
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
|
|
2
|
-
import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
|
|
3
|
-
import { tmpdir } from 'node:os'
|
|
4
|
-
import { join } from 'node:path'
|
|
5
|
-
|
|
6
|
-
const cliRoot = join(import.meta.dir, '../../..')
|
|
7
|
-
|
|
8
|
-
let tmp: string
|
|
9
|
-
|
|
10
|
-
beforeEach(async () => {
|
|
11
|
-
tmp = await mkdtemp(join(tmpdir(), 'astrale-auth-login-'))
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
afterEach(async () => {
|
|
15
|
-
await rm(tmp, { recursive: true, force: true })
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
describe('auth login command', () => {
|
|
19
|
-
test('rejects requested audience when provider mints a different access-token aud', async () => {
|
|
20
|
-
const server = oauthServer({
|
|
21
|
-
accessToken: unsignedJwt({
|
|
22
|
-
iss: 'http://127.0.0.1',
|
|
23
|
-
sub: 'user_123',
|
|
24
|
-
aud: 'unknown/api',
|
|
25
|
-
exp: 1893456000,
|
|
26
|
-
}),
|
|
27
|
-
})
|
|
28
|
-
try {
|
|
29
|
-
await writeIdpConfig(server.url)
|
|
30
|
-
|
|
31
|
-
const result = await runAuthLogin(
|
|
32
|
-
'--idp',
|
|
33
|
-
'test',
|
|
34
|
-
'--name',
|
|
35
|
-
'alice',
|
|
36
|
-
'--client-credentials',
|
|
37
|
-
'--client-secret-env',
|
|
38
|
-
'TEST_CLIENT_SECRET',
|
|
39
|
-
'--audience',
|
|
40
|
-
'https://kernel.example.com',
|
|
41
|
-
'--raw',
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
expect(result.exitCode).toBe(1)
|
|
45
|
-
expect(result.stderr).toContain(
|
|
46
|
-
'IdP response access_token was not minted for requested audience https://kernel.example.com',
|
|
47
|
-
)
|
|
48
|
-
expect(
|
|
49
|
-
await readFile(join(tmp, 'idp-sessions', 'alice.json'), 'utf-8').catch(() => null),
|
|
50
|
-
).toBeNull()
|
|
51
|
-
} finally {
|
|
52
|
-
await server.stop()
|
|
53
|
-
}
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
test('stores the session when provider mints the requested access-token aud', async () => {
|
|
57
|
-
const server = oauthServer({
|
|
58
|
-
accessToken: unsignedJwt({
|
|
59
|
-
iss: 'http://127.0.0.1',
|
|
60
|
-
sub: 'user_123',
|
|
61
|
-
aud: 'https://kernel.example.com',
|
|
62
|
-
exp: 1893456000,
|
|
63
|
-
}),
|
|
64
|
-
})
|
|
65
|
-
try {
|
|
66
|
-
await writeIdpConfig(server.url)
|
|
67
|
-
|
|
68
|
-
const result = await runAuthLogin(
|
|
69
|
-
'--idp',
|
|
70
|
-
'test',
|
|
71
|
-
'--name',
|
|
72
|
-
'alice',
|
|
73
|
-
'--client-credentials',
|
|
74
|
-
'--client-secret-env',
|
|
75
|
-
'TEST_CLIENT_SECRET',
|
|
76
|
-
'--audience',
|
|
77
|
-
'https://kernel.example.com',
|
|
78
|
-
'--raw',
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
expect(result.exitCode).toBe(0)
|
|
82
|
-
const session = JSON.parse(await readFile(join(tmp, 'idp-sessions', 'alice.json'), 'utf-8'))
|
|
83
|
-
expect(session.audience).toBe('https://kernel.example.com')
|
|
84
|
-
expect(session.clientId).toBe('client_123')
|
|
85
|
-
expect(session.subject).toBe('user_123')
|
|
86
|
-
} finally {
|
|
87
|
-
await server.stop()
|
|
88
|
-
}
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
test('persists an explicit client id and reuses it for a named login', async () => {
|
|
92
|
-
const server = oauthServer({
|
|
93
|
-
accessToken: unsignedJwt({
|
|
94
|
-
iss: 'http://127.0.0.1',
|
|
95
|
-
sub: 'user_123',
|
|
96
|
-
exp: 1893456000,
|
|
97
|
-
}),
|
|
98
|
-
})
|
|
99
|
-
try {
|
|
100
|
-
await writeIdpConfig(server.url)
|
|
101
|
-
|
|
102
|
-
const explicit = await runAuthLogin(
|
|
103
|
-
'--idp',
|
|
104
|
-
'test',
|
|
105
|
-
'--name',
|
|
106
|
-
'alice',
|
|
107
|
-
'--client-id',
|
|
108
|
-
'client_override',
|
|
109
|
-
'--client-credentials',
|
|
110
|
-
'--client-secret-env',
|
|
111
|
-
'TEST_CLIENT_SECRET',
|
|
112
|
-
'--raw',
|
|
113
|
-
)
|
|
114
|
-
const reused = await runAuthLogin(
|
|
115
|
-
'--idp',
|
|
116
|
-
'test',
|
|
117
|
-
'--name',
|
|
118
|
-
'alice',
|
|
119
|
-
'--client-credentials',
|
|
120
|
-
'--client-secret-env',
|
|
121
|
-
'TEST_CLIENT_SECRET',
|
|
122
|
-
'--raw',
|
|
123
|
-
)
|
|
124
|
-
|
|
125
|
-
expect(explicit.exitCode).toBe(0)
|
|
126
|
-
expect(reused.exitCode).toBe(0)
|
|
127
|
-
expect(server.clientIds()).toEqual(['client_override', 'client_override'])
|
|
128
|
-
const session = JSON.parse(await readFile(join(tmp, 'idp-sessions', 'alice.json'), 'utf-8'))
|
|
129
|
-
expect(session.clientId).toBe('client_override')
|
|
130
|
-
} finally {
|
|
131
|
-
await server.stop()
|
|
132
|
-
}
|
|
133
|
-
})
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
async function writeIdpConfig(baseUrl: string): Promise<void> {
|
|
137
|
-
await mkdir(join(tmp, 'idps', 'test'), { recursive: true })
|
|
138
|
-
await writeFile(
|
|
139
|
-
join(tmp, 'idps', 'index.json'),
|
|
140
|
-
JSON.stringify(
|
|
141
|
-
{
|
|
142
|
-
idps: {
|
|
143
|
-
test: {
|
|
144
|
-
issuer: baseUrl,
|
|
145
|
-
createdAt: '2026-01-01T00:00:00.000Z',
|
|
146
|
-
updatedAt: '2026-01-01T00:00:00.000Z',
|
|
147
|
-
},
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
null,
|
|
151
|
-
2,
|
|
152
|
-
) + '\n',
|
|
153
|
-
)
|
|
154
|
-
await writeFile(
|
|
155
|
-
join(tmp, 'idps', 'test', 'metadata.json'),
|
|
156
|
-
JSON.stringify(
|
|
157
|
-
{
|
|
158
|
-
issuer: baseUrl,
|
|
159
|
-
token_endpoint: `${baseUrl}/token`,
|
|
160
|
-
jwks_uri: `${baseUrl}/jwks`,
|
|
161
|
-
},
|
|
162
|
-
null,
|
|
163
|
-
2,
|
|
164
|
-
) + '\n',
|
|
165
|
-
)
|
|
166
|
-
await writeFile(
|
|
167
|
-
join(tmp, 'idps', 'test', 'client.json'),
|
|
168
|
-
JSON.stringify(
|
|
169
|
-
{
|
|
170
|
-
client_id: 'client_123',
|
|
171
|
-
client_secret_env: 'TEST_CLIENT_SECRET',
|
|
172
|
-
},
|
|
173
|
-
null,
|
|
174
|
-
2,
|
|
175
|
-
) + '\n',
|
|
176
|
-
)
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
function oauthServer(args: { accessToken: string }): {
|
|
180
|
-
url: string
|
|
181
|
-
clientIds: () => Array<string | null>
|
|
182
|
-
stop: () => Promise<void>
|
|
183
|
-
} {
|
|
184
|
-
const clientIds: Array<string | null> = []
|
|
185
|
-
const server = Bun.serve({
|
|
186
|
-
port: 0,
|
|
187
|
-
fetch: async (request) => {
|
|
188
|
-
const url = new URL(request.url)
|
|
189
|
-
if (url.pathname !== '/token') return new Response('not found', { status: 404 })
|
|
190
|
-
const form = new URLSearchParams(await request.text())
|
|
191
|
-
clientIds.push(form.get('client_id'))
|
|
192
|
-
return Response.json({
|
|
193
|
-
access_token: args.accessToken,
|
|
194
|
-
token_type: 'Bearer',
|
|
195
|
-
expires_in: 3600,
|
|
196
|
-
})
|
|
197
|
-
},
|
|
198
|
-
})
|
|
199
|
-
return {
|
|
200
|
-
url: `http://${server.hostname}:${server.port}`,
|
|
201
|
-
clientIds: () => clientIds,
|
|
202
|
-
stop: () => server.stop(true),
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
async function runAuthLogin(...args: string[]): Promise<{
|
|
207
|
-
exitCode: number
|
|
208
|
-
stdout: string
|
|
209
|
-
stderr: string
|
|
210
|
-
}> {
|
|
211
|
-
const proc = Bun.spawn({
|
|
212
|
-
cmd: ['bun', join(cliRoot, 'bin/astrale.ts'), 'auth', 'login', ...args],
|
|
213
|
-
env: { ...process.env, ASTRALE_HOME: tmp, TEST_CLIENT_SECRET: 'secret_123' },
|
|
214
|
-
stdout: 'pipe',
|
|
215
|
-
stderr: 'pipe',
|
|
216
|
-
})
|
|
217
|
-
const [stdout, stderr, exitCode] = await Promise.all([
|
|
218
|
-
new Response(proc.stdout).text(),
|
|
219
|
-
new Response(proc.stderr).text(),
|
|
220
|
-
proc.exited,
|
|
221
|
-
])
|
|
222
|
-
return { exitCode, stdout, stderr }
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function unsignedJwt(payload: Record<string, unknown>): string {
|
|
226
|
-
return [base64url({ alg: 'none', typ: 'JWT' }), base64url(payload), ''].join('.')
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
function base64url(value: Record<string, unknown>): string {
|
|
230
|
-
return Buffer.from(JSON.stringify(value)).toString('base64url')
|
|
231
|
-
}
|