# Ten critical failures in CLI installer ownership journal designs found by adversarial review
## When to use
Apply this checklist when designing or reviewing a CLI installer that journals ownership of permission rules or settings entries in user-editable files. Use it after drafting the basic ownership tracking mechanism but before implementation, and again during adversarial design review. Covers failure modes that survive initial review and emerge only under concurrent access, crash recovery, and retry scenarios.
This documents failures found through reasoned adversarial analysis, not executed tests.
## Failure 1: TOCTOU race destroys concurrent user edits
**Scenario**: Uninstall reads settings at step one, decides what to remove at step three, then atomically replaces the entire file at step four. Between steps three and four, an external process adds a new user setting. Step four's atomic replace silently destroys that setting because it writes a complete file based on the step-one read.
**Prevention**: Either hold an advisory lock spanning all steps, or re-read the file immediately before the final write and abort if its digest changed. If using digest verification, the abort requires manual reconciliation. If using advisory locking, the lock must span from initial read through final journal write completion.
## Failure 2: Witness token collision between operations
**Scenario**: Install completes with witness W1 in settings. Cleanup to remove W1 crashes. Uninstall starts, generates witness W2, writes journal, crashes before writing W2 to settings. Recovery reads settings, finds W1 from the old install, incorrectly concludes the uninstall write landed, and marks the uninstall journal complete without actually removing any rules.
**Prevention**: Tag witness tokens with operation type, use separate metadata keys per operation type, or include operation type in the recovery witness comparison. A witness from install must never validate an uninstall operation.
## Failure 3: Orphaned journal records from install retry
**Scenario**: Install attempt one writes journal J1 with witness W1, then crashes before writing settings. Recovery finds witness W1 absent, generates a NEW witness W2 and NEW journal record J2, completes successfully. Journal J1 remains pending forever because witness W1 never appears.
**Prevention**: Expire or overwrite pending records on retry instead of creating new ones. Alternatively, include attempt sequence numbers and ignore all records except the highest-sequence pending record during recovery.
## Failure 4: Partial uninstall reported as complete success
**Scenario**: Three rules to uninstall: A matches exactly, B was user-modified, C matches exactly. Uninstall preserves B as designed, removes A and C, writes witness W indicating success, marks operation complete. Journal shows complete, but rule B was not removed. Future operations see complete status and never retry B.
**Prevention**: Use graduated completion states: fully complete when all planned removals succeeded, partially complete when some rules were preserved due to modification, failed when the write did not land. Or record per-rule outcomes in the journal so repair can address individually preserved rules.
## Failure 5: Witness cleanup crash leaves permanent metadata
**Scenario**: Uninstall completes all rule removals and marks journal complete. Witness removal step crashes. Recovery sees complete journal, finds witness still present, has no defined cleanup path. Witness remains permanently.
**Prevention**: Include witness cleanup in the recovery path: if journal shows complete and witness is present, remove witness and continue. Or make witness removal idempotent and retry it on every command run until it succeeds.
## Failure 6: Aggressive tombstoning prevents user recovery from mistakes
**Scenario**: Install adds rule A. Developer accidentally deletes A with unrelated edits. Developer runs any command that loads settings. That command tombstones A immediately upon noticing it absent. Developer realizes mistake minutes later and runs repair. Repair sees tombstone, permanently refuses to restore A.
**Prevention**: Defer tombstoning until an explicit user action confirms the removal was intentional, such as running uninstall or answering a prompt. Or record tombstones with timestamps and allow repair to override tombstones created within a grace period like one hour.
## Failure 7: Install retry duplicates rules without deduplication
**Scenario**: Install attempt one adds rules to settings, crashes before writing witness. Recovery finds witness absent, retries, adds the same rules again without checking if they are already present. Settings now contain duplicate rules.
**Prevention**: Before adding a rule, check if an exact match already exists in the current file. Count existing matches and only insert additional copies if the current count is less than the target count, which is typically one.
## Failure 8: Uninstall retry loses original content baseline for detecting user modifications
**Scenario**: Install records rules with content V1 in journal. Uninstall attempt one writes releasing intent, crashes before writing settings. User edits rules to V2 between attempts. Recovery retries, creates NEW journal entry with current content V2 as baseline. Compare current V2 to journal V2 finds exact match. Uninstall removes rules despite user modification.
**Prevention**: Preserve the original install-time content baseline across all retry attempts. On uninstall retry, reuse the releasing intent from the prior attempt instead of creating a new one, or copy the install-time baseline from the owned record into each releasing record so comparison always uses the original baseline.
## Failure 9: No correlation between journal records and witness tokens
**Scenario**: Multiple pending journal records exist from retries: J1 with W1, J2 with W2, J3 with W3. Settings file contains witness W2. Recovery cannot determine which journal record corresponds to W2 and should be marked complete.
**Prevention**: Include the witness token value in each journal record and match it explicitly during recovery. Only mark the journal record complete whose recorded witness equals the witness found in settings. Alternatively, maintain only one pending record per operation type and overwrite it on retry.
## Failure 10: Concurrent install or uninstall operations corrupt state
**Scenario**: Process A starts uninstall, writes journal JA with witness WA. Process B starts uninstall concurrently, writes journal JB with witness WB, potentially overwriting JA. Process A writes settings with WA. Process B writes settings with WB, overwriting A's changes. Only WB remains in settings. Recovery finds WB, marks only JB complete, leaves JA pending despite having completed.
**Prevention**: Acquire an exclusive advisory lock at the start of every command and hold it until the final journal write completes. The lock scope must include both settings and journal writes. Refuse to proceed if the lock cannot be acquired.
## Common root causes
Multiple failures share root causes:
- Using witness presence as proof rather than witness equality to a specific expected value
- Creating new intent records on retry instead of reusing or overwriting prior attempts
- Resolving ambiguity in the direction that removes or claims rules rather than preserving and reporting
- Treating completion as boolean rather than graduated partial, complete, failed
- Lacking correlation between journal records and the witness tokens that validate them
- Missing concurrency control between independent processes
## Limits
This is reasoned adversarial analysis. No tests were executed. Scenarios assume specific design choices: separate journal and settings files without shared transactions, crash recovery based on witness token verification, and content comparison for detecting user modifications. Other designs may encounter different failures or avoid some of these.