@b00dea/cockpit 0.0.0-stage → 0.1.1
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 +474 -0
- package/LICENSE +21 -0
- package/README.md +25 -2
- package/bin/cockpit.mjs +33 -0
- package/cockpit.schema.json +2644 -0
- package/dist/autonomy.d.ts +45 -0
- package/dist/autonomy.js +173 -0
- package/dist/bounded-read.d.ts +14 -0
- package/dist/bounded-read.js +42 -0
- package/dist/browser/commands.d.ts +117 -0
- package/dist/browser/commands.js +453 -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 +118 -0
- package/dist/browser/runtime.js +186 -0
- package/dist/browser/surfaces.d.ts +141 -0
- package/dist/browser/surfaces.js +561 -0
- package/dist/browser/ui-gate.d.ts +15 -0
- package/dist/browser/ui-gate.js +18 -0
- package/dist/canonical-json.d.ts +2 -0
- package/dist/canonical-json.js +5 -0
- package/dist/cli-guard.d.ts +5 -0
- package/dist/cli-guard.js +71 -0
- package/dist/cli-main.d.ts +176 -0
- package/dist/cli-main.js +1584 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +16 -0
- package/dist/command-table.d.ts +121 -0
- package/dist/command-table.js +664 -0
- package/dist/config/load.d.ts +183 -0
- package/dist/config/load.js +367 -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/unconfirmed-toml.d.ts +9 -0
- package/dist/config/unconfirmed-toml.js +29 -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 +344 -0
- package/dist/docs/check.d.ts +16 -0
- package/dist/docs/check.js +197 -0
- package/dist/docs/decision-record.d.ts +34 -0
- package/dist/docs/decision-record.js +135 -0
- package/dist/docs/decisions.d.ts +16 -0
- package/dist/docs/decisions.js +103 -0
- package/dist/docs/markdown.d.ts +36 -0
- package/dist/docs/markdown.js +88 -0
- package/dist/docs/references.d.ts +32 -0
- package/dist/docs/references.js +148 -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/confirm.d.ts +35 -0
- package/dist/environment/application/confirm.js +122 -0
- package/dist/environment/application/destructive.d.ts +6 -0
- package/dist/environment/application/destructive.js +429 -0
- package/dist/environment/application/doctor.d.ts +94 -0
- package/dist/environment/application/doctor.js +247 -0
- package/dist/environment/application/guard.d.ts +49 -0
- package/dist/environment/application/guard.js +677 -0
- package/dist/environment/application/health.d.ts +143 -0
- package/dist/environment/application/health.js +385 -0
- package/dist/environment/application/lifecycle-context.d.ts +235 -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 +202 -0
- package/dist/environment/application/lifecycle.d.ts +18 -0
- package/dist/environment/application/lifecycle.js +737 -0
- package/dist/environment/application/logs.d.ts +45 -0
- package/dist/environment/application/logs.js +127 -0
- package/dist/environment/application/services.d.ts +60 -0
- package/dist/environment/application/services.js +89 -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/application/siblings.d.ts +43 -0
- package/dist/environment/application/siblings.js +269 -0
- package/dist/environment/claims.d.ts +389 -0
- package/dist/environment/claims.js +1701 -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 +125 -0
- package/dist/environment/compose-topology.js +490 -0
- package/dist/environment/contract.d.ts +522 -0
- package/dist/environment/contract.js +794 -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 +38 -0
- package/dist/environment/executable.js +190 -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 +191 -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 +278 -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 +492 -0
- package/dist/environment/generated-application/shared.js +354 -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 +400 -0
- package/dist/environment/generated-application/surfaces.d.ts +3 -0
- package/dist/environment/generated-application/surfaces.js +704 -0
- package/dist/environment/generated-application/sync.d.ts +6 -0
- package/dist/environment/generated-application/sync.js +124 -0
- package/dist/environment/git-observation.d.ts +202 -0
- package/dist/environment/git-observation.js +553 -0
- package/dist/environment/health-composition.d.ts +12 -0
- package/dist/environment/health-composition.js +645 -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 +333 -0
- package/dist/environment/init-application.js +726 -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 +31 -0
- package/dist/environment/lifecycle-composition.js +742 -0
- package/dist/environment/lifecycle-stage.d.ts +120 -0
- package/dist/environment/lifecycle-stage.js +408 -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/map-limit.d.ts +2 -0
- package/dist/environment/map-limit.js +13 -0
- package/dist/environment/mcp-observation.d.ts +9 -0
- package/dist/environment/mcp-observation.js +46 -0
- package/dist/environment/observations.d.ts +46 -0
- package/dist/environment/observations.js +346 -0
- package/dist/environment/operator-application.d.ts +79 -0
- package/dist/environment/operator-application.js +197 -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/presence.d.ts +4 -0
- package/dist/environment/presence.js +26 -0
- package/dist/environment/read-composition.d.ts +32 -0
- package/dist/environment/read-composition.js +397 -0
- package/dist/environment/readiness-composition.d.ts +57 -0
- package/dist/environment/readiness-composition.js +151 -0
- package/dist/environment/reclaim.d.ts +370 -0
- package/dist/environment/reclaim.js +1940 -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 +551 -0
- package/dist/environment/runtime.js +2405 -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/served-checkout-grants.d.ts +53 -0
- package/dist/environment/served-checkout-grants.js +182 -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-checkouts.d.ts +119 -0
- package/dist/environment/sibling-checkouts.js +254 -0
- package/dist/environment/sibling-instructions.d.ts +33 -0
- package/dist/environment/sibling-instructions.js +224 -0
- package/dist/environment/sibling-observation.d.ts +27 -0
- package/dist/environment/sibling-observation.js +45 -0
- package/dist/environment/sibling-pull.d.ts +23 -0
- package/dist/environment/sibling-pull.js +95 -0
- package/dist/environment/sibling-registration.d.ts +45 -0
- package/dist/environment/sibling-registration.js +538 -0
- package/dist/environment/stack-inputs.d.ts +18 -0
- package/dist/environment/stack-inputs.js +210 -0
- package/dist/environment/stack-inventory-prune.d.ts +31 -0
- package/dist/environment/stack-inventory-prune.js +129 -0
- package/dist/environment/stack-inventory-report.d.ts +44 -0
- package/dist/environment/stack-inventory-report.js +78 -0
- package/dist/environment/stack-inventory.d.ts +94 -0
- package/dist/environment/stack-inventory.js +418 -0
- package/dist/environment/state.d.ts +410 -0
- package/dist/environment/state.js +2153 -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 +92 -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 +105 -0
- package/dist/environment-exec/execute.js +1179 -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 +271 -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/answer-confirmation.d.ts +41 -0
- package/dist/guards/answer-confirmation.js +109 -0
- package/dist/guards/evaluator.d.ts +130 -0
- package/dist/guards/evaluator.js +1258 -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 +44 -0
- package/dist/guards/local-identity.js +129 -0
- package/dist/guards/policy-change.d.ts +43 -0
- package/dist/guards/policy-change.js +159 -0
- package/dist/guards/policy-pin.d.ts +13 -0
- package/dist/guards/policy-pin.js +177 -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 +41 -0
- package/dist/init/command.js +330 -0
- package/dist/init/derive.d.ts +53 -0
- package/dist/init/derive.js +819 -0
- package/dist/init/draft.d.ts +140 -0
- package/dist/init/draft.js +1228 -0
- package/dist/init/render.d.ts +47 -0
- package/dist/init/render.js +104 -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/repository-path.d.ts +9 -0
- package/dist/repository-path.js +16 -0
- package/dist/schema-json.d.ts +1 -0
- package/dist/schema-json.js +177 -0
- package/dist/schema.d.ts +1289 -0
- package/dist/schema.js +985 -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 +260 -0
- package/dist/surfaces/harness-registry.js +146 -0
- package/dist/surfaces/mcp.d.ts +145 -0
- package/dist/surfaces/mcp.js +349 -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 +716 -0
- package/dist/surfaces/render.d.ts +79 -0
- package/dist/surfaces/render.js +636 -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 +513 -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/test-protection.d.ts +34 -0
- package/dist/testing/test-protection.js +137 -0
- package/dist/testing/verdict.d.ts +29 -0
- package/dist/testing/verdict.js +62 -0
- package/dist/testing/weakening.d.ts +15 -0
- package/dist/testing/weakening.js +30 -0
- package/dist/work-orders/application-closure.d.ts +7 -0
- package/dist/work-orders/application-closure.js +76 -0
- package/dist/work-orders/application-context.d.ts +162 -0
- package/dist/work-orders/application-context.js +137 -0
- package/dist/work-orders/application-decisions.d.ts +27 -0
- package/dist/work-orders/application-decisions.js +121 -0
- package/dist/work-orders/application-grading.d.ts +11 -0
- package/dist/work-orders/application-grading.js +212 -0
- package/dist/work-orders/application.d.ts +6 -0
- package/dist/work-orders/application.js +223 -0
- package/dist/work-orders/composition.d.ts +101 -0
- package/dist/work-orders/composition.js +1202 -0
- package/dist/work-orders/contract.d.ts +77 -0
- package/dist/work-orders/contract.js +140 -0
- package/dist/work-orders/decisions.d.ts +23 -0
- package/dist/work-orders/decisions.js +55 -0
- package/dist/work-orders/store.d.ts +207 -0
- package/dist/work-orders/store.js +291 -0
- package/docs/README.md +68 -0
- package/docs/architecture.md +136 -0
- package/docs/capability-matrix.md +58 -0
- package/docs/cli-reference.md +807 -0
- package/docs/command-list.md +62 -0
- package/docs/compose-patterns.md +99 -0
- package/docs/concepts.md +173 -0
- package/docs/configuration-essentials.md +177 -0
- package/docs/configuration-reference.md +636 -0
- package/docs/docs-check.md +76 -0
- package/docs/environment.md +948 -0
- package/docs/extending.md +43 -0
- package/docs/faq.md +113 -0
- package/docs/getting-started.md +692 -0
- package/docs/harness-surfaces.md +500 -0
- package/docs/joining-a-team.md +76 -0
- package/docs/release-policy.md +49 -0
- package/docs/safety-and-autonomy.md +463 -0
- package/docs/troubleshooting.md +382 -0
- package/docs/tutorial.md +171 -0
- package/docs/work-and-browser.md +420 -0
- package/libexec/browser-operation.cjs +270 -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 +74 -4
- 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 +59 -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 +66 -0
- package/surfaces/skills/procedures/fix.md +95 -0
- package/surfaces/skills/procedures/setup.md +452 -0
- package/surfaces/skills/procedures/work.md +134 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
closeSync,
|
|
5
|
+
constants,
|
|
6
|
+
fstatSync,
|
|
7
|
+
fsyncSync,
|
|
8
|
+
lstatSync,
|
|
9
|
+
linkSync,
|
|
10
|
+
mkdirSync,
|
|
11
|
+
openSync,
|
|
12
|
+
readFileSync,
|
|
13
|
+
readdirSync,
|
|
14
|
+
renameSync,
|
|
15
|
+
rmdirSync,
|
|
16
|
+
unlinkSync,
|
|
17
|
+
writeSync,
|
|
18
|
+
} = require('node:fs')
|
|
19
|
+
const { basename, dirname, isAbsolute, join, normalize, relative, sep } = require('node:path')
|
|
20
|
+
|
|
21
|
+
const SEGMENT = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/
|
|
22
|
+
const REQUEST_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
|
23
|
+
const MAX_REQUEST_BYTES = 65_536
|
|
24
|
+
const MAX_FILE_BYTES = 1_048_576
|
|
25
|
+
|
|
26
|
+
function portableSegment(value) {
|
|
27
|
+
return typeof value === 'string' && value.length <= 255 && SEGMENT.test(value) && !value.endsWith('.')
|
|
28
|
+
&& !/^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/i.test(value)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function exactKeys(value, expected) {
|
|
32
|
+
const actual = Object.keys(value).sort()
|
|
33
|
+
const names = [...expected].sort()
|
|
34
|
+
return actual.length === names.length && actual.every((name, index) => name === names[index])
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function sameNode(left, right) {
|
|
38
|
+
return left.dev === right.dev && left.ino === right.ino
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function directory(path) {
|
|
42
|
+
const status = lstatSync(path, { bigint: true })
|
|
43
|
+
if (!status.isDirectory() || status.isSymbolicLink()) throw new Error('unsafe directory')
|
|
44
|
+
return status
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function checkedRoot(value) {
|
|
48
|
+
if (typeof value !== 'string' || !isAbsolute(value) || normalize(value) !== value || dirname(value) === value || value.includes('\0')) {
|
|
49
|
+
throw new Error('invalid root')
|
|
50
|
+
}
|
|
51
|
+
directory(value)
|
|
52
|
+
return value
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function checkedSegments(value) {
|
|
56
|
+
if (!Array.isArray(value) || value.length < 1 || value.length > 32 || value.some((segment) => !portableSegment(segment))) {
|
|
57
|
+
throw new Error('invalid path segments')
|
|
58
|
+
}
|
|
59
|
+
return value
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function child(root, segments) {
|
|
63
|
+
const path = join(root, ...segments)
|
|
64
|
+
const relation = relative(root, path)
|
|
65
|
+
if (relation === '' || relation === '..' || relation.startsWith(`..${sep}`) || isAbsolute(relation)) throw new Error('escaped path')
|
|
66
|
+
return path
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function syncDirectory(path) {
|
|
70
|
+
const descriptor = openSync(path, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW)
|
|
71
|
+
try { fsyncSync(descriptor) } finally { closeSync(descriptor) }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function ensureDirectory(root, segments) {
|
|
75
|
+
let current = root
|
|
76
|
+
let prior = directory(root)
|
|
77
|
+
for (const segment of segments) {
|
|
78
|
+
const next = join(current, segment)
|
|
79
|
+
let created = false
|
|
80
|
+
try { mkdirSync(next, { mode: 0o700 }); created = true } catch (error) {
|
|
81
|
+
if (error.code !== 'EEXIST') throw error
|
|
82
|
+
}
|
|
83
|
+
if (created) syncDirectory(current)
|
|
84
|
+
const status = directory(next)
|
|
85
|
+
const parent = directory(current)
|
|
86
|
+
if (!sameNode(parent, prior)) throw new Error('parent changed while creating directory')
|
|
87
|
+
current = next
|
|
88
|
+
prior = status
|
|
89
|
+
}
|
|
90
|
+
return { path: current, status: prior }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function writeAll(descriptor, bytes) {
|
|
94
|
+
let offset = 0
|
|
95
|
+
while (offset < bytes.length) offset += writeSync(descriptor, bytes, offset, bytes.length - offset)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function atomicFile(directoryPath, name, bytes, requestId) {
|
|
99
|
+
if (!portableSegment(name) || basename(name) !== name || bytes.length > MAX_FILE_BYTES) throw new Error('invalid file publication')
|
|
100
|
+
// Keep the temporary component independent of the target so a maximum portable name remains publishable.
|
|
101
|
+
const temporary = `.${requestId}.tmp`
|
|
102
|
+
const temporaryPath = join(directoryPath, temporary)
|
|
103
|
+
const target = join(directoryPath, name)
|
|
104
|
+
const descriptor = openSync(temporaryPath, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600)
|
|
105
|
+
try {
|
|
106
|
+
writeAll(descriptor, bytes)
|
|
107
|
+
fsyncSync(descriptor)
|
|
108
|
+
} finally {
|
|
109
|
+
closeSync(descriptor)
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
linkSync(temporaryPath, target)
|
|
113
|
+
unlinkSync(temporaryPath)
|
|
114
|
+
syncDirectory(directoryPath)
|
|
115
|
+
} catch (error) {
|
|
116
|
+
try { unlinkSync(temporaryPath) } catch { /* The primary refusal preserves the publication failure. */ }
|
|
117
|
+
throw error
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function readBounded(path) {
|
|
122
|
+
const before = lstatSync(path, { bigint: true })
|
|
123
|
+
if (!before.isFile() || before.isSymbolicLink() || before.nlink !== 1n || before.size > BigInt(MAX_FILE_BYTES)) throw new Error('unsafe evidence file')
|
|
124
|
+
const descriptor = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK)
|
|
125
|
+
try {
|
|
126
|
+
const opened = fstatSync(descriptor, { bigint: true })
|
|
127
|
+
if (!sameNode(before, opened) || opened.nlink !== 1n || opened.size > BigInt(MAX_FILE_BYTES)) throw new Error('evidence changed before read')
|
|
128
|
+
const bytes = readFileSync(descriptor)
|
|
129
|
+
const after = fstatSync(descriptor, { bigint: true })
|
|
130
|
+
const named = lstatSync(path, { bigint: true })
|
|
131
|
+
if (!sameNode(opened, after) || !sameNode(opened, named) || named.nlink !== 1n || bytes.length !== Number(opened.size)) throw new Error('evidence changed during read')
|
|
132
|
+
return bytes
|
|
133
|
+
} finally { closeSync(descriptor) }
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function acquire(request) {
|
|
137
|
+
if (!exactKeys(request, ['version', 'requestId', 'operation', 'root', 'segments', 'ownerBase64'])) throw new Error('invalid acquire request')
|
|
138
|
+
const root = checkedRoot(request.root)
|
|
139
|
+
const segments = checkedSegments(request.segments)
|
|
140
|
+
const owner = Buffer.from(request.ownerBase64, 'base64')
|
|
141
|
+
if (owner.length < 1 || owner.length > MAX_FILE_BYTES || owner.toString('base64') !== request.ownerBase64) throw new Error('invalid owner evidence')
|
|
142
|
+
const parent = ensureDirectory(root, segments.slice(0, -1))
|
|
143
|
+
const lockPath = child(root, segments)
|
|
144
|
+
try { mkdirSync(lockPath, { mode: 0o700 }) } catch (error) {
|
|
145
|
+
if (error.code !== 'EEXIST') throw error
|
|
146
|
+
const status = directory(lockPath)
|
|
147
|
+
const entries = readdirSync(lockPath).sort()
|
|
148
|
+
const ownerBytes = entries.length === 1 && entries[0] === 'owner.json' ? readBounded(join(lockPath, 'owner.json')) : undefined
|
|
149
|
+
return { kind: 'exists', lock: { path: lockPath, dev: Number(status.dev), ino: Number(status.ino), entries, ownerBase64: ownerBytes?.toString('base64') ?? null } }
|
|
150
|
+
}
|
|
151
|
+
const status = directory(lockPath)
|
|
152
|
+
if (!sameNode(directory(parent.path), parent.status)) throw new Error('lock parent changed during acquisition')
|
|
153
|
+
try {
|
|
154
|
+
atomicFile(lockPath, 'owner.json', owner, request.requestId)
|
|
155
|
+
syncDirectory(parent.path)
|
|
156
|
+
const named = directory(lockPath)
|
|
157
|
+
if (!sameNode(status, named)) throw new Error('lock changed during owner publication')
|
|
158
|
+
return { kind: 'acquired', lock: { path: lockPath, dev: Number(status.dev), ino: Number(status.ino), ownerBase64: owner.toString('base64') } }
|
|
159
|
+
} catch (error) {
|
|
160
|
+
try { rmdirSync(lockPath); syncDirectory(parent.path) } catch { /* Residue is intentionally left for explicit recovery. */ }
|
|
161
|
+
throw error
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function release(request) {
|
|
166
|
+
if (!exactKeys(request, ['version', 'requestId', 'operation', 'root', 'segments', 'dev', 'ino', 'ownerBase64', 'quarantine'])) throw new Error('invalid release request')
|
|
167
|
+
const root = checkedRoot(request.root)
|
|
168
|
+
const segments = checkedSegments(request.segments)
|
|
169
|
+
if (typeof request.quarantine !== 'string' || request.quarantine.length > 255
|
|
170
|
+
|| !request.quarantine.startsWith('.release-') || !portableSegment(request.quarantine.slice(1))) throw new Error('invalid quarantine name')
|
|
171
|
+
const lockPath = child(root, segments)
|
|
172
|
+
const parentPath = join(root, ...segments.slice(0, -1))
|
|
173
|
+
const status = directory(lockPath)
|
|
174
|
+
if (Number(status.dev) !== request.dev || Number(status.ino) !== request.ino) throw new Error('lock identity changed')
|
|
175
|
+
const owner = readBounded(join(lockPath, 'owner.json'))
|
|
176
|
+
if (owner.toString('base64') !== request.ownerBase64) throw new Error('lock owner changed')
|
|
177
|
+
const quarantinePath = join(parentPath, request.quarantine)
|
|
178
|
+
renameSync(lockPath, quarantinePath)
|
|
179
|
+
syncDirectory(parentPath)
|
|
180
|
+
const moved = directory(quarantinePath)
|
|
181
|
+
if (!sameNode(status, moved)) throw new Error('quarantine identity changed')
|
|
182
|
+
const entries = readdirSync(quarantinePath).sort()
|
|
183
|
+
if (entries.length !== 1 || entries[0] !== 'owner.json') return { kind: 'residue', path: quarantinePath, entries }
|
|
184
|
+
if (readBounded(join(quarantinePath, 'owner.json')).toString('base64') !== request.ownerBase64) return { kind: 'residue', path: quarantinePath, entries }
|
|
185
|
+
unlinkSync(join(quarantinePath, 'owner.json'))
|
|
186
|
+
syncDirectory(quarantinePath)
|
|
187
|
+
rmdirSync(quarantinePath)
|
|
188
|
+
syncDirectory(parentPath)
|
|
189
|
+
return { kind: 'released', path: lockPath }
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function stamp(request) {
|
|
193
|
+
if (!exactKeys(request, ['version', 'requestId', 'operation', 'root', 'segments', 'name', 'bytesBase64'])) throw new Error('invalid stamp request')
|
|
194
|
+
const root = checkedRoot(request.root)
|
|
195
|
+
const directoryPath = child(root, checkedSegments(request.segments))
|
|
196
|
+
directory(directoryPath)
|
|
197
|
+
const bytes = Buffer.from(request.bytesBase64, 'base64')
|
|
198
|
+
if (bytes.length < 1 || bytes.toString('base64') !== request.bytesBase64) throw new Error('invalid stamp bytes')
|
|
199
|
+
atomicFile(directoryPath, request.name, bytes, request.requestId)
|
|
200
|
+
return { kind: 'stamped', path: join(directoryPath, request.name) }
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function ensure(request) {
|
|
204
|
+
if (!exactKeys(request, ['version', 'requestId', 'operation', 'root', 'segments'])) throw new Error('invalid ensure-directory request')
|
|
205
|
+
const root = checkedRoot(request.root)
|
|
206
|
+
const result = ensureDirectory(root, checkedSegments(request.segments))
|
|
207
|
+
return { kind: 'complete', path: result.path, dev: Number(result.status.dev), ino: Number(result.status.ino) }
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
try {
|
|
211
|
+
if (process.argv.length !== 3) throw new Error('expected exactly one request argument')
|
|
212
|
+
const encoded = process.argv[2]
|
|
213
|
+
if (typeof encoded !== 'string' || Buffer.byteLength(encoded) > MAX_REQUEST_BYTES) throw new Error('missing or oversized request')
|
|
214
|
+
const request = JSON.parse(encoded)
|
|
215
|
+
if (!request || typeof request !== 'object' || Array.isArray(request) || request.version !== 1 || !REQUEST_ID.test(request.requestId)) throw new Error('invalid request envelope')
|
|
216
|
+
const result = request.operation === 'acquire' ? acquire(request)
|
|
217
|
+
: request.operation === 'release' ? release(request)
|
|
218
|
+
: request.operation === 'stamp' ? stamp(request)
|
|
219
|
+
: request.operation === 'ensure-directory' ? ensure(request)
|
|
220
|
+
: (() => { throw new Error('unsupported operation') })()
|
|
221
|
+
process.stdout.write(`${JSON.stringify({ version: 1, requestId: request.requestId, ...result })}\n`)
|
|
222
|
+
} catch (error) {
|
|
223
|
+
process.stderr.write(`install-filesystem: ${error instanceof Error ? error.message : 'request failed'}\n`)
|
|
224
|
+
process.exitCode = 2
|
|
225
|
+
}
|