carlos / platform Public

census: moves-offline extension for the release item; liveNotSealed reads the link only

The census owner's extension of census-ruling-moves-offline (platform-1c)
re-freezes landRun.release at its disposition (whole:Route@368, digest
492cffa9 to d589aea5) and accepts the new landRun.liveNotSealed as legacy:
it runs as the agent, is read-only and fails closed.

The acceptance carried a condition: the check compares the live link's
target string and follows nothing beyond the link. It called
release.ResolveLiveLink, which walks the chain (EvalSymlinks on the parent,
Lstat and Readlink on every hop), so it now does Lstat, Readlink and a
string comparison with the sealed build's VersionPath, as PointLive writes
it. A non-link at the live path fails the item too.

The internal/host envelope is re-pinned and the seal moves to b14f1723.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 3df4f7cf0b6e8b67e55ac09ed74ee890887a29b1 parent 8dc2a54
4 files changed, +28 −9
  • docs/superpowers/notes/census-proposal-moves-offline.md +1 −0
  • internal/host/movesoffline_land.go +15 −4
  • internal/provision/plan14_root_reads_test.go +6 −2
  • internal/provision/testdata/plan14-root-reads-moves-offline.tsv +6 −3
diff --git a/docs/superpowers/notes/census-proposal-moves-offline.md b/docs/superpowers/notes/census-proposal-moves-offline.md
index 87f884148..8f5131acc 100644
--- a/docs/superpowers/notes/census-proposal-moves-offline.md
+++ b/docs/superpowers/notes/census-proposal-moves-offline.md
@@ -145,3 +145,4 @@ regenerated the same way.
- **R1 (root-read units).** Accepted. The 39 new units are accepted legacy under their executing identities (the agent as carlos, the console, or the CLI; no root decision). The 4 changed legacy units are re-frozen, the 2 authority units are re-pinned at main's class and task, and the 10 envelopes are re-pinned. The seal moves to 914d2a18…fc6855 (833ae5ae…dff196 before the rev3 tag was rewritten to the ruling).
- **R2 (9B8).** Accepted as classified.
- **R3 (agentRunsAsRoot).** Accepted with a condition. The offline move must never run on a box whose agent actually runs as root. The runbook prechecks, read-only on every source-region box and the target box, that `systemctl show carlos-edge -p User` prints `User=carlos`. Any other value is a STOP.
+- **Extension (platform-1c, 2026-10-20, for 8dc2a544's release item).** `landRun.release` is re-frozen at its disposition (whole:Route@368, digest 492cffa9… to d589aea5…). `landRun.liveNotSealed` is accepted legacy under the same tag, on the condition that it compares the live link's Readlink target string with the sealed build's path and follows nothing beyond the link. It used `release.ResolveLiveLink`, which walks the chain, so it now does Lstat, Readlink and a string comparison; its sites are file:Lstat@172, file:Readlink@404, registry:App@537, whole:Route@516, whole:Route@539. The internal/host envelope is re-pinned, and the seal moves to b14f1723…570637.
diff --git a/internal/host/movesoffline_land.go b/internal/host/movesoffline_land.go
index 8ac434d5a..97cea3d12 100644
--- a/internal/host/movesoffline_land.go
+++ b/internal/host/movesoffline_land.go
@@ -1214,24 +1214,35 @@ func (r *landRun) release(ctx context.Context) {
// item again, never releases the hold over it. No link is fine: nothing can
// run until adoption stages the sealed build. The link is only read here,
// never changed. The error is the box's log line.
+//
+// The check reads the link itself and nothing beyond it (the census ruling
+// on this unit): Lstat, then Readlink, then a string comparison of the
+// target with the sealed build's path, exactly as PointLive writes it. It
+// never follows the link to stat or open what it names, so a target that
+// reaches the sealed build only through another link or a relative
+// spelling fails, and so does a live path that is not a symlink.
func (r *landRun) liveNotSealed() error {
optDir := r.cfg().OptDir
if optDir == "" {
optDir = release.OptDir()
}
link := release.LiveLink(optDir, r.host)
- if _, err := os.Lstat(link); errors.Is(err, os.ErrNotExist) {
+ fi, err := os.Lstat(link)
+ if errors.Is(err, os.ErrNotExist) {
return nil
} else if err != nil {
return err
}
- id, err := release.ResolveLiveLink(optDir, r.host)
+ if fi.Mode()&os.ModeSymlink == 0 {
+ return fmt.Errorf("%s is not a symlink (%s)", link, fi.Mode().Type())
+ }
+ target, err := os.Readlink(link)
if err != nil {
return err
}
want := release.VersionPath(optDir, release.RouteAccount(*r.rt), r.seal.Release, r.rt.App)
- if id.Version != r.seal.Release || id.StagedPath != want {
- return fmt.Errorf("%s names build %q at %s, the seal recorded %q at %s", link, id.Version, id.StagedPath, r.seal.Release, want)
+ if target != want {
+ return fmt.Errorf("%s names %s, the seal recorded %q at %s", link, target, r.seal.Release, want)
}
return nil
}
diff --git a/internal/provision/plan14_root_reads_test.go b/internal/provision/plan14_root_reads_test.go
index 3a2f99c01..b873d2714 100644
--- a/internal/provision/plan14_root_reads_test.go
+++ b/internal/provision/plan14_root_reads_test.go
@@ -961,11 +961,15 @@ func TestPlan14RootReadCensus(t *testing.T) {
// decision, so they are proposed accepted legacy at their moves
// siblings' dispositions; four changed legacy units are re-frozen and
// two authority units re-pinned at main's class. 43 frozen declarations
- // are added, so the seal moves.
+ // are added, so the seal moves. The ruling's extension (platform-1c,
+ // for 8dc2a544's release item) re-freezes landRun.release at its
+ // disposition and accepts landRun.liveNotSealed as legacy, on the
+ // condition that it compares the live link's Readlink target string and
+ // follows nothing beyond the link; 44 frozen declarations in all.
if err = loadRootReadInventory(filepath.Join(root, "internal/provision/testdata/plan14-root-reads-moves-offline.tsv"), &inv, true); err != nil {
t.Fatal(err)
}
- seal = "914d2a18ce4c93959954a95ea858426c85d900f6225084e262a8d2ec59fc6855"
+ seal = "b14f1723a516d4c95d68b044773b0774f74e7369d22f2d09e8e1c667e7570637"
errs := append(compareRootReads(got, inv), checkRootReadLegacy(inv, seal)...)
errs = append(errs, checkRootReadDeclarations(got, inv)...)
if len(errs) > 0 {
diff --git a/internal/provision/testdata/plan14-root-reads-moves-offline.tsv b/internal/provision/testdata/plan14-root-reads-moves-offline.tsv
index 7b356aa57..ddfc6dc42 100644
--- a/internal/provision/testdata/plan14-root-reads-moves-offline.tsv
+++ b/internal/provision/testdata/plan14-root-reads-moves-offline.tsv
@@ -1,10 +1,11 @@
# Census overlay moves-offline (the offline operator move: docs/superpowers/plans/2026-10-20-offline-operator-move.md), loaded LAST, after bootstrap-carlos-follows-316. RULED (census-ruling-moves-offline, platform-1c, 2026-10-20), accepted as proposed; every row is rev3=census-ruling-moves-offline, and the ruling is asked of the census owner (platform-1c). The proposal, with each unit's executing identity: docs/superpowers/notes/census-proposal-moves-offline.md.
# Every new root-read unit runs as the agent (carlos-edge.service, user carlos), the console (user carlos-console) or the carlos CLI on a person's machine, and makes no root decision, so each is proposed accepted legacy on census-ruling-carlos-run's footing, at the disposition main gives its moves siblings (J1 root-route for registry and route reads, J4 root-input for file reads). In a root process the armed moves worker is nil, so reconcileSerializedWith adds no offline hook there.
# Four changed legacy units are re-frozen at main's disposition with the change named in their basis (edgesFileLoop, NewS3Server, archive.walk, mover.roundTrip). Two authority units (fastConvergeLoop B3, armMovesPass B,C) are re-pinned at main's class and task. The accepted-legacy rows add 43 frozen declarations, so the seal moves. Ten source envelopes are re-pinned.
+# Extension of the ruling (platform-1c, for 8dc2a544's release item): landRun.release is re-frozen at its disposition with its new digest; landRun.liveNotSealed is accepted legacy on the condition that it compares the live link's Readlink target string and follows nothing beyond the link (44 frozen declarations); the internal/host envelope is re-pinned.
@coverage . 1d5649fef5f08e01c5b974b164e2aae3c5178f281601f6ffcb2df89fb1ab5fc2
@coverage internal/cgroup 59eaf7077de51aad79f5370fd21972e2b8782ffc76f7223f95e3efab4e47c0ed
@coverage internal/console f500b73a74639435526caee7592de07ce79936a3b09870203c379dc70255c999
-@coverage internal/host 4cb244f10264f758b41ef0b24879b6c79892622b374e36428764742eda76420b
+@coverage internal/host 87f132ee6b10faa94c53fc1c7959d4c730bead49fc4fc643868fa8d673226e11
@coverage internal/layout ad22438dbe7560e52e57fa201f94cebab357cfc0627965c9aae89fdfcf52043a
@coverage internal/lease 6b6e9501d36079f0efbfc3a3739b09ff0e40837f2cb986a1ce6638dc3cd1bd87
@coverage internal/lease/leasetest 36f174cae2871a12582d804ac8887ca43ae51ad4421bd645eaabbbac4c5387fd
@@ -57,10 +58,12 @@ internal/host/movesoffline_land.go landRun.config legacy accepted-legacy accepte
internal/host/movesoffline_land.go landRun.env legacy accepted-legacy accepted-legacy;rev3=census-ruling-moves-offline;basis=root-input (J4, as main's moves units); the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): new, reads the landed env file and rendered configuration to compare with the seal's sha256s file:ReadFile@122,file:ReadFile@720 8c26fe55bec8d23180f0819b77d49b1a73f0ab0156f238f230d770cecc1e4da4
@legacy ab73461b3e38dfeac1ab0a0640da8f016bd5bd42e222e46f35e269aea93c0e23 internal/host/movesoffline_land.go landRun.envPin legacy accepted-legacy accepted-legacy;rev3=census-ruling-moves-offline;basis=root-route (J1, as main's moves units); the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): new, reads the held row for LaunchLayers' composed environment, compared with the seal's portable digest whole:Route@699 1033516d233bafb55febb2c02331e3afe5a9fd63a3bad540cc6ae712c56ac3d3
internal/host/movesoffline_land.go landRun.envPin legacy accepted-legacy accepted-legacy;rev3=census-ruling-moves-offline;basis=root-route (J1, as main's moves units); the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): new, reads the held row for LaunchLayers' composed environment, compared with the seal's portable digest whole:Route@699 1033516d233bafb55febb2c02331e3afe5a9fd63a3bad540cc6ae712c56ac3d3
+@legacy 196a35eaec4c55a0214e245b9c93b0dd60f9d0f69fc031075604ba223f259204 internal/host/movesoffline_land.go landRun.liveNotSealed legacy accepted-legacy accepted-legacy;rev3=census-ruling-moves-offline;basis=route-and-input (J1,J4, as main's sourceFinal.run); the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): new, the release item's second half; reads only the target's live link for the host (Lstat, then Readlink, never following it to stat or open its target) and compares the target string with the sealed build's path from the held row; read-only, it changes nothing, and any other target, a non-link or an error fails the item closed file:Lstat@172,file:Readlink@404,registry:App@537,whole:Route@516,whole:Route@539 0242dbc6c3bbeddf0c17a6b1e04aa3d81236ff4485a707ec558978382a578c0f
+internal/host/movesoffline_land.go landRun.liveNotSealed legacy accepted-legacy accepted-legacy;rev3=census-ruling-moves-offline;basis=route-and-input (J1,J4, as main's sourceFinal.run); the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): new, the release item's second half; reads only the target's live link for the host (Lstat, then Readlink, never following it to stat or open its target) and compares the target string with the sealed build's path from the held row; read-only, it changes nothing, and any other target, a non-link or an error fails the item closed file:Lstat@172,file:Readlink@404,registry:App@537,whole:Route@516,whole:Route@539 0242dbc6c3bbeddf0c17a6b1e04aa3d81236ff4485a707ec558978382a578c0f
@legacy 73d2a509d08e9d1af690e37bfd16d9b4fed62e4eb5af3c2946686de892bff983 internal/host/movesoffline_land.go landRun.nextDue legacy accepted-legacy accepted-legacy;rev3=census-ruling-moves-offline;basis=root-route (J1, as main's moves units); the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): new, sets the held row's NextDue to the seal's and reads it back registry:NextDue@34,registry:NextDue@386,whole:Route@36,whole:Route@388 169ab1633a7a87651c56a87c7e419d263038fbb35185beb478c330824b0c7115
internal/host/movesoffline_land.go landRun.nextDue legacy accepted-legacy accepted-legacy;rev3=census-ruling-moves-offline;basis=root-route (J1, as main's moves units); the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): new, sets the held row's NextDue to the seal's and reads it back registry:NextDue@34,registry:NextDue@386,whole:Route@36,whole:Route@388 169ab1633a7a87651c56a87c7e419d263038fbb35185beb478c330824b0c7115
-@legacy 7c675cdf178131d6c1e57e690b5d2d065e2033e5d22be385e1773e29e61cdb3c internal/host/movesoffline_land.go landRun.release legacy accepted-legacy accepted-legacy;rev3=census-ruling-moves-offline;basis=root-route (J1, as main's moves units); the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): new, reads the held row's channel to compare its build with the seal's whole:Route@368 492cffa9ec2601d9dd15014bc493b4c7f3772237df269a245367e325455fae6d
-internal/host/movesoffline_land.go landRun.release legacy accepted-legacy accepted-legacy;rev3=census-ruling-moves-offline;basis=root-route (J1, as main's moves units); the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): new, reads the held row's channel to compare its build with the seal's whole:Route@368 492cffa9ec2601d9dd15014bc493b4c7f3772237df269a245367e325455fae6d
+@legacy 9fd7b9828d639ca270968c0849e9fabfc2dd26cdde62512b5a2064651176320d internal/host/movesoffline_land.go landRun.release legacy accepted-legacy accepted-legacy;rev3=census-ruling-moves-offline;basis=root-route (J1, as main's moves units); the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): new, reads the held row's channel to compare its build with the seal's whole:Route@368 d589aea52cc3810373426d2e6e95041eeeacceb7e872c017b86cfb2ee982c597
+internal/host/movesoffline_land.go landRun.release legacy accepted-legacy accepted-legacy;rev3=census-ruling-moves-offline;basis=root-route (J1, as main's moves units); the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): new, reads the held row's channel to compare its build with the seal's whole:Route@368 d589aea52cc3810373426d2e6e95041eeeacceb7e872c017b86cfb2ee982c597
@legacy 59f3a72885a0b6031a82f9110bad2dec8d8cae109c01642ff3069de3bf1b7460 internal/host/movesoffline_land.go landRun.replication legacy accepted-legacy accepted-legacy;rev3=census-ruling-moves-offline;basis=root-route (J1, as main's moves units); the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): new, sets the held row's replication rung to the seal's and reads it back registry:Replication@38,registry:Replication@430,whole:Route@40,whole:Route@432 0a01d500ad7df33b758fa029db808e15083e8fc0de6533f56ecdecddc2cddb6a
internal/host/movesoffline_land.go landRun.replication legacy accepted-legacy accepted-legacy;rev3=census-ruling-moves-offline;basis=root-route (J1, as main's moves units); the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): new, sets the held row's replication rung to the seal's and reads it back registry:Replication@38,registry:Replication@430,whole:Route@40,whole:Route@432 0a01d500ad7df33b758fa029db808e15083e8fc0de6533f56ecdecddc2cddb6a
@legacy d1b0cc18dd42253f9190bad0d98f8ab482351f282849f8187d0740365b61c410 internal/host/movesoffline_land.go landRun.reread legacy accepted-legacy accepted-legacy;rev3=census-ruling-moves-offline;basis=root-route (J1, as main's moves units); the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): new, re-reads the row after a column write whole:Route@246,whole:Route@251,whole:Route@96 ebb86b70b728cfefc2c6962c1ed6d582e8259a6527e40e580196fd3cae807c57