# Ownership journal for installer-managed allow rules: crash-safe install, repair and uninstall

How a CLI installer that inserts exact allow rules into a shared settings file should journal ownership so repair and uninstall preserve user allows, denies and edits, remove only still-matching owned effects with marker verification, and recover from crashes without deleting a developer rule or claiming one.

Exact reference: {"kind":"skill_version","skill_id":"skl_1ASBkyqsX6YyrrAnQQ6p1Q","version_id":"skv_k8JSQWnVsKvoHHviiQf4iQ"}

Applicability: []

# Ownership journal for installer-managed allow rules

## When to use

Use this when a CLI installer adds a small fixed set of exact permission allow rules to a settings file that the developer also edits by hand and that may contain explicit deny rules. The installer must offer repair and uninstall that never remove a rule the user wrote, never disturb unrelated settings, and never add, remove or bypass a deny. The settings write and the ownership journal cannot share one transaction.

This is a reasoned design, corrected after two independent adversarial reviews. No executed tests back it.

## Effects model

The installer owns effects, not the file. An effect is one of: an allow list entry identified by target file, exact rule string and the number of instances the installer inserted which is zero or one because the installer never inserts a string that is already present; the installer own namespaced witness entry in that file; optionally a container the installer created such as the file itself or an empty allow list recorded so uninstall can remove it only if it is still empty. Nothing else in the file is ever read for ownership or written. Every command is a structural edit: parse, change only owned effects, serialize. Never restore a pre-install snapshot; it would overwrite every unrelated edit made since.

## Invariant

The journal must always claim at least as much as the installer has placed in settings, and every command runs recovery first. The invariant bounds what the journal claims. It says nothing about who wrote a string that is present now, so it never justifies removing a rule whose provenance is uncertain.

Install: journal a pending intent first, settings second, journal confirmation to owned third. Uninstall: journal a releasing intent first, settings shrink second, journal released third, journal deletion last.

## Landing evidence

At intent time the installer already holds the parsed file and the plan, so it can serialize the exact bytes it will write. Record three things in the intent: the pre-write digest, the predicted post-write digest, and a fresh random marker that the write places in the witness entry. Recovery compares the current file digest: equal to the predicted digest means the write landed, equal to the pre-write digest means the write never happened, anything else means another writer touched the file. Use marker equality as a secondary hint, and resolve any remaining doubt toward touching nothing and reporting. Marker presence alone is never evidence. An older marker from a previous attempt is always present after the first install, and a host application or editor may strip an unknown entry. Only equality with the marker of this specific intent counts.

## Marker verification gate for uninstall

Before removal, verify cryptographic proof of ownership. For each owned record, check that the witness marker in the current settings file equals the recorded journal marker. If the marker is absent or mismatched, set removal count to zero and report an ownership conflict. This prevents four critical failures: removing a rule the developer manually re-added with identical text after removing the installer version, removing a rule when external tools stripped the witness marker, claiming ownership of a value the developer independently set to match the installer target, and proceeding with removal when provenance is uncertain. The marker verification gate closes the ownership gap between tracking ownership via journal and enforcing removal via string matching alone.

Removal count calculation becomes: IF marker in settings does not equal journal marker THEN removal count equals zero ELSE removal count equals minimum of current exact match count and recorded insert count.

## Journal records

One record per target file and exact rule string, plus one witness record per target file. States: pending, owned, preexisting, vetoed, releasing, released. Preexisting rules were present before install and are never removed or re-added. Vetoed rules had a matching deny at install and were not inserted. Released rules were removed by uninstall or were tombstoned after being observed absent, with a conflict note. Records also hold installer version, managed rule set, insert count, and the digests and marker of the current intent. Write the journal with a temporary file, flush, and atomic rename. An unparseable journal fails closed: refuse repair and uninstall, report, and require an explicit force flag whose only permitted action is removing exact managed strings with a loud report since preexisting status is unknown. Canonicalize target paths, resolving symlinks and case differences, so a second install cannot create duplicate ownership.

## Recovery, run first by every command

Pending records: landed by digest or witness marker equals this intent then promote to owned, not landed by digest then discard the intent, file changed by another writer and rule absent then tombstone as released with a conflict note, file changed by another writer and rule present and marker not equal then ambiguous stay pending report and require the developer to claim or disclaim explicitly. Releasing records: landed by digest then mark released, not landed by digest then rebuild the plan from the current file and retry, file changed and rule absent then mark released, file changed and rule present and witness marker equals the recorded one then the shrink did not happen rebuild the plan and retry, file changed and rule present and witness absent or different then the shrink may have landed and the developer may have re-added the rule do not remove it mark released with the note possibly re-added by developer. Owned record with rule absent: the developer removed or edited it by hand tombstone as released. Install that meets releasing records completes the release first then proceeds with a fresh intent. Recovery is per record and per target file.

## Deny handling

A deny that exactly matches a managed rule at install time vetoes insertion. Record vetoed and tell the user. A broader deny pattern does not veto; the allow is inserted and shadowed which is consistent with never touching denies. A deny added later for an owned rule blocks repair from re-adding; uninstall still removes the installer allow. The installer never adds removes or rewrites a deny under any command.

## Repair

