chore(memory): BDR-095 LRN-160 BLK-022, journal + TODO 2026-09-22

This commit is contained in:
bastien
2026-09-22 07:43:13 +02:00
parent 9da5d8d52c
commit e600394acc
5 changed files with 67 additions and 0 deletions
+8
View File
@@ -1196,3 +1196,11 @@ Branch feature/user-writing-web-rules, UNMERGED (human gate).
- **Alternatives rejected**: before/after skill-version compare (first idea) → cannot separate rotted-pin no-op from up-to-date no-op, identical files + rc 0 both times → false warn on every rerun. `--force` → re-downloads ~15 MB engine + dist on every `make plugin`, and the CLI's own update check already refreshes without it. Shared `lib/impeccable.sh` for `imp_install` → deferred: two mirrored 12-line helpers vs new lib + test; revisit at a third caller. Project-scope install inside this repo → Claude Code scans `.claude/skills` too = skill listed twice, shadows the global copy (seen live, TODO T6).
- **Status**: accepted. Verified: harness on extracted Step 8d, sandbox HOME, real installer, 4/4: fresh install (skill 4.3.1, 4 agents); rotted pin over a copy → fallback fires; same pin rerun → no false warn; parked + rotted → fallback, returned to `skills-disabled/`. `make test` green minus 2 pre-existing T16a (gitleaks absent), shellcheck clean. `update-all.sh` block: `bash -n` + shellcheck only, same helper, not run end to end.
- **Reference**: `install-plugins.sh` Step 8d, `update-all.sh`, `plugins.lock.json`, `.gitignore`, `link.sh`, `lib/design-gate.md` §5. Links [[LRN-159]], [[LRN-158]] (21st: opposite case, installer refuses symlinks → stage), [[LRN-077]] (pin doctrine), [[BLK-021]].
## BDR-095 — Data-loss guardrails: static deny for transfer/destructive tools, push every commit, brief ≠ user authority
- **Date**: 2026-09-22
- **Decision**: layer C of the post-incident plan (layers A OS/backup and B sandbox/managed-settings = user's side). (1) `permissions.deny` static: lftp/sftp/ftp/curl -T, `rsync --delete`, `xargs rm`, pipe-to-shell, `chmod/chown -R`, sudo/doas/pkexec, dd/mkfs/shred/wipefs/fdisk/parted, chattr, docker volume drops/system prune/compose down -v/--privileged/docker.sock/`-v /:`, git push --delete/--mirror/:ref/--force-with-lease, branch -D, filter-branch, reflog expire, stash clear/drop, clean -f, --no-verify, core.hooksPath. `ask` entries for pipe-to-shell + stash drop/clear retired into deny. (2) `hard_deny`: destructive tool against a local path from a variable/`~`/`..`/wildcard/outside cwd+tmp, trace or rehearsal included, brief carries no user authority. (3) `soft_deny`: docker entry reworded (promoted items out), + discarding uncommitted work. (4) `environment`: incident, push discipline, Claude never deploys. (5) `lib/gitflow.sh`: `start` pushes `-u origin`, `_gitflow_merge_into` pushes target, `install-hook` writes post-commit + post-merge push hooks (`--follow-tags`, timeout 30, `GITFLOW_NO_PUSH=1`, warn-never-block). (6) `hooks/unpushed-guard.sh` SessionStart+Stop systemMessage. (7) doctrine section "Destructive tools & data loss" + 4 report-only agents clause. (8) `lib/tests/guard-bash.test.sh` = spec of the PreToolUse guard, hook not shipped ([[BLK-022]]).
- **Why**: 21/09 wipe ([[LRN-160]]): prose tiers named neither lftp nor a local trace, the orchestrator's brief authorized it, auto mode inherited by the sub-agent, nothing pushed for 4 days. User: Claude never deploys, only explains; test = dev server on this machine → lftp has zero legitimate use. Static deny resolves before the classifier and inside sub-agents (doc verified 2026-09-22); prose is judgment, static is a rule.
- **Alternatives rejected**: `ask` tier → doc says it prompts under auto, LRN-155 probe says inert, unresolved → nothing entrusted to ask. Keep docker volume drops in soft_deny (BDR-092) → "à tout prix" beats in-turn convenience; user runs them by hand. Post-commit hook alone for push → `git merge` fires post-merge, not post-commit (T18f caught it) → lib pushes the target explicitly AND post-merge hook emitted. Force-push allowance after amend → static deny stays; a rejected push warns and the user decides. Stop-hook `decision: block` on unpushed work → BDR-083 refused control-flow hooks; systemMessage only.
- **Status**: accepted, on feature/destructive-guardrails. `gitflow-test.sh` T18 7/7 + T19 3/3, unpushed-guard 9/9, `make test` green minus 2 pre-existing T16a, shellcheck clean, doctor 0 errors. NOT DONE: `hooks/guard-bash.sh` ([[BLK-022]]). Existing projects need `gitflow install-hook` re-run for the push hooks.
- **Reference**: `settings.json`, `lib/gitflow.sh`, `.githooks/{post-commit,post-merge}`, `hooks/unpushed-guard.sh`, `lib/tests/{guard-bash,unpushed-guard}.test.sh`, `CLAUDE.global.md`, `templates/settings/SETTINGS.md`, `agents/{verifier,plan-challenger,analyzer,security-auditor}.md`. Extends [[BDR-090]] [[BDR-092]] (ask inert, soft_deny doctrine); links [[LRN-114]] (T19 drift gate), [[LRN-155]], [[BDR-083]].