bootproof 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +844 -152
  2. package/dist/agent-plan.d.ts +44 -0
  3. package/dist/agent-plan.js +826 -0
  4. package/dist/agent-run.d.ts +117 -0
  5. package/dist/agent-run.js +459 -0
  6. package/dist/ai-repair.d.ts +58 -0
  7. package/dist/ai-repair.js +380 -0
  8. package/dist/cli.js +730 -46
  9. package/dist/diagnosis.js +101 -16
  10. package/dist/diff.d.ts +29 -0
  11. package/dist/diff.js +569 -0
  12. package/dist/exec.d.ts +30 -2
  13. package/dist/exec.js +329 -51
  14. package/dist/external-health.d.ts +16 -0
  15. package/dist/external-health.js +214 -0
  16. package/dist/infer.js +238 -39
  17. package/dist/plan.js +2 -0
  18. package/dist/proof.d.ts +78 -2
  19. package/dist/proof.js +265 -12
  20. package/dist/receipt.d.ts +52 -0
  21. package/dist/receipt.js +356 -0
  22. package/dist/redact.d.ts +4 -0
  23. package/dist/redact.js +86 -2
  24. package/dist/registry.d.ts +82 -30
  25. package/dist/registry.js +355 -53
  26. package/dist/remote.js +3 -3
  27. package/dist/repair-playbooks.d.ts +24 -0
  28. package/dist/repair-playbooks.js +593 -0
  29. package/dist/repair-safety.d.ts +130 -0
  30. package/dist/repair-safety.js +766 -0
  31. package/dist/repair.d.ts +43 -11
  32. package/dist/repair.js +716 -7
  33. package/dist/run.d.ts +3 -0
  34. package/dist/run.js +218 -41
  35. package/dist/sbom.d.ts +22 -0
  36. package/dist/sbom.js +99 -0
  37. package/dist/taxonomy.d.ts +8 -3
  38. package/dist/taxonomy.js +404 -8
  39. package/dist/types.d.ts +40 -1
  40. package/docs/AGENT_IN_THE_LOOP.md +171 -0
  41. package/docs/AGENT_RUN_RECEIPTS.md +38 -0
  42. package/docs/CI_ACTION.md +67 -2
  43. package/docs/DETERMINISTIC_REPAIR_SAFETY_MODEL.md +705 -0
  44. package/docs/DISTRIBUTION.md +83 -0
  45. package/docs/FAILURE_TAXONOMY.md +28 -1
  46. package/docs/HONESTY_CONTRACT.md +34 -12
  47. package/docs/LAUNCH_PLAYBOOK.md +232 -0
  48. package/docs/REAL_WORLD_FIXTURES.md +105 -0
  49. package/docs/REGISTRY.md +48 -28
  50. package/docs/REPAIR_RECEIPT.md +54 -8
  51. package/docs/agent-loop-gap-analysis.md +188 -0
  52. package/docs/examples/registry-seeds/advertised-port-mismatch.json +28 -0
  53. package/docs/examples/registry-seeds/airbyte-abctl-external-orchestrator.json +36 -0
  54. package/docs/examples/registry-seeds/go-ollama-service.json +36 -0
  55. package/docs/examples/registry-seeds/laravel-vite-sqlite.json +36 -0
  56. package/docs/examples/registry-seeds/monorepo-ambiguous-health.json +29 -0
  57. package/docs/examples/registry-seeds/php-composer.json +33 -0
  58. package/docs/examples/registry-seeds/rails-bundler.json +32 -0
  59. package/docs/examples/registry-seeds/sentry-devenv-direnv.json +41 -0
  60. package/docs/schemas/action-verdict-v1.schema.json +64 -0
  61. package/docs/schemas/agent-plan-v1.schema.json +148 -0
  62. package/docs/schemas/agent-run-receipts-v1.schema.json +192 -0
  63. package/docs/schemas/ai-repair-suggestion-v1.schema.json +70 -0
  64. package/docs/schemas/ci-context-v1.schema.json +63 -0
  65. package/docs/schemas/diff-result-v1.schema.json +66 -0
  66. package/docs/schemas/federated-receipt-v1.schema.json +51 -0
  67. package/docs/schemas/registry-entry-v1.schema.json +95 -0
  68. package/docs/schemas/registry-seed-example-v1.schema.json +102 -0
  69. package/docs/schemas/repair-action-v1.schema.json +136 -0
  70. package/docs/schemas/repair-receipt-v1.schema.json +221 -0
  71. package/package.json +21 -11
