adispatchd 0.0.0-stage → 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/LICENSE +21 -0
- package/README.md +195 -2
- package/dist/api/errors.d.ts +27 -0
- package/dist/api/errors.js +80 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/api/index.d.ts +10 -0
- package/dist/api/index.js +11 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/logs.d.ts +30 -0
- package/dist/api/logs.js +88 -0
- package/dist/api/logs.js.map +1 -0
- package/dist/api/serialize.d.ts +65 -0
- package/dist/api/serialize.js +135 -0
- package/dist/api/serialize.js.map +1 -0
- package/dist/api/server.d.ts +89 -0
- package/dist/api/server.js +751 -0
- package/dist/api/server.js.map +1 -0
- package/dist/api/sse.d.ts +90 -0
- package/dist/api/sse.js +225 -0
- package/dist/api/sse.js.map +1 -0
- package/dist/app.d.ts +173 -0
- package/dist/app.js +488 -0
- package/dist/app.js.map +1 -0
- package/dist/cli/config-validate.d.ts +6 -0
- package/dist/cli/config-validate.js +39 -0
- package/dist/cli/config-validate.js.map +1 -0
- package/dist/cli/control.d.ts +31 -0
- package/dist/cli/control.js +186 -0
- package/dist/cli/control.js.map +1 -0
- package/dist/cli/http-client.d.ts +57 -0
- package/dist/cli/http-client.js +174 -0
- package/dist/cli/http-client.js.map +1 -0
- package/dist/cli/index.d.ts +14 -0
- package/dist/cli/index.js +14 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init-templates.d.ts +20 -0
- package/dist/cli/init-templates.js +275 -0
- package/dist/cli/init-templates.js.map +1 -0
- package/dist/cli/init.d.ts +16 -0
- package/dist/cli/init.js +107 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +25 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/program.d.ts +102 -0
- package/dist/cli/program.js +133 -0
- package/dist/cli/program.js.map +1 -0
- package/dist/cli/service.d.ts +27 -0
- package/dist/cli/service.js +252 -0
- package/dist/cli/service.js.map +1 -0
- package/dist/cli/start.d.ts +22 -0
- package/dist/cli/start.js +133 -0
- package/dist/cli/start.js.map +1 -0
- package/dist/cli/workflow-dry-run.d.ts +13 -0
- package/dist/cli/workflow-dry-run.js +144 -0
- package/dist/cli/workflow-dry-run.js.map +1 -0
- package/dist/config/field-catalog.d.ts +33 -0
- package/dist/config/field-catalog.js +172 -0
- package/dist/config/field-catalog.js.map +1 -0
- package/dist/config/filter-schema.d.ts +15 -0
- package/dist/config/filter-schema.js +110 -0
- package/dist/config/filter-schema.js.map +1 -0
- package/dist/config/index.d.ts +15 -0
- package/dist/config/index.js +16 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/issues.d.ts +27 -0
- package/dist/config/issues.js +37 -0
- package/dist/config/issues.js.map +1 -0
- package/dist/config/loader.d.ts +32 -0
- package/dist/config/loader.js +250 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/manager.d.ts +153 -0
- package/dist/config/manager.js +276 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/config/model.d.ts +334 -0
- package/dist/config/model.js +2 -0
- package/dist/config/model.js.map +1 -0
- package/dist/config/normalize.d.ts +20 -0
- package/dist/config/normalize.js +200 -0
- package/dist/config/normalize.js.map +1 -0
- package/dist/config/parameters.d.ts +37 -0
- package/dist/config/parameters.js +71 -0
- package/dist/config/parameters.js.map +1 -0
- package/dist/config/public.d.ts +6 -0
- package/dist/config/public.js +18 -0
- package/dist/config/public.js.map +1 -0
- package/dist/config/schemas.d.ts +538 -0
- package/dist/config/schemas.js +321 -0
- package/dist/config/schemas.js.map +1 -0
- package/dist/config/snapshot.d.ts +38 -0
- package/dist/config/snapshot.js +57 -0
- package/dist/config/snapshot.js.map +1 -0
- package/dist/config/validate.d.ts +33 -0
- package/dist/config/validate.js +346 -0
- package/dist/config/validate.js.map +1 -0
- package/dist/core/clock.d.ts +59 -0
- package/dist/core/clock.js +133 -0
- package/dist/core/clock.js.map +1 -0
- package/dist/core/duration.d.ts +19 -0
- package/dist/core/duration.js +93 -0
- package/dist/core/duration.js.map +1 -0
- package/dist/core/errors.d.ts +62 -0
- package/dist/core/errors.js +72 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/ids.d.ts +57 -0
- package/dist/core/ids.js +88 -0
- package/dist/core/ids.js.map +1 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.js +14 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/logger.d.ts +100 -0
- package/dist/core/logger.js +207 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/paths.d.ts +84 -0
- package/dist/core/paths.js +138 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/template.d.ts +136 -0
- package/dist/core/template.js +261 -0
- package/dist/core/template.js.map +1 -0
- package/dist/core/types.d.ts +544 -0
- package/dist/core/types.js +172 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/worker-protocol.d.ts +102 -0
- package/dist/core/worker-protocol.js +75 -0
- package/dist/core/worker-protocol.js.map +1 -0
- package/dist/executors/classify.d.ts +25 -0
- package/dist/executors/classify.js +54 -0
- package/dist/executors/classify.js.map +1 -0
- package/dist/executors/dispatcher.d.ts +35 -0
- package/dist/executors/dispatcher.js +68 -0
- package/dist/executors/dispatcher.js.map +1 -0
- package/dist/executors/env.d.ts +43 -0
- package/dist/executors/env.js +66 -0
- package/dist/executors/env.js.map +1 -0
- package/dist/executors/event-parser.d.ts +41 -0
- package/dist/executors/event-parser.js +106 -0
- package/dist/executors/event-parser.js.map +1 -0
- package/dist/executors/index.d.ts +12 -0
- package/dist/executors/index.js +13 -0
- package/dist/executors/index.js.map +1 -0
- package/dist/executors/log-capture.d.ts +57 -0
- package/dist/executors/log-capture.js +155 -0
- package/dist/executors/log-capture.js.map +1 -0
- package/dist/executors/process-identity.d.ts +124 -0
- package/dist/executors/process-identity.js +283 -0
- package/dist/executors/process-identity.js.map +1 -0
- package/dist/executors/shell-executor.d.ts +35 -0
- package/dist/executors/shell-executor.js +478 -0
- package/dist/executors/shell-executor.js.map +1 -0
- package/dist/executors/stream-redactor.d.ts +40 -0
- package/dist/executors/stream-redactor.js +89 -0
- package/dist/executors/stream-redactor.js.map +1 -0
- package/dist/executors/workspace.d.ts +10 -0
- package/dist/executors/workspace.js +47 -0
- package/dist/executors/workspace.js.map +1 -0
- package/dist/filters/evaluate.d.ts +77 -0
- package/dist/filters/evaluate.js +187 -0
- package/dist/filters/evaluate.js.map +1 -0
- package/dist/filters/fields.d.ts +35 -0
- package/dist/filters/fields.js +75 -0
- package/dist/filters/fields.js.map +1 -0
- package/dist/filters/index.d.ts +11 -0
- package/dist/filters/index.js +12 -0
- package/dist/filters/index.js.map +1 -0
- package/dist/filters/iso-date.d.ts +10 -0
- package/dist/filters/iso-date.js +42 -0
- package/dist/filters/iso-date.js.map +1 -0
- package/dist/filters/predicate.d.ts +24 -0
- package/dist/filters/predicate.js +178 -0
- package/dist/filters/predicate.js.map +1 -0
- package/dist/filters/priority.d.ts +51 -0
- package/dist/filters/priority.js +91 -0
- package/dist/filters/priority.js.map +1 -0
- package/dist/filters/pushdown.d.ts +12 -0
- package/dist/filters/pushdown.js +52 -0
- package/dist/filters/pushdown.js.map +1 -0
- package/dist/filters/shell-check.d.ts +110 -0
- package/dist/filters/shell-check.js +304 -0
- package/dist/filters/shell-check.js.map +1 -0
- package/dist/identities/github-app.d.ts +55 -0
- package/dist/identities/github-app.js +160 -0
- package/dist/identities/github-app.js.map +1 -0
- package/dist/identities/index.d.ts +6 -0
- package/dist/identities/index.js +7 -0
- package/dist/identities/index.js.map +1 -0
- package/dist/identities/jwt.d.ts +24 -0
- package/dist/identities/jwt.js +56 -0
- package/dist/identities/jwt.js.map +1 -0
- package/dist/lifecycle/context.d.ts +106 -0
- package/dist/lifecycle/context.js +170 -0
- package/dist/lifecycle/context.js.map +1 -0
- package/dist/lifecycle/engine.d.ts +185 -0
- package/dist/lifecycle/engine.js +551 -0
- package/dist/lifecycle/engine.js.map +1 -0
- package/dist/lifecycle/errors.d.ts +48 -0
- package/dist/lifecycle/errors.js +71 -0
- package/dist/lifecycle/errors.js.map +1 -0
- package/dist/lifecycle/index.d.ts +9 -0
- package/dist/lifecycle/index.js +9 -0
- package/dist/lifecycle/index.js.map +1 -0
- package/dist/lifecycle/performers.d.ts +66 -0
- package/dist/lifecycle/performers.js +179 -0
- package/dist/lifecycle/performers.js.map +1 -0
- package/dist/notifications/index.d.ts +6 -0
- package/dist/notifications/index.js +7 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/notifications/service.d.ts +115 -0
- package/dist/notifications/service.js +364 -0
- package/dist/notifications/service.js.map +1 -0
- package/dist/persistence/actions.d.ts +101 -0
- package/dist/persistence/actions.js +196 -0
- package/dist/persistence/actions.js.map +1 -0
- package/dist/persistence/blocks.d.ts +85 -0
- package/dist/persistence/blocks.js +140 -0
- package/dist/persistence/blocks.js.map +1 -0
- package/dist/persistence/cron-firings.d.ts +55 -0
- package/dist/persistence/cron-firings.js +70 -0
- package/dist/persistence/cron-firings.js.map +1 -0
- package/dist/persistence/database.d.ts +60 -0
- package/dist/persistence/database.js +124 -0
- package/dist/persistence/database.js.map +1 -0
- package/dist/persistence/errors.d.ts +39 -0
- package/dist/persistence/errors.js +67 -0
- package/dist/persistence/errors.js.map +1 -0
- package/dist/persistence/events.d.ts +72 -0
- package/dist/persistence/events.js +83 -0
- package/dist/persistence/events.js.map +1 -0
- package/dist/persistence/index.d.ts +18 -0
- package/dist/persistence/index.js +19 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/instance-lock.d.ts +26 -0
- package/dist/persistence/instance-lock.js +117 -0
- package/dist/persistence/instance-lock.js.map +1 -0
- package/dist/persistence/lock-keys.d.ts +16 -0
- package/dist/persistence/lock-keys.js +41 -0
- package/dist/persistence/lock-keys.js.map +1 -0
- package/dist/persistence/notifications.d.ts +113 -0
- package/dist/persistence/notifications.js +213 -0
- package/dist/persistence/notifications.js.map +1 -0
- package/dist/persistence/persistence.d.ts +46 -0
- package/dist/persistence/persistence.js +42 -0
- package/dist/persistence/persistence.js.map +1 -0
- package/dist/persistence/retention.d.ts +46 -0
- package/dist/persistence/retention.js +68 -0
- package/dist/persistence/retention.js.map +1 -0
- package/dist/persistence/runs.d.ts +215 -0
- package/dist/persistence/runs.js +417 -0
- package/dist/persistence/runs.js.map +1 -0
- package/dist/persistence/schema.d.ts +16 -0
- package/dist/persistence/schema.js +183 -0
- package/dist/persistence/schema.js.map +1 -0
- package/dist/persistence/sqlite.d.ts +49 -0
- package/dist/persistence/sqlite.js +131 -0
- package/dist/persistence/sqlite.js.map +1 -0
- package/dist/runs/controller.d.ts +307 -0
- package/dist/runs/controller.js +1078 -0
- package/dist/runs/controller.js.map +1 -0
- package/dist/runs/errors.d.ts +20 -0
- package/dist/runs/errors.js +26 -0
- package/dist/runs/errors.js.map +1 -0
- package/dist/runs/event-bus.d.ts +106 -0
- package/dist/runs/event-bus.js +105 -0
- package/dist/runs/event-bus.js.map +1 -0
- package/dist/runs/execution.d.ts +39 -0
- package/dist/runs/execution.js +146 -0
- package/dist/runs/execution.js.map +1 -0
- package/dist/runs/index.d.ts +12 -0
- package/dist/runs/index.js +13 -0
- package/dist/runs/index.js.map +1 -0
- package/dist/runs/retention.d.ts +64 -0
- package/dist/runs/retention.js +232 -0
- package/dist/runs/retention.js.map +1 -0
- package/dist/runs/workspace.d.ts +20 -0
- package/dist/runs/workspace.js +51 -0
- package/dist/runs/workspace.js.map +1 -0
- package/dist/scheduler/checks.d.ts +41 -0
- package/dist/scheduler/checks.js +111 -0
- package/dist/scheduler/checks.js.map +1 -0
- package/dist/scheduler/cron.d.ts +32 -0
- package/dist/scheduler/cron.js +83 -0
- package/dist/scheduler/cron.js.map +1 -0
- package/dist/scheduler/dry-run.d.ts +42 -0
- package/dist/scheduler/dry-run.js +167 -0
- package/dist/scheduler/dry-run.js.map +1 -0
- package/dist/scheduler/errors.d.ts +22 -0
- package/dist/scheduler/errors.js +22 -0
- package/dist/scheduler/errors.js.map +1 -0
- package/dist/scheduler/format.d.ts +3 -0
- package/dist/scheduler/format.js +73 -0
- package/dist/scheduler/format.js.map +1 -0
- package/dist/scheduler/index.d.ts +13 -0
- package/dist/scheduler/index.js +14 -0
- package/dist/scheduler/index.js.map +1 -0
- package/dist/scheduler/planner.d.ts +88 -0
- package/dist/scheduler/planner.js +255 -0
- package/dist/scheduler/planner.js.map +1 -0
- package/dist/scheduler/scheduler.d.ts +160 -0
- package/dist/scheduler/scheduler.js +680 -0
- package/dist/scheduler/scheduler.js.map +1 -0
- package/dist/scheduler/state.d.ts +26 -0
- package/dist/scheduler/state.js +25 -0
- package/dist/scheduler/state.js.map +1 -0
- package/dist/scheduler/types.d.ts +197 -0
- package/dist/scheduler/types.js +3 -0
- package/dist/scheduler/types.js.map +1 -0
- package/dist/service/index.d.ts +6 -0
- package/dist/service/index.js +7 -0
- package/dist/service/index.js.map +1 -0
- package/dist/service/install.d.ts +93 -0
- package/dist/service/install.js +250 -0
- package/dist/service/install.js.map +1 -0
- package/dist/service/unit.d.ts +50 -0
- package/dist/service/unit.js +171 -0
- package/dist/service/unit.js.map +1 -0
- package/dist/sources/github/adapter.d.ts +99 -0
- package/dist/sources/github/adapter.js +336 -0
- package/dist/sources/github/adapter.js.map +1 -0
- package/dist/sources/github/fields.d.ts +8 -0
- package/dist/sources/github/fields.js +72 -0
- package/dist/sources/github/fields.js.map +1 -0
- package/dist/sources/github/http.d.ts +100 -0
- package/dist/sources/github/http.js +288 -0
- package/dist/sources/github/http.js.map +1 -0
- package/dist/sources/github/index.d.ts +6 -0
- package/dist/sources/github/index.js +7 -0
- package/dist/sources/github/index.js.map +1 -0
- package/dist/sources/github/pushdown.d.ts +14 -0
- package/dist/sources/github/pushdown.js +47 -0
- package/dist/sources/github/pushdown.js.map +1 -0
- package/dist/sources/github/refs.d.ts +17 -0
- package/dist/sources/github/refs.js +61 -0
- package/dist/sources/github/refs.js.map +1 -0
- package/dist/sources/index.d.ts +6 -0
- package/dist/sources/index.js +7 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/ui/index.d.ts +12 -0
- package/dist/ui/index.js +28 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/public/app.css +239 -0
- package/dist/ui/public/favicon.svg +1 -0
- package/dist/ui/public/index.html +27 -0
- package/dist/ui/public/js/client/api.js +68 -0
- package/dist/ui/public/js/client/app.js +146 -0
- package/dist/ui/public/js/client/dom.js +34 -0
- package/dist/ui/public/js/client/page.js +9 -0
- package/dist/ui/public/js/client/pages/actions.js +35 -0
- package/dist/ui/public/js/client/pages/blocked.js +58 -0
- package/dist/ui/public/js/client/pages/config.js +126 -0
- package/dist/ui/public/js/client/pages/dashboard.js +175 -0
- package/dist/ui/public/js/client/pages/run.js +367 -0
- package/dist/ui/public/js/client/pages/runs.js +72 -0
- package/dist/ui/public/js/client/pages/views.js +80 -0
- package/dist/ui/public/js/client/pages/workflows.js +291 -0
- package/dist/ui/public/js/client/types.js +1 -0
- package/dist/ui/public/js/client/ui.js +152 -0
- package/dist/ui/public/js/shared/dom.js +77 -0
- package/dist/ui/public/js/shared/events.js +88 -0
- package/dist/ui/public/js/shared/format.js +213 -0
- package/dist/ui/public/js/shared/logs.js +136 -0
- package/dist/ui/public/js/shared/params.js +90 -0
- package/dist/ui/public/js/shared/route.js +36 -0
- package/dist/ui/public/js/shared/sort.js +70 -0
- package/dist/ui/public/js/shared/sse.js +193 -0
- package/dist/ui/public/js/shared/throttle.js +65 -0
- package/dist/views/index.d.ts +6 -0
- package/dist/views/index.js +7 -0
- package/dist/views/index.js.map +1 -0
- package/dist/views/service.d.ts +131 -0
- package/dist/views/service.js +264 -0
- package/dist/views/service.js.map +1 -0
- package/docs/api.md +239 -0
- package/docs/configuration-reference.md +1785 -0
- package/docs/cron-semantics.md +96 -0
- package/docs/manual-tests/github-fixture/config.yaml +30 -0
- package/docs/manual-tests/github-fixture/helpers.sh +93 -0
- package/docs/manual-tests/github-fixture/identities.yaml +18 -0
- package/docs/manual-tests/github-fixture/scripts/test-worker.sh +100 -0
- package/docs/manual-tests/github-fixture/sources.yaml +13 -0
- package/docs/manual-tests/github-fixture/views/dependencies.yaml +17 -0
- package/docs/manual-tests/github-fixture/views/needs-maintainer.yaml +17 -0
- package/docs/manual-tests/github-fixture/workflows/coder-test.yaml +76 -0
- package/docs/manual-tests/github-fixture/workflows/commenter-test.yaml +63 -0
- package/docs/manual-tests/github-fixture/workflows/reviewer-test.yaml +60 -0
- package/docs/manual-tests/github.md +1308 -0
- package/docs/manual-tests/process-supervision.md +64 -0
- package/docs/manual-tests/systemd.md +68 -0
- package/docs/operations.md +271 -0
- package/docs/worker-protocol.md +145 -0
- package/examples/config/config.yaml +35 -0
- package/examples/config/identities.yaml +18 -0
- package/examples/config/sources.yaml +13 -0
- package/examples/config/views/needs-maintainer.yaml +15 -0
- package/examples/config/workflows/coder-project-a.yaml +86 -0
- package/examples/config/workflows/deploy.yaml +15 -0
- package/examples/config/workflows/nightly-maintenance.yaml +13 -0
- package/package.json +75 -4
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell executor (Spec §8.2, §8.3, §9, §13, §20): spawns the main worker in
|
|
3
|
+
* its own process group with a minimal environment, captures logs and
|
|
4
|
+
* events, enforces timeouts and supervises cancel/termination.
|
|
5
|
+
*/
|
|
6
|
+
import { spawn } from 'node:child_process';
|
|
7
|
+
import { mkdir, readFile, rename, rm, stat, writeFile } from 'node:fs/promises';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import { MAX_RESULT_FILE_BYTES, OrchestratorError, SecretRedactor, errorMessage, noopLogger, parseWorkerResult, redactValue, systemClock, systemTimers, } from '../core/index.js';
|
|
10
|
+
import { Channel, Dispatcher } from './dispatcher.js';
|
|
11
|
+
import { buildOrchEnv, buildWorkerEnv } from './env.js';
|
|
12
|
+
import { LogBudget, StreamCapture } from './log-capture.js';
|
|
13
|
+
import { defaultProcessInspector, getStartIdentity, processGroupAlive, processGroupExists, } from './process-identity.js';
|
|
14
|
+
import { StreamRedactor } from './stream-redactor.js';
|
|
15
|
+
import { ensureWorkspaceWithin } from './workspace.js';
|
|
16
|
+
/** Executor for local shell workers (V1). */
|
|
17
|
+
export class ShellExecutor {
|
|
18
|
+
type = 'shell';
|
|
19
|
+
deps;
|
|
20
|
+
constructor(options = {}) {
|
|
21
|
+
this.deps = {
|
|
22
|
+
clock: options.clock ?? systemClock,
|
|
23
|
+
timers: options.timers ?? systemTimers,
|
|
24
|
+
logger: options.logger ?? noopLogger,
|
|
25
|
+
baseEnv: options.baseEnv ?? process.env,
|
|
26
|
+
inspector: options.inspector ?? defaultProcessInspector(),
|
|
27
|
+
kill: options.kill ?? ((pid, signal) => process.kill(pid, signal)),
|
|
28
|
+
killConfirmMs: options.killConfirmMs ?? 5000,
|
|
29
|
+
stdioDrainMs: options.stdioDrainMs ?? 2000,
|
|
30
|
+
pollIntervalMs: options.pollIntervalMs ?? 25,
|
|
31
|
+
workspaceBaseDir: options.workspaceBaseDir,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
async start(spec) {
|
|
35
|
+
const proc = new ShellProcess(spec, this.deps);
|
|
36
|
+
await proc.launch();
|
|
37
|
+
// Delivery starts on a later turn, after the caller had the chance to subscribe.
|
|
38
|
+
proc.openDelivery();
|
|
39
|
+
return proc;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
class ShellProcess {
|
|
43
|
+
spec;
|
|
44
|
+
deps;
|
|
45
|
+
log;
|
|
46
|
+
dispatcher;
|
|
47
|
+
outputs;
|
|
48
|
+
events;
|
|
49
|
+
diagnostics;
|
|
50
|
+
secretRedactor = new SecretRedactor();
|
|
51
|
+
child;
|
|
52
|
+
_pid;
|
|
53
|
+
_identity;
|
|
54
|
+
startedAt;
|
|
55
|
+
captures = [];
|
|
56
|
+
stdioClosed = Promise.resolve();
|
|
57
|
+
leaderExited = false;
|
|
58
|
+
exitCode = null;
|
|
59
|
+
exitSignal = null;
|
|
60
|
+
stopReason;
|
|
61
|
+
terminating;
|
|
62
|
+
maxTimer;
|
|
63
|
+
idleTimer;
|
|
64
|
+
outcome;
|
|
65
|
+
resolveDone;
|
|
66
|
+
/** Resolves (via the dispatcher, after all prior notifications) with the outcome. */
|
|
67
|
+
done;
|
|
68
|
+
constructor(spec, deps) {
|
|
69
|
+
this.spec = spec;
|
|
70
|
+
this.deps = deps;
|
|
71
|
+
this.log = deps.logger.child({ component: 'shell-executor', runId: spec.runId });
|
|
72
|
+
this.dispatcher = new Dispatcher(this.log);
|
|
73
|
+
this.outputs = new Channel(this.dispatcher, this.log);
|
|
74
|
+
this.events = new Channel(this.dispatcher, this.log);
|
|
75
|
+
this.diagnostics = new Channel(this.dispatcher, this.log);
|
|
76
|
+
this.startedAt = deps.clock.now();
|
|
77
|
+
this.done = new Promise((resolve) => (this.resolveDone = resolve));
|
|
78
|
+
for (const value of Object.values(spec.secrets))
|
|
79
|
+
this.secretRedactor.add(value);
|
|
80
|
+
}
|
|
81
|
+
get pid() {
|
|
82
|
+
return this._pid;
|
|
83
|
+
}
|
|
84
|
+
get startIdentity() {
|
|
85
|
+
return this._identity;
|
|
86
|
+
}
|
|
87
|
+
onOutput(listener) {
|
|
88
|
+
return this.outputs.subscribe(listener);
|
|
89
|
+
}
|
|
90
|
+
onEvent(listener) {
|
|
91
|
+
return this.events.subscribe(listener);
|
|
92
|
+
}
|
|
93
|
+
onDiagnostic(listener) {
|
|
94
|
+
return this.diagnostics.subscribe(listener);
|
|
95
|
+
}
|
|
96
|
+
wait() {
|
|
97
|
+
return this.done;
|
|
98
|
+
}
|
|
99
|
+
openDelivery() {
|
|
100
|
+
this.dispatcher.open();
|
|
101
|
+
}
|
|
102
|
+
async cancel(graceMs) {
|
|
103
|
+
if (this.outcome || this._pid === undefined) {
|
|
104
|
+
await this.done;
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (!this.leaderExited && this.stopReason === undefined)
|
|
108
|
+
this.stopReason = 'cancel';
|
|
109
|
+
if (!this.leaderExited || processGroupExists(this._pid)) {
|
|
110
|
+
await this.terminate(graceMs ?? this.spec.cancelGraceMs);
|
|
111
|
+
}
|
|
112
|
+
await this.done;
|
|
113
|
+
}
|
|
114
|
+
// -------------------------------------------------------------------------
|
|
115
|
+
// Launch
|
|
116
|
+
// -------------------------------------------------------------------------
|
|
117
|
+
async launch() {
|
|
118
|
+
const spec = this.spec;
|
|
119
|
+
try {
|
|
120
|
+
await this.prepareFiles();
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
this.failStart(err);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
this.captures = await this.openCaptures();
|
|
127
|
+
const env = buildWorkerEnv({
|
|
128
|
+
base: this.deps.baseEnv,
|
|
129
|
+
env: spec.env,
|
|
130
|
+
secrets: spec.secrets,
|
|
131
|
+
orch: buildOrchEnv({
|
|
132
|
+
runId: spec.runId,
|
|
133
|
+
context: spec.context,
|
|
134
|
+
workflowId: spec.workflowId,
|
|
135
|
+
contextFile: spec.files.contextFile,
|
|
136
|
+
resultFile: spec.files.resultFile,
|
|
137
|
+
workspace: spec.workingDirectory,
|
|
138
|
+
}),
|
|
139
|
+
});
|
|
140
|
+
let child;
|
|
141
|
+
try {
|
|
142
|
+
child = spawn(spec.command, [...spec.args], {
|
|
143
|
+
cwd: spec.workingDirectory,
|
|
144
|
+
env,
|
|
145
|
+
detached: true,
|
|
146
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
await this.endCaptures();
|
|
151
|
+
this.failStart(err);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const spawned = await new Promise((resolve) => {
|
|
155
|
+
child.once('spawn', () => resolve(null));
|
|
156
|
+
child.once('error', (err) => resolve(err));
|
|
157
|
+
});
|
|
158
|
+
if (spawned) {
|
|
159
|
+
child.stdout?.destroy();
|
|
160
|
+
child.stderr?.destroy();
|
|
161
|
+
await this.endCaptures();
|
|
162
|
+
this.failStart(spawned);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
this.child = child;
|
|
166
|
+
this._pid = child.pid;
|
|
167
|
+
this.startedAt = this.deps.clock.now();
|
|
168
|
+
child.on('error', (err) => this.log.warn('worker process error', { error: err }));
|
|
169
|
+
this.attachStreams(child);
|
|
170
|
+
child.once('exit', (code, signal) => this.onLeaderExit(code, signal));
|
|
171
|
+
this.startTimers();
|
|
172
|
+
const identity = child.pid !== undefined ? await getStartIdentity(child.pid, this.deps.inspector) : undefined;
|
|
173
|
+
// If the leader exited meanwhile, its PID may already be reused: never expose that identity.
|
|
174
|
+
this._identity = this.leaderExited ? undefined : identity;
|
|
175
|
+
if (!this._identity && !this.leaderExited) {
|
|
176
|
+
this.log.warn('could not determine process start identity', { pid: child.pid });
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
async prepareFiles() {
|
|
180
|
+
const { workingDirectory, files, createDirectory } = this.spec;
|
|
181
|
+
for (const p of [workingDirectory, files.contextFile, files.resultFile, files.stdoutLog, files.stderrLog]) {
|
|
182
|
+
if (!path.isAbsolute(p))
|
|
183
|
+
throw new OrchestratorError('invalid_path', `path must be absolute: ${p}`);
|
|
184
|
+
}
|
|
185
|
+
const baseDir = this.deps.workspaceBaseDir;
|
|
186
|
+
if (baseDir !== undefined) {
|
|
187
|
+
await ensureWorkspaceWithin(baseDir, workingDirectory, createDirectory);
|
|
188
|
+
}
|
|
189
|
+
else if (createDirectory) {
|
|
190
|
+
await mkdir(workingDirectory, { recursive: true });
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
const st = await stat(workingDirectory);
|
|
194
|
+
if (!st.isDirectory()) {
|
|
195
|
+
throw new OrchestratorError('ENOTDIR', `working directory is not a directory: ${workingDirectory}`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
await mkdir(path.dirname(files.contextFile), { recursive: true });
|
|
199
|
+
await mkdir(path.dirname(files.resultFile), { recursive: true });
|
|
200
|
+
// A stale result file must never be attributed to this execution.
|
|
201
|
+
await rm(files.resultFile, { force: true });
|
|
202
|
+
const context = this.secretRedactor.redact(JSON.stringify(this.spec.context, null, 2));
|
|
203
|
+
const tmp = `${files.contextFile}.tmp-${process.pid}`;
|
|
204
|
+
await writeFile(tmp, `${context}\n`, { mode: 0o600 });
|
|
205
|
+
await rename(tmp, files.contextFile);
|
|
206
|
+
}
|
|
207
|
+
async openCaptures() {
|
|
208
|
+
const redactorSecrets = Object.values(this.spec.secrets);
|
|
209
|
+
const sinks = {
|
|
210
|
+
output: (chunk) => this.outputs.emit(chunk),
|
|
211
|
+
event: (type, data, stream) => this.events.emit({ type, data, stream, at: this.deps.clock.now() }),
|
|
212
|
+
diagnostic: (d) => this.emitDiagnostic(d),
|
|
213
|
+
};
|
|
214
|
+
const budget = new LogBudget(this.spec.maxLogBytes);
|
|
215
|
+
const result = [];
|
|
216
|
+
for (const [stream, filePath] of [
|
|
217
|
+
['stdout', this.spec.files.stdoutLog],
|
|
218
|
+
['stderr', this.spec.files.stderrLog],
|
|
219
|
+
]) {
|
|
220
|
+
let openError;
|
|
221
|
+
try {
|
|
222
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
openError = err;
|
|
226
|
+
}
|
|
227
|
+
result.push(new StreamCapture({
|
|
228
|
+
stream,
|
|
229
|
+
filePath,
|
|
230
|
+
openError,
|
|
231
|
+
budget,
|
|
232
|
+
redactor: new StreamRedactor(redactorSecrets),
|
|
233
|
+
clock: this.deps.clock,
|
|
234
|
+
sinks,
|
|
235
|
+
}));
|
|
236
|
+
}
|
|
237
|
+
return result;
|
|
238
|
+
}
|
|
239
|
+
attachStreams(child) {
|
|
240
|
+
const closes = [];
|
|
241
|
+
const pairs = [
|
|
242
|
+
[child.stdout, this.captures[0]],
|
|
243
|
+
[child.stderr, this.captures[1]],
|
|
244
|
+
];
|
|
245
|
+
for (const [source, capture] of pairs) {
|
|
246
|
+
if (!source || !capture)
|
|
247
|
+
continue;
|
|
248
|
+
closes.push(new Promise((resolve) => source.once('close', () => resolve())));
|
|
249
|
+
source.on('error', (err) => this.log.warn('worker stream error', { error: err }));
|
|
250
|
+
source.on('data', (buf) => {
|
|
251
|
+
this.touch();
|
|
252
|
+
if (!capture.push(buf, () => source.resume()))
|
|
253
|
+
source.pause();
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
this.stdioClosed = Promise.all(closes).then(() => undefined);
|
|
257
|
+
}
|
|
258
|
+
failStart(err) {
|
|
259
|
+
const code = err.code;
|
|
260
|
+
const spawnError = {
|
|
261
|
+
...(typeof code === 'string' ? { code } : {}),
|
|
262
|
+
message: this.secretRedactor.redact(errorMessage(err)),
|
|
263
|
+
};
|
|
264
|
+
this.log.warn('worker could not be started', { error: spawnError });
|
|
265
|
+
this.complete({
|
|
266
|
+
exitCode: null,
|
|
267
|
+
signal: null,
|
|
268
|
+
spawnError,
|
|
269
|
+
timedOut: false,
|
|
270
|
+
cancelled: false,
|
|
271
|
+
resultFile: { state: 'missing' },
|
|
272
|
+
startedAt: this.startedAt,
|
|
273
|
+
finishedAt: this.deps.clock.now(),
|
|
274
|
+
logs: { stdoutBytes: 0, stderrBytes: 0, truncated: false },
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
// -------------------------------------------------------------------------
|
|
278
|
+
// Timeouts
|
|
279
|
+
// -------------------------------------------------------------------------
|
|
280
|
+
startTimers() {
|
|
281
|
+
const { maxDurationMs, idleTimeoutMs } = this.spec.timeouts;
|
|
282
|
+
if (maxDurationMs !== undefined) {
|
|
283
|
+
this.maxTimer = this.deps.timers.setTimeout(() => this.onTimeout('max_duration'), maxDurationMs);
|
|
284
|
+
}
|
|
285
|
+
if (idleTimeoutMs !== undefined)
|
|
286
|
+
this.armIdle();
|
|
287
|
+
}
|
|
288
|
+
armIdle() {
|
|
289
|
+
const ms = this.spec.timeouts.idleTimeoutMs;
|
|
290
|
+
if (ms === undefined || this.leaderExited || this.stopReason)
|
|
291
|
+
return;
|
|
292
|
+
if (this.idleTimer)
|
|
293
|
+
this.deps.timers.clearTimeout(this.idleTimer);
|
|
294
|
+
this.idleTimer = this.deps.timers.setTimeout(() => this.onTimeout('idle'), ms);
|
|
295
|
+
}
|
|
296
|
+
/** Any output (including event lines) resets the idle timeout. */
|
|
297
|
+
touch() {
|
|
298
|
+
if (this.idleTimer)
|
|
299
|
+
this.armIdle();
|
|
300
|
+
}
|
|
301
|
+
clearTimers() {
|
|
302
|
+
if (this.maxTimer)
|
|
303
|
+
this.deps.timers.clearTimeout(this.maxTimer);
|
|
304
|
+
if (this.idleTimer)
|
|
305
|
+
this.deps.timers.clearTimeout(this.idleTimer);
|
|
306
|
+
this.maxTimer = undefined;
|
|
307
|
+
this.idleTimer = undefined;
|
|
308
|
+
}
|
|
309
|
+
onTimeout(kind) {
|
|
310
|
+
if (this.leaderExited || this.stopReason)
|
|
311
|
+
return;
|
|
312
|
+
this.stopReason = kind;
|
|
313
|
+
this.clearTimers();
|
|
314
|
+
this.log.info('worker timed out, terminating process group', { timeout: kind });
|
|
315
|
+
this.terminate(this.spec.cancelGraceMs).catch(() => {
|
|
316
|
+
/* kill_failed diagnostic already emitted */
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
// -------------------------------------------------------------------------
|
|
320
|
+
// Termination
|
|
321
|
+
// -------------------------------------------------------------------------
|
|
322
|
+
/** SIGTERM to the group, SIGKILL after `graceMs`, then confirm the group is gone. */
|
|
323
|
+
terminate(graceMs) {
|
|
324
|
+
this.terminating ??= this.doTerminate(graceMs).catch((err) => {
|
|
325
|
+
// Allow a later cancel() to retry.
|
|
326
|
+
this.terminating = undefined;
|
|
327
|
+
throw err;
|
|
328
|
+
});
|
|
329
|
+
return this.terminating;
|
|
330
|
+
}
|
|
331
|
+
async doTerminate(graceMs) {
|
|
332
|
+
this.signalGroup('SIGTERM');
|
|
333
|
+
if (await this.waitGone(graceMs))
|
|
334
|
+
return;
|
|
335
|
+
this.signalGroup('SIGKILL');
|
|
336
|
+
if (await this.waitGone(this.deps.killConfirmMs))
|
|
337
|
+
return;
|
|
338
|
+
const message = `process group ${this._pid} could not be terminated (still alive after SIGKILL)`;
|
|
339
|
+
this.emitDiagnostic({ type: 'kill_failed', at: this.deps.clock.now(), message, details: { pgid: this._pid } });
|
|
340
|
+
throw new OrchestratorError('kill_failed', message, { details: { pgid: this._pid } });
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Signal our own process group. Safe without identity check: while the
|
|
344
|
+
* leader is not reaped its PID cannot be reused, and while group members
|
|
345
|
+
* exist the PGID cannot be reused by a new process.
|
|
346
|
+
*/
|
|
347
|
+
signalGroup(signal) {
|
|
348
|
+
const pgid = this._pid;
|
|
349
|
+
if (pgid === undefined || pgid <= 1)
|
|
350
|
+
return;
|
|
351
|
+
if (this.leaderExited && !processGroupExists(pgid))
|
|
352
|
+
return;
|
|
353
|
+
try {
|
|
354
|
+
this.deps.kill(-pgid, signal);
|
|
355
|
+
}
|
|
356
|
+
catch (err) {
|
|
357
|
+
if (err.code !== 'ESRCH') {
|
|
358
|
+
this.log.warn('failed to signal process group', { pgid, signal, error: err });
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
async isGone() {
|
|
363
|
+
if (!this.leaderExited)
|
|
364
|
+
return false;
|
|
365
|
+
return this._pid === undefined || !(await processGroupAlive(this._pid, this.deps.inspector));
|
|
366
|
+
}
|
|
367
|
+
async waitGone(ms) {
|
|
368
|
+
const step = Math.max(1, this.deps.pollIntervalMs);
|
|
369
|
+
let waited = 0;
|
|
370
|
+
while (!(await this.isGone())) {
|
|
371
|
+
if (waited >= ms)
|
|
372
|
+
return false;
|
|
373
|
+
await this.delay(Math.min(step, ms - waited));
|
|
374
|
+
waited += step;
|
|
375
|
+
}
|
|
376
|
+
return true;
|
|
377
|
+
}
|
|
378
|
+
delay(ms) {
|
|
379
|
+
return new Promise((resolve) => this.deps.timers.setTimeout(resolve, ms));
|
|
380
|
+
}
|
|
381
|
+
// -------------------------------------------------------------------------
|
|
382
|
+
// Completion
|
|
383
|
+
// -------------------------------------------------------------------------
|
|
384
|
+
onLeaderExit(code, signal) {
|
|
385
|
+
this.leaderExited = true;
|
|
386
|
+
this.exitCode = code;
|
|
387
|
+
this.exitSignal = signal;
|
|
388
|
+
this.clearTimers();
|
|
389
|
+
void this.finish().catch((err) => {
|
|
390
|
+
this.log.error('finishing execution failed', { error: err });
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
async finish() {
|
|
394
|
+
const pgid = this._pid;
|
|
395
|
+
if (processGroupExists(pgid)) {
|
|
396
|
+
if (!this.stopReason) {
|
|
397
|
+
this.log.warn('worker exited but left processes in its group; terminating them', { pgid });
|
|
398
|
+
}
|
|
399
|
+
try {
|
|
400
|
+
await this.terminate(this.spec.cancelGraceMs);
|
|
401
|
+
}
|
|
402
|
+
catch {
|
|
403
|
+
// Never report the execution as finished while the group is alive (Spec §13).
|
|
404
|
+
while (await processGroupAlive(pgid, this.deps.inspector))
|
|
405
|
+
await this.delay(1000);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
// Processes outside the group may still hold stdout/stderr open.
|
|
409
|
+
let drainTimer;
|
|
410
|
+
const drained = await Promise.race([
|
|
411
|
+
this.stdioClosed.then(() => true),
|
|
412
|
+
new Promise((resolve) => {
|
|
413
|
+
drainTimer = this.deps.timers.setTimeout(() => resolve(false), this.deps.stdioDrainMs);
|
|
414
|
+
}),
|
|
415
|
+
]);
|
|
416
|
+
if (drainTimer)
|
|
417
|
+
this.deps.timers.clearTimeout(drainTimer);
|
|
418
|
+
if (!drained) {
|
|
419
|
+
this.log.warn('worker output streams still open after exit; closing them', { pid: pgid });
|
|
420
|
+
this.child?.stdout?.destroy();
|
|
421
|
+
this.child?.stderr?.destroy();
|
|
422
|
+
}
|
|
423
|
+
await this.endCaptures();
|
|
424
|
+
const [stdout, stderr] = this.captures;
|
|
425
|
+
const resultFile = await this.inspectResultFile();
|
|
426
|
+
this.complete({
|
|
427
|
+
exitCode: this.exitCode,
|
|
428
|
+
signal: this.exitSignal,
|
|
429
|
+
timedOut: this.stopReason === 'max_duration' || this.stopReason === 'idle' ? this.stopReason : false,
|
|
430
|
+
cancelled: this.stopReason === 'cancel',
|
|
431
|
+
resultFile,
|
|
432
|
+
startedAt: this.startedAt,
|
|
433
|
+
finishedAt: this.deps.clock.now(),
|
|
434
|
+
logs: {
|
|
435
|
+
stdoutBytes: stdout?.bytesWritten ?? 0,
|
|
436
|
+
stderrBytes: stderr?.bytesWritten ?? 0,
|
|
437
|
+
truncated: (stdout?.truncated ?? false) || (stderr?.truncated ?? false),
|
|
438
|
+
},
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
async endCaptures() {
|
|
442
|
+
await Promise.all(this.captures.map((c) => c.end()));
|
|
443
|
+
}
|
|
444
|
+
async inspectResultFile() {
|
|
445
|
+
const file = this.spec.files.resultFile;
|
|
446
|
+
try {
|
|
447
|
+
const st = await stat(file);
|
|
448
|
+
if (!st.isFile())
|
|
449
|
+
return { state: 'invalid', error: 'result file is not a regular file' };
|
|
450
|
+
if (st.size > MAX_RESULT_FILE_BYTES) {
|
|
451
|
+
return { state: 'invalid', error: `result file exceeds ${MAX_RESULT_FILE_BYTES} bytes` };
|
|
452
|
+
}
|
|
453
|
+
const parsed = parseWorkerResult(await readFile(file, 'utf8'));
|
|
454
|
+
if (!parsed.ok)
|
|
455
|
+
return { state: 'invalid', error: this.secretRedactor.redact(parsed.error) };
|
|
456
|
+
// Spec §9.2: redact sensitive values before the result is persisted anywhere.
|
|
457
|
+
const result = redactValue(parsed.result, this.secretRedactor.asRedactor);
|
|
458
|
+
return { state: 'valid', result };
|
|
459
|
+
}
|
|
460
|
+
catch (err) {
|
|
461
|
+
if (err.code === 'ENOENT')
|
|
462
|
+
return { state: 'missing' };
|
|
463
|
+
return { state: 'invalid', error: `result file could not be read: ${errorMessage(err)}` };
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
emitDiagnostic(diagnostic) {
|
|
467
|
+
this.log.warn('executor diagnostic', { type: diagnostic.type, message: diagnostic.message });
|
|
468
|
+
this.diagnostics.emit(diagnostic);
|
|
469
|
+
}
|
|
470
|
+
complete(outcome) {
|
|
471
|
+
if (this.outcome)
|
|
472
|
+
return;
|
|
473
|
+
this.outcome = outcome;
|
|
474
|
+
// Resolve after every notification emitted before has been delivered.
|
|
475
|
+
this.dispatcher.enqueue(() => this.resolveDone(outcome));
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
//# sourceMappingURL=shell-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell-executor.js","sourceRoot":"","sources":["../../src/executors/shell-executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Best-effort, chunk-boundary-safe secret redaction for raw process output
|
|
3
|
+
* (Spec §20.4, §24.8).
|
|
4
|
+
*
|
|
5
|
+
* Works on raw bytes: data is mapped 1:1 to a `latin1` string, so bytes that
|
|
6
|
+
* are not part of a secret are passed through unchanged (also invalid UTF-8).
|
|
7
|
+
*
|
|
8
|
+
* Limits (documented, Spec §24.8): only exact occurrences of registered secret
|
|
9
|
+
* values (and the `\n`-escaped form of multi-line values) are replaced.
|
|
10
|
+
* Transformed secrets (base64, URL-encoded, reversed, split by other output,
|
|
11
|
+
* printed character by character with interleaved bytes) are NOT detected. A
|
|
12
|
+
* worker can always leak secrets it was given; reliable secrecy requires
|
|
13
|
+
* trusted workers.
|
|
14
|
+
*/
|
|
15
|
+
/** Replacement marker for redacted secrets (same as the core logger). */
|
|
16
|
+
export declare const REDACTION_MARKER = "[REDACTED]";
|
|
17
|
+
/** Secrets shorter than this are ignored (too many false positives). */
|
|
18
|
+
export declare const MIN_STREAM_SECRET_LENGTH = 4;
|
|
19
|
+
/**
|
|
20
|
+
* Redacts known secret values from a byte stream split into arbitrary chunks.
|
|
21
|
+
*
|
|
22
|
+
* Holds back the shortest possible tail: only bytes at the end of a chunk
|
|
23
|
+
* that could be the beginning of a secret are withheld until the next chunk
|
|
24
|
+
* (or {@link flush}). Output without such a tail is passed through immediately.
|
|
25
|
+
*/
|
|
26
|
+
export declare class StreamRedactor {
|
|
27
|
+
/** Secrets as latin1 strings of their UTF-8 bytes, longest first. */
|
|
28
|
+
private readonly secrets;
|
|
29
|
+
private carry;
|
|
30
|
+
constructor(secretValues: Iterable<string>);
|
|
31
|
+
/** True if at least one secret is registered (otherwise data passes unchanged). */
|
|
32
|
+
get active(): boolean;
|
|
33
|
+
/** Feed a chunk; returns the bytes that are safe to emit now. */
|
|
34
|
+
push(chunk: Buffer): Buffer;
|
|
35
|
+
/** Emit the withheld tail (it is not a complete secret). */
|
|
36
|
+
flush(): Buffer;
|
|
37
|
+
private redact;
|
|
38
|
+
/** Length of the longest suffix of `text` that is a proper prefix of a secret. */
|
|
39
|
+
private pendingPrefixLength;
|
|
40
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Best-effort, chunk-boundary-safe secret redaction for raw process output
|
|
3
|
+
* (Spec §20.4, §24.8).
|
|
4
|
+
*
|
|
5
|
+
* Works on raw bytes: data is mapped 1:1 to a `latin1` string, so bytes that
|
|
6
|
+
* are not part of a secret are passed through unchanged (also invalid UTF-8).
|
|
7
|
+
*
|
|
8
|
+
* Limits (documented, Spec §24.8): only exact occurrences of registered secret
|
|
9
|
+
* values (and the `\n`-escaped form of multi-line values) are replaced.
|
|
10
|
+
* Transformed secrets (base64, URL-encoded, reversed, split by other output,
|
|
11
|
+
* printed character by character with interleaved bytes) are NOT detected. A
|
|
12
|
+
* worker can always leak secrets it was given; reliable secrecy requires
|
|
13
|
+
* trusted workers.
|
|
14
|
+
*/
|
|
15
|
+
/** Replacement marker for redacted secrets (same as the core logger). */
|
|
16
|
+
export const REDACTION_MARKER = '[REDACTED]';
|
|
17
|
+
/** Secrets shorter than this are ignored (too many false positives). */
|
|
18
|
+
export const MIN_STREAM_SECRET_LENGTH = 4;
|
|
19
|
+
/**
|
|
20
|
+
* Redacts known secret values from a byte stream split into arbitrary chunks.
|
|
21
|
+
*
|
|
22
|
+
* Holds back the shortest possible tail: only bytes at the end of a chunk
|
|
23
|
+
* that could be the beginning of a secret are withheld until the next chunk
|
|
24
|
+
* (or {@link flush}). Output without such a tail is passed through immediately.
|
|
25
|
+
*/
|
|
26
|
+
export class StreamRedactor {
|
|
27
|
+
/** Secrets as latin1 strings of their UTF-8 bytes, longest first. */
|
|
28
|
+
secrets;
|
|
29
|
+
carry = '';
|
|
30
|
+
constructor(secretValues) {
|
|
31
|
+
const set = new Set();
|
|
32
|
+
for (const value of secretValues) {
|
|
33
|
+
if (typeof value !== 'string' || value.length < MIN_STREAM_SECRET_LENGTH)
|
|
34
|
+
continue;
|
|
35
|
+
set.add(toLatin1(value));
|
|
36
|
+
if (value.includes('\n'))
|
|
37
|
+
set.add(toLatin1(value.replace(/\n/g, '\\n')));
|
|
38
|
+
}
|
|
39
|
+
this.secrets = [...set].sort((a, b) => b.length - a.length);
|
|
40
|
+
}
|
|
41
|
+
/** True if at least one secret is registered (otherwise data passes unchanged). */
|
|
42
|
+
get active() {
|
|
43
|
+
return this.secrets.length > 0;
|
|
44
|
+
}
|
|
45
|
+
/** Feed a chunk; returns the bytes that are safe to emit now. */
|
|
46
|
+
push(chunk) {
|
|
47
|
+
if (!this.active)
|
|
48
|
+
return chunk;
|
|
49
|
+
const text = this.redact(this.carry + chunk.toString('latin1'));
|
|
50
|
+
const hold = this.pendingPrefixLength(text);
|
|
51
|
+
this.carry = text.slice(text.length - hold);
|
|
52
|
+
return Buffer.from(text.slice(0, text.length - hold), 'latin1');
|
|
53
|
+
}
|
|
54
|
+
/** Emit the withheld tail (it is not a complete secret). */
|
|
55
|
+
flush() {
|
|
56
|
+
const rest = this.carry;
|
|
57
|
+
this.carry = '';
|
|
58
|
+
return Buffer.from(rest, 'latin1');
|
|
59
|
+
}
|
|
60
|
+
redact(text) {
|
|
61
|
+
let out = text;
|
|
62
|
+
for (const secret of this.secrets) {
|
|
63
|
+
if (out.includes(secret))
|
|
64
|
+
out = out.split(secret).join(REDACTION_MARKER);
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
/** Length of the longest suffix of `text` that is a proper prefix of a secret. */
|
|
69
|
+
pendingPrefixLength(text) {
|
|
70
|
+
let best = 0;
|
|
71
|
+
for (const secret of this.secrets) {
|
|
72
|
+
const first = secret.charCodeAt(0);
|
|
73
|
+
const from = Math.max(0, text.length - (secret.length - 1));
|
|
74
|
+
for (let i = from; i < text.length; i++) {
|
|
75
|
+
if (text.length - i <= best)
|
|
76
|
+
break;
|
|
77
|
+
if (text.charCodeAt(i) === first && secret.startsWith(text.slice(i))) {
|
|
78
|
+
best = text.length - i;
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return best;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function toLatin1(value) {
|
|
87
|
+
return Buffer.from(value, 'utf8').toString('latin1');
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=stream-redactor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-redactor.js","sourceRoot":"","sources":["../../src/executors/stream-redactor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensure `target` exists as a directory strictly below `baseDir` (never
|
|
3
|
+
* `baseDir` itself). Directories are created one segment at a time and each
|
|
4
|
+
* segment's real path is checked BEFORE anything is created below it, so a
|
|
5
|
+
* symlink inside `baseDir` cannot cause directories to be created outside.
|
|
6
|
+
* With `create: false` the existing directory is only verified.
|
|
7
|
+
*
|
|
8
|
+
* @throws PathTraversalError on lexical or symlink escapes
|
|
9
|
+
*/
|
|
10
|
+
export declare function ensureWorkspaceWithin(baseDir: string, target: string, create: boolean): Promise<string>;
|