@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,190 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { constants } from 'node:fs';
|
|
3
|
+
import { lstat, open, realpath } from 'node:fs/promises';
|
|
4
|
+
import { basename, delimiter, isAbsolute, join, normalize, resolve } from 'node:path';
|
|
5
|
+
import { errorCause } from './contract.js';
|
|
6
|
+
import { fileFingerprint, recordVerifiedDigest, verifiedDigest } from '../environment-exec/verified-digest.js';
|
|
7
|
+
import { exactKeys } from '../exact-keys.js';
|
|
8
|
+
// A guard runs inside the agent's hook with an environment the agent controls, so the tools it
|
|
9
|
+
// observes with are found on this fixed search path rather than the inherited PATH.
|
|
10
|
+
export const GUARD_EXECUTABLE_SEARCH_PATH = '/usr/bin:/bin:/usr/local/bin:/opt/homebrew/bin';
|
|
11
|
+
const SHA256 = /^[a-f0-9]{64}$/;
|
|
12
|
+
export function resolvedExecutable(value) {
|
|
13
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value)
|
|
14
|
+
|| !exactKeys(value, ['canonicalPath', 'invocationPath', 'sha256', 'executionMode']))
|
|
15
|
+
return undefined;
|
|
16
|
+
const { canonicalPath, invocationPath, sha256, executionMode } = value;
|
|
17
|
+
return typeof canonicalPath === 'string' && isAbsolute(canonicalPath) && normalize(canonicalPath) === canonicalPath
|
|
18
|
+
&& !canonicalPath.includes('\0') && typeof invocationPath === 'string' && isAbsolute(invocationPath)
|
|
19
|
+
&& normalize(invocationPath) === invocationPath && !invocationPath.includes('\0')
|
|
20
|
+
&& typeof sha256 === 'string' && SHA256.test(sha256)
|
|
21
|
+
&& executionMode === 'verified-path'
|
|
22
|
+
? { canonicalPath, invocationPath, sha256, executionMode }
|
|
23
|
+
: undefined;
|
|
24
|
+
}
|
|
25
|
+
export function isResolvedExecutable(value) {
|
|
26
|
+
return resolvedExecutable(value) !== undefined;
|
|
27
|
+
}
|
|
28
|
+
export function resolvedDockerExecutable(value) {
|
|
29
|
+
const executable = resolvedExecutable(value);
|
|
30
|
+
return executable !== undefined && basename(executable.invocationPath) === 'docker' ? executable : undefined;
|
|
31
|
+
}
|
|
32
|
+
export function isResolvedDockerExecutable(value) {
|
|
33
|
+
return resolvedDockerExecutable(value) !== undefined;
|
|
34
|
+
}
|
|
35
|
+
export function resolvedGitExecutable(value) {
|
|
36
|
+
const executable = resolvedExecutable(value);
|
|
37
|
+
return executable !== undefined && basename(executable.invocationPath) === 'git' ? executable : undefined;
|
|
38
|
+
}
|
|
39
|
+
export function isResolvedGitExecutable(value) {
|
|
40
|
+
return resolvedGitExecutable(value) !== undefined;
|
|
41
|
+
}
|
|
42
|
+
const EXECUTABLE_BYTE_LIMIT = 536_870_912;
|
|
43
|
+
const PATH_ENTRY_LIMIT = 256;
|
|
44
|
+
function searchPath(env) {
|
|
45
|
+
try {
|
|
46
|
+
return { kind: 'selected', path: env.PATH };
|
|
47
|
+
}
|
|
48
|
+
catch { /* A throwing PATH getter means the environment is unreadable; the caller reports it as unavailable. */
|
|
49
|
+
return { kind: 'unreadable' };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function unavailable(reason) {
|
|
53
|
+
return { state: 'unavailable', reason };
|
|
54
|
+
}
|
|
55
|
+
async function digestRegularFile(path) {
|
|
56
|
+
let file;
|
|
57
|
+
try {
|
|
58
|
+
const before = await lstat(path);
|
|
59
|
+
if (before.isSymbolicLink() || !before.isFile() || before.size > EXECUTABLE_BYTE_LIMIT || (before.mode & 0o111) === 0)
|
|
60
|
+
return undefined;
|
|
61
|
+
file = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
62
|
+
const opened = await file.stat();
|
|
63
|
+
if (!opened.isFile() || opened.dev !== before.dev || opened.ino !== before.ino || opened.size > EXECUTABLE_BYTE_LIMIT)
|
|
64
|
+
return undefined;
|
|
65
|
+
const fingerprint = fileFingerprint(path, opened);
|
|
66
|
+
const remembered = verifiedDigest(fingerprint);
|
|
67
|
+
if (remembered !== undefined)
|
|
68
|
+
return fileFingerprint(path, await lstat(path)) === fingerprint ? remembered : undefined;
|
|
69
|
+
const hash = createHash('sha256');
|
|
70
|
+
const chunk = Buffer.allocUnsafe(1_048_576);
|
|
71
|
+
let total = 0;
|
|
72
|
+
while (true) {
|
|
73
|
+
const { bytesRead } = await file.read(chunk, 0, Math.min(chunk.byteLength, EXECUTABLE_BYTE_LIMIT - total + 1), null);
|
|
74
|
+
if (bytesRead === 0)
|
|
75
|
+
break;
|
|
76
|
+
total += bytesRead;
|
|
77
|
+
if (total > EXECUTABLE_BYTE_LIMIT)
|
|
78
|
+
return undefined;
|
|
79
|
+
hash.update(chunk.subarray(0, bytesRead));
|
|
80
|
+
}
|
|
81
|
+
const after = await file.stat();
|
|
82
|
+
const linked = await lstat(path);
|
|
83
|
+
const sha256 = total === opened.size && after.size === opened.size && after.mtimeMs === opened.mtimeMs
|
|
84
|
+
&& linked.dev === opened.dev && linked.ino === opened.ino && linked.size === opened.size && linked.mtimeMs === opened.mtimeMs
|
|
85
|
+
? hash.digest('hex')
|
|
86
|
+
: undefined;
|
|
87
|
+
if (sha256 !== undefined && fileFingerprint(path, after) === fingerprint)
|
|
88
|
+
recordVerifiedDigest(fingerprint, sha256);
|
|
89
|
+
await file.close();
|
|
90
|
+
file = undefined;
|
|
91
|
+
return sha256;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Any read failure means no digest; the caller reports the executable identity as unavailable.
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
try {
|
|
99
|
+
await file?.close();
|
|
100
|
+
}
|
|
101
|
+
catch { /* The caller receives unavailable; no descriptor authority survives. */ }
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// The checks that need no file contents: an exact absolute path naming an executable file, or a
|
|
105
|
+
// link that resolves to one.
|
|
106
|
+
async function checkExecutablePath(path) {
|
|
107
|
+
if (typeof path !== 'string' || !isAbsolute(path) || normalize(path) !== path || path.includes('\0')) {
|
|
108
|
+
return { state: 'unavailable', reason: 'Executable path must be an exact absolute path' };
|
|
109
|
+
}
|
|
110
|
+
let invocation;
|
|
111
|
+
try {
|
|
112
|
+
invocation = await lstat(path);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
return { state: 'unavailable', reason: `Executable is unavailable: ${path}: ${errorCause(error)}` };
|
|
116
|
+
}
|
|
117
|
+
if (!(invocation.isFile() || invocation.isSymbolicLink()) || invocation.isFile() && (invocation.mode & 0o111) === 0) {
|
|
118
|
+
return { state: 'unavailable', reason: `Executable is unavailable: ${path}` };
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
return { state: 'present', path, canonicalPath: await realpath(path) };
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
return { state: 'unavailable', reason: `Executable is unavailable: ${path}: ${errorCause(error)}` };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
export async function resolveExecutablePath(path) {
|
|
128
|
+
const checked = await checkExecutablePath(path);
|
|
129
|
+
if (checked.state === 'unavailable')
|
|
130
|
+
return unavailable(checked.reason);
|
|
131
|
+
const sha256 = await digestRegularFile(checked.canonicalPath);
|
|
132
|
+
if (sha256 === undefined)
|
|
133
|
+
return unavailable(`Executable identity is unavailable: ${path}`);
|
|
134
|
+
const value = resolvedExecutable({ canonicalPath: checked.canonicalPath, invocationPath: path, sha256, executionMode: 'verified-path' });
|
|
135
|
+
return value ? { state: 'available', value } : unavailable(`Executable identity is invalid: ${path}`);
|
|
136
|
+
}
|
|
137
|
+
const miss = (reason) => ({ state: 'unavailable', reason });
|
|
138
|
+
// Validates the search path once and tries each directory in order; `probe` decides what a hit is.
|
|
139
|
+
async function searchExecutable(name, env, probe, found) {
|
|
140
|
+
const selected = searchPath(env);
|
|
141
|
+
if (selected.kind === 'unreadable')
|
|
142
|
+
return miss('Executable search path is not readable');
|
|
143
|
+
const pathValue = selected.path;
|
|
144
|
+
if (typeof pathValue !== 'string' || pathValue.length === 0 || pathValue.includes('\0') || Buffer.byteLength(pathValue) > 65_536) {
|
|
145
|
+
return miss('Executable search path is missing or invalid');
|
|
146
|
+
}
|
|
147
|
+
const directories = pathValue.split(delimiter);
|
|
148
|
+
if (directories.length > PATH_ENTRY_LIMIT || directories.some(path => !isAbsolute(path) || normalize(path) !== path)) {
|
|
149
|
+
return miss('Executable search path must contain bounded absolute directories');
|
|
150
|
+
}
|
|
151
|
+
for (const directory of directories) {
|
|
152
|
+
const result = await probe(join(directory, name));
|
|
153
|
+
if (found(result))
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
return miss(`Executable was not found in the supplied search path: ${name}`);
|
|
157
|
+
}
|
|
158
|
+
export async function resolveExecutable(name, env) {
|
|
159
|
+
if (typeof name !== 'string' || name.length === 0 || name.includes('\0'))
|
|
160
|
+
return unavailable('Executable name is invalid');
|
|
161
|
+
if (isAbsolute(name))
|
|
162
|
+
return resolveExecutablePath(name);
|
|
163
|
+
if (basename(name) !== name)
|
|
164
|
+
return unavailable('Executable name must be absolute or a PATH entry name');
|
|
165
|
+
return searchExecutable(name, env, resolveExecutablePath, result => result.state === 'available');
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Whether a command can be started from `cwd`, found the way a wrapper that changes into `cwd` would
|
|
169
|
+
* find it, without hashing the file: a command with a slash is relative to `cwd`, a bare name is
|
|
170
|
+
* looked up on PATH. For callers that report presence rather than run the file.
|
|
171
|
+
*/
|
|
172
|
+
export async function locateExecutable(command, env, cwd) {
|
|
173
|
+
if (typeof command !== 'string' || command.length === 0 || command.includes('\0'))
|
|
174
|
+
return miss('Executable name is invalid');
|
|
175
|
+
if (command.includes('/'))
|
|
176
|
+
return checkExecutablePath(resolve(cwd, command));
|
|
177
|
+
return searchExecutable(command, env, checkExecutablePath, result => result.state === 'present');
|
|
178
|
+
}
|
|
179
|
+
export async function resolveGitExecutable(env) {
|
|
180
|
+
return resolveExecutable('git', env);
|
|
181
|
+
}
|
|
182
|
+
export async function resolveDiskCapacityExecutable() {
|
|
183
|
+
return resolveExecutablePath(process.execPath);
|
|
184
|
+
}
|
|
185
|
+
export async function resolveDockerExecutable(env) {
|
|
186
|
+
return resolveExecutable('docker', env);
|
|
187
|
+
}
|
|
188
|
+
export async function resolvePathRemovalExecutable() {
|
|
189
|
+
return resolveExecutablePath('/bin/rm');
|
|
190
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type ConsumedWorkApplicationAuthorities, type GeneratedApplicationProjection, type GeneratedEnvironmentCommandInput, type RefusalOutcome, type WorkApplicationAuthoritiesProjection } from './shared.js';
|
|
2
|
+
export declare function generatedApplicationProjection(value: unknown): GeneratedApplicationProjection | undefined;
|
|
3
|
+
export declare function projectWorkApplicationAuthorities(application: GeneratedApplicationProjection): WorkApplicationAuthoritiesProjection | undefined;
|
|
4
|
+
export declare function consumeWorkApplicationAuthorities(projection: WorkApplicationAuthoritiesProjection): ConsumedWorkApplicationAuthorities | undefined;
|
|
5
|
+
export declare function prepareWorkApplicationAuthorities(input: GeneratedEnvironmentCommandInput): Promise<WorkApplicationAuthoritiesProjection | RefusalOutcome>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { consumeWorkEnvironmentConfigProjection, loadCockpitConfig, projectWorkEnvironmentConfig } from '../../config/load.js';
|
|
3
|
+
import { CORE_EVALUATOR_ASSET as EVALUATOR_ASSET } from '../../surfaces/core-declarations.js';
|
|
4
|
+
import { nodeAuthority, readAnchoredFile } from '../../generated-environment/transaction.js';
|
|
5
|
+
import { TESTING_GUIDE_REGISTRY, createGateRegistry } from '../../testing/gates.js';
|
|
6
|
+
import { refusalOutcome as refuse } from '../../refusal.js';
|
|
7
|
+
import { MAX_SURFACE_FILE_BYTES, SURFACE_ROOT, defaultAdapters, issuedApplicationProjections, issuedWorkApplicationAuthorities, projectedWorkApplicationAuthorities, readSurfaceAsset, sha256, } from './shared.js';
|
|
8
|
+
import { commandInput } from './prepare.js';
|
|
9
|
+
export function generatedApplicationProjection(value) {
|
|
10
|
+
return value !== null && typeof value === 'object' && issuedApplicationProjections.has(value)
|
|
11
|
+
? value : undefined;
|
|
12
|
+
}
|
|
13
|
+
export function projectWorkApplicationAuthorities(application) {
|
|
14
|
+
if (application === null || typeof application !== 'object' || projectedWorkApplicationAuthorities.has(application))
|
|
15
|
+
return undefined;
|
|
16
|
+
const record = issuedApplicationProjections.get(application);
|
|
17
|
+
if (!record?.workApplication)
|
|
18
|
+
return undefined;
|
|
19
|
+
const projection = { kind: 'work-application-authorities' };
|
|
20
|
+
projectedWorkApplicationAuthorities.add(application);
|
|
21
|
+
issuedWorkApplicationAuthorities.set(projection, record.workApplication);
|
|
22
|
+
return projection;
|
|
23
|
+
}
|
|
24
|
+
export function consumeWorkApplicationAuthorities(projection) {
|
|
25
|
+
if (projection === null || typeof projection !== 'object')
|
|
26
|
+
return undefined;
|
|
27
|
+
const record = issuedWorkApplicationAuthorities.get(projection);
|
|
28
|
+
if (!record)
|
|
29
|
+
return undefined;
|
|
30
|
+
issuedWorkApplicationAuthorities.delete(projection);
|
|
31
|
+
return record;
|
|
32
|
+
}
|
|
33
|
+
export async function prepareWorkApplicationAuthorities(input) {
|
|
34
|
+
const request = commandInput(input);
|
|
35
|
+
if (!request)
|
|
36
|
+
return refuse('GENERATED_INPUT_INVALID', 'work application input is invalid', 'work');
|
|
37
|
+
const loaded = await loadCockpitConfig(request.configPath);
|
|
38
|
+
if (loaded.kind !== 'complete')
|
|
39
|
+
return {
|
|
40
|
+
kind: 'refusal', artifact: null, destination: null, result: null, status: 2,
|
|
41
|
+
diagnostics: [...loaded.diagnostics],
|
|
42
|
+
};
|
|
43
|
+
const configProjection = projectWorkEnvironmentConfig(loaded.result);
|
|
44
|
+
const workEnvironment = configProjection && consumeWorkEnvironmentConfigProjection(configProjection);
|
|
45
|
+
const node = await nodeAuthority();
|
|
46
|
+
if (!workEnvironment || !node)
|
|
47
|
+
return refuse('GENERATED_RENDER_UNAUTHENTICATED', 'work configuration or Node authority is unavailable', request.configPath);
|
|
48
|
+
const read = await readAnchoredFile(SURFACE_ROOT, EVALUATOR_ASSET, MAX_SURFACE_FILE_BYTES, node, defaultAdapters);
|
|
49
|
+
const evaluator = readSurfaceAsset(EVALUATOR_ASSET, read);
|
|
50
|
+
if (!evaluator)
|
|
51
|
+
return refuse('SURFACE_INPUT_INVALID', 'the shipped evaluator could not be authenticated', EVALUATOR_ASSET);
|
|
52
|
+
const projection = { kind: 'work-application-authorities' };
|
|
53
|
+
issuedWorkApplicationAuthorities.set(projection, Object.freeze({
|
|
54
|
+
workEnvironment,
|
|
55
|
+
evaluator: Object.freeze({ path: resolve(SURFACE_ROOT, evaluator.path), bytes: evaluator.bytes,
|
|
56
|
+
sha256: evaluator.sha256, identity: evaluator.identity, restriction: 'instructed' }),
|
|
57
|
+
installedSkills: Object.freeze([]),
|
|
58
|
+
testing: Object.freeze({ registry: workEnvironment.testing ? createGateRegistry(workEnvironment.testing.declarations) : TESTING_GUIDE_REGISTRY }),
|
|
59
|
+
}));
|
|
60
|
+
return projection;
|
|
61
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type SurfaceTarget } from '../../surfaces/contract.js';
|
|
2
|
+
import type { SurfacePriorOwnedEntry } from '../../surfaces/ownership.js';
|
|
3
|
+
import type { ResolvedExecutable } from '../executable.js';
|
|
4
|
+
import { type GeneratedEnvironmentCommandAdapters, type GeneratedEnvironmentSyncInput, type SelectedBootstrapPublicationAuthority, type SelectedBootstrapResumeInput, type SelectedBootstrapResumeOutcome, type SelectedBootstrapSurfaceInput, type SelectedBootstrapSurfaceOutcome } from './shared.js';
|
|
5
|
+
export declare function prepareSelectedBootstrapSurface(input: SelectedBootstrapSurfaceInput, adapterOverrides?: Partial<GeneratedEnvironmentCommandAdapters>): Promise<SelectedBootstrapSurfaceOutcome>;
|
|
6
|
+
export declare function applySelectedBootstrapSurface(authority: SelectedBootstrapPublicationAuthority): Promise<SelectedBootstrapSurfaceOutcome>;
|
|
7
|
+
export declare function resumeSelectedBootstrapSurface(input: SelectedBootstrapResumeInput, adapterOverrides?: Partial<GeneratedEnvironmentCommandAdapters>): Promise<SelectedBootstrapResumeOutcome>;
|
|
8
|
+
export declare function authenticatedBootstrapPriorSurfaces(root: string, state: NonNullable<GeneratedEnvironmentSyncInput['bootstrapState']>, node: ResolvedExecutable, adapters: GeneratedEnvironmentCommandAdapters): Promise<readonly SurfacePriorOwnedEntry[] | undefined>;
|
|
9
|
+
export declare function unfinishedInitSurfaces(root: string, node: ResolvedExecutable, adapters: GeneratedEnvironmentCommandAdapters): Promise<UnfinishedInit | undefined>;
|
|
10
|
+
export interface UnfinishedInit {
|
|
11
|
+
readonly root: string;
|
|
12
|
+
readonly target: SurfaceTarget;
|
|
13
|
+
readonly published: readonly string[];
|
|
14
|
+
/** Absent when the files no longer hold what init recorded, so sync cannot take them over. */
|
|
15
|
+
readonly surfaces: readonly SurfacePriorOwnedEntry[] | undefined;
|
|
16
|
+
}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import { lstat, realpath } from 'node:fs/promises';
|
|
2
|
+
import { isAbsolute, join, resolve } from 'node:path';
|
|
3
|
+
import { SURFACE_TARGETS } from '../../surfaces/contract.js';
|
|
4
|
+
import { CORE_PROCEDURE_ASSETS as PROCEDURE_ASSETS, CORE_SKILL_ASSETS as SKILL_ASSETS, shippedSkillSources, } from '../../surfaces/core-declarations.js';
|
|
5
|
+
import { SHIPPED_SETUP_SKILL, inspectSkillSet, projectInspectedSkillOutputs } from '../../surfaces/skill-contract.js';
|
|
6
|
+
import { nodeAuthority, readAnchoredEntry, readAnchoredBatches, expectedState, admitPublicationPlan, runPublicationPlan, } from '../../generated-environment/transaction.js';
|
|
7
|
+
import { errorCause, RefusalError } from '../contract.js';
|
|
8
|
+
import { authenticateStatePublication, readState, selectBootstrapStateRoot } from '../state.js';
|
|
9
|
+
import { exactKeys } from '../../exact-keys.js';
|
|
10
|
+
import { refusalOutcome as refuse } from '../../refusal.js';
|
|
11
|
+
import { MAX_OWNERSHIP_BYTES, MAX_SURFACE_FILE_BYTES, OWNERSHIP_PATH, SURFACE_ROOT, consumedBootstrapStatePublications, issuedSelectedBootstrapAuthorities, mergedAdapters, ownRecord, readSurfaceAsset, sha256, sourceIdentity, } from './shared.js';
|
|
12
|
+
import { prepare, readOwnership } from './prepare.js';
|
|
13
|
+
function selectedBootstrapInput(input) {
|
|
14
|
+
const record = ownRecord(input);
|
|
15
|
+
if (!record || !exactKeys(record, ['root', 'target', 'tools']) || typeof record.root !== 'string'
|
|
16
|
+
|| !isAbsolute(record.root) || resolve(record.root) !== record.root
|
|
17
|
+
|| !SURFACE_TARGETS.includes(record.target)
|
|
18
|
+
|| !Array.isArray(record.tools) || record.tools[0] !== record.target
|
|
19
|
+
|| new Set(record.tools).size !== record.tools.length
|
|
20
|
+
|| record.tools.some(tool => !SURFACE_TARGETS.includes(tool)))
|
|
21
|
+
return undefined;
|
|
22
|
+
return { root: record.root, target: record.target, tools: [...record.tools] };
|
|
23
|
+
}
|
|
24
|
+
/** The shipped skill sources with the packaged collection and procedures that authenticate them. */
|
|
25
|
+
function bootstrapSkillInput(assets, tools) {
|
|
26
|
+
const skills = shippedSkillSources(assets, tools);
|
|
27
|
+
const collection = assets.get('skills/collection.json');
|
|
28
|
+
const procedures = PROCEDURE_ASSETS.map(path => assets.get(path));
|
|
29
|
+
if (!skills || !collection || procedures.some(row => row === undefined))
|
|
30
|
+
return undefined;
|
|
31
|
+
const pick = ({ path, bytes, sha256: digest }) => ({ path, bytes, sha256: digest });
|
|
32
|
+
return { sources: skills.flatMap(skill => skill.sources), collection: pick(collection),
|
|
33
|
+
procedures: procedures.map(pick), tools };
|
|
34
|
+
}
|
|
35
|
+
async function selectedBootstrapAssets(node, adapters) {
|
|
36
|
+
const reads = await readAnchoredBatches(SURFACE_ROOT, SKILL_ASSETS.map(path => ({
|
|
37
|
+
path, maxBytes: MAX_SURFACE_FILE_BYTES, action: 'read-file',
|
|
38
|
+
})), node, adapters);
|
|
39
|
+
if (!reads || reads.kind !== 'complete' || reads.results.length !== SKILL_ASSETS.length)
|
|
40
|
+
return undefined;
|
|
41
|
+
const assets = SKILL_ASSETS.map((path, index) => readSurfaceAsset(path, reads.results[index]));
|
|
42
|
+
return assets.every((asset) => asset !== undefined) ? assets : undefined;
|
|
43
|
+
}
|
|
44
|
+
async function selectedBootstrapRecordCurrent(record) {
|
|
45
|
+
try {
|
|
46
|
+
const root = await lstat(record.root);
|
|
47
|
+
if (!root.isDirectory() || root.isSymbolicLink() || root.dev !== record.rootIdentity.dev || root.ino !== record.rootIdentity.ino)
|
|
48
|
+
return false;
|
|
49
|
+
const reads = await readAnchoredBatches(SURFACE_ROOT, record.assets.map(asset => ({
|
|
50
|
+
path: asset.path, maxBytes: MAX_SURFACE_FILE_BYTES, action: 'read-file',
|
|
51
|
+
})), record.node, record.adapters);
|
|
52
|
+
const state = record.bootstrapState && await readState(record.bootstrapState.address);
|
|
53
|
+
return (!record.bootstrapState || state?.kind === 'complete'
|
|
54
|
+
&& JSON.stringify(state.value) === JSON.stringify(record.bootstrapState.record))
|
|
55
|
+
&& !!reads && reads.kind === 'complete' && reads.results.length === record.assets.length
|
|
56
|
+
&& reads.results.every((read, index) => read.kind === 'complete' && read.sha256 === record.assets[index].sha256
|
|
57
|
+
&& sourceIdentity(read.identity) === sourceIdentity(record.assets[index].identity));
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// a failed re-observation means the inputs are no longer authenticated; the caller refuses.
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export async function prepareSelectedBootstrapSurface(input, adapterOverrides = {}) {
|
|
65
|
+
const captured = selectedBootstrapInput(input);
|
|
66
|
+
if (!captured)
|
|
67
|
+
return refuse('GENERATED_INPUT_INVALID', 'selected bootstrap input is invalid', 'bootstrap');
|
|
68
|
+
const adapters = mergedAdapters(adapterOverrides);
|
|
69
|
+
let root;
|
|
70
|
+
let rootIdentity;
|
|
71
|
+
try {
|
|
72
|
+
root = await realpath(captured.root);
|
|
73
|
+
const status = await lstat(root);
|
|
74
|
+
if (root !== captured.root || !status.isDirectory() || status.isSymbolicLink())
|
|
75
|
+
throw new RefusalError('root');
|
|
76
|
+
rootIdentity = { dev: status.dev, ino: status.ino };
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
return refuse('GENERATED_INPUT_INVALID', `selected bootstrap root is not a canonical directory: ${errorCause(error)}`, captured.root);
|
|
80
|
+
}
|
|
81
|
+
const node = await nodeAuthority();
|
|
82
|
+
const assets = node && await selectedBootstrapAssets(node, adapters);
|
|
83
|
+
if (!node || !assets)
|
|
84
|
+
return refuse('SURFACE_INPUT_INVALID', 'packaged bootstrap assets could not be authenticated', 'bootstrap');
|
|
85
|
+
const skillInput = bootstrapSkillInput(new Map(assets.map(asset => [asset.path, asset])), captured.tools);
|
|
86
|
+
if (!skillInput)
|
|
87
|
+
return refuse('SURFACE_INPUT_INVALID', 'packaged bootstrap assets are incomplete', 'bootstrap');
|
|
88
|
+
const { sources } = skillInput;
|
|
89
|
+
const inspection = await inspectSkillSet(skillInput);
|
|
90
|
+
if (inspection.kind !== 'complete')
|
|
91
|
+
return refuse('SURFACE_INPUT_INVALID', 'packaged bootstrap skill set was refused', 'bootstrap');
|
|
92
|
+
const inspected = projectInspectedSkillOutputs(inspection, captured.tools, SHIPPED_SETUP_SKILL);
|
|
93
|
+
if (inspected.kind !== 'complete')
|
|
94
|
+
return refuse('SURFACE_INPUT_INVALID', 'selected bootstrap output set was refused', captured.target);
|
|
95
|
+
const reads = await readAnchoredBatches(root, inspected.files.map(file => ({
|
|
96
|
+
path: file.path, maxBytes: MAX_SURFACE_FILE_BYTES, action: 'read-entry',
|
|
97
|
+
})), node, adapters);
|
|
98
|
+
if (!reads || reads.kind !== 'complete' || reads.results.length !== inspected.files.length) {
|
|
99
|
+
return refuse('SURFACE_STATE_CONFLICT', 'selected bootstrap destinations could not be authenticated', captured.target);
|
|
100
|
+
}
|
|
101
|
+
const mutations = [];
|
|
102
|
+
for (const [index, file] of inspected.files.entries()) {
|
|
103
|
+
const current = reads.results[index];
|
|
104
|
+
if (current.kind !== 'missing' && current.kind !== 'file')
|
|
105
|
+
return refuse('SURFACE_STATE_CONFLICT', 'selected bootstrap destination is not a regular file or missing', file.path);
|
|
106
|
+
if (current.kind === 'file' && current.sha256 !== file.sha256)
|
|
107
|
+
return refuse('SURFACE_STATE_CONFLICT', 'selected bootstrap destination contains unmanaged bytes', file.path);
|
|
108
|
+
if (current.kind === 'missing')
|
|
109
|
+
mutations.push({ path: file.path, phase: 'desired', operation: 'write-file',
|
|
110
|
+
bytes: file.bytes, sha256: file.sha256, expected: { kind: 'missing' } });
|
|
111
|
+
}
|
|
112
|
+
const admitted = await admitPublicationPlan({ mode: 'bootstrap', root, rootIdentity, node, inspected,
|
|
113
|
+
mutations }, adapters);
|
|
114
|
+
if (admitted.kind !== 'complete')
|
|
115
|
+
return admitted;
|
|
116
|
+
const sourceRows = sources.map(source => ({ path: source.path, sha256: sha256(source.bytes) }));
|
|
117
|
+
const files = inspected.files.map(file => ({ path: file.path, sha256: file.sha256 }));
|
|
118
|
+
const previewSha256 = sha256(JSON.stringify({ target: captured.target, sources: sourceRows, files }));
|
|
119
|
+
const result = { root, target: captured.target, sources: sourceRows, files,
|
|
120
|
+
previewSha256, changes: admitted.plan.changes };
|
|
121
|
+
const authority = { kind: 'selected-bootstrap-publication-authority' };
|
|
122
|
+
issuedSelectedBootstrapAuthorities.set(authority, Object.freeze({ root, rootIdentity, target: captured.target, node,
|
|
123
|
+
assets: Object.freeze(assets.map(({ path, sha256: digest, identity }) => ({ path, sha256: digest, identity }))),
|
|
124
|
+
inspected, result, plan: admitted.plan, adapters }));
|
|
125
|
+
return { kind: 'complete', artifact: null, destination: null, diagnostics: [], result, authority, status: 0 };
|
|
126
|
+
}
|
|
127
|
+
export async function applySelectedBootstrapSurface(authority) {
|
|
128
|
+
const record = authority !== null && typeof authority === 'object' ? issuedSelectedBootstrapAuthorities.get(authority) : undefined;
|
|
129
|
+
if (!record)
|
|
130
|
+
return refuse('GENERATED_PUBLICATION_FAILED', 'selected bootstrap publication authority is unknown or already consumed', 'bootstrap');
|
|
131
|
+
issuedSelectedBootstrapAuthorities.delete(authority);
|
|
132
|
+
const outcome = await runPublicationPlan(record.plan, { execute: record.adapters.execute,
|
|
133
|
+
revalidate: async () => selectedBootstrapRecordCurrent(record) });
|
|
134
|
+
if (outcome.kind !== 'complete')
|
|
135
|
+
return outcome;
|
|
136
|
+
return { kind: 'complete', artifact: null, destination: null, diagnostics: [],
|
|
137
|
+
result: record.result, authority, status: 0 };
|
|
138
|
+
}
|
|
139
|
+
export async function resumeSelectedBootstrapSurface(input, adapterOverrides = {}) {
|
|
140
|
+
const captured = selectedBootstrapInput({ root: input.root, target: input.target, tools: input.tools });
|
|
141
|
+
const durable = await readState(input.address);
|
|
142
|
+
if (!captured || durable.kind !== 'complete' || durable.value.kind !== 'bootstrap'
|
|
143
|
+
|| durable.value.value.checkoutRoot !== captured.root || durable.value.target !== captured.target
|
|
144
|
+
|| input.address.checkoutRoot !== captured.root || input.address.target !== captured.target
|
|
145
|
+
|| durable.value.value.stage === 'surface-previewed')
|
|
146
|
+
return refuse('GENERATED_OWNERSHIP_INVALID', 'bootstrap resume requires the current durable state, root and target', 'bootstrap');
|
|
147
|
+
const adapters = mergedAdapters(adapterOverrides);
|
|
148
|
+
let rootIdentity;
|
|
149
|
+
try {
|
|
150
|
+
const status = await lstat(captured.root);
|
|
151
|
+
if (!status.isDirectory() || status.isSymbolicLink() || await realpath(captured.root) !== captured.root)
|
|
152
|
+
throw new RefusalError('root');
|
|
153
|
+
rootIdentity = { dev: status.dev, ino: status.ino };
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
return refuse('GENERATED_INPUT_INVALID', `selected bootstrap root is not a canonical directory: ${errorCause(error)}`, captured.root);
|
|
157
|
+
}
|
|
158
|
+
const node = await nodeAuthority();
|
|
159
|
+
if (!node)
|
|
160
|
+
return refuse('SURFACE_INPUT_INVALID', 'bootstrap resume could not authenticate the node executable', 'bootstrap');
|
|
161
|
+
const ownership = await readAnchoredEntry(captured.root, OWNERSHIP_PATH, MAX_OWNERSHIP_BYTES, node, adapters);
|
|
162
|
+
if (ownership.kind !== 'missing' && ownership.kind !== 'file')
|
|
163
|
+
return refuse('GENERATED_OWNERSHIP_INVALID', 'bootstrap resume ownership could not be read safely', OWNERSHIP_PATH);
|
|
164
|
+
const assets = await selectedBootstrapAssets(node, adapters);
|
|
165
|
+
if (!assets)
|
|
166
|
+
return refuse('SURFACE_INPUT_INVALID', 'bootstrap resume packaged assets could not be authenticated', 'bootstrap');
|
|
167
|
+
const skillInput = bootstrapSkillInput(new Map(assets.map(asset => [asset.path, asset])), captured.tools);
|
|
168
|
+
if (!skillInput)
|
|
169
|
+
return refuse('SURFACE_INPUT_INVALID', 'bootstrap resume packaged assets are incomplete', 'bootstrap');
|
|
170
|
+
const { sources } = skillInput;
|
|
171
|
+
const inspection = await inspectSkillSet(skillInput);
|
|
172
|
+
if (inspection.kind !== 'complete')
|
|
173
|
+
return refuse('SURFACE_INPUT_INVALID', 'bootstrap resume skill set was refused', 'bootstrap');
|
|
174
|
+
const inspected = projectInspectedSkillOutputs(inspection, captured.tools, SHIPPED_SETUP_SKILL);
|
|
175
|
+
if (inspected.kind !== 'complete')
|
|
176
|
+
return refuse('SURFACE_INPUT_INVALID', 'bootstrap resume output projection was refused', captured.target);
|
|
177
|
+
const sourceRows = sources.map(source => ({ path: source.path, sha256: sha256(source.bytes) }));
|
|
178
|
+
const files = inspected.files.map(file => ({ path: file.path, sha256: file.sha256 }));
|
|
179
|
+
const previewSha256 = sha256(JSON.stringify({ target: captured.target, sources: sourceRows, files }));
|
|
180
|
+
const state = durable.value.value;
|
|
181
|
+
const sourcesCurrent = JSON.stringify(state.sources) === JSON.stringify(sourceRows)
|
|
182
|
+
&& JSON.stringify(state.published) === JSON.stringify(files) && state.previewSha256 === previewSha256;
|
|
183
|
+
if (ownership.kind === 'missing') {
|
|
184
|
+
if (sourcesCurrent)
|
|
185
|
+
return { kind: 'pending', status: 0, diagnostics: [],
|
|
186
|
+
result: null, canonicalOwnership: false };
|
|
187
|
+
const priorPreviewSha256 = sha256(JSON.stringify({ target: captured.target, sources: state.sources, files: state.published }));
|
|
188
|
+
if (input.expectedRevision !== durable.value.revision || input.expectedCommandSha256 !== state.commandSha256
|
|
189
|
+
|| priorPreviewSha256 !== state.previewSha256 || state.stage !== 'surface-published'
|
|
190
|
+
|| JSON.stringify(state.published.map(row => row.path)) !== JSON.stringify(files.map(row => row.path)))
|
|
191
|
+
return refuse('GENERATED_SOURCE_CHANGED', 'bootstrap resume package sources differ from the accepted durable preview', 'bootstrap');
|
|
192
|
+
const reads = await readAnchoredBatches(captured.root, inspected.files.map(file => ({
|
|
193
|
+
path: file.path, maxBytes: MAX_SURFACE_FILE_BYTES, action: 'read-entry',
|
|
194
|
+
})), node, adapters);
|
|
195
|
+
if (!reads || reads.kind !== 'complete' || reads.results.length !== inspected.files.length)
|
|
196
|
+
return refuse('SURFACE_STATE_CONFLICT', 'bootstrap refresh destinations could not be authenticated', captured.target);
|
|
197
|
+
const mutations = [];
|
|
198
|
+
for (const [index, file] of inspected.files.entries()) {
|
|
199
|
+
const current = reads.results[index];
|
|
200
|
+
const prior = state.published[index];
|
|
201
|
+
if (current.kind !== 'file' || current.sha256 !== prior.sha256 && current.sha256 !== file.sha256)
|
|
202
|
+
return refuse('SURFACE_STATE_CONFLICT', 'bootstrap refresh destination differs from its authenticated publication', file.path);
|
|
203
|
+
if (current.sha256 === file.sha256)
|
|
204
|
+
continue;
|
|
205
|
+
const expected = expectedState(current);
|
|
206
|
+
if (!expected)
|
|
207
|
+
return refuse('SURFACE_STATE_CONFLICT', 'bootstrap refresh destination could not be authenticated', file.path);
|
|
208
|
+
mutations.push({ path: file.path, phase: 'desired', operation: 'write-file',
|
|
209
|
+
bytes: file.bytes, sha256: file.sha256, expected });
|
|
210
|
+
}
|
|
211
|
+
const admitted = await admitPublicationPlan({ mode: 'bootstrap', root: captured.root, rootIdentity, node, inspected,
|
|
212
|
+
mutations, refresh: { address: input.address,
|
|
213
|
+
revision: durable.value.revision, commandSha256: state.commandSha256 } }, adapters);
|
|
214
|
+
if (admitted.kind !== 'complete')
|
|
215
|
+
return admitted;
|
|
216
|
+
const result = { root: captured.root, target: captured.target,
|
|
217
|
+
sources: sourceRows, files, previewSha256, changes: admitted.plan.changes };
|
|
218
|
+
const authority = { kind: 'selected-bootstrap-publication-authority' };
|
|
219
|
+
issuedSelectedBootstrapAuthorities.set(authority, Object.freeze({ root: captured.root, rootIdentity,
|
|
220
|
+
target: captured.target, node,
|
|
221
|
+
assets: Object.freeze(assets.map(({ path, sha256: digest, identity }) => ({ path, sha256: digest, identity }))),
|
|
222
|
+
inspected, result, plan: admitted.plan, adapters,
|
|
223
|
+
bootstrapState: Object.freeze({ address: input.address, record: durable.value }),
|
|
224
|
+
}));
|
|
225
|
+
return { kind: 'refresh', status: 0, diagnostics: [], result, authority,
|
|
226
|
+
canonicalOwnership: false };
|
|
227
|
+
}
|
|
228
|
+
if (ownership.kind !== 'file')
|
|
229
|
+
return refuse('GENERATED_OWNERSHIP_INVALID', 'bootstrap resume ownership changed after classification', OWNERSHIP_PATH);
|
|
230
|
+
if (!sourcesCurrent)
|
|
231
|
+
return refuse('GENERATED_SOURCE_CHANGED', 'bootstrap resume package sources differ from the accepted durable preview', 'bootstrap');
|
|
232
|
+
const base = await prepare({ configPath: join(captured.root, 'cockpit.toml') }, adapters);
|
|
233
|
+
if ('status' in base)
|
|
234
|
+
return base;
|
|
235
|
+
const canonical = await readOwnership(base, adapters);
|
|
236
|
+
if (base.root !== captured.root || canonical.kind !== 'complete'
|
|
237
|
+
|| canonical.manifest.format !== 'cockpit-generated-ownership/v3' || canonical.sha256 !== ownership.sha256)
|
|
238
|
+
return refuse('GENERATED_OWNERSHIP_INVALID', 'bootstrap resume requires canonical ownership bound to the current checkout and configuration', OWNERSHIP_PATH);
|
|
239
|
+
const current = await readAnchoredEntry(captured.root, OWNERSHIP_PATH, MAX_OWNERSHIP_BYTES, node, adapters);
|
|
240
|
+
const refreshed = await readState(input.address);
|
|
241
|
+
if (current.kind !== 'file' || current.sha256 !== ownership.sha256
|
|
242
|
+
|| sourceIdentity(current.identity) !== sourceIdentity(ownership.identity)
|
|
243
|
+
|| refreshed.kind !== 'complete' || JSON.stringify(refreshed.value) !== JSON.stringify(durable.value))
|
|
244
|
+
return refuse('GENERATED_SOURCE_CHANGED', 'bootstrap resume ownership or state changed during checking', 'bootstrap');
|
|
245
|
+
return { kind: 'complete', status: 0, diagnostics: [], canonicalOwnership: true,
|
|
246
|
+
result: { root: captured.root, target: captured.target, sources: sourceRows, files, previewSha256,
|
|
247
|
+
changes: [] } };
|
|
248
|
+
}
|
|
249
|
+
export async function authenticatedBootstrapPriorSurfaces(root, state, node, adapters) {
|
|
250
|
+
const publication = state.publication;
|
|
251
|
+
if (publication === null || typeof publication !== 'object' || consumedBootstrapStatePublications.has(publication))
|
|
252
|
+
return undefined;
|
|
253
|
+
const authenticated = authenticateStatePublication(state);
|
|
254
|
+
if (!authenticated || authenticated.status !== 'complete' || authenticated.record.kind !== 'bootstrap')
|
|
255
|
+
return undefined;
|
|
256
|
+
const record = authenticated.record;
|
|
257
|
+
if (record.target !== state.address.target || state.address.checkoutRoot !== root)
|
|
258
|
+
return undefined;
|
|
259
|
+
const surfaces = await bootstrapPublishedSurfaces(root, record, node, adapters);
|
|
260
|
+
if (surfaces)
|
|
261
|
+
consumedBootstrapStatePublications.add(publication);
|
|
262
|
+
return surfaces;
|
|
263
|
+
}
|
|
264
|
+
// A plain sync between an interrupted init and its rerun met init's own setup skill files with no
|
|
265
|
+
// ownership record and refused them, and its remedy had an agent delete them. The bootstrap record
|
|
266
|
+
// sync reads here comes from this user's private state root, scoped to this cockpit root, and the
|
|
267
|
+
// files must still hold exactly the bytes init published from the installed package.
|
|
268
|
+
export async function unfinishedInitSurfaces(root, node, adapters) {
|
|
269
|
+
if (process.platform !== 'darwin' && process.platform !== 'linux')
|
|
270
|
+
return undefined;
|
|
271
|
+
for (const target of SURFACE_TARGETS) {
|
|
272
|
+
const namespace = await selectBootstrapStateRoot({ platform: process.platform, home: process.env.HOME,
|
|
273
|
+
xdgStateHome: process.env.XDG_STATE_HOME, checkoutRoot: root, target });
|
|
274
|
+
if (namespace.kind !== 'complete')
|
|
275
|
+
return undefined;
|
|
276
|
+
const read = await readState(namespace.value.paths.bootstrap(target));
|
|
277
|
+
if (read.kind === 'complete')
|
|
278
|
+
return { root, target, published: read.value.value.published.map(row => row.path),
|
|
279
|
+
surfaces: await bootstrapPublishedSurfaces(root, read.value, node, adapters) };
|
|
280
|
+
}
|
|
281
|
+
return undefined;
|
|
282
|
+
}
|
|
283
|
+
async function bootstrapPublishedSurfaces(root, record, node, adapters) {
|
|
284
|
+
if (record.kind !== 'bootstrap' || record.value.stage === 'surface-previewed' || record.value.checkoutRoot !== root
|
|
285
|
+
|| record.value.target !== record.target)
|
|
286
|
+
return undefined;
|
|
287
|
+
const assets = await selectedBootstrapAssets(node, adapters);
|
|
288
|
+
if (!assets)
|
|
289
|
+
return undefined;
|
|
290
|
+
// The record names no tools, so they are the targets whose setup skill it published, in published order.
|
|
291
|
+
const allTools = bootstrapSkillInput(new Map(assets.map(asset => [asset.path, asset])), SURFACE_TARGETS);
|
|
292
|
+
const allInspection = allTools && await inspectSkillSet(allTools);
|
|
293
|
+
const allProjection = allInspection?.kind === 'complete'
|
|
294
|
+
? projectInspectedSkillOutputs(allInspection, SURFACE_TARGETS, SHIPPED_SETUP_SKILL) : undefined;
|
|
295
|
+
if (allProjection?.kind !== 'complete')
|
|
296
|
+
return undefined;
|
|
297
|
+
const targetByPath = new Map(allProjection.files.map(file => [file.path, file.target]));
|
|
298
|
+
const tools = [...new Set(record.value.published.map(row => targetByPath.get(row.path)))];
|
|
299
|
+
if (tools.some(tool => tool === undefined))
|
|
300
|
+
return undefined;
|
|
301
|
+
const skillInput = bootstrapSkillInput(new Map(assets.map(asset => [asset.path, asset])), tools);
|
|
302
|
+
if (!skillInput)
|
|
303
|
+
return undefined;
|
|
304
|
+
const sourceRows = skillInput.sources.map(source => ({ path: source.path, sha256: sha256(source.bytes) }));
|
|
305
|
+
if (JSON.stringify(sourceRows) !== JSON.stringify(record.value.sources))
|
|
306
|
+
return undefined;
|
|
307
|
+
const inspection = await inspectSkillSet(skillInput);
|
|
308
|
+
if (inspection.kind !== 'complete')
|
|
309
|
+
return undefined;
|
|
310
|
+
const inspected = projectInspectedSkillOutputs(inspection, tools, SHIPPED_SETUP_SKILL);
|
|
311
|
+
if (inspected.kind !== 'complete')
|
|
312
|
+
return undefined;
|
|
313
|
+
const files = inspected.files;
|
|
314
|
+
const published = files.map(file => ({ path: file.path, sha256: file.sha256 }));
|
|
315
|
+
if (JSON.stringify(published) !== JSON.stringify(record.value.published))
|
|
316
|
+
return undefined;
|
|
317
|
+
const reads = await readAnchoredBatches(root, files.map(file => ({
|
|
318
|
+
path: file.path, maxBytes: MAX_SURFACE_FILE_BYTES, action: 'read-entry',
|
|
319
|
+
})), node, adapters);
|
|
320
|
+
if (!reads || reads.kind !== 'complete' || reads.results.length !== files.length
|
|
321
|
+
|| reads.results.some((read, index) => read.kind !== 'file' || read.sha256 !== files[index].sha256))
|
|
322
|
+
return undefined;
|
|
323
|
+
return files.map(file => ({
|
|
324
|
+
kind: 'file', path: file.path, harnesses: [file.target], scope: 'always',
|
|
325
|
+
capability: 'instructed', writer: 'cockpit', schemaVersion: 1,
|
|
326
|
+
ownership: 'whole-file', sha256: file.sha256,
|
|
327
|
+
}));
|
|
328
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type PublicationPlan } from '../../generated-environment/transaction.js';
|
|
2
|
+
import { type GeneratedEnvironmentCommandAdapters, type GeneratedEnvironmentCommandInput, type GeneratedEnvironmentCommandOutcome, type GeneratedEnvironmentCurrentness, type GeneratedEnvironmentRepairAuthority, type PreparedEnvironment } from './shared.js';
|
|
3
|
+
interface RepairRecord {
|
|
4
|
+
readonly prepared: PreparedEnvironment;
|
|
5
|
+
readonly plan: PublicationPlan;
|
|
6
|
+
readonly adapters: GeneratedEnvironmentCommandAdapters;
|
|
7
|
+
}
|
|
8
|
+
export declare const issuedRepairs: WeakMap<GeneratedEnvironmentRepairAuthority, RepairRecord>;
|
|
9
|
+
export declare function issueRepairAuthority(record: RepairRecord): GeneratedEnvironmentRepairAuthority;
|
|
10
|
+
export declare function prepareGeneratedEnvironmentCurrentness(input: GeneratedEnvironmentCommandInput, adapterOverrides?: Partial<GeneratedEnvironmentCommandAdapters>): Promise<GeneratedEnvironmentCurrentness>;
|
|
11
|
+
export declare function checkCanonicalGeneratedEnvironment(input: GeneratedEnvironmentCommandInput, seed?: PreparedEnvironment, adapters?: GeneratedEnvironmentCommandAdapters): Promise<GeneratedEnvironmentCommandOutcome>;
|
|
12
|
+
export declare function checkGeneratedEnvironment(input: GeneratedEnvironmentCommandInput, adapterOverrides?: Partial<GeneratedEnvironmentCommandAdapters>): Promise<GeneratedEnvironmentCommandOutcome>;
|
|
13
|
+
export {};
|