@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,404 +0,0 @@
|
|
|
1
|
-
import type { Fetch } from '@astrale-os/sdk/client'
|
|
2
|
-
|
|
3
|
-
import { issuer } from '@astrale-os/sdk/auth'
|
|
4
|
-
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
|
|
5
|
-
import { mkdtemp, rm } from 'node:fs/promises'
|
|
6
|
-
import { tmpdir } from 'node:os'
|
|
7
|
-
import { join } from 'node:path'
|
|
8
|
-
|
|
9
|
-
import { ExchangeCredentialCache } from '../../state/exchange-credentials'
|
|
10
|
-
import { createExchangeCredentialResolver } from '../exchange'
|
|
11
|
-
|
|
12
|
-
const KERNEL = issuer.accept('https://kernel.example')
|
|
13
|
-
const DOMAIN = issuer.accept('https://admin.example')
|
|
14
|
-
const TARGET = { url: `${KERNEL}/api`, kernelIssuer: KERNEL, domainIssuer: DOMAIN }
|
|
15
|
-
const INVOCATION = `${KERNEL}/invoke`
|
|
16
|
-
const EXPIRES_AT = Math.floor(Date.now() / 1_000) + 500
|
|
17
|
-
const SOURCE_EXPIRES_AT = Math.floor(Date.now() / 1_000) + 600
|
|
18
|
-
const SOURCE_TOKEN = sourceToken('user-1')
|
|
19
|
-
let directory: string
|
|
20
|
-
|
|
21
|
-
beforeEach(async () => {
|
|
22
|
-
directory = await mkdtemp(join(tmpdir(), 'astrale-exchange-'))
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
afterEach(async () => {
|
|
26
|
-
await rm(directory, { recursive: true, force: true })
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
describe('Domain token exchange', () => {
|
|
30
|
-
/** @evidence TEST-CLI-EXCHANGE-WHOAMI-DELEGATE-EXCHANGE-CACHE */
|
|
31
|
-
test('runs the exact User to Kernel to Domain journey once and reuses it before whoami', async () => {
|
|
32
|
-
const observed: Array<{
|
|
33
|
-
url: string
|
|
34
|
-
init: RequestInit | undefined
|
|
35
|
-
body?: Record<string, any>
|
|
36
|
-
}> = []
|
|
37
|
-
const exchanged = token(DOMAIN, KERNEL, 'user-1', EXPIRES_AT)
|
|
38
|
-
const fetch: Fetch = async (input, init) => {
|
|
39
|
-
const url = String(input)
|
|
40
|
-
if (url === INVOCATION) {
|
|
41
|
-
const body = JSON.parse(await new Response(init?.body).text()) as Record<string, any>
|
|
42
|
-
observed.push({ url, init, body })
|
|
43
|
-
const index = observed.filter((entry) => entry.url === INVOCATION).length
|
|
44
|
-
return invocationResponse(
|
|
45
|
-
body.requestId,
|
|
46
|
-
index === 1
|
|
47
|
-
? { id: 'user-1' }
|
|
48
|
-
: index === 2
|
|
49
|
-
? 'kernel-destination-envelope'
|
|
50
|
-
: { id: 'user-1' },
|
|
51
|
-
new Headers(init?.headers).get('accept')!,
|
|
52
|
-
)
|
|
53
|
-
}
|
|
54
|
-
observed.push({ url, init })
|
|
55
|
-
if (url.endsWith('/.well-known/openid-configuration')) {
|
|
56
|
-
return jsonResponse(configuration(true))
|
|
57
|
-
}
|
|
58
|
-
if (url.endsWith('/.well-known/astrale/token')) {
|
|
59
|
-
expect(init?.body).toBeUndefined()
|
|
60
|
-
expect(new Headers(init?.headers).get('authorization')).toBe(
|
|
61
|
-
'Bearer kernel-destination-envelope',
|
|
62
|
-
)
|
|
63
|
-
return jsonResponse(
|
|
64
|
-
{ token: exchanged, expiresAt: EXPIRES_AT },
|
|
65
|
-
200,
|
|
66
|
-
'application/vnd.astrale+json',
|
|
67
|
-
)
|
|
68
|
-
}
|
|
69
|
-
throw new Error(`unexpected URL ${url}`)
|
|
70
|
-
}
|
|
71
|
-
const sourceAudiences: string[] = []
|
|
72
|
-
const resolver = createExchangeCredentialResolver(
|
|
73
|
-
TARGET,
|
|
74
|
-
{
|
|
75
|
-
async resolve(audience) {
|
|
76
|
-
sourceAudiences.push(audience)
|
|
77
|
-
return SOURCE_TOKEN
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
fetch,
|
|
81
|
-
5_000,
|
|
82
|
-
new ExchangeCredentialCache(join(directory, 'credentials.json')),
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
expect(await resolver.resolve(KERNEL, new AbortController().signal)).toBe(exchanged)
|
|
86
|
-
await expect(resolver.resolve(KERNEL, new AbortController().signal)).resolves.toBe(exchanged)
|
|
87
|
-
|
|
88
|
-
const kernelRequests = observed.filter((entry) => entry.url === INVOCATION)
|
|
89
|
-
expect(kernelRequests).toHaveLength(2)
|
|
90
|
-
expect(kernelRequests[0]!.body).toMatchObject({
|
|
91
|
-
credential: SOURCE_TOKEN,
|
|
92
|
-
call: { input: {} },
|
|
93
|
-
})
|
|
94
|
-
expect(kernelRequests[1]!.body).toMatchObject({
|
|
95
|
-
credential: SOURCE_TOKEN,
|
|
96
|
-
call: {
|
|
97
|
-
input: {
|
|
98
|
-
audience: DOMAIN,
|
|
99
|
-
attenuation: { kind: 'identity', self: true },
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
})
|
|
103
|
-
const delegatedTtl = kernelRequests[1]!.body!.call.input.ttlSeconds
|
|
104
|
-
expect(delegatedTtl).toBe(75)
|
|
105
|
-
expect(sourceAudiences).toEqual([KERNEL, KERNEL])
|
|
106
|
-
expect(
|
|
107
|
-
observed.filter((entry) => entry.url.endsWith('/.well-known/astrale/token')),
|
|
108
|
-
).toHaveLength(1)
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
test('rejects a source credential without a stable cache identity before network I/O', async () => {
|
|
112
|
-
let fetches = 0
|
|
113
|
-
const resolver = createExchangeCredentialResolver(
|
|
114
|
-
TARGET,
|
|
115
|
-
{ resolve: async () => sourceToken(undefined) },
|
|
116
|
-
async () => {
|
|
117
|
-
fetches += 1
|
|
118
|
-
throw new Error('network must remain untouched')
|
|
119
|
-
},
|
|
120
|
-
5_000,
|
|
121
|
-
new ExchangeCredentialCache(join(directory, 'credentials.json')),
|
|
122
|
-
)
|
|
123
|
-
await expect(resolver.resolve(KERNEL, new AbortController().signal)).rejects.toMatchObject({
|
|
124
|
-
code: 'TOKEN_EXCHANGE_SOURCE_INVALID',
|
|
125
|
-
})
|
|
126
|
-
expect(fetches).toBe(0)
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
/** @evidence TEST-CLI-EXCHANGE-NO-LEGACY-FALLBACK */
|
|
130
|
-
test('fails closed when issuer discovery does not advertise exchange', async () => {
|
|
131
|
-
const fetch: Fetch = async (input, init) => {
|
|
132
|
-
const url = String(input)
|
|
133
|
-
if (url === INVOCATION) {
|
|
134
|
-
const body = JSON.parse(await new Response(init?.body).text()) as Record<string, any>
|
|
135
|
-
return invocationResponse(
|
|
136
|
-
body.requestId,
|
|
137
|
-
body.call.input && Object.keys(body.call.input).length === 0
|
|
138
|
-
? { id: 'user-1' }
|
|
139
|
-
: 'kernel-destination-envelope',
|
|
140
|
-
new Headers(init?.headers).get('accept')!,
|
|
141
|
-
)
|
|
142
|
-
}
|
|
143
|
-
if (url.endsWith('/.well-known/openid-configuration'))
|
|
144
|
-
return jsonResponse(configuration(false))
|
|
145
|
-
throw new Error('exchange endpoint must not be called')
|
|
146
|
-
}
|
|
147
|
-
const resolver = createExchangeCredentialResolver(
|
|
148
|
-
TARGET,
|
|
149
|
-
{ resolve: async () => SOURCE_TOKEN },
|
|
150
|
-
fetch,
|
|
151
|
-
5_000,
|
|
152
|
-
new ExchangeCredentialCache(join(directory, 'credentials.json')),
|
|
153
|
-
)
|
|
154
|
-
await expect(resolver.resolve(KERNEL, new AbortController().signal)).rejects.toMatchObject({
|
|
155
|
-
code: 'TOKEN_EXCHANGE_UNSUPPORTED',
|
|
156
|
-
})
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
test('rejects an exchanged token bound to another Kernel', async () => {
|
|
160
|
-
const wrong = token(DOMAIN, issuer.accept('https://other-kernel.example'), 'user-1', EXPIRES_AT)
|
|
161
|
-
const fetch = exchangeFetch(wrong)
|
|
162
|
-
const resolver = createExchangeCredentialResolver(
|
|
163
|
-
TARGET,
|
|
164
|
-
{ resolve: async () => SOURCE_TOKEN },
|
|
165
|
-
fetch,
|
|
166
|
-
5_000,
|
|
167
|
-
new ExchangeCredentialCache(join(directory, 'credentials.json')),
|
|
168
|
-
)
|
|
169
|
-
await expect(resolver.resolve(KERNEL, new AbortController().signal)).rejects.toMatchObject({
|
|
170
|
-
code: 'TOKEN_EXCHANGE_PROTOCOL_ERROR',
|
|
171
|
-
})
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
test('requests and retains a carrier that covers a supported long command deadline', async () => {
|
|
175
|
-
const expiresAt = Math.floor(Date.now() / 1_000) + 250
|
|
176
|
-
const exchanged = token(DOMAIN, KERNEL, 'user-1', expiresAt)
|
|
177
|
-
const observed: Record<string, any>[] = []
|
|
178
|
-
const base = exchangeFetch(exchanged, { expiresAt })
|
|
179
|
-
const fetch: Fetch = async (input, init) => {
|
|
180
|
-
if (String(input) === INVOCATION) {
|
|
181
|
-
observed.push(JSON.parse(await new Response(init?.body).text()))
|
|
182
|
-
}
|
|
183
|
-
return base(input, init)
|
|
184
|
-
}
|
|
185
|
-
const resolver = createExchangeCredentialResolver(
|
|
186
|
-
TARGET,
|
|
187
|
-
{ resolve: async () => sourceToken('user-1', expiresAt + 50) },
|
|
188
|
-
fetch,
|
|
189
|
-
180_000,
|
|
190
|
-
new ExchangeCredentialCache(join(directory, 'long-credential.json')),
|
|
191
|
-
)
|
|
192
|
-
|
|
193
|
-
await expect(resolver.resolve(KERNEL, new AbortController().signal)).resolves.toBe(exchanged)
|
|
194
|
-
expect(observed[1]!.call.input.ttlSeconds).toBe(200)
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
/** @evidence TEST-CLI-EXCHANGE-REJECTS-INSUFFICIENT-LIFETIME */
|
|
198
|
-
test('rejects a too-short Domain exchange credential before destination dispatch', async () => {
|
|
199
|
-
const expiresAt = Math.floor(Date.now() / 1_000) + 150
|
|
200
|
-
const exchanged = token(DOMAIN, KERNEL, 'user-1', expiresAt)
|
|
201
|
-
const resolver = createExchangeCredentialResolver(
|
|
202
|
-
TARGET,
|
|
203
|
-
{ resolve: async () => sourceToken('user-1', expiresAt + 150) },
|
|
204
|
-
exchangeFetch(exchanged, { expiresAt }),
|
|
205
|
-
180_000,
|
|
206
|
-
new ExchangeCredentialCache(join(directory, 'short-credential.json')),
|
|
207
|
-
)
|
|
208
|
-
|
|
209
|
-
await expect(resolver.resolve(KERNEL, new AbortController().signal)).rejects.toMatchObject({
|
|
210
|
-
code: 'TOKEN_EXCHANGE_LIFETIME_INSUFFICIENT',
|
|
211
|
-
})
|
|
212
|
-
})
|
|
213
|
-
|
|
214
|
-
test('rejects a long outer Domain token whose carried Kernel proof is too short', async () => {
|
|
215
|
-
const outerExpiresAt = Math.floor(Date.now() / 1_000) + 250
|
|
216
|
-
const proofExpiresAt = Math.floor(Date.now() / 1_000) + 150
|
|
217
|
-
const exchanged = token(DOMAIN, KERNEL, 'user-1', outerExpiresAt, proofExpiresAt)
|
|
218
|
-
const resolver = createExchangeCredentialResolver(
|
|
219
|
-
TARGET,
|
|
220
|
-
{ resolve: async () => sourceToken('user-1', outerExpiresAt + 50) },
|
|
221
|
-
exchangeFetch(exchanged, { expiresAt: outerExpiresAt }),
|
|
222
|
-
180_000,
|
|
223
|
-
new ExchangeCredentialCache(join(directory, 'short-proof.json')),
|
|
224
|
-
)
|
|
225
|
-
|
|
226
|
-
await expect(resolver.resolve(KERNEL, new AbortController().signal)).rejects.toMatchObject({
|
|
227
|
-
code: 'TOKEN_EXCHANGE_LIFETIME_INSUFFICIENT',
|
|
228
|
-
})
|
|
229
|
-
})
|
|
230
|
-
|
|
231
|
-
test('rejects the real 300-second Domain ceiling for a 600-second command before destination dispatch', async () => {
|
|
232
|
-
const expiresAt = Math.floor(Date.now() / 1_000) + 300
|
|
233
|
-
const exchanged = token(DOMAIN, KERNEL, 'user-1', expiresAt)
|
|
234
|
-
const observed: string[] = []
|
|
235
|
-
const base = exchangeFetch(exchanged, { expiresAt })
|
|
236
|
-
const fetch: Fetch = async (input, init) => {
|
|
237
|
-
observed.push(String(input))
|
|
238
|
-
return base(input, init)
|
|
239
|
-
}
|
|
240
|
-
const resolver = createExchangeCredentialResolver(
|
|
241
|
-
TARGET,
|
|
242
|
-
{ resolve: async () => sourceToken('user-1', expiresAt + 700) },
|
|
243
|
-
fetch,
|
|
244
|
-
600_000,
|
|
245
|
-
new ExchangeCredentialCache(join(directory, 'domain-ceiling.json')),
|
|
246
|
-
)
|
|
247
|
-
|
|
248
|
-
await expect(resolver.resolve(KERNEL, new AbortController().signal)).rejects.toMatchObject({
|
|
249
|
-
code: 'TOKEN_EXCHANGE_LIFETIME_INSUFFICIENT',
|
|
250
|
-
})
|
|
251
|
-
expect(observed.filter((url) => url === INVOCATION)).toHaveLength(2)
|
|
252
|
-
expect(observed.filter((url) => url.endsWith('/.well-known/astrale/token'))).toHaveLength(1)
|
|
253
|
-
})
|
|
254
|
-
|
|
255
|
-
test('rejects success responses without no-store or with malformed fields', async () => {
|
|
256
|
-
const exchanged = token(DOMAIN, KERNEL, 'user-1', EXPIRES_AT)
|
|
257
|
-
const cache = () => new ExchangeCredentialCache(join(directory, crypto.randomUUID()))
|
|
258
|
-
const resolver = (fetch: Fetch) =>
|
|
259
|
-
createExchangeCredentialResolver(
|
|
260
|
-
TARGET,
|
|
261
|
-
{ resolve: async () => SOURCE_TOKEN },
|
|
262
|
-
fetch,
|
|
263
|
-
5_000,
|
|
264
|
-
cache(),
|
|
265
|
-
)
|
|
266
|
-
|
|
267
|
-
await expect(
|
|
268
|
-
resolver(exchangeFetch(exchanged, { cacheControl: false })).resolve(
|
|
269
|
-
KERNEL,
|
|
270
|
-
new AbortController().signal,
|
|
271
|
-
),
|
|
272
|
-
).rejects.toMatchObject({
|
|
273
|
-
code: 'TOKEN_EXCHANGE_PROTOCOL_ERROR',
|
|
274
|
-
message: 'Token exchange response is missing Cache-Control: no-store.',
|
|
275
|
-
})
|
|
276
|
-
await expect(
|
|
277
|
-
resolver(exchangeFetch(exchanged, { body: { token: 7, expiresAt: 'soon' } })).resolve(
|
|
278
|
-
KERNEL,
|
|
279
|
-
new AbortController().signal,
|
|
280
|
-
),
|
|
281
|
-
).rejects.toMatchObject({
|
|
282
|
-
code: 'TOKEN_EXCHANGE_PROTOCOL_ERROR',
|
|
283
|
-
message: 'Token exchange returned an invalid success response.',
|
|
284
|
-
})
|
|
285
|
-
})
|
|
286
|
-
|
|
287
|
-
test('normalizes native issuer Fetch failures without exposing their message', async () => {
|
|
288
|
-
const native = new AggregateError([new Error('private DNS state')], '')
|
|
289
|
-
const resolver = createExchangeCredentialResolver(
|
|
290
|
-
TARGET,
|
|
291
|
-
{ resolve: async () => SOURCE_TOKEN },
|
|
292
|
-
async (input, init) => {
|
|
293
|
-
if (String(input) === INVOCATION) {
|
|
294
|
-
const body = JSON.parse(await new Response(init?.body).text()) as Record<string, any>
|
|
295
|
-
return invocationResponse(
|
|
296
|
-
body.requestId,
|
|
297
|
-
body.call.input && Object.keys(body.call.input).length === 0
|
|
298
|
-
? { id: 'user-1' }
|
|
299
|
-
: 'kernel-destination-envelope',
|
|
300
|
-
new Headers(init?.headers).get('accept')!,
|
|
301
|
-
)
|
|
302
|
-
}
|
|
303
|
-
throw native
|
|
304
|
-
},
|
|
305
|
-
5_000,
|
|
306
|
-
new ExchangeCredentialCache(join(directory, 'native-failure.json')),
|
|
307
|
-
)
|
|
308
|
-
|
|
309
|
-
await expect(resolver.resolve(KERNEL, new AbortController().signal)).rejects.toMatchObject({
|
|
310
|
-
code: 'TOKEN_EXCHANGE_UNAVAILABLE',
|
|
311
|
-
message: 'Domain issuer discovery could not be reached.',
|
|
312
|
-
cause: native,
|
|
313
|
-
})
|
|
314
|
-
})
|
|
315
|
-
})
|
|
316
|
-
|
|
317
|
-
function exchangeFetch(
|
|
318
|
-
exchanged: string,
|
|
319
|
-
options: {
|
|
320
|
-
readonly body?: unknown
|
|
321
|
-
readonly cacheControl?: boolean
|
|
322
|
-
readonly expiresAt?: number
|
|
323
|
-
} = {},
|
|
324
|
-
): Fetch {
|
|
325
|
-
return async (input, init) => {
|
|
326
|
-
const url = String(input)
|
|
327
|
-
if (url === INVOCATION) {
|
|
328
|
-
const body = JSON.parse(await new Response(init?.body).text()) as Record<string, any>
|
|
329
|
-
return invocationResponse(
|
|
330
|
-
body.requestId,
|
|
331
|
-
body.call.input && Object.keys(body.call.input).length === 0
|
|
332
|
-
? { id: 'user-1' }
|
|
333
|
-
: 'kernel-destination-envelope',
|
|
334
|
-
new Headers(init?.headers).get('accept')!,
|
|
335
|
-
)
|
|
336
|
-
}
|
|
337
|
-
if (url.endsWith('/.well-known/openid-configuration')) return jsonResponse(configuration(true))
|
|
338
|
-
const response = new Response(
|
|
339
|
-
JSON.stringify(
|
|
340
|
-
options.body ?? { token: exchanged, expiresAt: options.expiresAt ?? EXPIRES_AT },
|
|
341
|
-
),
|
|
342
|
-
{
|
|
343
|
-
status: 200,
|
|
344
|
-
headers: {
|
|
345
|
-
'content-type': 'application/vnd.astrale+json',
|
|
346
|
-
...(options.cacheControl === false ? {} : { 'cache-control': 'no-store' }),
|
|
347
|
-
},
|
|
348
|
-
},
|
|
349
|
-
)
|
|
350
|
-
return response
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
function configuration(enabled: boolean) {
|
|
355
|
-
return {
|
|
356
|
-
issuer: DOMAIN,
|
|
357
|
-
jwks_uri: `${DOMAIN}/.well-known/jwks.json`,
|
|
358
|
-
subject_types_supported: ['public'],
|
|
359
|
-
id_token_signing_alg_values_supported: ['EdDSA'],
|
|
360
|
-
...(enabled ? { token_exchange_endpoint: `${DOMAIN}/.well-known/astrale/token` } : {}),
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
function invocationResponse(requestId: unknown, result: unknown, contentType: string): Response {
|
|
365
|
-
const invocation = { source: KERNEL, id: `exchange-${String(requestId)}` }
|
|
366
|
-
return new Response(JSON.stringify({ requestId, invocation, result }), {
|
|
367
|
-
headers: { 'content-type': contentType, 'cache-control': 'no-store' },
|
|
368
|
-
})
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
function jsonResponse(value: unknown, status = 200, contentType = 'application/json'): Response {
|
|
372
|
-
return new Response(JSON.stringify(value), {
|
|
373
|
-
status,
|
|
374
|
-
headers: { 'content-type': contentType, 'cache-control': 'no-store' },
|
|
375
|
-
})
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
function token(iss: string, aud: string, user: string, exp: number, proofExp = exp): string {
|
|
379
|
-
const encode = (value: unknown) => Buffer.from(JSON.stringify(value)).toString('base64url')
|
|
380
|
-
const proof = `${encode({ alg: 'EdDSA', typ: 'JWT' })}.${encode({
|
|
381
|
-
iss: aud,
|
|
382
|
-
sub: user,
|
|
383
|
-
aud,
|
|
384
|
-
exp: proofExp,
|
|
385
|
-
delegation: { v: 1, expr: { kind: 'identity', id: user } },
|
|
386
|
-
})}.signature`
|
|
387
|
-
return `${encode({ alg: 'EdDSA', typ: 'JWT' })}.${encode({
|
|
388
|
-
iss,
|
|
389
|
-
sub: 'admin-domain',
|
|
390
|
-
aud,
|
|
391
|
-
exp,
|
|
392
|
-
grant: { v: 1, expr: { kind: 'identity', credential: proof } },
|
|
393
|
-
})}.signature`
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
function sourceToken(subject: string | undefined, expiresAt = SOURCE_EXPIRES_AT): string {
|
|
397
|
-
const encode = (value: unknown) => Buffer.from(JSON.stringify(value)).toString('base64url')
|
|
398
|
-
return `${encode({ alg: 'EdDSA', typ: 'JWT' })}.${encode({
|
|
399
|
-
iss: 'https://workos.example',
|
|
400
|
-
...(subject === undefined ? {} : { sub: subject }),
|
|
401
|
-
aud: KERNEL,
|
|
402
|
-
exp: expiresAt,
|
|
403
|
-
})}.signature`
|
|
404
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { ClientError, TransportError } from '@astrale-os/sdk/client'
|
|
2
|
-
|
|
3
|
-
import type { TransportDiagnosticContext } from '../failure/model'
|
|
4
|
-
|
|
5
|
-
type CompatibleTransportPhase = TransportError['phase'] | 'unknown'
|
|
6
|
-
|
|
7
|
-
export function transportFailure(
|
|
8
|
-
message: string,
|
|
9
|
-
phase: CompatibleTransportPhase,
|
|
10
|
-
context: TransportDiagnosticContext,
|
|
11
|
-
): TransportError {
|
|
12
|
-
const error = new Error(message) as TransportError & {
|
|
13
|
-
context: TransportDiagnosticContext
|
|
14
|
-
}
|
|
15
|
-
Object.setPrototypeOf(error, TransportError.prototype)
|
|
16
|
-
Object.assign(error, { name: 'TransportError', phase, context })
|
|
17
|
-
return error
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function legacyTransportFailure(
|
|
21
|
-
message: string,
|
|
22
|
-
phase: CompatibleTransportPhase,
|
|
23
|
-
delivery: 'not-sent' | 'unknown',
|
|
24
|
-
): TransportError {
|
|
25
|
-
const error = new Error(message) as TransportError & { delivery: typeof delivery }
|
|
26
|
-
Object.setPrototypeOf(error, TransportError.prototype)
|
|
27
|
-
Object.assign(error, { name: 'TransportError', phase, delivery })
|
|
28
|
-
return error
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function sessionFailure(
|
|
32
|
-
message: string,
|
|
33
|
-
failure: 'cancelled' | 'closed' | 'timeout',
|
|
34
|
-
): ClientError {
|
|
35
|
-
const error = new Error(message) as ClientError & { failure: typeof failure }
|
|
36
|
-
Object.setPrototypeOf(error, ClientError.prototype)
|
|
37
|
-
Object.assign(error, { name: 'SessionError', failure })
|
|
38
|
-
return error
|
|
39
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { expect, test } from 'bun:test'
|
|
2
|
-
|
|
3
|
-
import { formatKernelError } from '../errors'
|
|
4
|
-
import { legacyTransportFailure, sessionFailure, transportFailure } from './failure-fixtures'
|
|
5
|
-
|
|
6
|
-
/** @evidence TEST-CLI-CONNECTION-FAILURE-SAFETY */
|
|
7
|
-
test('unknown and empty native failures never become ordinary diagnostics', async () => {
|
|
8
|
-
for (const failure of [new Error('private provider detail'), new Error(''), { secret: true }]) {
|
|
9
|
-
const output = await capture(() => formatKernelError(failure, true))
|
|
10
|
-
expect(JSON.parse(output)).toEqual({
|
|
11
|
-
error: 'UNEXPECTED_ERROR',
|
|
12
|
-
message: 'The CLI encountered an unexpected internal failure.',
|
|
13
|
-
})
|
|
14
|
-
expect(output).not.toContain('private provider detail')
|
|
15
|
-
}
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
test('Aggregate children are available only under explicit debug output', async () => {
|
|
19
|
-
const failure = new AggregateError([new Error('first private'), new Error('second private')], '')
|
|
20
|
-
const ordinary = await capture(() => formatKernelError(failure, true))
|
|
21
|
-
expect(ordinary).not.toContain('first private')
|
|
22
|
-
expect(ordinary).not.toContain('second private')
|
|
23
|
-
|
|
24
|
-
const debug = await capture(() => formatKernelError(failure, true, '', true))
|
|
25
|
-
expect(debug).toContain('aggregate: Error: first private')
|
|
26
|
-
expect(debug).toContain('aggregate: Error: second private')
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
test('Session and acquisition failures remain typed without unsafe recovery advice', async () => {
|
|
30
|
-
const session = await capture(() =>
|
|
31
|
-
formatKernelError(sessionFailure('Session operation timed out.', 'timeout'), true),
|
|
32
|
-
)
|
|
33
|
-
expect(JSON.parse(session)).toEqual({ error: 'TIMEOUT', message: 'Session operation timed out.' })
|
|
34
|
-
|
|
35
|
-
const acquisition = await capture(() =>
|
|
36
|
-
formatKernelError(
|
|
37
|
-
transportFailure('Publication failed.', 'unknown', {
|
|
38
|
-
kind: 'acquisition',
|
|
39
|
-
resource: 'publication',
|
|
40
|
-
}),
|
|
41
|
-
true,
|
|
42
|
-
'',
|
|
43
|
-
false,
|
|
44
|
-
{ recovery: { operation: 'must-not-leak', retry: 'must-not-leak' } },
|
|
45
|
-
),
|
|
46
|
-
)
|
|
47
|
-
expect(JSON.parse(acquisition)).toMatchObject({
|
|
48
|
-
error: 'TRANSPORT_ERROR',
|
|
49
|
-
transport: { kind: 'acquisition', resource: 'publication' },
|
|
50
|
-
})
|
|
51
|
-
expect(acquisition).not.toContain('must-not-leak')
|
|
52
|
-
|
|
53
|
-
const legacy = await capture(() =>
|
|
54
|
-
formatKernelError(legacyTransportFailure('Legacy send failed.', 'send', 'not-sent'), true),
|
|
55
|
-
)
|
|
56
|
-
expect(JSON.parse(legacy)).toMatchObject({
|
|
57
|
-
error: 'TRANSPORT_ERROR',
|
|
58
|
-
transport: { kind: 'invocation', delivery: 'not-sent' },
|
|
59
|
-
})
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
async function capture(action: () => Promise<void>): Promise<string> {
|
|
63
|
-
const writes: string[] = []
|
|
64
|
-
const original = process.stderr.write
|
|
65
|
-
process.stderr.write = ((chunk: string | Uint8Array) => {
|
|
66
|
-
writes.push(typeof chunk === 'string' ? chunk : new TextDecoder().decode(chunk))
|
|
67
|
-
return true
|
|
68
|
-
}) as typeof process.stderr.write
|
|
69
|
-
try {
|
|
70
|
-
await action()
|
|
71
|
-
return writes.join('')
|
|
72
|
-
} finally {
|
|
73
|
-
process.stderr.write = original
|
|
74
|
-
}
|
|
75
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
-----BEGIN CERTIFICATE-----
|
|
2
|
-
MIIDJTCCAg2gAwIBAgIULD/vMZdJ/u94wRaoyRt5crvKLL0wDQYJKoZIhvcNAQEL
|
|
3
|
-
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI2MDgxMTE0MDUxNFoXDTM2MDgw
|
|
4
|
-
ODE0MDUxNFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
|
|
5
|
-
AAOCAQ8AMIIBCgKCAQEApheXGRylshfFubAJ1sBoecE9q+giTVJZlAKqXE+Cp/wn
|
|
6
|
-
CQv/uOMQtus6ikSjDmyk8/qiSRAGZYzmZjjt5ICttav7Kb0krdRAnOSB9zd4+hEP
|
|
7
|
-
jq7O5IcAlriey8KKZInugB7GD7HDVGKYPrJpJrOmfxXW0s1Vj55nehP3vn59obfH
|
|
8
|
-
EE4mJ50SV9k/VS5AZ3nJHQwKyGjIKvkHI9Ll0++Wu5/ny84TwYkgY8RYwMwfj2Z0
|
|
9
|
-
ltqGo7bsanwk3JFfrphBSYteAxcgF0Y//Vv557RnM2+zX7W6K1FD7s7Nen4/vx01
|
|
10
|
-
cEacj59lNTDANUNJNNj+cCpol4Ie7Krk0deq/Ih3KQIDAQABo28wbTAdBgNVHQ4E
|
|
11
|
-
FgQU7+UbkfznwiPgzxoBtkPHay+Ifu8wHwYDVR0jBBgwFoAU7+UbkfznwiPgzxoB
|
|
12
|
-
tkPHay+Ifu8wDwYDVR0TAQH/BAUwAwEB/zAaBgNVHREEEzARgglsb2NhbGhvc3SH
|
|
13
|
-
BH8AAAEwDQYJKoZIhvcNAQELBQADggEBAGsPr3yfMuVyCuPQMCaUAWY8Qulepl1V
|
|
14
|
-
NIvqyEAb94F1L8Mfh3UNPF9UljBGcI1RBL8e21iNF7vnR0WBF2SSTlf18/qcErVA
|
|
15
|
-
4A7AwlqIVUXjERN9wKesCS/w92CBswLxq/6KrnLahngoBW/tDJ/uzZLXvSdCnYG7
|
|
16
|
-
NMZMpIB0rLdT6GYr1KT/hUSKOKLqC5x0WtEAdoIOqCyYaZrxso4gIicPMWTS3Eho
|
|
17
|
-
9wzXiIHOme9rtlEPnDPVseuIw2ADRPQHAHXiIlyUcJwmt01mgAKPoMp3wCgTaj2H
|
|
18
|
-
NO7KMXAdJgGmmrCkP3dOWri81NlQVoOrbE432bAfKE7S+KehDYJpeAU=
|
|
19
|
-
-----END CERTIFICATE-----
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRQ21GNWNaSEtXeUY4VzUKc0FuV3dHaDV3VDJyNkNKTlVsbVVBcXBjVDRLbi9DY0pDLys0NHhDMjZ6cUtSS01PYktUeitxSkpFQVpsak9abQpPTzNrZ0syMXEvc3B2U1N0MUVDYzVJSDNOM2o2RVErT3JzN2tod0NXdUo3THdvcGtpZTZBSHNZUHNjTlVZcGcrCnNta21zNlovRmRiU3pWV1BubWQ2RS9lK2ZuMmh0OGNRVGlZbm5SSlgyVDlWTGtCbmVja2REQXJJYU1ncStRY2oKMHVYVDc1YTduK2ZMemhQQmlTQmp4RmpBekIrUFpuU1cyb2FqdHV4cWZDVGNrVit1bUVGSmkxNERGeUFYUmovOQpXL25udEdjemI3TmZ0Ym9yVVVQdXpzMTZmaisvSFRWd1JweVBuMlUxTU1BMVEwazAyUDV3S21pWGdoN3NxdVRSCjE2cjhpSGNwQWdNQkFBRUNnZ0VBRHZPRnJ3V0VwdXo3NkJUQU5mdzVDMmpKVCszRUZMaktob2ZjNVJWbE9oRDUKUkplM2ErSEkwZWFIN1FWenRpc3lpQ0h5Tk9pRDR1VlZvak1TdXlTWVBvZmVRcW9ib0toQUxyOWxNYWRsTlFHUApLSFYwKzE1cHY2ZWI1OVM1MTRZUkdhaHJoT01vSmJNQWFIaHYvY05qUkFKbnhhOGxPaG4wejZqM2ZzYnRNVDd3Ck11dFpVMm85RWRjc09iUHBnemlnZVFEbmw0NVlNbFVsLzY5b2lSR2w0NWw1a2xyaUtMdk9YQWcydWJXTFR0QWYKWVJjeW9mOEdySmFXL1F5ZmRGVVloRUUydVNqUHNyMkFLMVNsMlBDZ1FZNmRNOUZZaDVkckZSNDU1R0VDUm94MApoaFVZS1NQRFhVU1VESUNMcVZ2UTdlOEhTMlVvUXZiaUdRRndMZHp3d1FLQmdRRGJYUVBMNlA5UDRZQ2tUZFFtCnQ4TTNvSlNYbXZHd2JRcTd2WVU5K3ZSYkMyYWRHekljaWYyT1E5OFFsc0R3Yy9XQ2psT01GalJjdTk3NVBueGsKR0RTZXZFdHpjR0JidkwzS094VzJybHo0NnVKOGw2MTkyMkE0a3BUbTNHREdBNFFabE9UZ2tWSkZyWHR5WDVXaApBQ1FkY0twWURFSXRYZm5kUXV5dGZ4anNzUUtCZ1FEQjFQQ2x3bkZqOHFMa2RMZ2xlODczLzJsdC9taGZFcnA5CmNJYkxtdFY3allsZDlzZExJb3RUL2ZyOU9odjUvKzdIUFBGNmQrb3pBcUpQSnBmVjhnNUpWMWhON1pRVWY4eW8KSldTbTZyRWphL0hWRCtsVENBLy9neU1DcFRGTXRhU2wraFBhcVpRb2ZWRm1BRm9OWjFrR0oxdm9iaEhhVmlwSwpQTHFrVGFIditRS0JnUUNydmtFd3JuVGxwNW0rQ2FrbHZ3MjZTYURNcVdTOFNrTHpCY2lCNUM3WDhTOGZwYUV3Ck11RXZOdmczMXErc0VqMlBQN3N0bkZ6V2xjaFd2NU5JRXFOdis5L2V1NGJWakFuVGdUclkwZDY4aTdsUzdyWEkKS2E5RjI0MTB5ZW1DWGxKWWJQaGMwYW5tSDVMYzB2VWxIaVVvWDRNZWVFcC9sbW4vejF2WjRmNHpvUUtCZ0V3MQpVN1JvWWJxaFFFaEFWOUpzL2kvbFhPZGhPbG4rL0JHcnQyTy82YVdkUFdBVFVjSUp2K3Z6Rk1hUkhVVEt5bS9OClYwZ0djNjlBbnQ0dDEwN0h6N1FvUWxESlV3cElRUWZ2UThhWXliS2FrMGRvN1J5M004c0xIUzNDRTBNTXU4S0MKTTJJcWdGVDNDSlRwR0g3aW5rN2NGTGVxNXh3SCtyS2JjK3A3bDJySkFvR0JBSmIxVDRpZFZPdmFZRFlINE1pUwpmUUpGU29QaFZqaklURmU2aG5hNkN0akNHdXoySGNqdXpRMWVFcVhRbzVIYkxRaGdYQnpsM3pUZllYTDJMWGhWCk9WRDB3UmJ2MFAyUk5nNXpqUERQMU8vL2ZISDFkc1hFUzNCZ2t6M3czUnduZXhucXZIRTU5Vm5VQ01yUnFOREYKeXAwVkQzM1F6aWhuRFdScWxhVUxSTit4Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from 'bun:test'
|
|
2
|
-
|
|
3
|
-
import type { ConnectionContext } from '../session'
|
|
4
|
-
import type { AdminConnectionOptions } from '../target'
|
|
5
|
-
|
|
6
|
-
import { lookupManagedInstance } from '../session'
|
|
7
|
-
|
|
8
|
-
describe('implicit managed target owner discovery', () => {
|
|
9
|
-
test('keeps target credentials out of the admin inventory lookup', async () => {
|
|
10
|
-
const owned = {
|
|
11
|
-
id: 'owned-id',
|
|
12
|
-
slug: 'owned',
|
|
13
|
-
url: 'https://owned.eu.astrale.ai',
|
|
14
|
-
state: 'ready',
|
|
15
|
-
} as const
|
|
16
|
-
let capturedOptions: AdminConnectionOptions | undefined
|
|
17
|
-
const openAdmin = async <Value>(
|
|
18
|
-
options: AdminConnectionOptions,
|
|
19
|
-
action: (context: ConnectionContext) => Promise<Value>,
|
|
20
|
-
): Promise<Value> => {
|
|
21
|
-
capturedOptions = options
|
|
22
|
-
return action({} as ConnectionContext)
|
|
23
|
-
}
|
|
24
|
-
const connect = async () => ({ list: async () => [owned] }) as never
|
|
25
|
-
|
|
26
|
-
await lookupManagedInstance(
|
|
27
|
-
'owned',
|
|
28
|
-
{
|
|
29
|
-
as: 'target-identity',
|
|
30
|
-
creds: 'target-delegation',
|
|
31
|
-
timeout: '45000',
|
|
32
|
-
},
|
|
33
|
-
openAdmin,
|
|
34
|
-
connect,
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
expect(capturedOptions).toEqual({ timeout: '45000' })
|
|
38
|
-
})
|
|
39
|
-
})
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from 'bun:test'
|
|
2
|
-
|
|
3
|
-
import { functionInputIssues, queryInputRepair } from '../reasons'
|
|
4
|
-
|
|
5
|
-
describe('public reason presentation admission', () => {
|
|
6
|
-
/** @evidence TEST-CLI-CONNECTION-ADMITS-BOUNDED-REASONS */
|
|
7
|
-
test('admits bounded public callable issues and filters unsafe additions', () => {
|
|
8
|
-
expect(
|
|
9
|
-
functionInputIssues({
|
|
10
|
-
code: 'FUNCTION_INPUT_INVALID',
|
|
11
|
-
details: {
|
|
12
|
-
issues: [
|
|
13
|
-
{
|
|
14
|
-
code: 'VALUE_SCHEMA_INSTANCE_INVALID',
|
|
15
|
-
path: '/issuer',
|
|
16
|
-
message: 'Object is missing required property issuer.',
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
code: 'VALUE_SCHEMA_INSTANCE_INVALID',
|
|
20
|
-
path: '/slug',
|
|
21
|
-
message: 'Object is missing required property slug.',
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
code: 'VALUE_SCHEMA_INSTANCE_INVALID',
|
|
25
|
-
path: '/unsafe',
|
|
26
|
-
message: 'private\ndiagnostic',
|
|
27
|
-
},
|
|
28
|
-
],
|
|
29
|
-
},
|
|
30
|
-
}),
|
|
31
|
-
).toEqual([
|
|
32
|
-
{
|
|
33
|
-
code: 'VALUE_SCHEMA_INSTANCE_INVALID',
|
|
34
|
-
path: '/issuer',
|
|
35
|
-
message: 'Object is missing required property issuer.',
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
code: 'VALUE_SCHEMA_INSTANCE_INVALID',
|
|
39
|
-
path: '/slug',
|
|
40
|
-
message: 'Object is missing required property slug.',
|
|
41
|
-
},
|
|
42
|
-
])
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
test('admits exact Query repair variants and rejects unbounded additions', () => {
|
|
46
|
-
expect(
|
|
47
|
-
queryInputRepair({
|
|
48
|
-
code: 'QUERY_INPUT_INVALID',
|
|
49
|
-
details: {
|
|
50
|
-
phase: 'plan',
|
|
51
|
-
issue: 'QUERY_DEFINITION_NOT_EDGE',
|
|
52
|
-
path: '/steps/0/via/0',
|
|
53
|
-
},
|
|
54
|
-
}),
|
|
55
|
-
).toEqual({
|
|
56
|
-
phase: 'plan',
|
|
57
|
-
issue: 'QUERY_DEFINITION_NOT_EDGE',
|
|
58
|
-
path: '/steps/0/via/0',
|
|
59
|
-
})
|
|
60
|
-
expect(
|
|
61
|
-
queryInputRepair({
|
|
62
|
-
code: 'QUERY_INPUT_INVALID',
|
|
63
|
-
details: { phase: 'limit', limit: 'steps', maximum: 4, actual: 5 },
|
|
64
|
-
}),
|
|
65
|
-
).toEqual({ phase: 'limit', limit: 'steps', maximum: 4, actual: 5 })
|
|
66
|
-
expect(
|
|
67
|
-
queryInputRepair({
|
|
68
|
-
code: 'QUERY_INPUT_INVALID',
|
|
69
|
-
details: {
|
|
70
|
-
phase: 'plan',
|
|
71
|
-
issue: 'QUERY_DEFINITION_NOT_EDGE',
|
|
72
|
-
path: '/steps/0/via/0',
|
|
73
|
-
provider: 'private',
|
|
74
|
-
},
|
|
75
|
-
}),
|
|
76
|
-
).toBeUndefined()
|
|
77
|
-
})
|
|
78
|
-
})
|