Design question about an installer that adds a small fixed set of exact permission allow rules to a developer tool settings file that users also edit by hand. Repair must restore missing managed rules, and uninstall must remove only what the installer introduced, while never deleting a rule the user already had and never weakening an explicit deny. Known constraints: rules are exact strings, the settings file is shared mutable state, and setup can be interrupted between persisting an ownership record and writing settings, so the record and the file can disagree in either direction. Open questions: what minimal per-rule ownership metadata makes removal decidable, what write ordering plus reconciliation on next run makes both interruption directions self-healing, how to classify a rule the user later added independently that duplicates a managed one, and whether deny precedence should be treated purely as an evaluation-time rule or also as an install-time refusal to add a conflicting allow. Interested in prior experience with journal plus reconcile approaches versus marker based ownership for third party managed config entries.
How should an installer track ownership of permission allow rules for safe repair and uninstall?
Four refinements reached by reasoning about the crash window. No tests were executed; these are arguments, not measurements.
One. An unforgeable commit witness beats inferring landing from rule content. Before writing, generate a random token and include it in an installer namespaced metadata key written in the same atomic replacement as the rules. On the next run the pending record names the expected token. Token present means the write landed, token absent means it did not, and no coincidence of user editing can forge either verdict. This removes the dependence on whole file hashing, which is unreliable because the host application may reformat the file on its own schedule. Where the settings format forbids extra keys, the weaker fallback is the pre-write file identity, since an atomic replace by rename changes identity, but that evidence decays once any later writer replaces the file again.
Two. Repair versus deliberate deletion is resolvable by tombstoning at observation time rather than at deletion time. The installer cannot see the deletion happen, but any command that loads settings can notice that a rule marked owned is now absent and record a released marker in the journal immediately. The first repair after a deletion then still has no marker and may ask or re-add, but every later repair sees the marker and stays silent. Without this, repair either nags forever or silently re-grants a permission the developer removed on purpose.
Three. A duplicate of a managed rule should not withdraw removal authority permanently. Treating any count other than the recorded one as absorbing ambiguity means a single user duplication makes clean uninstall impossible forever. Removing the smaller of the recorded count and the current count is safer and terminates. If the installer recorded one occurrence and now two exist, deleting one leaves the developer copy intact, so the effective permission set is unchanged and the developer loses nothing. The invariant that matters is not occurrence parity, it is that the resulting grant set never loses a grant the developer authored.
Four. Deny precedence deserves an install-time refusal and not only evaluation-time shadowing. If an explicit deny already covers a rule in the managed set, adding the shadowed allow looks harmless because evaluation rejects it anyway. The hazard is deferred: when the developer later removes the deny for an unrelated reason, the forgotten allow silently activates a permission they never granted. Recording the rule as blocked, skipping the write and reporting it keeps the deny as the single place where the decision lives. The same argument says uninstall must never touch a deny, and that a blocked entry is never later promoted to owned without a fresh install-time decision.
Open question for anyone who has shipped this: whether the metadata token approach survives host applications that strip unknown keys during their own rewrites, which would turn every such rewrite into a false not-landed verdict.
Refinement covering the case where the developer edits an owned rule and unrelated settings before uninstalling. Reached by reasoning; no tests were executed.
One. An edited owned rule and a deleted owned rule are the same decision. With exact string values, the removal test is only whether the recorded value is still present in the recorded container. If it is absent, the effect is gone, nothing is removed, and ownership has passed to the developer. Do not try to recognise the new neighbouring value as a descendant of the recorded one. Array position is not identity, so inferring lineage from adjacency is exactly the content based ownership inference the whole design exists to avoid. Report both observations separately, that the recorded value is absent and that an unrecorded value occupies the same container, without asserting a relationship between them.
Two. Re-planning after a not landed verdict is more dangerous than the crash it recovers from. The recovery window is unbounded, so a plan built before the interruption may name values the developer has since edited. Executing that stale plan deletes a developer authored value while believing it is removing an installer one. The rule is that a not landed verdict discards the plan entirely and re-runs the compare before remove step against the file as it exists now. Only the verdict survives recovery, never the plan.
Three. Resolving a pending record is not the same as executing it. If the developer reinstalls after an interrupted uninstall, recovery should decide what happened and update the journal, but must not carry out the interrupted removals. Conflating the two lets a stale uninstall fire in the middle of an install.
Four. A commit token gives uninstall a positive witness in both directions, and incidentally removes the empty plan hazard. Have the uninstall write set the installer metadata block to a terminal marker carrying the uninstall run token rather than deleting the block, and delete the block in a later cleanup write. Uninstall token present means the removal write landed. Install token still present means it did not. If an interruption leaves an orphan terminal marker it is inert, and the next run of any command clears it. Because every write now carries at least one witnessed effect, a landed verdict can no longer be computed over an empty effect set and come back vacuously true, which was a hazard when the plan happened to contain no removals.
Five. Preserving unrelated edits requires proving the editor is lossless before trusting it. Patching the live document rather than restoring a snapshot is necessary but not sufficient, because a parse and re-serialise round trip can silently drop comments, key order or unknown keys, which destroys developer edits that have nothing to do with the managed set. A cheap gate is to parse the file, re-serialise with no mutation applied, and compare bytes with what was read. If they differ, the editor is not lossless for this file and the run should fall back to a targeted textual edit or abort with a report rather than rewrite.
Six. An ambiguous verdict must never resolve toward deletion. Leaving an installer rule behind is recoverable by a later explicit command. Deleting a developer value on a guess is not. The asymmetry should be stated as a design rule so nobody optimises it away later in the name of clean uninstalls.
Still open, and the same question as before in a new form: whether hosts that strip unknown keys during their own rewrites make the metadata block unusable as a witness, since that would also strip the terminal marker and turn a landed uninstall into an ambiguous one.