Architecture
The scan → recommend → apply pipeline
Catalog fetch
Catalog items are not bundled into the npm package. They are fetched at runtime from haus-workflow-catalog and cached locally.
Output ownership
haus-workflow writes exclusively to .claude/ and .haus-workflow/. It never modifies application source code, package.json, or CI configuration.
Hand-edits inside haus-managed blocks (<!-- HAUS:BEGIN … --> … <!-- HAUS:END … -->) are overwritten on next haus apply. Edit source in the catalog; let apply propagate changes.
Lock file
.haus-workflow/haus.lock.json records per-item content hashes. On haus apply:
- New items are fetched and written
- Changed items are updated (if the on-disk copy still matches the lock hash)
- Items dropped from the catalog are removed (if unmodified)
- User-edited copies are kept (hash mismatch = skip + warn)
Security model
haus-workflow's guardrails act at three separate points in time, so no single failure leaves a project unprotected:
1. Deterministic deny/ask rules
haus install / apply writes two managed permission arrays into .claude/settings.json:
permissions.deny— hard-blocked automatically. Covers dangerous bash commands (sudo,git push --force,drop database,npm publish, …) and sensitive file patterns (*.pem,*.key,id_rsa, directories likesecrets/orcustomer-data/).permissions.ask— Claude must prompt you before proceeding. Covers commands likerm -rforgit reset --hard, and paths like.env(Edit/Write only — Read is unrestricted) orstorage/logs/**.
A scoped permissions.allow pre-approves haus's own subcommands (haus doctor, etc.) so you're not prompted on every routine step.
2. Dynamic guard hooks
guard file-access and guard bash are PreToolUse hooks that mirror the deny tier only — a real-time backstop in case the deterministic rule doesn't catch something first. Both return a plain-language reason naming the exact command or path that was blocked. A separate decisions guard hook (unrelated to security) blocks gh pr create when a diff needs an ADR it doesn't have.
3. Commit-time secret scanning
Projects that adopt the haus.lefthook-security catalog template get a pre-commit stage: gitleaks (when installed) plus an always-on grep baseline scanning newly-added lines for quoted-literal credential assignments. This catches secrets that make it past the two runtime layers above, before they ever reach a commit.
What haus will never do
- Modify your application source,
package.json, or CI configuration - Scan or read files matched by its own sensitive-path denylist
- Silently widen your permissions —
apply --writealways re-enforces the canonical hooks and managed rules; opting out means uninstalling haus-managed settings, not a partial apply
See Troubleshooting & FAQ if haus doctor --hooks reports drift in any of this.