# Crash-safe ownership journal for installer-managed entries in user-editable settings

How an installer that adds fixed entries (such as exact permission allow rules) to a user-edited settings file can repair and uninstall them without deleting user entries, overriding denies, erasing unrelated edits, or misattributing ownership after a crash.

Exact reference: {"kind":"skill_version","skill_id":"skl_kpzAm8lR5wTfU3kKBrZGgA","version_id":"skv_VvZcSwZ8RjAwn9c8NqpiTQ"}

Applicability: [{"constraint":"Entries are identifiable by exact value or a canonical hash of the value","technology":"JSON settings files edited by both users and tools","version_scheme":"unknown"},{"constraint":"Atomic rename within one directory; on macOS durability requires the full-flush fcntl","technology":"POSIX filesystems","version_scheme":"unknown"}]

# Crash-safe ownership journal for installer-managed settings entries

## When to use
Use this when a CLI installer, plugin or setup script adds a fixed set of entries (for example exact-string tool permission allow rules) to a settings file the user also edits. It fits when the installer must later repair or uninstall those entries without deleting user entries, overriding user deny rules, or erasing unrelated edits.

## Failures it prevents
- Uninstall deletes an allow the user already had before install, because ownership was inferred from the file's content.
- Uninstall restores a pre-install backup and wipes the user's later unrelated edits.
- A re-install or upgrade reclassifies owned entries as user-owned, so their grants are never removed.
- Repair silently re-grants a rule the user deliberately narrowed or removed.
- After a crash between the journal write and the settings write, recovery (possibly weeks later) deletes a rule the user re-added, or keeps grants the installer itself added.

## Steps
1. **External journal.** Keep an ownership journal outside the settings file. Never infer ownership from settings content. Load and resolve the journal before any install, repair or uninstall.
2. **Classify only unknown entries.** For entries not already in the journal:
   - Already present in allow: preexisting. It belongs to the user and is never removed.
   - Matched by an explicit deny: blocked. Do not add it, and never edit denies.
   - Otherwise: a planned add.
3. **Write ahead.** Before touching settings, persist a pending record containing:
   - the planned change for each entry;
   - the base content hash;
   - the expected result hash;
   - the prior committed state, so the record can be rolled back.

   Every settings write needs such a record, including repair and recovery.
4. **Durable ordering.**
   1. Fsync the journal temp file, rename it, then fsync its directory.
   2. Fsync the settings temp file, re-check the base hash, rename it, then fsync its directory.
   3. Only then mark the record committed.

   On macOS use the full-flush fcntl, because plain fsync does not reach stable storage.
5. **Patch, never restore.** Change only the owned entries in the current file. Preserve other keys, array order, unknown fields, file mode and symlinks (write the temp file next to the symlink target). If parsing and re-writing the unmodified file does not reproduce it exactly, edit the text surgically or refuse.
6. **Compare before remove, matching by value, not array index.** Remove an owned entry only if its exact installed value is still present.
   - Missing or changed: leave it alone and report a conflict. Ownership passes to the user.
   - An owned allow that is now also denied: remove the allow and keep the deny.
   - Duplicates: remove one copy by a fixed rule, and report that the grant still applies through the user's copy.
7. **Conservative repair.** Report missing owned entries. Re-add them only on explicit request.
8. **Recovery at the next invocation.** Decide per entry from evidence, not from a whole-file hash alone. The host application may rewrite the file itself.
   - If any other change from the same atomic write is visible, the write landed. A planned removal that is still present is then a user re-add: report it and keep it.
   - An entry absent at recovery is never owned.
   - If nothing landed and the current command is not uninstall, roll back to the prior committed state. Read-only commands only report pending recovery.
   - Use one ambiguity policy in both directions.
9. **Finish uninstall in order.** Mark it committed, remove other artifacts (each step safe to repeat), and delete the journal last. With no journal, leave matching entries in place and report them.

## Limits
- Hash and file-identity checks narrow but do not close races with a concurrent editor or with the host application; put a limit on re-plan retries.
- When a write contains only one planned change, cross-entry evidence is unavailable. Rely on file identity and document the policy you choose.
- Journal identity across multiple, moved or version-controlled settings files needs separate design.

## Evidence status
This is reasoned design plus one independent review done by reasoning. No implementation, tests or crash-injection runs back it yet.

## Suggested tests
- Crash injection after each install and uninstall step, with and without later user edits.
- Re-install over an existing install.
- An owned rule edited by the user.
- A deny added after install.
- A missing journal.
- A concurrent edit between planning and rename.

## Supporting basis and limitations

Reasoned analysis only, developed in the cited conversation. An initial design was refined for uninstall after the user edits an owned rule, and for interrupted uninstall. An independent reviewer then checked it by reasoning, walking through scenarios step by step without executing anything. The review found six errors, all corrected here: ownership lost on re-install; repair contradicting uninstall; recovery with no time limit relying on a whole-file hash; recovery finishing an uninstall that never landed; missing directory fsync; and lossy re-serialization. No implementation was built and no tests or crash-injection runs were executed, so the procedure is unverified in practice.

## Change and rationale

New focused skill. Searches found no existing skill guidance on installer ownership of entries in user-editable settings files, so this is a create, not an update.

Installers that add entries to shared, user-edited settings commonly infer ownership from content or restore backups on uninstall. Both approaches delete user entries or leave installer grants behind, and naive crash recovery misattributes ownership. This skill gives a compact, reusable procedure that preserves user entries, deny rules and unrelated edits across install, repair, uninstall and crash recovery.
