bootproof 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/LICENSE +201 -0
- package/README.md +265 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +402 -0
- package/dist/diagnosis.d.ts +7 -0
- package/dist/diagnosis.js +139 -0
- package/dist/exec.d.ts +29 -0
- package/dist/exec.js +125 -0
- package/dist/infer.d.ts +4 -0
- package/dist/infer.js +432 -0
- package/dist/plan.d.ts +7 -0
- package/dist/plan.js +94 -0
- package/dist/platform.d.ts +3 -0
- package/dist/platform.js +23 -0
- package/dist/proof.d.ts +24 -0
- package/dist/proof.js +104 -0
- package/dist/redact.d.ts +4 -0
- package/dist/redact.js +31 -0
- package/dist/registry.d.ts +38 -0
- package/dist/registry.js +70 -0
- package/dist/remote.d.ts +13 -0
- package/dist/remote.js +73 -0
- package/dist/run.d.ts +23 -0
- package/dist/run.js +198 -0
- package/dist/taxonomy.d.ts +6 -0
- package/dist/taxonomy.js +68 -0
- package/dist/types.d.ts +117 -0
- package/dist/types.js +7 -0
- package/docs/CI_ACTION.md +75 -0
- package/docs/FAILURE_TAXONOMY.md +55 -0
- package/docs/HONESTY_CONTRACT.md +86 -0
- package/docs/REAL_REPO_EVIDENCE.md +72 -0
- package/docs/REGISTRY.md +49 -0
- package/docs/RELEASE_CHECKLIST.md +74 -0
- package/package.json +52 -0
package/dist/taxonomy.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
function classifyHealthFailure(evidence) {
|
|
2
|
+
if (/(only HTTP 5\d\d observed|HTTP 5\d\d|status\s*5\d\d|returned 5\d\d)/i.test(evidence)) {
|
|
3
|
+
return "health_http_error";
|
|
4
|
+
}
|
|
5
|
+
return "health_check_timeout";
|
|
6
|
+
}
|
|
7
|
+
function isServicePortAllocatedEvidence(evidence) {
|
|
8
|
+
const lower = evidence.toLowerCase();
|
|
9
|
+
return (lower.includes("port is already allocated") ||
|
|
10
|
+
lower.includes("bind for 0.0.0.0:") ||
|
|
11
|
+
lower.includes("failed programming external connectivity") ||
|
|
12
|
+
lower.includes("ports are not available") ||
|
|
13
|
+
lower.includes("address already in use"));
|
|
14
|
+
}
|
|
15
|
+
const RULES = [
|
|
16
|
+
{ class: "package_manager_version_mismatch", pattern: /(ERR_PNPM_UNSUPPORTED_ENGINE|Unsupported environment \(bad (?:pnpm|yarn|npm|bun) and\/or Node\.js version\)|(?:pnpm|yarn|npm|bun)[\s\S]{0,160}Expected version:\s*[^\n]+[\s\S]{0,120}Got:\s*[^\n]+|packageManager field[\s\S]{0,120}(?:version|mismatch)|engines\.(?:pnpm|yarn|npm|bun))/i,
|
|
17
|
+
explain: () => "The repository declares a package manager version that does not match the version available in the current environment. Enable Corepack or install the required package manager version before rerunning BootProof." },
|
|
18
|
+
{ class: "runtime_engine_mismatch", pattern: /(Node version .{0,40}doesn'?t (?:satisfy|match)|The engine "node" is incompatible|EBADENGINE|required:\s*\{\s*node)/i,
|
|
19
|
+
explain: () => "The host Node version does not satisfy the project's engines requirement. Switch Node versions (nvm/fnm/corepack) and retry." },
|
|
20
|
+
{ class: "missing_package_manager", pattern: /\b(yarn|pnpm|bun): (command )?not found/i,
|
|
21
|
+
explain: m => `The project needs ${m[1]} and it is not installed. Enable Corepack (corepack enable) or install ${m[1]} directly.` },
|
|
22
|
+
{ class: "private_registry_or_auth", pattern: /(401 Unauthorized|E401|ENEEDAUTH|authentication token not provided|Permission.*registry)/i,
|
|
23
|
+
explain: () => "Dependency install needs credentials for a private registry. Bootproof will not invent credentials; provide real ones and retry." },
|
|
24
|
+
{ class: "native_build_dependency", pattern: /(node-gyp|gyp ERR|pg_config.*not found|fatal error: .*\.h|prebuild-install)/i,
|
|
25
|
+
explain: () => "A dependency needs a native toolchain or OS package that is missing on this machine." },
|
|
26
|
+
{ class: "port_in_use", pattern: /(EADDRINUSE|[Pp]ort \d+ is (already )?in use)/,
|
|
27
|
+
explain: () => "The app port is occupied by another process. Stop it or run with a different PORT." },
|
|
28
|
+
{ class: "postgres_auth_env_missing", pattern: /(SASL: SCRAM-SERVER-FIRST-MESSAGE|password authentication failed for user|client password must be a string)/i,
|
|
29
|
+
explain: () => "Postgres was reached but authentication failed — the app's DATABASE_URL credentials don't match the running database. Inspect the repository's own env and compose examples, or rerun after generating BootProof service scaffolding; bootproof will not edit your .env." },
|
|
30
|
+
{ class: "database_unreachable", pattern: /(ECONNREFUSED.*:(5432|3306|6379|27017)|P1001|Can'?t reach database server|Connection refused.*postgres)/i,
|
|
31
|
+
explain: () => "The app requires a database that is not reachable. Start the generated docker-compose.bootproof.yml services first." },
|
|
32
|
+
{ class: "migrations_missing", pattern: /(relation .* does not exist|no such table|Migration.*pending|P3009)/i,
|
|
33
|
+
explain: () => "The database schema is missing or behind. Run the project's migration command against the local database." },
|
|
34
|
+
{ class: "missing_env_var", pattern: /((Missing|Please set|required) (env(ironment)? var(iable)?s?|.*[A-Z][A-Z0-9_]{3,})|Invalid environment variables)/,
|
|
35
|
+
explain: () => "The app refuses to start without specific environment variables. See .env.bootproof.example; secrets without safe defaults must come from you." },
|
|
36
|
+
{ class: "tls_or_proxy_interception", pattern: /(SELF_SIGNED_CERT_IN_CHAIN|UNABLE_TO_VERIFY_LEAF_SIGNATURE|unable to get local issuer certificate)/,
|
|
37
|
+
explain: () => "A TLS-intercepting proxy or self-signed certificate chain is blocking package/tool downloads. Configure your proxy CA (NODE_EXTRA_CA_CERTS) or run outside the intercepting network." },
|
|
38
|
+
{ class: "service_port_allocated", pattern: /(port is already allocated|Bind for 0\.0\.0\.0:\d+ failed|failed programming external connectivity|Ports are not available)/i,
|
|
39
|
+
explain: () => "Docker is available, but a required service port is already allocated by another local process or container. Stop the process using that port, or rerun with a different service port." },
|
|
40
|
+
{ class: "docker_unavailable", pattern: /(Cannot connect to the Docker daemon|docker: (command )?not found|docker daemon is not running|error during connect)/i,
|
|
41
|
+
explain: () => "Docker is not available, and this plan needs it for services. Start Docker, or rerun with --provider local --unsafe-local if the app needs no containers." },
|
|
42
|
+
{ class: "health_http_error", pattern: /(only HTTP 5\d\d observed|HTTP 5\d\d|status\s*5\d\d|returned 5\d\d)/i,
|
|
43
|
+
explain: () => "The app responded on the configured health URL, but returned HTTP 5xx. BootProof observed a running server, but not a verified healthy boot." },
|
|
44
|
+
];
|
|
45
|
+
export function classifyFailure(evidence) {
|
|
46
|
+
if (isServicePortAllocatedEvidence(evidence) && /(docker|container|bind for|external connectivity|ports are not available|port is already allocated)/i.test(evidence)) {
|
|
47
|
+
return {
|
|
48
|
+
class: "service_port_allocated",
|
|
49
|
+
explanation: "Docker is available, but a required service port is already allocated by another local process or container. Stop the process using that port, or rerun with a different service port.",
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
for (const rule of RULES) {
|
|
53
|
+
const m = evidence.match(rule.pattern);
|
|
54
|
+
if (m)
|
|
55
|
+
return { class: rule.class, explanation: rule.explain(m) };
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
class: "unknown_failure",
|
|
59
|
+
explanation: "Bootproof could not classify this failure. The raw evidence is preserved in the attestation — please open an issue with it so this becomes a new detector.",
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export const TAXONOMY_DOC_CLASSES = [
|
|
63
|
+
"not_an_application", "runtime_engine_mismatch", "missing_package_manager", "package_manager_version_mismatch",
|
|
64
|
+
"dependency_install_skipped", "python_flask_setup_required", "missing_env_var",
|
|
65
|
+
"database_unreachable", "postgres_auth_env_missing", "migrations_missing", "port_in_use", "native_build_dependency",
|
|
66
|
+
"private_registry_or_auth", "tls_or_proxy_interception", "service_port_allocated", "docker_unavailable", "install_failed", "app_exited_early",
|
|
67
|
+
"health_check_timeout", "health_http_error", "workspace_ambiguous", "unknown_failure",
|
|
68
|
+
];
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
export type PackageManager = "npm" | "pnpm" | "yarn" | "bun" | "unknown";
|
|
2
|
+
export type FailureClass = "not_an_application" | "runtime_engine_mismatch" | "missing_package_manager" | "package_manager_version_mismatch" | "dependency_install_skipped" | "python_flask_setup_required" | "missing_env_var" | "database_unreachable" | "postgres_auth_env_missing" | "migrations_missing" | "port_in_use" | "native_build_dependency" | "private_registry_or_auth" | "tls_or_proxy_interception" | "service_port_allocated" | "docker_unavailable" | "install_failed" | "app_exited_early" | "health_check_timeout" | "health_http_error" | "workspace_ambiguous" | "unknown_failure";
|
|
3
|
+
export interface ServiceNeed {
|
|
4
|
+
kind: "postgres" | "mysql" | "redis" | "mongodb";
|
|
5
|
+
evidence: string;
|
|
6
|
+
}
|
|
7
|
+
export interface WorkspaceCandidate {
|
|
8
|
+
dir: string;
|
|
9
|
+
name: string;
|
|
10
|
+
score: number;
|
|
11
|
+
reason: string;
|
|
12
|
+
}
|
|
13
|
+
export interface Inference {
|
|
14
|
+
repoPath: string;
|
|
15
|
+
isApplication: boolean;
|
|
16
|
+
notAppReason?: string;
|
|
17
|
+
stack: string[];
|
|
18
|
+
backendMarkers: string[];
|
|
19
|
+
frontendMarkers: string[];
|
|
20
|
+
serviceMarkers: string[];
|
|
21
|
+
setupSteps: string[];
|
|
22
|
+
packageManager: PackageManager;
|
|
23
|
+
packageManagerEvidence: string;
|
|
24
|
+
packageManagerVersion: string | null;
|
|
25
|
+
installCommand: string | null;
|
|
26
|
+
dependencyInstallRequired: boolean;
|
|
27
|
+
appCommand: string | null;
|
|
28
|
+
appCommandSource: string;
|
|
29
|
+
backendCommand: string | null;
|
|
30
|
+
frontendCommand: string | null;
|
|
31
|
+
workerCommand: string | null;
|
|
32
|
+
commandScope: string;
|
|
33
|
+
incompleteAppCommand: boolean;
|
|
34
|
+
multiAppCommand: boolean;
|
|
35
|
+
port: number;
|
|
36
|
+
portEvidence: string;
|
|
37
|
+
healthCandidates: string[];
|
|
38
|
+
services: ServiceNeed[];
|
|
39
|
+
requiredEnv: string[];
|
|
40
|
+
envWithoutSafeDefault: string[];
|
|
41
|
+
engines: {
|
|
42
|
+
node?: string;
|
|
43
|
+
npm?: string;
|
|
44
|
+
pnpm?: string;
|
|
45
|
+
yarn?: string;
|
|
46
|
+
bun?: string;
|
|
47
|
+
};
|
|
48
|
+
workspaces: WorkspaceCandidate[];
|
|
49
|
+
confidence: number;
|
|
50
|
+
}
|
|
51
|
+
export interface PlanStep {
|
|
52
|
+
id: string;
|
|
53
|
+
kind: "install" | "service" | "start-app" | "health";
|
|
54
|
+
command?: string;
|
|
55
|
+
description: string;
|
|
56
|
+
required: boolean;
|
|
57
|
+
}
|
|
58
|
+
export interface RunPlan {
|
|
59
|
+
provider: "docker" | "local";
|
|
60
|
+
steps: PlanStep[];
|
|
61
|
+
healthUrl: string;
|
|
62
|
+
healthCandidates: string[];
|
|
63
|
+
generatedFiles: {
|
|
64
|
+
path: string;
|
|
65
|
+
purpose: string;
|
|
66
|
+
}[];
|
|
67
|
+
}
|
|
68
|
+
export interface ObservedStep {
|
|
69
|
+
id: string;
|
|
70
|
+
kind: PlanStep["kind"];
|
|
71
|
+
command?: string;
|
|
72
|
+
startedAt: string;
|
|
73
|
+
finishedAt: string;
|
|
74
|
+
exitCode: number | null;
|
|
75
|
+
ok: boolean;
|
|
76
|
+
observation: string;
|
|
77
|
+
evidenceTail?: string;
|
|
78
|
+
}
|
|
79
|
+
export interface AttestationTrust {
|
|
80
|
+
level: "local_developer_signed" | "ci_oidc_signed";
|
|
81
|
+
signer: "local_ed25519" | "ci_oidc";
|
|
82
|
+
oidc: Record<string, string> | null;
|
|
83
|
+
}
|
|
84
|
+
export interface Attestation {
|
|
85
|
+
schema: "bootproof/attestation/v1";
|
|
86
|
+
tool: string;
|
|
87
|
+
repo: {
|
|
88
|
+
path: string;
|
|
89
|
+
remote: string | null;
|
|
90
|
+
commit: string | null;
|
|
91
|
+
dirty: boolean | null;
|
|
92
|
+
};
|
|
93
|
+
environment: {
|
|
94
|
+
os: string;
|
|
95
|
+
arch: string;
|
|
96
|
+
node: string;
|
|
97
|
+
};
|
|
98
|
+
trust: AttestationTrust;
|
|
99
|
+
plan: RunPlan;
|
|
100
|
+
observed: ObservedStep[];
|
|
101
|
+
result: {
|
|
102
|
+
booted: boolean;
|
|
103
|
+
healthVerified: boolean;
|
|
104
|
+
healthObservation: string | null;
|
|
105
|
+
observedHealthCandidates: string[];
|
|
106
|
+
failureClass: FailureClass | null;
|
|
107
|
+
failureEvidence: string | null;
|
|
108
|
+
explanation: string;
|
|
109
|
+
};
|
|
110
|
+
startedAt: string;
|
|
111
|
+
finishedAt: string;
|
|
112
|
+
signer: {
|
|
113
|
+
publicKey: string;
|
|
114
|
+
algorithm: "ed25519";
|
|
115
|
+
} | null;
|
|
116
|
+
signature: string | null;
|
|
117
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# CI Usage
|
|
2
|
+
|
|
3
|
+
BootProof has a fail-closed machine interface:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
bootproof up . --ci --json
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Exit `0` means both `booted` and `healthVerified` are true. Every refusal or failure exits `1`.
|
|
10
|
+
|
|
11
|
+
## GitHub Actions Example
|
|
12
|
+
|
|
13
|
+
This example records the JSON result and preserves the signed attestation even when verification fails:
|
|
14
|
+
|
|
15
|
+
```yaml
|
|
16
|
+
name: bootproof
|
|
17
|
+
|
|
18
|
+
on:
|
|
19
|
+
push:
|
|
20
|
+
branches: [main]
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
bootproof:
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
permissions:
|
|
26
|
+
contents: read
|
|
27
|
+
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v4
|
|
30
|
+
- uses: actions/setup-node@v4
|
|
31
|
+
with:
|
|
32
|
+
node-version: "22"
|
|
33
|
+
|
|
34
|
+
- run: npm install --global bootproof
|
|
35
|
+
|
|
36
|
+
- name: Run BootProof
|
|
37
|
+
id: bootproof
|
|
38
|
+
continue-on-error: true
|
|
39
|
+
shell: bash
|
|
40
|
+
run: |
|
|
41
|
+
mkdir -p .bootproof
|
|
42
|
+
set +e
|
|
43
|
+
bootproof up . --provider local --unsafe-local --install --timeout 120000 --ci --json \
|
|
44
|
+
| tee .bootproof/result.json
|
|
45
|
+
code=${PIPESTATUS[0]}
|
|
46
|
+
echo "exit_code=$code" >> "$GITHUB_OUTPUT"
|
|
47
|
+
exit "$code"
|
|
48
|
+
|
|
49
|
+
- name: Upload evidence
|
|
50
|
+
if: always()
|
|
51
|
+
uses: actions/upload-artifact@v4
|
|
52
|
+
with:
|
|
53
|
+
name: bootproof-evidence
|
|
54
|
+
path: .bootproof/
|
|
55
|
+
|
|
56
|
+
- name: Enforce verdict
|
|
57
|
+
if: steps.bootproof.outputs.exit_code != '0'
|
|
58
|
+
run: exit 1
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Review execution flags for the target repository. `--install` can run package-manager lifecycle scripts, and `--unsafe-local` acknowledges host execution.
|
|
62
|
+
|
|
63
|
+
## Current Trust Limitation
|
|
64
|
+
|
|
65
|
+
Running BootProof in CI does not automatically produce OIDC trust.
|
|
66
|
+
|
|
67
|
+
Current attestations still say:
|
|
68
|
+
|
|
69
|
+
```text
|
|
70
|
+
local_developer_signed
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
They are signed evidence generated on a CI runner, but they are not yet `ci_oidc_signed`. Workload-identity-backed signing remains future work.
|
|
74
|
+
|
|
75
|
+
BootProof does not silently push commits or upload evidence. The workflow owner chooses whether to retain artifacts or commit `.bootproof/`.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Failure Taxonomy
|
|
2
|
+
|
|
3
|
+
BootProof classifies failure so humans get a runbook and machines get a stable verdict.
|
|
4
|
+
|
|
5
|
+
Every class still means:
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
booted: false
|
|
9
|
+
healthVerified: false
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Unknown evidence remains `unknown_failure`. BootProof does not pick a more marketable class when the evidence is inconclusive.
|
|
13
|
+
|
|
14
|
+
| Class | Meaning | Safe next step |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| `not_an_application` | No trustworthy runnable entrypoint was found. | Select a runnable workspace or add an explicit start command. |
|
|
17
|
+
| `runtime_engine_mismatch` | Node.js does not satisfy the declared engine. | Switch to a compatible runtime and rerun. |
|
|
18
|
+
| `missing_package_manager` | The declared package manager executable is absent. | Enable Corepack or install the required manager. |
|
|
19
|
+
| `package_manager_version_mismatch` | The available package-manager version differs from the exact/simple declared version. | Activate the declared version, then rerun. |
|
|
20
|
+
| `dependency_install_skipped` | A dependency-backed application was not started because install was not requested. | Review the install command and opt in with `--install`. |
|
|
21
|
+
| `python_flask_setup_required` | Python/Flask setup requires migrations, initialization, workers, frontend, or service orchestration not yet supported safely. | Complete the documented setup manually; do not treat detection as full support. |
|
|
22
|
+
| `missing_env_var` | Required environment configuration is missing. | Supply real values through the repository's documented path. BootProof will not edit `.env`. |
|
|
23
|
+
| `database_unreachable` | A required database or cache could not be reached. | Start the real required service and verify its address. |
|
|
24
|
+
| `postgres_auth_env_missing` | Postgres was reached but authentication or env configuration did not match. | Correct the real database configuration; BootProof will not invent credentials. |
|
|
25
|
+
| `migrations_missing` | The database schema is absent or behind. | Run the repository's documented migration flow. |
|
|
26
|
+
| `port_in_use` | The application port is occupied. | Stop the process or use a supported explicit port. |
|
|
27
|
+
| `native_build_dependency` | An OS toolchain or native dependency is missing. | Install the required build dependency and rerun. |
|
|
28
|
+
| `private_registry_or_auth` | Package installation requires credentials. | Provide real registry credentials outside BootProof. |
|
|
29
|
+
| `tls_or_proxy_interception` | TLS verification is blocked by a proxy or certificate chain. | Configure the trusted CA or use an appropriate network. |
|
|
30
|
+
| `service_port_allocated` | Docker is available, but a service port bind failed. | Stop the conflicting process/container or change the service port. |
|
|
31
|
+
| `docker_unavailable` | Docker is required by the plan but unavailable. | Start Docker or explicitly choose a safe local path. |
|
|
32
|
+
| `install_failed` | Dependency installation failed for an otherwise unclassified reason. | Inspect preserved install evidence and fix the underlying cause. |
|
|
33
|
+
| `app_exited_early` | The application exited before health was observed. | Inspect process evidence and fix startup. |
|
|
34
|
+
| `health_check_timeout` | No HTTP response was observed before timeout. | Check logs, port inference, and health candidates. |
|
|
35
|
+
| `health_http_error` | A health candidate returned HTTP 5xx. | Fix the server error; a responding process is not yet healthy. |
|
|
36
|
+
| `workspace_ambiguous` | Multiple applications or health targets are plausible. | Choose one with `--workspace <dir>`. |
|
|
37
|
+
| `unknown_failure` | Available evidence does not match a trustworthy detector. | Inspect the signed raw evidence and report a reproducible detector case. |
|
|
38
|
+
|
|
39
|
+
## Important Distinctions
|
|
40
|
+
|
|
41
|
+
- Docker bind conflicts are `service_port_allocated`, not `docker_unavailable`.
|
|
42
|
+
- HTTP 5xx is `health_http_error`, not `health_check_timeout`.
|
|
43
|
+
- Postgres authentication/env mismatch is `postgres_auth_env_missing`.
|
|
44
|
+
- A skipped install is not success.
|
|
45
|
+
- A detected stack is not a verified boot.
|
|
46
|
+
|
|
47
|
+
## Evidence
|
|
48
|
+
|
|
49
|
+
Local failed attestations preserve available raw evidence:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
.bootproof/attestation.json
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Registry export redacts sensitive values before producing a shareable entry.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# BootProof Honesty Contract
|
|
2
|
+
|
|
3
|
+
BootProof's promise is not that every repository boots. Its promise is that the verdict matches the evidence.
|
|
4
|
+
|
|
5
|
+
## Non-Negotiable Rules
|
|
6
|
+
|
|
7
|
+
1. A run is `BOOTED` only after an HTTP health response is observed.
|
|
8
|
+
2. Skipped steps are never rendered as success.
|
|
9
|
+
3. Dry runs execute nothing, write nothing, and create no proof.
|
|
10
|
+
4. `.env`, `.env.local`, `.env.development`, and `.env.production` are never written or modified.
|
|
11
|
+
5. Secrets are never invented.
|
|
12
|
+
6. BootProof never silently patches project files to force startup.
|
|
13
|
+
7. Ambiguous workspaces are surfaced instead of guessed.
|
|
14
|
+
8. Generated files are referenced as generated evidence only when they were actually written.
|
|
15
|
+
9. Refusals and execution failures write signed failed attestations where a signer is available.
|
|
16
|
+
10. Failed attestations preserve available raw local evidence; exported registry entries redact it.
|
|
17
|
+
11. A process starting is not enough. A health signal must be observed.
|
|
18
|
+
12. Confidence describes evidence found, not predicted success.
|
|
19
|
+
|
|
20
|
+
These behaviors are enforced by tests.
|
|
21
|
+
|
|
22
|
+
## Human And Machine Modes
|
|
23
|
+
|
|
24
|
+
Human mode:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
bootproof up .
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
It explains:
|
|
31
|
+
|
|
32
|
+
- what happened
|
|
33
|
+
- why BootProof withheld proof
|
|
34
|
+
- a safe next step
|
|
35
|
+
- where the signed evidence lives
|
|
36
|
+
|
|
37
|
+
Machine mode:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
bootproof up . --ci --json
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
It emits one JSON object and exits `0` only for an observed, health-verified boot. Human prose and ANSI colour are excluded from JSON output.
|
|
44
|
+
|
|
45
|
+
Both modes use the same inference, execution, classification, and signing engine.
|
|
46
|
+
|
|
47
|
+
## What An Attestation Proves
|
|
48
|
+
|
|
49
|
+
An attestation is a signed execution receipt containing repository state, environment metadata, the plan, observed steps, health candidates, and the result.
|
|
50
|
+
|
|
51
|
+
It can prove a narrow claim such as:
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
HTTP 200 was observed at http://localhost:3000/
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
It does not prove:
|
|
58
|
+
|
|
59
|
+
- every feature works
|
|
60
|
+
- every dependency is production-ready
|
|
61
|
+
- every service in a platform is healthy
|
|
62
|
+
- another machine will produce the same outcome
|
|
63
|
+
|
|
64
|
+
## Trust Levels
|
|
65
|
+
|
|
66
|
+
Current local runs use:
|
|
67
|
+
|
|
68
|
+
```text
|
|
69
|
+
local_developer_signed
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Local attestations are useful evidence. CI/OIDC attestations are stronger supply-chain proof. BootProof does not pretend local laptop proof is enterprise CI proof.
|
|
73
|
+
|
|
74
|
+
`ci_oidc_signed` is reserved for future workload-identity-backed signing. BootProof does not emit it today.
|
|
75
|
+
|
|
76
|
+
## Network And Sharing
|
|
77
|
+
|
|
78
|
+
BootProof itself does not upload telemetry or evidence.
|
|
79
|
+
|
|
80
|
+
Commands chosen from a repository, such as package installation or application startup, may perform their own network activity. That behavior belongs to the command being executed and should be reviewed before using `--install` or unsafe local execution.
|
|
81
|
+
|
|
82
|
+
Remote mode accepts only credential-free public HTTPS GitHub repository URLs. BootProof clones them into a retained `.bootproof/remotes/` workspace. Cloning does not authorize execution: a remote application command runs only with `--provider local --unsafe-local`.
|
|
83
|
+
|
|
84
|
+
Remote `--dry-run` is refused before cloning. A clone writes files, while the dry-run contract promises that nothing is written.
|
|
85
|
+
|
|
86
|
+
Sharing proof is deliberate: inspect and commit `.bootproof/`, or export a redacted registry entry.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Real Repository Evidence
|
|
2
|
+
|
|
3
|
+
This document records observed validation outcomes. It is an evidence ledger, not a compatibility matrix.
|
|
4
|
+
|
|
5
|
+
A detected stack or useful failure class does not mean BootProof fully supports that repository.
|
|
6
|
+
|
|
7
|
+
## Plane
|
|
8
|
+
|
|
9
|
+
- Result: `BOOTED`
|
|
10
|
+
- Observed: HTTP 200 at `localhost:3000`
|
|
11
|
+
- Value: demonstrated an observed web boot with signed proof
|
|
12
|
+
- Limitation: proves only the observed web boot, not full platform health
|
|
13
|
+
|
|
14
|
+
This result comes from prior validation evidence and was not rerun during the June 10, 2026 documentation pass.
|
|
15
|
+
|
|
16
|
+
## Twenty
|
|
17
|
+
|
|
18
|
+
- Result: `NOT VERIFIED`
|
|
19
|
+
- Class: `postgres_auth_env_missing`
|
|
20
|
+
- Value: detected a real database/environment authentication mismatch
|
|
21
|
+
- Limitation: BootProof did not repair credentials, edit `.env`, or claim a boot
|
|
22
|
+
|
|
23
|
+
This result comes from prior validation evidence and was not rerun during the June 10, 2026 documentation pass.
|
|
24
|
+
|
|
25
|
+
## Documenso
|
|
26
|
+
|
|
27
|
+
- Result: `NOT VERIFIED`
|
|
28
|
+
- Class: `health_http_error`
|
|
29
|
+
- Value: services started, dependency installation passed, and the application returned HTTP 500
|
|
30
|
+
- Limitation: a running process and responding server were not treated as healthy
|
|
31
|
+
|
|
32
|
+
This result comes from prior validation evidence and was not rerun during the June 10, 2026 documentation pass.
|
|
33
|
+
|
|
34
|
+
## Grafana
|
|
35
|
+
|
|
36
|
+
- Result: `NOT VERIFIED`
|
|
37
|
+
- Latest class: `dependency_install_skipped`
|
|
38
|
+
- Earlier observed class: `health_check_timeout`
|
|
39
|
+
- Value: exposed the need to distinguish the Go backend from the Node/React frontend pipeline and to downrank test plugins
|
|
40
|
+
- Current inference: `go-backend`, `node-frontend`, `react`
|
|
41
|
+
- Limitation: BootProof detects the hybrid architecture but does not yet orchestrate the full application
|
|
42
|
+
|
|
43
|
+
The latest local validation ran on June 10, 2026.
|
|
44
|
+
|
|
45
|
+
## Supabase
|
|
46
|
+
|
|
47
|
+
- Result: `NOT VERIFIED`
|
|
48
|
+
- Historical class: `package_manager_version_mismatch`
|
|
49
|
+
- Historical evidence: repository required pnpm 10.24 while the environment had pnpm 9.15.4
|
|
50
|
+
- Latest local class: `workspace_ambiguous`
|
|
51
|
+
- Value: package-manager mismatch detection is implemented and tested; a matching package manager still does not make a parallel multi-workspace root command a single verifiable app
|
|
52
|
+
- Limitation: BootProof requires a specific workspace instead of accepting one responding service as proof for the entire repository
|
|
53
|
+
|
|
54
|
+
The latest local validation on June 10, 2026 had pnpm 10.24.0, so the historical version mismatch did not reproduce.
|
|
55
|
+
|
|
56
|
+
## Superset
|
|
57
|
+
|
|
58
|
+
- Result: `NOT VERIFIED`
|
|
59
|
+
- Class: `python_flask_setup_required`
|
|
60
|
+
- Value: detected Python/Flask, React frontend, Docker Compose, Celery, migration/init steps, and port 8088
|
|
61
|
+
- Limitation: BootProof does not yet orchestrate the database migration, initialization, frontend, worker, and service lifecycle required for verification
|
|
62
|
+
|
|
63
|
+
The latest local validation ran on June 10, 2026.
|
|
64
|
+
|
|
65
|
+
## Reading These Results
|
|
66
|
+
|
|
67
|
+
Useful failure is part of the product:
|
|
68
|
+
|
|
69
|
+
- `BOOTED` requires an observed health signal.
|
|
70
|
+
- `NOT VERIFIED` can still provide a precise diagnosis and signed evidence.
|
|
71
|
+
- Detection is not the same as execution support.
|
|
72
|
+
- Local proof remains `local_developer_signed`, not enterprise CI/OIDC proof.
|
package/docs/REGISTRY.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Git-Native Registry Design
|
|
2
|
+
|
|
3
|
+
BootProof does not operate a public registry service today.
|
|
4
|
+
|
|
5
|
+
The current primitive is portable signed evidence:
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
.bootproof/attestation.json
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Projects may deliberately commit that file or export a redacted entry:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
bootproof attest export .
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This writes:
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
.bootproof/registry-entry.json
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Nothing is uploaded automatically.
|
|
24
|
+
|
|
25
|
+
## Intended Design
|
|
26
|
+
|
|
27
|
+
The proposed registry model is federated:
|
|
28
|
+
|
|
29
|
+
- write path: repositories deliberately publish signed proof through Git
|
|
30
|
+
- read path: a future index discovers public attestations, verifies signatures, and links claims to source commits
|
|
31
|
+
- failure corpus: classified failures improve detectors without converting failures into success claims
|
|
32
|
+
|
|
33
|
+
The index, badge service, freshness tracking, and signer trust graph are roadmap items. They are not deployed capabilities.
|
|
34
|
+
|
|
35
|
+
## Consent And Privacy
|
|
36
|
+
|
|
37
|
+
1. BootProof sends no telemetry or hidden evidence upload.
|
|
38
|
+
2. Sharing requires a visible local artifact and an explicit user action.
|
|
39
|
+
3. Full local attestations may contain raw failure evidence.
|
|
40
|
+
4. Registry export applies redaction and records which redactions were used.
|
|
41
|
+
5. A future index should trust only valid signatures and public evidence.
|
|
42
|
+
|
|
43
|
+
Repository commands executed by BootProof may access the network independently. The no-upload promise applies to BootProof's own telemetry and evidence handling, not arbitrary install or application commands.
|
|
44
|
+
|
|
45
|
+
## Trust
|
|
46
|
+
|
|
47
|
+
Current attestations are `local_developer_signed`.
|
|
48
|
+
|
|
49
|
+
CI/OIDC-backed proof will be stronger because a verifier can bind the signature to a repository workflow identity. BootProof does not claim that trust level yet.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# npm Release Checklist
|
|
2
|
+
|
|
3
|
+
BootProof publishes compiled JavaScript, not TypeScript source. `dist/` is required by the `bootproof` executable, generated during `prepack`, ignored by Git, and must not be committed.
|
|
4
|
+
|
|
5
|
+
## Before Publishing
|
|
6
|
+
|
|
7
|
+
1. Confirm the working tree contains only the intended release changes:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
git status --short
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
2. Install exactly the locked development dependencies:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm ci
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
3. Run the tests and a clean build:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm test
|
|
23
|
+
npm run build
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
4. Pack and smoke-test the installed artifact:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm run pack:check
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
This checks archive hygiene, installs the tarball under a temporary `HOME`, runs `bootproof --help`, exercises a signed early refusal, verifies and explains that attestation, verifies a healthy fixture, and checks that remote URL mode clones but refuses execution without the host safety gate.
|
|
33
|
+
|
|
34
|
+
5. Inspect the exact public archive:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm pack --dry-run
|
|
38
|
+
npm publish --dry-run
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The archive must not contain `.git/`, `node_modules/`, `.DS_Store`, `.bootproof/`, local evidence, fixtures, test repositories, or source-only development files.
|
|
42
|
+
|
|
43
|
+
6. Confirm the package name, version, npm account, and registry target:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm view bootproof
|
|
47
|
+
npm whoami
|
|
48
|
+
npm config get registry
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Publish
|
|
52
|
+
|
|
53
|
+
1. Commit the release changes and create the matching GitHub tag:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
git tag v0.1.0
|
|
57
|
+
git push origin main --tags
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
2. Publish the public package:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm publish
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
3. Install from the registry in a fresh temporary directory and rerun:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
npx bootproof --help
|
|
70
|
+
npx bootproof up /path/to/local/repository
|
|
71
|
+
npx bootproof up https://github.com/user/repository
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Remote URL mode accepts credential-free public HTTPS GitHub repositories. It retains clones under `.bootproof/remotes/` and requires `--provider local --unsafe-local` before executing remote repository code.
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bootproof",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "The honest run button for repos. Boots unfamiliar code when it safely can, tells the truth when it cannot, and signs proof of what happened.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"bootproof": "dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"LICENSE",
|
|
13
|
+
"README.md",
|
|
14
|
+
"docs"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
18
|
+
"build": "npm run clean && tsc -p tsconfig.json",
|
|
19
|
+
"prepack": "npm run build",
|
|
20
|
+
"pack:check": "node scripts/pack-smoke.mjs",
|
|
21
|
+
"release:check": "npm test && npm run build && npm run pack:check && npm publish --dry-run",
|
|
22
|
+
"lint": "tsc -p tsconfig.json --noEmit",
|
|
23
|
+
"test": "npm run build && node --test tests/*.test.mjs",
|
|
24
|
+
"ci": "npm run lint && npm run test"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/rossbuckley1990-hash/bootproof.git"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"devtools",
|
|
32
|
+
"onboarding",
|
|
33
|
+
"docker",
|
|
34
|
+
"run",
|
|
35
|
+
"attestation",
|
|
36
|
+
"reproducibility"
|
|
37
|
+
],
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=20.11"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/node": "^22.19.20",
|
|
46
|
+
"typescript": "5.8.3"
|
|
47
|
+
},
|
|
48
|
+
"bugs": {
|
|
49
|
+
"url": "https://github.com/rossbuckley1990-hash/bootproof/issues"
|
|
50
|
+
},
|
|
51
|
+
"homepage": "https://github.com/rossbuckley1990-hash/bootproof#readme"
|
|
52
|
+
}
|