@b00dea/cockpit 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +375 -0
- package/LICENSE +21 -0
- package/README.md +22 -2
- package/bin/cockpit.mjs +33 -0
- package/cockpit.schema.json +2574 -0
- package/dist/autonomy.d.ts +44 -0
- package/dist/autonomy.js +156 -0
- package/dist/bounded-read.d.ts +14 -0
- package/dist/bounded-read.js +42 -0
- package/dist/browser/commands.d.ts +62 -0
- package/dist/browser/commands.js +349 -0
- package/dist/browser/package-paths.d.ts +1 -0
- package/dist/browser/package-paths.js +6 -0
- package/dist/browser/proxy.d.ts +22 -0
- package/dist/browser/proxy.js +37 -0
- package/dist/browser/runtime.d.ts +117 -0
- package/dist/browser/runtime.js +183 -0
- package/dist/browser/surfaces.d.ts +141 -0
- package/dist/browser/surfaces.js +556 -0
- package/dist/browser/ui-gate.d.ts +15 -0
- package/dist/browser/ui-gate.js +18 -0
- package/dist/cli-guard.d.ts +5 -0
- package/dist/cli-guard.js +71 -0
- package/dist/cli-main.d.ts +139 -0
- package/dist/cli-main.js +1405 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +16 -0
- package/dist/command-table.d.ts +113 -0
- package/dist/command-table.js +512 -0
- package/dist/config/load.d.ts +171 -0
- package/dist/config/load.js +345 -0
- package/dist/config/sibling-toml.d.ts +48 -0
- package/dist/config/sibling-toml.js +160 -0
- package/dist/config/surface-tools-toml.d.ts +9 -0
- package/dist/config/surface-tools-toml.js +37 -0
- package/dist/config/verified-write.d.ts +43 -0
- package/dist/config/verified-write.js +89 -0
- package/dist/diagnostics.d.ts +26 -0
- package/dist/diagnostics.js +335 -0
- package/dist/emit.d.ts +22 -0
- package/dist/emit.js +43 -0
- package/dist/entrypoint-kinds.d.ts +3 -0
- package/dist/entrypoint-kinds.js +11 -0
- package/dist/environment/application/destructive.d.ts +6 -0
- package/dist/environment/application/destructive.js +425 -0
- package/dist/environment/application/doctor.d.ts +89 -0
- package/dist/environment/application/doctor.js +235 -0
- package/dist/environment/application/guard.d.ts +43 -0
- package/dist/environment/application/guard.js +622 -0
- package/dist/environment/application/health.d.ts +134 -0
- package/dist/environment/application/health.js +379 -0
- package/dist/environment/application/lifecycle-context.d.ts +228 -0
- package/dist/environment/application/lifecycle-context.js +154 -0
- package/dist/environment/application/lifecycle-state.d.ts +25 -0
- package/dist/environment/application/lifecycle-state.js +201 -0
- package/dist/environment/application/lifecycle.d.ts +17 -0
- package/dist/environment/application/lifecycle.js +729 -0
- package/dist/environment/application/logs.d.ts +45 -0
- package/dist/environment/application/logs.js +127 -0
- package/dist/environment/application/setup.d.ts +129 -0
- package/dist/environment/application/setup.js +741 -0
- package/dist/environment/application/shared.d.ts +11 -0
- package/dist/environment/application/shared.js +61 -0
- package/dist/environment/claims.d.ts +389 -0
- package/dist/environment/claims.js +1709 -0
- package/dist/environment/codex-hook-trust.d.ts +11 -0
- package/dist/environment/codex-hook-trust.js +185 -0
- package/dist/environment/compose-environment.d.ts +1 -0
- package/dist/environment/compose-environment.js +6 -0
- package/dist/environment/compose-ownership.d.ts +21 -0
- package/dist/environment/compose-ownership.js +117 -0
- package/dist/environment/compose-topology.d.ts +117 -0
- package/dist/environment/compose-topology.js +413 -0
- package/dist/environment/contract.d.ts +489 -0
- package/dist/environment/contract.js +761 -0
- package/dist/environment/declaration.d.ts +14 -0
- package/dist/environment/declaration.js +39 -0
- package/dist/environment/destructive-composition.d.ts +29 -0
- package/dist/environment/destructive-composition.js +333 -0
- package/dist/environment/docker-daemon.d.ts +30 -0
- package/dist/environment/docker-daemon.js +78 -0
- package/dist/environment/docker-endpoint.d.ts +10 -0
- package/dist/environment/docker-endpoint.js +19 -0
- package/dist/environment/env-schema-observation.d.ts +46 -0
- package/dist/environment/env-schema-observation.js +241 -0
- package/dist/environment/evidence.d.ts +136 -0
- package/dist/environment/evidence.js +437 -0
- package/dist/environment/executable.d.ts +26 -0
- package/dist/environment/executable.js +167 -0
- package/dist/environment/generated-application/authorities.d.ts +5 -0
- package/dist/environment/generated-application/authorities.js +61 -0
- package/dist/environment/generated-application/bootstrap-skill.d.ts +16 -0
- package/dist/environment/generated-application/bootstrap-skill.js +328 -0
- package/dist/environment/generated-application/check.d.ts +13 -0
- package/dist/environment/generated-application/check.js +189 -0
- package/dist/environment/generated-application/custom-surface.d.ts +26 -0
- package/dist/environment/generated-application/custom-surface.js +289 -0
- package/dist/environment/generated-application/prepare.d.ts +29 -0
- package/dist/environment/generated-application/prepare.js +276 -0
- package/dist/environment/generated-application/publication.d.ts +33 -0
- package/dist/environment/generated-application/publication.js +547 -0
- package/dist/environment/generated-application/shared.d.ts +484 -0
- package/dist/environment/generated-application/shared.js +349 -0
- package/dist/environment/generated-application/surface-observation.d.ts +4 -0
- package/dist/environment/generated-application/surface-observation.js +69 -0
- package/dist/environment/generated-application/surface-outputs.d.ts +71 -0
- package/dist/environment/generated-application/surface-outputs.js +389 -0
- package/dist/environment/generated-application/surfaces.d.ts +3 -0
- package/dist/environment/generated-application/surfaces.js +699 -0
- package/dist/environment/generated-application/sync.d.ts +6 -0
- package/dist/environment/generated-application/sync.js +109 -0
- package/dist/environment/git-observation.d.ts +183 -0
- package/dist/environment/git-observation.js +544 -0
- package/dist/environment/health-composition.d.ts +11 -0
- package/dist/environment/health-composition.js +628 -0
- package/dist/environment/host-observation.d.ts +56 -0
- package/dist/environment/host-observation.js +52 -0
- package/dist/environment/identity.d.ts +48 -0
- package/dist/environment/identity.js +85 -0
- package/dist/environment/init-application.d.ts +308 -0
- package/dist/environment/init-application.js +697 -0
- package/dist/environment/install-policy-observation.d.ts +71 -0
- package/dist/environment/install-policy-observation.js +284 -0
- package/dist/environment/install-policy.d.ts +48 -0
- package/dist/environment/install-policy.js +96 -0
- package/dist/environment/instance.d.ts +33 -0
- package/dist/environment/instance.js +122 -0
- package/dist/environment/instruction-pointer.d.ts +19 -0
- package/dist/environment/instruction-pointer.js +144 -0
- package/dist/environment/lifecycle-composition.d.ts +29 -0
- package/dist/environment/lifecycle-composition.js +675 -0
- package/dist/environment/lifecycle-stage.d.ts +115 -0
- package/dist/environment/lifecycle-stage.js +398 -0
- package/dist/environment/lifecycle.d.ts +75 -0
- package/dist/environment/lifecycle.js +354 -0
- package/dist/environment/logs.d.ts +132 -0
- package/dist/environment/logs.js +519 -0
- package/dist/environment/observations.d.ts +46 -0
- package/dist/environment/observations.js +344 -0
- package/dist/environment/operator-application.d.ts +50 -0
- package/dist/environment/operator-application.js +155 -0
- package/dist/environment/ports.d.ts +182 -0
- package/dist/environment/ports.js +1205 -0
- package/dist/environment/posture-observation.d.ts +68 -0
- package/dist/environment/posture-observation.js +253 -0
- package/dist/environment/read-composition.d.ts +27 -0
- package/dist/environment/read-composition.js +352 -0
- package/dist/environment/readiness-composition.d.ts +38 -0
- package/dist/environment/readiness-composition.js +130 -0
- package/dist/environment/reclaim.d.ts +333 -0
- package/dist/environment/reclaim.js +1835 -0
- package/dist/environment/repository-identity.d.ts +13 -0
- package/dist/environment/repository-identity.js +108 -0
- package/dist/environment/runtime-measurement-record.d.ts +38 -0
- package/dist/environment/runtime-measurement-record.js +111 -0
- package/dist/environment/runtime-measurement.d.ts +27 -0
- package/dist/environment/runtime-measurement.js +224 -0
- package/dist/environment/runtime-probe-residue.d.ts +43 -0
- package/dist/environment/runtime-probe-residue.js +148 -0
- package/dist/environment/runtime-probe.d.ts +72 -0
- package/dist/environment/runtime-probe.js +725 -0
- package/dist/environment/runtime.d.ts +505 -0
- package/dist/environment/runtime.js +2335 -0
- package/dist/environment/seed.d.ts +16 -0
- package/dist/environment/seed.js +43 -0
- package/dist/environment/selftest-application.d.ts +86 -0
- package/dist/environment/selftest-application.js +713 -0
- package/dist/environment/sensitive.d.ts +3 -0
- package/dist/environment/sensitive.js +48 -0
- package/dist/environment/setup-observation.d.ts +62 -0
- package/dist/environment/setup-observation.js +1473 -0
- package/dist/environment/setup.d.ts +43 -0
- package/dist/environment/setup.js +176 -0
- package/dist/environment/sibling-instructions.d.ts +33 -0
- package/dist/environment/sibling-instructions.js +224 -0
- package/dist/environment/sibling-registration.d.ts +45 -0
- package/dist/environment/sibling-registration.js +538 -0
- package/dist/environment/state.d.ts +371 -0
- package/dist/environment/state.js +2013 -0
- package/dist/environment/templates.d.ts +140 -0
- package/dist/environment/templates.js +685 -0
- package/dist/environment/tool-registration.d.ts +9 -0
- package/dist/environment/tool-registration.js +96 -0
- package/dist/environment/upgrade-application.d.ts +19 -0
- package/dist/environment/upgrade-application.js +175 -0
- package/dist/environment-exec/execute.d.ts +102 -0
- package/dist/environment-exec/execute.js +1175 -0
- package/dist/environment-exec/libexec-program.d.ts +6 -0
- package/dist/environment-exec/libexec-program.js +22 -0
- package/dist/environment-exec/verified-digest.d.ts +4 -0
- package/dist/environment-exec/verified-digest.js +16 -0
- package/dist/exact-keys.d.ts +7 -0
- package/dist/exact-keys.js +15 -0
- package/dist/fix-catalogue.d.ts +32 -0
- package/dist/fix-catalogue.js +60 -0
- package/dist/freshness.d.ts +29 -0
- package/dist/freshness.js +75 -0
- package/dist/generated-environment/adopt.d.ts +16 -0
- package/dist/generated-environment/adopt.js +275 -0
- package/dist/generated-environment/command.d.ts +47 -0
- package/dist/generated-environment/command.js +75 -0
- package/dist/generated-environment/transaction.d.ts +186 -0
- package/dist/generated-environment/transaction.js +1770 -0
- package/dist/grading/evaluate.d.ts +71 -0
- package/dist/grading/evaluate.js +403 -0
- package/dist/grading/grade.d.ts +33 -0
- package/dist/grading/grade.js +57 -0
- package/dist/guards/evaluator.d.ts +113 -0
- package/dist/guards/evaluator.js +1226 -0
- package/dist/guards/harness-adapter.d.ts +17 -0
- package/dist/guards/harness-adapter.js +57 -0
- package/dist/guards/host.d.ts +8 -0
- package/dist/guards/host.js +10 -0
- package/dist/guards/invocation-parser.d.ts +66 -0
- package/dist/guards/invocation-parser.js +595 -0
- package/dist/guards/local-identity.d.ts +40 -0
- package/dist/guards/local-identity.js +123 -0
- package/dist/guards/policy-pin.d.ts +13 -0
- package/dist/guards/policy-pin.js +175 -0
- package/dist/guards/protected-locations.d.ts +62 -0
- package/dist/guards/protected-locations.js +461 -0
- package/dist/guards/read-only.d.ts +37 -0
- package/dist/guards/read-only.js +315 -0
- package/dist/init/command.d.ts +40 -0
- package/dist/init/command.js +310 -0
- package/dist/init/derive.d.ts +51 -0
- package/dist/init/derive.js +715 -0
- package/dist/init/draft.d.ts +138 -0
- package/dist/init/draft.js +1205 -0
- package/dist/init/render.d.ts +35 -0
- package/dist/init/render.js +82 -0
- package/dist/init/scaffold.d.ts +53 -0
- package/dist/init/scaffold.js +121 -0
- package/dist/invocation.d.ts +13 -0
- package/dist/invocation.js +20 -0
- package/dist/package-metadata.d.ts +9 -0
- package/dist/package-metadata.js +19 -0
- package/dist/readiness.d.ts +53 -0
- package/dist/readiness.js +88 -0
- package/dist/references/named.d.ts +24 -0
- package/dist/references/named.js +27 -0
- package/dist/refusal.d.ts +15 -0
- package/dist/refusal.js +7 -0
- package/dist/registry-derivation.d.ts +31 -0
- package/dist/registry-derivation.js +32 -0
- package/dist/registry-resolve/command.d.ts +47 -0
- package/dist/registry-resolve/command.js +226 -0
- package/dist/registry-resolve/registry.d.ts +68 -0
- package/dist/registry-resolve/registry.js +292 -0
- package/dist/registry-resolve/render-shell.d.ts +18 -0
- package/dist/registry-resolve/render-shell.js +36 -0
- package/dist/repair.d.ts +29 -0
- package/dist/repair.js +8 -0
- package/dist/schema-json.d.ts +1 -0
- package/dist/schema-json.js +177 -0
- package/dist/schema.d.ts +1322 -0
- package/dist/schema.js +934 -0
- package/dist/setup/command.d.ts +4 -0
- package/dist/setup/command.js +4 -0
- package/dist/sha256.d.ts +1 -0
- package/dist/sha256.js +4 -0
- package/dist/surfaces/adoption.d.ts +41 -0
- package/dist/surfaces/adoption.js +217 -0
- package/dist/surfaces/consumer-instructions.d.ts +20 -0
- package/dist/surfaces/consumer-instructions.js +43 -0
- package/dist/surfaces/contract.d.ts +42 -0
- package/dist/surfaces/contract.js +169 -0
- package/dist/surfaces/core-declarations.d.ts +24 -0
- package/dist/surfaces/core-declarations.js +79 -0
- package/dist/surfaces/development-markers.d.ts +1 -0
- package/dist/surfaces/development-markers.js +18 -0
- package/dist/surfaces/generator-adapter.d.ts +71 -0
- package/dist/surfaces/generator-adapter.js +809 -0
- package/dist/surfaces/harness-registry.d.ts +180 -0
- package/dist/surfaces/harness-registry.js +117 -0
- package/dist/surfaces/mcp.d.ts +95 -0
- package/dist/surfaces/mcp.js +186 -0
- package/dist/surfaces/merge.d.ts +30 -0
- package/dist/surfaces/merge.js +105 -0
- package/dist/surfaces/ownership.d.ts +190 -0
- package/dist/surfaces/ownership.js +795 -0
- package/dist/surfaces/projection.d.ts +136 -0
- package/dist/surfaces/projection.js +681 -0
- package/dist/surfaces/render.d.ts +118 -0
- package/dist/surfaces/render.js +633 -0
- package/dist/surfaces/restrictions.d.ts +130 -0
- package/dist/surfaces/restrictions.js +447 -0
- package/dist/surfaces/selftest.d.ts +162 -0
- package/dist/surfaces/selftest.js +393 -0
- package/dist/surfaces/skill-contract.d.ts +85 -0
- package/dist/surfaces/skill-contract.js +449 -0
- package/dist/surfaces/sync.d.ts +57 -0
- package/dist/surfaces/sync.js +164 -0
- package/dist/team-metadata.d.ts +41 -0
- package/dist/team-metadata.js +512 -0
- package/dist/testing/gates.d.ts +91 -0
- package/dist/testing/gates.js +182 -0
- package/dist/testing/hooks.d.ts +59 -0
- package/dist/testing/hooks.js +139 -0
- package/dist/testing/verdict.d.ts +29 -0
- package/dist/testing/verdict.js +62 -0
- package/dist/work-orders/application.d.ts +99 -0
- package/dist/work-orders/application.js +383 -0
- package/dist/work-orders/composition.d.ts +124 -0
- package/dist/work-orders/composition.js +1010 -0
- package/dist/work-orders/contract.d.ts +61 -0
- package/dist/work-orders/contract.js +122 -0
- package/dist/work-orders/store.d.ts +158 -0
- package/dist/work-orders/store.js +197 -0
- package/docs/README.md +65 -0
- package/docs/architecture.md +136 -0
- package/docs/capability-matrix.md +50 -0
- package/docs/cli-reference.md +599 -0
- package/docs/command-list.md +51 -0
- package/docs/compose-patterns.md +99 -0
- package/docs/concepts.md +171 -0
- package/docs/configuration-essentials.md +172 -0
- package/docs/configuration-reference.md +621 -0
- package/docs/environment.md +760 -0
- package/docs/extending.md +43 -0
- package/docs/faq.md +111 -0
- package/docs/getting-started.md +608 -0
- package/docs/harness-surfaces.md +433 -0
- package/docs/joining-a-team.md +76 -0
- package/docs/release-policy.md +49 -0
- package/docs/safety-and-autonomy.md +419 -0
- package/docs/troubleshooting.md +361 -0
- package/docs/tutorial.md +170 -0
- package/docs/work-and-browser.md +254 -0
- package/libexec/browser-operation.cjs +186 -0
- package/libexec/fence-marker.cjs +101 -0
- package/libexec/fence-marker.d.cts +24 -0
- package/libexec/fenced-group-runner.cjs +77 -0
- package/libexec/fenced-supervisor.cjs +137 -0
- package/libexec/generated-filesystem.cjs +731 -0
- package/libexec/install-filesystem.cjs +225 -0
- package/libexec/rulesync-generator.NOTICE.md +1112 -0
- package/libexec/rulesync-generator.cjs +743 -0
- package/libexec/surface-generator-worker.cjs +266 -0
- package/libexec/surface-output-reader.cjs +99 -0
- package/libexec/surface-scratch-cleanup.cjs +14 -0
- package/libexec/validate-harness-evidence.d.mts +183 -0
- package/libexec/validate-harness-evidence.mjs +1312 -0
- package/package.json +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 +54 -0
- package/surfaces/skills/cockpit-explain.skill.md +32 -0
- package/surfaces/skills/cockpit-fix.skill.md +37 -0
- package/surfaces/skills/cockpit-setup.skill.md +39 -0
- package/surfaces/skills/cockpit-work.skill.md +34 -0
- package/surfaces/skills/collection.json +5 -0
- package/surfaces/skills/procedures/explain.md +61 -0
- package/surfaces/skills/procedures/fix.md +81 -0
- package/surfaces/skills/procedures/setup.md +379 -0
- package/surfaces/skills/procedures/work.md +105 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { dirname, join, resolve } from 'node:path';
|
|
2
|
+
import { ENVIRONMENT_CODES, errorCause, snapshotJson } from '../contract.js';
|
|
3
|
+
import { effectivePolicy, policyWeakening, policyWeakeningDiagnostic, readRecordedPolicy } from '../../autonomy.js';
|
|
4
|
+
import { prepareGeneratedEnvironmentCurrentness } from '../generated-application/check.js';
|
|
5
|
+
import {} from '../generated-application/shared.js';
|
|
6
|
+
import { declaredRuntime, declaresNothingToRun } from '../declaration.js';
|
|
7
|
+
import { readinessReport } from '../../readiness.js';
|
|
8
|
+
import { proposeGeneratedEnvironmentRepair } from '../../repair.js';
|
|
9
|
+
import { SURFACE_FEATURES } from '../../surfaces/contract.js';
|
|
10
|
+
import { loadCockpitConfig, evaluatorTools } from '../../config/load.js';
|
|
11
|
+
import { projectDoctor } from '../observations.js';
|
|
12
|
+
import { applicationDiagnostic, evaluateApplicationHealth, healthDiagnostics, issueHealthObservationSource, prepareHealthObservation, } from './health.js';
|
|
13
|
+
import { ownDataValues } from './shared.js';
|
|
14
|
+
import { unreadableStateWarning } from './lifecycle-state.js';
|
|
15
|
+
// What reset and up do to product data rests on these declarations; doctor names an absent one
|
|
16
|
+
// instead of letting it read as a passed check.
|
|
17
|
+
async function doctorDeclarations(loading) {
|
|
18
|
+
const loaded = await loading;
|
|
19
|
+
if (loaded.kind !== 'complete')
|
|
20
|
+
return [];
|
|
21
|
+
const environment = loaded.result.config.environment;
|
|
22
|
+
const runtime = declaredRuntime(environment) === 'compose';
|
|
23
|
+
const absent = runtime ? 'not declared in cockpit.toml' : 'no runtime environment is declared';
|
|
24
|
+
const row = (subject, declared, source, reason) => ({ subject, state: declared ? 'declared' : 'not-declared', source, reason: declared ? reason : absent });
|
|
25
|
+
return [
|
|
26
|
+
row('runtime', runtime, 'environment.compose_files', runtime ? 'cockpit runs the declared Compose files'
|
|
27
|
+
: 'environment.compose_files is not declared; runtime commands refuse'),
|
|
28
|
+
row('reset-volumes', environment.resettable_volumes.length > 0, 'environment.resettable_volumes', 'reset may delete and recreate these volumes'),
|
|
29
|
+
row('seed', environment.seed !== undefined, 'environment.seed', 'up runs the seed when a resettable volume is new'),
|
|
30
|
+
];
|
|
31
|
+
}
|
|
32
|
+
// The guard denies agent commands that reach these hosts. Two empty lists deny nothing, and that
|
|
33
|
+
// looks exactly like a guard that is working, so doctor says so. A declared runtime is the signal
|
|
34
|
+
// that hosted environments exist. Both keys
|
|
35
|
+
// written as empty lists, as init records an explicit "none", is a decision and is not warned about.
|
|
36
|
+
async function doctorGuardHostDiagnostics(loading) {
|
|
37
|
+
const loaded = await loading;
|
|
38
|
+
if (loaded.kind !== 'complete')
|
|
39
|
+
return [];
|
|
40
|
+
const { environment, guards } = loaded.result.config;
|
|
41
|
+
if (declaredRuntime(environment) === 'none' || loaded.result.guardHostsStated
|
|
42
|
+
|| guards.hosted_db_hosts.length > 0 || guards.vendor_endpoint_hosts.length > 0) {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
return [{
|
|
46
|
+
severity: 'warning',
|
|
47
|
+
// A literal, so the diagnostic inventory captures the fix beside the code.
|
|
48
|
+
code: 'GUARD_HOSTS_UNDECLARED',
|
|
49
|
+
message: 'guards.hosted_db_hosts and guards.vendor_endpoint_hosts are both empty, so the guard denies no agent command by host even though this cockpit declares a runtime',
|
|
50
|
+
target: 'guards',
|
|
51
|
+
fix: 'list the database and live vendor API hosts of every non-local environment (production, staging, shared) under [guards] in cockpit.toml, then run npx --no cockpit sync --config <your cockpit.toml>; if no such environment exists, record that by writing hosted_db_hosts = [] and vendor_endpoint_hosts = [] under [guards]',
|
|
52
|
+
}];
|
|
53
|
+
}
|
|
54
|
+
// A product with no declared gate gives test-run nothing to run, so no work in it can be graded PASS;
|
|
55
|
+
// a docs-only cockpit has no product to test and stays quiet.
|
|
56
|
+
async function doctorEvaluatorDiagnostics(loading, adapters) {
|
|
57
|
+
const loaded = await loading;
|
|
58
|
+
return loaded.kind === 'complete' && adapters.inspectEvaluator ? adapters.inspectEvaluator(evaluatorTools(loaded.result.config)) : [];
|
|
59
|
+
}
|
|
60
|
+
async function doctorTestingGateDiagnostics(loading) {
|
|
61
|
+
const loaded = await loading;
|
|
62
|
+
if (loaded.kind !== 'complete' || loaded.result.config.testing || declaredRuntime(loaded.result.config.environment) === 'none') {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
return [{
|
|
66
|
+
severity: 'warning',
|
|
67
|
+
// A literal, so the diagnostic inventory captures the fix beside the code.
|
|
68
|
+
code: 'TESTING_GATE_UNDECLARED',
|
|
69
|
+
message: 'cockpit.toml declares no [testing] gate, so test-run has nothing to run and no work in this product can be graded PASS',
|
|
70
|
+
target: 'testing',
|
|
71
|
+
fix: 'declare the product test commands as [testing] stages with a targeted and a full gate in cockpit.toml, then run npx --no cockpit sync --config <your cockpit.toml>',
|
|
72
|
+
}];
|
|
73
|
+
}
|
|
74
|
+
// init records answers no person stated under `unconfirmed`. They look exactly like stated values
|
|
75
|
+
// in the file, so doctor keeps naming them until a person confirms each and deletes its entry.
|
|
76
|
+
async function doctorUnconfirmedDiagnostics(loading) {
|
|
77
|
+
const loaded = await loading;
|
|
78
|
+
if (loaded.kind !== 'complete' || !loaded.result.config.unconfirmed)
|
|
79
|
+
return [];
|
|
80
|
+
return [{
|
|
81
|
+
severity: 'warning',
|
|
82
|
+
// A literal, so the diagnostic inventory captures the fix beside the code.
|
|
83
|
+
code: 'DECLARATION_UNCONFIRMED',
|
|
84
|
+
message: `${loaded.result.config.unconfirmed.join(', ')} in cockpit.toml were chosen by the setup agent or by no one named, not stated by a person, so they may not describe this product`,
|
|
85
|
+
target: 'unconfirmed',
|
|
86
|
+
fix: 'confirm each value with whoever owns the product and correct it in cockpit.toml if it is wrong, delete each confirmed entry from unconfirmed, then run npx --no cockpit sync --config <your cockpit.toml>',
|
|
87
|
+
}];
|
|
88
|
+
}
|
|
89
|
+
// The same weakening `check` fails on: a policy cockpit.toml sets below the one the last sync recorded
|
|
90
|
+
// is not in force, and doctor is where an agent looks first.
|
|
91
|
+
async function doctorPolicyDiagnostics(loading) {
|
|
92
|
+
const loaded = await loading;
|
|
93
|
+
if (loaded.kind !== 'complete')
|
|
94
|
+
return [];
|
|
95
|
+
const recorded = await readRecordedPolicy(dirname(loaded.result.source.path));
|
|
96
|
+
const weakened = recorded ? policyWeakening(recorded, effectivePolicy(loaded.result.config)) : [];
|
|
97
|
+
return weakened.length ? [{ ...policyWeakeningDiagnostic(weakened), severity: 'warning' }] : [];
|
|
98
|
+
}
|
|
99
|
+
const unavailableSurfaceOverrideInspection = Object.freeze({
|
|
100
|
+
kind: 'unavailable',
|
|
101
|
+
code: 'SURFACE_OVERRIDE_INSPECTION_UNAVAILABLE',
|
|
102
|
+
reason: 'authenticated generated surface override inspection is unavailable',
|
|
103
|
+
});
|
|
104
|
+
async function inspectDoctorSurfaceOverrides(configPath, adapters) {
|
|
105
|
+
if (!adapters.inspectSurfaceOverrides)
|
|
106
|
+
return unavailableSurfaceOverrideInspection;
|
|
107
|
+
try {
|
|
108
|
+
const inspection = await adapters.inspectSurfaceOverrides(configPath);
|
|
109
|
+
const captured = snapshotJson(inspection);
|
|
110
|
+
const record = ownDataValues(captured, ['kind'], ['activeOverrides', 'changedOverrideOriginals', 'code', 'reason']);
|
|
111
|
+
const sha256 = /^[a-f0-9]{64}$/;
|
|
112
|
+
const activeOverride = (value) => {
|
|
113
|
+
const row = ownDataValues(value, ['name', 'feature', 'originalSha256', 'recordedSha256', 'overlaySource']);
|
|
114
|
+
return row !== undefined
|
|
115
|
+
&& typeof row.name === 'string' && row.name.length > 0
|
|
116
|
+
&& typeof row.feature === 'string' && SURFACE_FEATURES.includes(row.feature)
|
|
117
|
+
&& typeof row.originalSha256 === 'string' && sha256.test(row.originalSha256)
|
|
118
|
+
&& typeof row.recordedSha256 === 'string' && sha256.test(row.recordedSha256)
|
|
119
|
+
&& typeof row.overlaySource === 'string' && row.overlaySource.length > 0;
|
|
120
|
+
};
|
|
121
|
+
const changedOriginal = (value) => {
|
|
122
|
+
const row = ownDataValues(value, ['code', 'name', 'recordedSha256', 'currentSha256', 'overlaySource']);
|
|
123
|
+
return row !== undefined && row.code === 'OVERRIDDEN_CORE_CHANGED'
|
|
124
|
+
&& typeof row.name === 'string' && row.name.length > 0
|
|
125
|
+
&& typeof row.recordedSha256 === 'string' && sha256.test(row.recordedSha256)
|
|
126
|
+
&& typeof row.currentSha256 === 'string' && sha256.test(row.currentSha256)
|
|
127
|
+
&& typeof row.overlaySource === 'string' && row.overlaySource.length > 0;
|
|
128
|
+
};
|
|
129
|
+
const complete = record?.kind === 'complete'
|
|
130
|
+
&& Reflect.ownKeys(record).length === 3
|
|
131
|
+
&& Array.isArray(record.activeOverrides) && record.activeOverrides.every(activeOverride)
|
|
132
|
+
&& Array.isArray(record.changedOverrideOriginals) && record.changedOverrideOriginals.every(changedOriginal);
|
|
133
|
+
const unavailableOrRefusal = (record?.kind === 'unavailable' || record?.kind === 'refusal')
|
|
134
|
+
&& Reflect.ownKeys(record).length === 3
|
|
135
|
+
&& typeof record.code === 'string' && record.code.length > 0
|
|
136
|
+
&& typeof record.reason === 'string' && record.reason.length > 0;
|
|
137
|
+
if (!complete && !unavailableOrRefusal) {
|
|
138
|
+
return {
|
|
139
|
+
kind: 'refusal',
|
|
140
|
+
code: 'SURFACE_OVERRIDE_INSPECTION_INVALID',
|
|
141
|
+
reason: 'surface override inspection returned invalid evidence',
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return captured;
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
return { ...unavailableSurfaceOverrideInspection,
|
|
148
|
+
reason: `${unavailableSurfaceOverrideInspection.reason}: ${errorCause(error)}` };
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function unavailableDoctor(code, message, surfaceOverrides, freshness, declarations, forwarded) {
|
|
152
|
+
return {
|
|
153
|
+
kind: 'complete', status: 0,
|
|
154
|
+
diagnostics: forwarded ?? [applicationDiagnostic(code, message, 'preflight')],
|
|
155
|
+
result: {
|
|
156
|
+
verdict: 'unavailable', checks: [], comparisons: [], surfaceOverrides, freshness, declarations,
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
export async function runDoctor(input, adapters) {
|
|
161
|
+
const config = loadCockpitConfig(input.configPath);
|
|
162
|
+
// Codex hook trust is advice for a Codex user; a cockpit that does not list Codex gets none.
|
|
163
|
+
const hookTrustFindings = async () => {
|
|
164
|
+
const loaded = await config;
|
|
165
|
+
return loaded.kind === 'complete' && loaded.result.config.surfaces.tools.includes('codexcli')
|
|
166
|
+
? adapters.inspectHookTrust?.() ?? [] : [];
|
|
167
|
+
};
|
|
168
|
+
const [outcome, guardHosts, unconfirmed, policyWeakened, testingGate, hookTrust, evaluator, readinessWarnings] = await Promise.all([doctorHealth(input, adapters, config),
|
|
169
|
+
doctorGuardHostDiagnostics(config), doctorUnconfirmedDiagnostics(config), doctorPolicyDiagnostics(config), doctorTestingGateDiagnostics(config), hookTrustFindings(),
|
|
170
|
+
doctorEvaluatorDiagnostics(config, adapters), adapters.inspectReadiness?.() ?? []]);
|
|
171
|
+
const stateInventory = await adapters.readUnreadableState?.();
|
|
172
|
+
const unreadableState = stateInventory?.kind === 'refusal'
|
|
173
|
+
// An inventory that cannot be read, such as one another command holds locked, is no clean one.
|
|
174
|
+
? stateInventory.diagnostics.map((diagnostic) => ({ ...diagnostic, severity: 'warning',
|
|
175
|
+
message: `doctor could not read this machine's cockpit state, so it did not check for other cockpits' state this version cannot read: ${diagnostic.message}` }))
|
|
176
|
+
: [unreadableStateWarning(stateInventory?.skipped ?? [])].filter((warning) => warning !== undefined);
|
|
177
|
+
const warnings = [...unconfirmed, ...policyWeakened, ...guardHosts, ...testingGate, ...hookTrust, ...evaluator, ...readinessWarnings, ...unreadableState];
|
|
178
|
+
const reported = warnings.length === 0 ? outcome
|
|
179
|
+
: { ...outcome, diagnostics: [...outcome.diagnostics, ...warnings] };
|
|
180
|
+
// Doctor reports on a configuration; without one there is nothing to report on, and a zero
|
|
181
|
+
// exit would let `doctor && ...` proceed past a missing or unparseable cockpit.toml.
|
|
182
|
+
const loaded = await config;
|
|
183
|
+
if (loaded.kind === 'complete') {
|
|
184
|
+
const state = declaresNothingToRun(loaded.result.config.environment) ? 'surfaces-only' : 'runtime';
|
|
185
|
+
return { ...reported, result: { ...reported.result,
|
|
186
|
+
readiness: readinessReport(state, reported.diagnostics, loaded.result.config.surfaces.tools) } };
|
|
187
|
+
}
|
|
188
|
+
const forwarded = new Set(reported.diagnostics.map(({ code, target }) => `${code}\0${target}`));
|
|
189
|
+
return {
|
|
190
|
+
...reported, kind: 'refusal', status: 2,
|
|
191
|
+
diagnostics: [...loaded.diagnostics.filter(({ code, target }) => !forwarded.has(`${code}\0${target}`)), ...reported.diagnostics],
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
async function doctorHealth(input, adapters, config) {
|
|
195
|
+
const surfaceOverrides = inspectDoctorSurfaceOverrides(input.configPath, adapters);
|
|
196
|
+
const declarations = doctorDeclarations(config);
|
|
197
|
+
const freshness = Promise.all([
|
|
198
|
+
prepareGeneratedEnvironmentCurrentness(input),
|
|
199
|
+
adapters.discoverReleaseFreshness?.() ?? Promise.resolve({ kind: 'unknown', reason: 'release discovery is not bound' }),
|
|
200
|
+
]).then(([currentness, release]) => ({
|
|
201
|
+
local: { kind: currentness.outcome.kind, status: currentness.outcome.status, diagnostics: currentness.outcome.diagnostics },
|
|
202
|
+
changes: currentness.changes, storedProducer: currentness.storedProducer,
|
|
203
|
+
installedProducer: currentness.currentProducer, release, repair: proposeGeneratedEnvironmentRepair(currentness),
|
|
204
|
+
}));
|
|
205
|
+
let health;
|
|
206
|
+
let doctor;
|
|
207
|
+
// A producer that refused says why, also when the observation is lost to a throw afterwards.
|
|
208
|
+
let refused;
|
|
209
|
+
try {
|
|
210
|
+
const source = await adapters.load(input, issueHealthObservationSource, (diagnostics) => { refused = diagnostics; return undefined; }, 'doctor');
|
|
211
|
+
if (!source) {
|
|
212
|
+
return unavailableDoctor(ENVIRONMENT_CODES.LIFECYCLE_EVIDENCE_INVALID, 'doctor observation source is unavailable', await surfaceOverrides, await freshness, await declarations, refused);
|
|
213
|
+
}
|
|
214
|
+
const observed = prepareHealthObservation(input, source);
|
|
215
|
+
if (!observed) {
|
|
216
|
+
return unavailableDoctor(ENVIRONMENT_CODES.LIFECYCLE_EVIDENCE_INVALID, 'doctor requires authenticated steady lifecycle evidence', await surfaceOverrides, await freshness, await declarations);
|
|
217
|
+
}
|
|
218
|
+
health = await evaluateApplicationHealth(observed, adapters);
|
|
219
|
+
doctor = projectDoctor(health.preflight);
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
return unavailableDoctor(ENVIRONMENT_CODES.LIFECYCLE_EVIDENCE_INVALID, `doctor requires authentic observation and lifecycle evidence: ${errorCause(error)}`, await surfaceOverrides, await freshness, await declarations, refused);
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
kind: 'complete', status: 0, diagnostics: healthDiagnostics(health),
|
|
226
|
+
result: {
|
|
227
|
+
verdict: health.verdict,
|
|
228
|
+
checks: doctor.checks,
|
|
229
|
+
comparisons: health.comparisons,
|
|
230
|
+
surfaceOverrides: await surfaceOverrides,
|
|
231
|
+
freshness: await freshness,
|
|
232
|
+
declarations: await declarations,
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type ExecuteProbeOutcome } from '../../environment-exec/execute.js';
|
|
2
|
+
import { type EnvironmentCommandOutcome, type ExecutionStep } from '../contract.js';
|
|
3
|
+
import { type GuardDecision, type GuardEvaluationPolicy } from '../../guards/evaluator.js';
|
|
4
|
+
import { type GuardSurfaceTarget } from '../../surfaces/harness-registry.js';
|
|
5
|
+
import { type FixContext } from '../../fix-catalogue.js';
|
|
6
|
+
import { observeSetupCheckout, type SetupCheckoutObservation } from '../setup-observation.js';
|
|
7
|
+
import { loadCockpitConfig, type LoadedConfigProjection } from '../../config/load.js';
|
|
8
|
+
export interface GuardEvaluationApplicationInput {
|
|
9
|
+
readonly identity: unknown;
|
|
10
|
+
/** The checkout the invoked guard script resolved from its own location. */
|
|
11
|
+
readonly guardRoot: string;
|
|
12
|
+
readonly payload: unknown;
|
|
13
|
+
readonly harness: GuardSurfaceTarget;
|
|
14
|
+
readonly cwd: string;
|
|
15
|
+
readonly askIsDeny?: boolean;
|
|
16
|
+
readonly ripgrepConfigActive?: boolean;
|
|
17
|
+
/** The harness's command search path, whose directories inside the allowed roots the guard protects. */
|
|
18
|
+
readonly searchPath?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface GuardEvaluationApplicationAdapters {
|
|
21
|
+
readonly loadConfig: typeof loadCockpitConfig;
|
|
22
|
+
readonly observeCheckout: typeof observeSetupCheckout;
|
|
23
|
+
readonly resolveGit: () => Promise<import('../executable.js').ExecutableResolution>;
|
|
24
|
+
/** Needed only by a compose-first cockpit, whose service list is read from its Compose files. */
|
|
25
|
+
readonly resolveDocker?: () => Promise<import('../executable.js').ExecutableResolution>;
|
|
26
|
+
readonly execute?: (step: ExecutionStep) => Promise<ExecuteProbeOutcome>;
|
|
27
|
+
}
|
|
28
|
+
export interface GuardEvaluationApplicationResult {
|
|
29
|
+
readonly decision: GuardDecision;
|
|
30
|
+
readonly diagnostics: readonly import('../contract.js').Diagnostic[];
|
|
31
|
+
readonly fixContext?: FixContext;
|
|
32
|
+
}
|
|
33
|
+
/** Installed bytes are authority only while their source, roots and publication still match. */
|
|
34
|
+
export declare function runGuardEvaluationApplication(input: GuardEvaluationApplicationInput, adapters: GuardEvaluationApplicationAdapters): Promise<GuardEvaluationApplicationResult>;
|
|
35
|
+
export interface PreparedGuardEvaluationPolicy {
|
|
36
|
+
readonly policy: GuardEvaluationPolicy;
|
|
37
|
+
}
|
|
38
|
+
export interface GuardEvaluationPolicyInput {
|
|
39
|
+
readonly configuration: LoadedConfigProjection;
|
|
40
|
+
readonly checkout: SetupCheckoutObservation;
|
|
41
|
+
}
|
|
42
|
+
/** Source projections share authenticated authority; installed consumption is admitted separately. */
|
|
43
|
+
export declare function prepareGuardEvaluationPolicy(input: GuardEvaluationPolicyInput): Promise<EnvironmentCommandOutcome<PreparedGuardEvaluationPolicy>>;
|