@mysten-incubation/devstack 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/dashboard-ui/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/dashboard-ui/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/dashboard-ui/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dashboard-ui/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-cyrillic-ext-wght-normal-I4S5GZfc.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-cyrillic-wght-normal-BmXc_FBt.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-latin-ext-wght-normal-DrnZ1wKl.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-latin-wght-normal-B_7UjwxQ.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-symbols2-wght-normal-GZpp1pK2.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-vietnamese-wght-normal-D8KDMBhC.woff2 +0 -0
- package/dashboard-ui/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/dashboard-ui/assets/index-Bmi1UtAg.js +1356 -0
- package/dashboard-ui/assets/index-D5EShVt4.js +3 -0
- package/dashboard-ui/assets/index-Deml9drg.css +1 -0
- package/dashboard-ui/index.html +13 -0
- package/dist/api/define-capabilities.d.mts +14 -3
- package/dist/api/define-capabilities.mjs +18 -1
- package/dist/api/define-capabilities.mjs.map +1 -1
- package/dist/api/define-devstack.d.mts +1 -1
- package/dist/api/define-devstack.mjs +6 -26
- package/dist/api/define-devstack.mjs.map +1 -1
- package/dist/api/define-plugin.d.mts +1 -0
- package/dist/api/define-plugin.mjs +2 -0
- package/dist/api/inference-network.d.mts +132 -0
- package/dist/api/inference-network.mjs +105 -16
- package/dist/api/inference-network.mjs.map +1 -1
- package/dist/api/plugin-errors.d.mts +7 -0
- package/dist/api/run-stack.d.mts +20 -9
- package/dist/api/run-stack.mjs +56 -29
- package/dist/api/run-stack.mjs.map +1 -1
- package/dist/build-integrations/playwright/config.d.mts +6 -4
- package/dist/build-integrations/playwright/config.mjs +5 -3
- package/dist/build-integrations/playwright/config.mjs.map +1 -1
- package/dist/build-integrations/playwright/errors.d.mts +1 -1
- package/dist/build-integrations/playwright/global-setup.d.mts +43 -17
- package/dist/build-integrations/playwright/global-setup.mjs +250 -13
- package/dist/build-integrations/playwright/global-setup.mjs.map +1 -1
- package/dist/build-integrations/playwright/index.d.mts +5 -3
- package/dist/build-integrations/playwright/index.mjs +4 -2
- package/dist/build-integrations/playwright/stack-context.d.mts +0 -1
- package/dist/build-integrations/playwright/stack-context.mjs +24 -63
- package/dist/build-integrations/playwright/stack-context.mjs.map +1 -1
- package/dist/build-integrations/playwright/wallet-context.d.mts +7 -10
- package/dist/build-integrations/playwright/wallet-context.mjs +8 -13
- package/dist/build-integrations/playwright/wallet-context.mjs.map +1 -1
- package/dist/build-integrations/runtime/cold-start-url.d.mts +5 -0
- package/dist/build-integrations/runtime/cold-start-url.mjs +4 -3
- package/dist/build-integrations/runtime/cold-start-url.mjs.map +1 -1
- package/dist/build-integrations/runtime/conventional-routes.d.mts +51 -0
- package/dist/build-integrations/runtime/conventional-routes.mjs +92 -0
- package/dist/build-integrations/runtime/conventional-routes.mjs.map +1 -0
- package/dist/build-integrations/runtime/discover.d.mts +38 -30
- package/dist/build-integrations/runtime/discover.mjs +73 -70
- package/dist/build-integrations/runtime/discover.mjs.map +1 -1
- package/dist/build-integrations/runtime/endpoint-registry.d.mts +3 -1
- package/dist/build-integrations/runtime/endpoint-registry.mjs +3 -1
- package/dist/build-integrations/runtime/endpoint-registry.mjs.map +1 -1
- package/dist/build-integrations/runtime/index.d.mts +7 -2
- package/dist/build-integrations/runtime/index.mjs +9 -2
- package/dist/build-integrations/runtime/manifest-types.d.mts +2 -0
- package/dist/build-integrations/runtime/manifest-types.mjs +3 -0
- package/dist/build-integrations/runtime/playwright-stack-context-slot.d.mts +29 -0
- package/dist/build-integrations/runtime/playwright-stack-context-slot.mjs +10 -0
- package/dist/build-integrations/runtime/playwright-stack-context-slot.mjs.map +1 -0
- package/dist/build-integrations/runtime/read-stack-context.d.mts +1 -1
- package/dist/build-integrations/runtime/read-stack-context.mjs +10 -4
- package/dist/build-integrations/runtime/read-stack-context.mjs.map +1 -1
- package/dist/build-integrations/runtime/resolve-discovery-env.d.mts +48 -0
- package/dist/build-integrations/runtime/resolve-discovery-env.mjs +42 -0
- package/dist/build-integrations/runtime/resolve-discovery-env.mjs.map +1 -0
- package/dist/build-integrations/runtime/stack-context.d.mts +1 -1
- package/dist/build-integrations/runtime/wallet-paths.mjs +2 -0
- package/dist/build-integrations/vite/index.d.mts +51 -0
- package/dist/build-integrations/vite/index.mjs +73 -0
- package/dist/build-integrations/vite/index.mjs.map +1 -0
- package/dist/build-integrations/vitest/env.d.mts +4 -3
- package/dist/build-integrations/vitest/env.mjs +6 -4
- package/dist/build-integrations/vitest/env.mjs.map +1 -1
- package/dist/build-integrations/vitest/errors.d.mts +25 -4
- package/dist/build-integrations/vitest/errors.mjs +15 -2
- package/dist/build-integrations/vitest/errors.mjs.map +1 -1
- package/dist/build-integrations/vitest/index.d.mts +2 -2
- package/dist/build-integrations/vitest/index.mjs +3 -3
- package/dist/build-integrations/vitest/setup.d.mts +4 -2
- package/dist/build-integrations/vitest/setup.mjs +2 -2
- package/dist/build-integrations/vitest/setup.mjs.map +1 -1
- package/dist/build-integrations/vitest/stack-context.d.mts +0 -1
- package/dist/build-integrations/vitest/stack-context.mjs +33 -13
- package/dist/build-integrations/vitest/stack-context.mjs.map +1 -1
- package/dist/cli/bail.mjs +23 -0
- package/dist/cli/bail.mjs.map +1 -0
- package/dist/{surfaces/cli/commands → cli}/doctor-probes.mjs +26 -16
- package/dist/cli/doctor-probes.mjs.map +1 -0
- package/dist/cli/main.d.mts +15 -1
- package/dist/cli/main.mjs +166 -482
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/prune-direct.mjs +31 -201
- package/dist/cli/prune-direct.mjs.map +1 -1
- package/dist/cli/snapshot-reader.mjs +14 -11
- package/dist/cli/snapshot-reader.mjs.map +1 -1
- package/dist/cli/up-lifecycle.mjs +4 -1
- package/dist/cli/up-lifecycle.mjs.map +1 -1
- package/dist/cli/wirings/apply.mjs +95 -0
- package/dist/cli/wirings/apply.mjs.map +1 -0
- package/dist/cli/wirings/build-verb-layers.mjs +42 -0
- package/dist/cli/wirings/build-verb-layers.mjs.map +1 -0
- package/dist/cli/wirings/config-loader.mjs +69 -0
- package/dist/cli/wirings/config-loader.mjs.map +1 -0
- package/dist/cli/wirings/engine-command.mjs +30 -0
- package/dist/cli/wirings/engine-command.mjs.map +1 -0
- package/dist/cli/wirings/identity.mjs +72 -0
- package/dist/cli/wirings/identity.mjs.map +1 -0
- package/dist/cli/wirings/provide-file-system.mjs +7 -0
- package/dist/cli/wirings/provide-file-system.mjs.map +1 -0
- package/dist/cli/wirings/snapshot.mjs +177 -0
- package/dist/cli/wirings/snapshot.mjs.map +1 -0
- package/dist/cli/wirings/up.mjs +287 -0
- package/dist/cli/wirings/up.mjs.map +1 -0
- package/dist/cli/wirings/wipe.mjs +40 -0
- package/dist/cli/wirings/wipe.mjs.map +1 -0
- package/dist/contracts/capability-decl.d.mts +0 -2
- package/dist/contracts/codegenable.d.mts +43 -0
- package/dist/contracts/container-runtime.d.mts +26 -1
- package/dist/contracts/faucet-strategy.d.mts +25 -0
- package/dist/contracts/funding-strategy.d.mts +42 -0
- package/dist/contracts/plugin-expander.mjs +60 -0
- package/dist/contracts/plugin-expander.mjs.map +1 -0
- package/dist/contracts/projection.d.mts +5 -3
- package/dist/contracts/renderer.d.mts +23 -0
- package/dist/contracts/routable.d.mts +14 -1
- package/dist/contracts/snapshotable.d.mts +25 -3
- package/dist/contracts/wallet-protocol.d.mts +52 -0
- package/dist/contracts/wallet-protocol.mjs +52 -0
- package/dist/contracts/wallet-protocol.mjs.map +1 -0
- package/dist/index.d.mts +26 -25
- package/dist/index.mjs +20 -13
- package/dist/{runtime → orchestrators}/built-in-plugin-layers.mjs +10 -5
- package/dist/orchestrators/built-in-plugin-layers.mjs.map +1 -0
- package/dist/orchestrators/codegen/bindings.d.mts +1 -2
- package/dist/orchestrators/codegen/bindings.mjs +52 -186
- package/dist/orchestrators/codegen/bindings.mjs.map +1 -1
- package/dist/orchestrators/codegen/emit.mjs +19 -1
- package/dist/orchestrators/codegen/emit.mjs.map +1 -1
- package/dist/orchestrators/codegen/errors.mjs +8 -3
- package/dist/orchestrators/codegen/errors.mjs.map +1 -1
- package/dist/orchestrators/codegen/format.mjs +47 -39
- package/dist/orchestrators/codegen/format.mjs.map +1 -1
- package/dist/orchestrators/codegen/gitignore.mjs +3 -1
- package/dist/orchestrators/codegen/gitignore.mjs.map +1 -1
- package/dist/orchestrators/codegen/output-location.mjs +40 -0
- package/dist/orchestrators/codegen/output-location.mjs.map +1 -0
- package/dist/orchestrators/codegen/paths.d.mts +1 -1
- package/dist/orchestrators/codegen/paths.mjs +40 -14
- package/dist/orchestrators/codegen/paths.mjs.map +1 -1
- package/dist/orchestrators/codegen/permissions.mjs +3 -1
- package/dist/orchestrators/codegen/permissions.mjs.map +1 -1
- package/dist/orchestrators/codegen/service.mjs +157 -105
- package/dist/orchestrators/codegen/service.mjs.map +1 -1
- package/dist/orchestrators/lifecycle-prune/errors.mjs +31 -0
- package/dist/orchestrators/lifecycle-prune/errors.mjs.map +1 -0
- package/dist/orchestrators/lifecycle-prune/index.mjs +350 -0
- package/dist/orchestrators/lifecycle-prune/index.mjs.map +1 -0
- package/dist/orchestrators/router/cleanup.mjs +26 -27
- package/dist/orchestrators/router/cleanup.mjs.map +1 -1
- package/dist/orchestrators/router/entrypoints.mjs +2 -2
- package/dist/orchestrators/router/entrypoints.mjs.map +1 -1
- package/dist/orchestrators/router/file-provider.mjs +14 -5
- package/dist/orchestrators/router/file-provider.mjs.map +1 -1
- package/dist/orchestrators/router/hostname.mjs +19 -55
- package/dist/orchestrators/router/hostname.mjs.map +1 -1
- package/dist/orchestrators/router/index.mjs +11 -0
- package/dist/orchestrators/router/profile.mjs +2 -2
- package/dist/orchestrators/router/sentinels.mjs +26 -0
- package/dist/orchestrators/router/sentinels.mjs.map +1 -0
- package/dist/orchestrators/router/service.mjs +40 -37
- package/dist/orchestrators/router/service.mjs.map +1 -1
- package/dist/orchestrators/router/traefik-container.mjs +27 -16
- package/dist/orchestrators/router/traefik-container.mjs.map +1 -1
- package/dist/{substrate/runtime → orchestrators}/run.mjs +26 -21
- package/dist/orchestrators/run.mjs.map +1 -0
- package/dist/orchestrators/runtime-composition.d.mts +1 -1
- package/dist/orchestrators/runtime-composition.mjs +123 -39
- package/dist/orchestrators/runtime-composition.mjs.map +1 -1
- package/dist/orchestrators/snapshot/capture-command.d.mts +1 -0
- package/dist/orchestrators/snapshot/capture-command.mjs +25 -0
- package/dist/orchestrators/snapshot/capture-command.mjs.map +1 -0
- package/dist/orchestrators/snapshot/capture.mjs +42 -28
- package/dist/orchestrators/snapshot/capture.mjs.map +1 -1
- package/dist/orchestrators/snapshot/descriptor.mjs +35 -10
- package/dist/orchestrators/snapshot/descriptor.mjs.map +1 -1
- package/dist/orchestrators/snapshot/identity-guard.mjs +1 -1
- package/dist/orchestrators/snapshot/index.mjs +13 -0
- package/dist/orchestrators/snapshot/integrity.d.mts +1 -1
- package/dist/orchestrators/snapshot/integrity.mjs +73 -17
- package/dist/orchestrators/snapshot/integrity.mjs.map +1 -1
- package/dist/orchestrators/snapshot/pending-marker.d.mts +1 -0
- package/dist/orchestrators/snapshot/pending-marker.mjs +99 -0
- package/dist/orchestrators/snapshot/pending-marker.mjs.map +1 -0
- package/dist/orchestrators/snapshot/phase-error.mjs +23 -0
- package/dist/orchestrators/snapshot/phase-error.mjs.map +1 -0
- package/dist/orchestrators/snapshot/prune.mjs +20 -55
- package/dist/orchestrators/snapshot/prune.mjs.map +1 -1
- package/dist/orchestrators/snapshot/recover-pending.d.mts +1 -0
- package/dist/orchestrators/snapshot/recover-pending.mjs +223 -0
- package/dist/orchestrators/snapshot/recover-pending.mjs.map +1 -0
- package/dist/orchestrators/snapshot/restore.mjs +118 -84
- package/dist/orchestrators/snapshot/restore.mjs.map +1 -1
- package/dist/orchestrators/snapshot/service.mjs +53 -56
- package/dist/orchestrators/snapshot/service.mjs.map +1 -1
- package/dist/orchestrators/snapshot/state-document.d.mts +1 -0
- package/dist/orchestrators/snapshot/state-document.mjs +47 -7
- package/dist/orchestrators/snapshot/state-document.mjs.map +1 -1
- package/dist/orchestrators/snapshot/wipe.mjs +67 -10
- package/dist/orchestrators/snapshot/wipe.mjs.map +1 -1
- package/dist/plugins/account/codegen.mjs +9 -8
- package/dist/plugins/account/codegen.mjs.map +1 -1
- package/dist/plugins/account/errors.d.mts +33 -6
- package/dist/plugins/account/errors.mjs.map +1 -1
- package/dist/plugins/account/funding.d.mts +29 -19
- package/dist/plugins/account/funding.mjs +84 -66
- package/dist/plugins/account/funding.mjs.map +1 -1
- package/dist/plugins/account/index.d.mts +2 -4
- package/dist/plugins/account/index.mjs +64 -31
- package/dist/plugins/account/index.mjs.map +1 -1
- package/dist/plugins/account/keypair.mjs +6 -9
- package/dist/plugins/account/keypair.mjs.map +1 -1
- package/dist/plugins/account/lease.mjs +1 -0
- package/dist/plugins/account/lease.mjs.map +1 -1
- package/dist/plugins/account/registry.d.mts +14 -1
- package/dist/plugins/account/registry.mjs +18 -18
- package/dist/plugins/account/registry.mjs.map +1 -1
- package/dist/plugins/account/service.d.mts +23 -4
- package/dist/plugins/account/service.mjs +83 -45
- package/dist/plugins/account/service.mjs.map +1 -1
- package/dist/plugins/account/snapshot.mjs +2 -5
- package/dist/plugins/account/snapshot.mjs.map +1 -1
- package/dist/plugins/account/spans.mjs +16 -0
- package/dist/plugins/account/spans.mjs.map +1 -0
- package/dist/plugins/account/variants/keystore.mjs +6 -8
- package/dist/plugins/account/variants/keystore.mjs.map +1 -1
- package/dist/plugins/action/build-context.d.mts +3 -2
- package/dist/plugins/action/errors.d.mts +16 -12
- package/dist/plugins/action/errors.mjs.map +1 -1
- package/dist/plugins/action/execute.mjs +65 -103
- package/dist/plugins/action/execute.mjs.map +1 -1
- package/dist/plugins/action/index.d.mts +0 -2
- package/dist/plugins/action/index.mjs +17 -13
- package/dist/plugins/action/index.mjs.map +1 -1
- package/dist/plugins/action/service.mjs +38 -35
- package/dist/plugins/action/service.mjs.map +1 -1
- package/dist/plugins/action/spans.mjs +11 -0
- package/dist/plugins/action/spans.mjs.map +1 -0
- package/dist/plugins/coin/codegen.mjs +9 -8
- package/dist/plugins/coin/codegen.mjs.map +1 -1
- package/dist/plugins/coin/discovery.mjs +8 -4
- package/dist/plugins/coin/discovery.mjs.map +1 -1
- package/dist/plugins/coin/index.d.mts +11 -29
- package/dist/plugins/coin/index.mjs +56 -27
- package/dist/plugins/coin/index.mjs.map +1 -1
- package/dist/plugins/coin/metadata.mjs +8 -15
- package/dist/plugins/coin/metadata.mjs.map +1 -1
- package/dist/plugins/coin/mint.d.mts +30 -11
- package/dist/plugins/coin/mint.mjs +78 -74
- package/dist/plugins/coin/mint.mjs.map +1 -1
- package/dist/plugins/coin/registry.mjs +4 -7
- package/dist/plugins/coin/registry.mjs.map +1 -1
- package/dist/plugins/coin/service.d.mts +39 -1
- package/dist/plugins/coin/service.mjs +11 -4
- package/dist/plugins/coin/service.mjs.map +1 -1
- package/dist/plugins/coin/spans.mjs +20 -0
- package/dist/plugins/coin/spans.mjs.map +1 -0
- package/dist/plugins/dashboard/domain.mjs +402 -0
- package/dist/plugins/dashboard/domain.mjs.map +1 -0
- package/dist/plugins/dashboard/index.d.mts +29 -0
- package/dist/plugins/dashboard/index.mjs +91 -0
- package/dist/plugins/dashboard/index.mjs.map +1 -0
- package/dist/plugins/dashboard/origin-policy.mjs +36 -0
- package/dist/plugins/dashboard/origin-policy.mjs.map +1 -0
- package/dist/plugins/dashboard/routable.mjs +27 -0
- package/dist/plugins/dashboard/routable.mjs.map +1 -0
- package/dist/plugins/dashboard/schema/builder.mjs +21 -0
- package/dist/plugins/dashboard/schema/builder.mjs.map +1 -0
- package/dist/plugins/dashboard/schema/enums.mjs +72 -0
- package/dist/plugins/dashboard/schema/enums.mjs.map +1 -0
- package/dist/plugins/dashboard/schema/root.mjs +351 -0
- package/dist/plugins/dashboard/schema/root.mjs.map +1 -0
- package/dist/plugins/dashboard/schema/types.mjs +508 -0
- package/dist/plugins/dashboard/schema/types.mjs.map +1 -0
- package/dist/plugins/dashboard/schema.mjs +11 -0
- package/dist/plugins/dashboard/schema.mjs.map +1 -0
- package/dist/plugins/dashboard/server.mjs +166 -0
- package/dist/plugins/dashboard/server.mjs.map +1 -0
- package/dist/plugins/deepbook/deploy.mjs +53 -115
- package/dist/plugins/deepbook/deploy.mjs.map +1 -1
- package/dist/plugins/deepbook/errors.mjs +1 -0
- package/dist/plugins/deepbook/errors.mjs.map +1 -1
- package/dist/plugins/deepbook/faucet-strategy.mjs +47 -34
- package/dist/plugins/deepbook/faucet-strategy.mjs.map +1 -1
- package/dist/plugins/deepbook/hash.mjs +9 -0
- package/dist/plugins/deepbook/hash.mjs.map +1 -0
- package/dist/plugins/deepbook/index.d.mts +1 -10
- package/dist/plugins/deepbook/index.mjs +25 -22
- package/dist/plugins/deepbook/index.mjs.map +1 -1
- package/dist/plugins/deepbook/pyth/index.mjs +26 -55
- package/dist/plugins/deepbook/pyth/index.mjs.map +1 -1
- package/dist/plugins/deepbook/snapshot.mjs +17 -29
- package/dist/plugins/deepbook/snapshot.mjs.map +1 -1
- package/dist/plugins/deepbook/spans.mjs +18 -0
- package/dist/plugins/deepbook/spans.mjs.map +1 -0
- package/dist/plugins/deepbook/type-strings.mjs +65 -0
- package/dist/plugins/deepbook/type-strings.mjs.map +1 -0
- package/dist/plugins/deepbook/types.d.mts +2 -3
- package/dist/plugins/deepbook/types.mjs.map +1 -1
- package/dist/plugins/faucet/dispatcher.d.mts +21 -2
- package/dist/plugins/faucet/dispatcher.mjs +1 -2
- package/dist/plugins/faucet/dispatcher.mjs.map +1 -1
- package/dist/plugins/faucet/errors.d.mts +11 -24
- package/dist/plugins/faucet/errors.mjs.map +1 -1
- package/dist/plugins/faucet/http.mjs +33 -14
- package/dist/plugins/faucet/http.mjs.map +1 -1
- package/dist/plugins/faucet/index.d.mts +15 -5
- package/dist/plugins/faucet/index.mjs +3 -0
- package/dist/plugins/faucet/index.mjs.map +1 -1
- package/dist/plugins/faucet/spans.mjs +12 -0
- package/dist/plugins/faucet/spans.mjs.map +1 -0
- package/dist/plugins/host-service/errors.d.mts +1 -1
- package/dist/plugins/host-service/index.mjs +34 -8
- package/dist/plugins/host-service/index.mjs.map +1 -1
- package/dist/plugins/host-service/routable.mjs +2 -1
- package/dist/plugins/host-service/routable.mjs.map +1 -1
- package/dist/plugins/host-service/service.d.mts +21 -0
- package/dist/plugins/host-service/service.mjs +136 -81
- package/dist/plugins/host-service/service.mjs.map +1 -1
- package/dist/plugins/internal/acquire-on-chain-artifact.mjs +23 -0
- package/dist/plugins/internal/acquire-on-chain-artifact.mjs.map +1 -0
- package/dist/plugins/internal/codegen-helpers.mjs +18 -0
- package/dist/plugins/internal/codegen-helpers.mjs.map +1 -0
- package/dist/plugins/internal/funding-failure-error.mjs +32 -0
- package/dist/plugins/internal/funding-failure-error.mjs.map +1 -0
- package/dist/plugins/package/build.mjs +1 -1
- package/dist/plugins/package/build.mjs.map +1 -1
- package/dist/plugins/package/codegen.mjs +26 -0
- package/dist/plugins/package/codegen.mjs.map +1 -1
- package/dist/plugins/package/errors.d.mts +16 -6
- package/dist/plugins/package/errors.mjs.map +1 -1
- package/dist/plugins/package/index.d.mts +0 -4
- package/dist/plugins/package/index.mjs +27 -21
- package/dist/plugins/package/index.mjs.map +1 -1
- package/dist/plugins/package/mode-known.mjs +26 -12
- package/dist/plugins/package/mode-known.mjs.map +1 -1
- package/dist/plugins/package/mode-local.mjs +47 -41
- package/dist/plugins/package/mode-local.mjs.map +1 -1
- package/dist/plugins/package/publish-executor.mjs +55 -114
- package/dist/plugins/package/publish-executor.mjs.map +1 -1
- package/dist/plugins/package/registry.mjs +2 -1
- package/dist/plugins/package/registry.mjs.map +1 -1
- package/dist/plugins/package/service.mjs.map +1 -1
- package/dist/plugins/package/spans.mjs +14 -0
- package/dist/plugins/package/spans.mjs.map +1 -0
- package/dist/plugins/postgres/db-ensure.mjs +19 -12
- package/dist/plugins/postgres/db-ensure.mjs.map +1 -1
- package/dist/plugins/postgres/errors.d.mts +5 -0
- package/dist/plugins/postgres/errors.mjs.map +1 -1
- package/dist/plugins/postgres/index.mjs +10 -17
- package/dist/plugins/postgres/index.mjs.map +1 -1
- package/dist/plugins/postgres/service.mjs +58 -24
- package/dist/plugins/postgres/service.mjs.map +1 -1
- package/dist/plugins/postgres/snapshot.mjs.map +1 -1
- package/dist/plugins/postgres/spans.mjs +11 -0
- package/dist/plugins/postgres/spans.mjs.map +1 -0
- package/dist/plugins/router-entrypoints.mjs +4 -4
- package/dist/plugins/router-entrypoints.mjs.map +1 -1
- package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs +15 -13
- package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs.map +1 -1
- package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs +15 -19
- package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs.map +1 -1
- package/dist/plugins/seal/codegen.d.mts +2 -3
- package/dist/plugins/seal/codegen.mjs.map +1 -1
- package/dist/plugins/seal/config-render.mjs +35 -8
- package/dist/plugins/seal/config-render.mjs.map +1 -1
- package/dist/plugins/seal/deploy.mjs +31 -39
- package/dist/plugins/seal/deploy.mjs.map +1 -1
- package/dist/plugins/seal/errors.d.mts +1 -3
- package/dist/plugins/seal/errors.mjs +7 -1
- package/dist/plugins/seal/errors.mjs.map +1 -1
- package/dist/plugins/seal/index.d.mts +1 -6
- package/dist/plugins/seal/index.mjs +40 -14
- package/dist/plugins/seal/index.mjs.map +1 -1
- package/dist/plugins/seal/key-manager.d.mts +1 -9
- package/dist/plugins/seal/key-manager.mjs +2 -18
- package/dist/plugins/seal/key-manager.mjs.map +1 -1
- package/dist/plugins/seal/key-server.mjs +37 -36
- package/dist/plugins/seal/key-server.mjs.map +1 -1
- package/dist/plugins/seal/keygen.mjs +16 -17
- package/dist/plugins/seal/keygen.mjs.map +1 -1
- package/dist/plugins/seal/mode/fork-known.mjs +36 -14
- package/dist/plugins/seal/mode/fork-known.mjs.map +1 -1
- package/dist/plugins/seal/mode/live.d.mts +6 -4
- package/dist/plugins/seal/mode/live.mjs +14 -21
- package/dist/plugins/seal/mode/live.mjs.map +1 -1
- package/dist/plugins/seal/mode/local-keygen.mjs +57 -21
- package/dist/plugins/seal/mode/local-keygen.mjs.map +1 -1
- package/dist/plugins/seal/registry-publish.mjs +1 -0
- package/dist/plugins/seal/registry-publish.mjs.map +1 -1
- package/dist/plugins/seal/routable.mjs.map +1 -1
- package/dist/plugins/seal/service.mjs.map +1 -1
- package/dist/plugins/seal/spans.mjs +18 -0
- package/dist/plugins/seal/spans.mjs.map +1 -0
- package/dist/plugins/sui/auto-tick.mjs +17 -23
- package/dist/plugins/sui/auto-tick.mjs.map +1 -1
- package/dist/plugins/sui/chain-build-container.mjs +18 -0
- package/dist/plugins/sui/chain-build-container.mjs.map +1 -0
- package/dist/plugins/sui/chain-probe.d.mts +5 -5
- package/dist/plugins/sui/chain-probe.mjs +28 -58
- package/dist/plugins/sui/chain-probe.mjs.map +1 -1
- package/dist/plugins/sui/codegen.mjs +26 -0
- package/dist/plugins/sui/codegen.mjs.map +1 -1
- package/dist/plugins/sui/errors.d.mts +2 -29
- package/dist/plugins/sui/errors.mjs +1 -3
- package/dist/plugins/sui/errors.mjs.map +1 -1
- package/dist/plugins/sui/fork-faucet-strategy.d.mts +1 -0
- package/dist/plugins/sui/fork-faucet-strategy.mjs +55 -0
- package/dist/plugins/sui/fork-faucet-strategy.mjs.map +1 -0
- package/dist/plugins/sui/fork-orchestration.d.mts +1 -0
- package/dist/plugins/sui/fork-orchestration.mjs +170 -2
- package/dist/plugins/sui/fork-orchestration.mjs.map +1 -1
- package/dist/plugins/sui/fork-transaction.d.mts +2 -0
- package/dist/plugins/sui/fork-transaction.mjs +92 -28
- package/dist/plugins/sui/fork-transaction.mjs.map +1 -1
- package/dist/plugins/sui/index.d.mts +33 -70
- package/dist/plugins/sui/index.mjs +58 -35
- package/dist/plugins/sui/index.mjs.map +1 -1
- package/dist/plugins/{faucet/strategies/sui-local.mjs → sui/local-faucet-strategy.mjs} +10 -7
- package/dist/plugins/sui/local-faucet-strategy.mjs.map +1 -0
- package/dist/plugins/sui/mode/external.mjs +7 -13
- package/dist/plugins/sui/mode/external.mjs.map +1 -1
- package/dist/plugins/sui/mode/fork.mjs +136 -59
- package/dist/plugins/sui/mode/fork.mjs.map +1 -1
- package/dist/plugins/sui/mode/live.mjs +10 -16
- package/dist/plugins/sui/mode/live.mjs.map +1 -1
- package/dist/plugins/sui/mode/local.mjs +37 -36
- package/dist/plugins/sui/mode/local.mjs.map +1 -1
- package/dist/plugins/sui/mode/shared-boot.mjs +38 -115
- package/dist/plugins/sui/mode/shared-boot.mjs.map +1 -1
- package/dist/plugins/sui/mode/shared.d.mts +1 -5
- package/dist/plugins/sui/mode/shared.mjs.map +1 -1
- package/dist/plugins/sui/mode/spec.d.mts +18 -0
- package/dist/plugins/sui/move-summary-runner.mjs +207 -0
- package/dist/plugins/sui/move-summary-runner.mjs.map +1 -0
- package/dist/plugins/sui/network-resolver.d.mts +4 -3
- package/dist/plugins/sui/service.mjs.map +1 -1
- package/dist/plugins/sui/snapshot.mjs +3 -0
- package/dist/plugins/sui/snapshot.mjs.map +1 -1
- package/dist/plugins/sui/spans.mjs +17 -0
- package/dist/plugins/sui/spans.mjs.map +1 -0
- package/dist/plugins/wallet/codegen.d.mts +0 -1
- package/dist/plugins/wallet/codegen.mjs +8 -9
- package/dist/plugins/wallet/codegen.mjs.map +1 -1
- package/dist/plugins/wallet/index.d.mts +6 -8
- package/dist/plugins/wallet/index.mjs +46 -35
- package/dist/plugins/wallet/index.mjs.map +1 -1
- package/dist/plugins/wallet/origin-policy.mjs +12 -28
- package/dist/plugins/wallet/origin-policy.mjs.map +1 -1
- package/dist/plugins/wallet/pairing.mjs +6 -4
- package/dist/plugins/wallet/pairing.mjs.map +1 -1
- package/dist/plugins/wallet/protocol.d.mts +1 -0
- package/dist/plugins/wallet/protocol.mjs +5 -44
- package/dist/plugins/wallet/protocol.mjs.map +1 -1
- package/dist/plugins/wallet/routable.mjs +2 -8
- package/dist/plugins/wallet/routable.mjs.map +1 -1
- package/dist/plugins/wallet/server.mjs +36 -44
- package/dist/plugins/wallet/server.mjs.map +1 -1
- package/dist/plugins/wallet/service.d.mts +1 -5
- package/dist/plugins/wallet/service.mjs +22 -18
- package/dist/plugins/wallet/service.mjs.map +1 -1
- package/dist/plugins/wallet/spans.mjs +22 -0
- package/dist/plugins/wallet/spans.mjs.map +1 -0
- package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs +33 -8
- package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs.map +1 -1
- package/dist/plugins/walrus/codegen.d.mts +3 -3
- package/dist/plugins/walrus/codegen.mjs.map +1 -1
- package/dist/plugins/walrus/deploy-paths.mjs +21 -5
- package/dist/plugins/walrus/deploy-paths.mjs.map +1 -1
- package/dist/plugins/walrus/deploy.mjs +67 -69
- package/dist/plugins/walrus/deploy.mjs.map +1 -1
- package/dist/plugins/walrus/errors.mjs +1 -0
- package/dist/plugins/walrus/errors.mjs.map +1 -1
- package/dist/plugins/walrus/faucet-strategy.mjs +12 -7
- package/dist/plugins/walrus/faucet-strategy.mjs.map +1 -1
- package/dist/plugins/walrus/index.d.mts +2 -13
- package/dist/plugins/walrus/index.mjs +18 -23
- package/dist/plugins/walrus/index.mjs.map +1 -1
- package/dist/plugins/walrus/mode/known-deploy.mjs +7 -5
- package/dist/plugins/walrus/mode/known-deploy.mjs.map +1 -1
- package/dist/plugins/walrus/mode/local-cluster.mjs +26 -7
- package/dist/plugins/walrus/mode/local-cluster.mjs.map +1 -1
- package/dist/plugins/walrus/registry-publish.mjs.map +1 -1
- package/dist/plugins/walrus/routable.mjs +7 -23
- package/dist/plugins/walrus/routable.mjs.map +1 -1
- package/dist/plugins/walrus/service.mjs.map +1 -1
- package/dist/plugins/walrus/spans.mjs +18 -0
- package/dist/plugins/walrus/spans.mjs.map +1 -0
- package/dist/plugins/walrus/storage-nodes.d.mts +6 -2
- package/dist/plugins/walrus/storage-nodes.mjs +15 -8
- package/dist/plugins/walrus/storage-nodes.mjs.map +1 -1
- package/dist/plugins/walrus/wal-swap.mjs +58 -15
- package/dist/plugins/walrus/wal-swap.mjs.map +1 -1
- package/dist/primitives/artifact-publisher.d.mts +1 -1
- package/dist/primitives/artifact-publisher.mjs +15 -0
- package/dist/primitives/artifact-publisher.mjs.map +1 -0
- package/dist/runtime/docker/client.mjs +17 -4
- package/dist/runtime/docker/client.mjs.map +1 -1
- package/dist/runtime/docker/container.mjs +219 -132
- package/dist/runtime/docker/container.mjs.map +1 -1
- package/dist/runtime/docker/errors.mjs +0 -6
- package/dist/runtime/docker/errors.mjs.map +1 -1
- package/dist/runtime/docker/exec.mjs +21 -18
- package/dist/runtime/docker/exec.mjs.map +1 -1
- package/dist/runtime/docker/image.mjs +36 -13
- package/dist/runtime/docker/image.mjs.map +1 -1
- package/dist/runtime/docker/index.mjs +14 -0
- package/dist/runtime/docker/inspect-and-decode.mjs +51 -0
- package/dist/runtime/docker/inspect-and-decode.mjs.map +1 -0
- package/dist/runtime/docker/inventory.mjs +14 -11
- package/dist/runtime/docker/inventory.mjs.map +1 -1
- package/dist/runtime/docker/labels.mjs +38 -5
- package/dist/runtime/docker/labels.mjs.map +1 -1
- package/dist/runtime/docker/logs.d.mts +1 -1
- package/dist/runtime/docker/logs.mjs.map +1 -1
- package/dist/runtime/docker/network.mjs +83 -47
- package/dist/runtime/docker/network.mjs.map +1 -1
- package/dist/runtime/docker/render-run-args.mjs +82 -0
- package/dist/runtime/docker/render-run-args.mjs.map +1 -0
- package/dist/runtime/docker/service.d.mts +1 -1
- package/dist/runtime/docker/service.mjs +12 -7
- package/dist/runtime/docker/service.mjs.map +1 -1
- package/dist/runtime/docker/sweep.mjs +118 -43
- package/dist/runtime/docker/sweep.mjs.map +1 -1
- package/dist/runtime/docker/volume.mjs +2 -0
- package/dist/runtime/docker/volume.mjs.map +1 -1
- package/dist/runtime/docker/wrap.mjs +30 -1
- package/dist/runtime/docker/wrap.mjs.map +1 -1
- package/dist/substrate/cross-process.mjs +14 -8
- package/dist/substrate/cross-process.mjs.map +1 -1
- package/dist/substrate/event-time.mjs +33 -0
- package/dist/substrate/event-time.mjs.map +1 -0
- package/dist/substrate/events.d.mts +28 -8
- package/dist/substrate/identity.d.mts +2 -1
- package/dist/substrate/manifest.d.mts +68 -5
- package/dist/substrate/manifest.mjs +34 -5
- package/dist/substrate/manifest.mjs.map +1 -1
- package/dist/substrate/network.d.mts +3 -5
- package/dist/substrate/options.d.mts +0 -2
- package/dist/substrate/plugin.d.mts +13 -0
- package/dist/substrate/plugin.mjs +4 -2
- package/dist/substrate/plugin.mjs.map +1 -1
- package/dist/substrate/projection.d.mts +35 -3
- package/dist/substrate/runtime/artifact-publisher/index.mjs +19 -9
- package/dist/substrate/runtime/artifact-publisher/index.mjs.map +1 -1
- package/dist/substrate/runtime/atomic-write.mjs +97 -32
- package/dist/substrate/runtime/atomic-write.mjs.map +1 -1
- package/dist/substrate/runtime/cache/index.mjs +3 -0
- package/dist/substrate/runtime/cache/schema.mjs +2 -2
- package/dist/substrate/runtime/cache/schema.mjs.map +1 -1
- package/dist/substrate/runtime/cache/service.mjs +9 -7
- package/dist/substrate/runtime/cache/service.mjs.map +1 -1
- package/dist/substrate/runtime/capability-sinks/index.d.mts +1 -1
- package/dist/substrate/runtime/capability-sinks/index.mjs +3 -0
- package/dist/substrate/runtime/capability-sinks/layer.mjs +1 -1
- package/dist/substrate/runtime/capability-sinks/service.d.mts +61 -2
- package/dist/substrate/runtime/capability-sinks/service.mjs +21 -26
- package/dist/substrate/runtime/capability-sinks/service.mjs.map +1 -1
- package/dist/substrate/runtime/config-validation.d.mts +1 -13
- package/dist/substrate/runtime/config-validation.mjs +2 -91
- package/dist/substrate/runtime/config-validation.mjs.map +1 -1
- package/dist/substrate/runtime/container-runtime.d.mts +1 -0
- package/dist/substrate/runtime/container-runtime.mjs +2 -0
- package/dist/substrate/runtime/control-plane/domain.mjs +101 -0
- package/dist/substrate/runtime/control-plane/domain.mjs.map +1 -0
- package/dist/substrate/runtime/control-plane/service.mjs +7 -0
- package/dist/substrate/runtime/control-plane/service.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/command-channel/channel.mjs +46 -19
- package/dist/substrate/runtime/cross-process/command-channel/channel.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs +30 -12
- package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/command-channel/index.mjs +5 -0
- package/dist/substrate/runtime/cross-process/command-channel/protocol.mjs +11 -2
- package/dist/substrate/runtime/cross-process/command-channel/protocol.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/command-channel/runtime-control-lock.mjs +1 -1
- package/dist/substrate/runtime/cross-process/index.mjs +11 -0
- package/dist/substrate/runtime/cross-process/live-clock.mjs +34 -0
- package/dist/substrate/runtime/cross-process/live-clock.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/liveness.mjs +52 -10
- package/dist/substrate/runtime/cross-process/liveness.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/lock.d.mts +1 -0
- package/dist/substrate/runtime/cross-process/lock.mjs +23 -0
- package/dist/substrate/runtime/cross-process/lock.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs +64 -0
- package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/roster.mjs +97 -83
- package/dist/substrate/runtime/cross-process/roster.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/self-pid.mjs +8 -0
- package/dist/substrate/runtime/cross-process/self-pid.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs +24 -28
- package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/stack-lock.mjs +41 -20
- package/dist/substrate/runtime/cross-process/stack-lock.mjs.map +1 -1
- package/dist/substrate/runtime/current-plugin.mjs +2 -2
- package/dist/substrate/runtime/current-plugin.mjs.map +1 -1
- package/dist/substrate/runtime/errors.mjs +12 -6
- package/dist/substrate/runtime/errors.mjs.map +1 -1
- package/dist/substrate/runtime/format-unknown-error.mjs +30 -0
- package/dist/substrate/runtime/format-unknown-error.mjs.map +1 -0
- package/dist/substrate/runtime/host-bind-mount-owner.mjs +10 -0
- package/dist/substrate/runtime/host-bind-mount-owner.mjs.map +1 -0
- package/dist/substrate/runtime/host-gateway.mjs +20 -0
- package/dist/substrate/runtime/host-gateway.mjs.map +1 -0
- package/dist/substrate/runtime/host-tree-tar/index.mjs +61 -50
- package/dist/substrate/runtime/host-tree-tar/index.mjs.map +1 -1
- package/dist/substrate/runtime/http-probe.d.mts +1 -1
- package/dist/substrate/runtime/index.mjs +14 -0
- package/dist/substrate/runtime/lease-broker/index.d.mts +1 -1
- package/dist/substrate/runtime/lease-broker/index.mjs +2 -0
- package/dist/substrate/runtime/lease-broker/service.d.mts +1 -64
- package/dist/substrate/runtime/lease-broker/service.mjs +1 -1
- package/dist/substrate/runtime/lease-broker/service.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/dep-graph.mjs +22 -3
- package/dist/substrate/runtime/lifecycle/dep-graph.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/index.mjs +9 -0
- package/dist/substrate/runtime/lifecycle/lifecycle-fact.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/plugin-registry.mjs +20 -3
- package/dist/substrate/runtime/lifecycle/plugin-registry.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/selective-restart.mjs +1 -1
- package/dist/substrate/runtime/lifecycle/signals.mjs +5 -5
- package/dist/substrate/runtime/lifecycle/signals.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/state-machine.mjs +1 -1
- package/dist/substrate/runtime/managed-container.d.mts +19 -1
- package/dist/substrate/runtime/managed-container.mjs +20 -1
- package/dist/substrate/runtime/managed-container.mjs.map +1 -1
- package/dist/substrate/runtime/manifest/index.mjs +3 -0
- package/dist/substrate/runtime/manifest/manifest.mjs +15 -11
- package/dist/substrate/runtime/manifest/manifest.mjs.map +1 -1
- package/dist/substrate/runtime/mode-errors.mjs +20 -0
- package/dist/substrate/runtime/mode-errors.mjs.map +1 -0
- package/dist/substrate/runtime/observability/cascade-formatter.mjs +9 -13
- package/dist/substrate/runtime/observability/cascade-formatter.mjs.map +1 -1
- package/dist/substrate/runtime/observability/formatter-registry.mjs +19 -36
- package/dist/substrate/runtime/observability/formatter-registry.mjs.map +1 -1
- package/dist/substrate/runtime/observability/ignore-with-log.d.mts +1 -0
- package/dist/substrate/runtime/observability/ignore-with-log.mjs +17 -0
- package/dist/substrate/runtime/observability/ignore-with-log.mjs.map +1 -0
- package/dist/substrate/runtime/observability/index.d.mts +1 -1
- package/dist/substrate/runtime/observability/index.mjs +13 -0
- package/dist/substrate/runtime/observability/log-store.d.mts +1 -0
- package/dist/substrate/runtime/observability/log-store.mjs +175 -0
- package/dist/substrate/runtime/observability/log-store.mjs.map +1 -0
- package/dist/substrate/runtime/observability/logger.d.mts +2 -1
- package/dist/substrate/runtime/observability/logger.mjs +5 -9
- package/dist/substrate/runtime/observability/logger.mjs.map +1 -1
- package/dist/substrate/runtime/observability/output-truncate.mjs +35 -0
- package/dist/substrate/runtime/observability/output-truncate.mjs.map +1 -0
- package/dist/substrate/runtime/observability/pretty-error.mjs +9 -12
- package/dist/substrate/runtime/observability/pretty-error.mjs.map +1 -1
- package/dist/substrate/runtime/observability/redaction.d.mts +2 -13
- package/dist/substrate/runtime/observability/redaction.mjs +8 -14
- package/dist/substrate/runtime/observability/redaction.mjs.map +1 -1
- package/dist/substrate/runtime/observability/span-store.d.mts +1 -0
- package/dist/substrate/runtime/observability/span-store.mjs +110 -0
- package/dist/substrate/runtime/observability/span-store.mjs.map +1 -0
- package/dist/substrate/runtime/observability/spans.mjs +14 -14
- package/dist/substrate/runtime/observability/spans.mjs.map +1 -1
- package/dist/substrate/runtime/observability/subprocess-capture.mjs +1 -1
- package/dist/substrate/runtime/passthrough-or-wrap.mjs +33 -0
- package/dist/substrate/runtime/passthrough-or-wrap.mjs.map +1 -0
- package/dist/substrate/runtime/paths.d.mts +1 -1
- package/dist/substrate/runtime/paths.mjs +4 -3
- package/dist/substrate/runtime/paths.mjs.map +1 -1
- package/dist/substrate/runtime/phase-preserving-produce.mjs +40 -0
- package/dist/substrate/runtime/phase-preserving-produce.mjs.map +1 -0
- package/dist/substrate/runtime/port-broker/index.mjs +3 -0
- package/dist/substrate/runtime/port-broker/service.mjs +170 -126
- package/dist/substrate/runtime/port-broker/service.mjs.map +1 -1
- package/dist/substrate/runtime/post-acquire-tasks.mjs +1 -1
- package/dist/substrate/runtime/post-acquire-tasks.mjs.map +1 -1
- package/dist/substrate/runtime/probes.d.mts +7 -5
- package/dist/substrate/runtime/probes.mjs +3 -1
- package/dist/substrate/runtime/probes.mjs.map +1 -1
- package/dist/substrate/runtime/projection/index.mjs +4 -0
- package/dist/substrate/runtime/projection/operational-endpoints.mjs +1 -2
- package/dist/substrate/runtime/projection/operational-endpoints.mjs.map +1 -1
- package/dist/substrate/runtime/projection/persisted.mjs +33 -15
- package/dist/substrate/runtime/projection/persisted.mjs.map +1 -1
- package/dist/substrate/runtime/projection/state-ref.mjs +26 -2
- package/dist/substrate/runtime/projection/state-ref.mjs.map +1 -1
- package/dist/substrate/runtime/projection/update.mjs +88 -24
- package/dist/substrate/runtime/projection/update.mjs.map +1 -1
- package/dist/substrate/runtime/random-suffix.mjs +11 -0
- package/dist/substrate/runtime/random-suffix.mjs.map +1 -0
- package/dist/substrate/runtime/retry-policy.d.mts +59 -1
- package/dist/substrate/runtime/retry-policy.mjs +66 -1
- package/dist/substrate/runtime/retry-policy.mjs.map +1 -1
- package/dist/substrate/runtime/routed-url.d.mts +1 -0
- package/dist/substrate/runtime/routed-url.mjs +79 -0
- package/dist/substrate/runtime/routed-url.mjs.map +1 -0
- package/dist/substrate/runtime/runtime-decode.d.mts +1 -1
- package/dist/substrate/runtime/runtime-decode.mjs.map +1 -1
- package/dist/substrate/runtime/scoped-http-server.mjs +2 -3
- package/dist/substrate/runtime/scoped-http-server.mjs.map +1 -1
- package/dist/substrate/runtime/scoped-multimap/index.mjs +2 -0
- package/dist/substrate/runtime/scoped-multimap/service.mjs +52 -0
- package/dist/substrate/runtime/scoped-multimap/service.mjs.map +1 -0
- package/dist/substrate/runtime/scoped-ref-map/index.mjs +2 -0
- package/dist/substrate/runtime/scoped-ref-map/service.mjs +2 -2
- package/dist/substrate/runtime/scoped-ref-map/service.mjs.map +1 -1
- package/dist/substrate/runtime/stage-and-swap/index.mjs +72 -4
- package/dist/substrate/runtime/stage-and-swap/index.mjs.map +1 -1
- package/dist/substrate/runtime/state-store/index.d.mts +1 -0
- package/dist/substrate/runtime/state-store/index.mjs +3 -0
- package/dist/substrate/runtime/state-store/schema.d.mts +1 -0
- package/dist/substrate/runtime/state-store/schema.mjs +19 -14
- package/dist/substrate/runtime/state-store/schema.mjs.map +1 -1
- package/dist/substrate/runtime/state-store/service.d.mts +1 -0
- package/dist/substrate/runtime/state-store/service.mjs +145 -0
- package/dist/substrate/runtime/state-store/service.mjs.map +1 -0
- package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.d.mts +1 -0
- package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.mjs +33 -0
- package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.mjs.map +1 -0
- package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs +1 -1
- package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs.map +1 -1
- package/dist/substrate/runtime/strategy-registry/index.mjs +4 -0
- package/dist/substrate/runtime/strategy-registry/service.mjs +19 -33
- package/dist/substrate/runtime/strategy-registry/service.mjs.map +1 -1
- package/dist/substrate/runtime/subnet-broker.mjs +60 -0
- package/dist/substrate/runtime/subnet-broker.mjs.map +1 -0
- package/dist/substrate/runtime/sui-execute/index.d.mts +21 -1
- package/dist/substrate/runtime/sui-execute/index.mjs +84 -20
- package/dist/substrate/runtime/sui-execute/index.mjs.map +1 -1
- package/dist/substrate/runtime/sui-execute/sign-and-dispatch.d.mts +1 -0
- package/dist/substrate/runtime/sui-execute/sign-and-dispatch.mjs +32 -0
- package/dist/substrate/runtime/sui-execute/sign-and-dispatch.mjs.map +1 -0
- package/dist/substrate/runtime/sui-ledger/object-ref.mjs +32 -0
- package/dist/substrate/runtime/sui-ledger/object-ref.mjs.map +1 -0
- package/dist/substrate/runtime/sui-move-build/index.mjs +93 -19
- package/dist/substrate/runtime/sui-move-build/index.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/acquire-node.mjs +181 -0
- package/dist/substrate/runtime/supervisor/acquire-node.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/background-tasks.mjs +144 -0
- package/dist/substrate/runtime/supervisor/background-tasks.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/command-loop.mjs +68 -0
- package/dist/substrate/runtime/supervisor/command-loop.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs +151 -0
- package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/errors.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/errors.mjs +9 -0
- package/dist/substrate/runtime/supervisor/errors.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/index.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/index.mjs +3 -0
- package/dist/substrate/runtime/supervisor/shutdown.mjs +51 -0
- package/dist/substrate/runtime/supervisor/shutdown.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/start-supervisor.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/start-supervisor.mjs +250 -0
- package/dist/substrate/runtime/supervisor/start-supervisor.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/state.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/state.mjs +22 -0
- package/dist/substrate/runtime/supervisor/state.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/teardown.mjs +57 -0
- package/dist/substrate/runtime/supervisor/teardown.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/types.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/wiring.mjs +133 -0
- package/dist/substrate/runtime/supervisor/wiring.mjs.map +1 -0
- package/dist/substrate/runtime/typed-env.mjs +8 -0
- package/dist/substrate/runtime/typed-env.mjs.map +1 -0
- package/dist/substrate/state-store.d.mts +1 -0
- package/dist/substrate/versioned-doc-schema.mjs +17 -0
- package/dist/substrate/versioned-doc-schema.mjs.map +1 -0
- package/dist/substrate/versioned-doc-sync.mjs +94 -0
- package/dist/substrate/versioned-doc-sync.mjs.map +1 -0
- package/dist/surfaces/cli/command-tree.mjs.map +1 -1
- package/dist/surfaces/cli/commands/index.mjs +9 -0
- package/dist/surfaces/cli/commands/prune-picker-entry.mjs +13 -0
- package/dist/surfaces/cli/commands/prune-picker-entry.mjs.map +1 -0
- package/dist/surfaces/cli/commands/prune-picker.mjs +3 -2
- package/dist/surfaces/cli/commands/prune-picker.mjs.map +1 -1
- package/dist/surfaces/cli/commands/prune.mjs +34 -17
- package/dist/surfaces/cli/commands/prune.mjs.map +1 -1
- package/dist/surfaces/cli/commands/status.mjs +2 -2
- package/dist/surfaces/cli/commands/status.mjs.map +1 -1
- package/dist/surfaces/cli/commands/supervisor-presence.mjs +5 -3
- package/dist/surfaces/cli/commands/supervisor-presence.mjs.map +1 -1
- package/dist/surfaces/cli/commands/wipe.mjs +38 -4
- package/dist/surfaces/cli/commands/wipe.mjs.map +1 -1
- package/dist/surfaces/cli/errors.mjs +1 -1
- package/dist/surfaces/cli/errors.mjs.map +1 -1
- package/dist/surfaces/cli/flags.mjs +0 -1
- package/dist/surfaces/cli/flags.mjs.map +1 -1
- package/dist/surfaces/cli/index.mjs +98 -18
- package/dist/surfaces/cli/index.mjs.map +1 -1
- package/dist/surfaces/cli/output.mjs +1 -0
- package/dist/surfaces/cli/output.mjs.map +1 -1
- package/dist/surfaces/cli/sysexits.mjs +2 -1
- package/dist/surfaces/cli/sysexits.mjs.map +1 -1
- package/dist/surfaces/tui/app.mjs +25 -3
- package/dist/surfaces/tui/app.mjs.map +1 -1
- package/dist/surfaces/tui/display-derivation.mjs +23 -74
- package/dist/surfaces/tui/display-derivation.mjs.map +1 -1
- package/dist/surfaces/tui/event-log.mjs +35 -23
- package/dist/surfaces/tui/event-log.mjs.map +1 -1
- package/dist/surfaces/tui/input.mjs +5 -1
- package/dist/surfaces/tui/input.mjs.map +1 -1
- package/dist/surfaces/tui/plain-renderer.mjs +70 -34
- package/dist/surfaces/tui/plain-renderer.mjs.map +1 -1
- package/package.json +24 -4
- package/dist/contracts/liveness-classifier.d.mts +0 -19
- package/dist/contracts/network-resolver.d.mts +0 -15
- package/dist/contracts/network-resolver.mjs +0 -7
- package/dist/contracts/network-resolver.mjs.map +0 -1
- package/dist/orchestrators/codegen/extras.mjs +0 -16
- package/dist/orchestrators/codegen/extras.mjs.map +0 -1
- package/dist/plugins/deepbook/routable.mjs +0 -21
- package/dist/plugins/deepbook/routable.mjs.map +0 -1
- package/dist/plugins/faucet/service.d.mts +0 -20
- package/dist/plugins/faucet/strategies/sui-local.d.mts +0 -23
- package/dist/plugins/faucet/strategies/sui-local.mjs.map +0 -1
- package/dist/plugins/sui/seed-objects.d.mts +0 -18
- package/dist/plugins/sui/seed-objects.mjs +0 -25
- package/dist/plugins/sui/seed-objects.mjs.map +0 -1
- package/dist/runtime/built-in-plugin-layers.mjs.map +0 -1
- package/dist/substrate/runtime/context-helpers.mjs +0 -32
- package/dist/substrate/runtime/context-helpers.mjs.map +0 -1
- package/dist/substrate/runtime/run.mjs.map +0 -1
- package/dist/substrate/runtime/strategy-registry/faucet-capability-for.mjs +0 -30
- package/dist/substrate/runtime/strategy-registry/faucet-capability-for.mjs.map +0 -1
- package/dist/substrate/runtime/supervisor.d.mts +0 -1
- package/dist/substrate/runtime/supervisor.mjs +0 -831
- package/dist/substrate/runtime/supervisor.mjs.map +0 -1
- package/dist/surfaces/cli/commands/doctor-probes.mjs.map +0 -1
- /package/dist/{substrate/runtime/strategy-registry/faucet-capability-for.d.mts → plugins/faucet/http.d.mts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Stream } from "effect";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logs.mjs","names":[],"sources":["../../../src/runtime/docker/logs.ts"],"sourcesContent":["// `docker logs --follow` as an Effect Stream.\n//\n// Architecture invariant: per-line `Stream<string, …>` so consumers\n// can filter / promote levels / dedupe followers across hot-restart\n// cycles via the L1 per-line sink.\n//\n// We DON'T solve the process-global follower-dedupe problem here; the\n// supervisor's per-container-key registry is where dedupe lives.\n// This stream is the raw substrate.\n\nimport { Effect, Stream } from 'effect';\n\nimport { splitUtf8Lines } from '../../substrate/runtime/observability/process-lines.ts';\nimport { DockerHost, DockerSpawner } from './client.ts';\nimport { DaemonUnreachable, type DockerRuntimeError } from './errors.ts';\nimport { dockerCommand } from './client.ts';\n\nexport interface FollowLogsOptions {\n\treadonly since?: string;\n\treadonly tail?: number;\n}\n\n/** `docker logs --follow --timestamps <id>` projected to a per-line\n * Stream. Combined stdout+stderr (docker writes both to the same\n * follow stream).\n *\n * IMPORTANT: the stream completes when the container exits (docker\n * closes the pipe). Consumers that want to re-follow after a restart\n * must re-call this. */\nexport const followLogs = (\n\tcontainerNameOrId: string,\n\topts: FollowLogsOptions = {},\n): Stream.Stream<string, DockerRuntimeError, DockerHost | DockerSpawner> => {\n\tconst args: Array<string> = ['--follow', '--timestamps'];\n\tif (opts.since !== undefined) args.push('--since', opts.since);\n\tif (opts.tail !== undefined) args.push('--tail', String(opts.tail));\n\targs.push(containerNameOrId);\n\tconst mapSpawnError = (cause: unknown): DockerRuntimeError =>\n\t\tnew DaemonUnreachable({ op: 'docker.logs', detail: 'logs follow stream failed', cause });\n\treturn Stream.unwrap(\n\t\tEffect.gen(function* () {\n\t\t\tconst host = yield* DockerHost;\n\t\t\tconst spawner = yield* DockerSpawner;\n\t\t\tconst cmd = dockerCommand(host, 'logs', args);\n\t\t\tconst handle = yield* spawner.spawn(cmd).pipe(Effect.mapError(mapSpawnError));\n\t\t\t// Merge stdout + stderr so caller sees the unified follow stream;\n\t\t\t// docker prefixes each line with its source via --timestamps.\n\t\t\tconst lineStream = splitUtf8Lines(Stream.merge(handle.stdout, handle.stderr)).pipe(\n\t\t\t\tStream.mapError(mapSpawnError),\n\t\t\t);\n\t\t\treturn lineStream;\n\t\t}),\n\t);\n};\n\n
|
|
1
|
+
{"version":3,"file":"logs.mjs","names":[],"sources":["../../../src/runtime/docker/logs.ts"],"sourcesContent":["// `docker logs --follow` as an Effect Stream.\n//\n// Architecture invariant: per-line `Stream<string, …>` so consumers\n// can filter / promote levels / dedupe followers across hot-restart\n// cycles via the L1 per-line sink.\n//\n// We DON'T solve the process-global follower-dedupe problem here; the\n// supervisor's per-container-key registry is where dedupe lives.\n// This stream is the raw substrate.\n\nimport { Effect, Stream } from 'effect';\n\nimport { splitUtf8Lines } from '../../substrate/runtime/observability/process-lines.ts';\nimport { DockerHost, DockerSpawner } from './client.ts';\nimport { DaemonUnreachable, type DockerRuntimeError } from './errors.ts';\nimport { dockerCommand } from './client.ts';\n\nexport interface FollowLogsOptions {\n\treadonly since?: string;\n\treadonly tail?: number;\n}\n\n/** `docker logs --follow --timestamps <id>` projected to a per-line\n * Stream. Combined stdout+stderr (docker writes both to the same\n * follow stream).\n *\n * IMPORTANT: the stream completes when the container exits (docker\n * closes the pipe). Consumers that want to re-follow after a restart\n * must re-call this. */\nexport const followLogs = (\n\tcontainerNameOrId: string,\n\topts: FollowLogsOptions = {},\n): Stream.Stream<string, DockerRuntimeError, DockerHost | DockerSpawner> => {\n\tconst args: Array<string> = ['--follow', '--timestamps'];\n\tif (opts.since !== undefined) args.push('--since', opts.since);\n\tif (opts.tail !== undefined) args.push('--tail', String(opts.tail));\n\targs.push(containerNameOrId);\n\tconst mapSpawnError = (cause: unknown): DockerRuntimeError =>\n\t\tnew DaemonUnreachable({ op: 'docker.logs', detail: 'logs follow stream failed', cause });\n\treturn Stream.unwrap(\n\t\tEffect.gen(function* () {\n\t\t\tconst host = yield* DockerHost;\n\t\t\tconst spawner = yield* DockerSpawner;\n\t\t\tconst cmd = dockerCommand(host, 'logs', args);\n\t\t\tconst handle = yield* spawner.spawn(cmd).pipe(Effect.mapError(mapSpawnError));\n\t\t\t// Merge stdout + stderr so caller sees the unified follow stream;\n\t\t\t// docker prefixes each line with its source via --timestamps.\n\t\t\tconst lineStream = splitUtf8Lines(Stream.merge(handle.stdout, handle.stderr)).pipe(\n\t\t\t\tStream.mapError(mapSpawnError),\n\t\t\t);\n\t\t\treturn lineStream;\n\t\t}),\n\t);\n};\n\n"],"mappings":";;;;;;;;;;;;AA6BA,MAAa,cACZ,mBACA,OAA0B,EAAE,KAC+C;CAC3E,MAAM,OAAsB,CAAC,YAAY,eAAe;AACxD,KAAI,KAAK,UAAU,KAAA,EAAW,MAAK,KAAK,WAAW,KAAK,MAAM;AAC9D,KAAI,KAAK,SAAS,KAAA,EAAW,MAAK,KAAK,UAAU,OAAO,KAAK,KAAK,CAAC;AACnE,MAAK,KAAK,kBAAkB;CAC5B,MAAM,iBAAiB,UACtB,IAAI,kBAAkB;EAAE,IAAI;EAAe,QAAQ;EAA6B;EAAO,CAAC;AACzF,QAAO,OAAO,OACb,OAAO,IAAI,aAAa;EACvB,MAAM,OAAO,OAAO;EACpB,MAAM,UAAU,OAAO;EACvB,MAAM,MAAM,cAAc,MAAM,QAAQ,KAAK;EAC7C,MAAM,SAAS,OAAO,QAAQ,MAAM,IAAI,CAAC,KAAK,OAAO,SAAS,cAAc,CAAC;AAM7E,SAHmB,eAAe,OAAO,MAAM,OAAO,QAAQ,OAAO,OAAO,CAAC,CAAC,KAC7E,OAAO,SAAS,cAAc,CAEd;GAChB,CACF"}
|
|
@@ -1,55 +1,45 @@
|
|
|
1
1
|
import { decodeJsonArrayElementSync } from "../../substrate/runtime/runtime-decode.mjs";
|
|
2
2
|
import { dockerRun, dockerRunOk } from "./client.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { ForeignDockerResource, NetworkIpReadbackTimeout, NetworkOperationFailed } from "./errors.mjs";
|
|
4
|
+
import { isAlreadyInNetworkStderr, isMissingNetworkStderr, isNetworkAlreadyExistsStderr, wrapNetworkError } from "./wrap.mjs";
|
|
5
|
+
import { dockerInspectAndDecode } from "./inspect-and-decode.mjs";
|
|
6
|
+
import { expectedNetworkOwnershipLabels, ownershipMismatchDetail, readLabels, renderNetworkLabels } from "./labels.mjs";
|
|
5
7
|
import { ProbeTimeoutError, waitForProbe } from "../../substrate/runtime/probes.mjs";
|
|
6
|
-
import { isAlreadyInNetworkStderr, isDaemonUnreachableStderr, wrapNetworkError } from "./wrap.mjs";
|
|
7
8
|
import { Effect, Schema } from "effect";
|
|
8
9
|
//#region src/runtime/docker/network.ts
|
|
9
|
-
const readLabels = (raw) => {
|
|
10
|
-
if (raw === null || typeof raw !== "object") return {};
|
|
11
|
-
const out = {};
|
|
12
|
-
for (const [key, value] of Object.entries(raw)) if (typeof value === "string") out[key] = value;
|
|
13
|
-
return out;
|
|
14
|
-
};
|
|
15
10
|
const NetworkInspectSchema = Schema.Struct({
|
|
16
11
|
Id: Schema.String,
|
|
17
|
-
Labels: Schema.optional(Schema.Unknown)
|
|
12
|
+
Labels: Schema.optional(Schema.Unknown),
|
|
13
|
+
Containers: Schema.optional(Schema.Unknown)
|
|
18
14
|
});
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
if (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
resource: "network",
|
|
30
|
-
name,
|
|
31
|
-
stderr: res.stderr,
|
|
32
|
-
exitCode: res.exitCode
|
|
33
|
-
}));
|
|
34
|
-
}
|
|
35
|
-
try {
|
|
36
|
-
const decoded = decodeJsonArrayElementSync(NetworkInspectSchema, res.stdout, {
|
|
37
|
-
source: `docker network inspect ${name}`,
|
|
38
|
-
missingMessage: "inspect returned an empty result",
|
|
39
|
-
mkError: (issue) => new DockerInspectDecodeFailed({
|
|
40
|
-
resource: "network",
|
|
41
|
-
name,
|
|
42
|
-
detail: issue.message === "inspect returned an empty result" ? issue.message : "inspect returned malformed network JSON",
|
|
43
|
-
cause: issue.cause
|
|
44
|
-
})
|
|
15
|
+
const readContainers = (raw) => {
|
|
16
|
+
if (raw === null || typeof raw !== "object") return [];
|
|
17
|
+
const out = [];
|
|
18
|
+
for (const [id, value] of Object.entries(raw)) {
|
|
19
|
+
if (value === null || typeof value !== "object") continue;
|
|
20
|
+
const name = value.Name;
|
|
21
|
+
if (typeof name !== "string" || name.length === 0) continue;
|
|
22
|
+
out.push({
|
|
23
|
+
id,
|
|
24
|
+
name
|
|
45
25
|
});
|
|
46
|
-
return {
|
|
47
|
-
id: decoded.Id,
|
|
48
|
-
labels: readLabels(decoded.Labels)
|
|
49
|
-
};
|
|
50
|
-
} catch (cause) {
|
|
51
|
-
return yield* Effect.fail(cause);
|
|
52
26
|
}
|
|
27
|
+
return out;
|
|
28
|
+
};
|
|
29
|
+
const inspectNetwork = (name) => Effect.gen(function* () {
|
|
30
|
+
const decoded = yield* dockerInspectAndDecode({
|
|
31
|
+
resourceKind: "network",
|
|
32
|
+
name,
|
|
33
|
+
op: "docker.network.inspect",
|
|
34
|
+
inspectCommand: dockerRunOk("network", ["inspect", name]).pipe(Effect.mapError(wrapNetworkError("inspect", name))),
|
|
35
|
+
schema: NetworkInspectSchema,
|
|
36
|
+
isMissingStderr: isMissingNetworkStderr
|
|
37
|
+
});
|
|
38
|
+
if (decoded === null) return null;
|
|
39
|
+
return {
|
|
40
|
+
id: decoded.Id,
|
|
41
|
+
labels: readLabels(decoded.Labels)
|
|
42
|
+
};
|
|
53
43
|
});
|
|
54
44
|
const assertNetworkOwned = (name, facts, opts) => Effect.gen(function* () {
|
|
55
45
|
const expected = expectedNetworkOwnershipLabels(opts.app, opts.stack);
|
|
@@ -82,15 +72,29 @@ const ensureNetwork = (name, opts) => Effect.gen(function* () {
|
|
|
82
72
|
...gatewayArgs,
|
|
83
73
|
...labelArgs,
|
|
84
74
|
name
|
|
85
|
-
]).pipe(Effect.mapError(wrapNetworkError("create", name)))).stdout.trim();
|
|
75
|
+
]).pipe(Effect.mapError(wrapNetworkError("create", name)), Effect.catchTag("NetworkOperationFailed", (err) => err.op === "create" && isNetworkAlreadyExistsStderr(err.stderr) ? adoptExistingNetwork(name, opts, err) : Effect.fail(err)))).stdout.trim();
|
|
86
76
|
}).pipe(Effect.withSpan("runtime.docker.network.ensure"));
|
|
77
|
+
/** Concurrent-create-loses recovery: a peer created the network between
|
|
78
|
+
* our inspect-miss and our `create`. Re-inspect, assert it carries our
|
|
79
|
+
* ownership labels, and return its id wrapped as a synthetic create
|
|
80
|
+
* `CaptureResult` (so the caller's `.stdout.trim()` reads the adopted
|
|
81
|
+
* id). A foreign/unowned network surfaces the ownership error; a vanished
|
|
82
|
+
* network (peer pruned it between create and re-inspect) re-surfaces the
|
|
83
|
+
* original typed create failure for the boot to retry. */
|
|
84
|
+
const adoptExistingNetwork = (name, opts, createFailure) => Effect.gen(function* () {
|
|
85
|
+
const adopted = yield* inspectNetwork(name);
|
|
86
|
+
if (adopted === null) return yield* Effect.fail(createFailure);
|
|
87
|
+
yield* assertNetworkOwned(name, adopted, opts);
|
|
88
|
+
return { stdout: adopted.id };
|
|
89
|
+
});
|
|
87
90
|
/** Idempotent `docker network connect`. Treats "already exists in
|
|
88
91
|
* network" stderr as success — architecture mandates idempotency on
|
|
89
|
-
* this verb.
|
|
90
|
-
|
|
92
|
+
* this verb. Multiple `--alias` flags register additional DNS names
|
|
93
|
+
* siblings can dial under the network. */
|
|
94
|
+
const connect = (containerNameOrId, network, aliases) => Effect.gen(function* () {
|
|
91
95
|
const res = yield* dockerRunOk("network", [
|
|
92
96
|
"connect",
|
|
93
|
-
...alias
|
|
97
|
+
...(aliases ?? []).flatMap((alias) => ["--alias", alias]),
|
|
94
98
|
network,
|
|
95
99
|
containerNameOrId
|
|
96
100
|
]).pipe(Effect.mapError(wrapNetworkError("connect", network)));
|
|
@@ -102,6 +106,38 @@ const connect = (containerNameOrId, network, alias) => Effect.gen(function* () {
|
|
|
102
106
|
stderr: res.stderr
|
|
103
107
|
}));
|
|
104
108
|
}).pipe(Effect.withSpan("runtime.docker.network.connect"));
|
|
109
|
+
/** Force-disconnect — `docker network disconnect -f`. Used by prune
|
|
110
|
+
* to evict our own endpoints from an in-use network before retrying
|
|
111
|
+
* `network rm`. Idempotent against "not connected". */
|
|
112
|
+
const forceDisconnect = (containerNameOrId, network) => Effect.gen(function* () {
|
|
113
|
+
const res = yield* dockerRunOk("network", [
|
|
114
|
+
"disconnect",
|
|
115
|
+
"-f",
|
|
116
|
+
network,
|
|
117
|
+
containerNameOrId
|
|
118
|
+
]).pipe(Effect.mapError(wrapNetworkError("disconnect", network)));
|
|
119
|
+
if (res.exitCode !== 0 && !/is not connected/i.test(res.stderr)) return yield* Effect.fail(new NetworkOperationFailed({
|
|
120
|
+
op: "disconnect",
|
|
121
|
+
network,
|
|
122
|
+
stderr: res.stderr
|
|
123
|
+
}));
|
|
124
|
+
}).pipe(Effect.withSpan("runtime.docker.network.forceDisconnect"));
|
|
125
|
+
/** List the endpoints currently attached to a network. Returns an
|
|
126
|
+
* empty list when the network is missing. Used by prune to decide
|
|
127
|
+
* whether to force-disconnect own endpoints or report foreign
|
|
128
|
+
* holders. */
|
|
129
|
+
const listAttachedContainers = (name) => Effect.gen(function* () {
|
|
130
|
+
const decoded = yield* dockerInspectAndDecode({
|
|
131
|
+
resourceKind: "network",
|
|
132
|
+
name,
|
|
133
|
+
op: "docker.network.inspect",
|
|
134
|
+
inspectCommand: dockerRunOk("network", ["inspect", name]).pipe(Effect.mapError(wrapNetworkError("inspect", name))),
|
|
135
|
+
schema: NetworkInspectSchema,
|
|
136
|
+
isMissingStderr: isMissingNetworkStderr
|
|
137
|
+
});
|
|
138
|
+
if (decoded === null) return [];
|
|
139
|
+
return readContainers(decoded.Containers);
|
|
140
|
+
}).pipe(Effect.withSpan("runtime.docker.network.listAttachedContainers"));
|
|
105
141
|
/** Schema of the small JSON slice of `docker inspect` we read for the
|
|
106
142
|
* network-membership / IP shape. */
|
|
107
143
|
const InspectNetworkSettings = Schema.Struct({ NetworkSettings: Schema.Struct({ Networks: Schema.Record(Schema.String, Schema.Struct({
|
|
@@ -163,6 +199,6 @@ const readIps = (containerNameOrId) => Effect.gen(function* () {
|
|
|
163
199
|
}
|
|
164
200
|
}).pipe(Effect.withSpan("runtime.docker.network.readIps"));
|
|
165
201
|
//#endregion
|
|
166
|
-
export { connect, ensureNetwork, readIps, waitForIp };
|
|
202
|
+
export { connect, ensureNetwork, forceDisconnect, listAttachedContainers, readIps, waitForIp };
|
|
167
203
|
|
|
168
204
|
//# sourceMappingURL=network.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network.mjs","names":[],"sources":["../../../src/runtime/docker/network.ts"],"sourcesContent":["// Docker network lifecycle.\n//\n// Architecture § Docker backend § Networking:\n// - ONE shared `devstack` network per host (cross-stack). Other\n// per-stack secondary networks are allowed by callers, but the\n// default surface assumes the shared bridge.\n// - `network connect` is idempotent — \"already exists in network\"\n// stderr is success (see `wrap.ts` classifier).\n// - `network connect` settle is ASYNCHRONOUS in docker — the\n// endpoint is registered before the IP is allocated. Callers must\n// wait for IP readback (see §5 and `waitForIp`).\n// - `network create` registers NO finalizer; the network outlives\n// individual stacks so resume into a stopped container reattaches\n// to the same bridge id. Cleanup is via `wipe` / `prune`.\n//\n// Surface:\n// - `ensureNetwork(name, opts)` — idempotent create\n// - `connect(container, network, alias?)` — idempotent attach\n// - `disconnect(container, network)` — idempotent detach\n// - `waitForIp(container, network, opts)` — bounded poll for IP\n\nimport { Effect, Schema } from 'effect';\n\nimport { DockerHost, DockerSpawner, dockerRun, dockerRunOk } from './client.ts';\nimport { ProbeTimeoutError, waitForProbe } from '../../substrate/runtime/probes.ts';\nimport { decodeJsonArrayElementSync } from '../../substrate/runtime/runtime-decode.ts';\nimport {\n\tDockerInspectDecodeFailed,\n\tDockerInspectFailed,\n\tDaemonUnreachable,\n\ttype DockerRuntimeError,\n\tForeignDockerResource,\n\tNetworkIpReadbackTimeout,\n\tNetworkOperationFailed,\n} from './errors.ts';\nimport {\n\texpectedNetworkOwnershipLabels,\n\townershipMismatchDetail,\n\trenderNetworkLabels,\n} from './labels.ts';\nimport { isAlreadyInNetworkStderr, isDaemonUnreachableStderr, wrapNetworkError } from './wrap.ts';\n\n/** The cross-host shared network name. Architecture-mandated single\n * bridge per host. Callers can target other networks (per-stack) but\n * this is the constant for the shared one. */\nexport const SHARED_NETWORK_NAME = 'devstack';\n\nexport interface EnsureNetworkOptions {\n\treadonly app: string;\n\treadonly stack: string;\n\treadonly subnet?: string;\n\treadonly gateway?: string;\n\treadonly driver?: 'bridge' | 'host' | 'overlay';\n\treadonly composeUi?: boolean;\n}\n\ninterface NetworkInspectFacts {\n\treadonly id: string;\n\treadonly labels: Readonly<Record<string, string>>;\n}\n\nconst readLabels = (raw: unknown): Readonly<Record<string, string>> => {\n\tif (raw === null || typeof raw !== 'object') return {};\n\tconst out: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(raw)) {\n\t\tif (typeof value === 'string') out[key] = value;\n\t}\n\treturn out;\n};\n\nconst NetworkInspectSchema = Schema.Struct({\n\tId: Schema.String,\n\tLabels: Schema.optional(Schema.Unknown),\n});\n\nconst isNoSuchNetworkStderr = (stderr: string): boolean =>\n\t/no such network|network .* not found|not found/i.test(stderr);\n\nconst inspectNetwork = (\n\tname: string,\n): Effect.Effect<NetworkInspectFacts | null, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst res = yield* dockerRunOk('network', ['inspect', name]).pipe(\n\t\t\tEffect.mapError(wrapNetworkError('inspect', name)),\n\t\t);\n\t\tif (res.exitCode !== 0) {\n\t\t\tif (isNoSuchNetworkStderr(res.stderr)) return null;\n\t\t\tif (isDaemonUnreachableStderr(res.stderr)) {\n\t\t\t\treturn yield* Effect.fail(\n\t\t\t\t\tnew DaemonUnreachable({\n\t\t\t\t\t\top: 'docker.network.inspect',\n\t\t\t\t\t\tdetail: 'docker daemon unreachable',\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew DockerInspectFailed({\n\t\t\t\t\tresource: 'network',\n\t\t\t\t\tname,\n\t\t\t\t\tstderr: res.stderr,\n\t\t\t\t\texitCode: res.exitCode,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\ttry {\n\t\t\tconst decoded = decodeJsonArrayElementSync(NetworkInspectSchema, res.stdout, {\n\t\t\t\tsource: `docker network inspect ${name}`,\n\t\t\t\tmissingMessage: 'inspect returned an empty result',\n\t\t\t\tmkError: (issue) =>\n\t\t\t\t\tnew DockerInspectDecodeFailed({\n\t\t\t\t\t\tresource: 'network',\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdetail:\n\t\t\t\t\t\t\tissue.message === 'inspect returned an empty result'\n\t\t\t\t\t\t\t\t? issue.message\n\t\t\t\t\t\t\t\t: 'inspect returned malformed network JSON',\n\t\t\t\t\t\tcause: issue.cause,\n\t\t\t\t\t}),\n\t\t\t});\n\t\t\treturn { id: decoded.Id, labels: readLabels(decoded.Labels) };\n\t\t} catch (cause) {\n\t\t\treturn yield* Effect.fail(cause as DockerRuntimeError);\n\t\t}\n\t});\n\nconst assertNetworkOwned = (\n\tname: string,\n\tfacts: NetworkInspectFacts,\n\topts: EnsureNetworkOptions,\n): Effect.Effect<void, DockerRuntimeError> =>\n\tEffect.gen(function* () {\n\t\tconst expected = expectedNetworkOwnershipLabels(opts.app, opts.stack);\n\t\tconst mismatch = ownershipMismatchDetail(expected, facts.labels);\n\t\tif (mismatch !== null) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew ForeignDockerResource({\n\t\t\t\t\tresource: 'network',\n\t\t\t\t\tname,\n\t\t\t\t\texpected,\n\t\t\t\t\tactual: facts.labels,\n\t\t\t\t\tdetail: mismatch,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t});\n\n// -----------------------------------------------------------------------------\n// Create / inspect\n// -----------------------------------------------------------------------------\n\n/** Idempotent `docker network create`. Returns the network's id (or\n * the pre-existing id). Architecture: NO scope finalizer — networks\n * outlive the supervisor. */\nexport const ensureNetwork = (\n\tname: string,\n\topts: EnsureNetworkOptions,\n): Effect.Effect<string, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst probe = yield* inspectNetwork(name);\n\t\tif (probe !== null) {\n\t\t\tyield* assertNetworkOwned(name, probe, opts);\n\t\t\treturn probe.id;\n\t\t}\n\t\t// Create with full label stamp.\n\t\tconst labelArgs = renderNetworkLabels(name, opts.app, opts.stack, {\n\t\t\tcomposeUi: opts.composeUi,\n\t\t}).flatMap((l) => ['--label', l]);\n\t\tconst driverArgs = opts.driver ? ['--driver', opts.driver] : [];\n\t\tconst subnetArgs = opts.subnet ? ['--subnet', opts.subnet] : [];\n\t\tconst gatewayArgs = opts.gateway ? ['--gateway', opts.gateway] : [];\n\t\tconst created = yield* dockerRun('network', [\n\t\t\t'create',\n\t\t\t...driverArgs,\n\t\t\t...subnetArgs,\n\t\t\t...gatewayArgs,\n\t\t\t...labelArgs,\n\t\t\tname,\n\t\t]).pipe(Effect.mapError(wrapNetworkError('create', name)));\n\t\treturn created.stdout.trim();\n\t}).pipe(Effect.withSpan('runtime.docker.network.ensure'));\n\n// -----------------------------------------------------------------------------\n// Connect / disconnect\n// -----------------------------------------------------------------------------\n\n/** Idempotent `docker network connect`. Treats \"already exists in\n * network\" stderr as success — architecture mandates idempotency on\n * this verb. */\nexport const connect = (\n\tcontainerNameOrId: string,\n\tnetwork: string,\n\talias?: string,\n): Effect.Effect<void, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst aliasArgs = alias ? ['--alias', alias] : [];\n\t\tconst res = yield* dockerRunOk('network', [\n\t\t\t'connect',\n\t\t\t...aliasArgs,\n\t\t\tnetwork,\n\t\t\tcontainerNameOrId,\n\t\t]).pipe(Effect.mapError(wrapNetworkError('connect', network)));\n\t\tif (res.exitCode === 0) return;\n\t\tif (isAlreadyInNetworkStderr(res.stderr)) return;\n\t\t// Non-idempotent failure path.\n\t\treturn yield* Effect.fail(\n\t\t\tnew NetworkOperationFailed({ op: 'connect', network, stderr: res.stderr }),\n\t\t);\n\t}).pipe(Effect.withSpan('runtime.docker.network.connect'));\n\nexport const disconnect = (\n\tcontainerNameOrId: string,\n\tnetwork: string,\n): Effect.Effect<void, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst res = yield* dockerRunOk('network', ['disconnect', network, containerNameOrId]).pipe(\n\t\t\tEffect.mapError(wrapNetworkError('disconnect', network)),\n\t\t);\n\t\t// \"is not connected\" is also idempotent success on the\n\t\t// disconnect side; we treat any non-fatal stderr as success here\n\t\t// since the postcondition (not connected) holds.\n\t\tif (res.exitCode !== 0 && !/is not connected/i.test(res.stderr)) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew NetworkOperationFailed({ op: 'disconnect', network, stderr: res.stderr }),\n\t\t\t);\n\t\t}\n\t}).pipe(Effect.withSpan('runtime.docker.network.disconnect'));\n\n// -----------------------------------------------------------------------------\n// IP readback\n// -----------------------------------------------------------------------------\n\n/** Schema of the small JSON slice of `docker inspect` we read for the\n * network-membership / IP shape. */\nconst InspectNetworkSettings = Schema.Struct({\n\tNetworkSettings: Schema.Struct({\n\t\tNetworks: Schema.Record(\n\t\t\tSchema.String,\n\t\t\tSchema.Struct({\n\t\t\t\tIPAddress: Schema.optional(Schema.String),\n\t\t\t\tNetworkID: Schema.optional(Schema.String),\n\t\t\t}),\n\t\t),\n\t}),\n});\n\nconst DEFAULT_IP_POLL_BUDGET_MILLIS = 3_000;\nconst DEFAULT_IP_POLL_INTERVAL_MILLIS = 100;\n\nexport interface WaitForIpOptions {\n\treadonly budgetMillis?: number;\n\treadonly intervalMillis?: number;\n}\n\n/** Poll `docker inspect` until the container has a non-empty IP on\n * `network`. Architecture §5 — async network-connect settle. */\nexport const waitForIp = (\n\tcontainerNameOrId: string,\n\tnetwork: string,\n\topts: WaitForIpOptions = {},\n): Effect.Effect<string, DockerRuntimeError, DockerHost | DockerSpawner> => {\n\tconst budget = opts.budgetMillis ?? DEFAULT_IP_POLL_BUDGET_MILLIS;\n\tconst interval = opts.intervalMillis ?? DEFAULT_IP_POLL_INTERVAL_MILLIS;\n\tconst start = Date.now();\n\tlet foundIp: string | undefined;\n\treturn waitForProbe({\n\t\tlabel: `docker.network.ip:${containerNameOrId}:${network}`,\n\t\ttimeoutMs: budget,\n\t\tintervalMs: interval,\n\t\tisRetryableError: () => false,\n\t\tprobe: () =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst res = yield* dockerRunOk('inspect', [containerNameOrId]).pipe(\n\t\t\t\t\tEffect.mapError(wrapNetworkError('inspect', network)),\n\t\t\t\t);\n\t\t\t\tif (res.exitCode === 0) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst decoded = decodeJsonArrayElementSync(InspectNetworkSettings, res.stdout, {\n\t\t\t\t\t\t\tsource: `docker inspect ${containerNameOrId}`,\n\t\t\t\t\t\t\tmkError: (issue) => issue,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tconst slot = decoded.NetworkSettings.Networks[network];\n\t\t\t\t\t\tconst ip = slot?.IPAddress;\n\t\t\t\t\t\tif (ip && ip.length > 0) {\n\t\t\t\t\t\t\tfoundIp = ip;\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Malformed — fall through to retry.\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}),\n\t}).pipe(\n\t\tEffect.map(() => foundIp ?? ''),\n\t\tEffect.mapError((cause) => {\n\t\t\tif (cause instanceof ProbeTimeoutError) {\n\t\t\t\treturn new NetworkIpReadbackTimeout({\n\t\t\t\t\tcontainer: containerNameOrId,\n\t\t\t\t\tnetwork,\n\t\t\t\t\twaitedMillis: Date.now() - start,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn cause;\n\t\t}),\n\t\tEffect.withSpan('runtime.docker.network.waitForIp'),\n\t);\n};\n\n/** Read out ALL networks + IPs for a container. Used by the contract's\n * `ContainerHandle.ips`. */\nexport const readIps = (\n\tcontainerNameOrId: string,\n): Effect.Effect<ReadonlyArray<string>, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst res = yield* dockerRunOk('inspect', [containerNameOrId]).pipe(\n\t\t\tEffect.mapError(wrapNetworkError('inspect', containerNameOrId)),\n\t\t);\n\t\tif (res.exitCode !== 0) return [];\n\t\ttry {\n\t\t\tconst decoded = decodeJsonArrayElementSync(InspectNetworkSettings, res.stdout, {\n\t\t\t\tsource: `docker inspect ${containerNameOrId}`,\n\t\t\t\tmkError: (issue) => issue,\n\t\t\t});\n\t\t\tconst ips: Array<string> = [];\n\t\t\tfor (const slot of Object.values(decoded.NetworkSettings.Networks)) {\n\t\t\t\tif (slot.IPAddress && slot.IPAddress.length > 0) ips.push(slot.IPAddress);\n\t\t\t}\n\t\t\treturn ips;\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t}).pipe(Effect.withSpan('runtime.docker.network.readIps'));\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"network.mjs","names":[],"sources":["../../../src/runtime/docker/network.ts"],"sourcesContent":["// Docker network lifecycle.\n//\n// Architecture § Docker backend § Networking:\n// - ONE shared `devstack` network per host (cross-stack). Other\n// per-stack secondary networks are allowed by callers, but the\n// default surface assumes the shared bridge.\n// - `network connect` is idempotent — \"already exists in network\"\n// stderr is success (see `wrap.ts` classifier).\n// - `network connect` settle is ASYNCHRONOUS in docker — the\n// endpoint is registered before the IP is allocated. Callers must\n// wait for IP readback (see §5 and `waitForIp`).\n// - `network create` registers NO finalizer; the network outlives\n// individual stacks so resume into a stopped container reattaches\n// to the same bridge id. Cleanup is via `wipe` / `prune`.\n//\n// Surface:\n// - `ensureNetwork(name, opts)` — idempotent create\n// - `connect(container, network, alias?)` — idempotent attach\n// - `disconnect(container, network)` — idempotent detach\n// - `waitForIp(container, network, opts)` — bounded poll for IP\n\nimport { Effect, Schema } from 'effect';\n\nimport { DockerHost, DockerSpawner, dockerRun, dockerRunOk } from './client.ts';\nimport { ProbeTimeoutError, waitForProbe } from '../../substrate/runtime/probes.ts';\nimport { decodeJsonArrayElementSync } from '../../substrate/runtime/runtime-decode.ts';\nimport {\n\ttype DockerRuntimeError,\n\tForeignDockerResource,\n\tNetworkIpReadbackTimeout,\n\tNetworkOperationFailed,\n} from './errors.ts';\nimport { dockerInspectAndDecode } from './inspect-and-decode.ts';\nimport {\n\texpectedNetworkOwnershipLabels,\n\townershipMismatchDetail,\n\treadLabels,\n\trenderNetworkLabels,\n} from './labels.ts';\nimport {\n\tisAlreadyInNetworkStderr,\n\tisMissingNetworkStderr,\n\tisNetworkAlreadyExistsStderr,\n\twrapNetworkError,\n} from './wrap.ts';\n\n/** The cross-host shared network name. Architecture-mandated single\n * bridge per host. Callers can target other networks (per-stack) but\n * this is the constant for the shared one. */\nexport const SHARED_NETWORK_NAME = 'devstack';\n\nexport interface EnsureNetworkOptions {\n\treadonly app: string;\n\treadonly stack: string;\n\treadonly subnet?: string;\n\treadonly gateway?: string;\n\treadonly driver?: 'bridge' | 'host' | 'overlay';\n\treadonly composeUi?: boolean;\n}\n\ninterface NetworkInspectFacts {\n\treadonly id: string;\n\treadonly labels: Readonly<Record<string, string>>;\n}\n\nconst NetworkInspectSchema = Schema.Struct({\n\tId: Schema.String,\n\tLabels: Schema.optional(Schema.Unknown),\n\tContainers: Schema.optional(Schema.Unknown),\n});\n\n/** One endpoint attached to a network, as reported by `docker network\n * inspect`. `name` is the container name; `id` is the container id. */\nexport interface NetworkAttachedEndpoint {\n\treadonly id: string;\n\treadonly name: string;\n}\n\nconst readContainers = (raw: unknown): ReadonlyArray<NetworkAttachedEndpoint> => {\n\tif (raw === null || typeof raw !== 'object') return [];\n\tconst out: Array<NetworkAttachedEndpoint> = [];\n\tfor (const [id, value] of Object.entries(raw)) {\n\t\tif (value === null || typeof value !== 'object') continue;\n\t\tconst name = (value as { Name?: unknown }).Name;\n\t\tif (typeof name !== 'string' || name.length === 0) continue;\n\t\tout.push({ id, name });\n\t}\n\treturn out;\n};\n\nconst inspectNetwork = (\n\tname: string,\n): Effect.Effect<NetworkInspectFacts | null, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst decoded = yield* dockerInspectAndDecode({\n\t\t\tresourceKind: 'network',\n\t\t\tname,\n\t\t\top: 'docker.network.inspect',\n\t\t\tinspectCommand: dockerRunOk('network', ['inspect', name]).pipe(\n\t\t\t\tEffect.mapError(wrapNetworkError('inspect', name)),\n\t\t\t),\n\t\t\tschema: NetworkInspectSchema,\n\t\t\tisMissingStderr: isMissingNetworkStderr,\n\t\t});\n\t\tif (decoded === null) return null;\n\t\treturn { id: decoded.Id, labels: readLabels(decoded.Labels) };\n\t});\n\nconst assertNetworkOwned = (\n\tname: string,\n\tfacts: NetworkInspectFacts,\n\topts: EnsureNetworkOptions,\n): Effect.Effect<void, DockerRuntimeError> =>\n\tEffect.gen(function* () {\n\t\tconst expected = expectedNetworkOwnershipLabels(opts.app, opts.stack);\n\t\tconst mismatch = ownershipMismatchDetail(expected, facts.labels);\n\t\tif (mismatch !== null) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew ForeignDockerResource({\n\t\t\t\t\tresource: 'network',\n\t\t\t\t\tname,\n\t\t\t\t\texpected,\n\t\t\t\t\tactual: facts.labels,\n\t\t\t\t\tdetail: mismatch,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t});\n\n// -----------------------------------------------------------------------------\n// Create / inspect\n// -----------------------------------------------------------------------------\n\n/** Idempotent `docker network create`. Returns the network's id (or\n * the pre-existing id). Architecture: NO scope finalizer — networks\n * outlive the supervisor. */\nexport const ensureNetwork = (\n\tname: string,\n\topts: EnsureNetworkOptions,\n): Effect.Effect<string, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst probe = yield* inspectNetwork(name);\n\t\tif (probe !== null) {\n\t\t\tyield* assertNetworkOwned(name, probe, opts);\n\t\t\treturn probe.id;\n\t\t}\n\t\t// Create with full label stamp.\n\t\tconst labelArgs = renderNetworkLabels(name, opts.app, opts.stack, {\n\t\t\tcomposeUi: opts.composeUi,\n\t\t}).flatMap((l) => ['--label', l]);\n\t\tconst driverArgs = opts.driver ? ['--driver', opts.driver] : [];\n\t\tconst subnetArgs = opts.subnet ? ['--subnet', opts.subnet] : [];\n\t\tconst gatewayArgs = opts.gateway ? ['--gateway', opts.gateway] : [];\n\t\tconst created = yield* dockerRun('network', [\n\t\t\t'create',\n\t\t\t...driverArgs,\n\t\t\t...subnetArgs,\n\t\t\t...gatewayArgs,\n\t\t\t...labelArgs,\n\t\t\tname,\n\t\t]).pipe(\n\t\t\tEffect.mapError(wrapNetworkError('create', name)),\n\t\t\t// `docker network create` is NOT name-atomic and — unlike\n\t\t\t// containers, which lean on `--name` atomicity plus a per-name\n\t\t\t// lock — networks have no per-name lock. Two processes booting\n\t\t\t// against the shared `devstack` bridge can both pass the\n\t\t\t// inspect-miss above and both run `create`; the loser's daemon\n\t\t\t// stderr (\"network with name … already exists\" / a `Conflict`\n\t\t\t// envelope) is classified by `wrapNetworkError` as a generic\n\t\t\t// `NetworkOperationFailed`. Recover that ONE case here by\n\t\t\t// re-inspecting and adopting the winner's network — but only if\n\t\t\t// it carries OUR ownership labels. This mirrors the container\n\t\t\t// `startAndAdopt` adopt-on-collision shape: recover from the\n\t\t\t// typed collision error, re-read facts, assert ownership, then\n\t\t\t// return the existing id; a foreign/unowned network surfaces the\n\t\t\t// ownership error rather than being silently adopted.\n\t\t\tEffect.catchTag('NetworkOperationFailed', (err) =>\n\t\t\t\terr.op === 'create' && isNetworkAlreadyExistsStderr(err.stderr)\n\t\t\t\t\t? adoptExistingNetwork(name, opts, err)\n\t\t\t\t\t: Effect.fail(err),\n\t\t\t),\n\t\t);\n\t\treturn created.stdout.trim();\n\t}).pipe(Effect.withSpan('runtime.docker.network.ensure'));\n\n/** Concurrent-create-loses recovery: a peer created the network between\n * our inspect-miss and our `create`. Re-inspect, assert it carries our\n * ownership labels, and return its id wrapped as a synthetic create\n * `CaptureResult` (so the caller's `.stdout.trim()` reads the adopted\n * id). A foreign/unowned network surfaces the ownership error; a vanished\n * network (peer pruned it between create and re-inspect) re-surfaces the\n * original typed create failure for the boot to retry. */\nconst adoptExistingNetwork = (\n\tname: string,\n\topts: EnsureNetworkOptions,\n\tcreateFailure: NetworkOperationFailed,\n): Effect.Effect<{ readonly stdout: string }, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst adopted = yield* inspectNetwork(name);\n\t\tif (adopted === null) return yield* Effect.fail(createFailure);\n\t\tyield* assertNetworkOwned(name, adopted, opts);\n\t\treturn { stdout: adopted.id };\n\t});\n\n// -----------------------------------------------------------------------------\n// Connect / disconnect\n// -----------------------------------------------------------------------------\n\n/** Idempotent `docker network connect`. Treats \"already exists in\n * network\" stderr as success — architecture mandates idempotency on\n * this verb. Multiple `--alias` flags register additional DNS names\n * siblings can dial under the network. */\nexport const connect = (\n\tcontainerNameOrId: string,\n\tnetwork: string,\n\taliases?: ReadonlyArray<string>,\n): Effect.Effect<void, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst aliasArgs = (aliases ?? []).flatMap((alias) => ['--alias', alias]);\n\t\tconst res = yield* dockerRunOk('network', [\n\t\t\t'connect',\n\t\t\t...aliasArgs,\n\t\t\tnetwork,\n\t\t\tcontainerNameOrId,\n\t\t]).pipe(Effect.mapError(wrapNetworkError('connect', network)));\n\t\tif (res.exitCode === 0) return;\n\t\tif (isAlreadyInNetworkStderr(res.stderr)) return;\n\t\t// Non-idempotent failure path.\n\t\treturn yield* Effect.fail(\n\t\t\tnew NetworkOperationFailed({ op: 'connect', network, stderr: res.stderr }),\n\t\t);\n\t}).pipe(Effect.withSpan('runtime.docker.network.connect'));\n\nexport const disconnect = (\n\tcontainerNameOrId: string,\n\tnetwork: string,\n): Effect.Effect<void, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst res = yield* dockerRunOk('network', ['disconnect', network, containerNameOrId]).pipe(\n\t\t\tEffect.mapError(wrapNetworkError('disconnect', network)),\n\t\t);\n\t\t// \"is not connected\" is also idempotent success on the\n\t\t// disconnect side; we treat any non-fatal stderr as success here\n\t\t// since the postcondition (not connected) holds.\n\t\tif (res.exitCode !== 0 && !/is not connected/i.test(res.stderr)) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew NetworkOperationFailed({ op: 'disconnect', network, stderr: res.stderr }),\n\t\t\t);\n\t\t}\n\t}).pipe(Effect.withSpan('runtime.docker.network.disconnect'));\n\n/** Force-disconnect — `docker network disconnect -f`. Used by prune\n * to evict our own endpoints from an in-use network before retrying\n * `network rm`. Idempotent against \"not connected\". */\nexport const forceDisconnect = (\n\tcontainerNameOrId: string,\n\tnetwork: string,\n): Effect.Effect<void, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst res = yield* dockerRunOk('network', [\n\t\t\t'disconnect',\n\t\t\t'-f',\n\t\t\tnetwork,\n\t\t\tcontainerNameOrId,\n\t\t]).pipe(Effect.mapError(wrapNetworkError('disconnect', network)));\n\t\tif (res.exitCode !== 0 && !/is not connected/i.test(res.stderr)) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tnew NetworkOperationFailed({ op: 'disconnect', network, stderr: res.stderr }),\n\t\t\t);\n\t\t}\n\t}).pipe(Effect.withSpan('runtime.docker.network.forceDisconnect'));\n\n/** List the endpoints currently attached to a network. Returns an\n * empty list when the network is missing. Used by prune to decide\n * whether to force-disconnect own endpoints or report foreign\n * holders. */\nexport const listAttachedContainers = (\n\tname: string,\n): Effect.Effect<\n\tReadonlyArray<NetworkAttachedEndpoint>,\n\tDockerRuntimeError,\n\tDockerHost | DockerSpawner\n> =>\n\tEffect.gen(function* () {\n\t\tconst decoded = yield* dockerInspectAndDecode({\n\t\t\tresourceKind: 'network',\n\t\t\tname,\n\t\t\top: 'docker.network.inspect',\n\t\t\tinspectCommand: dockerRunOk('network', ['inspect', name]).pipe(\n\t\t\t\tEffect.mapError(wrapNetworkError('inspect', name)),\n\t\t\t),\n\t\t\tschema: NetworkInspectSchema,\n\t\t\tisMissingStderr: isMissingNetworkStderr,\n\t\t});\n\t\tif (decoded === null) return [];\n\t\treturn readContainers(decoded.Containers);\n\t}).pipe(Effect.withSpan('runtime.docker.network.listAttachedContainers'));\n\n// -----------------------------------------------------------------------------\n// IP readback\n// -----------------------------------------------------------------------------\n\n/** Schema of the small JSON slice of `docker inspect` we read for the\n * network-membership / IP shape. */\nconst InspectNetworkSettings = Schema.Struct({\n\tNetworkSettings: Schema.Struct({\n\t\tNetworks: Schema.Record(\n\t\t\tSchema.String,\n\t\t\tSchema.Struct({\n\t\t\t\tIPAddress: Schema.optional(Schema.String),\n\t\t\t\tNetworkID: Schema.optional(Schema.String),\n\t\t\t}),\n\t\t),\n\t}),\n});\n\nconst DEFAULT_IP_POLL_BUDGET_MILLIS = 3_000;\nconst DEFAULT_IP_POLL_INTERVAL_MILLIS = 100;\n\nexport interface WaitForIpOptions {\n\treadonly budgetMillis?: number;\n\treadonly intervalMillis?: number;\n}\n\n/** Poll `docker inspect` until the container has a non-empty IP on\n * `network`. Architecture §5 — async network-connect settle. */\nexport const waitForIp = (\n\tcontainerNameOrId: string,\n\tnetwork: string,\n\topts: WaitForIpOptions = {},\n): Effect.Effect<string, DockerRuntimeError, DockerHost | DockerSpawner> => {\n\tconst budget = opts.budgetMillis ?? DEFAULT_IP_POLL_BUDGET_MILLIS;\n\tconst interval = opts.intervalMillis ?? DEFAULT_IP_POLL_INTERVAL_MILLIS;\n\tconst start = Date.now();\n\tlet foundIp: string | undefined;\n\treturn waitForProbe({\n\t\tlabel: `docker.network.ip:${containerNameOrId}:${network}`,\n\t\ttimeoutMs: budget,\n\t\tintervalMs: interval,\n\t\tisRetryableError: () => false,\n\t\tprobe: () =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst res = yield* dockerRunOk('inspect', [containerNameOrId]).pipe(\n\t\t\t\t\tEffect.mapError(wrapNetworkError('inspect', network)),\n\t\t\t\t);\n\t\t\t\tif (res.exitCode === 0) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst decoded = decodeJsonArrayElementSync(InspectNetworkSettings, res.stdout, {\n\t\t\t\t\t\t\tsource: `docker inspect ${containerNameOrId}`,\n\t\t\t\t\t\t\tmkError: (issue) => issue,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tconst slot = decoded.NetworkSettings.Networks[network];\n\t\t\t\t\t\tconst ip = slot?.IPAddress;\n\t\t\t\t\t\tif (ip && ip.length > 0) {\n\t\t\t\t\t\t\tfoundIp = ip;\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Malformed — fall through to retry.\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}),\n\t}).pipe(\n\t\tEffect.map(() => foundIp ?? ''),\n\t\tEffect.mapError((cause) => {\n\t\t\tif (cause instanceof ProbeTimeoutError) {\n\t\t\t\treturn new NetworkIpReadbackTimeout({\n\t\t\t\t\tcontainer: containerNameOrId,\n\t\t\t\t\tnetwork,\n\t\t\t\t\twaitedMillis: Date.now() - start,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn cause;\n\t\t}),\n\t\tEffect.withSpan('runtime.docker.network.waitForIp'),\n\t);\n};\n\n/** Read out ALL networks + IPs for a container. Used by the contract's\n * `ContainerHandle.ips`. */\nexport const readIps = (\n\tcontainerNameOrId: string,\n): Effect.Effect<ReadonlyArray<string>, DockerRuntimeError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst res = yield* dockerRunOk('inspect', [containerNameOrId]).pipe(\n\t\t\tEffect.mapError(wrapNetworkError('inspect', containerNameOrId)),\n\t\t);\n\t\tif (res.exitCode !== 0) return [];\n\t\ttry {\n\t\t\tconst decoded = decodeJsonArrayElementSync(InspectNetworkSettings, res.stdout, {\n\t\t\t\tsource: `docker inspect ${containerNameOrId}`,\n\t\t\t\tmkError: (issue) => issue,\n\t\t\t});\n\t\t\tconst ips: Array<string> = [];\n\t\t\tfor (const slot of Object.values(decoded.NetworkSettings.Networks)) {\n\t\t\t\tif (slot.IPAddress && slot.IPAddress.length > 0) ips.push(slot.IPAddress);\n\t\t\t}\n\t\t\treturn ips;\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t}).pipe(Effect.withSpan('runtime.docker.network.readIps'));\n"],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
//#region src/runtime/docker/render-run-args.ts
|
|
2
|
+
const pushEnv = (args, env) => {
|
|
3
|
+
if (env === void 0) return;
|
|
4
|
+
for (const [k, v] of Object.entries(env)) args.push("--env", `${k}=${v}`);
|
|
5
|
+
};
|
|
6
|
+
const pushMounts = (args, mounts) => {
|
|
7
|
+
if (mounts === void 0) return;
|
|
8
|
+
for (const m of mounts) {
|
|
9
|
+
const ro = m.readonly ? ",readonly" : "";
|
|
10
|
+
args.push("--mount", `type=bind,source=${m.source},target=${m.target}${ro}`);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
const pushAddHosts = (args, addHosts) => {
|
|
14
|
+
if (addHosts === void 0) return;
|
|
15
|
+
for (const [host, ip] of Object.entries(addHosts)) args.push("--add-host", `${host}:${ip}`);
|
|
16
|
+
};
|
|
17
|
+
const pushLabels = (args, labels) => {
|
|
18
|
+
if (labels === void 0) return;
|
|
19
|
+
for (const l of labels) args.push("--label", l);
|
|
20
|
+
};
|
|
21
|
+
const pushPorts = (args, ports) => {
|
|
22
|
+
if (ports === void 0) return;
|
|
23
|
+
for (const p of ports) {
|
|
24
|
+
const hostPrefix = p.hostIp === void 0 ? "" : `${p.hostIp}:`;
|
|
25
|
+
args.push("-p", `${hostPrefix}${p.hostPort}:${p.containerPort}`);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
/** Render argv for `docker run --rm`-style one-shot invocations.
|
|
29
|
+
*
|
|
30
|
+
* Output order:
|
|
31
|
+
* `[--rm?] --name N [--network …] [--entrypoint …] [--user …]
|
|
32
|
+
* env… mount… label… add-host… <image> [argv…]`
|
|
33
|
+
*
|
|
34
|
+
* Order is load-bearing — callers' fake-docker tests assert against
|
|
35
|
+
* this exact sequence. */
|
|
36
|
+
const renderRunArgs = (spec) => {
|
|
37
|
+
const args = [];
|
|
38
|
+
if (!spec.keep) args.push("--rm");
|
|
39
|
+
args.push("--name", spec.name);
|
|
40
|
+
if (spec.network) args.push("--network", spec.network);
|
|
41
|
+
if (spec.entrypoint) args.push("--entrypoint", spec.entrypoint);
|
|
42
|
+
if (spec.user) args.push("--user", spec.user);
|
|
43
|
+
pushEnv(args, spec.env);
|
|
44
|
+
pushMounts(args, spec.mounts);
|
|
45
|
+
pushLabels(args, spec.labels);
|
|
46
|
+
pushAddHosts(args, spec.addHosts);
|
|
47
|
+
args.push(spec.image);
|
|
48
|
+
if (spec.argv) args.push(...spec.argv);
|
|
49
|
+
return args;
|
|
50
|
+
};
|
|
51
|
+
/** Render argv for `docker run -d`-style long-lived container create.
|
|
52
|
+
*
|
|
53
|
+
* Output order:
|
|
54
|
+
* `-d --name N label… env… -p… mount… [--network N --network-alias …]
|
|
55
|
+
* add-host… [--entrypoint …] <image> [command…]`
|
|
56
|
+
*
|
|
57
|
+
* Order is load-bearing — tests that snapshot the create argv assert
|
|
58
|
+
* against this exact sequence. */
|
|
59
|
+
const renderCreateArgs = (spec) => {
|
|
60
|
+
const args = [
|
|
61
|
+
"-d",
|
|
62
|
+
"--name",
|
|
63
|
+
spec.name
|
|
64
|
+
];
|
|
65
|
+
pushLabels(args, spec.labels);
|
|
66
|
+
pushEnv(args, spec.env);
|
|
67
|
+
pushPorts(args, spec.ports);
|
|
68
|
+
pushMounts(args, spec.mounts);
|
|
69
|
+
if (spec.network !== void 0) {
|
|
70
|
+
args.push("--network", spec.network.name);
|
|
71
|
+
for (const alias of spec.network.aliases ?? []) args.push("--network-alias", alias);
|
|
72
|
+
}
|
|
73
|
+
pushAddHosts(args, spec.addHosts);
|
|
74
|
+
if (spec.entrypoint) args.push("--entrypoint", spec.entrypoint);
|
|
75
|
+
args.push(spec.image);
|
|
76
|
+
if (spec.command) args.push(...spec.command);
|
|
77
|
+
return args;
|
|
78
|
+
};
|
|
79
|
+
//#endregion
|
|
80
|
+
export { renderCreateArgs, renderRunArgs };
|
|
81
|
+
|
|
82
|
+
//# sourceMappingURL=render-run-args.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-run-args.mjs","names":[],"sources":["../../../src/runtime/docker/render-run-args.ts"],"sourcesContent":["// `docker run` / `docker create` argv assembly.\n//\n// `dockerRunOneShot` (one-shot `docker run --rm`) and `freshCreate`\n// (long-lived `docker run -d` from `container.ts`) both flatten a\n// structured spec into the same repeating argv patterns —\n// `--env K=V`, `--mount type=bind,...`, `--add-host h:ip`, etc. The\n// flag order differs between the two consumers and that order is\n// load-bearing for byte-identical migration (tests assert exact\n// argv strings), so this module exposes:\n//\n// - `renderRunArgs` — argv shape used by `dockerRunOneShot`.\n// - `renderCreateArgs` — argv shape used by `freshCreate`.\n//\n// Both share the internal per-flag emit helpers so the repeated\n// patterns live in one place. New Docker-run-style call sites should\n// pick whichever helper matches the order they want (or extend this\n// module rather than open-coding `args.push('--env', ...)` again).\n\n// -----------------------------------------------------------------------------\n// Shared flag shapes\n// -----------------------------------------------------------------------------\n\n/** `--mount type=bind,source=...,target=...[,readonly]`. */\nexport interface BindMountSpec {\n\treadonly source: string;\n\treadonly target: string;\n\treadonly readonly?: boolean;\n}\n\n/** `-p [hostIp:]hostPort:containerPort`. Mirrors `ContainerPortPublish`\n * but kept independent so this module has no upward dep on\n * `contracts/`. */\nexport interface PortPublishSpec {\n\treadonly containerPort: number;\n\treadonly hostPort: number;\n\treadonly hostIp?: string;\n}\n\n/** First-network attachment + optional per-network DNS aliases. */\nexport interface NetworkAttachSpec {\n\treadonly name: string;\n\treadonly aliases?: ReadonlyArray<string>;\n}\n\n// -----------------------------------------------------------------------------\n// Per-flag emit helpers — internal\n// -----------------------------------------------------------------------------\n\nconst pushEnv = (args: Array<string>, env: Readonly<Record<string, string>> | undefined): void => {\n\tif (env === undefined) return;\n\tfor (const [k, v] of Object.entries(env)) {\n\t\targs.push('--env', `${k}=${v}`);\n\t}\n};\n\nconst pushMounts = (\n\targs: Array<string>,\n\tmounts: ReadonlyArray<BindMountSpec> | undefined,\n): void => {\n\tif (mounts === undefined) return;\n\tfor (const m of mounts) {\n\t\tconst ro = m.readonly ? ',readonly' : '';\n\t\targs.push('--mount', `type=bind,source=${m.source},target=${m.target}${ro}`);\n\t}\n};\n\nconst pushAddHosts = (\n\targs: Array<string>,\n\taddHosts: Readonly<Record<string, string>> | undefined,\n): void => {\n\tif (addHosts === undefined) return;\n\tfor (const [host, ip] of Object.entries(addHosts)) {\n\t\targs.push('--add-host', `${host}:${ip}`);\n\t}\n};\n\nconst pushLabels = (args: Array<string>, labels: ReadonlyArray<string> | undefined): void => {\n\tif (labels === undefined) return;\n\tfor (const l of labels) args.push('--label', l);\n};\n\nconst pushPorts = (\n\targs: Array<string>,\n\tports: ReadonlyArray<PortPublishSpec> | undefined,\n): void => {\n\tif (ports === undefined) return;\n\tfor (const p of ports) {\n\t\tconst hostPrefix = p.hostIp === undefined ? '' : `${p.hostIp}:`;\n\t\targs.push('-p', `${hostPrefix}${p.hostPort}:${p.containerPort}`);\n\t}\n};\n\n// -----------------------------------------------------------------------------\n// `renderRunArgs` — one-shot `docker run --rm`\n// -----------------------------------------------------------------------------\n\n/** Spec for `renderRunArgs`. Mirrors what `dockerRunOneShot` already\n * flattens. Order of the resulting argv is fixed by `renderRunArgs`. */\nexport interface RenderRunArgsSpec {\n\t/** Drop `--rm` when true (forensic-retention escape hatch). */\n\treadonly keep?: boolean;\n\treadonly name: string;\n\treadonly image: string;\n\t/** Positional argv appended after the image. */\n\treadonly argv?: ReadonlyArray<string>;\n\treadonly network?: string;\n\treadonly entrypoint?: string;\n\treadonly user?: string;\n\treadonly env?: Readonly<Record<string, string>>;\n\treadonly mounts?: ReadonlyArray<BindMountSpec>;\n\t/** Pre-rendered `key=value` strings. */\n\treadonly labels?: ReadonlyArray<string>;\n\treadonly addHosts?: Readonly<Record<string, string>>;\n}\n\n/** Render argv for `docker run --rm`-style one-shot invocations.\n *\n * Output order:\n * `[--rm?] --name N [--network …] [--entrypoint …] [--user …]\n * env… mount… label… add-host… <image> [argv…]`\n *\n * Order is load-bearing — callers' fake-docker tests assert against\n * this exact sequence. */\nexport const renderRunArgs = (spec: RenderRunArgsSpec): ReadonlyArray<string> => {\n\tconst args: Array<string> = [];\n\tif (!spec.keep) args.push('--rm');\n\targs.push('--name', spec.name);\n\tif (spec.network) args.push('--network', spec.network);\n\tif (spec.entrypoint) args.push('--entrypoint', spec.entrypoint);\n\tif (spec.user) args.push('--user', spec.user);\n\tpushEnv(args, spec.env);\n\tpushMounts(args, spec.mounts);\n\tpushLabels(args, spec.labels);\n\tpushAddHosts(args, spec.addHosts);\n\targs.push(spec.image);\n\tif (spec.argv) args.push(...spec.argv);\n\treturn args;\n};\n\n// -----------------------------------------------------------------------------\n// `renderCreateArgs` — long-lived `docker run -d`\n// -----------------------------------------------------------------------------\n\n/** Spec for `renderCreateArgs`. Used by `freshCreate` in\n * `container.ts`. Long-lived containers always run detached. */\nexport interface RenderCreateArgsSpec {\n\treadonly name: string;\n\treadonly image: string;\n\t/** Positional argv appended after the image. */\n\treadonly command?: ReadonlyArray<string>;\n\t/** First network attach — emitted via `--network`. Per-network\n\t * aliases become `--network-alias` flags. Secondary attaches are\n\t * done post-start by the caller (architecture §5). */\n\treadonly network?: NetworkAttachSpec;\n\treadonly entrypoint?: string;\n\treadonly env?: Readonly<Record<string, string>>;\n\treadonly mounts?: ReadonlyArray<BindMountSpec>;\n\treadonly ports?: ReadonlyArray<PortPublishSpec>;\n\t/** Pre-rendered `key=value` strings (typically from `renderContainerLabels`). */\n\treadonly labels?: ReadonlyArray<string>;\n\treadonly addHosts?: Readonly<Record<string, string>>;\n}\n\n/** Render argv for `docker run -d`-style long-lived container create.\n *\n * Output order:\n * `-d --name N label… env… -p… mount… [--network N --network-alias …]\n * add-host… [--entrypoint …] <image> [command…]`\n *\n * Order is load-bearing — tests that snapshot the create argv assert\n * against this exact sequence. */\nexport const renderCreateArgs = (spec: RenderCreateArgsSpec): ReadonlyArray<string> => {\n\tconst args: Array<string> = ['-d', '--name', spec.name];\n\tpushLabels(args, spec.labels);\n\tpushEnv(args, spec.env);\n\tpushPorts(args, spec.ports);\n\tpushMounts(args, spec.mounts);\n\tif (spec.network !== undefined) {\n\t\targs.push('--network', spec.network.name);\n\t\tfor (const alias of spec.network.aliases ?? []) {\n\t\t\targs.push('--network-alias', alias);\n\t\t}\n\t}\n\tpushAddHosts(args, spec.addHosts);\n\tif (spec.entrypoint) args.push('--entrypoint', spec.entrypoint);\n\targs.push(spec.image);\n\tif (spec.command) args.push(...spec.command);\n\treturn args;\n};\n"],"mappings":";AAgDA,MAAM,WAAW,MAAqB,QAA4D;AACjG,KAAI,QAAQ,KAAA,EAAW;AACvB,MAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,IAAI,CACvC,MAAK,KAAK,SAAS,GAAG,EAAE,GAAG,IAAI;;AAIjC,MAAM,cACL,MACA,WACU;AACV,KAAI,WAAW,KAAA,EAAW;AAC1B,MAAK,MAAM,KAAK,QAAQ;EACvB,MAAM,KAAK,EAAE,WAAW,cAAc;AACtC,OAAK,KAAK,WAAW,oBAAoB,EAAE,OAAO,UAAU,EAAE,SAAS,KAAK;;;AAI9E,MAAM,gBACL,MACA,aACU;AACV,KAAI,aAAa,KAAA,EAAW;AAC5B,MAAK,MAAM,CAAC,MAAM,OAAO,OAAO,QAAQ,SAAS,CAChD,MAAK,KAAK,cAAc,GAAG,KAAK,GAAG,KAAK;;AAI1C,MAAM,cAAc,MAAqB,WAAoD;AAC5F,KAAI,WAAW,KAAA,EAAW;AAC1B,MAAK,MAAM,KAAK,OAAQ,MAAK,KAAK,WAAW,EAAE;;AAGhD,MAAM,aACL,MACA,UACU;AACV,KAAI,UAAU,KAAA,EAAW;AACzB,MAAK,MAAM,KAAK,OAAO;EACtB,MAAM,aAAa,EAAE,WAAW,KAAA,IAAY,KAAK,GAAG,EAAE,OAAO;AAC7D,OAAK,KAAK,MAAM,GAAG,aAAa,EAAE,SAAS,GAAG,EAAE,gBAAgB;;;;;;;;;;;AAmClE,MAAa,iBAAiB,SAAmD;CAChF,MAAM,OAAsB,EAAE;AAC9B,KAAI,CAAC,KAAK,KAAM,MAAK,KAAK,OAAO;AACjC,MAAK,KAAK,UAAU,KAAK,KAAK;AAC9B,KAAI,KAAK,QAAS,MAAK,KAAK,aAAa,KAAK,QAAQ;AACtD,KAAI,KAAK,WAAY,MAAK,KAAK,gBAAgB,KAAK,WAAW;AAC/D,KAAI,KAAK,KAAM,MAAK,KAAK,UAAU,KAAK,KAAK;AAC7C,SAAQ,MAAM,KAAK,IAAI;AACvB,YAAW,MAAM,KAAK,OAAO;AAC7B,YAAW,MAAM,KAAK,OAAO;AAC7B,cAAa,MAAM,KAAK,SAAS;AACjC,MAAK,KAAK,KAAK,MAAM;AACrB,KAAI,KAAK,KAAM,MAAK,KAAK,GAAG,KAAK,KAAK;AACtC,QAAO;;;;;;;;;;AAmCR,MAAa,oBAAoB,SAAsD;CACtF,MAAM,OAAsB;EAAC;EAAM;EAAU,KAAK;EAAK;AACvD,YAAW,MAAM,KAAK,OAAO;AAC7B,SAAQ,MAAM,KAAK,IAAI;AACvB,WAAU,MAAM,KAAK,MAAM;AAC3B,YAAW,MAAM,KAAK,OAAO;AAC7B,KAAI,KAAK,YAAY,KAAA,GAAW;AAC/B,OAAK,KAAK,aAAa,KAAK,QAAQ,KAAK;AACzC,OAAK,MAAM,SAAS,KAAK,QAAQ,WAAW,EAAE,CAC7C,MAAK,KAAK,mBAAmB,MAAM;;AAGrC,cAAa,MAAM,KAAK,SAAS;AACjC,KAAI,KAAK,WAAY,MAAK,KAAK,gBAAgB,KAAK,WAAW;AAC/D,MAAK,KAAK,KAAK,MAAM;AACrB,KAAI,KAAK,QAAS,MAAK,KAAK,GAAG,KAAK,QAAQ;AAC5C,QAAO"}
|
|
@@ -2,7 +2,7 @@ import { ContainerRuntime } from "../../contracts/container-runtime.mjs";
|
|
|
2
2
|
import { Context, Layer, Ref } from "effect";
|
|
3
3
|
|
|
4
4
|
//#region src/runtime/docker/service.d.ts
|
|
5
|
-
declare const ContainerRuntimeService_base: Context.ServiceClass<ContainerRuntimeService, "@devstack
|
|
5
|
+
declare const ContainerRuntimeService_base: Context.ServiceClass<ContainerRuntimeService, "@devstack/runtime-docker/ContainerRuntime", ContainerRuntime>;
|
|
6
6
|
declare class ContainerRuntimeService extends ContainerRuntimeService_base {}
|
|
7
7
|
//#endregion
|
|
8
8
|
export { ContainerRuntimeService };
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { StackPathsService } from "../../substrate/runtime/paths.mjs";
|
|
2
1
|
import { chainId, contentHash } from "../../substrate/brand.mjs";
|
|
2
|
+
import { StackPathsService } from "../../substrate/runtime/paths.mjs";
|
|
3
|
+
import { mintRandomSuffix } from "../../substrate/runtime/random-suffix.mjs";
|
|
3
4
|
import { CacheService } from "../../substrate/runtime/cache/service.mjs";
|
|
5
|
+
import "../../substrate/runtime/cache/index.mjs";
|
|
4
6
|
import { DockerHost, DockerSpawner, dockerRunOk } from "./client.mjs";
|
|
5
7
|
import { toContractError } from "./errors.mjs";
|
|
8
|
+
import { expectedImageOwnershipLabels } from "./labels.mjs";
|
|
6
9
|
import { ensureNetwork } from "./network.mjs";
|
|
7
10
|
import { assertContainerHandleOwned, commit, ensureContainer, inspectContainer, pause, stop, unpause } from "./container.mjs";
|
|
8
11
|
import { dockerExec, dockerRunOneShot } from "./exec.mjs";
|
|
@@ -11,18 +14,18 @@ import { listContainers } from "./inventory.mjs";
|
|
|
11
14
|
import { followLogs } from "./logs.mjs";
|
|
12
15
|
import { removeManagedContainers, removeManagedImages, removeManagedNetworks, removeManagedVolumes, sweepOrphans } from "./sweep.mjs";
|
|
13
16
|
import { Context, Duration, Effect, Layer, Ref, Stream } from "effect";
|
|
14
|
-
import { createHash, randomUUID } from "node:crypto";
|
|
15
17
|
import { lstatSync, readFileSync, readdirSync, readlinkSync } from "node:fs";
|
|
18
|
+
import { createHash } from "node:crypto";
|
|
16
19
|
import { join, relative, sep } from "node:path";
|
|
17
20
|
//#region src/runtime/docker/service.ts
|
|
18
|
-
var ContainerRuntimeService = class extends Context.Service()("@devstack
|
|
19
|
-
var DockerCycle = class extends Context.Service()("@devstack
|
|
21
|
+
var ContainerRuntimeService = class extends Context.Service()("@devstack/runtime-docker/ContainerRuntime") {};
|
|
22
|
+
var DockerCycle = class extends Context.Service()("@devstack/runtime-docker/Cycle") {};
|
|
20
23
|
const layerDockerCycleInitial = Layer.effect(DockerCycle, Effect.gen(function* () {
|
|
21
24
|
return yield* Ref.make(0);
|
|
22
25
|
}));
|
|
23
26
|
const mapToContractError = (eff) => eff.pipe(Effect.mapError(toContractError));
|
|
24
27
|
const snapshotTempTag = (containerName) => {
|
|
25
|
-
return `devstack-snapshot:${containerName.replace(/[^A-Za-z0-9_.-]/g, "-")}-${
|
|
28
|
+
return `devstack-snapshot:${containerName.replace(/[^A-Za-z0-9_.-]/g, "-")}-${mintRandomSuffix(12)}`;
|
|
26
29
|
};
|
|
27
30
|
const stableRelativePath = (root, path) => {
|
|
28
31
|
const rel = relative(root, path);
|
|
@@ -125,12 +128,14 @@ const layerContainerRuntimeDocker = Layer.effect(ContainerRuntimeService, Effect
|
|
|
125
128
|
} : ctx;
|
|
126
129
|
const hash = buildContentHash(effectiveCtx);
|
|
127
130
|
const tag = expected?.tag ?? `devstack-build:${hash.slice(0, 16)}`;
|
|
131
|
+
const ownerLabels = effectiveCtx.owner !== void 0 ? expectedImageOwnershipLabels(effectiveCtx.owner) : void 0;
|
|
128
132
|
return yield* ensureImageCached({
|
|
129
133
|
contextPath: effectiveCtx.contextPath,
|
|
130
134
|
dockerfile: effectiveCtx.dockerfile,
|
|
131
135
|
platform: effectiveCtx.platform,
|
|
132
136
|
buildArgs: effectiveCtx.buildArgs,
|
|
133
|
-
tag
|
|
137
|
+
tag,
|
|
138
|
+
...ownerLabels !== void 0 && { labels: ownerLabels }
|
|
134
139
|
}, {
|
|
135
140
|
namespace: "runtime-docker-build",
|
|
136
141
|
chain: chainId("n/a"),
|
|
@@ -261,6 +266,6 @@ const layerContainerRuntimeDocker = Layer.effect(ContainerRuntimeService, Effect
|
|
|
261
266
|
});
|
|
262
267
|
}));
|
|
263
268
|
//#endregion
|
|
264
|
-
export { ContainerRuntimeService, layerContainerRuntimeDocker, layerDockerCycleInitial };
|
|
269
|
+
export { ContainerRuntimeService, DockerCycle, layerContainerRuntimeDocker, layerDockerCycleInitial };
|
|
265
270
|
|
|
266
271
|
//# sourceMappingURL=service.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.mjs","names":["ensureNetworkImpl","pullImageImpl","followLogsStream","stopContainer","saveImageStream","saveImagesStream","loadImageImpl","tagImageImpl","removeImageImpl"],"sources":["../../../src/runtime/docker/service.ts"],"sourcesContent":["// `ContainerRuntime` capability — Docker reference implementation.\n//\n// Composes the subsystems in this directory into the contract surface\n// declared in `contracts/container-runtime.ts`. Plugins consume the\n// `ContainerRuntime` interface through this service; the typed\n// docker-specific error variants are accessible to advanced consumers\n// via the underlying subsystems but the public surface projects to\n// the contract's narrow `ContainerRuntimeError`.\n\nimport { createHash, randomUUID } from 'node:crypto';\nimport { lstatSync, readdirSync, readFileSync, readlinkSync } from 'node:fs';\nimport { join, relative, sep } from 'node:path';\n\nimport { Context, Duration, Effect, Layer, Ref, Stream } from 'effect';\n\nimport type {\n\tContainerBuildContext,\n\tContainerHandle,\n\tContainerRuntime,\n\tContainerRuntimeError,\n\tEnsureContainerSpec,\n\tEnsureNetworkSpec,\n\tExecOptions,\n\tExecResult,\n\tImageRef,\n\tLoadedImageBundle,\n\tOneShotSpec,\n\tSaveImageOptions,\n\tTagImageOptions,\n\tTaggedImageRef,\n} from '../../contracts/container-runtime.ts';\nimport type { ContainerLabelTuple } from '../../contracts/snapshotable.ts';\nimport { chainId, contentHash } from '../../substrate/brand.ts';\nimport { CacheService } from '../../substrate/runtime/cache/index.ts';\nimport { StackPathsService } from '../../substrate/runtime/paths.ts';\nimport { DockerHost, DockerSpawner, dockerRunOk } from './client.ts';\nimport {\n\tassertContainerHandleOwned,\n\tcommit,\n\tensureContainer,\n\tinspectContainer,\n\tpause,\n\ttype PerNameLockState,\n\tstop as stopContainer,\n\tunpause,\n} from './container.ts';\nimport { toContractError } from './errors.ts';\nimport { dockerExec, dockerRunOneShot } from './exec.ts';\nimport {\n\tensureImageCached,\n\tloadImage as loadImageImpl,\n\tpull as pullImageImpl,\n\trefOf,\n\tremoveImage as removeImageImpl,\n\tsaveImage as saveImageStream,\n\tsaveImages as saveImagesStream,\n\ttagImage as tagImageImpl,\n} from './image.ts';\nimport { listContainers } from './inventory.ts';\nimport { followLogs as followLogsStream } from './logs.ts';\nimport { ensureNetwork as ensureNetworkImpl } from './network.ts';\nimport {\n\tremoveManagedContainers,\n\tremoveManagedImages,\n\tremoveManagedNetworks,\n\tremoveManagedVolumes,\n\tsweepOrphans,\n} from './sweep.ts';\n\n// -----------------------------------------------------------------------------\n// Service tag — `Context.Service` per Effect-v4 idioms\n// -----------------------------------------------------------------------------\n\nexport class ContainerRuntimeService extends Context.Service<\n\tContainerRuntimeService,\n\tContainerRuntime\n>()('@devstack-rewrite/runtime-docker/ContainerRuntime') {}\n\n// -----------------------------------------------------------------------------\n// Cycle counter — stamped on container labels at create time\n// -----------------------------------------------------------------------------\n\nexport class DockerCycle extends Context.Service<DockerCycle, Ref.Ref<number>>()(\n\t'@devstack-rewrite/runtime-docker/Cycle',\n) {}\n\nexport const layerDockerCycleInitial: Layer.Layer<DockerCycle> = Layer.effect(\n\tDockerCycle,\n\tEffect.gen(function* () {\n\t\tconst ref = yield* Ref.make(0);\n\t\treturn ref;\n\t}),\n);\n\n// -----------------------------------------------------------------------------\n// Layer — wire the subsystems into the contract interface\n// -----------------------------------------------------------------------------\n\nconst mapToContractError = <R, A>(\n\teff: Effect.Effect<A, import('./errors.ts').DockerRuntimeError, R>,\n): Effect.Effect<A, ContainerRuntimeError, R> => eff.pipe(Effect.mapError(toContractError));\n\nconst snapshotTempTag = (containerName: string): string => {\n\tconst safeName = containerName.replace(/[^A-Za-z0-9_.-]/g, '-');\n\tconst suffix = randomUUID().replace(/-/g, '').slice(0, 12);\n\treturn `devstack-snapshot:${safeName}-${suffix}`;\n};\n\nconst stableRelativePath = (root: string, path: string): string => {\n\tconst rel = relative(root, path);\n\treturn rel.length === 0 ? '.' : rel.split(sep).join('/');\n};\n\nconst updateContextEntryHash = (\n\thash: ReturnType<typeof createHash>,\n\troot: string,\n\tpath: string,\n): void => {\n\tconst stat = lstatSync(path);\n\tconst rel = stableRelativePath(root, path);\n\n\tif (stat.isDirectory()) {\n\t\thash.update('dir\\0');\n\t\thash.update(rel);\n\t\thash.update('\\0');\n\t\tfor (const child of readdirSync(path).sort((a, b) => a.localeCompare(b))) {\n\t\t\tupdateContextEntryHash(hash, root, join(path, child));\n\t\t}\n\t\treturn;\n\t}\n\n\tif (stat.isFile()) {\n\t\thash.update('file\\0');\n\t\thash.update(rel);\n\t\thash.update('\\0');\n\t\thash.update(String(stat.mode));\n\t\thash.update('\\0');\n\t\thash.update(readFileSync(path));\n\t\thash.update('\\0');\n\t\treturn;\n\t}\n\n\tif (stat.isSymbolicLink()) {\n\t\thash.update('symlink\\0');\n\t\thash.update(rel);\n\t\thash.update('\\0');\n\t\thash.update(readlinkSync(path));\n\t\thash.update('\\0');\n\t\treturn;\n\t}\n\n\thash.update('other\\0');\n\thash.update(rel);\n\thash.update('\\0');\n\thash.update(String(stat.mode));\n\thash.update('\\0');\n};\n\nconst normalizeFingerprintPath = (path: string): string =>\n\tpath\n\t\t.split(/[\\\\/]+/g)\n\t\t.filter((part) => part.length > 0)\n\t\t.join('/');\n\nconst normalizeFingerprintPaths = (\n\tpaths: ReadonlyArray<string> | undefined,\n): ReadonlyArray<string> =>\n\t[...new Set((paths ?? []).map(normalizeFingerprintPath).filter((path) => path.length > 0))].sort(\n\t\t(a, b) => a.localeCompare(b),\n\t);\n\nconst buildContextFingerprint = (\n\tcontextPath: string,\n\tfingerprintPaths?: ReadonlyArray<string>,\n): string => {\n\tconst hash = createHash('sha256');\n\tconst requestedPaths = normalizeFingerprintPaths(fingerprintPaths);\n\tconst paths = requestedPaths.length === 0 ? null : requestedPaths;\n\ttry {\n\t\tif (paths === null) {\n\t\t\tupdateContextEntryHash(hash, contextPath, contextPath);\n\t\t} else {\n\t\t\tfor (const relPath of paths) {\n\t\t\t\thash.update('fingerprint-path\\0');\n\t\t\t\thash.update(relPath);\n\t\t\t\thash.update('\\0');\n\t\t\t\tupdateContextEntryHash(hash, contextPath, join(contextPath, relPath));\n\t\t\t}\n\t\t}\n\t} catch (err) {\n\t\thash.update('unreadable\\0');\n\t\thash.update(String(err));\n\t\thash.update('\\0');\n\t}\n\treturn hash.digest('hex');\n};\n\n/** Stable content hash for the build context. Sorts build args so two\n * equivalent specs whose key insertion order differs produce the same\n * hash. The Docker build context's files are part of the key: changing\n * a vendored entrypoint script must force a new managed image tag. */\nexport const buildContentHash = (ctx: ContainerBuildContext): string => {\n\tconst dockerfile = ctx.dockerfile ?? 'Dockerfile';\n\tconst sortedArgs = Object.entries(ctx.buildArgs ?? {}).sort(([a], [b]) => a.localeCompare(b));\n\tconst argsKey = sortedArgs.map(([k, v]) => `${k}=${v}`).join('\\x00');\n\tconst platform = ctx.platform ?? '';\n\tconst fingerprintPathsKey = normalizeFingerprintPaths(ctx.fingerprintPaths).join('\\x00');\n\treturn createHash('sha256')\n\t\t.update(ctx.contextPath)\n\t\t.update('\\x00')\n\t\t.update(dockerfile)\n\t\t.update('\\x00')\n\t\t.update(platform)\n\t\t.update('\\x00')\n\t\t.update(argsKey)\n\t\t.update('\\x00')\n\t\t.update(fingerprintPathsKey)\n\t\t.update('\\x00')\n\t\t.update(buildContextFingerprint(ctx.contextPath, ctx.fingerprintPaths))\n\t\t.digest('hex');\n};\n\nconst DOCKER_ARCH_ALIASES: Readonly<Record<string, string>> = {\n\taarch64: 'arm64',\n\tarm64: 'arm64',\n\tx86_64: 'amd64',\n\tamd64: 'amd64',\n};\n\nexport const normalizeDockerInfoPlatform = (raw: string): string | null => {\n\tconst trimmed = raw.trim();\n\tconst slash = trimmed.indexOf('/');\n\tif (slash <= 0 || slash === trimmed.length - 1) return null;\n\tconst os = trimmed.slice(0, slash);\n\tconst arch = trimmed.slice(slash + 1);\n\tconst normalizedArch = DOCKER_ARCH_ALIASES[arch] ?? arch;\n\treturn `${os}/${normalizedArch}`;\n};\n\nconst inferDockerBuildPlatform = (): Effect.Effect<\n\tstring | null,\n\tnever,\n\tDockerHost | DockerSpawner\n> =>\n\tdockerRunOk('info', ['--format', '{{.OSType}}/{{.Architecture}}']).pipe(\n\t\tEffect.map((result) =>\n\t\t\tresult.exitCode === 0 ? normalizeDockerInfoPlatform(result.stdout) : null,\n\t\t),\n\t\tEffect.catch(() => Effect.succeed(null)),\n\t);\n\nexport const layerContainerRuntimeDocker: Layer.Layer<\n\tContainerRuntimeService,\n\tnever,\n\tCacheService | DockerHost | DockerSpawner | DockerCycle | StackPathsService\n> = Layer.effect(\n\tContainerRuntimeService,\n\tEffect.gen(function* () {\n\t\tconst cycleRef = yield* DockerCycle;\n\t\t// Snapshot the substrate services so we can provide them to the\n\t\t// closures that implement the contract's R=never surface.\n\t\tconst dockerHost = yield* DockerHost;\n\t\tconst dockerSpawner = yield* DockerSpawner;\n\t\tconst stackPaths = yield* StackPathsService;\n\t\tconst cache = yield* CacheService;\n\t\tconst baseCtx = Context.empty().pipe(\n\t\t\tContext.add(DockerHost, dockerHost),\n\t\t\tContext.add(DockerSpawner, dockerSpawner),\n\t\t\tContext.add(StackPathsService, stackPaths),\n\t\t\tContext.add(CacheService, cache),\n\t\t);\n\t\t// Per-name in-process serialization. Architecture invariant:\n\t\t// two concurrent ensureContainer calls for the same name must\n\t\t// not interleave docker inspect/create/start. The cross-process\n\t\t// safety is the daemon's `--name` atomicity (see container.ts\n\t\t// collision recovery). The in-process side is this ref.\n\t\tconst perNameLock = yield* Ref.make<PerNameLockState>(new Map());\n\n\t\tconst ensureImage = (\n\t\t\tctx: ContainerBuildContext,\n\t\t\texpected?: ImageRef,\n\t\t): Effect.Effect<ImageRef, ContainerRuntimeError> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst inferredPlatform =\n\t\t\t\t\tctx.platform === undefined\n\t\t\t\t\t\t? yield* inferDockerBuildPlatform().pipe(Effect.provide(baseCtx))\n\t\t\t\t\t\t: null;\n\t\t\t\tconst effectiveCtx =\n\t\t\t\t\tctx.platform === undefined && inferredPlatform !== null\n\t\t\t\t\t\t? { ...ctx, platform: inferredPlatform }\n\t\t\t\t\t\t: ctx;\n\t\t\t\t// Architecture §8: bring-your-own-image vs build is a closed sum.\n\t\t\t\t// The contract accepts `ContainerBuildContext` (build path);\n\t\t\t\t// pull is exposed via `image.ts::pull` directly to plugins\n\t\t\t\t// that need it (not through this contract entry point).\n\t\t\t\t//\n\t\t\t\t// Content-addressed cache: namespace is the constant\n\t\t\t\t// `runtime-docker-build` (one substrate-owned namespace);\n\t\t\t\t// chain is `n/a` (build artifacts are chain-independent);\n\t\t\t\t// contentHash is a hash of the build context's identifying\n\t\t\t\t// fields. The caller-supplied `expected.tag`, when present,\n\t\t\t\t// is honoured as the on-host tag; absent, we derive a tag\n\t\t\t\t// from the content hash so two unrelated contexts cannot\n\t\t\t\t// collide on the sanitized contextPath form.\n\t\t\t\tconst hash = buildContentHash(effectiveCtx);\n\t\t\t\tconst tag = expected?.tag ?? `devstack-build:${hash.slice(0, 16)}`;\n\t\t\t\treturn yield* ensureImageCached(\n\t\t\t\t\t{\n\t\t\t\t\t\tcontextPath: effectiveCtx.contextPath,\n\t\t\t\t\t\tdockerfile: effectiveCtx.dockerfile,\n\t\t\t\t\t\tplatform: effectiveCtx.platform,\n\t\t\t\t\t\tbuildArgs: effectiveCtx.buildArgs,\n\t\t\t\t\t\ttag,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tnamespace: 'runtime-docker-build',\n\t\t\t\t\t\tchain: chainId('n/a'),\n\t\t\t\t\t\tcontentHash: contentHash(hash),\n\t\t\t\t\t},\n\t\t\t\t).pipe(\n\t\t\t\t\tEffect.map((digest) => refOf(digest, tag)),\n\t\t\t\t\tmapToContractError,\n\t\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\t\tEffect.withSpan('runtime.docker.contract.ensureImage'),\n\t\t\t\t);\n\t\t\t});\n\n\t\tconst ensureNetworkContractImpl = (\n\t\t\tspec: EnsureNetworkSpec,\n\t\t): Effect.Effect<string, ContainerRuntimeError> =>\n\t\t\tensureNetworkImpl(spec.name, {\n\t\t\t\tapp: spec.app,\n\t\t\t\tstack: spec.stack,\n\t\t\t\t...(spec.subnet === undefined ? {} : { subnet: spec.subnet }),\n\t\t\t\t...(spec.gateway === undefined ? {} : { gateway: spec.gateway }),\n\t\t\t}).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.ensureNetwork'),\n\t\t\t);\n\n\t\tconst pullImageContractImpl = (ref: string): Effect.Effect<ImageRef, ContainerRuntimeError> =>\n\t\t\tpullImageImpl(ref).pipe(\n\t\t\t\tEffect.map((digest) => refOf(digest, ref)),\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.pullImage'),\n\t\t\t);\n\n\t\tconst ensureContainerImpl = (\n\t\t\tspec: EnsureContainerSpec,\n\t\t): Effect.Effect<ContainerHandle, ContainerRuntimeError, import('effect').Scope.Scope> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst cycle = yield* Ref.get(cycleRef);\n\t\t\t\treturn yield* ensureContainer(spec, { cycle, perNameLock });\n\t\t\t}).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.ensureContainer'),\n\t\t\t);\n\n\t\tconst inspectByLabels = (\n\t\t\tlabels: ContainerLabelTuple,\n\t\t): Effect.Effect<ReadonlyArray<ContainerHandle>, ContainerRuntimeError> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst summaries = yield* listContainers(labels);\n\t\t\t\treturn yield* Effect.forEach(\n\t\t\t\t\tsummaries,\n\t\t\t\t\t(s) =>\n\t\t\t\t\t\tinspectContainer(s.name).pipe(\n\t\t\t\t\t\t\tEffect.map(\n\t\t\t\t\t\t\t\t(facts): ContainerHandle => ({\n\t\t\t\t\t\t\t\t\tid: facts?.id ?? s.id,\n\t\t\t\t\t\t\t\t\tname: s.name,\n\t\t\t\t\t\t\t\t\tlabels,\n\t\t\t\t\t\t\t\t\timageName: facts?.image ?? s.image,\n\t\t\t\t\t\t\t\t\tstatus: (facts?.paused\n\t\t\t\t\t\t\t\t\t\t? 'paused'\n\t\t\t\t\t\t\t\t\t\t: (facts?.running ?? s.state === 'running')\n\t\t\t\t\t\t\t\t\t\t\t? 'running'\n\t\t\t\t\t\t\t\t\t\t\t: s.state === 'paused'\n\t\t\t\t\t\t\t\t\t\t\t\t? 'paused'\n\t\t\t\t\t\t\t\t\t\t\t\t: s.state === 'created'\n\t\t\t\t\t\t\t\t\t\t\t\t\t? 'created'\n\t\t\t\t\t\t\t\t\t\t\t\t\t: 'exited') as ContainerHandle['status'],\n\t\t\t\t\t\t\t\t\tips: [],\n\t\t\t\t\t\t\t\t\t...(facts?.ports !== undefined ? { ports: facts.ports } : {}),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t{ concurrency: 'unbounded' },\n\t\t\t\t);\n\t\t\t}).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.inspectByLabels'),\n\t\t\t);\n\n\t\tconst followLogsImpl = (\n\t\t\thandle: ContainerHandle,\n\t\t): Stream.Stream<string, ContainerRuntimeError> =>\n\t\t\tfollowLogsStream(handle.name).pipe(\n\t\t\t\tStream.mapError(toContractError),\n\t\t\t\t// R-channel: the underlying stream needs DockerHost +\n\t\t\t\t// DockerSpawner from the spawn step. Provide the\n\t\t\t\t// snapshotted base context so the contract surface is\n\t\t\t\t// `R = never`. `Stream.mapError` does NOT drop R; the\n\t\t\t\t// `as`-cast in the previous shape was a release-blocker\n\t\t\t\t// per runtime-docker review issue #3.\n\t\t\t\tStream.provideContext(baseCtx),\n\t\t\t);\n\n\t\tconst pauseAndCommitImpl = (\n\t\t\thandle: ContainerHandle,\n\t\t): Effect.Effect<TaggedImageRef, ContainerRuntimeError> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tyield* assertContainerHandleOwned(handle);\n\t\t\t\tif (handle.status === 'running') {\n\t\t\t\t\tyield* pause(handle.name);\n\t\t\t\t\tyield* assertContainerHandleOwned(handle);\n\t\t\t\t}\n\t\t\t\tconst tag = snapshotTempTag(handle.name);\n\t\t\t\tconst digest = yield* commit(handle.name, tag);\n\t\t\t\treturn { digest, tag };\n\t\t\t}).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.pauseAndCommit'),\n\t\t\t);\n\n\t\tconst pauseImpl = (handle: ContainerHandle): Effect.Effect<void, ContainerRuntimeError> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tyield* assertContainerHandleOwned(handle);\n\t\t\t\tyield* pause(handle.name);\n\t\t\t}).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.pause'),\n\t\t\t);\n\n\t\tconst unpauseImpl = (handle: ContainerHandle): Effect.Effect<void, ContainerRuntimeError> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tyield* assertContainerHandleOwned(handle);\n\t\t\t\tyield* unpause(handle.name);\n\t\t\t}).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.unpause'),\n\t\t\t);\n\n\t\tconst stopImpl = (\n\t\t\thandle: ContainerHandle,\n\t\t\tgrace: Duration.Duration,\n\t\t): Effect.Effect<void, ContainerRuntimeError> => {\n\t\t\tconst seconds = Math.max(0, Math.ceil(Duration.toMillis(grace) / 1000));\n\t\t\treturn Effect.gen(function* () {\n\t\t\t\tyield* assertContainerHandleOwned(handle);\n\t\t\t\tyield* stopContainer(handle.name, seconds);\n\t\t\t}).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.stop'),\n\t\t\t);\n\t\t};\n\n\t\tconst sweepOrphansImpl = (\n\t\t\tlabelMatch: Partial<ContainerLabelTuple>,\n\t\t): Effect.Effect<number, ContainerRuntimeError> =>\n\t\t\tsweepOrphans(labelMatch).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.sweepOrphans'),\n\t\t\t);\n\n\t\tconst removeManagedContainersImpl = (\n\t\t\tlabelMatch: Partial<ContainerLabelTuple>,\n\t\t): Effect.Effect<number, ContainerRuntimeError> =>\n\t\t\tremoveManagedContainers(labelMatch).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.removeManagedContainers'),\n\t\t\t);\n\n\t\tconst removeManagedImagesImpl = (\n\t\t\tlabelMatch: Partial<ContainerLabelTuple>,\n\t\t): Effect.Effect<number, ContainerRuntimeError> =>\n\t\t\tremoveManagedImages(labelMatch).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.removeManagedImages'),\n\t\t\t);\n\n\t\tconst removeManagedNetworksImpl = (\n\t\t\tlabelMatch: Partial<ContainerLabelTuple>,\n\t\t): Effect.Effect<number, ContainerRuntimeError> =>\n\t\t\tremoveManagedNetworks(labelMatch).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.removeManagedNetworks'),\n\t\t\t);\n\n\t\tconst removeManagedVolumesImpl = (\n\t\t\tlabelMatch: Partial<ContainerLabelTuple>,\n\t\t): Effect.Effect<number, ContainerRuntimeError> =>\n\t\t\tremoveManagedVolumes(labelMatch).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.removeManagedVolumes'),\n\t\t\t);\n\n\t\tconst execImpl = (\n\t\t\thandle: ContainerHandle,\n\t\t\targv: ReadonlyArray<string>,\n\t\t\topts?: ExecOptions,\n\t\t): Effect.Effect<ExecResult, ContainerRuntimeError> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tyield* assertContainerHandleOwned(handle);\n\t\t\t\treturn yield* dockerExec(handle.name, argv, {\n\t\t\t\t\tuser: opts?.user,\n\t\t\t\t\tenv: opts?.env,\n\t\t\t\t\tworkdir: opts?.workdir,\n\t\t\t\t});\n\t\t\t}).pipe(\n\t\t\t\t// Contract surface: NEVER promote non-zero exit to failure\n\t\t\t\t// here. The caller is the policy holder.\n\t\t\t\tEffect.map(\n\t\t\t\t\t(r): ExecResult => ({\n\t\t\t\t\t\texitCode: r.exitCode,\n\t\t\t\t\t\tstdout: r.stdout,\n\t\t\t\t\t\tstderr: r.stderr,\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.exec'),\n\t\t\t);\n\n\t\tconst saveImageImpl = (\n\t\t\tref: ImageRef,\n\t\t\topts?: SaveImageOptions,\n\t\t): Stream.Stream<Uint8Array, ContainerRuntimeError> => {\n\t\t\tconst resolved = ref.tag ?? ref.digest;\n\t\t\treturn saveImageStream(resolved, opts).pipe(\n\t\t\t\tStream.mapError(toContractError),\n\t\t\t\tStream.provideContext(baseCtx),\n\t\t\t);\n\t\t};\n\t\tconst saveImagesImpl = (\n\t\t\trefs: ReadonlyArray<ImageRef>,\n\t\t\topts?: SaveImageOptions,\n\t\t): Stream.Stream<Uint8Array, ContainerRuntimeError> => {\n\t\t\tconst resolved = refs.map((ref) => ref.tag ?? ref.digest);\n\t\t\treturn saveImagesStream(resolved, opts).pipe(\n\t\t\t\tStream.mapError(toContractError),\n\t\t\t\tStream.provideContext(baseCtx),\n\t\t\t);\n\t\t};\n\n\t\tconst loadImageContractImpl = (\n\t\t\ttar: Stream.Stream<Uint8Array, unknown>,\n\t\t): Effect.Effect<LoadedImageBundle, ContainerRuntimeError> =>\n\t\t\tloadImageImpl(tar).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.loadImage'),\n\t\t\t);\n\n\t\tconst tagImageContractImpl = (\n\t\t\tsrc: ImageRef,\n\t\t\tnewTag: string,\n\t\t\topts?: TagImageOptions,\n\t\t): Effect.Effect<void, ContainerRuntimeError> => {\n\t\t\tconst resolved = src.tag ?? src.digest;\n\t\t\treturn tagImageImpl(resolved, newTag, opts).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.tagImage'),\n\t\t\t);\n\t\t};\n\n\t\tconst removeImageContractImpl = (ref: ImageRef): Effect.Effect<void, ContainerRuntimeError> => {\n\t\t\tconst resolved = ref.tag ?? ref.digest;\n\t\t\treturn removeImageImpl(resolved).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.removeImage'),\n\t\t\t);\n\t\t};\n\n\t\tconst runOneShotImpl = (\n\t\t\tspec: OneShotSpec,\n\t\t): Effect.Effect<ExecResult, ContainerRuntimeError, import('effect').Scope.Scope> =>\n\t\t\tdockerRunOneShot({\n\t\t\t\timage: spec.image.tag ?? spec.image.digest,\n\t\t\t\targv: spec.argv,\n\t\t\t\tenv: spec.env,\n\t\t\t\tmounts: spec.mounts,\n\t\t\t\tnetwork: spec.network,\n\t\t\t\tentrypoint: spec.entrypoint,\n\t\t\t\tuser: spec.user,\n\t\t\t\ttimeoutMillis: spec.timeoutMillis,\n\t\t\t\textraHosts: spec.extraHosts,\n\t\t\t}).pipe(\n\t\t\t\t// Same contract: never promote non-zero exit to failure.\n\t\t\t\tEffect.map(\n\t\t\t\t\t(r): ExecResult => ({\n\t\t\t\t\t\texitCode: r.exitCode,\n\t\t\t\t\t\tstdout: r.stdout,\n\t\t\t\t\t\tstderr: r.stderr,\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.runOneShot'),\n\t\t\t);\n\n\t\treturn ContainerRuntimeService.of({\n\t\t\tensureImage,\n\t\t\tpullImage: pullImageContractImpl,\n\t\t\tensureNetwork: ensureNetworkContractImpl,\n\t\t\tensureContainer: ensureContainerImpl,\n\t\t\texec: execImpl,\n\t\t\trunOneShot: runOneShotImpl,\n\t\t\tinspectByLabels,\n\t\t\tfollowLogs: followLogsImpl,\n\t\t\tpause: pauseImpl,\n\t\t\tpauseAndCommit: pauseAndCommitImpl,\n\t\t\tsaveImage: saveImageImpl,\n\t\t\tsaveImages: saveImagesImpl,\n\t\t\tloadImage: loadImageContractImpl,\n\t\t\ttagImage: tagImageContractImpl,\n\t\t\tremoveImage: removeImageContractImpl,\n\t\t\tunpause: unpauseImpl,\n\t\t\tstop: stopImpl,\n\t\t\tsweepOrphans: sweepOrphansImpl,\n\t\t\tremoveManagedContainers: removeManagedContainersImpl,\n\t\t\tremoveManagedImages: removeManagedImagesImpl,\n\t\t\tremoveManagedNetworks: removeManagedNetworksImpl,\n\t\t\tremoveManagedVolumes: removeManagedVolumesImpl,\n\t\t});\n\t}),\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service.mjs","names":["ensureNetworkImpl","pullImageImpl","followLogsStream","stopContainer","saveImageStream","saveImagesStream","loadImageImpl","tagImageImpl","removeImageImpl"],"sources":["../../../src/runtime/docker/service.ts"],"sourcesContent":["// `ContainerRuntime` capability — Docker reference implementation.\n//\n// Composes the subsystems in this directory into the contract surface\n// declared in `contracts/container-runtime.ts`. Plugins consume the\n// `ContainerRuntime` interface through this service; the typed\n// docker-specific error variants are accessible to advanced consumers\n// via the underlying subsystems but the public surface projects to\n// the contract's narrow `ContainerRuntimeError`.\n\nimport { createHash } from 'node:crypto';\nimport { lstatSync, readdirSync, readFileSync, readlinkSync } from 'node:fs';\nimport { join, relative, sep } from 'node:path';\n\nimport { Context, Duration, Effect, Layer, Ref, Stream } from 'effect';\n\nimport type {\n\tContainerBuildContext,\n\tContainerHandle,\n\tContainerRuntime,\n\tContainerRuntimeError,\n\tEnsureContainerSpec,\n\tEnsureNetworkSpec,\n\tExecOptions,\n\tExecResult,\n\tImageRef,\n\tLoadedImageBundle,\n\tOneShotSpec,\n\tSaveImageOptions,\n\tTagImageOptions,\n\tTaggedImageRef,\n} from '../../contracts/container-runtime.ts';\nimport type { ContainerLabelTuple } from '../../contracts/snapshotable.ts';\nimport { chainId, contentHash } from '../../substrate/brand.ts';\nimport { mintRandomSuffix } from '../../substrate/runtime/random-suffix.ts';\nimport { CacheService } from '../../substrate/runtime/cache/index.ts';\nimport { StackPathsService } from '../../substrate/runtime/paths.ts';\nimport { DockerHost, DockerSpawner, dockerRunOk } from './client.ts';\nimport {\n\tassertContainerHandleOwned,\n\tcommit,\n\tensureContainer,\n\tinspectContainer,\n\tpause,\n\ttype PerNameLockState,\n\tstop as stopContainer,\n\tunpause,\n} from './container.ts';\nimport { toContractError } from './errors.ts';\nimport { dockerExec, dockerRunOneShot } from './exec.ts';\nimport {\n\tensureImageCached,\n\tloadImage as loadImageImpl,\n\tpull as pullImageImpl,\n\trefOf,\n\tremoveImage as removeImageImpl,\n\tsaveImage as saveImageStream,\n\tsaveImages as saveImagesStream,\n\ttagImage as tagImageImpl,\n} from './image.ts';\nimport { listContainers } from './inventory.ts';\nimport { expectedImageOwnershipLabels } from './labels.ts';\nimport { followLogs as followLogsStream } from './logs.ts';\nimport { ensureNetwork as ensureNetworkImpl } from './network.ts';\nimport {\n\tremoveManagedContainers,\n\tremoveManagedImages,\n\tremoveManagedNetworks,\n\tremoveManagedVolumes,\n\tsweepOrphans,\n} from './sweep.ts';\n\n// -----------------------------------------------------------------------------\n// Service tag — `Context.Service` per Effect-v4 idioms\n// -----------------------------------------------------------------------------\n\nexport class ContainerRuntimeService extends Context.Service<\n\tContainerRuntimeService,\n\tContainerRuntime\n>()('@devstack/runtime-docker/ContainerRuntime') {}\n\n// -----------------------------------------------------------------------------\n// Cycle counter — stamped on container labels at create time\n// -----------------------------------------------------------------------------\n\nexport class DockerCycle extends Context.Service<DockerCycle, Ref.Ref<number>>()(\n\t'@devstack/runtime-docker/Cycle',\n) {}\n\nexport const layerDockerCycleInitial: Layer.Layer<DockerCycle> = Layer.effect(\n\tDockerCycle,\n\tEffect.gen(function* () {\n\t\tconst ref = yield* Ref.make(0);\n\t\treturn ref;\n\t}),\n);\n\n// -----------------------------------------------------------------------------\n// Layer — wire the subsystems into the contract interface\n// -----------------------------------------------------------------------------\n\nconst mapToContractError = <R, A>(\n\teff: Effect.Effect<A, import('./errors.ts').DockerRuntimeError, R>,\n): Effect.Effect<A, ContainerRuntimeError, R> => eff.pipe(Effect.mapError(toContractError));\n\nconst snapshotTempTag = (containerName: string): string => {\n\tconst safeName = containerName.replace(/[^A-Za-z0-9_.-]/g, '-');\n\tconst suffix = mintRandomSuffix(12);\n\treturn `devstack-snapshot:${safeName}-${suffix}`;\n};\n\nconst stableRelativePath = (root: string, path: string): string => {\n\tconst rel = relative(root, path);\n\treturn rel.length === 0 ? '.' : rel.split(sep).join('/');\n};\n\nconst updateContextEntryHash = (\n\thash: ReturnType<typeof createHash>,\n\troot: string,\n\tpath: string,\n): void => {\n\tconst stat = lstatSync(path);\n\tconst rel = stableRelativePath(root, path);\n\n\tif (stat.isDirectory()) {\n\t\thash.update('dir\\0');\n\t\thash.update(rel);\n\t\thash.update('\\0');\n\t\tfor (const child of readdirSync(path).sort((a, b) => a.localeCompare(b))) {\n\t\t\tupdateContextEntryHash(hash, root, join(path, child));\n\t\t}\n\t\treturn;\n\t}\n\n\tif (stat.isFile()) {\n\t\thash.update('file\\0');\n\t\thash.update(rel);\n\t\thash.update('\\0');\n\t\thash.update(String(stat.mode));\n\t\thash.update('\\0');\n\t\thash.update(readFileSync(path));\n\t\thash.update('\\0');\n\t\treturn;\n\t}\n\n\tif (stat.isSymbolicLink()) {\n\t\thash.update('symlink\\0');\n\t\thash.update(rel);\n\t\thash.update('\\0');\n\t\thash.update(readlinkSync(path));\n\t\thash.update('\\0');\n\t\treturn;\n\t}\n\n\thash.update('other\\0');\n\thash.update(rel);\n\thash.update('\\0');\n\thash.update(String(stat.mode));\n\thash.update('\\0');\n};\n\nconst normalizeFingerprintPath = (path: string): string =>\n\tpath\n\t\t.split(/[\\\\/]+/g)\n\t\t.filter((part) => part.length > 0)\n\t\t.join('/');\n\nconst normalizeFingerprintPaths = (\n\tpaths: ReadonlyArray<string> | undefined,\n): ReadonlyArray<string> =>\n\t[...new Set((paths ?? []).map(normalizeFingerprintPath).filter((path) => path.length > 0))].sort(\n\t\t(a, b) => a.localeCompare(b),\n\t);\n\nconst buildContextFingerprint = (\n\tcontextPath: string,\n\tfingerprintPaths?: ReadonlyArray<string>,\n): string => {\n\tconst hash = createHash('sha256');\n\tconst requestedPaths = normalizeFingerprintPaths(fingerprintPaths);\n\tconst paths = requestedPaths.length === 0 ? null : requestedPaths;\n\ttry {\n\t\tif (paths === null) {\n\t\t\tupdateContextEntryHash(hash, contextPath, contextPath);\n\t\t} else {\n\t\t\tfor (const relPath of paths) {\n\t\t\t\thash.update('fingerprint-path\\0');\n\t\t\t\thash.update(relPath);\n\t\t\t\thash.update('\\0');\n\t\t\t\tupdateContextEntryHash(hash, contextPath, join(contextPath, relPath));\n\t\t\t}\n\t\t}\n\t} catch (err) {\n\t\thash.update('unreadable\\0');\n\t\thash.update(String(err));\n\t\thash.update('\\0');\n\t}\n\treturn hash.digest('hex');\n};\n\n/** Stable content hash for the build context. Sorts build args so two\n * equivalent specs whose key insertion order differs produce the same\n * hash. The Docker build context's files are part of the key: changing\n * a vendored entrypoint script must force a new managed image tag. */\nexport const buildContentHash = (ctx: ContainerBuildContext): string => {\n\tconst dockerfile = ctx.dockerfile ?? 'Dockerfile';\n\tconst sortedArgs = Object.entries(ctx.buildArgs ?? {}).sort(([a], [b]) => a.localeCompare(b));\n\tconst argsKey = sortedArgs.map(([k, v]) => `${k}=${v}`).join('\\x00');\n\tconst platform = ctx.platform ?? '';\n\tconst fingerprintPathsKey = normalizeFingerprintPaths(ctx.fingerprintPaths).join('\\x00');\n\treturn createHash('sha256')\n\t\t.update(ctx.contextPath)\n\t\t.update('\\x00')\n\t\t.update(dockerfile)\n\t\t.update('\\x00')\n\t\t.update(platform)\n\t\t.update('\\x00')\n\t\t.update(argsKey)\n\t\t.update('\\x00')\n\t\t.update(fingerprintPathsKey)\n\t\t.update('\\x00')\n\t\t.update(buildContextFingerprint(ctx.contextPath, ctx.fingerprintPaths))\n\t\t.digest('hex');\n};\n\nconst DOCKER_ARCH_ALIASES: Readonly<Record<string, string>> = {\n\taarch64: 'arm64',\n\tarm64: 'arm64',\n\tx86_64: 'amd64',\n\tamd64: 'amd64',\n};\n\nexport const normalizeDockerInfoPlatform = (raw: string): string | null => {\n\tconst trimmed = raw.trim();\n\tconst slash = trimmed.indexOf('/');\n\tif (slash <= 0 || slash === trimmed.length - 1) return null;\n\tconst os = trimmed.slice(0, slash);\n\tconst arch = trimmed.slice(slash + 1);\n\tconst normalizedArch = DOCKER_ARCH_ALIASES[arch] ?? arch;\n\treturn `${os}/${normalizedArch}`;\n};\n\nconst inferDockerBuildPlatform = (): Effect.Effect<\n\tstring | null,\n\tnever,\n\tDockerHost | DockerSpawner\n> =>\n\tdockerRunOk('info', ['--format', '{{.OSType}}/{{.Architecture}}']).pipe(\n\t\tEffect.map((result) =>\n\t\t\tresult.exitCode === 0 ? normalizeDockerInfoPlatform(result.stdout) : null,\n\t\t),\n\t\tEffect.catch(() => Effect.succeed(null)),\n\t);\n\nexport const layerContainerRuntimeDocker: Layer.Layer<\n\tContainerRuntimeService,\n\tnever,\n\tCacheService | DockerHost | DockerSpawner | DockerCycle | StackPathsService\n> = Layer.effect(\n\tContainerRuntimeService,\n\tEffect.gen(function* () {\n\t\tconst cycleRef = yield* DockerCycle;\n\t\t// Snapshot the substrate services so we can provide them to the\n\t\t// closures that implement the contract's R=never surface.\n\t\tconst dockerHost = yield* DockerHost;\n\t\tconst dockerSpawner = yield* DockerSpawner;\n\t\tconst stackPaths = yield* StackPathsService;\n\t\tconst cache = yield* CacheService;\n\t\tconst baseCtx = Context.empty().pipe(\n\t\t\tContext.add(DockerHost, dockerHost),\n\t\t\tContext.add(DockerSpawner, dockerSpawner),\n\t\t\tContext.add(StackPathsService, stackPaths),\n\t\t\tContext.add(CacheService, cache),\n\t\t);\n\t\t// Per-name in-process serialization. Architecture invariant:\n\t\t// two concurrent ensureContainer calls for the same name must\n\t\t// not interleave docker inspect/create/start. The cross-process\n\t\t// safety is the daemon's `--name` atomicity (see container.ts\n\t\t// collision recovery). The in-process side is this ref.\n\t\tconst perNameLock = yield* Ref.make<PerNameLockState>(new Map());\n\n\t\tconst ensureImage = (\n\t\t\tctx: ContainerBuildContext,\n\t\t\texpected?: ImageRef,\n\t\t): Effect.Effect<ImageRef, ContainerRuntimeError> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst inferredPlatform =\n\t\t\t\t\tctx.platform === undefined\n\t\t\t\t\t\t? yield* inferDockerBuildPlatform().pipe(Effect.provide(baseCtx))\n\t\t\t\t\t\t: null;\n\t\t\t\tconst effectiveCtx =\n\t\t\t\t\tctx.platform === undefined && inferredPlatform !== null\n\t\t\t\t\t\t? { ...ctx, platform: inferredPlatform }\n\t\t\t\t\t\t: ctx;\n\t\t\t\t// Architecture §8: bring-your-own-image vs build is a closed sum.\n\t\t\t\t// The contract accepts `ContainerBuildContext` (build path);\n\t\t\t\t// pull is exposed via `image.ts::pull` directly to plugins\n\t\t\t\t// that need it (not through this contract entry point).\n\t\t\t\t//\n\t\t\t\t// Content-addressed cache: namespace is the constant\n\t\t\t\t// `runtime-docker-build` (one substrate-owned namespace);\n\t\t\t\t// chain is `n/a` (build artifacts are chain-independent);\n\t\t\t\t// contentHash is a hash of the build context's identifying\n\t\t\t\t// fields. The caller-supplied `expected.tag`, when present,\n\t\t\t\t// is honoured as the on-host tag; absent, we derive a tag\n\t\t\t\t// from the content hash so two unrelated contexts cannot\n\t\t\t\t// collide on the sanitized contextPath form.\n\t\t\t\tconst hash = buildContentHash(effectiveCtx);\n\t\t\t\tconst tag = expected?.tag ?? `devstack-build:${hash.slice(0, 16)}`;\n\t\t\t\t// Owner identity flows through as `--label` flags on\n\t\t\t\t// `docker build`, making the resulting image visible to\n\t\t\t\t// label-driven prune. Labels are metadata, NOT part of\n\t\t\t\t// the cache key — a previously-unlabelled cached image\n\t\t\t\t// stays a cache hit (the legacy cleanup script reaps it).\n\t\t\t\tconst ownerLabels =\n\t\t\t\t\teffectiveCtx.owner !== undefined\n\t\t\t\t\t\t? expectedImageOwnershipLabels(effectiveCtx.owner)\n\t\t\t\t\t\t: undefined;\n\t\t\t\treturn yield* ensureImageCached(\n\t\t\t\t\t{\n\t\t\t\t\t\tcontextPath: effectiveCtx.contextPath,\n\t\t\t\t\t\tdockerfile: effectiveCtx.dockerfile,\n\t\t\t\t\t\tplatform: effectiveCtx.platform,\n\t\t\t\t\t\tbuildArgs: effectiveCtx.buildArgs,\n\t\t\t\t\t\ttag,\n\t\t\t\t\t\t...(ownerLabels !== undefined && { labels: ownerLabels }),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tnamespace: 'runtime-docker-build',\n\t\t\t\t\t\tchain: chainId('n/a'),\n\t\t\t\t\t\tcontentHash: contentHash(hash),\n\t\t\t\t\t},\n\t\t\t\t).pipe(\n\t\t\t\t\tEffect.map((digest) => refOf(digest, tag)),\n\t\t\t\t\tmapToContractError,\n\t\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\t\tEffect.withSpan('runtime.docker.contract.ensureImage'),\n\t\t\t\t);\n\t\t\t});\n\n\t\tconst ensureNetworkContractImpl = (\n\t\t\tspec: EnsureNetworkSpec,\n\t\t): Effect.Effect<string, ContainerRuntimeError> =>\n\t\t\tensureNetworkImpl(spec.name, {\n\t\t\t\tapp: spec.app,\n\t\t\t\tstack: spec.stack,\n\t\t\t\t...(spec.subnet === undefined ? {} : { subnet: spec.subnet }),\n\t\t\t\t...(spec.gateway === undefined ? {} : { gateway: spec.gateway }),\n\t\t\t}).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.ensureNetwork'),\n\t\t\t);\n\n\t\tconst pullImageContractImpl = (ref: string): Effect.Effect<ImageRef, ContainerRuntimeError> =>\n\t\t\tpullImageImpl(ref).pipe(\n\t\t\t\tEffect.map((digest) => refOf(digest, ref)),\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.pullImage'),\n\t\t\t);\n\n\t\tconst ensureContainerImpl = (\n\t\t\tspec: EnsureContainerSpec,\n\t\t): Effect.Effect<ContainerHandle, ContainerRuntimeError, import('effect').Scope.Scope> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst cycle = yield* Ref.get(cycleRef);\n\t\t\t\treturn yield* ensureContainer(spec, { cycle, perNameLock });\n\t\t\t}).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.ensureContainer'),\n\t\t\t);\n\n\t\tconst inspectByLabels = (\n\t\t\tlabels: ContainerLabelTuple,\n\t\t): Effect.Effect<ReadonlyArray<ContainerHandle>, ContainerRuntimeError> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst summaries = yield* listContainers(labels);\n\t\t\t\treturn yield* Effect.forEach(\n\t\t\t\t\tsummaries,\n\t\t\t\t\t(s) =>\n\t\t\t\t\t\tinspectContainer(s.name).pipe(\n\t\t\t\t\t\t\tEffect.map(\n\t\t\t\t\t\t\t\t(facts): ContainerHandle => ({\n\t\t\t\t\t\t\t\t\tid: facts?.id ?? s.id,\n\t\t\t\t\t\t\t\t\tname: s.name,\n\t\t\t\t\t\t\t\t\tlabels,\n\t\t\t\t\t\t\t\t\timageName: facts?.image ?? s.image,\n\t\t\t\t\t\t\t\t\tstatus: (facts?.paused\n\t\t\t\t\t\t\t\t\t\t? 'paused'\n\t\t\t\t\t\t\t\t\t\t: (facts?.running ?? s.state === 'running')\n\t\t\t\t\t\t\t\t\t\t\t? 'running'\n\t\t\t\t\t\t\t\t\t\t\t: s.state === 'paused'\n\t\t\t\t\t\t\t\t\t\t\t\t? 'paused'\n\t\t\t\t\t\t\t\t\t\t\t\t: s.state === 'created'\n\t\t\t\t\t\t\t\t\t\t\t\t\t? 'created'\n\t\t\t\t\t\t\t\t\t\t\t\t\t: 'exited') as ContainerHandle['status'],\n\t\t\t\t\t\t\t\t\tips: [],\n\t\t\t\t\t\t\t\t\t...(facts?.ports !== undefined ? { ports: facts.ports } : {}),\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t{ concurrency: 'unbounded' },\n\t\t\t\t);\n\t\t\t}).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.inspectByLabels'),\n\t\t\t);\n\n\t\tconst followLogsImpl = (\n\t\t\thandle: ContainerHandle,\n\t\t): Stream.Stream<string, ContainerRuntimeError> =>\n\t\t\tfollowLogsStream(handle.name).pipe(\n\t\t\t\tStream.mapError(toContractError),\n\t\t\t\t// R-channel: the underlying stream needs DockerHost +\n\t\t\t\t// DockerSpawner from the spawn step. Provide the\n\t\t\t\t// snapshotted base context so the contract surface is\n\t\t\t\t// `R = never`. `Stream.mapError` does NOT drop R; the\n\t\t\t\t// `as`-cast in the previous shape was a release-blocker\n\t\t\t\t// per runtime-docker review issue #3.\n\t\t\t\tStream.provideContext(baseCtx),\n\t\t\t);\n\n\t\tconst pauseAndCommitImpl = (\n\t\t\thandle: ContainerHandle,\n\t\t): Effect.Effect<TaggedImageRef, ContainerRuntimeError> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tyield* assertContainerHandleOwned(handle);\n\t\t\t\tif (handle.status === 'running') {\n\t\t\t\t\tyield* pause(handle.name);\n\t\t\t\t\tyield* assertContainerHandleOwned(handle);\n\t\t\t\t}\n\t\t\t\tconst tag = snapshotTempTag(handle.name);\n\t\t\t\tconst digest = yield* commit(handle.name, tag);\n\t\t\t\treturn { digest, tag };\n\t\t\t}).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.pauseAndCommit'),\n\t\t\t);\n\n\t\tconst pauseImpl = (handle: ContainerHandle): Effect.Effect<void, ContainerRuntimeError> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tyield* assertContainerHandleOwned(handle);\n\t\t\t\tyield* pause(handle.name);\n\t\t\t}).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.pause'),\n\t\t\t);\n\n\t\tconst unpauseImpl = (handle: ContainerHandle): Effect.Effect<void, ContainerRuntimeError> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tyield* assertContainerHandleOwned(handle);\n\t\t\t\tyield* unpause(handle.name);\n\t\t\t}).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.unpause'),\n\t\t\t);\n\n\t\tconst stopImpl = (\n\t\t\thandle: ContainerHandle,\n\t\t\tgrace: Duration.Duration,\n\t\t): Effect.Effect<void, ContainerRuntimeError> => {\n\t\t\tconst seconds = Math.max(0, Math.ceil(Duration.toMillis(grace) / 1000));\n\t\t\treturn Effect.gen(function* () {\n\t\t\t\tyield* assertContainerHandleOwned(handle);\n\t\t\t\tyield* stopContainer(handle.name, seconds);\n\t\t\t}).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.stop'),\n\t\t\t);\n\t\t};\n\n\t\tconst sweepOrphansImpl = (\n\t\t\tlabelMatch: Partial<ContainerLabelTuple>,\n\t\t): Effect.Effect<number, ContainerRuntimeError> =>\n\t\t\tsweepOrphans(labelMatch).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.sweepOrphans'),\n\t\t\t);\n\n\t\tconst removeManagedContainersImpl = (\n\t\t\tlabelMatch: Partial<ContainerLabelTuple>,\n\t\t): Effect.Effect<number, ContainerRuntimeError> =>\n\t\t\tremoveManagedContainers(labelMatch).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.removeManagedContainers'),\n\t\t\t);\n\n\t\tconst removeManagedImagesImpl = (\n\t\t\tlabelMatch: Partial<ContainerLabelTuple>,\n\t\t): Effect.Effect<number, ContainerRuntimeError> =>\n\t\t\tremoveManagedImages(labelMatch).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.removeManagedImages'),\n\t\t\t);\n\n\t\tconst removeManagedNetworksImpl = (\n\t\t\tlabelMatch: Partial<ContainerLabelTuple>,\n\t\t): Effect.Effect<number, ContainerRuntimeError> =>\n\t\t\tremoveManagedNetworks(labelMatch).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.removeManagedNetworks'),\n\t\t\t);\n\n\t\tconst removeManagedVolumesImpl = (\n\t\t\tlabelMatch: Partial<ContainerLabelTuple>,\n\t\t): Effect.Effect<number, ContainerRuntimeError> =>\n\t\t\tremoveManagedVolumes(labelMatch).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.removeManagedVolumes'),\n\t\t\t);\n\n\t\tconst execImpl = (\n\t\t\thandle: ContainerHandle,\n\t\t\targv: ReadonlyArray<string>,\n\t\t\topts?: ExecOptions,\n\t\t): Effect.Effect<ExecResult, ContainerRuntimeError> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tyield* assertContainerHandleOwned(handle);\n\t\t\t\treturn yield* dockerExec(handle.name, argv, {\n\t\t\t\t\tuser: opts?.user,\n\t\t\t\t\tenv: opts?.env,\n\t\t\t\t\tworkdir: opts?.workdir,\n\t\t\t\t});\n\t\t\t}).pipe(\n\t\t\t\t// Contract surface: NEVER promote non-zero exit to failure\n\t\t\t\t// here. The caller is the policy holder.\n\t\t\t\tEffect.map(\n\t\t\t\t\t(r): ExecResult => ({\n\t\t\t\t\t\texitCode: r.exitCode,\n\t\t\t\t\t\tstdout: r.stdout,\n\t\t\t\t\t\tstderr: r.stderr,\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.exec'),\n\t\t\t);\n\n\t\tconst saveImageImpl = (\n\t\t\tref: ImageRef,\n\t\t\topts?: SaveImageOptions,\n\t\t): Stream.Stream<Uint8Array, ContainerRuntimeError> => {\n\t\t\tconst resolved = ref.tag ?? ref.digest;\n\t\t\treturn saveImageStream(resolved, opts).pipe(\n\t\t\t\tStream.mapError(toContractError),\n\t\t\t\tStream.provideContext(baseCtx),\n\t\t\t);\n\t\t};\n\t\tconst saveImagesImpl = (\n\t\t\trefs: ReadonlyArray<ImageRef>,\n\t\t\topts?: SaveImageOptions,\n\t\t): Stream.Stream<Uint8Array, ContainerRuntimeError> => {\n\t\t\tconst resolved = refs.map((ref) => ref.tag ?? ref.digest);\n\t\t\treturn saveImagesStream(resolved, opts).pipe(\n\t\t\t\tStream.mapError(toContractError),\n\t\t\t\tStream.provideContext(baseCtx),\n\t\t\t);\n\t\t};\n\n\t\tconst loadImageContractImpl = (\n\t\t\ttar: Stream.Stream<Uint8Array, unknown>,\n\t\t): Effect.Effect<LoadedImageBundle, ContainerRuntimeError> =>\n\t\t\tloadImageImpl(tar).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.loadImage'),\n\t\t\t);\n\n\t\tconst tagImageContractImpl = (\n\t\t\tsrc: ImageRef,\n\t\t\tnewTag: string,\n\t\t\topts?: TagImageOptions,\n\t\t): Effect.Effect<void, ContainerRuntimeError> => {\n\t\t\tconst resolved = src.tag ?? src.digest;\n\t\t\treturn tagImageImpl(resolved, newTag, opts).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.tagImage'),\n\t\t\t);\n\t\t};\n\n\t\tconst removeImageContractImpl = (ref: ImageRef): Effect.Effect<void, ContainerRuntimeError> => {\n\t\t\tconst resolved = ref.tag ?? ref.digest;\n\t\t\treturn removeImageImpl(resolved).pipe(\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.removeImage'),\n\t\t\t);\n\t\t};\n\n\t\tconst runOneShotImpl = (\n\t\t\tspec: OneShotSpec,\n\t\t): Effect.Effect<ExecResult, ContainerRuntimeError, import('effect').Scope.Scope> =>\n\t\t\tdockerRunOneShot({\n\t\t\t\timage: spec.image.tag ?? spec.image.digest,\n\t\t\t\targv: spec.argv,\n\t\t\t\tenv: spec.env,\n\t\t\t\tmounts: spec.mounts,\n\t\t\t\tnetwork: spec.network,\n\t\t\t\tentrypoint: spec.entrypoint,\n\t\t\t\tuser: spec.user,\n\t\t\t\ttimeoutMillis: spec.timeoutMillis,\n\t\t\t\textraHosts: spec.extraHosts,\n\t\t\t}).pipe(\n\t\t\t\t// Same contract: never promote non-zero exit to failure.\n\t\t\t\tEffect.map(\n\t\t\t\t\t(r): ExecResult => ({\n\t\t\t\t\t\texitCode: r.exitCode,\n\t\t\t\t\t\tstdout: r.stdout,\n\t\t\t\t\t\tstderr: r.stderr,\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\tmapToContractError,\n\t\t\t\tEffect.provide(baseCtx),\n\t\t\t\tEffect.withSpan('runtime.docker.contract.runOneShot'),\n\t\t\t);\n\n\t\treturn ContainerRuntimeService.of({\n\t\t\tensureImage,\n\t\t\tpullImage: pullImageContractImpl,\n\t\t\tensureNetwork: ensureNetworkContractImpl,\n\t\t\tensureContainer: ensureContainerImpl,\n\t\t\texec: execImpl,\n\t\t\trunOneShot: runOneShotImpl,\n\t\t\tinspectByLabels,\n\t\t\tfollowLogs: followLogsImpl,\n\t\t\tpause: pauseImpl,\n\t\t\tpauseAndCommit: pauseAndCommitImpl,\n\t\t\tsaveImage: saveImageImpl,\n\t\t\tsaveImages: saveImagesImpl,\n\t\t\tloadImage: loadImageContractImpl,\n\t\t\ttagImage: tagImageContractImpl,\n\t\t\tremoveImage: removeImageContractImpl,\n\t\t\tunpause: unpauseImpl,\n\t\t\tstop: stopImpl,\n\t\t\tsweepOrphans: sweepOrphansImpl,\n\t\t\tremoveManagedContainers: removeManagedContainersImpl,\n\t\t\tremoveManagedImages: removeManagedImagesImpl,\n\t\t\tremoveManagedNetworks: removeManagedNetworksImpl,\n\t\t\tremoveManagedVolumes: removeManagedVolumesImpl,\n\t\t});\n\t}),\n);\n"],"mappings":"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"}
|