@b00dea/cockpit 0.0.0-bootstrap.0 → 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/CHANGELOG.md +375 -0
- package/LICENSE +21 -0
- package/README.md +21 -1
- package/bin/cockpit.mjs +33 -0
- package/cockpit.schema.json +2574 -0
- package/dist/autonomy.d.ts +44 -0
- package/dist/autonomy.js +156 -0
- package/dist/bounded-read.d.ts +14 -0
- package/dist/bounded-read.js +42 -0
- package/dist/browser/commands.d.ts +62 -0
- package/dist/browser/commands.js +349 -0
- package/dist/browser/package-paths.d.ts +1 -0
- package/dist/browser/package-paths.js +6 -0
- package/dist/browser/proxy.d.ts +22 -0
- package/dist/browser/proxy.js +37 -0
- package/dist/browser/runtime.d.ts +117 -0
- package/dist/browser/runtime.js +183 -0
- package/dist/browser/surfaces.d.ts +141 -0
- package/dist/browser/surfaces.js +556 -0
- package/dist/browser/ui-gate.d.ts +15 -0
- package/dist/browser/ui-gate.js +18 -0
- package/dist/cli-guard.d.ts +5 -0
- package/dist/cli-guard.js +71 -0
- package/dist/cli-main.d.ts +139 -0
- package/dist/cli-main.js +1405 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +16 -0
- package/dist/command-table.d.ts +113 -0
- package/dist/command-table.js +512 -0
- package/dist/config/load.d.ts +171 -0
- package/dist/config/load.js +345 -0
- package/dist/config/sibling-toml.d.ts +48 -0
- package/dist/config/sibling-toml.js +160 -0
- package/dist/config/surface-tools-toml.d.ts +9 -0
- package/dist/config/surface-tools-toml.js +37 -0
- package/dist/config/verified-write.d.ts +43 -0
- package/dist/config/verified-write.js +89 -0
- package/dist/diagnostics.d.ts +26 -0
- package/dist/diagnostics.js +335 -0
- package/dist/emit.d.ts +22 -0
- package/dist/emit.js +43 -0
- package/dist/entrypoint-kinds.d.ts +3 -0
- package/dist/entrypoint-kinds.js +11 -0
- package/dist/environment/application/destructive.d.ts +6 -0
- package/dist/environment/application/destructive.js +425 -0
- package/dist/environment/application/doctor.d.ts +89 -0
- package/dist/environment/application/doctor.js +235 -0
- package/dist/environment/application/guard.d.ts +43 -0
- package/dist/environment/application/guard.js +622 -0
- package/dist/environment/application/health.d.ts +134 -0
- package/dist/environment/application/health.js +379 -0
- package/dist/environment/application/lifecycle-context.d.ts +228 -0
- package/dist/environment/application/lifecycle-context.js +154 -0
- package/dist/environment/application/lifecycle-state.d.ts +25 -0
- package/dist/environment/application/lifecycle-state.js +201 -0
- package/dist/environment/application/lifecycle.d.ts +17 -0
- package/dist/environment/application/lifecycle.js +729 -0
- package/dist/environment/application/logs.d.ts +45 -0
- package/dist/environment/application/logs.js +127 -0
- package/dist/environment/application/setup.d.ts +129 -0
- package/dist/environment/application/setup.js +741 -0
- package/dist/environment/application/shared.d.ts +11 -0
- package/dist/environment/application/shared.js +61 -0
- package/dist/environment/claims.d.ts +389 -0
- package/dist/environment/claims.js +1709 -0
- package/dist/environment/codex-hook-trust.d.ts +11 -0
- package/dist/environment/codex-hook-trust.js +185 -0
- package/dist/environment/compose-environment.d.ts +1 -0
- package/dist/environment/compose-environment.js +6 -0
- package/dist/environment/compose-ownership.d.ts +21 -0
- package/dist/environment/compose-ownership.js +117 -0
- package/dist/environment/compose-topology.d.ts +117 -0
- package/dist/environment/compose-topology.js +413 -0
- package/dist/environment/contract.d.ts +489 -0
- package/dist/environment/contract.js +761 -0
- package/dist/environment/declaration.d.ts +14 -0
- package/dist/environment/declaration.js +39 -0
- package/dist/environment/destructive-composition.d.ts +29 -0
- package/dist/environment/destructive-composition.js +333 -0
- package/dist/environment/docker-daemon.d.ts +30 -0
- package/dist/environment/docker-daemon.js +78 -0
- package/dist/environment/docker-endpoint.d.ts +10 -0
- package/dist/environment/docker-endpoint.js +19 -0
- package/dist/environment/env-schema-observation.d.ts +46 -0
- package/dist/environment/env-schema-observation.js +241 -0
- package/dist/environment/evidence.d.ts +136 -0
- package/dist/environment/evidence.js +437 -0
- package/dist/environment/executable.d.ts +26 -0
- package/dist/environment/executable.js +167 -0
- package/dist/environment/generated-application/authorities.d.ts +5 -0
- package/dist/environment/generated-application/authorities.js +61 -0
- package/dist/environment/generated-application/bootstrap-skill.d.ts +16 -0
- package/dist/environment/generated-application/bootstrap-skill.js +328 -0
- package/dist/environment/generated-application/check.d.ts +13 -0
- package/dist/environment/generated-application/check.js +189 -0
- package/dist/environment/generated-application/custom-surface.d.ts +26 -0
- package/dist/environment/generated-application/custom-surface.js +289 -0
- package/dist/environment/generated-application/prepare.d.ts +29 -0
- package/dist/environment/generated-application/prepare.js +276 -0
- package/dist/environment/generated-application/publication.d.ts +33 -0
- package/dist/environment/generated-application/publication.js +547 -0
- package/dist/environment/generated-application/shared.d.ts +484 -0
- package/dist/environment/generated-application/shared.js +349 -0
- package/dist/environment/generated-application/surface-observation.d.ts +4 -0
- package/dist/environment/generated-application/surface-observation.js +69 -0
- package/dist/environment/generated-application/surface-outputs.d.ts +71 -0
- package/dist/environment/generated-application/surface-outputs.js +389 -0
- package/dist/environment/generated-application/surfaces.d.ts +3 -0
- package/dist/environment/generated-application/surfaces.js +699 -0
- package/dist/environment/generated-application/sync.d.ts +6 -0
- package/dist/environment/generated-application/sync.js +109 -0
- package/dist/environment/git-observation.d.ts +183 -0
- package/dist/environment/git-observation.js +544 -0
- package/dist/environment/health-composition.d.ts +11 -0
- package/dist/environment/health-composition.js +628 -0
- package/dist/environment/host-observation.d.ts +56 -0
- package/dist/environment/host-observation.js +52 -0
- package/dist/environment/identity.d.ts +48 -0
- package/dist/environment/identity.js +85 -0
- package/dist/environment/init-application.d.ts +308 -0
- package/dist/environment/init-application.js +697 -0
- package/dist/environment/install-policy-observation.d.ts +71 -0
- package/dist/environment/install-policy-observation.js +284 -0
- package/dist/environment/install-policy.d.ts +48 -0
- package/dist/environment/install-policy.js +96 -0
- package/dist/environment/instance.d.ts +33 -0
- package/dist/environment/instance.js +122 -0
- package/dist/environment/instruction-pointer.d.ts +19 -0
- package/dist/environment/instruction-pointer.js +144 -0
- package/dist/environment/lifecycle-composition.d.ts +29 -0
- package/dist/environment/lifecycle-composition.js +675 -0
- package/dist/environment/lifecycle-stage.d.ts +115 -0
- package/dist/environment/lifecycle-stage.js +398 -0
- package/dist/environment/lifecycle.d.ts +75 -0
- package/dist/environment/lifecycle.js +354 -0
- package/dist/environment/logs.d.ts +132 -0
- package/dist/environment/logs.js +519 -0
- package/dist/environment/observations.d.ts +46 -0
- package/dist/environment/observations.js +344 -0
- package/dist/environment/operator-application.d.ts +50 -0
- package/dist/environment/operator-application.js +155 -0
- package/dist/environment/ports.d.ts +182 -0
- package/dist/environment/ports.js +1205 -0
- package/dist/environment/posture-observation.d.ts +68 -0
- package/dist/environment/posture-observation.js +253 -0
- package/dist/environment/read-composition.d.ts +27 -0
- package/dist/environment/read-composition.js +352 -0
- package/dist/environment/readiness-composition.d.ts +38 -0
- package/dist/environment/readiness-composition.js +130 -0
- package/dist/environment/reclaim.d.ts +333 -0
- package/dist/environment/reclaim.js +1835 -0
- package/dist/environment/repository-identity.d.ts +13 -0
- package/dist/environment/repository-identity.js +108 -0
- package/dist/environment/runtime-measurement-record.d.ts +38 -0
- package/dist/environment/runtime-measurement-record.js +111 -0
- package/dist/environment/runtime-measurement.d.ts +27 -0
- package/dist/environment/runtime-measurement.js +224 -0
- package/dist/environment/runtime-probe-residue.d.ts +43 -0
- package/dist/environment/runtime-probe-residue.js +148 -0
- package/dist/environment/runtime-probe.d.ts +72 -0
- package/dist/environment/runtime-probe.js +725 -0
- package/dist/environment/runtime.d.ts +505 -0
- package/dist/environment/runtime.js +2335 -0
- package/dist/environment/seed.d.ts +16 -0
- package/dist/environment/seed.js +43 -0
- package/dist/environment/selftest-application.d.ts +86 -0
- package/dist/environment/selftest-application.js +713 -0
- package/dist/environment/sensitive.d.ts +3 -0
- package/dist/environment/sensitive.js +48 -0
- package/dist/environment/setup-observation.d.ts +62 -0
- package/dist/environment/setup-observation.js +1473 -0
- package/dist/environment/setup.d.ts +43 -0
- package/dist/environment/setup.js +176 -0
- package/dist/environment/sibling-instructions.d.ts +33 -0
- package/dist/environment/sibling-instructions.js +224 -0
- package/dist/environment/sibling-registration.d.ts +45 -0
- package/dist/environment/sibling-registration.js +538 -0
- package/dist/environment/state.d.ts +371 -0
- package/dist/environment/state.js +2013 -0
- package/dist/environment/templates.d.ts +140 -0
- package/dist/environment/templates.js +685 -0
- package/dist/environment/tool-registration.d.ts +9 -0
- package/dist/environment/tool-registration.js +96 -0
- package/dist/environment/upgrade-application.d.ts +19 -0
- package/dist/environment/upgrade-application.js +175 -0
- package/dist/environment-exec/execute.d.ts +102 -0
- package/dist/environment-exec/execute.js +1175 -0
- package/dist/environment-exec/libexec-program.d.ts +6 -0
- package/dist/environment-exec/libexec-program.js +22 -0
- package/dist/environment-exec/verified-digest.d.ts +4 -0
- package/dist/environment-exec/verified-digest.js +16 -0
- package/dist/exact-keys.d.ts +7 -0
- package/dist/exact-keys.js +15 -0
- package/dist/fix-catalogue.d.ts +32 -0
- package/dist/fix-catalogue.js +60 -0
- package/dist/freshness.d.ts +29 -0
- package/dist/freshness.js +75 -0
- package/dist/generated-environment/adopt.d.ts +16 -0
- package/dist/generated-environment/adopt.js +275 -0
- package/dist/generated-environment/command.d.ts +47 -0
- package/dist/generated-environment/command.js +75 -0
- package/dist/generated-environment/transaction.d.ts +186 -0
- package/dist/generated-environment/transaction.js +1770 -0
- package/dist/grading/evaluate.d.ts +71 -0
- package/dist/grading/evaluate.js +403 -0
- package/dist/grading/grade.d.ts +33 -0
- package/dist/grading/grade.js +57 -0
- package/dist/guards/evaluator.d.ts +113 -0
- package/dist/guards/evaluator.js +1226 -0
- package/dist/guards/harness-adapter.d.ts +17 -0
- package/dist/guards/harness-adapter.js +57 -0
- package/dist/guards/host.d.ts +8 -0
- package/dist/guards/host.js +10 -0
- package/dist/guards/invocation-parser.d.ts +66 -0
- package/dist/guards/invocation-parser.js +595 -0
- package/dist/guards/local-identity.d.ts +40 -0
- package/dist/guards/local-identity.js +123 -0
- package/dist/guards/policy-pin.d.ts +13 -0
- package/dist/guards/policy-pin.js +175 -0
- package/dist/guards/protected-locations.d.ts +62 -0
- package/dist/guards/protected-locations.js +461 -0
- package/dist/guards/read-only.d.ts +37 -0
- package/dist/guards/read-only.js +315 -0
- package/dist/init/command.d.ts +40 -0
- package/dist/init/command.js +310 -0
- package/dist/init/derive.d.ts +51 -0
- package/dist/init/derive.js +715 -0
- package/dist/init/draft.d.ts +138 -0
- package/dist/init/draft.js +1205 -0
- package/dist/init/render.d.ts +35 -0
- package/dist/init/render.js +82 -0
- package/dist/init/scaffold.d.ts +53 -0
- package/dist/init/scaffold.js +121 -0
- package/dist/invocation.d.ts +13 -0
- package/dist/invocation.js +20 -0
- package/dist/package-metadata.d.ts +9 -0
- package/dist/package-metadata.js +19 -0
- package/dist/readiness.d.ts +53 -0
- package/dist/readiness.js +88 -0
- package/dist/references/named.d.ts +24 -0
- package/dist/references/named.js +27 -0
- package/dist/refusal.d.ts +15 -0
- package/dist/refusal.js +7 -0
- package/dist/registry-derivation.d.ts +31 -0
- package/dist/registry-derivation.js +32 -0
- package/dist/registry-resolve/command.d.ts +47 -0
- package/dist/registry-resolve/command.js +226 -0
- package/dist/registry-resolve/registry.d.ts +68 -0
- package/dist/registry-resolve/registry.js +292 -0
- package/dist/registry-resolve/render-shell.d.ts +18 -0
- package/dist/registry-resolve/render-shell.js +36 -0
- package/dist/repair.d.ts +29 -0
- package/dist/repair.js +8 -0
- package/dist/schema-json.d.ts +1 -0
- package/dist/schema-json.js +177 -0
- package/dist/schema.d.ts +1322 -0
- package/dist/schema.js +934 -0
- package/dist/setup/command.d.ts +4 -0
- package/dist/setup/command.js +4 -0
- package/dist/sha256.d.ts +1 -0
- package/dist/sha256.js +4 -0
- package/dist/surfaces/adoption.d.ts +41 -0
- package/dist/surfaces/adoption.js +217 -0
- package/dist/surfaces/consumer-instructions.d.ts +20 -0
- package/dist/surfaces/consumer-instructions.js +43 -0
- package/dist/surfaces/contract.d.ts +42 -0
- package/dist/surfaces/contract.js +169 -0
- package/dist/surfaces/core-declarations.d.ts +24 -0
- package/dist/surfaces/core-declarations.js +79 -0
- package/dist/surfaces/development-markers.d.ts +1 -0
- package/dist/surfaces/development-markers.js +18 -0
- package/dist/surfaces/generator-adapter.d.ts +71 -0
- package/dist/surfaces/generator-adapter.js +809 -0
- package/dist/surfaces/harness-registry.d.ts +180 -0
- package/dist/surfaces/harness-registry.js +117 -0
- package/dist/surfaces/mcp.d.ts +95 -0
- package/dist/surfaces/mcp.js +186 -0
- package/dist/surfaces/merge.d.ts +30 -0
- package/dist/surfaces/merge.js +105 -0
- package/dist/surfaces/ownership.d.ts +190 -0
- package/dist/surfaces/ownership.js +795 -0
- package/dist/surfaces/projection.d.ts +136 -0
- package/dist/surfaces/projection.js +681 -0
- package/dist/surfaces/render.d.ts +118 -0
- package/dist/surfaces/render.js +633 -0
- package/dist/surfaces/restrictions.d.ts +130 -0
- package/dist/surfaces/restrictions.js +447 -0
- package/dist/surfaces/selftest.d.ts +162 -0
- package/dist/surfaces/selftest.js +393 -0
- package/dist/surfaces/skill-contract.d.ts +85 -0
- package/dist/surfaces/skill-contract.js +449 -0
- package/dist/surfaces/sync.d.ts +57 -0
- package/dist/surfaces/sync.js +164 -0
- package/dist/team-metadata.d.ts +41 -0
- package/dist/team-metadata.js +512 -0
- package/dist/testing/gates.d.ts +91 -0
- package/dist/testing/gates.js +182 -0
- package/dist/testing/hooks.d.ts +59 -0
- package/dist/testing/hooks.js +139 -0
- package/dist/testing/verdict.d.ts +29 -0
- package/dist/testing/verdict.js +62 -0
- package/dist/work-orders/application.d.ts +99 -0
- package/dist/work-orders/application.js +383 -0
- package/dist/work-orders/composition.d.ts +124 -0
- package/dist/work-orders/composition.js +1010 -0
- package/dist/work-orders/contract.d.ts +61 -0
- package/dist/work-orders/contract.js +122 -0
- package/dist/work-orders/store.d.ts +158 -0
- package/dist/work-orders/store.js +197 -0
- package/docs/README.md +65 -0
- package/docs/architecture.md +136 -0
- package/docs/capability-matrix.md +50 -0
- package/docs/cli-reference.md +599 -0
- package/docs/command-list.md +51 -0
- package/docs/compose-patterns.md +99 -0
- package/docs/concepts.md +171 -0
- package/docs/configuration-essentials.md +172 -0
- package/docs/configuration-reference.md +621 -0
- package/docs/environment.md +760 -0
- package/docs/extending.md +43 -0
- package/docs/faq.md +111 -0
- package/docs/getting-started.md +608 -0
- package/docs/harness-surfaces.md +433 -0
- package/docs/joining-a-team.md +76 -0
- package/docs/release-policy.md +49 -0
- package/docs/safety-and-autonomy.md +419 -0
- package/docs/troubleshooting.md +361 -0
- package/docs/tutorial.md +170 -0
- package/docs/work-and-browser.md +254 -0
- package/libexec/browser-operation.cjs +186 -0
- package/libexec/fence-marker.cjs +101 -0
- package/libexec/fence-marker.d.cts +24 -0
- package/libexec/fenced-group-runner.cjs +77 -0
- package/libexec/fenced-supervisor.cjs +137 -0
- package/libexec/generated-filesystem.cjs +731 -0
- package/libexec/install-filesystem.cjs +225 -0
- package/libexec/rulesync-generator.NOTICE.md +1112 -0
- package/libexec/rulesync-generator.cjs +743 -0
- package/libexec/surface-generator-worker.cjs +266 -0
- package/libexec/surface-output-reader.cjs +99 -0
- package/libexec/surface-scratch-cleanup.cjs +14 -0
- package/libexec/validate-harness-evidence.d.mts +183 -0
- package/libexec/validate-harness-evidence.mjs +1312 -0
- package/package.json +76 -1
- package/surfaces/README.md +33 -0
- package/surfaces/agents/evaluator.agent.md +76 -0
- package/surfaces/guards/bash-guard.sh +48 -0
- package/surfaces/guards/claude.adapter.json +25 -0
- package/surfaces/guards/codex.adapter.json +24 -0
- package/surfaces/guards/opencode.adapter.json +25 -0
- package/surfaces/references/browser.md +63 -0
- package/surfaces/references/test-data-and-personas.md +84 -0
- package/surfaces/references/testing-tiers.md +11 -0
- package/surfaces/skills/cockpit-browser.skill.md +54 -0
- package/surfaces/skills/cockpit-explain.skill.md +32 -0
- package/surfaces/skills/cockpit-fix.skill.md +37 -0
- package/surfaces/skills/cockpit-setup.skill.md +39 -0
- package/surfaces/skills/cockpit-work.skill.md +34 -0
- package/surfaces/skills/collection.json +5 -0
- package/surfaces/skills/procedures/explain.md +61 -0
- package/surfaces/skills/procedures/fix.md +81 -0
- package/surfaces/skills/procedures/setup.md +379 -0
- package/surfaces/skills/procedures/work.md +105 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// Runs one fenced action as the leader of its own process group, under libexec/fenced-supervisor.cjs.
|
|
4
|
+
//
|
|
5
|
+
// argv: <config>, base64url JSON { command, args, argv0, cwd, spawnNotAfter, fence, approved }, where
|
|
6
|
+
// `approved` is the active marker the executor published ({ supervisorPid, markerDev, markerIno,
|
|
7
|
+
// parentDev, parentIno }).
|
|
8
|
+
// fd 3 to the supervisor: 'EXPIRED\n' when the spawn deadline had passed (the action never starts),
|
|
9
|
+
// otherwise exactly one 'DONE <exit code>\n' when the action closes.
|
|
10
|
+
// stdin from the supervisor: 'STOP\n' stops the group. Any other input, or stdin closing without it,
|
|
11
|
+
// means the supervisor is gone: the runner then records a 'terminating' marker naming its group, so
|
|
12
|
+
// a later repair can prove the group ended, before it stops the group itself.
|
|
13
|
+
const { spawn } = require('node:child_process')
|
|
14
|
+
const fs = require('node:fs')
|
|
15
|
+
const path = require('node:path')
|
|
16
|
+
const { replaceApprovedActiveMarker, syncDirectory } = require('./fence-marker.cjs')
|
|
17
|
+
|
|
18
|
+
const STOP_KILL_DELAY_MS = 50
|
|
19
|
+
|
|
20
|
+
const config = JSON.parse(Buffer.from(process.argv[2], 'base64url').toString('utf8'))
|
|
21
|
+
const { fence, approved } = config
|
|
22
|
+
|
|
23
|
+
// The group ends only through SIGKILL below, after the action had its SIGTERM; a stray terminal
|
|
24
|
+
// signal must not take the runner down and orphan the action outside its fence.
|
|
25
|
+
process.on('SIGTERM', () => {})
|
|
26
|
+
process.on('SIGINT', () => {})
|
|
27
|
+
|
|
28
|
+
const expired = config.spawnNotAfter !== undefined && Date.now() > Date.parse(config.spawnNotAfter)
|
|
29
|
+
const child = expired ? undefined : spawn(config.command, config.args, {
|
|
30
|
+
argv0: config.argv0, cwd: config.cwd, env: process.env, stdio: ['ignore', 'inherit', 'inherit'],
|
|
31
|
+
})
|
|
32
|
+
let reported = false
|
|
33
|
+
const report = code => {
|
|
34
|
+
if (reported) return
|
|
35
|
+
reported = true
|
|
36
|
+
fs.writeSync(3, `DONE ${Number.isInteger(code) ? code : 1}\n`)
|
|
37
|
+
}
|
|
38
|
+
if (expired) fs.writeSync(3, 'EXPIRED\n')
|
|
39
|
+
else {
|
|
40
|
+
child.once('error', () => report(1))
|
|
41
|
+
child.once('close', code => report(code))
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function publishTerminating() {
|
|
45
|
+
if (!replaceApprovedActiveMarker(fence, approved, 'runner', { status: 'terminating', groupPid: process.pid })) return false
|
|
46
|
+
try {
|
|
47
|
+
try { fs.unlinkSync(fence.socketPath) } catch (error) { if (error.code !== 'ENOENT') return false }
|
|
48
|
+
syncDirectory(path.dirname(fence.socketPath))
|
|
49
|
+
return true
|
|
50
|
+
} catch {
|
|
51
|
+
// The 'terminating' marker is already durable; repair still waits for the socket to go.
|
|
52
|
+
return false
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let stopping = false
|
|
57
|
+
let controlled = false
|
|
58
|
+
function stop(supervisorLost) {
|
|
59
|
+
if (stopping) return
|
|
60
|
+
if (supervisorLost) publishTerminating()
|
|
61
|
+
stopping = true
|
|
62
|
+
process.kill(-process.pid, 'SIGTERM')
|
|
63
|
+
setTimeout(() => process.kill(-process.pid, 'SIGKILL'), STOP_KILL_DELAY_MS)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let input = ''
|
|
67
|
+
process.stdin.setEncoding('utf8')
|
|
68
|
+
process.stdin.on('data', chunk => {
|
|
69
|
+
input += chunk
|
|
70
|
+
if (stopping || !input.includes('\n')) return
|
|
71
|
+
if (input !== 'STOP\n') return stop(true)
|
|
72
|
+
controlled = true
|
|
73
|
+
stop(false)
|
|
74
|
+
})
|
|
75
|
+
process.stdin.on('end', () => { if (!controlled) stop(true) })
|
|
76
|
+
// Keeps the runner alive after the action closes, until the supervisor sends STOP.
|
|
77
|
+
setInterval(() => {}, 1000)
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// Supervises one fenced action for the executor (packages/cockpit/src/environment-exec/execute.ts) so
|
|
4
|
+
// that an attempt whose executor died can still be ended and proven gone by `repairFencedExecution`.
|
|
5
|
+
//
|
|
6
|
+
// argv: <config>, base64url JSON { command, args, argv0, cwd, spawnNotAfter, fence }.
|
|
7
|
+
// fd 3 to the executor: 'READY\n' once the repair socket listens; 'EXPIRED\n' before exiting when the
|
|
8
|
+
// action was never released because its spawn deadline passed or the executor cancelled it.
|
|
9
|
+
// stdin from the executor: one release line, 'GO' or 'CANCEL', then the attempt id and the device and
|
|
10
|
+
// inode of the active marker and its parent directory that the executor published. Anything else exits.
|
|
11
|
+
// repair socket: a client that writes the attempt id is answered { attemptId, supervisorPid } and the
|
|
12
|
+
// action is stopped.
|
|
13
|
+
// exit code: the action's exit code, or 125 when the fence could not be kept (protocol violation, the
|
|
14
|
+
// runner lost, or no durable 'terminated' marker). The supervisor exits only after the action's process
|
|
15
|
+
// group is gone and the marker reads 'terminated', so that marker proves nothing of the attempt runs.
|
|
16
|
+
const { spawn } = require('node:child_process')
|
|
17
|
+
const { createServer } = require('node:net')
|
|
18
|
+
const fs = require('node:fs')
|
|
19
|
+
const path = require('node:path')
|
|
20
|
+
const { replaceApprovedActiveMarker } = require('./fence-marker.cjs')
|
|
21
|
+
|
|
22
|
+
const FENCE_LOST = 125
|
|
23
|
+
const GROUP_EXIT_WAIT_MS = 2000
|
|
24
|
+
const RUNNER = path.join(__dirname, 'fenced-group-runner.cjs')
|
|
25
|
+
|
|
26
|
+
const config = JSON.parse(Buffer.from(process.argv[2], 'base64url').toString('utf8'))
|
|
27
|
+
const { fence } = config
|
|
28
|
+
|
|
29
|
+
let action
|
|
30
|
+
let approved
|
|
31
|
+
let started = false
|
|
32
|
+
let finished = false
|
|
33
|
+
let terminating = false
|
|
34
|
+
let expired = false
|
|
35
|
+
let actionCode = 1
|
|
36
|
+
|
|
37
|
+
const groupGone = pid => {
|
|
38
|
+
try { process.kill(-pid, 0); return false } catch (error) { return error.code === 'ESRCH' }
|
|
39
|
+
}
|
|
40
|
+
const removeSocket = () => {
|
|
41
|
+
try { fs.unlinkSync(fence.socketPath) } catch { /* already absent; repair checks absence itself */ }
|
|
42
|
+
}
|
|
43
|
+
const abandon = () => {
|
|
44
|
+
removeSocket()
|
|
45
|
+
process.exit(FENCE_LOST)
|
|
46
|
+
}
|
|
47
|
+
const publishTerminated = () => approved !== undefined && replaceApprovedActiveMarker(
|
|
48
|
+
fence, { ...approved, supervisorPid: process.pid }, 'supervisor',
|
|
49
|
+
{ status: 'terminated', finishedAt: new Date().toISOString() },
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
const server = createServer(socket => {
|
|
53
|
+
let request = ''
|
|
54
|
+
socket.setEncoding('utf8')
|
|
55
|
+
socket.on('data', chunk => {
|
|
56
|
+
request += chunk
|
|
57
|
+
if (request.length > 256) return socket.destroy()
|
|
58
|
+
if (!request.includes('\n')) return
|
|
59
|
+
if (request.trim() !== fence.attemptId) return socket.destroy()
|
|
60
|
+
socket.end(`${JSON.stringify({ attemptId: fence.attemptId, supervisorPid: process.pid })}\n`)
|
|
61
|
+
terminate()
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
function finish(deadline) {
|
|
66
|
+
if (finished) return
|
|
67
|
+
if (action && !groupGone(action.pid)) {
|
|
68
|
+
if (Date.now() >= deadline) return abandon()
|
|
69
|
+
return setTimeout(() => finish(deadline), 10)
|
|
70
|
+
}
|
|
71
|
+
finished = true
|
|
72
|
+
server.close()
|
|
73
|
+
removeSocket()
|
|
74
|
+
if (!publishTerminated()) process.exit(FENCE_LOST)
|
|
75
|
+
if (expired) fs.writeSync(3, 'EXPIRED\n')
|
|
76
|
+
process.exit(actionCode)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function terminate(code) {
|
|
80
|
+
if (!action || terminating) return
|
|
81
|
+
terminating = true
|
|
82
|
+
actionCode = Number.isInteger(code) ? code : 1
|
|
83
|
+
// A stop line that cannot be written means the action is unreachable; abandon exits with the fence-lost status.
|
|
84
|
+
try { action.stdin.end('STOP\n') } catch { abandon() }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function startAction() {
|
|
88
|
+
const runnerConfig = Buffer.from(JSON.stringify({
|
|
89
|
+
command: config.command, args: config.args, argv0: config.argv0, cwd: config.cwd,
|
|
90
|
+
spawnNotAfter: config.spawnNotAfter, fence, approved: { ...approved, supervisorPid: process.pid },
|
|
91
|
+
})).toString('base64url')
|
|
92
|
+
action = spawn(process.execPath, ['--', RUNNER, runnerConfig], {
|
|
93
|
+
cwd: config.cwd, env: process.env, stdio: ['pipe', 'inherit', 'inherit', 'pipe'], detached: true,
|
|
94
|
+
})
|
|
95
|
+
let control = ''
|
|
96
|
+
action.stdio[3].setEncoding('utf8')
|
|
97
|
+
action.stdio[3].on('data', chunk => {
|
|
98
|
+
control += chunk
|
|
99
|
+
if (control.length > 64) return abandon()
|
|
100
|
+
if (!control.includes('\n')) return
|
|
101
|
+
if (control === 'EXPIRED\n') {
|
|
102
|
+
expired = true
|
|
103
|
+
return terminate(1)
|
|
104
|
+
}
|
|
105
|
+
const done = /^DONE (-?[0-9]+)\n$/.exec(control)
|
|
106
|
+
if (!done) return abandon()
|
|
107
|
+
terminate(Number(done[1]))
|
|
108
|
+
})
|
|
109
|
+
action.once('error', abandon)
|
|
110
|
+
action.once('close', () => {
|
|
111
|
+
if (!terminating) return abandon()
|
|
112
|
+
finish(Date.now() + GROUP_EXIT_WAIT_MS)
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
try { fs.unlinkSync(fence.socketPath) } catch (error) { if (error.code !== 'ENOENT') process.exit(FENCE_LOST) }
|
|
117
|
+
server.listen(fence.socketPath, () => fs.writeSync(3, 'READY\n'))
|
|
118
|
+
|
|
119
|
+
let release = ''
|
|
120
|
+
process.stdin.setEncoding('utf8')
|
|
121
|
+
process.stdin.on('data', chunk => {
|
|
122
|
+
release += chunk
|
|
123
|
+
if (started || !release.includes('\n')) return
|
|
124
|
+
const fields = release.trim().split(' ')
|
|
125
|
+
if (fields.length !== 6 || (fields[0] !== 'GO' && fields[0] !== 'CANCEL') || fields[1] !== fence.attemptId
|
|
126
|
+
|| fields.slice(2).some(value => !/^[0-9]+$/.test(value))) return abandon()
|
|
127
|
+
approved = { markerDev: fields[2], markerIno: fields[3], parentDev: fields[4], parentIno: fields[5] }
|
|
128
|
+
started = true
|
|
129
|
+
if (fields[0] === 'CANCEL' || config.spawnNotAfter !== undefined && Date.now() > Date.parse(config.spawnNotAfter)) {
|
|
130
|
+
expired = true
|
|
131
|
+
return finish(Date.now() + GROUP_EXIT_WAIT_MS)
|
|
132
|
+
}
|
|
133
|
+
startAction()
|
|
134
|
+
})
|
|
135
|
+
process.stdin.on('end', () => { if (!started) abandon() })
|
|
136
|
+
process.on('SIGTERM', () => terminate(1))
|
|
137
|
+
process.on('SIGINT', () => terminate(1))
|