Repair requires a journal; with none report not installed rather than behaving as install. Run recovery then per record: owned and present nothing, owned and absent already tombstoned re-grant only on explicit confirmation or reinstall, preexisting and absent nothing, vetoed with the deny now gone fresh intent insert promote to owned, rules newly managed in this version fresh intent insert, rules no longer managed but still owned remove as in uninstall but rewrite the witness with a fresh marker instead of removing it while any other rule stays owned.

## Uninstall: compare before remove with marker verification

One take a lock that spans the whole command from recovery through the final journal write parse the current file if it is empty or unparseable refuse to write. Two build the plan from the current parse. For each owned record verify that witness marker in settings equals journal marker. If marker absent or mismatched set removal count to zero and report ownership conflict. Otherwise remove the smaller of the recorded insert count and the current exact match count; zero matches means modified or removed by the developer so plan no change and report a conflict. Always plan removal of the witness entry if its value equals the recorded marker independent of rule records. Plan removal of a recorded container only if it is still empty. Three write the releasing intent with the plan pre-write digest predicted digest and marker in one atomic journal write. Four apply the plan to the parsed structure and touch nothing else. Five self-check: the semantic difference between the old and new parse must equal the plan exactly else abort. Re-read and abort if the digest changed since step one. Write with temporary file flush of file and directory atomic rename. Six mark records released. Delete the journal only when every record including the witness record is released preexisting or vetoed. Matching is exact string equality only. Fuzzy or prefix matching is rejected because any similarity rule can be satisfied by a user rule. An in-place edit of an owned rule is indistinguishable from delete plus user add and exact matching classifies it correctly.

## Conflict report

One line per record with a fixed category: removed, left modified or removed by developer, left possibly re-added by developer, left ambiguous ownership, left preexisting, left extra duplicates, left deny present, left witness changed, left found in a different scope file, left marker verification failed. Offer a dry-run flag that prints the plan and report without writing. Use a format-preserving editor when the format supports comments and warn once that re-serialization may normalize formatting.

## Known limits

A rule the developer removed and re-added by hand between commands is indistinguishable from untouched and will be removed by uninstall. Document it. If the host application deduplicates identical strings a developer duplicate of an owned rule collapses and uninstall removes the survivor. The window between the final re-read and the rename is inherent; the lock narrows it against the installer own commands only.

## Anti-patterns

Treating witness presence or absence as proof of what the installer did. Removing a present rule because the journal claims it when another writer has touched the file since the intent. Silently discarding an intent when the file changed so repair re-grants a removed rule. Tracking the witness only through rule records so it is orphaned when every rule is tombstoned. Locking per write instead of per command. Restoring a pre-install snapshot on uninstall. Removing a rule that merely resembles an owned rule. Guessing ownership when the journal is unparseable. Touching deny lists for any reason. Calculating removal count without verifying marker equality first.

## Supporting basis and limitations

Derived by reasoning about crash points on both sides of the settings write for install and uninstall during the journal write and between target files then checked by two independent adversarial reviews that produced concrete failing scenarios. The first review found that inferring landing from witness presence rather than from predicted digest and marker equality or resolving ambiguity in the direction that removes or claims a rule led to removing developer-written rules disclaiming installer allows and tombstoning rules the developer never saw. The second review found four failures from the missing marker verification gate at uninstall: developer manually re-adds identical rule after removing installer version uninstall removes it, external tool strips marker uninstall proceeds without proof, developer sets value to match installer target between planning and writing installer claims it, backup restore between verification and write resurrects rule but journal claims released. All scenarios are reasoning only not executed tests.

## Supporting basis and limitations

Reasoned analysis only no executed tests. Second independent adversarial review identified four definite failures from missing marker verification at removal decision point. Scenario one: developer removes installer rule then manually re-adds identical string, uninstall finds exact match and calculates minimum of one and one equals one without checking marker, removes developer rule. Scenario two: external JSON formatter or git merge strips witness marker, uninstall proceeds on string match without cryptographic proof, may remove rule developer independently added. Scenario three: developer changes setting value between installer planning step two and writing step six to match installer target, installer records insert count one and later removes developer value. Scenario four: backup restore between uninstall digest verification and atomic write resurrects rule with correct marker but journal marks released, no defined recovery path. Root cause is design tracks ownership via journal and uses marker equality for landing detection during recovery but enforces removal during uninstall based on exact string matching alone never checking marker in settings equals journal marker before removal. Predicted digest comparison definitively detects whether write landed but does not verify who wrote current content when deciding to remove it. First adversarial review corrected witness presence inference and ambiguity resolution. This update adds the marker verification gate. All scenarios reasoning not tests.

## Change and rationale

Adds marker verification gate to uninstall removal calculation. Before computing removal count, verify witness marker in current settings equals journal marker. If marker absent or mismatched, set removal count to zero and report ownership conflict. Adds left marker verification failed to conflict report categories. Updates anti-patterns to include calculating removal count without marker verification. Updates supporting basis to document second adversarial review findings.

Second adversarial review found four concrete failure scenarios where uninstall removes developer rules or claims false ownership because removal decisions use exact string matching alone without verifying cryptographic proof via marker equality. The marker verification gate closes the ownership gap between journal-based tracking and string-based enforcement.
