a73x

aee1395c

docs: record what the decisions rest on

a73x   2026-08-06 09:12

Commit message
docs: record what the decisions rest on

Every settled choice depends on claims that could be false. assumptions.md
names them beside the decision they underpin, and says for each whether it is
proven, partly proven, or still taken on trust—so the untested ones are
visible rather than implied.

docs/README.md
Old New
@@ -31,3 +31,5 @@ By what you're trying to do:
31 31
32 - [decisions.md](decisions.md)—the settled decisions, the alternatives they 32 - [decisions.md](decisions.md)—the settled decisions, the alternatives they
33 beat, and the reasons 33 beat, and the reasons
34 - [assumptions.md](assumptions.md)—what those decisions rest on, and which
35 claims are proven versus still taken on trust
docs/assumptions.md
Old New
@@ -0,0 +1,71 @@
1 # Assumptions
2
3 What the decisions rest on. Every entry is a claim that could be false, the
4 decision that would be wrong if it were, and how we know—or that we don't.
5 Three lines each. For the choices themselves, see [decisions.md](decisions.md).
6
7 Write one down whenever a decision is made. An assumption nobody recorded is
8 one nobody can re-check when the ground moves.
9
10 ### A guest's address is host-local
11
12 Nothing outside a host ever dials a guest: the gate resolves a name to
13 (host, VM) and tunnels over the sync connection, and the agent on that host
14 does the dial. Underpins putting network attachment inside the provisioner.
15 **Proven**: traced in code, and live—gate SSH reaches guests on two hosts.
16
17 ### The reservation table is the used-address set
18
19 The agent's DHCP responder builds its allocation exclusion list from the same
20 map it stores reservations in, under one lock. This is why replaying
21 reservations at startup makes address collisions impossible, and why the
22 address hint was redundant enough to delete.
23 **Proven**: verified in code; a new VM has never taken a live guest's address.
24
25 ### An agent upgrade preserves running guests and their addresses
26
27 Replacing the binary under running VMs leaves them alive and re-adopts them
28 with the same addresses. Underpins rolling agents to a live fleet at all.
29 **Proven** 2026-08-01 on bare metal: a guest created by the old agent survived
30 the swap, kept its address, and stayed reachable through the gate.
31
32 ### Old agents tolerate raw images
33
34 `qemu-img convert -O raw` auto-detects its input, so a raw image is copied
35 rather than rejected. This is what makes the rollout order safe—publish raw
36 and repoint the default *before* shipping the agent that drops conversion.
37 **Proven** 2026-08-01: converting a raw input with `-O raw` yields a
38 byte-identical copy at exit 0, with the input detected as raw. The claim is
39 about the tool, not a particular host—which is why it outlived the fleet's
40 last old-agent machine.
41
42 ### macOS hands out guest addresses; we can only read them
43
44 vmnet's DHCP assigns after the guest boots, and the lease is readable without
45 privileges. Underpins discovering the address rather than assigning it, and
46 rejecting both bootpd reservations and a userspace network stack.
47 **Partly proven**: lease read-back spiked on real hardware; no provisioner
48 consumes it yet.
49
50 ### Nobody depends on bring-your-own qcow2
51
52 Dropping conversion entirely—rather than keeping a fallback—assumes no user
53 supplies their own qcow2 image today.
54 **Unverified**: we have no telemetry on custom `image_url` use. The blast
55 radius is a permanent, legible failure at create, not silent breakage.
56
57 ### A laptop is a viable fleet host
58
59 A Mac that sleeps and wakes rejoins without intervention. Underpins enrolling
60 one at all.
61 **Partly proven**: the agent survived sleep and reconnected on its own—with
62 zero guests. What sleep does to a host *running* VMs is untested, and neither
63 reconcile nor lost-VM detection was designed for it.
64
65 ### Fleet hosts can reach the image server locally
66
67 Serving guest images from the box that serves eitri.sh assumes every host
68 reaches it over the LAN rather than hairpinning out through the uplink, and
69 that hosts stay on that LAN.
70 **Unverified**: one fleet host is a laptop that leaves the network, and a
71 public hostname resolving to a public address would route the long way round.
docs/decisions.md
Old New
@@ -2,7 +2,8 @@
2 2
3 Settled ground: the irreversible or contested choices, what they beat, and why. 3 Settled ground: the irreversible or contested choices, what they beat, and why.
4 Three lines each—when a rationale needs more, it lives in the relevant doc. 4 Three lines each—when a rationale needs more, it lives in the relevant doc.
5 For *how* we decide, see [ethos.md](ethos.md). 5 For *how* we decide, see [ethos.md](ethos.md); for what these rest on, see
6 [assumptions.md](assumptions.md).
6 7
7 ### Desired-state loop, not RPC 8 ### Desired-state loop, not RPC
8 9