fix: platform reads #61's actual manifest schema, not invented keys
The reader asked for `version` and `bootstrapped`. #61 specifies `schema`, `bootstrapped_by`/`bootstrapped_at` and `converged_by`/`converged_at` — so no writer would ever have produced the keys being read, and the day #61 landed this command would have rendered 'unknown' with the timestamp omitted, forever, with nothing to say why. Keyed to #61's spelling, with fixtures carrying that schema verbatim so the contract is pinned rather than assumed. Birth and latest are reported separately and neither is inferred from the other: under #61 rule 2 converged_* is written only when the version differs, so its absence is a legitimate state on a freshly bootstrapped box, printed 'not recorded' rather than backfilled from birth. A manifest whose schema this rig does not know is named as such instead of being half-read in silence. Found in review of #74. Refs #64
This commit is contained in:
parent
3cfbb8921c
commit
91a8905a71
4 changed files with 70 additions and 16 deletions
|
|
@ -29,8 +29,11 @@ on the way to cutting its first release, and this file starts there.
|
|||
the harness can RUN for real instead of grepping: the tests assert the
|
||||
actual answer describes the actual test machine. Provenance is read, never
|
||||
written, and degrades per-file — `/etc/rig/manifest` is #61 and does not
|
||||
exist yet, so that line reads `not bootstrapped` on every machine today and
|
||||
nothing else depends on it. Named `platform` and not `status` on purpose:
|
||||
exist yet, so those lines read `not bootstrapped` on every machine today and
|
||||
nothing else depends on it. The reader is keyed to #61's documented schema
|
||||
(`schema`, `bootstrapped_by`/`_at`, `converged_by`/`_at`) and fixtures pin
|
||||
that exact spelling, so the integration cannot land silently broken; birth
|
||||
and latest stay separate rather than one being inferred from the other. Named `platform` and not `status` on purpose:
|
||||
`users status` and `runner status` cross-check recorded against live state
|
||||
and print `DRIFT`, and a command that records nothing cannot drift — which
|
||||
also leaves `rig status` free for the machine-wide roll-up. Known
|
||||
|
|
|
|||
22
README.md
22
README.md
|
|
@ -738,7 +738,8 @@ DISK 456Gi total, 201Gi free on /
|
|||
VIRT kvm
|
||||
|
||||
PROVENANCE
|
||||
RIG 0.4.0, bootstrapped 2026-07-19T14:24:51Z
|
||||
CONVERGED 0.6.0, 2026-08-02T09:11:03Z
|
||||
BOOTSTRAP 0.4.0, 2026-07-19T14:24:51Z
|
||||
ROLE dev (class=human host=yes join=authkey)
|
||||
```
|
||||
|
||||
|
|
@ -763,11 +764,20 @@ needs no root, makes no network call, and writes nothing, ever.
|
|||
|
||||
The `PROVENANCE` block is the complementary half — which rig, and when, which
|
||||
is *decided* rather than observed, so it is stored. It is **read, never
|
||||
written**: `RIG` comes from `/etc/rig/manifest` and `ROLE` from
|
||||
`/etc/rig/role`. Neither file is required — a machine missing one reads `not
|
||||
bootstrapped` for that line, which is itself the useful answer. The manifest
|
||||
is #61 and is not implemented yet, so today that line reads `not bootstrapped`
|
||||
on every machine; nothing else in the command depends on it.
|
||||
written**: `CONVERGED`/`BOOTSTRAP` come from `/etc/rig/manifest` and `ROLE`
|
||||
from `/etc/rig/role`. Neither file is required — a machine missing one reads
|
||||
`not bootstrapped` for that line, which is itself the useful answer. The
|
||||
manifest is #61 and is not implemented yet, so today those lines read `not
|
||||
bootstrapped` on every machine; nothing else in the command depends on it.
|
||||
|
||||
**The two dates are deliberately separate**, matching #61's schema: `BOOTSTRAP`
|
||||
is birth (`bootstrapped_by`/`bootstrapped_at`, first-write-wins, pinned
|
||||
forever) and `CONVERGED` is latest (`converged_by`/`converged_at`, updated only
|
||||
when the converging version actually differs). That distinction is what answers
|
||||
"is this machine still converged by a rig that predates the fix?" — so
|
||||
`CONVERGED` reads `not recorded` rather than being backfilled from birth on a
|
||||
box that has only ever been bootstrapped once. A manifest whose `schema=` this
|
||||
rig does not know is named as such instead of being half-read in silence.
|
||||
|
||||
**Known limitation — `CPU` and `MEMORY` inside a container-style guest are
|
||||
unverified.** `CPU` and `MEMORY` are read straight from `/proc/cpuinfo` and
|
||||
|
|
|
|||
|
|
@ -155,10 +155,29 @@ manifest_field() { # $1 = key — empty when absent, unreadable or unset
|
|||
}
|
||||
|
||||
printf '%s\n' "PROVENANCE"
|
||||
# Keys are #61's documented schema verbatim — schema/bootstrapped_by/
|
||||
# bootstrapped_at/converged_by/converged_at — NOT invented ones. #61 keeps
|
||||
# birth and latest deliberately separate ("is this machine converged by a rig
|
||||
# that predates the fix?"), so both are reported and neither is inferred from
|
||||
# the other: CONVERGED answers currency, BOOTSTRAPPED answers provenance.
|
||||
# Every field degrades independently, so a partial manifest from a future
|
||||
# schema still renders what it does carry.
|
||||
if [ -r "$MANIFEST" ]; then
|
||||
RIG_VER="$(manifest_field version)"
|
||||
RIG_WHEN="$(manifest_field bootstrapped)"
|
||||
field RIG "${RIG_VER:-unknown}${RIG_WHEN:+, bootstrapped $RIG_WHEN}"
|
||||
M_SCHEMA="$(manifest_field schema)"
|
||||
B_BY="$(manifest_field bootstrapped_by)"; B_AT="$(manifest_field bootstrapped_at)"
|
||||
C_BY="$(manifest_field converged_by)"; C_AT="$(manifest_field converged_at)"
|
||||
# A manifest with no schema= line is pre-#61; say so rather than render blanks.
|
||||
if [ -z "$M_SCHEMA$B_BY$B_AT$C_BY$C_AT" ]; then
|
||||
field RIG "manifest present but carries no recognised fields ($MANIFEST)"
|
||||
else
|
||||
# 'not recorded' rather than 'unknown': under #61's rule 2 converged_* is
|
||||
# written only when the version actually differs, so its absence is a
|
||||
# legitimate state on a freshly bootstrapped box, not a lost value.
|
||||
field CONVERGED "${C_BY:-not recorded}${C_AT:+, $C_AT}"
|
||||
field BOOTSTRAP "${B_BY:-not recorded}${B_AT:+, $B_AT}"
|
||||
[ -n "$M_SCHEMA" ] && [ "$M_SCHEMA" != "1" ] && \
|
||||
field NOTE "manifest schema=$M_SCHEMA is newer than this rig reads (expects 1)"
|
||||
fi
|
||||
else
|
||||
field RIG "not bootstrapped (no $MANIFEST)"
|
||||
fi
|
||||
|
|
|
|||
32
test/cli.sh
32
test/cli.sh
|
|
@ -1006,23 +1006,45 @@ check "platform: MEMORY carries real numbers" 0 "total," "$ROOT/bin/rig" platfor
|
|||
# not exist yet, so 'not bootstrapped' is the state of the world today and the
|
||||
# command must ship complete without it. Both paths driven against fixtures.
|
||||
PLATWORK="$(mktemp -d)"
|
||||
printf 'version=9.9.9\nbootstrapped=2026-07-19T14:24:51Z\n' > "$PLATWORK/manifest"
|
||||
# THE INTEGRATION CONTRACT (#61, found in #74 review): these fixtures carry
|
||||
# #61's documented schema VERBATIM — schema/bootstrapped_by/bootstrapped_at/
|
||||
# converged_by/converged_at. An earlier draft of this reader invented `version`
|
||||
# and `bootstrapped`, which no writer would ever have produced: the command
|
||||
# would have rendered 'unknown' forever the day #61 landed, and nothing here
|
||||
# would have said so. Keep these keys in step with #61; that is the point.
|
||||
printf 'schema=1\nbootstrapped_by=0.4.0\nbootstrapped_at=2026-07-19T14:24:51Z\nconverged_by=0.6.0\nconverged_at=2026-08-02T09:11:03Z\n' > "$PLATWORK/manifest"
|
||||
check "platform: no manifest reads 'not bootstrapped'" 0 "RIG not bootstrapped" \
|
||||
env RIG_MANIFEST="$PLATWORK/absent" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
|
||||
check "platform: no role marker reads 'not bootstrapped'" 0 "ROLE not bootstrapped" \
|
||||
env RIG_MANIFEST="$PLATWORK/absent" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
|
||||
# A manifest that DOES exist is read, never written — the forward-compatible
|
||||
# half, so #61 landing needs no change here.
|
||||
check "platform: reads the manifest version" 0 "9.9.9" \
|
||||
check "platform: reads #61's converged_by/at" 0 "CONVERGED 0.6.0, 2026-08-02T09:11:03Z" \
|
||||
env RIG_MANIFEST="$PLATWORK/manifest" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
|
||||
check "platform: reads the manifest timestamp" 0 "bootstrapped 2026-07-19T14:24:51Z" \
|
||||
check "platform: reads #61's bootstrapped_by/at" 0 "BOOTSTRAP 0.4.0, 2026-07-19T14:24:51Z" \
|
||||
env RIG_MANIFEST="$PLATWORK/manifest" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
|
||||
# Birth and latest stay SEPARATE: #61 rule 2 writes converged_* only when the
|
||||
# version actually differs, so its absence on a freshly bootstrapped box is a
|
||||
# legitimate state — it must not be silently backfilled from bootstrapped_*.
|
||||
printf 'schema=1\nbootstrapped_by=0.4.0\nbootstrapped_at=2026-07-19T14:24:51Z\n' > "$PLATWORK/manifest-birth"
|
||||
check "platform: unconverged box says so, never infers from birth" 0 "CONVERGED not recorded" \
|
||||
env RIG_MANIFEST="$PLATWORK/manifest-birth" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
|
||||
# A newer schema renders what it recognises and says the rest is unreadable,
|
||||
# rather than pretending a partial read is the whole truth.
|
||||
printf 'schema=2\nbootstrapped_by=9.9.9\nbootstrapped_at=2027-01-01T00:00:00Z\n' > "$PLATWORK/manifest-v2"
|
||||
check "platform: a newer schema is named, not silently half-read" 0 "schema=2 is newer" \
|
||||
env RIG_MANIFEST="$PLATWORK/manifest-v2" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
|
||||
# A manifest carrying none of #61's keys is reported as such — the pre-#61 or
|
||||
# corrupt case, distinct from both 'absent' and 'read fine'.
|
||||
printf 'somethingelse=1\n' > "$PLATWORK/manifest-alien"
|
||||
check "platform: an unrecognised manifest is not read as empty" 0 "no recognised fields" \
|
||||
env RIG_MANIFEST="$PLATWORK/manifest-alien" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
|
||||
# ...including one whose last line has no trailing newline: `read` returns 1 at
|
||||
# EOF even having filled the variables, so an unguarded loop drops that line
|
||||
# silently — the timestamp would vanish while the version still rendered. #61's
|
||||
# writer must not have to know this reader's tolerances (found in #74 review).
|
||||
printf 'version=9.9.9\nbootstrapped=2026-07-19T14:24:51Z' > "$PLATWORK/manifest-nonl"
|
||||
check "platform: reads a manifest with no trailing newline" 0 "bootstrapped 2026-07-19T14:24:51Z" \
|
||||
printf 'schema=1\nbootstrapped_by=0.4.0\nbootstrapped_at=2026-07-19T14:24:51Z' > "$PLATWORK/manifest-nonl"
|
||||
check "platform: reads a manifest with no trailing newline" 0 "BOOTSTRAP 0.4.0, 2026-07-19T14:24:51Z" \
|
||||
env RIG_MANIFEST="$PLATWORK/manifest-nonl" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
|
||||
printf 'role=dev class=human host=yes join=authkey\n' > "$PLATWORK/role"
|
||||
check "platform: renders the role marker's traits" 0 "dev (class=human host=yes join=authkey)" \
|
||||
|
|
|
|||
Loading…
Reference in a new issue