@b00dea/cockpit 0.0.0-bootstrap.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +375 -0
- package/LICENSE +21 -0
- package/README.md +21 -1
- package/bin/cockpit.mjs +33 -0
- package/cockpit.schema.json +2574 -0
- package/dist/autonomy.d.ts +44 -0
- package/dist/autonomy.js +156 -0
- package/dist/bounded-read.d.ts +14 -0
- package/dist/bounded-read.js +42 -0
- package/dist/browser/commands.d.ts +62 -0
- package/dist/browser/commands.js +349 -0
- package/dist/browser/package-paths.d.ts +1 -0
- package/dist/browser/package-paths.js +6 -0
- package/dist/browser/proxy.d.ts +22 -0
- package/dist/browser/proxy.js +37 -0
- package/dist/browser/runtime.d.ts +117 -0
- package/dist/browser/runtime.js +183 -0
- package/dist/browser/surfaces.d.ts +141 -0
- package/dist/browser/surfaces.js +556 -0
- package/dist/browser/ui-gate.d.ts +15 -0
- package/dist/browser/ui-gate.js +18 -0
- package/dist/cli-guard.d.ts +5 -0
- package/dist/cli-guard.js +71 -0
- package/dist/cli-main.d.ts +139 -0
- package/dist/cli-main.js +1405 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +16 -0
- package/dist/command-table.d.ts +113 -0
- package/dist/command-table.js +512 -0
- package/dist/config/load.d.ts +171 -0
- package/dist/config/load.js +345 -0
- package/dist/config/sibling-toml.d.ts +48 -0
- package/dist/config/sibling-toml.js +160 -0
- package/dist/config/surface-tools-toml.d.ts +9 -0
- package/dist/config/surface-tools-toml.js +37 -0
- package/dist/config/verified-write.d.ts +43 -0
- package/dist/config/verified-write.js +89 -0
- package/dist/diagnostics.d.ts +26 -0
- package/dist/diagnostics.js +335 -0
- package/dist/emit.d.ts +22 -0
- package/dist/emit.js +43 -0
- package/dist/entrypoint-kinds.d.ts +3 -0
- package/dist/entrypoint-kinds.js +11 -0
- package/dist/environment/application/destructive.d.ts +6 -0
- package/dist/environment/application/destructive.js +425 -0
- package/dist/environment/application/doctor.d.ts +89 -0
- package/dist/environment/application/doctor.js +235 -0
- package/dist/environment/application/guard.d.ts +43 -0
- package/dist/environment/application/guard.js +622 -0
- package/dist/environment/application/health.d.ts +134 -0
- package/dist/environment/application/health.js +379 -0
- package/dist/environment/application/lifecycle-context.d.ts +228 -0
- package/dist/environment/application/lifecycle-context.js +154 -0
- package/dist/environment/application/lifecycle-state.d.ts +25 -0
- package/dist/environment/application/lifecycle-state.js +201 -0
- package/dist/environment/application/lifecycle.d.ts +17 -0
- package/dist/environment/application/lifecycle.js +729 -0
- package/dist/environment/application/logs.d.ts +45 -0
- package/dist/environment/application/logs.js +127 -0
- package/dist/environment/application/setup.d.ts +129 -0
- package/dist/environment/application/setup.js +741 -0
- package/dist/environment/application/shared.d.ts +11 -0
- package/dist/environment/application/shared.js +61 -0
- package/dist/environment/claims.d.ts +389 -0
- package/dist/environment/claims.js +1709 -0
- package/dist/environment/codex-hook-trust.d.ts +11 -0
- package/dist/environment/codex-hook-trust.js +185 -0
- package/dist/environment/compose-environment.d.ts +1 -0
- package/dist/environment/compose-environment.js +6 -0
- package/dist/environment/compose-ownership.d.ts +21 -0
- package/dist/environment/compose-ownership.js +117 -0
- package/dist/environment/compose-topology.d.ts +117 -0
- package/dist/environment/compose-topology.js +413 -0
- package/dist/environment/contract.d.ts +489 -0
- package/dist/environment/contract.js +761 -0
- package/dist/environment/declaration.d.ts +14 -0
- package/dist/environment/declaration.js +39 -0
- package/dist/environment/destructive-composition.d.ts +29 -0
- package/dist/environment/destructive-composition.js +333 -0
- package/dist/environment/docker-daemon.d.ts +30 -0
- package/dist/environment/docker-daemon.js +78 -0
- package/dist/environment/docker-endpoint.d.ts +10 -0
- package/dist/environment/docker-endpoint.js +19 -0
- package/dist/environment/env-schema-observation.d.ts +46 -0
- package/dist/environment/env-schema-observation.js +241 -0
- package/dist/environment/evidence.d.ts +136 -0
- package/dist/environment/evidence.js +437 -0
- package/dist/environment/executable.d.ts +26 -0
- package/dist/environment/executable.js +167 -0
- package/dist/environment/generated-application/authorities.d.ts +5 -0
- package/dist/environment/generated-application/authorities.js +61 -0
- package/dist/environment/generated-application/bootstrap-skill.d.ts +16 -0
- package/dist/environment/generated-application/bootstrap-skill.js +328 -0
- package/dist/environment/generated-application/check.d.ts +13 -0
- package/dist/environment/generated-application/check.js +189 -0
- package/dist/environment/generated-application/custom-surface.d.ts +26 -0
- package/dist/environment/generated-application/custom-surface.js +289 -0
- package/dist/environment/generated-application/prepare.d.ts +29 -0
- package/dist/environment/generated-application/prepare.js +276 -0
- package/dist/environment/generated-application/publication.d.ts +33 -0
- package/dist/environment/generated-application/publication.js +547 -0
- package/dist/environment/generated-application/shared.d.ts +484 -0
- package/dist/environment/generated-application/shared.js +349 -0
- package/dist/environment/generated-application/surface-observation.d.ts +4 -0
- package/dist/environment/generated-application/surface-observation.js +69 -0
- package/dist/environment/generated-application/surface-outputs.d.ts +71 -0
- package/dist/environment/generated-application/surface-outputs.js +389 -0
- package/dist/environment/generated-application/surfaces.d.ts +3 -0
- package/dist/environment/generated-application/surfaces.js +699 -0
- package/dist/environment/generated-application/sync.d.ts +6 -0
- package/dist/environment/generated-application/sync.js +109 -0
- package/dist/environment/git-observation.d.ts +183 -0
- package/dist/environment/git-observation.js +544 -0
- package/dist/environment/health-composition.d.ts +11 -0
- package/dist/environment/health-composition.js +628 -0
- package/dist/environment/host-observation.d.ts +56 -0
- package/dist/environment/host-observation.js +52 -0
- package/dist/environment/identity.d.ts +48 -0
- package/dist/environment/identity.js +85 -0
- package/dist/environment/init-application.d.ts +308 -0
- package/dist/environment/init-application.js +697 -0
- package/dist/environment/install-policy-observation.d.ts +71 -0
- package/dist/environment/install-policy-observation.js +284 -0
- package/dist/environment/install-policy.d.ts +48 -0
- package/dist/environment/install-policy.js +96 -0
- package/dist/environment/instance.d.ts +33 -0
- package/dist/environment/instance.js +122 -0
- package/dist/environment/instruction-pointer.d.ts +19 -0
- package/dist/environment/instruction-pointer.js +144 -0
- package/dist/environment/lifecycle-composition.d.ts +29 -0
- package/dist/environment/lifecycle-composition.js +675 -0
- package/dist/environment/lifecycle-stage.d.ts +115 -0
- package/dist/environment/lifecycle-stage.js +398 -0
- package/dist/environment/lifecycle.d.ts +75 -0
- package/dist/environment/lifecycle.js +354 -0
- package/dist/environment/logs.d.ts +132 -0
- package/dist/environment/logs.js +519 -0
- package/dist/environment/observations.d.ts +46 -0
- package/dist/environment/observations.js +344 -0
- package/dist/environment/operator-application.d.ts +50 -0
- package/dist/environment/operator-application.js +155 -0
- package/dist/environment/ports.d.ts +182 -0
- package/dist/environment/ports.js +1205 -0
- package/dist/environment/posture-observation.d.ts +68 -0
- package/dist/environment/posture-observation.js +253 -0
- package/dist/environment/read-composition.d.ts +27 -0
- package/dist/environment/read-composition.js +352 -0
- package/dist/environment/readiness-composition.d.ts +38 -0
- package/dist/environment/readiness-composition.js +130 -0
- package/dist/environment/reclaim.d.ts +333 -0
- package/dist/environment/reclaim.js +1835 -0
- package/dist/environment/repository-identity.d.ts +13 -0
- package/dist/environment/repository-identity.js +108 -0
- package/dist/environment/runtime-measurement-record.d.ts +38 -0
- package/dist/environment/runtime-measurement-record.js +111 -0
- package/dist/environment/runtime-measurement.d.ts +27 -0
- package/dist/environment/runtime-measurement.js +224 -0
- package/dist/environment/runtime-probe-residue.d.ts +43 -0
- package/dist/environment/runtime-probe-residue.js +148 -0
- package/dist/environment/runtime-probe.d.ts +72 -0
- package/dist/environment/runtime-probe.js +725 -0
- package/dist/environment/runtime.d.ts +505 -0
- package/dist/environment/runtime.js +2335 -0
- package/dist/environment/seed.d.ts +16 -0
- package/dist/environment/seed.js +43 -0
- package/dist/environment/selftest-application.d.ts +86 -0
- package/dist/environment/selftest-application.js +713 -0
- package/dist/environment/sensitive.d.ts +3 -0
- package/dist/environment/sensitive.js +48 -0
- package/dist/environment/setup-observation.d.ts +62 -0
- package/dist/environment/setup-observation.js +1473 -0
- package/dist/environment/setup.d.ts +43 -0
- package/dist/environment/setup.js +176 -0
- package/dist/environment/sibling-instructions.d.ts +33 -0
- package/dist/environment/sibling-instructions.js +224 -0
- package/dist/environment/sibling-registration.d.ts +45 -0
- package/dist/environment/sibling-registration.js +538 -0
- package/dist/environment/state.d.ts +371 -0
- package/dist/environment/state.js +2013 -0
- package/dist/environment/templates.d.ts +140 -0
- package/dist/environment/templates.js +685 -0
- package/dist/environment/tool-registration.d.ts +9 -0
- package/dist/environment/tool-registration.js +96 -0
- package/dist/environment/upgrade-application.d.ts +19 -0
- package/dist/environment/upgrade-application.js +175 -0
- package/dist/environment-exec/execute.d.ts +102 -0
- package/dist/environment-exec/execute.js +1175 -0
- package/dist/environment-exec/libexec-program.d.ts +6 -0
- package/dist/environment-exec/libexec-program.js +22 -0
- package/dist/environment-exec/verified-digest.d.ts +4 -0
- package/dist/environment-exec/verified-digest.js +16 -0
- package/dist/exact-keys.d.ts +7 -0
- package/dist/exact-keys.js +15 -0
- package/dist/fix-catalogue.d.ts +32 -0
- package/dist/fix-catalogue.js +60 -0
- package/dist/freshness.d.ts +29 -0
- package/dist/freshness.js +75 -0
- package/dist/generated-environment/adopt.d.ts +16 -0
- package/dist/generated-environment/adopt.js +275 -0
- package/dist/generated-environment/command.d.ts +47 -0
- package/dist/generated-environment/command.js +75 -0
- package/dist/generated-environment/transaction.d.ts +186 -0
- package/dist/generated-environment/transaction.js +1770 -0
- package/dist/grading/evaluate.d.ts +71 -0
- package/dist/grading/evaluate.js +403 -0
- package/dist/grading/grade.d.ts +33 -0
- package/dist/grading/grade.js +57 -0
- package/dist/guards/evaluator.d.ts +113 -0
- package/dist/guards/evaluator.js +1226 -0
- package/dist/guards/harness-adapter.d.ts +17 -0
- package/dist/guards/harness-adapter.js +57 -0
- package/dist/guards/host.d.ts +8 -0
- package/dist/guards/host.js +10 -0
- package/dist/guards/invocation-parser.d.ts +66 -0
- package/dist/guards/invocation-parser.js +595 -0
- package/dist/guards/local-identity.d.ts +40 -0
- package/dist/guards/local-identity.js +123 -0
- package/dist/guards/policy-pin.d.ts +13 -0
- package/dist/guards/policy-pin.js +175 -0
- package/dist/guards/protected-locations.d.ts +62 -0
- package/dist/guards/protected-locations.js +461 -0
- package/dist/guards/read-only.d.ts +37 -0
- package/dist/guards/read-only.js +315 -0
- package/dist/init/command.d.ts +40 -0
- package/dist/init/command.js +310 -0
- package/dist/init/derive.d.ts +51 -0
- package/dist/init/derive.js +715 -0
- package/dist/init/draft.d.ts +138 -0
- package/dist/init/draft.js +1205 -0
- package/dist/init/render.d.ts +35 -0
- package/dist/init/render.js +82 -0
- package/dist/init/scaffold.d.ts +53 -0
- package/dist/init/scaffold.js +121 -0
- package/dist/invocation.d.ts +13 -0
- package/dist/invocation.js +20 -0
- package/dist/package-metadata.d.ts +9 -0
- package/dist/package-metadata.js +19 -0
- package/dist/readiness.d.ts +53 -0
- package/dist/readiness.js +88 -0
- package/dist/references/named.d.ts +24 -0
- package/dist/references/named.js +27 -0
- package/dist/refusal.d.ts +15 -0
- package/dist/refusal.js +7 -0
- package/dist/registry-derivation.d.ts +31 -0
- package/dist/registry-derivation.js +32 -0
- package/dist/registry-resolve/command.d.ts +47 -0
- package/dist/registry-resolve/command.js +226 -0
- package/dist/registry-resolve/registry.d.ts +68 -0
- package/dist/registry-resolve/registry.js +292 -0
- package/dist/registry-resolve/render-shell.d.ts +18 -0
- package/dist/registry-resolve/render-shell.js +36 -0
- package/dist/repair.d.ts +29 -0
- package/dist/repair.js +8 -0
- package/dist/schema-json.d.ts +1 -0
- package/dist/schema-json.js +177 -0
- package/dist/schema.d.ts +1322 -0
- package/dist/schema.js +934 -0
- package/dist/setup/command.d.ts +4 -0
- package/dist/setup/command.js +4 -0
- package/dist/sha256.d.ts +1 -0
- package/dist/sha256.js +4 -0
- package/dist/surfaces/adoption.d.ts +41 -0
- package/dist/surfaces/adoption.js +217 -0
- package/dist/surfaces/consumer-instructions.d.ts +20 -0
- package/dist/surfaces/consumer-instructions.js +43 -0
- package/dist/surfaces/contract.d.ts +42 -0
- package/dist/surfaces/contract.js +169 -0
- package/dist/surfaces/core-declarations.d.ts +24 -0
- package/dist/surfaces/core-declarations.js +79 -0
- package/dist/surfaces/development-markers.d.ts +1 -0
- package/dist/surfaces/development-markers.js +18 -0
- package/dist/surfaces/generator-adapter.d.ts +71 -0
- package/dist/surfaces/generator-adapter.js +809 -0
- package/dist/surfaces/harness-registry.d.ts +180 -0
- package/dist/surfaces/harness-registry.js +117 -0
- package/dist/surfaces/mcp.d.ts +95 -0
- package/dist/surfaces/mcp.js +186 -0
- package/dist/surfaces/merge.d.ts +30 -0
- package/dist/surfaces/merge.js +105 -0
- package/dist/surfaces/ownership.d.ts +190 -0
- package/dist/surfaces/ownership.js +795 -0
- package/dist/surfaces/projection.d.ts +136 -0
- package/dist/surfaces/projection.js +681 -0
- package/dist/surfaces/render.d.ts +118 -0
- package/dist/surfaces/render.js +633 -0
- package/dist/surfaces/restrictions.d.ts +130 -0
- package/dist/surfaces/restrictions.js +447 -0
- package/dist/surfaces/selftest.d.ts +162 -0
- package/dist/surfaces/selftest.js +393 -0
- package/dist/surfaces/skill-contract.d.ts +85 -0
- package/dist/surfaces/skill-contract.js +449 -0
- package/dist/surfaces/sync.d.ts +57 -0
- package/dist/surfaces/sync.js +164 -0
- package/dist/team-metadata.d.ts +41 -0
- package/dist/team-metadata.js +512 -0
- package/dist/testing/gates.d.ts +91 -0
- package/dist/testing/gates.js +182 -0
- package/dist/testing/hooks.d.ts +59 -0
- package/dist/testing/hooks.js +139 -0
- package/dist/testing/verdict.d.ts +29 -0
- package/dist/testing/verdict.js +62 -0
- package/dist/work-orders/application.d.ts +99 -0
- package/dist/work-orders/application.js +383 -0
- package/dist/work-orders/composition.d.ts +124 -0
- package/dist/work-orders/composition.js +1010 -0
- package/dist/work-orders/contract.d.ts +61 -0
- package/dist/work-orders/contract.js +122 -0
- package/dist/work-orders/store.d.ts +158 -0
- package/dist/work-orders/store.js +197 -0
- package/docs/README.md +65 -0
- package/docs/architecture.md +136 -0
- package/docs/capability-matrix.md +50 -0
- package/docs/cli-reference.md +599 -0
- package/docs/command-list.md +51 -0
- package/docs/compose-patterns.md +99 -0
- package/docs/concepts.md +171 -0
- package/docs/configuration-essentials.md +172 -0
- package/docs/configuration-reference.md +621 -0
- package/docs/environment.md +760 -0
- package/docs/extending.md +43 -0
- package/docs/faq.md +111 -0
- package/docs/getting-started.md +608 -0
- package/docs/harness-surfaces.md +433 -0
- package/docs/joining-a-team.md +76 -0
- package/docs/release-policy.md +49 -0
- package/docs/safety-and-autonomy.md +419 -0
- package/docs/troubleshooting.md +361 -0
- package/docs/tutorial.md +170 -0
- package/docs/work-and-browser.md +254 -0
- package/libexec/browser-operation.cjs +186 -0
- package/libexec/fence-marker.cjs +101 -0
- package/libexec/fence-marker.d.cts +24 -0
- package/libexec/fenced-group-runner.cjs +77 -0
- package/libexec/fenced-supervisor.cjs +137 -0
- package/libexec/generated-filesystem.cjs +731 -0
- package/libexec/install-filesystem.cjs +225 -0
- package/libexec/rulesync-generator.NOTICE.md +1112 -0
- package/libexec/rulesync-generator.cjs +743 -0
- package/libexec/surface-generator-worker.cjs +266 -0
- package/libexec/surface-output-reader.cjs +99 -0
- package/libexec/surface-scratch-cleanup.cjs +14 -0
- package/libexec/validate-harness-evidence.d.mts +183 -0
- package/libexec/validate-harness-evidence.mjs +1312 -0
- package/package.json +76 -1
- package/surfaces/README.md +33 -0
- package/surfaces/agents/evaluator.agent.md +76 -0
- package/surfaces/guards/bash-guard.sh +48 -0
- package/surfaces/guards/claude.adapter.json +25 -0
- package/surfaces/guards/codex.adapter.json +24 -0
- package/surfaces/guards/opencode.adapter.json +25 -0
- package/surfaces/references/browser.md +63 -0
- package/surfaces/references/test-data-and-personas.md +84 -0
- package/surfaces/references/testing-tiers.md +11 -0
- package/surfaces/skills/cockpit-browser.skill.md +54 -0
- package/surfaces/skills/cockpit-explain.skill.md +32 -0
- package/surfaces/skills/cockpit-fix.skill.md +37 -0
- package/surfaces/skills/cockpit-setup.skill.md +39 -0
- package/surfaces/skills/cockpit-work.skill.md +34 -0
- package/surfaces/skills/collection.json +5 -0
- package/surfaces/skills/procedures/explain.md +61 -0
- package/surfaces/skills/procedures/fix.md +81 -0
- package/surfaces/skills/procedures/setup.md +379 -0
- package/surfaces/skills/procedures/work.md +105 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { type AddressingPosture, type AuthPosture } from '../schema.js';
|
|
2
|
+
import { type CockpitId, type EnvironmentObservation, type JsonSnapshot, type StackId } from './contract.js';
|
|
3
|
+
import { type StackVariant } from './identity.js';
|
|
4
|
+
import { type LifecycleStageAuthority } from './lifecycle-stage.js';
|
|
5
|
+
/** The owner of the posture-requirement checks preflight derives from the declared postures. */
|
|
6
|
+
export declare const POSTURE_REQUIREMENT_OWNER = "posture-requirements";
|
|
7
|
+
export interface ResolvedPostureAuthority {
|
|
8
|
+
readonly stackId: StackId;
|
|
9
|
+
readonly evaluatedAt: string;
|
|
10
|
+
readonly validThrough: string;
|
|
11
|
+
readonly revision: string;
|
|
12
|
+
readonly source: string;
|
|
13
|
+
readonly postures: readonly string[];
|
|
14
|
+
readonly environmentPostures: Readonly<{
|
|
15
|
+
addressing: AddressingPosture | null;
|
|
16
|
+
authentication: AuthPosture | null;
|
|
17
|
+
}>;
|
|
18
|
+
readonly postureRequirements: readonly Readonly<{
|
|
19
|
+
requirement: string;
|
|
20
|
+
addressing?: AddressingPosture;
|
|
21
|
+
authentication?: AuthPosture;
|
|
22
|
+
}>[];
|
|
23
|
+
}
|
|
24
|
+
interface ObservationPostureInput {
|
|
25
|
+
readonly configuration: EnvironmentObservation;
|
|
26
|
+
readonly cockpitId: CockpitId;
|
|
27
|
+
readonly checkoutPath: string;
|
|
28
|
+
readonly variant: StackVariant;
|
|
29
|
+
}
|
|
30
|
+
export declare function resolveObservationPostures(input: ObservationPostureInput): Promise<ResolvedPostureAuthority>;
|
|
31
|
+
export declare function refreshObservationPostures(input: ObservationPostureInput & {
|
|
32
|
+
readonly previous: ResolvedPostureAuthority;
|
|
33
|
+
}): Promise<ResolvedPostureAuthority>;
|
|
34
|
+
export interface PreflightContext {
|
|
35
|
+
readonly authorities: readonly ResolvedPostureAuthority[];
|
|
36
|
+
readonly stages: readonly LifecycleStageAuthority[];
|
|
37
|
+
}
|
|
38
|
+
interface PostureRequirementCheck {
|
|
39
|
+
readonly code: EnvironmentObservation['code'];
|
|
40
|
+
readonly owner: string;
|
|
41
|
+
readonly stackId: StackId;
|
|
42
|
+
readonly source: string;
|
|
43
|
+
readonly verdict: 'pass' | 'fail';
|
|
44
|
+
readonly reason: string;
|
|
45
|
+
readonly remedy: string;
|
|
46
|
+
readonly observedAt: string;
|
|
47
|
+
readonly measured?: JsonSnapshot;
|
|
48
|
+
readonly expected: EnvironmentObservation['expectation'];
|
|
49
|
+
}
|
|
50
|
+
export type PostureDimension = 'addressing' | 'authentication';
|
|
51
|
+
/**
|
|
52
|
+
* Whether each selected posture is named by the requirements that depend on it, and every tag agrees.
|
|
53
|
+
* Preflight gates on this; init applies it to an operator's posture answer so a draft that can never
|
|
54
|
+
* pass preflight is refused while the operator is still answering.
|
|
55
|
+
*/
|
|
56
|
+
export declare function judgePostureDeclaration(postures: ResolvedPostureAuthority['environmentPostures'], requirements: ResolvedPostureAuthority['postureRequirements']): readonly Readonly<{
|
|
57
|
+
dimension: PostureDimension;
|
|
58
|
+
selected: AddressingPosture | AuthPosture | null;
|
|
59
|
+
pass: boolean;
|
|
60
|
+
reason: string;
|
|
61
|
+
}>[];
|
|
62
|
+
export declare function authenticateObservationPostureContext(context: PreflightContext): {
|
|
63
|
+
evaluationInstant: number;
|
|
64
|
+
authorities: Map<StackId, ResolvedPostureAuthority>;
|
|
65
|
+
stages: Map<StackId, "bootstrap" | "steady">;
|
|
66
|
+
checks: PostureRequirementCheck[];
|
|
67
|
+
};
|
|
68
|
+
export {};
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
// Owns current configuration posture and lifecycle context authentication for health and browser use.
|
|
2
|
+
// Keeps producer declarations and verdict aggregation in observations.ts so browser preparation cannot
|
|
3
|
+
// depend on the generated publication it is preparing.
|
|
4
|
+
import { createHash } from 'node:crypto';
|
|
5
|
+
import { closeSync, constants, fstatSync, lstatSync, openSync, readSync } from 'node:fs';
|
|
6
|
+
import { realpath } from 'node:fs/promises';
|
|
7
|
+
import { dirname, isAbsolute, normalize, relative, sep } from 'node:path';
|
|
8
|
+
import { loadCockpitConfig } from '../config/load.js';
|
|
9
|
+
import { STRUCTURED_INPUT_ENTRY_LIMIT } from '../schema.js';
|
|
10
|
+
import { ENVIRONMENT_CODES, errorCause, snapshotJson, RefusalError } from './contract.js';
|
|
11
|
+
import { checkoutId, stackId as deriveStackId } from './identity.js';
|
|
12
|
+
import { authenticateLifecycleStageAuthority } from './lifecycle-stage.js';
|
|
13
|
+
import { isStateObservation } from './state.js';
|
|
14
|
+
/** The owner of the posture-requirement checks preflight derives from the declared postures. */
|
|
15
|
+
export const POSTURE_REQUIREMENT_OWNER = 'posture-requirements';
|
|
16
|
+
const compareCodeUnits = (left, right) => left < right ? -1 : left > right ? 1 : 0;
|
|
17
|
+
function boundedArray(value) {
|
|
18
|
+
return Array.isArray(value) && value.length <= STRUCTURED_INPUT_ENTRY_LIMIT ? value : undefined;
|
|
19
|
+
}
|
|
20
|
+
const issuedPostureAuthorities = new WeakMap();
|
|
21
|
+
const postureRefreshWindows = new WeakMap();
|
|
22
|
+
const POSTURE_AUTHORITY_LIFETIME_MS = 30_000;
|
|
23
|
+
const PREFLIGHT_OBSERVATION_WINDOW_MS = 300_000;
|
|
24
|
+
const CONFIGURATION_BYTE_LIMIT = 1_048_576;
|
|
25
|
+
function currentConfigurationRevision(path) {
|
|
26
|
+
let descriptor;
|
|
27
|
+
try {
|
|
28
|
+
const before = lstatSync(path, { bigint: true });
|
|
29
|
+
if (!before.isFile() || before.isSymbolicLink() || before.nlink !== 1n || before.size > BigInt(CONFIGURATION_BYTE_LIMIT))
|
|
30
|
+
return undefined;
|
|
31
|
+
descriptor = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
32
|
+
const opened = fstatSync(descriptor, { bigint: true });
|
|
33
|
+
if (!opened.isFile() || opened.nlink !== 1n || opened.dev !== before.dev || opened.ino !== before.ino
|
|
34
|
+
|| opened.size > BigInt(CONFIGURATION_BYTE_LIMIT))
|
|
35
|
+
return undefined;
|
|
36
|
+
const hash = createHash('sha256');
|
|
37
|
+
const buffer = Buffer.allocUnsafe(65_536);
|
|
38
|
+
let total = 0;
|
|
39
|
+
while (true) {
|
|
40
|
+
const count = readSync(descriptor, buffer, 0, Math.min(buffer.length, CONFIGURATION_BYTE_LIMIT - total + 1), null);
|
|
41
|
+
if (count === 0)
|
|
42
|
+
break;
|
|
43
|
+
total += count;
|
|
44
|
+
if (total > CONFIGURATION_BYTE_LIMIT)
|
|
45
|
+
return undefined;
|
|
46
|
+
hash.update(buffer.subarray(0, count));
|
|
47
|
+
}
|
|
48
|
+
const after = fstatSync(descriptor, { bigint: true });
|
|
49
|
+
const named = lstatSync(path, { bigint: true });
|
|
50
|
+
if (!named.isFile() || named.isSymbolicLink() || named.dev !== opened.dev || named.ino !== opened.ino
|
|
51
|
+
|| after.dev !== opened.dev || after.ino !== opened.ino || after.size !== opened.size || named.size !== opened.size
|
|
52
|
+
|| after.mtimeNs !== opened.mtimeNs || after.ctimeNs !== opened.ctimeNs || total !== Number(opened.size))
|
|
53
|
+
return undefined;
|
|
54
|
+
return hash.digest('hex');
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
throw new RefusalError(`configuration could not be re-read after posture resolution: ${errorCause(error)}`);
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
if (descriptor !== undefined) {
|
|
61
|
+
try {
|
|
62
|
+
closeSync(descriptor);
|
|
63
|
+
}
|
|
64
|
+
catch { /* A failed identity check grants no authority. */ }
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function issueObservationPostures(input, previous) {
|
|
69
|
+
const configuration = input?.configuration;
|
|
70
|
+
const owned = snapshotJson({ cockpitId: input.cockpitId, checkoutPath: input.checkoutPath, variant: input.variant });
|
|
71
|
+
const identity = owned && typeof owned === 'object' && !Array.isArray(owned)
|
|
72
|
+
? owned
|
|
73
|
+
: undefined;
|
|
74
|
+
let expectedStackId;
|
|
75
|
+
let canonicalCheckoutPath;
|
|
76
|
+
try {
|
|
77
|
+
if (!identity || typeof identity.cockpitId !== 'string' || typeof identity.checkoutPath !== 'string'
|
|
78
|
+
|| normalize(identity.checkoutPath) !== identity.checkoutPath)
|
|
79
|
+
throw new RefusalError('invalid identity');
|
|
80
|
+
canonicalCheckoutPath = await realpath(identity.checkoutPath);
|
|
81
|
+
expectedStackId = deriveStackId({
|
|
82
|
+
cockpitId: identity.cockpitId,
|
|
83
|
+
checkoutId: checkoutId({ checkoutPath: canonicalCheckoutPath }),
|
|
84
|
+
variant: identity.variant,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
throw new RefusalError('resolved posture configuration source is malformed');
|
|
89
|
+
}
|
|
90
|
+
const issuedAt = Date.now();
|
|
91
|
+
const observedAt = configuration && typeof configuration === 'object'
|
|
92
|
+
&& 'observed' in configuration && configuration.observed.state === 'available'
|
|
93
|
+
? Date.parse(configuration.observed.observedAt)
|
|
94
|
+
: Number.NaN;
|
|
95
|
+
if (!isStateObservation(configuration)
|
|
96
|
+
|| configuration.code !== ENVIRONMENT_CODES.CONFIG_STALE
|
|
97
|
+
|| configuration.observed.state !== 'available'
|
|
98
|
+
|| configuration.stackId !== expectedStackId
|
|
99
|
+
|| observedAt > issuedAt
|
|
100
|
+
|| issuedAt - observedAt > 30_000) {
|
|
101
|
+
throw new RefusalError('resolved posture configuration source is malformed');
|
|
102
|
+
}
|
|
103
|
+
const configurationRoot = relative(canonicalCheckoutPath, dirname(configuration.source));
|
|
104
|
+
if (configurationRoot === '..' || configurationRoot.startsWith(`..${sep}`) || isAbsolute(configurationRoot)) {
|
|
105
|
+
throw new RefusalError('resolved posture configuration source is malformed');
|
|
106
|
+
}
|
|
107
|
+
const loaded = await loadCockpitConfig(configuration.source);
|
|
108
|
+
if (loaded.kind !== 'complete')
|
|
109
|
+
throw new RefusalError('resolved posture configuration source is unavailable');
|
|
110
|
+
if (loaded.result.source.path !== configuration.source || loaded.result.source.sha256 !== configuration.observed.value) {
|
|
111
|
+
throw new RefusalError('resolved posture configuration changed after observation');
|
|
112
|
+
}
|
|
113
|
+
const previousWindow = previous === undefined ? undefined : postureRefreshWindows.get(previous);
|
|
114
|
+
if (previous !== undefined && (!previousWindow || previousWindow.cockpitId !== identity.cockpitId
|
|
115
|
+
|| previous.stackId !== configuration.stackId || previous.source !== loaded.result.source.path
|
|
116
|
+
|| previous.revision !== loaded.result.source.sha256)) {
|
|
117
|
+
throw new RefusalError('resolved posture refresh does not match its initial authority');
|
|
118
|
+
}
|
|
119
|
+
const evaluatedAt = previous?.evaluatedAt ?? configuration.observed.observedAt;
|
|
120
|
+
const windowExpiresAt = previousWindow?.expiresAt ?? Date.parse(evaluatedAt) + PREFLIGHT_OBSERVATION_WINDOW_MS;
|
|
121
|
+
if (!Number.isSafeInteger(windowExpiresAt) || issuedAt > windowExpiresAt) {
|
|
122
|
+
throw new RefusalError('resolved posture refresh window expired');
|
|
123
|
+
}
|
|
124
|
+
const postures = new Set(['environment']);
|
|
125
|
+
if (loaded.result.config.environment.machine)
|
|
126
|
+
postures.add('machine-floor');
|
|
127
|
+
if (loaded.result.config.environment.compose_files.length > 0)
|
|
128
|
+
postures.add('running-stack');
|
|
129
|
+
if (loaded.result.config.sibling.some(({ mount }) => mount === 'always'))
|
|
130
|
+
postures.add('directory-grants');
|
|
131
|
+
for (const sibling of loaded.result.config.sibling) {
|
|
132
|
+
if (sibling.mount === 'none')
|
|
133
|
+
continue;
|
|
134
|
+
if (sibling.mount === 'host')
|
|
135
|
+
postures.add('host');
|
|
136
|
+
else
|
|
137
|
+
postures.add('mounted');
|
|
138
|
+
}
|
|
139
|
+
const authority = {
|
|
140
|
+
stackId: configuration.stackId,
|
|
141
|
+
evaluatedAt,
|
|
142
|
+
validThrough: new Date(Math.min(issuedAt + POSTURE_AUTHORITY_LIFETIME_MS, windowExpiresAt)).toISOString(),
|
|
143
|
+
revision: loaded.result.source.sha256,
|
|
144
|
+
source: loaded.result.source.path,
|
|
145
|
+
postures: [...postures].sort(compareCodeUnits),
|
|
146
|
+
environmentPostures: {
|
|
147
|
+
addressing: loaded.result.config.environment.addressing ?? null,
|
|
148
|
+
authentication: loaded.result.config.environment.authentication ?? null,
|
|
149
|
+
},
|
|
150
|
+
postureRequirements: (loaded.result.config.environment.posture_requirements ?? [])
|
|
151
|
+
.map((requirement) => ({ ...requirement })),
|
|
152
|
+
};
|
|
153
|
+
issuedPostureAuthorities.set(authority, identity.cockpitId);
|
|
154
|
+
postureRefreshWindows.set(authority, Object.freeze({ cockpitId: identity.cockpitId, expiresAt: windowExpiresAt }));
|
|
155
|
+
return authority;
|
|
156
|
+
}
|
|
157
|
+
export async function resolveObservationPostures(input) {
|
|
158
|
+
return issueObservationPostures(input);
|
|
159
|
+
}
|
|
160
|
+
export async function refreshObservationPostures(input) {
|
|
161
|
+
const previous = input?.previous;
|
|
162
|
+
if (!previous)
|
|
163
|
+
throw new RefusalError('resolved posture refresh requires initial authority');
|
|
164
|
+
return issueObservationPostures(input, previous);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Whether each selected posture is named by the requirements that depend on it, and every tag agrees.
|
|
168
|
+
* Preflight gates on this; init applies it to an operator's posture answer so a draft that can never
|
|
169
|
+
* pass preflight is refused while the operator is still answering.
|
|
170
|
+
*/
|
|
171
|
+
export function judgePostureDeclaration(postures, requirements) {
|
|
172
|
+
return ['addressing', 'authentication'].map((dimension) => {
|
|
173
|
+
const selected = postures[dimension];
|
|
174
|
+
const tagged = requirements.filter((requirement) => requirement[dimension] !== undefined);
|
|
175
|
+
// A stack with no sign-in has nothing that depends on one, so it needs no tagged requirement.
|
|
176
|
+
const untaggedNone = selected === 'none' && tagged.length === 0 && requirements.length > 0;
|
|
177
|
+
const matched = selected !== null && tagged.some((requirement) => requirement[dimension] === selected);
|
|
178
|
+
const pass = untaggedNone || matched && tagged.every((requirement) => requirement[dimension] === selected);
|
|
179
|
+
const reason = selected === null
|
|
180
|
+
? `${dimension} posture is not declared`
|
|
181
|
+
: requirements.length === 0
|
|
182
|
+
? 'posture requirement catalog is not declared'
|
|
183
|
+
: untaggedNone ? 'no authentication is declared, and no requirement depends on one'
|
|
184
|
+
: tagged.length === 0
|
|
185
|
+
? `${dimension} posture ${selected} is not named by a requirement`
|
|
186
|
+
: !pass ? `${dimension} requirement tags do not match selected posture ${selected}`
|
|
187
|
+
: 'declared requirement tags match the selected posture';
|
|
188
|
+
return { dimension, selected, pass, reason };
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
export function authenticateObservationPostureContext(context) {
|
|
192
|
+
const evaluationInstant = Date.now();
|
|
193
|
+
const authorityInputs = boundedArray(context?.authorities);
|
|
194
|
+
const stageInputs = boundedArray(context?.stages);
|
|
195
|
+
if (!authorityInputs || authorityInputs.length === 0)
|
|
196
|
+
throw new RefusalError('preflight needs resolved posture authority');
|
|
197
|
+
const authorities = new Map();
|
|
198
|
+
let windowStart = Number.NEGATIVE_INFINITY;
|
|
199
|
+
let windowEnd = Number.POSITIVE_INFINITY;
|
|
200
|
+
for (const authorityInput of authorityInputs) {
|
|
201
|
+
const authority = authorityInput;
|
|
202
|
+
const cockpitId = issuedPostureAuthorities.get(authority);
|
|
203
|
+
if (!cockpitId)
|
|
204
|
+
throw new RefusalError('preflight needs resolved posture authority');
|
|
205
|
+
if (authorities.has(authority.stackId))
|
|
206
|
+
throw new RefusalError('preflight contains duplicate posture authority');
|
|
207
|
+
const currentRevision = currentConfigurationRevision(authority.source);
|
|
208
|
+
if (currentRevision !== authority.revision)
|
|
209
|
+
throw new RefusalError('configuration changed after posture resolution');
|
|
210
|
+
const authorityStart = Date.parse(authority.evaluatedAt);
|
|
211
|
+
const authorityEnd = Date.parse(authority.validThrough);
|
|
212
|
+
if (!Number.isFinite(authorityStart) || !Number.isFinite(authorityEnd) || authorityStart > authorityEnd)
|
|
213
|
+
throw new RefusalError('preflight posture authorities are incoherent');
|
|
214
|
+
if (evaluationInstant > authorityEnd)
|
|
215
|
+
throw new RefusalError('preflight posture authority has expired');
|
|
216
|
+
authorities.set(authority.stackId, authority);
|
|
217
|
+
windowStart = Math.max(windowStart, authorityStart);
|
|
218
|
+
windowEnd = Math.min(windowEnd, authorityEnd);
|
|
219
|
+
}
|
|
220
|
+
if (windowStart > windowEnd)
|
|
221
|
+
throw new RefusalError('preflight posture authorities are incoherent');
|
|
222
|
+
if (!stageInputs || stageInputs.length !== authorityInputs.length)
|
|
223
|
+
throw new RefusalError('preflight needs lifecycle stage authority');
|
|
224
|
+
const stages = new Map();
|
|
225
|
+
for (const stageInput of stageInputs) {
|
|
226
|
+
if (stageInput === null || typeof stageInput !== 'object')
|
|
227
|
+
throw new RefusalError('preflight needs lifecycle stage authority');
|
|
228
|
+
const stageStackId = stageInput.stackId;
|
|
229
|
+
const authority = typeof stageStackId === 'string' ? authorities.get(stageStackId) : undefined;
|
|
230
|
+
if (!authority || stages.has(authority.stackId))
|
|
231
|
+
throw new RefusalError('preflight needs one matching lifecycle stage authority per stack');
|
|
232
|
+
const stage = authenticateLifecycleStageAuthority(stageInput, authority.stackId, issuedPostureAuthorities.get(authority), Date.parse(authority.evaluatedAt), Date.parse(authority.validThrough), evaluationInstant);
|
|
233
|
+
if (!stage)
|
|
234
|
+
throw new RefusalError('preflight needs authentic lifecycle stage authority');
|
|
235
|
+
stages.set(authority.stackId, stage);
|
|
236
|
+
}
|
|
237
|
+
if (stages.size !== authorities.size)
|
|
238
|
+
throw new RefusalError('preflight needs one matching lifecycle stage authority per stack');
|
|
239
|
+
const postureChecks = [...authorities.values()].flatMap((authority) => judgePostureDeclaration(authority.environmentPostures, authority.postureRequirements).map(({ dimension, selected, pass, reason }) => ({
|
|
240
|
+
code: ENVIRONMENT_CODES.EVIDENCE_UNAVAILABLE,
|
|
241
|
+
owner: POSTURE_REQUIREMENT_OWNER,
|
|
242
|
+
stackId: authority.stackId,
|
|
243
|
+
source: `${authority.source}:${dimension}`,
|
|
244
|
+
verdict: pass ? 'pass' : 'fail',
|
|
245
|
+
reason,
|
|
246
|
+
remedy: `declare ${dimension} and tag every dependent requirement with the same posture`,
|
|
247
|
+
observedAt: authority.evaluatedAt,
|
|
248
|
+
...(selected === null ? {} : { measured: selected }),
|
|
249
|
+
expected: { kind: 'present' },
|
|
250
|
+
})));
|
|
251
|
+
return { evaluationInstant, authorities, stages,
|
|
252
|
+
checks: postureChecks };
|
|
253
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ExecuteProbeOutcome } from '../environment-exec/execute.js';
|
|
2
|
+
import { type RuntimeEvidenceObservation } from './application/health.js';
|
|
3
|
+
import { type LogsCommandAdapters } from './application/logs.js';
|
|
4
|
+
import { type ExecutionStep } from './contract.js';
|
|
5
|
+
import { type RuntimeMeasurementProbeAuthority } from './runtime.js';
|
|
6
|
+
export interface ReadCommandCompositionInput {
|
|
7
|
+
readonly configPath: string;
|
|
8
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
9
|
+
readonly sessionId: string;
|
|
10
|
+
readonly timeoutMs: number;
|
|
11
|
+
readonly outputLimitBytes?: number;
|
|
12
|
+
readonly signal?: AbortSignal;
|
|
13
|
+
readonly runtimeMeasurementProbeAuthority?: RuntimeMeasurementProbeAuthority;
|
|
14
|
+
}
|
|
15
|
+
export interface ReadCommandAdapterComposition {
|
|
16
|
+
readonly logs: LogsCommandAdapters;
|
|
17
|
+
readonly environment: Readonly<{
|
|
18
|
+
observe: (input: {
|
|
19
|
+
readonly configPath: string;
|
|
20
|
+
}) => Promise<RuntimeEvidenceObservation>;
|
|
21
|
+
}>;
|
|
22
|
+
}
|
|
23
|
+
type Executor = (step: ExecutionStep, options?: {
|
|
24
|
+
readonly signal?: AbortSignal;
|
|
25
|
+
}) => Promise<ExecuteProbeOutcome>;
|
|
26
|
+
export declare function createReadCommandAdapters(rawInput: ReadCommandCompositionInput, execute: Executor): ReadCommandAdapterComposition;
|
|
27
|
+
export {};
|