looply-cli 0.0.0-stage → 0.3.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 +137 -3
- package/dist/.src-hash +1 -0
- package/dist/acceptance-observe.d.ts +108 -0
- package/dist/acceptance-observe.d.ts.map +1 -0
- package/dist/acceptance-observe.js +152 -0
- package/dist/acceptance-observe.js.map +1 -0
- package/dist/agent-cmd.d.ts +131 -0
- package/dist/agent-cmd.d.ts.map +1 -0
- package/dist/agent-cmd.js +154 -0
- package/dist/agent-cmd.js.map +1 -0
- package/dist/agent-contained.d.ts +114 -0
- package/dist/agent-contained.d.ts.map +1 -0
- package/dist/agent-contained.js +292 -0
- package/dist/agent-contained.js.map +1 -0
- package/dist/agent-driver.d.ts +130 -0
- package/dist/agent-driver.d.ts.map +1 -0
- package/dist/agent-driver.js +170 -0
- package/dist/agent-driver.js.map +1 -0
- package/dist/agent-envelope.d.ts +94 -0
- package/dist/agent-envelope.d.ts.map +1 -0
- package/dist/agent-envelope.js +214 -0
- package/dist/agent-envelope.js.map +1 -0
- package/dist/agent-exec.d.ts +182 -0
- package/dist/agent-exec.d.ts.map +1 -0
- package/dist/agent-exec.js +125 -0
- package/dist/agent-exec.js.map +1 -0
- package/dist/agent-runtime.d.ts +23 -0
- package/dist/agent-runtime.d.ts.map +1 -0
- package/dist/agent-runtime.js +143 -0
- package/dist/agent-runtime.js.map +1 -0
- package/dist/approval-gate-read.d.ts +66 -0
- package/dist/approval-gate-read.d.ts.map +1 -0
- package/dist/approval-gate-read.js +138 -0
- package/dist/approval-gate-read.js.map +1 -0
- package/dist/approval-resolution.d.ts +87 -0
- package/dist/approval-resolution.d.ts.map +1 -0
- package/dist/approval-resolution.js +100 -0
- package/dist/approval-resolution.js.map +1 -0
- package/dist/approval-resumes.d.ts +102 -0
- package/dist/approval-resumes.d.ts.map +1 -0
- package/dist/approval-resumes.js +167 -0
- package/dist/approval-resumes.js.map +1 -0
- package/dist/ask-brain.d.ts +167 -0
- package/dist/ask-brain.d.ts.map +1 -0
- package/dist/ask-brain.js +355 -0
- package/dist/ask-brain.js.map +1 -0
- package/dist/autonomy-authority.d.ts +80 -0
- package/dist/autonomy-authority.d.ts.map +1 -0
- package/dist/autonomy-authority.js +82 -0
- package/dist/autonomy-authority.js.map +1 -0
- package/dist/autonomy-controller.d.ts +321 -0
- package/dist/autonomy-controller.d.ts.map +1 -0
- package/dist/autonomy-controller.js +517 -0
- package/dist/autonomy-controller.js.map +1 -0
- package/dist/autonomy-store.d.ts +327 -0
- package/dist/autonomy-store.d.ts.map +1 -0
- package/dist/autonomy-store.js +581 -0
- package/dist/autonomy-store.js.map +1 -0
- package/dist/autonomy-tick.d.ts +257 -0
- package/dist/autonomy-tick.d.ts.map +1 -0
- package/dist/autonomy-tick.js +616 -0
- package/dist/autonomy-tick.js.map +1 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +2727 -0
- package/dist/bin.js.map +1 -0
- package/dist/brain-advice.d.ts +21 -0
- package/dist/brain-advice.d.ts.map +1 -0
- package/dist/brain-advice.js +51 -0
- package/dist/brain-advice.js.map +1 -0
- package/dist/candidate-replay-runtime.d.ts +125 -0
- package/dist/candidate-replay-runtime.d.ts.map +1 -0
- package/dist/candidate-replay-runtime.js +188 -0
- package/dist/candidate-replay-runtime.js.map +1 -0
- package/dist/checkout-carry.d.ts +76 -0
- package/dist/checkout-carry.d.ts.map +1 -0
- package/dist/checkout-carry.js +125 -0
- package/dist/checkout-carry.js.map +1 -0
- package/dist/citation-readers.d.ts +26 -0
- package/dist/citation-readers.d.ts.map +1 -0
- package/dist/citation-readers.js +102 -0
- package/dist/citation-readers.js.map +1 -0
- package/dist/command-receipts.d.ts +79 -0
- package/dist/command-receipts.d.ts.map +1 -0
- package/dist/command-receipts.js +143 -0
- package/dist/command-receipts.js.map +1 -0
- package/dist/command-runner.d.ts +32 -0
- package/dist/command-runner.d.ts.map +1 -0
- package/dist/command-runner.js +108 -0
- package/dist/command-runner.js.map +1 -0
- package/dist/compatible-sets.d.ts +67 -0
- package/dist/compatible-sets.d.ts.map +1 -0
- package/dist/compatible-sets.js +81 -0
- package/dist/compatible-sets.js.map +1 -0
- package/dist/compile-check.d.ts +31 -0
- package/dist/compile-check.d.ts.map +1 -0
- package/dist/compile-check.js +34 -0
- package/dist/compile-check.js.map +1 -0
- package/dist/compile-store.d.ts +16 -0
- package/dist/compile-store.d.ts.map +1 -0
- package/dist/compile-store.js +21 -0
- package/dist/compile-store.js.map +1 -0
- package/dist/completion.d.ts +106 -0
- package/dist/completion.d.ts.map +1 -0
- package/dist/completion.js +131 -0
- package/dist/completion.js.map +1 -0
- package/dist/config.d.ts +549 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +763 -0
- package/dist/config.js.map +1 -0
- package/dist/control-file.d.ts +142 -0
- package/dist/control-file.d.ts.map +1 -0
- package/dist/control-file.js +144 -0
- package/dist/control-file.js.map +1 -0
- package/dist/coordinator-state.d.ts +131 -0
- package/dist/coordinator-state.d.ts.map +1 -0
- package/dist/coordinator-state.js +380 -0
- package/dist/coordinator-state.js.map +1 -0
- package/dist/coordinator.d.ts +95 -0
- package/dist/coordinator.d.ts.map +1 -0
- package/dist/coordinator.js +97 -0
- package/dist/coordinator.js.map +1 -0
- package/dist/cursor-store.d.ts +53 -0
- package/dist/cursor-store.d.ts.map +1 -0
- package/dist/cursor-store.js +98 -0
- package/dist/cursor-store.js.map +1 -0
- package/dist/daemon-cmd.d.ts +239 -0
- package/dist/daemon-cmd.d.ts.map +1 -0
- package/dist/daemon-cmd.js +1751 -0
- package/dist/daemon-cmd.js.map +1 -0
- package/dist/daemon-lock.d.ts +140 -0
- package/dist/daemon-lock.d.ts.map +1 -0
- package/dist/daemon-lock.js +352 -0
- package/dist/daemon-lock.js.map +1 -0
- package/dist/daemon-recovery.d.ts +78 -0
- package/dist/daemon-recovery.d.ts.map +1 -0
- package/dist/daemon-recovery.js +161 -0
- package/dist/daemon-recovery.js.map +1 -0
- package/dist/daemon.d.ts +368 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +601 -0
- package/dist/daemon.js.map +1 -0
- package/dist/declared-response-shape.d.ts +93 -0
- package/dist/declared-response-shape.d.ts.map +1 -0
- package/dist/declared-response-shape.js +200 -0
- package/dist/declared-response-shape.js.map +1 -0
- package/dist/declared-surfaces.d.ts +16 -0
- package/dist/declared-surfaces.d.ts.map +1 -0
- package/dist/declared-surfaces.js +19 -0
- package/dist/declared-surfaces.js.map +1 -0
- package/dist/depends-review.d.ts +113 -0
- package/dist/depends-review.d.ts.map +1 -0
- package/dist/depends-review.js +110 -0
- package/dist/depends-review.js.map +1 -0
- package/dist/doctor.d.ts +91 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +71 -0
- package/dist/doctor.js.map +1 -0
- package/dist/edge-approval.d.ts +105 -0
- package/dist/edge-approval.d.ts.map +1 -0
- package/dist/edge-approval.js +100 -0
- package/dist/edge-approval.js.map +1 -0
- package/dist/evidence-cache.d.ts +45 -0
- package/dist/evidence-cache.d.ts.map +1 -0
- package/dist/evidence-cache.js +90 -0
- package/dist/evidence-cache.js.map +1 -0
- package/dist/evidence-cmd.d.ts +133 -0
- package/dist/evidence-cmd.d.ts.map +1 -0
- package/dist/evidence-cmd.js +347 -0
- package/dist/evidence-cmd.js.map +1 -0
- package/dist/evidence-facts.d.ts +40 -0
- package/dist/evidence-facts.d.ts.map +1 -0
- package/dist/evidence-facts.js +114 -0
- package/dist/evidence-facts.js.map +1 -0
- package/dist/exclusive-lock.d.ts +52 -0
- package/dist/exclusive-lock.d.ts.map +1 -0
- package/dist/exclusive-lock.js +150 -0
- package/dist/exclusive-lock.js.map +1 -0
- package/dist/exec-domains.d.ts +140 -0
- package/dist/exec-domains.d.ts.map +1 -0
- package/dist/exec-domains.js +287 -0
- package/dist/exec-domains.js.map +1 -0
- package/dist/exemption-store.d.ts +197 -0
- package/dist/exemption-store.d.ts.map +1 -0
- package/dist/exemption-store.js +266 -0
- package/dist/exemption-store.js.map +1 -0
- package/dist/explicit-start-gate.d.ts +96 -0
- package/dist/explicit-start-gate.d.ts.map +1 -0
- package/dist/explicit-start-gate.js +103 -0
- package/dist/explicit-start-gate.js.map +1 -0
- package/dist/fs-trouble.d.ts +70 -0
- package/dist/fs-trouble.d.ts.map +1 -0
- package/dist/fs-trouble.js +98 -0
- package/dist/fs-trouble.js.map +1 -0
- package/dist/gate.d.ts +278 -0
- package/dist/gate.d.ts.map +1 -0
- package/dist/gate.js +278 -0
- package/dist/gate.js.map +1 -0
- package/dist/git-driver.d.ts +519 -0
- package/dist/git-driver.d.ts.map +1 -0
- package/dist/git-driver.js +900 -0
- package/dist/git-driver.js.map +1 -0
- package/dist/git-push-executor.d.ts +41 -0
- package/dist/git-push-executor.d.ts.map +1 -0
- package/dist/git-push-executor.js +142 -0
- package/dist/git-push-executor.js.map +1 -0
- package/dist/glob.d.ts +26 -0
- package/dist/glob.d.ts.map +1 -0
- package/dist/glob.js +93 -0
- package/dist/glob.js.map +1 -0
- package/dist/goal-adaptive.d.ts +295 -0
- package/dist/goal-adaptive.d.ts.map +1 -0
- package/dist/goal-adaptive.js +393 -0
- package/dist/goal-adaptive.js.map +1 -0
- package/dist/goal-compile.d.ts +342 -0
- package/dist/goal-compile.d.ts.map +1 -0
- package/dist/goal-compile.js +444 -0
- package/dist/goal-compile.js.map +1 -0
- package/dist/goal-depends-executor.d.ts +55 -0
- package/dist/goal-depends-executor.d.ts.map +1 -0
- package/dist/goal-depends-executor.js +202 -0
- package/dist/goal-depends-executor.js.map +1 -0
- package/dist/goal-execution-evidence.d.ts +135 -0
- package/dist/goal-execution-evidence.d.ts.map +1 -0
- package/dist/goal-execution-evidence.js +159 -0
- package/dist/goal-execution-evidence.js.map +1 -0
- package/dist/goal-gap.d.ts +140 -0
- package/dist/goal-gap.d.ts.map +1 -0
- package/dist/goal-gap.js +197 -0
- package/dist/goal-gap.js.map +1 -0
- package/dist/goal-met-target.d.ts +98 -0
- package/dist/goal-met-target.d.ts.map +1 -0
- package/dist/goal-met-target.js +92 -0
- package/dist/goal-met-target.js.map +1 -0
- package/dist/goal-ownership.d.ts +416 -0
- package/dist/goal-ownership.d.ts.map +1 -0
- package/dist/goal-ownership.js +576 -0
- package/dist/goal-ownership.js.map +1 -0
- package/dist/goal-runs.d.ts +82 -0
- package/dist/goal-runs.d.ts.map +1 -0
- package/dist/goal-runs.js +120 -0
- package/dist/goal-runs.js.map +1 -0
- package/dist/goal-store.d.ts +146 -0
- package/dist/goal-store.d.ts.map +1 -0
- package/dist/goal-store.js +294 -0
- package/dist/goal-store.js.map +1 -0
- package/dist/goal-view.d.ts +156 -0
- package/dist/goal-view.d.ts.map +1 -0
- package/dist/goal-view.js +499 -0
- package/dist/goal-view.js.map +1 -0
- package/dist/governed-approvals.d.ts +152 -0
- package/dist/governed-approvals.d.ts.map +1 -0
- package/dist/governed-approvals.js +246 -0
- package/dist/governed-approvals.js.map +1 -0
- package/dist/governed-broker.d.ts +169 -0
- package/dist/governed-broker.d.ts.map +1 -0
- package/dist/governed-broker.js +196 -0
- package/dist/governed-broker.js.map +1 -0
- package/dist/governed-run.d.ts +220 -0
- package/dist/governed-run.d.ts.map +1 -0
- package/dist/governed-run.js +406 -0
- package/dist/governed-run.js.map +1 -0
- package/dist/grant-reconcile.d.ts +63 -0
- package/dist/grant-reconcile.d.ts.map +1 -0
- package/dist/grant-reconcile.js +121 -0
- package/dist/grant-reconcile.js.map +1 -0
- package/dist/index-for-head.d.ts +56 -0
- package/dist/index-for-head.d.ts.map +1 -0
- package/dist/index-for-head.js +103 -0
- package/dist/index-for-head.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/init-detect.d.ts +39 -0
- package/dist/init-detect.d.ts.map +1 -0
- package/dist/init-detect.js +188 -0
- package/dist/init-detect.js.map +1 -0
- package/dist/integration-deps.d.ts +62 -0
- package/dist/integration-deps.d.ts.map +1 -0
- package/dist/integration-deps.js +251 -0
- package/dist/integration-deps.js.map +1 -0
- package/dist/integration-runtime.d.ts +458 -0
- package/dist/integration-runtime.d.ts.map +1 -0
- package/dist/integration-runtime.js +681 -0
- package/dist/integration-runtime.js.map +1 -0
- package/dist/integration.d.ts +45 -0
- package/dist/integration.d.ts.map +1 -0
- package/dist/integration.js +87 -0
- package/dist/integration.js.map +1 -0
- package/dist/integrator.d.ts +84 -0
- package/dist/integrator.d.ts.map +1 -0
- package/dist/integrator.js +193 -0
- package/dist/integrator.js.map +1 -0
- package/dist/lane-claims.d.ts +174 -0
- package/dist/lane-claims.d.ts.map +1 -0
- package/dist/lane-claims.js +218 -0
- package/dist/lane-claims.js.map +1 -0
- package/dist/lane-coverage.d.ts +87 -0
- package/dist/lane-coverage.d.ts.map +1 -0
- package/dist/lane-coverage.js +129 -0
- package/dist/lane-coverage.js.map +1 -0
- package/dist/ledger-replay.d.ts +115 -0
- package/dist/ledger-replay.d.ts.map +1 -0
- package/dist/ledger-replay.js +155 -0
- package/dist/ledger-replay.js.map +1 -0
- package/dist/ledger-store.d.ts +68 -0
- package/dist/ledger-store.d.ts.map +1 -0
- package/dist/ledger-store.js +111 -0
- package/dist/ledger-store.js.map +1 -0
- package/dist/loop-safety-observer.d.ts +132 -0
- package/dist/loop-safety-observer.d.ts.map +1 -0
- package/dist/loop-safety-observer.js +76 -0
- package/dist/loop-safety-observer.js.map +1 -0
- package/dist/loop-safety-store.d.ts +339 -0
- package/dist/loop-safety-store.d.ts.map +1 -0
- package/dist/loop-safety-store.js +800 -0
- package/dist/loop-safety-store.js.map +1 -0
- package/dist/machine-store.d.ts +54 -0
- package/dist/machine-store.d.ts.map +1 -0
- package/dist/machine-store.js +149 -0
- package/dist/machine-store.js.map +1 -0
- package/dist/mcp-main.d.ts +2 -0
- package/dist/mcp-main.d.ts.map +1 -0
- package/dist/mcp-main.js +116 -0
- package/dist/mcp-main.js.map +1 -0
- package/dist/mcp-server.d.ts +72 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +259 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/model-routing.d.ts +75 -0
- package/dist/model-routing.d.ts.map +1 -0
- package/dist/model-routing.js +108 -0
- package/dist/model-routing.js.map +1 -0
- package/dist/model-transport.d.ts +188 -0
- package/dist/model-transport.d.ts.map +1 -0
- package/dist/model-transport.js +625 -0
- package/dist/model-transport.js.map +1 -0
- package/dist/notify-cadence.d.ts +55 -0
- package/dist/notify-cadence.d.ts.map +1 -0
- package/dist/notify-cadence.js +68 -0
- package/dist/notify-cadence.js.map +1 -0
- package/dist/notify-channel.d.ts +69 -0
- package/dist/notify-channel.d.ts.map +1 -0
- package/dist/notify-channel.js +151 -0
- package/dist/notify-channel.js.map +1 -0
- package/dist/notify.d.ts +71 -0
- package/dist/notify.d.ts.map +1 -0
- package/dist/notify.js +125 -0
- package/dist/notify.js.map +1 -0
- package/dist/observation-inventory.d.ts +65 -0
- package/dist/observation-inventory.d.ts.map +1 -0
- package/dist/observation-inventory.js +139 -0
- package/dist/observation-inventory.js.map +1 -0
- package/dist/owned-children.d.ts +45 -0
- package/dist/owned-children.d.ts.map +1 -0
- package/dist/owned-children.js +64 -0
- package/dist/owned-children.js.map +1 -0
- package/dist/packet-for-goal.d.ts +19 -0
- package/dist/packet-for-goal.d.ts.map +1 -0
- package/dist/packet-for-goal.js +32 -0
- package/dist/packet-for-goal.js.map +1 -0
- package/dist/pair-cmd.d.ts +85 -0
- package/dist/pair-cmd.d.ts.map +1 -0
- package/dist/pair-cmd.js +205 -0
- package/dist/pair-cmd.js.map +1 -0
- package/dist/partial-asker.d.ts +96 -0
- package/dist/partial-asker.d.ts.map +1 -0
- package/dist/partial-asker.js +117 -0
- package/dist/partial-asker.js.map +1 -0
- package/dist/pdf-text-lines.d.ts +17 -0
- package/dist/pdf-text-lines.d.ts.map +1 -0
- package/dist/pdf-text-lines.js +70 -0
- package/dist/pdf-text-lines.js.map +1 -0
- package/dist/pdf-text-worker.d.ts +2 -0
- package/dist/pdf-text-worker.d.ts.map +1 -0
- package/dist/pdf-text-worker.js +81 -0
- package/dist/pdf-text-worker.js.map +1 -0
- package/dist/pdf-text.d.ts +56 -0
- package/dist/pdf-text.d.ts.map +1 -0
- package/dist/pdf-text.js +64 -0
- package/dist/pdf-text.js.map +1 -0
- package/dist/pending-action.d.ts +154 -0
- package/dist/pending-action.d.ts.map +1 -0
- package/dist/pending-action.js +148 -0
- package/dist/pending-action.js.map +1 -0
- package/dist/preemptor.d.ts +40 -0
- package/dist/preemptor.d.ts.map +1 -0
- package/dist/preemptor.js +49 -0
- package/dist/preemptor.js.map +1 -0
- package/dist/programme-mode.d.ts +29 -0
- package/dist/programme-mode.d.ts.map +1 -0
- package/dist/programme-mode.js +50 -0
- package/dist/programme-mode.js.map +1 -0
- package/dist/progress-view.d.ts +14 -0
- package/dist/progress-view.d.ts.map +1 -0
- package/dist/progress-view.js +114 -0
- package/dist/progress-view.js.map +1 -0
- package/dist/project-graph-builder.d.ts +81 -0
- package/dist/project-graph-builder.d.ts.map +1 -0
- package/dist/project-graph-builder.js +246 -0
- package/dist/project-graph-builder.js.map +1 -0
- package/dist/project-graph-runtime.d.ts +86 -0
- package/dist/project-graph-runtime.d.ts.map +1 -0
- package/dist/project-graph-runtime.js +112 -0
- package/dist/project-graph-runtime.js.map +1 -0
- package/dist/project-index-builder.d.ts +96 -0
- package/dist/project-index-builder.d.ts.map +1 -0
- package/dist/project-index-builder.js +298 -0
- package/dist/project-index-builder.js.map +1 -0
- package/dist/project-index-facts.d.ts +51 -0
- package/dist/project-index-facts.d.ts.map +1 -0
- package/dist/project-index-facts.js +117 -0
- package/dist/project-index-facts.js.map +1 -0
- package/dist/project-index-store.d.ts +97 -0
- package/dist/project-index-store.d.ts.map +1 -0
- package/dist/project-index-store.js +140 -0
- package/dist/project-index-store.js.map +1 -0
- package/dist/project-memory-store.d.ts +127 -0
- package/dist/project-memory-store.d.ts.map +1 -0
- package/dist/project-memory-store.js +302 -0
- package/dist/project-memory-store.js.map +1 -0
- package/dist/proposal-store.d.ts +14 -0
- package/dist/proposal-store.d.ts.map +1 -0
- package/dist/proposal-store.js +19 -0
- package/dist/proposal-store.js.map +1 -0
- package/dist/prover.d.ts +80 -0
- package/dist/prover.d.ts.map +1 -0
- package/dist/prover.js +137 -0
- package/dist/prover.js.map +1 -0
- package/dist/provider-identity-store.d.ts +34 -0
- package/dist/provider-identity-store.d.ts.map +1 -0
- package/dist/provider-identity-store.js +72 -0
- package/dist/provider-identity-store.js.map +1 -0
- package/dist/provider-identity.d.ts +104 -0
- package/dist/provider-identity.d.ts.map +1 -0
- package/dist/provider-identity.js +167 -0
- package/dist/provider-identity.js.map +1 -0
- package/dist/provider-limit.d.ts +79 -0
- package/dist/provider-limit.d.ts.map +1 -0
- package/dist/provider-limit.js +148 -0
- package/dist/provider-limit.js.map +1 -0
- package/dist/provider-preflight.d.ts +171 -0
- package/dist/provider-preflight.d.ts.map +1 -0
- package/dist/provider-preflight.js +395 -0
- package/dist/provider-preflight.js.map +1 -0
- package/dist/provider-state.d.ts +120 -0
- package/dist/provider-state.d.ts.map +1 -0
- package/dist/provider-state.js +182 -0
- package/dist/provider-state.js.map +1 -0
- package/dist/providers.d.ts +132 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/providers.js +161 -0
- package/dist/providers.js.map +1 -0
- package/dist/publication-recorder.d.ts +117 -0
- package/dist/publication-recorder.d.ts.map +1 -0
- package/dist/publication-recorder.js +124 -0
- package/dist/publication-recorder.js.map +1 -0
- package/dist/pursuit-delivery.d.ts +24 -0
- package/dist/pursuit-delivery.d.ts.map +1 -0
- package/dist/pursuit-delivery.js +38 -0
- package/dist/pursuit-delivery.js.map +1 -0
- package/dist/queue-store.d.ts +132 -0
- package/dist/queue-store.d.ts.map +1 -0
- package/dist/queue-store.js +185 -0
- package/dist/queue-store.js.map +1 -0
- package/dist/queue-summary.d.ts +14 -0
- package/dist/queue-summary.d.ts.map +1 -0
- package/dist/queue-summary.js +82 -0
- package/dist/queue-summary.js.map +1 -0
- package/dist/queue-view.d.ts +20 -0
- package/dist/queue-view.d.ts.map +1 -0
- package/dist/queue-view.js +163 -0
- package/dist/queue-view.js.map +1 -0
- package/dist/queue-write-lease.d.ts +106 -0
- package/dist/queue-write-lease.d.ts.map +1 -0
- package/dist/queue-write-lease.js +282 -0
- package/dist/queue-write-lease.js.map +1 -0
- package/dist/rails-home.d.ts +162 -0
- package/dist/rails-home.d.ts.map +1 -0
- package/dist/rails-home.js +452 -0
- package/dist/rails-home.js.map +1 -0
- package/dist/rails-migrations.d.ts +75 -0
- package/dist/rails-migrations.d.ts.map +1 -0
- package/dist/rails-migrations.js +199 -0
- package/dist/rails-migrations.js.map +1 -0
- package/dist/rails-stores.d.ts +49 -0
- package/dist/rails-stores.d.ts.map +1 -0
- package/dist/rails-stores.js +100 -0
- package/dist/rails-stores.js.map +1 -0
- package/dist/reaper.d.ts +69 -0
- package/dist/reaper.d.ts.map +1 -0
- package/dist/reaper.js +152 -0
- package/dist/reaper.js.map +1 -0
- package/dist/record-store.d.ts +36 -0
- package/dist/record-store.d.ts.map +1 -0
- package/dist/record-store.js +78 -0
- package/dist/record-store.js.map +1 -0
- package/dist/recovery-io.d.ts +50 -0
- package/dist/recovery-io.d.ts.map +1 -0
- package/dist/recovery-io.js +122 -0
- package/dist/recovery-io.js.map +1 -0
- package/dist/recovery.d.ts +146 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +110 -0
- package/dist/recovery.js.map +1 -0
- package/dist/redraw.d.ts +34 -0
- package/dist/redraw.d.ts.map +1 -0
- package/dist/redraw.js +62 -0
- package/dist/redraw.js.map +1 -0
- package/dist/rejected-evidence.d.ts +255 -0
- package/dist/rejected-evidence.d.ts.map +1 -0
- package/dist/rejected-evidence.js +324 -0
- package/dist/rejected-evidence.js.map +1 -0
- package/dist/report-cmd.d.ts +32 -0
- package/dist/report-cmd.d.ts.map +1 -0
- package/dist/report-cmd.js +201 -0
- package/dist/report-cmd.js.map +1 -0
- package/dist/repos-cmd.d.ts +80 -0
- package/dist/repos-cmd.d.ts.map +1 -0
- package/dist/repos-cmd.js +240 -0
- package/dist/repos-cmd.js.map +1 -0
- package/dist/request-body-shape.d.ts +93 -0
- package/dist/request-body-shape.d.ts.map +1 -0
- package/dist/request-body-shape.js +407 -0
- package/dist/request-body-shape.js.map +1 -0
- package/dist/requirement-claims.d.ts +89 -0
- package/dist/requirement-claims.d.ts.map +1 -0
- package/dist/requirement-claims.js +92 -0
- package/dist/requirement-claims.js.map +1 -0
- package/dist/retention-apply-runtime.d.ts +105 -0
- package/dist/retention-apply-runtime.d.ts.map +1 -0
- package/dist/retention-apply-runtime.js +269 -0
- package/dist/retention-apply-runtime.js.map +1 -0
- package/dist/reverify.d.ts +41 -0
- package/dist/reverify.d.ts.map +1 -0
- package/dist/reverify.js +69 -0
- package/dist/reverify.js.map +1 -0
- package/dist/round-records.d.ts +65 -0
- package/dist/round-records.d.ts.map +1 -0
- package/dist/round-records.js +61 -0
- package/dist/round-records.js.map +1 -0
- package/dist/round-runner.d.ts +924 -0
- package/dist/round-runner.d.ts.map +1 -0
- package/dist/round-runner.js +1693 -0
- package/dist/round-runner.js.map +1 -0
- package/dist/run-approval.d.ts +180 -0
- package/dist/run-approval.d.ts.map +1 -0
- package/dist/run-approval.js +199 -0
- package/dist/run-approval.js.map +1 -0
- package/dist/run-cmd.d.ts +359 -0
- package/dist/run-cmd.d.ts.map +1 -0
- package/dist/run-cmd.js +4418 -0
- package/dist/run-cmd.js.map +1 -0
- package/dist/run-delivery.d.ts +71 -0
- package/dist/run-delivery.d.ts.map +1 -0
- package/dist/run-delivery.js +104 -0
- package/dist/run-delivery.js.map +1 -0
- package/dist/run-ended.d.ts +75 -0
- package/dist/run-ended.d.ts.map +1 -0
- package/dist/run-ended.js +27 -0
- package/dist/run-ended.js.map +1 -0
- package/dist/run-ending-locator.d.ts +125 -0
- package/dist/run-ending-locator.d.ts.map +1 -0
- package/dist/run-ending-locator.js +133 -0
- package/dist/run-ending-locator.js.map +1 -0
- package/dist/run-launcher.d.ts +459 -0
- package/dist/run-launcher.d.ts.map +1 -0
- package/dist/run-launcher.js +652 -0
- package/dist/run-launcher.js.map +1 -0
- package/dist/run-lease.d.ts +208 -0
- package/dist/run-lease.d.ts.map +1 -0
- package/dist/run-lease.js +301 -0
- package/dist/run-lease.js.map +1 -0
- package/dist/run-refusal-marks.d.ts +189 -0
- package/dist/run-refusal-marks.d.ts.map +1 -0
- package/dist/run-refusal-marks.js +249 -0
- package/dist/run-refusal-marks.js.map +1 -0
- package/dist/run-start-marks.d.ts +153 -0
- package/dist/run-start-marks.d.ts.map +1 -0
- package/dist/run-start-marks.js +269 -0
- package/dist/run-start-marks.js.map +1 -0
- package/dist/scan-cmd.d.ts +14 -0
- package/dist/scan-cmd.d.ts.map +1 -0
- package/dist/scan-cmd.js +270 -0
- package/dist/scan-cmd.js.map +1 -0
- package/dist/scan-events.d.ts +50 -0
- package/dist/scan-events.d.ts.map +1 -0
- package/dist/scan-events.js +91 -0
- package/dist/scan-events.js.map +1 -0
- package/dist/scan.d.ts +191 -0
- package/dist/scan.d.ts.map +1 -0
- package/dist/scan.js +417 -0
- package/dist/scan.js.map +1 -0
- package/dist/scope-rule.d.ts +148 -0
- package/dist/scope-rule.d.ts.map +1 -0
- package/dist/scope-rule.js +121 -0
- package/dist/scope-rule.js.map +1 -0
- package/dist/self-repo-id.d.ts +18 -0
- package/dist/self-repo-id.d.ts.map +1 -0
- package/dist/self-repo-id.js +70 -0
- package/dist/self-repo-id.js.map +1 -0
- package/dist/serve-cmd.d.ts +115 -0
- package/dist/serve-cmd.d.ts.map +1 -0
- package/dist/serve-cmd.js +505 -0
- package/dist/serve-cmd.js.map +1 -0
- package/dist/serve.d.ts +167 -0
- package/dist/serve.d.ts.map +1 -0
- package/dist/serve.js +336 -0
- package/dist/serve.js.map +1 -0
- package/dist/server-client.d.ts +766 -0
- package/dist/server-client.d.ts.map +1 -0
- package/dist/server-client.js +475 -0
- package/dist/server-client.js.map +1 -0
- package/dist/session-adapter-runtime.d.ts +195 -0
- package/dist/session-adapter-runtime.d.ts.map +1 -0
- package/dist/session-adapter-runtime.js +373 -0
- package/dist/session-adapter-runtime.js.map +1 -0
- package/dist/session-checkpoint-runtime.d.ts +62 -0
- package/dist/session-checkpoint-runtime.d.ts.map +1 -0
- package/dist/session-checkpoint-runtime.js +268 -0
- package/dist/session-checkpoint-runtime.js.map +1 -0
- package/dist/session-control-transport.d.ts +106 -0
- package/dist/session-control-transport.d.ts.map +1 -0
- package/dist/session-control-transport.js +232 -0
- package/dist/session-control-transport.js.map +1 -0
- package/dist/session-observation-store.d.ts +98 -0
- package/dist/session-observation-store.d.ts.map +1 -0
- package/dist/session-observation-store.js +155 -0
- package/dist/session-observation-store.js.map +1 -0
- package/dist/session-observe-runtime.d.ts +123 -0
- package/dist/session-observe-runtime.d.ts.map +1 -0
- package/dist/session-observe-runtime.js +317 -0
- package/dist/session-observe-runtime.js.map +1 -0
- package/dist/session-store.d.ts +98 -0
- package/dist/session-store.d.ts.map +1 -0
- package/dist/session-store.js +116 -0
- package/dist/session-store.js.map +1 -0
- package/dist/sessions-cmd.d.ts +202 -0
- package/dist/sessions-cmd.d.ts.map +1 -0
- package/dist/sessions-cmd.js +609 -0
- package/dist/sessions-cmd.js.map +1 -0
- package/dist/settings-overlay.d.ts +53 -0
- package/dist/settings-overlay.d.ts.map +1 -0
- package/dist/settings-overlay.js +175 -0
- package/dist/settings-overlay.js.map +1 -0
- package/dist/setup-prompt.d.ts +34 -0
- package/dist/setup-prompt.d.ts.map +1 -0
- package/dist/setup-prompt.js +92 -0
- package/dist/setup-prompt.js.map +1 -0
- package/dist/setup.d.ts +103 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +283 -0
- package/dist/setup.js.map +1 -0
- package/dist/shared-grants.d.ts +164 -0
- package/dist/shared-grants.d.ts.map +1 -0
- package/dist/shared-grants.js +242 -0
- package/dist/shared-grants.js.map +1 -0
- package/dist/signals.d.ts +55 -0
- package/dist/signals.d.ts.map +1 -0
- package/dist/signals.js +85 -0
- package/dist/signals.js.map +1 -0
- package/dist/source-cmd.d.ts +201 -0
- package/dist/source-cmd.d.ts.map +1 -0
- package/dist/source-cmd.js +684 -0
- package/dist/source-cmd.js.map +1 -0
- package/dist/source-verdict.d.ts +99 -0
- package/dist/source-verdict.d.ts.map +1 -0
- package/dist/source-verdict.js +182 -0
- package/dist/source-verdict.js.map +1 -0
- package/dist/spend-ledger.d.ts +350 -0
- package/dist/spend-ledger.d.ts.map +1 -0
- package/dist/spend-ledger.js +546 -0
- package/dist/spend-ledger.js.map +1 -0
- package/dist/stale-run-sweep.d.ts +79 -0
- package/dist/stale-run-sweep.d.ts.map +1 -0
- package/dist/stale-run-sweep.js +116 -0
- package/dist/stale-run-sweep.js.map +1 -0
- package/dist/start-attempts.d.ts +385 -0
- package/dist/start-attempts.d.ts.map +1 -0
- package/dist/start-attempts.js +613 -0
- package/dist/start-attempts.js.map +1 -0
- package/dist/status-cmd.d.ts +28 -0
- package/dist/status-cmd.d.ts.map +1 -0
- package/dist/status-cmd.js +116 -0
- package/dist/status-cmd.js.map +1 -0
- package/dist/stop-follow-up.d.ts +107 -0
- package/dist/stop-follow-up.d.ts.map +1 -0
- package/dist/stop-follow-up.js +172 -0
- package/dist/stop-follow-up.js.map +1 -0
- package/dist/surface-lease.d.ts +118 -0
- package/dist/surface-lease.d.ts.map +1 -0
- package/dist/surface-lease.js +485 -0
- package/dist/surface-lease.js.map +1 -0
- package/dist/sync.d.ts +54 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +93 -0
- package/dist/sync.js.map +1 -0
- package/dist/syncing-ledger.d.ts +45 -0
- package/dist/syncing-ledger.d.ts.map +1 -0
- package/dist/syncing-ledger.js +53 -0
- package/dist/syncing-ledger.js.map +1 -0
- package/dist/temp-fixtures.d.ts +68 -0
- package/dist/temp-fixtures.d.ts.map +1 -0
- package/dist/temp-fixtures.js +38 -0
- package/dist/temp-fixtures.js.map +1 -0
- package/dist/token-window.d.ts +84 -0
- package/dist/token-window.d.ts.map +1 -0
- package/dist/token-window.js +143 -0
- package/dist/token-window.js.map +1 -0
- package/dist/tool-bridge.d.ts +177 -0
- package/dist/tool-bridge.d.ts.map +1 -0
- package/dist/tool-bridge.js +329 -0
- package/dist/tool-bridge.js.map +1 -0
- package/dist/tool-call-record.d.ts +197 -0
- package/dist/tool-call-record.d.ts.map +1 -0
- package/dist/tool-call-record.js +276 -0
- package/dist/tool-call-record.js.map +1 -0
- package/dist/tool-protocol.d.ts +135 -0
- package/dist/tool-protocol.d.ts.map +1 -0
- package/dist/tool-protocol.js +104 -0
- package/dist/tool-protocol.js.map +1 -0
- package/dist/tool-worker.d.ts +3 -0
- package/dist/tool-worker.d.ts.map +1 -0
- package/dist/tool-worker.js +478 -0
- package/dist/tool-worker.js.map +1 -0
- package/dist/toolchain-mirror.d.ts +86 -0
- package/dist/toolchain-mirror.d.ts.map +1 -0
- package/dist/toolchain-mirror.js +307 -0
- package/dist/toolchain-mirror.js.map +1 -0
- package/dist/trusted-git.d.ts +243 -0
- package/dist/trusted-git.d.ts.map +1 -0
- package/dist/trusted-git.js +920 -0
- package/dist/trusted-git.js.map +1 -0
- package/dist/ui.d.ts +76 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +118 -0
- package/dist/ui.js.map +1 -0
- package/dist/untrusted-exec.d.ts +275 -0
- package/dist/untrusted-exec.d.ts.map +1 -0
- package/dist/untrusted-exec.js +479 -0
- package/dist/untrusted-exec.js.map +1 -0
- package/dist/untrusted-gate.d.ts +73 -0
- package/dist/untrusted-gate.d.ts.map +1 -0
- package/dist/untrusted-gate.js +226 -0
- package/dist/untrusted-gate.js.map +1 -0
- package/dist/uploader.d.ts +153 -0
- package/dist/uploader.d.ts.map +1 -0
- package/dist/uploader.js +204 -0
- package/dist/uploader.js.map +1 -0
- package/dist/verifier.d.ts +66 -0
- package/dist/verifier.d.ts.map +1 -0
- package/dist/verifier.js +170 -0
- package/dist/verifier.js.map +1 -0
- package/dist/verify-apply.d.ts +26 -0
- package/dist/verify-apply.d.ts.map +1 -0
- package/dist/verify-apply.js +36 -0
- package/dist/verify-apply.js.map +1 -0
- package/dist/verify-cmd.d.ts +44 -0
- package/dist/verify-cmd.d.ts.map +1 -0
- package/dist/verify-cmd.js +125 -0
- package/dist/verify-cmd.js.map +1 -0
- package/dist/verify-pass.d.ts +73 -0
- package/dist/verify-pass.d.ts.map +1 -0
- package/dist/verify-pass.js +103 -0
- package/dist/verify-pass.js.map +1 -0
- package/dist/welcome.d.ts +43 -0
- package/dist/welcome.d.ts.map +1 -0
- package/dist/welcome.js +116 -0
- package/dist/welcome.js.map +1 -0
- package/dist/workspace-provisioner.d.ts +65 -0
- package/dist/workspace-provisioner.d.ts.map +1 -0
- package/dist/workspace-provisioner.js +66 -0
- package/dist/workspace-provisioner.js.map +1 -0
- package/dist/workspace-quarantine.d.ts +64 -0
- package/dist/workspace-quarantine.d.ts.map +1 -0
- package/dist/workspace-quarantine.js +156 -0
- package/dist/workspace-quarantine.js.map +1 -0
- package/dist/workspace-residue-sweep.d.ts +113 -0
- package/dist/workspace-residue-sweep.d.ts.map +1 -0
- package/dist/workspace-residue-sweep.js +158 -0
- package/dist/workspace-residue-sweep.js.map +1 -0
- package/dist/workspace.d.ts +639 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +2026 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +52 -4
- package/win/CredProbe.cs +64 -0
- package/win/FakeClaude.cs +56 -0
- package/win/HandleProbe.cs +116 -0
- package/win/TokenProbe.cs +53 -0
- package/win/appcontainer.ps1 +500 -0
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
<#
|
|
2
|
+
THE WINDOWS HALF OF UNTRUSTED EXECUTION.
|
|
3
|
+
|
|
4
|
+
Node cannot reach the AppContainer APIs, so this script is the bridge. It is
|
|
5
|
+
the smallest thing that works: source-controlled PowerShell, compiled at
|
|
6
|
+
runtime by the .NET Framework compiler every Windows box already has. No npm
|
|
7
|
+
dependency, no build step, no downloaded binary, no administrator.
|
|
8
|
+
|
|
9
|
+
IT TAKES JSON ON STDIN AND WRITES ONE JSON OBJECT TO STDOUT. Never a shell
|
|
10
|
+
string: the executable and its arguments arrive as separate fields and are
|
|
11
|
+
passed to CreateProcess as separate things, so nothing the agent writes can
|
|
12
|
+
become a command.
|
|
13
|
+
|
|
14
|
+
What it does, in order:
|
|
15
|
+
|
|
16
|
+
1. ensure an AppContainer profile exists for the requested identity
|
|
17
|
+
2. grant that container SID access to exactly the paths named, and nothing
|
|
18
|
+
else
|
|
19
|
+
3. launch the process inside the container with an explicit cwd and an
|
|
20
|
+
explicit environment block
|
|
21
|
+
4. hold it in a job object so descendants die with it
|
|
22
|
+
5. wait, with a timeout, and report the exit code
|
|
23
|
+
|
|
24
|
+
The security property is deny-by-default: a path nobody granted is a path
|
|
25
|
+
the child cannot reach, whatever the child tries.
|
|
26
|
+
#>
|
|
27
|
+
[CmdletBinding()]
|
|
28
|
+
param()
|
|
29
|
+
|
|
30
|
+
$ErrorActionPreference = 'Stop'
|
|
31
|
+
|
|
32
|
+
function Write-Result($obj) {
|
|
33
|
+
# One line, one object. The caller parses stdout as a single document.
|
|
34
|
+
[Console]::Out.Write((ConvertTo-Json $obj -Compress -Depth 6))
|
|
35
|
+
[Console]::Out.Flush()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
$src = @'
|
|
39
|
+
using System;
|
|
40
|
+
using System.Runtime.InteropServices;
|
|
41
|
+
using System.Text;
|
|
42
|
+
|
|
43
|
+
public static class LooplyAc {
|
|
44
|
+
[StructLayout(LayoutKind.Sequential)] public struct SID_AND_ATTRIBUTES {
|
|
45
|
+
public IntPtr Sid; public uint Attributes; }
|
|
46
|
+
[StructLayout(LayoutKind.Sequential)] public struct SECURITY_CAPABILITIES {
|
|
47
|
+
public IntPtr AppContainerSid; public IntPtr Capabilities; public uint CapabilityCount; public uint Reserved; }
|
|
48
|
+
[StructLayout(LayoutKind.Sequential)] public struct SECURITY_ATTRIBUTES {
|
|
49
|
+
public int nLength; public IntPtr lpSecurityDescriptor; public int bInheritHandle; }
|
|
50
|
+
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] public struct STARTUPINFOEX {
|
|
51
|
+
public int cb; public string lpReserved; public string lpDesktop; public string lpTitle;
|
|
52
|
+
public int dwX; public int dwY; public int dwXSize; public int dwYSize;
|
|
53
|
+
public int dwXCountChars; public int dwYCountChars; public int dwFillAttribute; public int dwFlags;
|
|
54
|
+
public short wShowWindow; public short cbReserved2; public IntPtr lpReserved2;
|
|
55
|
+
public IntPtr hStdInput; public IntPtr hStdOutput; public IntPtr hStdError; public IntPtr lpAttributeList; }
|
|
56
|
+
[StructLayout(LayoutKind.Sequential)] public struct PROCESS_INFORMATION {
|
|
57
|
+
public IntPtr hProcess; public IntPtr hThread; public int dwProcessId; public int dwThreadId; }
|
|
58
|
+
[StructLayout(LayoutKind.Sequential)] public struct JOBOBJECT_BASIC_LIMIT_INFORMATION {
|
|
59
|
+
public long PerProcessUserTimeLimit; public long PerJobUserTimeLimit; public uint LimitFlags;
|
|
60
|
+
public UIntPtr MinimumWorkingSetSize; public UIntPtr MaximumWorkingSetSize; public uint ActiveProcessLimit;
|
|
61
|
+
public UIntPtr Affinity; public uint PriorityClass; public uint SchedulingClass; }
|
|
62
|
+
[StructLayout(LayoutKind.Sequential)] public struct IO_COUNTERS {
|
|
63
|
+
public ulong ReadOperationCount; public ulong WriteOperationCount; public ulong OtherOperationCount;
|
|
64
|
+
public ulong ReadTransferCount; public ulong WriteTransferCount; public ulong OtherTransferCount; }
|
|
65
|
+
[StructLayout(LayoutKind.Sequential)] public struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION {
|
|
66
|
+
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation; public IO_COUNTERS IoInfo;
|
|
67
|
+
public UIntPtr ProcessMemoryLimit; public UIntPtr JobMemoryLimit;
|
|
68
|
+
public UIntPtr PeakProcessMemoryUsed; public UIntPtr PeakJobMemoryUsed; }
|
|
69
|
+
|
|
70
|
+
[DllImport("userenv.dll", CharSet=CharSet.Unicode)] public static extern int CreateAppContainerProfile(string n, string d, string desc, IntPtr caps, uint c, out IntPtr sid);
|
|
71
|
+
[DllImport("userenv.dll", CharSet=CharSet.Unicode)] public static extern int DeriveAppContainerSidFromAppContainerName(string n, out IntPtr sid);
|
|
72
|
+
[DllImport("userenv.dll", CharSet=CharSet.Unicode)] public static extern int DeleteAppContainerProfile(string n);
|
|
73
|
+
// CharSet matters: without it this binds ConvertSidToStringSidA and the
|
|
74
|
+
// wide read below returns question marks instead of a SID.
|
|
75
|
+
[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)] public static extern bool ConvertSidToStringSid(IntPtr sid, out IntPtr str);
|
|
76
|
+
[DllImport("kernel32.dll", SetLastError=true)] public static extern bool InitializeProcThreadAttributeList(IntPtr l, int c, int f, ref IntPtr size);
|
|
77
|
+
[DllImport("kernel32.dll", SetLastError=true)] public static extern bool UpdateProcThreadAttribute(IntPtr l, uint f, IntPtr a, IntPtr v, IntPtr s, IntPtr p, IntPtr r);
|
|
78
|
+
[DllImport("kernel32.dll")] public static extern void DeleteProcThreadAttributeList(IntPtr l);
|
|
79
|
+
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)] public static extern bool CreateProcess(string app, StringBuilder cmd, IntPtr pa, IntPtr ta, bool inherit, uint flags, IntPtr env, string cwd, ref STARTUPINFOEX si, out PROCESS_INFORMATION pi);
|
|
80
|
+
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)] public static extern IntPtr CreateFile(string name, uint access, uint share, ref SECURITY_ATTRIBUTES sa, uint disp, uint flags, IntPtr tmpl);
|
|
81
|
+
[DllImport("kernel32.dll")] public static extern uint WaitForSingleObject(IntPtr h, uint ms);
|
|
82
|
+
[DllImport("kernel32.dll")] public static extern bool GetExitCodeProcess(IntPtr h, out uint c);
|
|
83
|
+
[DllImport("kernel32.dll")] public static extern bool TerminateProcess(IntPtr h, uint c);
|
|
84
|
+
[DllImport("kernel32.dll")] public static extern bool CloseHandle(IntPtr h);
|
|
85
|
+
[DllImport("kernel32.dll")] public static extern void LocalFree(IntPtr p);
|
|
86
|
+
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)] public static extern IntPtr CreateJobObject(IntPtr sa, string name);
|
|
87
|
+
[DllImport("kernel32.dll", SetLastError=true)] public static extern bool AssignProcessToJobObject(IntPtr job, IntPtr proc);
|
|
88
|
+
[DllImport("kernel32.dll", SetLastError=true)] public static extern bool SetInformationJobObject(IntPtr job, int cls, IntPtr info, uint len);
|
|
89
|
+
|
|
90
|
+
public const uint CREATE_UNICODE_ENVIRONMENT = 0x00000400;
|
|
91
|
+
public const uint EXTENDED_STARTUPINFO_PRESENT = 0x00080000;
|
|
92
|
+
public const uint CREATE_NO_WINDOW = 0x08000000;
|
|
93
|
+
public const uint CREATE_SUSPENDED = 0x00000004;
|
|
94
|
+
public const uint STARTF_USESTDHANDLES = 0x00000100;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The container SID for a name, creating the profile on first use.
|
|
98
|
+
*
|
|
99
|
+
* Kept in a static and returned as a string rather than through an `out`
|
|
100
|
+
* parameter: PowerShell does not bind C# `out IntPtr` through [ref], and the
|
|
101
|
+
* silent result is a null SID that fails much later, at the ACL call, with an
|
|
102
|
+
* error naming sddlForm rather than the profile.
|
|
103
|
+
*/
|
|
104
|
+
public static IntPtr Sid = IntPtr.Zero;
|
|
105
|
+
public static string Ensure(string name) {
|
|
106
|
+
IntPtr sid;
|
|
107
|
+
int hr = CreateAppContainerProfile(name, name, "Looply untrusted execution", IntPtr.Zero, 0, out sid);
|
|
108
|
+
if (hr != 0) {
|
|
109
|
+
// 0x800700B7 is "already exists", which is the ordinary second call.
|
|
110
|
+
int hr2 = DeriveAppContainerSidFromAppContainerName(name, out sid);
|
|
111
|
+
if (hr2 != 0) return "ERR profile create hr=0x" + hr.ToString("X8") + " derive hr=0x" + hr2.ToString("X8");
|
|
112
|
+
}
|
|
113
|
+
Sid = sid;
|
|
114
|
+
return SidToString(sid);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public static string SidToString(IntPtr sid) {
|
|
118
|
+
IntPtr p; ConvertSidToStringSid(sid, out p);
|
|
119
|
+
string s = Marshal.PtrToStringUni(p); LocalFree(p); return s;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* A UTF-16 environment block: KEY=VALUE\0 ... \0\0, and nothing inherited.
|
|
124
|
+
*
|
|
125
|
+
* Marshalled as BYTES rather than through StringToHGlobalUni. The block is
|
|
126
|
+
* defined by its embedded nulls, and a string marshaller is exactly the kind
|
|
127
|
+
* of thing that treats the first one as the end — so the copy is done
|
|
128
|
+
* explicitly, where the length is ours to decide.
|
|
129
|
+
*
|
|
130
|
+
* Sorted, because CreateProcess documents the block as sorted and answers
|
|
131
|
+
* ERROR_ENVVAR_NOT_FOUND rather than anything more specific when it is not.
|
|
132
|
+
*/
|
|
133
|
+
public static IntPtr EnvBlock(string[] pairs) {
|
|
134
|
+
string[] sorted = (string[])pairs.Clone();
|
|
135
|
+
Array.Sort(sorted, StringComparer.OrdinalIgnoreCase);
|
|
136
|
+
StringBuilder sb = new StringBuilder();
|
|
137
|
+
foreach (string p in sorted) {
|
|
138
|
+
if (p == null || p.Length == 0 || p.IndexOf('=') <= 0) continue;
|
|
139
|
+
sb.Append(p); sb.Append('\0');
|
|
140
|
+
}
|
|
141
|
+
sb.Append('\0');
|
|
142
|
+
byte[] bytes = Encoding.Unicode.GetBytes(sb.ToString());
|
|
143
|
+
IntPtr mem = Marshal.AllocHGlobal(bytes.Length + 2);
|
|
144
|
+
Marshal.Copy(bytes, 0, mem, bytes.Length);
|
|
145
|
+
// One more UTF-16 null, so the block is terminated even if the last entry
|
|
146
|
+
// was dropped by the filter above.
|
|
147
|
+
Marshal.WriteInt16(mem, bytes.Length, 0);
|
|
148
|
+
return mem;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* A file opened for READING, inheritable, to become the child's stdin.
|
|
153
|
+
*
|
|
154
|
+
* The prompt is many lines of model instructions and must never be part of a
|
|
155
|
+
* command line: a shell would eat the newlines and quoting, and on Windows a
|
|
156
|
+
* command line is capped besides. It travels as bytes through a handle
|
|
157
|
+
* instead, which also means the container needs no grant to read it.
|
|
158
|
+
*/
|
|
159
|
+
public static IntPtr OpenForRead(string path) {
|
|
160
|
+
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
|
|
161
|
+
sa.nLength = Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES));
|
|
162
|
+
sa.lpSecurityDescriptor = IntPtr.Zero;
|
|
163
|
+
sa.bInheritHandle = 1;
|
|
164
|
+
// OPEN_EXISTING, GENERIC_READ, share read.
|
|
165
|
+
return CreateFile(path, 0x80000000, 0x00000001, ref sa, 3, 0x80, IntPtr.Zero);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
public static IntPtr OpenForWrite(string path) {
|
|
169
|
+
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
|
|
170
|
+
sa.nLength = Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES));
|
|
171
|
+
sa.lpSecurityDescriptor = IntPtr.Zero;
|
|
172
|
+
sa.bInheritHandle = 1;
|
|
173
|
+
// CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, GENERIC_WRITE, share read+write.
|
|
174
|
+
return CreateFile(path, 0x40000000, 0x00000003, ref sa, 2, 0x80, IntPtr.Zero);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Launch inside the container and wait.
|
|
179
|
+
*
|
|
180
|
+
* The stdout/stderr handles are opened by US and inherited, so the child
|
|
181
|
+
* writes through a handle it was given rather than through a path it must be
|
|
182
|
+
* granted — the output files never widen the container's filesystem policy.
|
|
183
|
+
*/
|
|
184
|
+
[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
|
|
185
|
+
static extern bool ConvertStringSidToSid(string s, out IntPtr sid);
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* The capability SIDs a container is given, as a native array.
|
|
189
|
+
*
|
|
190
|
+
* A container with none has no network at all, which is what a gate wants and
|
|
191
|
+
* what an agent cannot live with — it has to reach its model. `internetClient`
|
|
192
|
+
* (S-1-15-3-1) is the outbound-client capability, and it is granted to the
|
|
193
|
+
* AGENT profile only.
|
|
194
|
+
*
|
|
195
|
+
* This is broad: it is "may make outbound connections", not "may reach this
|
|
196
|
+
* one host". Narrowing it to the provider's endpoints is egress policy and
|
|
197
|
+
* belongs to a later phase; what matters here is that the agent holds no
|
|
198
|
+
* machine or broker credential to send anywhere.
|
|
199
|
+
*/
|
|
200
|
+
public static IntPtr CapabilityArray(string[] sids, out uint count) {
|
|
201
|
+
count = 0;
|
|
202
|
+
if (sids == null || sids.Length == 0) return IntPtr.Zero;
|
|
203
|
+
int size = Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES));
|
|
204
|
+
IntPtr block = Marshal.AllocHGlobal(size * sids.Length);
|
|
205
|
+
uint n = 0;
|
|
206
|
+
foreach (string s in sids) {
|
|
207
|
+
IntPtr sid;
|
|
208
|
+
if (!ConvertStringSidToSid(s, out sid)) continue;
|
|
209
|
+
SID_AND_ATTRIBUTES sa = new SID_AND_ATTRIBUTES();
|
|
210
|
+
sa.Sid = sid;
|
|
211
|
+
sa.Attributes = 4; // SE_GROUP_ENABLED
|
|
212
|
+
Marshal.StructureToPtr(sa, (IntPtr)(block.ToInt64() + size * (int)n), false);
|
|
213
|
+
n++;
|
|
214
|
+
}
|
|
215
|
+
count = n;
|
|
216
|
+
return n == 0 ? IntPtr.Zero : block;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
public static string Run(string exe, string cmdLine, string cwd, string[] env,
|
|
220
|
+
string outPath, string errPath, string inPath, uint timeoutMs, string[] capabilities,
|
|
221
|
+
out uint exitCode, out bool timedOut) {
|
|
222
|
+
exitCode = 0xFFFFFFFF; timedOut = false;
|
|
223
|
+
uint capCount;
|
|
224
|
+
IntPtr caps = CapabilityArray(capabilities, out capCount);
|
|
225
|
+
SECURITY_CAPABILITIES sc = new SECURITY_CAPABILITIES();
|
|
226
|
+
sc.AppContainerSid = Sid; sc.Capabilities = caps; sc.CapabilityCount = capCount; sc.Reserved = 0;
|
|
227
|
+
|
|
228
|
+
/*
|
|
229
|
+
* TWO attributes, not one. The second is the handle list, and it is the
|
|
230
|
+
* difference between "the child gets the three handles we opened for it"
|
|
231
|
+
* and "the child gets those AND everything inheritable this process holds".
|
|
232
|
+
*
|
|
233
|
+
* 🔴 bInheritHandles IS STILL true BELOW, AND MUST BE. The handle list only
|
|
234
|
+
* NARROWS what an already-inheriting CreateProcess passes; with inheritance
|
|
235
|
+
* off it does nothing and stdio breaks, because an AppContainer cannot open
|
|
236
|
+
* a Windows named pipe (see appcontainer-limits.spec.ts) and handle-inherited
|
|
237
|
+
* file stdio is the only arrangement that works here.
|
|
238
|
+
*
|
|
239
|
+
* What was crossing before: powershell.exe is spawned by Node with
|
|
240
|
+
* stdio:['pipe','pipe','pipe'], and an inherited handle keeps the source
|
|
241
|
+
* handle's HANDLE_FLAG_INHERIT. So this process holds three inheritable
|
|
242
|
+
* NAMED PIPE handles into a trusted, uncontained Node parent — and passed
|
|
243
|
+
* all three to the contained child. That is a channel out of the container
|
|
244
|
+
* that no ACL can deny, on the very pipe the daemon parses as its single
|
|
245
|
+
* JSON reply.
|
|
246
|
+
*
|
|
247
|
+
* The capacity in BOTH calls must match the number of UpdateProcThreadAttribute
|
|
248
|
+
* calls; adding more attributes than the list was sized for corrupts it
|
|
249
|
+
* silently.
|
|
250
|
+
*/
|
|
251
|
+
IntPtr size = IntPtr.Zero;
|
|
252
|
+
InitializeProcThreadAttributeList(IntPtr.Zero, 2, 0, ref size);
|
|
253
|
+
IntPtr attrs = Marshal.AllocHGlobal(size);
|
|
254
|
+
if (!InitializeProcThreadAttributeList(attrs, 2, 0, ref size)) return "attrlist: " + Marshal.GetLastWin32Error();
|
|
255
|
+
IntPtr scPtr = Marshal.AllocHGlobal(Marshal.SizeOf(sc));
|
|
256
|
+
Marshal.StructureToPtr(sc, scPtr, false);
|
|
257
|
+
// PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES — the containment boundary,
|
|
258
|
+
// untouched.
|
|
259
|
+
if (!UpdateProcThreadAttribute(attrs, 0, (IntPtr)0x00020009, scPtr, (IntPtr)Marshal.SizeOf(sc), IntPtr.Zero, IntPtr.Zero))
|
|
260
|
+
return "attrupdate: " + Marshal.GetLastWin32Error();
|
|
261
|
+
|
|
262
|
+
IntPtr hOut = OpenForWrite(outPath);
|
|
263
|
+
IntPtr hErr = OpenForWrite(errPath);
|
|
264
|
+
|
|
265
|
+
STARTUPINFOEX si = new STARTUPINFOEX();
|
|
266
|
+
si.cb = Marshal.SizeOf(si);
|
|
267
|
+
si.lpAttributeList = attrs;
|
|
268
|
+
si.dwFlags = (int)STARTF_USESTDHANDLES;
|
|
269
|
+
IntPtr hIn = string.IsNullOrEmpty(inPath) ? IntPtr.Zero : OpenForRead(inPath);
|
|
270
|
+
si.hStdInput = hIn; si.hStdOutput = hOut; si.hStdError = hErr;
|
|
271
|
+
|
|
272
|
+
/*
|
|
273
|
+
* Every handle in the list must be valid and inheritable, or CreateProcess
|
|
274
|
+
* fails with ERROR_INVALID_PARAMETER (87) — which reads exactly like a
|
|
275
|
+
* containment failure and would be misdiagnosed as one. So the opens are
|
|
276
|
+
* checked HERE, where the cause can still be named, rather than becoming
|
|
277
|
+
* silent bad stdio further down.
|
|
278
|
+
*/
|
|
279
|
+
IntPtr INVALID = new IntPtr(-1);
|
|
280
|
+
if (hOut == INVALID) return "stdio: cannot open the stdout file for the contained child";
|
|
281
|
+
if (hErr == INVALID) return "stdio: cannot open the stderr file for the contained child";
|
|
282
|
+
if (!string.IsNullOrEmpty(inPath) && hIn == INVALID) return "stdio: cannot open the stdin file for the contained child";
|
|
283
|
+
|
|
284
|
+
int hCount = (hIn == IntPtr.Zero) ? 2 : 3;
|
|
285
|
+
IntPtr[] inheritable = (hCount == 2) ? new IntPtr[] { hOut, hErr } : new IntPtr[] { hOut, hErr, hIn };
|
|
286
|
+
IntPtr hlPtr = Marshal.AllocHGlobal(IntPtr.Size * hCount);
|
|
287
|
+
Marshal.Copy(inheritable, 0, hlPtr, hCount);
|
|
288
|
+
// PROC_THREAD_ATTRIBUTE_HANDLE_LIST — exactly the three we opened, and
|
|
289
|
+
// nothing this process happens to be holding.
|
|
290
|
+
if (!UpdateProcThreadAttribute(attrs, 0, (IntPtr)0x00020002, hlPtr, (IntPtr)(IntPtr.Size * hCount), IntPtr.Zero, IntPtr.Zero))
|
|
291
|
+
return "handlelist: " + Marshal.GetLastWin32Error();
|
|
292
|
+
|
|
293
|
+
// NEVER IntPtr.Zero: that means "inherit mine", which is the daemon's
|
|
294
|
+
// environment and the whole thing we are keeping away from this child.
|
|
295
|
+
if (env.Length == 0) return "environment: refusing to launch with no environment block, because a null block would inherit the daemon's";
|
|
296
|
+
IntPtr envPtr = EnvBlock(env);
|
|
297
|
+
PROCESS_INFORMATION pi;
|
|
298
|
+
bool ok = CreateProcess(exe, new StringBuilder(cmdLine), IntPtr.Zero, IntPtr.Zero, true,
|
|
299
|
+
CREATE_UNICODE_ENVIRONMENT | EXTENDED_STARTUPINFO_PRESENT | CREATE_NO_WINDOW | CREATE_SUSPENDED,
|
|
300
|
+
envPtr, cwd, ref si, out pi);
|
|
301
|
+
if (!ok) { int e = Marshal.GetLastWin32Error(); CloseHandle(hOut); CloseHandle(hErr); return "launch: " + e; }
|
|
302
|
+
|
|
303
|
+
// A job object so descendants cannot outlive the command. This is LIFETIME
|
|
304
|
+
// control, not the authority boundary — the container is the boundary.
|
|
305
|
+
//
|
|
306
|
+
// 🔴 EVERY STEP IS CHECKED, AND A FAILURE REFUSES TO LAUNCH.
|
|
307
|
+
//
|
|
308
|
+
// This block used to discard all three results: `CreateJobObject` returning
|
|
309
|
+
// null skipped the `if` entirely, and `SetInformationJobObject` and
|
|
310
|
+
// `AssignProcessToJobObject` were called for effect with their `bool`
|
|
311
|
+
// thrown away. Any of the three failing left the process resuming OUTSIDE
|
|
312
|
+
// any job, with no kill-on-close and nothing anywhere saying so — the
|
|
313
|
+
// lifetime boundary silently absent while every caller believed it was
|
|
314
|
+
// there.
|
|
315
|
+
//
|
|
316
|
+
// Failing closed is clean here precisely because of the ordering already
|
|
317
|
+
// chosen: the process is created SUSPENDED, so nothing of it has run yet
|
|
318
|
+
// and terminating it costs nothing. That ordering was correct for the
|
|
319
|
+
// reason it was written — there is no window in which a child could escape
|
|
320
|
+
// before assignment — and it is what makes refusal possible now.
|
|
321
|
+
IntPtr job = CreateJobObject(IntPtr.Zero, null);
|
|
322
|
+
if (job == IntPtr.Zero) {
|
|
323
|
+
int e = Marshal.GetLastWin32Error();
|
|
324
|
+
TerminateProcess(pi.hProcess, 1);
|
|
325
|
+
CloseHandle(pi.hThread); CloseHandle(pi.hProcess);
|
|
326
|
+
CloseHandle(hOut); CloseHandle(hErr); if (hIn != IntPtr.Zero) CloseHandle(hIn);
|
|
327
|
+
return "job: could not create a job object (" + e + ")";
|
|
328
|
+
}
|
|
329
|
+
JOBOBJECT_EXTENDED_LIMIT_INFORMATION li = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
|
|
330
|
+
li.BasicLimitInformation.LimitFlags = 0x00002000; // KILL_ON_JOB_CLOSE
|
|
331
|
+
IntPtr lp = Marshal.AllocHGlobal(Marshal.SizeOf(li));
|
|
332
|
+
Marshal.StructureToPtr(li, lp, false);
|
|
333
|
+
bool limitsSet = SetInformationJobObject(job, 9, lp, (uint)Marshal.SizeOf(li));
|
|
334
|
+
Marshal.FreeHGlobal(lp);
|
|
335
|
+
bool assigned = limitsSet && AssignProcessToJobObject(job, pi.hProcess);
|
|
336
|
+
if (!assigned) {
|
|
337
|
+
int e = Marshal.GetLastWin32Error();
|
|
338
|
+
TerminateProcess(pi.hProcess, 1);
|
|
339
|
+
CloseHandle(pi.hThread); CloseHandle(pi.hProcess);
|
|
340
|
+
CloseHandle(hOut); CloseHandle(hErr); if (hIn != IntPtr.Zero) CloseHandle(hIn);
|
|
341
|
+
CloseHandle(job);
|
|
342
|
+
return (limitsSet ? "job: could not assign the process to the job (" : "job: could not set kill-on-close (") + e + ")";
|
|
343
|
+
}
|
|
344
|
+
ResumeThreadSafe(pi.hThread);
|
|
345
|
+
|
|
346
|
+
uint w = WaitForSingleObject(pi.hProcess, timeoutMs);
|
|
347
|
+
if (w == 0x00000102) { timedOut = true; TerminateProcess(pi.hProcess, 1); WaitForSingleObject(pi.hProcess, 5000); }
|
|
348
|
+
GetExitCodeProcess(pi.hProcess, out exitCode);
|
|
349
|
+
|
|
350
|
+
CloseHandle(pi.hThread); CloseHandle(pi.hProcess);
|
|
351
|
+
CloseHandle(hOut); CloseHandle(hErr);
|
|
352
|
+
if (hIn != IntPtr.Zero) CloseHandle(hIn);
|
|
353
|
+
if (job != IntPtr.Zero) CloseHandle(job);
|
|
354
|
+
DeleteProcThreadAttributeList(attrs);
|
|
355
|
+
Marshal.FreeHGlobal(attrs); Marshal.FreeHGlobal(scPtr); Marshal.FreeHGlobal(envPtr);
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
[DllImport("kernel32.dll", SetLastError=true)] static extern uint ResumeThread(IntPtr h);
|
|
360
|
+
static void ResumeThreadSafe(IntPtr h) { ResumeThread(h); }
|
|
361
|
+
}
|
|
362
|
+
'@
|
|
363
|
+
|
|
364
|
+
try {
|
|
365
|
+
$raw = [Console]::In.ReadToEnd()
|
|
366
|
+
$req = $raw | ConvertFrom-Json
|
|
367
|
+
} catch {
|
|
368
|
+
Write-Result @{ ok = $false; stage = 'request'; error = "could not read the request: $($_.Exception.Message)" }
|
|
369
|
+
exit 0
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
try {
|
|
373
|
+
Add-Type -TypeDefinition $src -Language CSharp
|
|
374
|
+
} catch {
|
|
375
|
+
Write-Result @{ ok = $false; stage = 'compile'; error = $_.Exception.Message }
|
|
376
|
+
exit 0
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
# --- profile -----------------------------------------------------------------
|
|
380
|
+
$sidStr = [LooplyAc]::Ensure($req.profile)
|
|
381
|
+
if ($sidStr -like 'ERR *') { Write-Result @{ ok = $false; stage = 'profile'; error = $sidStr }; exit 0 }
|
|
382
|
+
if (-not $sidStr) { Write-Result @{ ok = $false; stage = 'profile'; error = 'no container SID' }; exit 0 }
|
|
383
|
+
|
|
384
|
+
if ($req.action -eq 'probe') {
|
|
385
|
+
Write-Result @{ ok = $true; stage = 'probe'; sid = $sidStr }
|
|
386
|
+
exit 0
|
|
387
|
+
}
|
|
388
|
+
if ($req.action -eq 'remove') {
|
|
389
|
+
$hr = [LooplyAc]::DeleteAppContainerProfile($req.profile)
|
|
390
|
+
Write-Result @{ ok = ($hr -eq 0); stage = 'remove'; hr = $hr }
|
|
391
|
+
exit 0
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
# --- filesystem grants -------------------------------------------------------
|
|
395
|
+
# Only the paths named, only the rights named. Additive: existing ACEs are left
|
|
396
|
+
# exactly as they were, so the owner never loses access to their own files.
|
|
397
|
+
try {
|
|
398
|
+
$sidObj = New-Object System.Security.Principal.SecurityIdentifier($sidStr)
|
|
399
|
+
foreach ($g in @($req.grants)) {
|
|
400
|
+
if (-not $g) { continue }
|
|
401
|
+
$rights = if ($g.write) { 'Modify' } else { 'ReadAndExecute' }
|
|
402
|
+
$acl = Get-Acl $g.path
|
|
403
|
+
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
|
|
404
|
+
$sidObj, $rights, 'ContainerInherit,ObjectInherit', 'None', 'Allow')
|
|
405
|
+
$acl.AddAccessRule($rule)
|
|
406
|
+
Set-Acl $g.path $acl
|
|
407
|
+
}
|
|
408
|
+
} catch {
|
|
409
|
+
Write-Result @{ ok = $false; stage = 'grant'; error = $_.Exception.Message; sid = $sidStr }
|
|
410
|
+
exit 0
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
# --- protected subtrees ------------------------------------------------------
|
|
414
|
+
# A grant on the project root is inheritable, so `.git` and `.looply/state` come
|
|
415
|
+
# with it unless they are taken back. They are taken back by BREAKING
|
|
416
|
+
# INHERITANCE and removing the container's own ACEs — not by adding a DENY.
|
|
417
|
+
#
|
|
418
|
+
# Deny ACEs sort ahead of allows and would apply to anyone who happened to match
|
|
419
|
+
# later, which on a path the person also owns is a good way to lock the owner
|
|
420
|
+
# out of their own repository. Removing the container's allow leaves every other
|
|
421
|
+
# ACE exactly as it was.
|
|
422
|
+
try {
|
|
423
|
+
$ACCESS_ONLY = [System.Security.AccessControl.AccessControlSections]::Access
|
|
424
|
+
foreach ($p in @($req.protect)) {
|
|
425
|
+
if (-not $p) { continue }
|
|
426
|
+
# A path that is not there protects itself. A project without a config.yaml
|
|
427
|
+
# must not fail to run a gate over it.
|
|
428
|
+
if (-not (Test-Path $p)) { continue }
|
|
429
|
+
# THE DACL ONLY. Get-Acl/Set-Acl round-trip the audit section too, and
|
|
430
|
+
# writing a SACL needs SeSecurityPrivilege, which an ordinary user does not
|
|
431
|
+
# hold — the operation then fails naming a privilege rather than a path.
|
|
432
|
+
# A protected path may be a file — `.looply/config.yaml` names the gate
|
|
433
|
+
# commands and the rails, so it is as worth protecting as the state
|
|
434
|
+
# directory, and FileInfo carries the same access-control surface.
|
|
435
|
+
if (Test-Path $p -PathType Leaf) {
|
|
436
|
+
$di = New-Object System.IO.FileInfo($p)
|
|
437
|
+
} else {
|
|
438
|
+
$di = New-Object System.IO.DirectoryInfo($p)
|
|
439
|
+
}
|
|
440
|
+
$acl = $di.GetAccessControl($ACCESS_ONLY)
|
|
441
|
+
# (true, true): stop inheriting, and keep what was inherited as explicit
|
|
442
|
+
# entries, so SYSTEM, Administrators and the owner are unaffected.
|
|
443
|
+
# TWO STEPS, and the order is the whole trick. An INHERITED entry cannot be
|
|
444
|
+
# removed where it appears — it lives on the parent. Breaking inheritance
|
|
445
|
+
# with (true, true) copies it down as an explicit entry, but only once that
|
|
446
|
+
# has been SAVED; purging before the save silently removes nothing and
|
|
447
|
+
# reports success.
|
|
448
|
+
$acl.SetAccessRuleProtection($true, $true)
|
|
449
|
+
$di.SetAccessControl($acl)
|
|
450
|
+
|
|
451
|
+
$acl = $di.GetAccessControl($ACCESS_ONLY)
|
|
452
|
+
# Purge by IDENTITY, not by rule: RemoveAccessRule matches rights and
|
|
453
|
+
# inheritance flags too, so an entry differing in any of them survives.
|
|
454
|
+
$acl.PurgeAccessRules($sidObj)
|
|
455
|
+
$di.SetAccessControl($acl)
|
|
456
|
+
# Prove it, rather than trust it: if the container can still be found in
|
|
457
|
+
# the effective ACL, the protection did not happen.
|
|
458
|
+
$after = (New-Object System.IO.DirectoryInfo($p)).GetAccessControl($ACCESS_ONLY)
|
|
459
|
+
foreach ($rule in @($after.Access)) {
|
|
460
|
+
if ($rule.IdentityReference.Value -eq $sidStr) {
|
|
461
|
+
throw "the container is still granted on $p after protection"
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
} catch {
|
|
466
|
+
# FAIL CLOSED. A protected path that could not be protected must not become a
|
|
467
|
+
# path the container may write; nothing has been launched yet.
|
|
468
|
+
Write-Result @{ ok = $false; stage = 'protect'; error = $_.Exception.Message; sid = $sidStr }
|
|
469
|
+
exit 0
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
# --- launch ------------------------------------------------------------------
|
|
473
|
+
$envPairs = @()
|
|
474
|
+
foreach ($p in $req.env.PSObject.Properties) { $envPairs += ("{0}={1}" -f $p.Name, $p.Value) }
|
|
475
|
+
|
|
476
|
+
$exitCode = [uint32]0
|
|
477
|
+
$timedOut = $false
|
|
478
|
+
# internetClient (S-1-15-3-1) for the agent; nothing at all for the gate.
|
|
479
|
+
$caps = @()
|
|
480
|
+
if ($req.network -eq 'internet-client') {
|
|
481
|
+
# internetClient, plus privateNetworkClientServer so an endpoint on the
|
|
482
|
+
# machine's own subnet is reachable too. Neither covers loopback: an
|
|
483
|
+
# AppContainer needs a separate CheckNetIsolation exemption for 127.0.0.1,
|
|
484
|
+
# which is why a loopback probe cannot tell these two profiles apart.
|
|
485
|
+
$caps = @('S-1-15-3-1', 'S-1-15-3-3')
|
|
486
|
+
}
|
|
487
|
+
$stdinPath = if ($req.stdinPath) { [string]$req.stdinPath } else { '' }
|
|
488
|
+
$runErr = [LooplyAc]::Run($req.executable, $req.commandLine, $req.cwd, [string[]]$envPairs,
|
|
489
|
+
$req.stdoutPath, $req.stderrPath, $stdinPath, [uint32]$req.timeoutMs, [string[]]$caps,
|
|
490
|
+
[ref]$exitCode, [ref]$timedOut)
|
|
491
|
+
if ($runErr) {
|
|
492
|
+
# The environment count travels with the failure: CreateProcess answers 203
|
|
493
|
+
# (ERROR_ENVVAR_NOT_FOUND) for an EMPTY block as readily as a malformed one,
|
|
494
|
+
# and those two look identical from the outside.
|
|
495
|
+
Write-Result @{ ok = $false; stage = 'launch'; error = $runErr; sid = $sidStr; envCount = $envPairs.Count; envSample = ($envPairs -join '|'); exeOk = (Test-Path $req.executable); cwdOk = (Test-Path $req.cwd) }
|
|
496
|
+
exit 0
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
Write-Result @{ ok = $true; stage = 'ran'; sid = $sidStr; exitCode = [int]$exitCode; timedOut = $timedOut }
|
|
500
|
+
exit 0
|