installer v1.28.0: the removal genuinely reverses the installation (R-316)
gates / gates (push) Successful in 13s

v1.27.0's fix worked exactly once per machine. Measured on drill-r50 from virgin,
on the PUBLISHED v1.27.0, before anything was changed: cycle 1 recorded 'no' and
freed :53; cycle 2 recorded 'yes' and left dnsmasq running on 0.0.0.0:53; cycle 3
refused, exit 1. Every box already in the field is at cycle 2, and a reinstall
onto a machine that has had Felhom is cycle 2 by definition.

Why cycle 2 says yes: the preflight's ownership question is dpkg-query package
presence and nothing else - not the absence of a record. Stopping the unit and
leaving the package made our own package read as the household's one cycle later.

Now the uninstall removes the package when the record says we installed it. Order
unchanged and load-bearing: read the record, act, then delete the state file that
holds it. TWO packages are recorded, because dnsmasq ships the unit and
dnsmasq-base ships /usr/sbin/dnsmasq, and each is taken back only if we added it.

The dependency check is a SIMULATION, not a guess: apt-get -s purge is asked what
it would remove and the purge proceeds only if that set is a subset of ours;
otherwise stop+disable, naming the package that blocked it. Never interactive,
never fatal, and the success is re-queried rather than read off an exit code.

Watched: three fixed cycles -> install 3 PASSES; a household resolver untouched; a
dependent package not purged and named; no record -> untouched with the command
named. Red-proofs with the mutation asserted applied: remove the purge -> cycle 3
refuses in those exact words; remove the ownership check -> a household resolver is
purged; infer ownership -> the guess is taken.

Also: R-317 (the agent stats a path dnsmasq-base owns to decide whether to install
dnsmasq - pre-existing, now reachable), R-318 (no honest ownership marker exists
for existing boxes; the preflight message is the mechanism), and the status page's
decisions section rewritten to say what each decision costs and what doing nothing
selects.
This commit is contained in:
2026-08-13 08:16:04 +02:00
parent d102ca5767
commit fc737b0fc0
5 changed files with 239 additions and 21 deletions
+41 -17
View File
@@ -8,24 +8,44 @@
## Waiting on you
*(Vouched and delivered 2026-08-12 night: golden **0.214.0**, agent **0.129.0**, min agent **0.129.0**,
floor **0.214.0**. **Both demo machines are now on controller 0.214.0 + agent 0.129.0** — checked on the
boxes, not assumed. The safety guard was watched doing its job on the way: `demo-hp` was **held** at
0.213.0 while its agent was still 0.128.0 (*"agent 0.128.0 < MinAgent 0.129.0 — controller floor
withheld"*), and took the update 6 seconds after the agent caught up. That guard exists because a box
once landed on a controller newer than its agent and a customer was told a correct recovery code was
wrong; this is the first time it has been seen firing.)*
*Three decisions. Each says what it would cost to leave alone, because two of them quietly choose an
outcome if you do not answer. The register row is the detail, not the decision.*
- **R-312 — one decision, and it is the interesting one.** The customer is now told the truth about an
older code, but there is still no button: restoring from a set-aside copy means either threading an
alternative location through the restore code, or adopting that copy as the machine's current one.
The second is a different product decision. **Nothing is broken while this waits.**
- **R-313 — the copy you told me to keep cannot be opened by anyone.** `demo-felhom`'s set-aside store
holds 36 snapshots and one key, and that key was destroyed by the bug we fixed on 4 August. Keeping
it is still the right call; it should be a decision, not an accumulation.
- **R-303 — one coherence decision**, ranked low: a box can still raise the "we cannot open your new
backups" card while counting down to deleting the old ones. The two no longer contradict each other,
but the state is odd and the wrong fix would hide a real second fault.
### Should a customer be able to get their old backups back themselves, or is that a phone call?
Since Tuesday a machine recognises an older recovery code and says so honestly, but it cannot hand the
files over — it tells the person to write to us, and we can do it by hand.
- **Build it:** the restore code has to accept a second location and password instead of only its own.
Contained — three functions and a screen — plus one genuine design question: what a customer sees
when they have several old sets and must pick one.
- **Leave it:** nothing breaks. Every customer in this position becomes a support conversation, and we
keep a promise we can only keep manually.
**If you do nothing:** the honest message stays and the work never gets scheduled. Nobody is blocked;
this is the one decision here with no deadline of any kind. *(register: R-312)*
### The old copy on the demo machine cannot be opened by anyone. Keep paying to store it, or delete it?
You told me to keep it, and I did. Then I found out what it is: 36 backups and a single key, and that
key was destroyed by the bug we fixed on 4 August. **No recovery code in existence opens it.**
- **Keep it:** pennies of storage, and it stays as the one physical example of what that bug cost.
- **Delete it:** irreversible, and the example goes with it.
**If you do nothing:** it stays forever and stops being a decision — which is how five scratch
customers accumulated. Nobody is blocked. *(register: R-313)*
### When a machine is in two kinds of trouble at once, should it say both things?
A machine can count down to deleting its old backups while also reporting that it cannot open its new
ones. Both cards are true; together they are bewildering.
- **Leave it:** two true statements, confusing side by side. Nobody has been hurt by it.
- **Hide the older card during a countdown:** tidier, and it risks hiding a real second failure — which
is why I have not done it.
**If you do nothing:** both keep showing. Ranked low on purpose. *(register: R-303)*
## What works
@@ -52,6 +72,10 @@ repository still opens with the machine's own key. `drill-r50` is reverted to `v
fine, write to us*. It deliberately promises no restore, because there is no button yet.
- **The countdown on `demo-felhom` is cancelled** on your ruling (R-307). Nothing was deleted; the
24 August deadline is gone. See R-313 for what that copy turns out to be.
- **Vouched and delivered 2026-08-12**: golden 0.214.0, agent 0.129.0, floor 0.214.0 — both machines
took it themselves. The version guard was watched working on the way: `demo-hp` was **held** back
while its agent was older, and updated 6 seconds after the agent caught up. That guard exists because
a machine once ran ahead of its agent and a customer was told a correct code was wrong; first sighting.
- **Both installer fixes are now PUBLISHED** as `installer-v1.27.0` (R-297 + R-300). Each fault was
watched happening first, on a machine reset to factory state: the old installer really did build a
machine on a base image from July, and our own uninstall really did block our own next install.