@@ -0,0 +1,705 @@
1
+ # Deterministic Repair Safety Model
2
+
3
+ Status: foundation plus interactive MVP in progress. The shared action model, safety validation,
4
+ additive receipt schema, uppercase-`Y` approval, structured executor, and initial real-world
5
+ playbooks are implemented. Signed repair plans and action-hash approvals remain future work.
6
+
7
+ ## Product Contract
8
+
9
+ BootProof proposes. The human approves. BootProof reruns. Proof decides.
10
+
11
+ `bootproof up` remains deterministic, zero-AI, and evidence-based. `bootproof fix` without
12
+ `--ai` is also deterministic and performs no mutation. It selects only registered local
13
+ playbooks whose predicates match signed failure evidence and repository facts.
14
+
15
+ The repair layer must not:
16
+
17
+ - execute a command or apply a patch during planning
18
+ - mutate protected `.env` files
19
+ - invent secrets
20
+ - use `sudo`
21
+ - execute a shell command string
22
+ - upload evidence, telemetry, receipts, or registry data
23
+ - turn an unknown failure into a guessed repair
24
+ - admit an AI suggestion into the deterministic playbook registry
25
+
26
+ ## Current Gap
27
+
28
+ The current implementation already provides useful foundations:
29
+
30
+ - signed before and after attestations
31
+ - sandboxed deterministic remediation attempts
32
+ - signed `bootproof/repair-receipt/v1` artifacts
33
+ - exact file preimage checks
34
+ - a separate `bootproof apply-repair` command for repository file changes
35
+
36
+ The first MVP directly prompts for exact CMake and Redis commands and records instructions for
37
+ `RAILS_ENV`. Existing legacy sandbox remediations remain until the full planning model changes
38
+ the boundary:
39
+
40
+ 1. `bootproof fix` plans only.
41
+ 2. `bootproof apply-repair` is the only command or patch mutation entrypoint.
42
+ 3. Approval binds to the exact action hash.
43
+ 4. Host, service, and database actions require additional scope-specific acknowledgement.
44
+ 5. The normal `bootproof up` engine reruns after an approved action.
45
+
46
+ ## Repair Lifecycle
47
+
48
+ ### 1. Find the attestation
49
+
50
+ By default, `bootproof fix <repo>` reads `.bootproof/attestation.json`. A future
51
+ `--attestation <path>` flag may select a different local file.
52
+
53
+ Planning continues only when:
54
+
55
+ - the schema is `bootproof/attestation/v1`
56
+ - the signature is valid
57
+ - `booted` and `healthVerified` are both false
58
+ - `failureClass` is present
59
+ - the attestation names the same repository remote and commit
60
+ - the Git working tree is clean and still at that commit
61
+
62
+ If freshness cannot be proved, `fix` refuses and tells the user to rerun `bootproof up`. It does
63
+ not reproduce the failure automatically because planning must execute nothing.
64
+
65
+ Non-Git repositories require a future signed repository snapshot manifest before they can use
66
+ an attestation as a repair-planning input. Until then, they receive an honest refusal.
67
+
68
+ ### 2. Select candidates
69
+
70
+ Candidate selection is a pure lookup:
71
+
72
+ 1. Look up the exact failure class in the deterministic playbook registry.
73
+ 2. Validate required classifier metadata.
74
+ 3. Inspect allowlisted repository files without executing them.
75
+ 4. Evaluate platform and tool preconditions.
76
+ 5. Construct zero or more immutable repair actions.
77
+ 6. Run every action through the safety validator.
78
+ 7. Sort candidates by stable playbook ID. Never silently choose between multiple candidates.
79
+
80
+ No candidate is built from free-form model output. An AI suggestion, if introduced separately
81
+ in the future, has `source: ai_suggestion` and can never be inserted into or executed through
82
+ the deterministic registry automatically.
83
+
84
+ ### 3. Write a signed plan
85
+
86
+ `fix` writes `.bootproof/repair-plan.json` only after a candidate was deterministically
87
+ constructed. The plan uses `bootproof/repair-plan/v1`, contains the before-attestation hash,
88
+ repository identity, candidate actions, safety decisions, and a local Ed25519 signature.
89
+
90
+ ```json
91
+ {
92
+ "schema": "bootproof/repair-plan/v1",
93
+ "createdAt": "...",
94
+ "tool": "bootproof@0.3.0",
95
+ "repo": {
96
+ "remote": "...",
97
+ "commit": "...",
98
+ "dirty": false
99
+ },
100
+ "beforeAttestationHash": "...",
101
+ "failureClass": "missing_ruby_version",
102
+ "candidates": [],
103
+ "optInRequired": true,
104
+ "signer": {
105
+ "publicKey": "...",
106
+ "algorithm": "ed25519"
107
+ },
108
+ "signature": "..."
109
+ }
110
+ ```
111
+
112
+ If no playbook matches, `fix` writes no executable action. It reports
113
+ `no_known_deterministic_repair` and preserves the original failed attestation.
114
+
115
+ ### 4. Approve and apply one action
116
+
117
+ `bootproof apply-repair`:
118
+
119
+ 1. verifies the plan signature and schema
120
+ 2. verifies the selected action hash
121
+ 3. verifies the original attestation signature and hash
122
+ 4. verifies the repository commit and all action preconditions
123
+ 5. reruns the safety validator immediately before mutation
124
+ 6. requires the exact approval flags for the action's scope and risk
125
+ 7. applies exactly one patch or executes exactly one structured command
126
+ 8. reruns `bootproof up` with the attested provider and explicit execution consent
127
+ 9. writes the after attestation and a signed repair receipt
128
+
129
+ An instruction action is never executable. The user follows it manually and reruns
130
+ `bootproof up`.
131
+
132
+ ## Repair Action Schema
133
+
134
+ Implemented foundation schema: `bootproof/repair-action/v1`.
135
+
136
+ ```json
137
+ {
138
+ "schema": "bootproof/repair-action/v1",
139
+ "actionType": "command",
140
+ "mutationScope": "host_tool_install",
141
+ "riskLevel": "high",
142
+ "requiresApproval": true,
143
+ "approvalPrompt": "This action may install or change tools on your local machine. Review the exact command before approving it.",
144
+ "blockedReason": "",
145
+ "verificationStep": "Rerun BootProof and require observed health evidence before marking progress.",
146
+ "command": {
147
+ "executable": "rbenv",
148
+ "args": ["install", "3.3.11"],
149
+ "display": "rbenv install 3.3.11"
150
+ },
151
+ "patch": null,
152
+ "instruction": null,
153
+ "explanation": "Install the exact Ruby version selected by the repository.",
154
+ "evidenceRefs": [".bootproof/attestation.json"],
155
+ "deterministic": true,
156
+ "source": "deterministic_playbook"
157
+ }
158
+ ```
159
+
160
+ Required enums:
161
+
162
+ ```text
163
+ actionType: command | patch | instruction
164
+ mutationScope: none | repo_only | project_cache | container_runtime |
165
+ host_tool_install | host_network | kubernetes_cluster | database |
166
+ service | credentials | unknown
167
+ riskLevel: none | low | medium | high | blocked
168
+ ```
169
+
170
+ Rules:
171
+
172
+ - `medium` and `high` actions always have `requiresApproval: true`.
173
+ - `none` and `low` actions may be displayed without approval.
174
+ - repository patches still require approval and use `mutationScope: repo_only`.
175
+ - instructions are not executable.
176
+ - `riskLevel: blocked` cannot have an executable command or applicable patch.
177
+ - unknown commands are at least `medium` risk and use `mutationScope: unknown`
178
+ unless a stricter deterministic classification applies.
179
+ - the shared classifier assigns high risk to host installs, Kubernetes creation
180
+ or application, database migrations, and credential generation.
181
+ - deterministic and `ai_suggested` actions use the same inferred risk floor;
182
+ provider-reported risk may raise that floor but never lower it.
183
+ - Exactly one of `command`, `patch`, or `instruction` is present.
184
+ - The future signed plan adds playbook identity, preconditions, progression rules, and an
185
+ action hash around this validated action payload.
186
+
187
+ Patch actions contain:
188
+
189
+ ```json
190
+ {
191
+ "patch": {
192
+ "format": "unified-diff",
193
+ "content": "...",
194
+ "files": ["config/database.yml"]
195
+ }
196
+ }
197
+ ```
198
+
199
+ The future signed repair plan binds patch hashes, preconditions, and transactional application
200
+ metadata around this exact payload. A failed post-repair boot does not silently roll back an
201
+ approved patch.
202
+
203
+ ## Command Safety Model
204
+
205
+ Command actions are structured argv, never shell strings. Execution uses `execFile` or
206
+ `spawn` with `shell: false`.
207
+
208
+ No hidden chaining means:
209
+
210
+ - one executable
211
+ - one argument array
212
+ - no `sh -c`, `bash -c`, `zsh -c`, `cmd /c`, or PowerShell command strings
213
+ - no `;`, `&&`, `||`, pipes, redirects, command substitution, backticks, or newlines
214
+ - no arbitrary interpreter snippets such as `node -e`, `python -c`, or `ruby -e`
215
+
216
+ The blocklist is a mandatory backstop, not the allow mechanism. A command must first be
217
+ constructed by a named playbook with executable-specific argument validation. It is then
218
+ rejected if its normalized executable, arguments, display form, target paths, or environment
219
+ match any blocked rule.
220
+
221
+ Hard-blocked patterns include:
222
+
223
+ - `rm -rf`
224
+ - `sudo rm`
225
+ - any use of `sudo`
226
+ - `curl | sh`
227
+ - `wget | sh`
228
+ - `chmod -R 777`
229
+ - recursive world-writable chmod in equivalent octal or symbolic forms, including
230
+ `0777`, `a+w`, and `o+w`
231
+ - `chown -R`
232
+ - `mkfs`
233
+ - `diskutil erase`
234
+ - raw block-device writes such as `dd ... of=/dev/sda`, `/dev/nvme*`, or
235
+ `/dev/disk*`
236
+ - inline interpreter snippets such as `node --eval`, `ruby -e`, `perl -E`,
237
+ `php -r`, and `python3 -c`
238
+ - destructive database drops, including `dropdb`, `DROP DATABASE`, `DROP SCHEMA`,
239
+ `rails db:drop`, migration reset commands, and equivalents
240
+ - commands that write a protected `.env`
241
+ - shell redirection into a protected `.env`
242
+ - secret exfiltration patterns
243
+ - upload of local secret files
244
+
245
+ High-risk approval-required commands include:
246
+
247
+ - destructive Git remote operations such as `git push --force`,
248
+ `--force-with-lease`, `--mirror`, or `--delete`
249
+ - local `tar`, `zip`, or `rsync` operations whose arguments include a home
250
+ directory or sensitive tree such as `.ssh`, `.aws`, or `.gnupg`
251
+
252
+ Network transfer of those sensitive trees remains blocked as exfiltration.
253
+
254
+ Protected env paths include `.env`, `.env.local`, `.env.development`, `.env.production`, and
255
+ `.env.*.local`. Example templates may be patched only when the playbook explicitly permits
256
+ them and the content passes secret scanning.
257
+
258
+ Additional command rules:
259
+
260
+ - resolved executables inside the repository are not trusted as host tools
261
+ - host commands must resolve to a playbook-approved executable
262
+ - repository commands are untrusted code and retain the existing `--unsafe-local` gate
263
+ - command environment values are never embedded in plans or receipts
264
+ - inherited environment names may be recorded, but their values are not
265
+ - stdout/stderr evidence is redacted before entering receipts
266
+ - network-capable upload tools are not valid deterministic repair executables
267
+ - blocklist validation runs during planning and again immediately before execution
268
+
269
+ ## Risk And Approval
270
+
271
+ Suggested approval interface:
272
+
273
+ ```bash
274
+ bootproof apply-repair . \
275
+ --action install-required-ruby \
276
+ --approve <action-hash> \
277
+ --allow-host-mutation
278
+ ```
279
+
280
+ Required acknowledgements:
281
+
282
+ | Scope/risk | Required flags |
283
+ |---|---|
284
+ | `repo`, low/medium patch | `--approve <action-hash>` |
285
+ | `host` | `--approve <action-hash> --allow-host-mutation` |
286
+ | `service` | `--approve <action-hash> --allow-service-mutation` |
287
+ | `database` | `--approve <action-hash> --allow-database-mutation` |
288
+ | `high` | scope flag plus `--allow-high-risk` |
289
+ | `blocked` | never executable |
290
+
291
+ The approval hash binds consent to the exact command or patch shown by `fix`. Changing any
292
+ argument, patch byte, precondition, scope, or risk changes the hash and invalidates approval.
293
+
294
+ CI mode never prompts. Missing approval flags fail closed. Human mode should also prefer the
295
+ explicit flags over a generic `y/N` prompt so approval is reproducible and auditable.
296
+
297
+ ## Command UX
298
+
299
+ Planning:
300
+
301
+ ```text
302
+ $ bootproof fix .
303
+
304
+ NOT APPLIED - deterministic repair candidate
305
+ failure: missing_ruby_version
306
+ action: install-required-ruby
307
+ type: command
308
+ scope: host
309
+ risk: medium
310
+ exact command: rbenv install 3.3.11
311
+ approval required: yes
312
+ action hash: 8f...
313
+
314
+ Nothing was executed or mutated.
315
+ Plan: .bootproof/repair-plan.json
316
+ Apply explicitly:
317
+ bootproof apply-repair . --action install-required-ruby \
318
+ --approve 8f... --allow-host-mutation
319
+ ```
320
+
321
+ Patch preview:
322
+
323
+ ```text
324
+ $ bootproof fix .
325
+
326
+ NOT APPLIED - deterministic repair candidate
327
+ failure: missing_database_config
328
+ action: copy-database-config-example
329
+ type: patch
330
+ scope: repo
331
+ risk: medium
332
+
333
+ --- /dev/null
334
+ +++ b/config/database.yml
335
+ ...
336
+
337
+ Nothing was executed or mutated.
338
+ ```
339
+
340
+ Application:
341
+
342
+ ```text
343
+ $ bootproof apply-repair . --action copy-database-config-example --approve 4a...
344
+
345
+ approved: exact patch hash 4a...
346
+ applied: config/database.yml
347
+ rerun: bootproof up . --provider local --unsafe-local
348
+ progress: missing_database_config -> postgres_unavailable
349
+ verified: no
350
+ receipt: .bootproof/repair-receipt.json
351
+ ```
352
+
353
+ Only an observed healthy rerun prints:
354
+
355
+ ```text
356
+ verified: yes - HTTP 302 Found -> /users/sign_in
357
+ ```
358
+
359
+ Proposed exit behavior:
360
+
361
+ - `bootproof fix` exits `0` when it successfully produces a valid plan, and `1` when planning
362
+ refuses or finds no deterministic candidate. Exit `0` means "plan created," never "booted."
363
+ - `bootproof apply-repair` exits `0` only for verified boot.
364
+ - `bootproof apply-repair` exits `2` when the action applied and reached an allowed later
365
+ blocker but did not verify.
366
+ - `bootproof apply-repair` exits `1` for refusal, blocked action, failed application, or no
367
+ measured progress.
368
+
369
+ Machine output must expose the lifecycle booleans so callers never need to infer boot proof
370
+ from prose or an action's process exit code.
371
+
372
+ ## Progress Detection
373
+
374
+ Application and verification are separate facts.
375
+
376
+ `applied` means the approved patch completed or the approved command exited successfully.
377
+ It does not mean the repository boots.
378
+
379
+ `verified` means the after attestation has:
380
+
381
+ ```text
382
+ booted: true
383
+ healthVerified: true
384
+ ```
385
+
386
+ `progressed` is true when either:
387
+
388
+ 1. `verified` is true; or
389
+ 2. the signed after attestation has a different failure class at a strictly later deterministic
390
+ setup stage allowed by the selected playbook.
391
+
392
+ Proposed stages:
393
+
394
+ | Stage | Failure examples |
395
+ |---|---|
396
+ | 10 runtime/toolchain | `missing_ruby_version`, `runtime_engine_mismatch`, `missing_runtime_tool` |
397
+ | 20 dependency build | `missing_build_tool`, `native_extension_compile_failed`, `install_failed` |
398
+ | 30 configuration | `missing_database_config`, `missing_required_config`, `unsupported_database_config`, `missing_env_var` |
399
+ | 40 services | `postgres_unavailable`, `redis_unavailable`, `service_port_allocated`, `docker_unavailable`, `unsupported_database_version` |
400
+ | 50 database identity/auth | `postgres_role_missing`, `postgres_auth_env_missing` |
401
+ | 60 database schema | `database_schema_missing`, `migrations_missing` |
402
+ | 70 application startup | `app_exited_early`, `port_in_use` |
403
+ | 80 health | `health_check_timeout`, `health_http_error` |
404
+ | 100 verified | observed healthy boot |
405
+
406
+ A stage number alone is insufficient. Each playbook also declares its allowed later failure
407
+ classes. `unknown_failure`, an unchanged class, a lower stage, or a class not allowed by that
408
+ playbook is not progress.
409
+
410
+ ## Repair Receipt Schema
411
+
412
+ The requested schema remains `bootproof/repair-receipt/v1`. Because this repository already
413
+ emits a v1 receipt, implementation must either make the lifecycle fields additive and retain
414
+ legacy verification or, before a stable release, explicitly migrate old v1 receipts. It must
415
+ not silently make existing signatures unverifiable.
416
+
417
+ Proposed receipt:
418
+
419
+ ```json
420
+ {
421
+ "schema": "bootproof/repair-receipt/v1",
422
+ "tool": "bootproof@0.3.0",
423
+ "planHash": "...",
424
+ "action": {
425
+ "id": "install-required-ruby",
426
+ "actionHash": "...",
427
+ "actionType": "command",
428
+ "mutationScope": "host_tool_install",
429
+ "riskLevel": "high",
430
+ "exactCommand": "rbenv install 3.3.11",
431
+ "exactPatchHash": null
432
+ },
433
+ "before": {
434
+ "failureClass": "missing_ruby_version",
435
+ "stage": 10,
436
+ "attestationHash": "..."
437
+ },
438
+ "lifecycle": {
439
+ "suggested": {
440
+ "value": true,
441
+ "at": "..."
442
+ },
443
+ "approved": {
444
+ "value": true,
445
+ "at": "...",
446
+ "approvalMethod": "action_hash_and_scope_flag"
447
+ },
448
+ "applied": {
449
+ "value": true,
450
+ "at": "...",
451
+ "exitCode": 0,
452
+ "changedFiles": []
453
+ },
454
+ "progressed": {
455
+ "value": true,
456
+ "reason": "later_failure_class"
457
+ },
458
+ "verified": {
459
+ "value": false,
460
+ "healthObservation": null
461
+ }
462
+ },
463
+ "after": {
464
+ "failureClass": "missing_build_tool",
465
+ "stage": 20,
466
+ "attestationHash": "..."
467
+ },
468
+ "evidence": {
469
+ "stdoutHeadRedacted": "...",
470
+ "stdoutTailRedacted": "...",
471
+ "stderrHeadRedacted": "...",
472
+ "stderrTailRedacted": "...",
473
+ "redactionsApplied": []
474
+ },
475
+ "safety": {
476
+ "ruleset": "bootproof/repair-command-safety/v1",
477
+ "blocklistPassed": true
478
+ },
479
+ "signer": {
480
+ "publicKey": "...",
481
+ "algorithm": "ed25519"
482
+ },
483
+ "signature": "..."
484
+ }
485
+ ```
486
+
487
+ Lifecycle meanings:
488
+
489
+ - `suggested`: a deterministic signed plan contained this exact action
490
+ - `approved`: the user supplied the exact action hash and required scope/risk flags
491
+ - `applied`: the patch transaction completed or command exited successfully
492
+ - `progressed`: the after proof verified or reached an allowed later blocker
493
+ - `verified`: observed health succeeded
494
+
495
+ A command that exits nonzero may still produce a signed receipt with `approved: true`,
496
+ `applied: false`, `progressed: false`, and `verified: false`. Failed approved attempts are
497
+ valuable evidence.
498
+
499
+ Receipt verification checks:
500
+
501
+ - strict schema validation
502
+ - receipt signature
503
+ - plan hash and action hash
504
+ - before and after attestation signatures and hashes
505
+ - approval requirements for the recorded scope/risk
506
+ - file preimages and postimages for patches
507
+ - command argv hash for commands
508
+ - safety ruleset and blocklist result
509
+ - internal lifecycle consistency
510
+
511
+ Examples of invalid state:
512
+
513
+ - `verified: true` without observed health
514
+ - `progressed: true` without a verified boot or allowed later failure
515
+ - `applied: true` for a blocked action
516
+ - `approved: false` with an applied command or patch
517
+
518
+ ## Initial Deterministic Playbooks
519
+
520
+ These candidates are implemented with exact evidence and repository-state gates. Multi-step
521
+ repairs expose one action per run; later actions are shown but never silently chained.
522
+
523
+ | Failure class | Proposed action | Scope | Risk | Conditions |
524
+ |---|---|---|---|---|
525
+ | `missing_ruby_version` | `rbenv install <requiredVersion>` | host | medium | Exact safe version metadata. |
526
+ | `missing_build_tool` | `brew install cmake` | host | medium | macOS, exact `cmake` classifier metadata, Homebrew available. Otherwise instruction. |
527
+ | `native_extension_compile_failed` for `idn-ruby` | Install `libidn` and `pkg-config`, then configure Bundler with the detected static Homebrew prefix in a later approved run. | host | medium | Exact affected gem and Homebrew prefix; no shell substitution. |
528
+ | `missing_database_config` | Copy the PostgreSQL example, otherwise the generic example, to `config/database.yml` as a patch. | repo | medium | Destination absent; source is repository-local; secret scan passes. |
529
+ | `missing_required_config` | Copy the exact sibling example to the reported path as a patch. | repo | medium | Reported safe relative path; unique example; secret scan passes. |
530
+ | `unsupported_database_config` | Remove only classifier-identified `geo` or `embedding` top-level database sections. | repo | medium | YAML parses; exact diff shown; secret scan passes. |
531
+ | `postgres_unavailable` | Start an exact local PostgreSQL service, such as `brew services start postgresql@17`. | service | medium | Localhost endpoint, exact required major when versioned, and one platform-specific registered service command. Otherwise instruction. |
532
+ | `redis_unavailable` | `brew services start redis` | service | medium | macOS, localhost endpoint, Homebrew available. Otherwise instruction. |
533
+ | `postgres_role_missing` | `createuser -s <role>` for the exact validated role. | database | medium | Role is shell-safe and comes from classifier metadata. |
534
+ | `database_schema_missing` | Run one exact framework migration command. | database | high | One unambiguous framework and migration directory/config. |
535
+ | `migrations_missing` | Run one exact framework migration command. | database | high | Existing Prisma/Django/Rails/Knex/Drizzle predicates remain unambiguous. |
536
+ | `unsupported_database_version` | Separate install and service-start actions for the exact required PostgreSQL major. | host/service | high | Homebrew and major version are exact; each action separately approved; PATH is never changed. |
537
+ | `service_port_allocated` | Patch a BootProof-owned Compose override/copy using the first available port in a deterministic bounded range. | repo | low | Exact service/port mapping and signed source precondition. |
538
+ | `package_manager_version_mismatch` | Activate the exact declared package manager version. | host | medium | Exact simple version declaration; Corepack available. |
539
+ | `missing_env_var` | Instruction showing exact variable names and safe known values only. | none | low | Never writes `.env`; never invents secret values. |
540
+
541
+ Database commands that can destroy or reset data are blocked even when the framework is known.
542
+ For example, `prisma migrate reset`, `rails db:drop`, and `dropdb` are never deterministic
543
+ repair actions.
544
+
545
+ ## No-Known-Repair Classes
546
+
547
+ The initial implementation should remain instruction-only or refuse for:
548
+
549
+ - `unknown_failure`
550
+ - `runtime_engine_mismatch`
551
+ - `missing_package_manager`
552
+ - `missing_runtime_tool`
553
+ - `private_registry_or_auth`
554
+ - `postgres_auth_env_missing`
555
+ - `tls_or_proxy_interception`
556
+ - `native_extension_compile_failed` without an exact classified missing tool
557
+ - generic `native_build_dependency`
558
+ - generic `database_unreachable`
559
+ - `dependency_install_skipped`
560
+ - `install_failed`
561
+ - `health_http_error`
562
+ - `health_check_timeout`
563
+ - `app_exited_early` without a more precise classifier
564
+ - `port_in_use`
565
+ - `docker_unavailable`
566
+ - `workspace_ambiguous`
567
+ - `not_an_application`
568
+ - `orchestration_not_supported`
569
+ - `python_flask_setup_required`
570
+
571
+ Credentials, tokens, proxy trust, and secret values are always human-supplied outside the
572
+ deterministic registry.
573
+
574
+ ## Proposed Files And Modules
575
+
576
+ Keep `src/repair.ts` as a compatibility facade while moving distinct responsibilities into:
577
+
578
+ ```text
579
+ src/repair/model.ts action, plan, receipt, and result types
580
+ src/repair/plan.ts attestation loading, freshness, candidate construction
581
+ src/repair/playbooks.ts deterministic registry and predicates
582
+ src/repair/safety.ts command allow rules, blocklist, protected paths
583
+ src/repair/apply.ts approval validation and one-action application
584
+ src/repair/progress.ts after-attestation stage/progression decision
585
+ src/repair/receipt.ts canonical hashing, signing, strict verification
586
+ src/repair/rerun.ts explicit handoff to the normal up engine
587
+ docs/schemas/repair-action-v1.schema.json
588
+ docs/schemas/repair-plan-v1.schema.json
589
+ docs/schemas/repair-receipt-v1.schema.json
590
+ ```
591
+
592
+ `src/cli.ts` should only parse flags, render the exact action, and call these modules.
593
+
594
+ ## Test Plan
595
+
596
+ ### Pure unit tests
597
+
598
+ - action schemas reject unknown fields and invalid enum combinations
599
+ - command and patch actions always require approval
600
+ - instruction actions cannot be executed
601
+ - action hashes are stable and change for any command, patch, scope, risk, or precondition change
602
+ - candidate selection is stable and refuses ambiguous playbooks
603
+ - stale, unsigned, successful, or mismatched attestations cannot produce plans
604
+ - unknown failures produce no executable candidate
605
+ - AI-source actions are rejected by the deterministic registry and apply path
606
+ - progress requires verified health or an allowed later failure class
607
+ - unchanged, lower-stage, unknown, or unapproved failure transitions are not progress
608
+
609
+ ### Blocklist tests
610
+
611
+ Test exact and obfuscated forms of every required block:
612
+
613
+ - whitespace and quoting variants of `rm -rf` and `sudo`
614
+ - `curl|sh`, `curl | sh`, `wget | bash`
615
+ - recursive world-writable chmod and recursive chown
616
+ - `mkfs` and `diskutil erase`
617
+ - database drop/reset commands
618
+ - shell operators in any argv item
619
+ - protected env paths passed to mutating tools
620
+ - `tee`, redirects, or interpreter snippets targeting `.env`
621
+ - uploads of `.env`, `.ssh`, `.aws`, private keys, and token files
622
+
623
+ Every blocked action must execute zero child processes and write zero files.
624
+
625
+ ### Patch tests
626
+
627
+ - exact config example copy preview and application
628
+ - unique-example requirement
629
+ - secret-bearing example refused
630
+ - protected `.env` destination refused
631
+ - symlink/path traversal refused
632
+ - stale source example or destination preimage refused
633
+ - transactional rollback on partial write failure
634
+ - displayed patch bytes equal applied patch bytes
635
+
636
+ ### Command tests
637
+
638
+ - exact argv shown equals exact argv executed
639
+ - execution uses `shell: false`
640
+ - no command runs without action hash approval
641
+ - host/service/database acknowledgements are independently required
642
+ - high-risk acknowledgement is required
643
+ - blocklist is checked again immediately before execution
644
+ - inherited env values reach the child but never enter plan/receipt JSON
645
+ - timeout, nonzero exit, and connection errors produce failed receipts
646
+
647
+ ### End-to-end tests
648
+
649
+ - `fix` reads a fresh signed failure and performs no command/file mutation
650
+ - `fix` writes a signed plan and prints exact command or patch
651
+ - `apply-repair` refuses stale or tampered plans
652
+ - approved patch reruns `up` and records verified boot
653
+ - approved command reruns `up` and records a later blocker as progress
654
+ - approved action with no progress records `applied: true`, `progressed: false`
655
+ - failed approved action records `approved: true`, `applied: false`
656
+ - receipt verification detects tampered lifecycle fields
657
+ - no receipt can claim verified without an after attestation containing observed health
658
+ - remote retained clones keep the existing `--unsafe-local` execution gate
659
+ - no telemetry, upload, or network call originates from BootProof evidence handling
660
+
661
+ ## Implementation Order
662
+
663
+ 1. Add strict action, plan, and additive receipt schemas plus validators.
664
+ 2. Add pure playbook selection and safety validation; change `fix` to planning only.
665
+ 3. Add patch-only approval/application with exact hashes and rerun.
666
+ 4. Add structured command execution with blocklist and scope/risk approvals.
667
+ 5. Add progress classification and lifecycle receipts for failed and successful attempts.
668
+ 6. Migrate existing port, package-manager, and migration remediations into the new registry.
669
+ 7. Add the narrowly evidenced Mastodon/GitLab playbooks listed above.
670
+
671
+ Patch-only application should land before host-mutating commands. This keeps the first
672
+ implementation step inside the already established signed file-preimage boundary.
673
+
674
+ ## Risks
675
+
676
+ - Changing current `fix` behavior from auto-attempt to plan-only is a CLI compatibility change
677
+ and must be explicit in release notes.
678
+ - The existing v1 receipt is already emitted; additive compatibility or a deliberate version
679
+ migration is required.
680
+ - Package managers and version managers perform their own network activity. Approval copy must
681
+ say so even though BootProof itself uploads nothing.
682
+ - Database migrations can be irreversible. Exact framework detection does not make them low
683
+ risk.
684
+ - Starting a service can affect unrelated local projects.
685
+ - A blocklist alone is insufficient; playbook-specific executable and argument allow rules are
686
+ mandatory.
687
+ - Repository-provided executables and migration code are untrusted code and still require
688
+ explicit local-execution consent.
689
+ - Progress stages can overstate improvement if they are global only; playbook-specific allowed
690
+ transitions are required.
691
+ - Exact patches may contain sensitive configuration. Candidate construction must secret-scan
692
+ and refuse rather than redact an executable patch into something different.
693
+ - Host changes may not be reversible. Receipts must never imply rollback capability that does
694
+ not exist.
695
+
696
+ ## Intentionally Not Implemented
697
+
698
+ The current foundation does not implement:
699
+
700
+ - additional repair playbooks beyond the three-command/instruction MVP
701
+ - receipt migration
702
+ - signed repair plans or action-hash approval
703
+ - general command or patch application through the new model
704
+ - AI repair
705
+ - hosted services, Cloud upload, crawler, telemetry, or automatic sharing