carlos / platform Public

ship: find docker or podman, ship a local image by name (rootfs Plan 1 Task 10)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 54dc05b149cd4e44d75008cc75bfed79b3133d43 parent 388a8d7
8 files changed, +836 −16
  • approved_rootfs_copy_test.go +4 −2
  • docs/superpowers/plans/2026-10-24-rootfs-apps-1-ship.md +2 −1
  • docs/superpowers/plans/2026-10-24-rootfs-apps-copy.md +2 −1
  • internal/rootfsimage/tar.go +87 −0
  • internal/rootfsimage/tar_test.go +144 −0
  • ship_rootfs.go +9 −12
  • ship_runtime.go +169 −0
  • ship_runtime_test.go +419 −0

CI failed — run details

CI log
=== gate ===
.amadan/test-gate.sh
=== launchctx (0 s)
ok  	amadan.net/carlos/platform.git/launchctx	0.015s
?   	amadan.net/carlos/platform.git/launchctx/controlname	[no test files]
?   	amadan.net/carlos/platform.git/launchctx/wireid	[no test files]
=== vet (17 s)
=== gofmt (0 s)
gofmt -l .: clean
=== rest (171 s)
?   	github.com/carlosframework/platform/cmd/changelog	[no test files]
ok  	github.com/carlosframework/platform/cmd/console	3.896s
ok  	github.com/carlosframework/platform/cmd/moveprobe	11.714s
ok  	github.com/carlosframework/platform/cmd/zddprobe	0.750s
ok  	github.com/carlosframework/platform/internal/activator	59.062s
ok  	github.com/carlosframework/platform/internal/agentsock	0.023s
ok  	github.com/carlosframework/platform/internal/alerting	0.003s
ok  	github.com/carlosframework/platform/internal/analytics	0.028s
ok  	github.com/carlosframework/platform/internal/appconfig	2.938s
ok  	github.com/carlosframework/platform/internal/apperr	0.095s
ok  	github.com/carlosframework/platform/internal/applog	0.176s
ok  	github.com/carlosframework/platform/internal/awsinv	0.005s
ok  	github.com/carlosframework/platform/internal/boxchoice	0.006s
ok  	github.com/carlosframework/platform/internal/boxid	0.765s
?   	github.com/carlosframework/platform/internal/boxid/boxidtest	[no test files]
?   	github.com/carlosframework/platform/internal/boxid/internal/signtest	[no test files]
ok  	github.com/carlosframework/platform/internal/boxvolumes	0.011s
ok  	github.com/carlosframework/platform/internal/caps	0.013s
ok  	github.com/carlosframework/platform/internal/certwarm	0.005s
ok  	github.com/carlosframework/platform/internal/cgroup	0.767s
ok  	github.com/carlosframework/platform/internal/changelog	0.404s
ok  	github.com/carlosframework/platform/internal/claimactivation	1.134s
ok  	github.com/carlosframework/platform/internal/clamd	0.058s
?   	github.com/carlosframework/platform/internal/cliflag	[no test files]
?   	github.com/carlosframework/platform/internal/controlname	[no test files]
?   	github.com/carlosframework/platform/internal/controlsock	[no test files]
ok  	github.com/carlosframework/platform/internal/dbdoor	7.672s
ok  	github.com/carlosframework/platform/internal/dbdoor/dbdoortest	0.017s
ok  	github.com/carlosframework/platform/internal/dbquery	0.006s
ok  	github.com/carlosframework/platform/internal/dbreads	2.101s
?   	github.com/carlosframework/platform/internal/dbreads/dbreadstest	[no test files]
ok  	github.com/carlosframework/platform/internal/dbverify	0.008s
ok  	github.com/carlosframework/platform/internal/dnsrec	0.008s
ok  	github.com/carlosframework/platform/internal/docsite	0.007s
ok  	github.com/carlosframework/platform/internal/domains	2.796s
ok  	github.com/carlosframework/platform/internal/doorkey	0.008s
ok  	github.com/carlosframework/platform/internal/economics	0.004s
ok  	github.com/carlosframework/platform/internal/edge	45.474s
?   	github.com/carlosframework/platform/internal/edgeproof	[no test files]
ok  	github.com/carlosframework/platform/internal/edgesfile	0.008s
ok  	github.com/carlosframework/platform/internal/fleetapi	0.133s
ok  	github.com/carlosframework/platform/internal/gate	1.654s
ok  	github.com/carlosframework/platform/internal/genselect	0.014s
ok  	github.com/carlosframework/platform/internal/geo	0.016s
ok  	github.com/carlosframework/platform/internal/geoip	0.030s
ok  	github.com/carlosframework/platform/internal/historyreadback	0.155s
ok  	github.com/carlosframework/platform/internal/host	143.605s
ok  	github.com/carlosframework/platform/internal/hostactors	5.830s
ok  	github.com/carlosframework/platform/internal/hostactors/awsmembership	0.016s
ok  	github.com/carlosframework/platform/internal/hostbox	3.022s
ok  	github.com/carlosframework/platform/internal/hostclaim	0.817s
ok  	github.com/carlosframework/platform/internal/hostenv	0.016s
ok  	github.com/carlosframework/platform/internal/hostevidence	0.012s
ok  	github.com/carlosframework/platform/internal/hostexec	5.336s
ok  	github.com/carlosframework/platform/internal/hostfence	0.067s
ok  	github.com/carlosframework/platform/internal/hostfiles	10.278s
ok  	github.com/carlosframework/platform/internal/hostfloor	0.027s
ok  	github.com/carlosframework/platform/internal/hostguard	1.062s
ok  	github.com/carlosframework/platform/internal/hostops	1.894s
?   	github.com/carlosframework/platform/internal/hostops/fencerelease	[no test files]
ok  	github.com/carlosframework/platform/internal/hostops/internal/fencerelease	0.016s
ok  	github.com/carlosframework/platform/internal/hostquarantine	0.005s
ok  	github.com/carlosframework/platform/internal/hostrelocate	0.692s
ok  	github.com/carlosframework/platform/internal/hostresolve	0.176s
ok  	github.com/carlosframework/platform/internal/hostwrite	0.004s
ok  	github.com/carlosframework/platform/internal/infraview	0.014s
ok  	github.com/carlosframework/platform/internal/instancectl	5.229s
ok  	github.com/carlosframework/platform/internal/instanceexec	2.853s
ok  	github.com/carlosframework/platform/internal/instancefs	0.015s
ok  	github.com/carlosframework/platform/internal/instancekey	0.013s
ok  	github.com/carlosframework/platform/internal/instanceupdates	0.015s
ok  	github.com/carlosframework/platform/internal/layout	1.749s
ok  	github.com/carlosframework/platform/internal/lbhealth	0.015s
ok  	github.com/carlosframework/platform/internal/lease	10.154s
ok  	github.com/carlosframework/platform/internal/lease/leasetest	0.599s
ok  	github.com/carlosframework/platform/internal/ledger	0.036s
ok  	github.com/carlosframework/platform/internal/mail	0.273s
ok  	github.com/carlosframework/platform/internal/maintenance	0.091s
ok  	github.com/carlosframework/platform/internal/maintenanceexec	5.596s
ok  	github.com/carlosframework/platform/internal/maintenanceguard	0.110s
ok  	github.com/carlosframework/platform/internal/metrics	0.008s
ok  	github.com/carlosframework/platform/internal/moves	22.305s
ok  	github.com/carlosframework/platform/internal/moves/archive	1.015s
ok  	github.com/carlosframework/platform/internal/objstore	0.282s
ok  	github.com/carlosframework/platform/internal/ops	0.225s
ok  	github.com/carlosframework/platform/internal/park	0.317s
ok  	github.com/carlosframework/platform/internal/plans	0.008s
ok  	github.com/carlosframework/platform/internal/privatefile	0.006s
2026/10/24 23:15:12 provision: listing apps/bab/blog/instances/: list refused — its records are unseen this pass
2026/10/24 23:15:12 provision: listing apps/bab/: listdirs refused — its records are unseen this pass
2026/10/24 23:15:12 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:12 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:12 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:12 provision: listing apps/bac/tito/instances/: list refused — its records are unseen this pass
2026/10/24 23:15:12 provision: listing apps/bac/tito/instances/: list refused — its records are unseen this pass
2026/10/24 23:15:12 provision: skipping record apps/bac/tito/instances/one.example.com.json: unreadable: read refused
2026/10/24 23:15:12 provision: listing apps/bac/tito/instances/: list refused — its records are unseen this pass
2026/10/24 23:15:12 provision: an app's records could not be listed: they are skipped
2026/10/24 23:15:12 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 23:15:12 provision: remove retired instance route shop.example: provision: claim admission unavailable
2026/10/24 23:15:12 provision: remove retired instance route shop.example: provision: claim admission unavailable
2026/10/24 23:15:12 provision: remove retired sidecar route worker.sidecar.internal: provision: claim admission unavailable
2026/10/24 23:15:12 provision: remove retired sidecar route worker.sidecar.internal: provision: claim admission unavailable
2026/10/24 23:15:12 provision: claim install acme.go.tito.io: provision: claim admission unavailable
2026/10/24 23:15:12 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:12 provision: claim install acme.go.tito.io: registry: claim row ownership changed or unknown
2026/10/24 23:15:12 provision: claim install bot.eleven.bac.sidecar.internal: provision: claim admission unavailable
2026/10/24 23:15:12 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 23:15:12 provision: claim install bot.eleven.bac.sidecar.internal: registry: claim row ownership changed or unknown
2026/10/24 23:15:12 provision: refusing to mint route acme.go.tito.io (app "tito" acct "bac"): this box declares CARLOS_INBOUND=none (no-inbound) and cannot serve routed instance traffic
2026/10/24 23:15:12 provision: acme.go.tito.io: not minting this pass: the box's layout intent could not be read: no sealed config
2026/10/24 23:15:12 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:12 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:12 provision: REFUSING to mint sidecar bot.eleven.bac.sidecar.internal: bot.eleven.bac.sidecar.internal-sidecar.env is staged on this box — the legacy file co-spawn and a native sidecar row are two mechanisms for one host; remove the file to migrate this host onto sidecar records
2026/10/24 23:15:12 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 23:15:12 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 23:15:12 provision: refusing to mint route acme.go.tito.io (app "tito" acct "bac"): this box declares CARLOS_INBOUND=none (no-inbound) and cannot serve routed instance traffic
2026/10/24 23:15:12 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:12 provision: REFUSING to mint sidecar bot.eleven.bac.sidecar.internal: bot.eleven.bac.sidecar.internal-sidecar.env is staged on this box — the legacy file co-spawn and a native sidecar row are two mechanisms for one host; remove the file to migrate this host onto sidecar records
2026/10/24 23:15:12 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 23:15:12 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 23:15:12 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:12 provision: claim install acme.go.tito.io: registry: claim row ownership changed or unknown
2026/10/24 23:15:12 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:12 provision: claim install acme.go.tito.io: registry: claim row ownership changed or unknown
2026/10/24 23:15:12 provision: bot.eleven.bac.sidecar.internal exists but is not a sidecar row this pass owns (kind "sidecar" provisioned false app "eleven" acct "bac") — leaving it alone
2026/10/24 23:15:12 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 23:15:12 provision: claim install bot.eleven.bac.sidecar.internal: registry: claim row ownership changed or unknown
2026/10/24 23:15:12 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 23:15:12 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:12 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 23:15:12 provision: bot.eleven.bac.sidecar.internal exists but is not a sidecar row this pass owns (kind "sidecar" provisioned false app "eleven" acct "bac") — leaving it alone
2026/10/24 23:15:12 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:12 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:12 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:12 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 23:15:12 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:12 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:12 provision: skipping record apps/bac/tito/instances/new.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:12 provision: not removing acme.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 23:15:12 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:12 provision: skipping record apps/bac/tito/instances/new.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:13 provision: minted instance route rh.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route ri.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route rk.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route re.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route rf.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route rj.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route rl.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route ra.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route rb.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route rc.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route rd.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route rg.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route rd.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route ra.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route rb.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route rc.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: skipping record apps/bac/tito/instances/rb.go.tito.io.json: read failed: read refused
2026/10/24 23:15:13 provision: skipping record apps/bac/tito/instances/rb.go.tito.io.json: read failed: read refused
2026/10/24 23:15:13 provision: minted instance route re.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route x.appa.example (app "appa" acct "bac")
2026/10/24 23:15:13 provision: minted instance route x.appb.example (app "appb" acct "bac")
2026/10/24 23:15:13 provision: minted instance route x.appc.example (app "appc" acct "bac")
2026/10/24 23:15:13 provision: minted instance route x.appe.example (app "appe" acct "bac")
2026/10/24 23:15:13 provision: minted instance route x.appf.example (app "appf" acct "bac")
2026/10/24 23:15:13 provision: minted instance route x.apph.example (app "apph" acct "bac")
2026/10/24 23:15:13 provision: minted instance route x.appj.example (app "appj" acct "bac")
2026/10/24 23:15:13 provision: minted instance route x.appd.example (app "appd" acct "bac")
2026/10/24 23:15:13 provision: minted instance route x.appg.example (app "appg" acct "bac")
2026/10/24 23:15:13 provision: minted instance route x.appi.example (app "appi" acct "bac")
2026/10/24 23:15:13 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 23:15:13 provision: minted instance route r0040.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0065.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0080.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0126.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0096.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0047.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0070.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0116.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0000.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0050.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0058.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0067.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0042.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0104.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0111.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0028.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0061.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0114.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0012.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0064.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0071.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0010.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0051.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0095.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0099.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0106.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0117.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0001.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0015.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0021.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0027.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0128.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0069.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0077.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0107.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0112.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0122.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0008.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0011.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0048.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0009.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0036.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0066.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0105.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0118.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0017.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0055.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0088.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0109.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0046.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0068.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0094.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0100.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0074.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0086.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0127.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0007.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0022.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0029.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0057.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0082.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0120.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0018.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0020.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0062.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0073.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0087.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0125.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0059.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0006.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0052.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0081.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0124.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0014.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0085.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0108.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0123.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0004.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0031.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0083.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0102.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0115.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0016.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0024.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0033.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0056.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0075.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0092.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0002.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0003.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0038.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0054.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0013.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0072.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0078.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0093.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0121.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0129.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0005.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0025.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0039.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0044.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0098.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0103.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0113.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0037.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0041.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0049.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0076.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0110.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0034.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0060.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0090.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0045.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0043.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0053.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0084.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0089.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0097.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0023.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0026.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0030.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0032.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0035.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0063.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0079.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0119.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0019.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0091.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:13 provision: minted instance route r0101.go.tito.io (app "tito" acct "bac")
--- FAIL: TestPlan9B8RecordWriteCensus (0.72s)
    plan9_b8_census_test.go:372: record-write census rejected 1 site(s); update the explicit inventory only after reviewing the source:
          changed site internal/release/rootfs_ship.go:establishShipKind: source differs from the reviewed digest
2026/10/24 23:15:14 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: refusing to mint route acme.go.tito.io (app "tito" acct "bac"): this box declares CARLOS_INBOUND=none (no-inbound) and cannot serve routed instance traffic
2026/10/24 23:15:14 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: minted instance route whole.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: minted instance route console.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: minted service route ha.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: minted service route svc.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: minted instance route shared.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: converged acme.go.tito.io channel stable -> edge
2026/10/24 23:15:14 provision: converged acme.go.tito.io channel edge -> canary/rehearsal
2026/10/24 23:15:14 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: empty channel
2026/10/24 23:15:14 provision: not removing acme.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 23:15:14 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: converged acme.go.tito.io environment "" -> "staging"
2026/10/24 23:15:14 provision: converged acme.go.tito.io environment "staging" -> ""
2026/10/24 23:15:14 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: converged acme.go.tito.io steering "" -> "latency"
2026/10/24 23:15:14 provision: converged acme.go.tito.io steering "latency" -> ""
2026/10/24 23:15:14 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: converged acme.go.tito.io hibernate false -> true
2026/10/24 23:15:14 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: converged acme.go.tito.io hibernate true -> false (replication "daily" cleared: only a hibernating route's rung is read)
2026/10/24 23:15:14 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:14 provision: converged acme.go.tito.io status-named false -> true
2026/10/24 23:15:14 provision: converged acme.go.tito.io status-named true -> false
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted service route ha.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: converged ha.go.tito.io upstreams addr "" -> "", addrs "127.0.0.1:7001,127.0.0.1:7002" -> "127.0.0.1:7001,127.0.0.1:7003" (probe "{\"path\":\"/\",\"status\":200,\"interval_ms\":2000,\"fail_after\":3,\"rise_after\":2}" -> "{\"path\":\"/\",\"status\":200,\"interval_ms\":2000,\"fail_after\":3,\"rise_after\":2}")
2026/10/24 23:15:15 provision: converged ha.go.tito.io upstreams addr "" -> "", addrs "127.0.0.1:7001,127.0.0.1:7003" -> "127.0.0.1:7003,127.0.0.1:7001" (probe "{\"path\":\"/\",\"status\":200,\"interval_ms\":2000,\"fail_after\":3,\"rise_after\":2}" -> "{\"path\":\"/\",\"status\":200,\"interval_ms\":2000,\"fail_after\":3,\"rise_after\":2}")
2026/10/24 23:15:15 provision: converged ha.go.tito.io upstreams addr "" -> "", addrs "127.0.0.1:7003,127.0.0.1:7001" -> "127.0.0.1:7003,127.0.0.1:7001" (probe "{\"path\":\"/\",\"status\":200,\"interval_ms\":2000,\"fail_after\":3,\"rise_after\":2}" -> "{\"path\":\"/healthz\",\"status\":200,\"interval_ms\":2000,\"fail_after\":3,\"rise_after\":2}")
2026/10/24 23:15:15 provision: minted service route whole.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: converged whole.go.tito.io upstreams addr "127.0.0.1:9443" -> "", addrs "" -> "127.0.0.1:9443,127.0.0.1:9444" (probe "" -> "{\"path\":\"/\",\"status\":200,\"interval_ms\":2000,\"fail_after\":3,\"rise_after\":2}")
2026/10/24 23:15:15 provision: converged whole.go.tito.io upstreams addr "" -> "", addrs "127.0.0.1:9443,127.0.0.1:9444" -> "" (probe "{\"path\":\"/\",\"status\":200,\"interval_ms\":2000,\"fail_after\":3,\"rise_after\":2}" -> "")
2026/10/24 23:15:15 provision: whole.go.tito.io: record describes a different route SHAPE than the row (kind "instance"/"service" unit ""/"" socket "/run/carlos/whole.go.tito.io.sock"/"" db "/data/whole.go.tito.io.db"/"") — not converged in place; `carlos remove whole.go.tito.io` purges this route's capability grants (registry.Delete's contract, not a bug) before the next pass re-mints it, so treat that as a last resort, not a routine fix
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted service route whole.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: skipping accounts/bac/account.json: malformed account manifest: invalid character 'o' in literal null (expecting 'u')
2026/10/24 23:15:15 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: manifest bac/tito: read failed: provision: manifest bac/tito: invalid character 'o' in literal null (expecting 'u')
2026/10/24 23:15:15 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: disagrees with its own path (host="wrong-host.go.tito.io" account="bac" app="tito")
2026/10/24 23:15:15 provision: skipping record apps/bac/tito/instances/acme$evil.go.tito.io.json: host "acme$evil.go.tito.io" is not a hostname
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: skipping record apps/bac/tito/instances/acme$evil.go.tito.io.json: host "acme$evil.go.tito.io" is not a hostname
2026/10/24 23:15:15 provision: not removing acme$evil.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 23:15:15 provision: skipping record apps/bac/tito/instances/bad-service.go.tito.io.json: invalid shape: kind service with no addr: the platform only proxies to a service, so the record must name the upstream it proxies to
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: skipping record apps/bac/tito/instances/bad-service.go.tito.io.json: invalid shape: kind service with no addr: the platform only proxies to a service, so the record must name the upstream it proxies to
2026/10/24 23:15:15 provision: not removing bad-service.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 23:15:15 provision: skipping record apps/bac/tito/instances/no-channel.go.tito.io.json: empty channel
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: skipping record apps/bac/tito/instances/no-channel.go.tito.io.json: empty channel
2026/10/24 23:15:15 provision: not removing no-channel.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:15 provision: not removing acme.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 23:15:15 provision: removed retired instance route ghost.go.tito.io (record gone)
2026/10/24 23:15:15 provision: duplicate host dup.go.tito.io: keeping apps/bac/tito/instances/dup.go.tito.io.json, skipping apps/bad/tito/instances/dup.go.tito.io.json
2026/10/24 23:15:15 provision: minted instance route dup.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 23:15:15 provision: removed retired instance route acme.go.tito.io (app in the trash)
2026/10/24 23:15:15 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 23:15:15 provision: removed retired static route site.go.tito.io (app in the trash)
2026/10/24 23:15:15 provision: trash marker for bac/tito unreadable: release: malformed trash marker for bac/tito: invalid character 'n' looking for beginning of object key string — not minting for this app
2026/10/24 23:15:15 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 23:15:15 provision: removed retired instance route acme.go.tito.io (app in the trash)
2026/10/24 23:15:15 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 23:15:15 provision: trash marker for bac/tito unreadable: release: malformed trash marker for bac/tito: invalid character 'n' looking for beginning of object key string — not minting for this app
2026/10/24 23:15:15 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 23:15:15 provision: converged acme.go.tito.io channel stable -> edge
2026/10/24 23:15:15 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 23:15:15 provision: converged acme.go.tito.io channel canary/rehearsal -> edge
2026/10/24 23:15:15 provision: converged acme.go.tito.io environment "staging" -> ""
2026/10/24 23:15:15 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 23:15:15 provision: acme.go.tito.io exists but is not the route this record describes (backing "unit" (box-scoped, not expressible in a record)) — leaving it alone
2026/10/24 23:15:15 provision: acme.go.tito.io exists but is not the route this record describes (tunnel "pi-fleet" (box-scoped, not expressible in a record)) — leaving it alone
2026/10/24 23:15:15 provision: acme.go.tito.io exists but is not the route this record describes (caps "port:25" (box-scoped, not expressible in a record)) — leaving it alone
2026/10/24 23:15:15 provision: acme.go.tito.io exists but is not the route this record describes (platform (owned by the domains reconcile pass)) — leaving it alone
2026/10/24 23:15:15 provision: acme.go.tito.io exists but is not the route this record describes (canary (owned by the domains reconcile pass)) — leaving it alone
2026/10/24 23:15:15 provision: acme.go.tito.io exists but is not the route this record describes (db "/data/other.db"/"/data/acme.go.tito.io.db") — leaving it alone
2026/10/24 23:15:15 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 23:15:15 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 23:15:15 provision: dry-run: would mint instance route acme.go.tito.io (app "tito" acct "bac" channel "stable")
2026/10/24 23:15:15 provision: dry-run: would adopt existing route adopt.go.tito.io (app "tito" acct "bac") — this record would own its channel and environment
2026/10/24 23:15:15 provision: dry-run: would converge adopt.go.tito.io channel stable -> edge
2026/10/24 23:15:15 provision: dry-run: would converge adopt.go.tito.io environment "" -> "staging"
2026/10/24 23:15:15 provision: dry-run: would converge owned.go.tito.io channel stable -> edge
2026/10/24 23:15:15 provision: dry-run: would converge owned.go.tito.io environment "" -> "staging"
2026/10/24 23:15:15 provision: dry-run: would converge owned.go.tito.io hibernate false -> true
2026/10/24 23:15:15 provision: dry-run: would converge owned.go.tito.io seed
2026/10/24 23:15:15 provision: dry-run: would remove retired instance route gone.go.tito.io (record gone)
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: adopted existing route adopt.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 23:15:15 provision: converged adopt.go.tito.io channel stable -> edge
2026/10/24 23:15:15 provision: converged adopt.go.tito.io environment "" -> "staging"
2026/10/24 23:15:15 provision: converged owned.go.tito.io channel stable -> edge
2026/10/24 23:15:15 provision: converged owned.go.tito.io environment "" -> "staging"
2026/10/24 23:15:15 provision: converged owned.go.tito.io hibernate false -> true
2026/10/24 23:15:15 provision: removed retired instance route gone.go.tito.io (record gone)
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: adopted existing route story.carlosframework.com (app "story" acct "bad") — this record now owns its channel and environment
2026/10/24 23:15:15 provision: story.carlosframework.com exists but is not the route this record describes (kind "instance"/"static") — leaving it alone
2026/10/24 23:15:15 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted service route pub.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted service route pubs.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted service route loop.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted service route named.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted service route priv.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted instance route unit.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted instance route exec.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted static route pisite.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: removed retired static route site.go.tito.io (record gone)
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted instance route acme-uk.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: converged acme.go.tito.io replicas "ie,uk" -> "uk"
2026/10/24 23:15:15 provision: converged acme.go.tito.io replicas "uk" -> ""
2026/10/24 23:15:15 provision: minted instance route acme-uk.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: converged acme-uk.go.tito.io replica mark true -> false
2026/10/24 23:15:15 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: acme.go.tito.io: row is on the nested layout (db "/data/instances/acme.go.tito.io/acme.go.tito.io.db" socket "/run/carlos/instances/acme.go.tito.io/app.sock"); the record's shared paths are not drift
2026/10/24 23:15:15 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:15 provision: acme.go.tito.io: not minting this pass: the box's layout intent could not be read: store down
2026/10/24 23:15:15 provision: router.go.tito.io: not minting this pass: the box's layout intent could not be read: store down
2026/10/24 23:15:15 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 23:15:15 provision: converged acme.go.tito.io channel stable -> edge
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io held landing by mv_acme (app "tito" acct "bac")
2026/10/24 23:15:15 provision: not removing acme.go.tito.io (record gone): participant of a running operation
2026/10/24 23:15:15 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 23:15:15 provision: minted instance route acme.go.tito.io held landing by mv_acme (app "tito" acct "bac")
2026/10/24 23:15:15 provision: refusing to mint held route acme.go.tito.io (app "tito" acct "bac"): this box declares CARLOS_INBOUND=none (no-inbound) and cannot serve routed instance traffic
2026/10/24 23:15:15 provision: held acme.go.tito.io landing by mv_acme (was ready)
2026/10/24 23:15:16 provision: acme.go.tito.io: held restoring by rb_other, not by mv_acme; leaving it
2026/10/24 23:15:16 provision: acme.go.tito.io: the row is not this pass's (app "other" acct ""); not holding it for mv_acme
2026/10/24 23:15:16 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 23:15:16 provision: dry-run: would mint instance route acme.go.tito.io held landing by mv_acme (app "tito" acct "bac" channel "stable")
2026/10/24 23:15:16 provision: acme.go.tito.io: not held landing by mv_acme: the row's hold changed under this pass; the next pass judges it afresh
2026/10/24 23:15:16 provision: held acme.go.tito.io landing by mv_acme (was ready)
2026/10/24 23:15:16 provision: minted instance route acme.example.com (app "shop" acct "bac")
2026/10/24 23:15:16 provision: minted instance route plain.example.com (app "shop" acct "bac")
2026/10/24 23:15:16 provision: skipping record apps/bac/shop/instances/garbled.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:16 provision: skipping record apps/bac/shop/instances/liar.shop.example.com.json: disagrees with its own path (host="other.shop.example.com" account="bac" app="shop")
2026/10/24 23:15:16 provision: skipping record apps/bac/shop/instances/garbled.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:16 provision: skipping record apps/bac/shop/instances/liar.shop.example.com.json: disagrees with its own path (host="other.shop.example.com" account="bac" app="shop")
2026/10/24 23:15:16 provision: skipping record apps/bac/shop/instances/garbled.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:16 provision: skipping record apps/bac/shop/instances/liar.shop.example.com.json: disagrees with its own path (host="other.shop.example.com" account="bac" app="shop")
2026/10/24 23:15:16 provision: skipping record apps/bac/shop/instances/garbled.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:16 provision: listing apps/bac/shop/instances/: list refused — its records are unseen this pass
2026/10/24 23:15:16 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:17 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:17 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 23:15:17 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:17 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 23:15:17 provision: minted sidecar route bot.shop.bac.sidecar.internal (app "shop" acct "bac" args ["run"])
2026/10/24 23:15:17 provision: removed retired sidecar route bot.shop.bac.sidecar.internal (record gone)
2026/10/24 23:15:17 provision: minted sidecar route bot.shop.bum.sidecar.internal (app "shop" acct "bum" args ["run"])
2026/10/24 23:15:17 provision: minted sidecar route bot.shop.bum.sidecar.internal (app "shop" acct "bum" args ["run"])
2026/10/24 23:15:17 provision: sidecar bot.shop.bum.sidecar.internal is not placeable here: it asks for "no-inbound" placement and this box accepts inbound work (CARLOS_INBOUND="")
2026/10/24 23:15:17 provision: sidecar bot.shop.bum.sidecar.internal is not placeable here: it asks for "no-inbound" placement and this box accepts inbound work (CARLOS_INBOUND="")
2026/10/24 23:15:17 provision: removed retired sidecar route bot.shop.bum.sidecar.internal (record gone)
2026/10/24 23:15:17 provision: sidecar bot.shop.bum.sidecar.internal is not placeable here: it asks for "no-inbound" placement and this box accepts inbound work (CARLOS_INBOUND="")
2026/10/24 23:15:17 provision: sidecar bot.shop.bum.sidecar.internal is not placeable here: it asks for "no-inbound" placement and this box accepts inbound work (CARLOS_INBOUND="")
2026/10/24 23:15:17 provision: removed retired sidecar route bot.shop.bum.sidecar.internal (record gone)
2026/10/24 23:15:17 provision: a.shop.example.com: swapped for import sd_jigsrk36spkedvrvwnpbrganuq (the original route is journaled)
2026/10/24 23:15:17 provision: a.shop.example.com: import sd_jigsrk36spkedvrvwnpbrganuq committed: its gate is cleared and its journal row dropped
2026/10/24 23:15:17 provision: a.shop.example.com: row is on the nested layout (db "/data/instances/a.shop.example.com/a.shop.example.com.db" socket "/run/carlos/instances/a.shop.example.com/app.sock"); the record's shared paths are not drift
2026/10/24 23:15:17 provision: a.shop.example.com: import sd_xxvyiid2wg5dg4lwvvr3pdncde rolled back to its original route
2026/10/24 23:15:17 provision: a.shop.example.com: import sd_xxvyiid2wg5dg4lwvvr3pdncde: the host's replica is left alone: the record apps/bac/shop/instances/a.shop.example.com.json holds the host
2026/10/24 23:15:17 provision: a.shop.example.com: import sd_xxvyiid2wg5dg4lwvvr3pdncde is cleaned up and its journal row retired
2026/10/24 23:15:17 provision: a.shop.example.com: import sd_tzdkf54t3ijzsokdb47qqjut2i rolled back to its original route
2026/10/24 23:15:17 provision: a.shop.example.com: import sd_tzdkf54t3ijzsokdb47qqjut2i: the host's replica is left alone: the record apps/bac/shop/instances/a.shop.example.com.json holds the host
2026/10/24 23:15:17 provision: a.shop.example.com: import sd_tzdkf54t3ijzsokdb47qqjut2i is cleaned up and its journal row retired
2026/10/24 23:15:17 provision: dry-run: would redo a.shop.example.com's swap record CAS for import sd_2b72xwm3zab43jt5nyecfitufe
2026/10/24 23:15:17 provision: dry-run: would clear a.shop.example.com's import gate
2026/10/24 23:15:17 provision: dry-run: would converge a.shop.example.com seed source
2026/10/24 23:15:17 provision: a.shop.example.com: row is on the nested layout (db "/data/instances/a.shop.example.com/a.shop.example.com.db" socket "/run/carlos/instances/a.shop.example.com/app.sock"); the record's shared paths are not drift
2026/10/24 23:15:17 provision: a.shop.example.com: the import's record apps/bac/shop/instances/a.shop.example.com.json is not one this pass can use (connection reset)
2026/10/24 23:15:17 provision: a.shop.example.com: the import's record apps/bac/shop/instances/a.shop.example.com.json is not one this pass can use (provision: invalid maintenance projection or protected fields)
2026/10/24 23:15:17 provision: a.shop.example.com: the import's record apps/bac/shop/instances/a.shop.example.com.json is not one this pass can use (the record under apps/bac/shop/instances/a.shop.example.com.json is apps/bac/shop/instances/b.shop.example.com.json's)
2026/10/24 23:15:17 provision: a.shop.example.com: import sd_zesd3eewdxxm52fubdg4qd7nja cannot roll back on this box: the activator is not wired; it stays journaled and gated
2026/10/24 23:15:17 provision: a.shop.example.com: import sd_iddmlldakdbpvznlyicbbr6pxa cannot roll back on this box: the activator is not wired; it stays journaled and gated
2026/10/24 23:15:17 provision: a.shop.example.com: import sd_kw5of7jju74gphrzsjuzkkwpdi is journaled, but this box cannot act on imports; its row is left alone
2026/10/24 23:15:17 provision: a.shop.example.com: import sd_fzotavo2qbj63pbpg3uyn6uc3u is journaled, but this box cannot act on imports; its row is left alone
2026/10/24 23:15:17 provision: a.shop.example.com: import sd_4tx23gfwz42uupd3x2hyqimtcy is journaled, but this box cannot act on imports; its row is left alone
2026/10/24 23:15:17 provision: the import journal could not be read: registry: import journal a.shop.example.com: original row: unexpected end of JSON input (no import is acted on and no route is removed this pass)
2026/10/24 23:15:17 provision: b.shop.example.com: import sd_ebhnnsu5vzjcdg3b2l5lvbhaxa left alone this pass: the import journal could not be read
2026/10/24 23:15:17 provision: c.shop.example.com: import sd_asxbfmdyu7gx7vh24hkcqnpqzq left alone this pass: the import journal could not be read
2026/10/24 23:15:17 provision: a.shop.example.com: import sd_nswsdo5killubnvxzo5et53tlm committed: its gate is cleared and its journal row dropped
2026/10/24 23:15:17 provision: a.shop.example.com: not converging import sd_nuayv7i6yvv6zngdd47np5twva: it is swapped but not committed, and the row on this box has no import gate
2026/10/24 23:15:17 provision: a.shop.example.com: not converging import sd_wsadyyfwjhugwmm7btsgxyfuee: it is swapped but not committed, and the row on this box has no import gate
2026/10/24 23:15:17 provision: a.shop.example.com: not converging import sd_3pt6ml2cg4d3ooygouop3jrr7a: it is placed but not committed, and the row on this box has no import gate
2026/10/24 23:15:17 provision: a.shop.example.com: not converging import sd_nxogkhuc5sjwq6hydqskmwfvie: it is placed but not committed, and the row on this box has no import gate
2026/10/24 23:15:18 provision: a.shop.example.com: row is on the nested layout (db "/data/instances/a.shop.example.com/a.shop.example.com.db" socket "/run/carlos/instances/a.shop.example.com/app.sock"); the record's shared paths are not drift
2026/10/24 23:15:18 provision: converge seed source on a.shop.example.com: constraint failed: seed_source is read-only here (1811)
2026/10/24 23:15:18 provision: a.shop.example.com: row is on the nested layout (db "/data/instances/a.shop.example.com/a.shop.example.com.db" socket "/run/carlos/instances/a.shop.example.com/app.sock"); the record's shared paths are not drift
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_nuom24yrzzsk7w74cw6ipqyltm committed: its gate is cleared and its journal row dropped
2026/10/24 23:15:18 provision: a.shop.example.com: row is on the nested layout (db "/data/instances/a.shop.example.com/a.shop.example.com.db" socket "/run/carlos/instances/a.shop.example.com/app.sock"); the record's shared paths are not drift
2026/10/24 23:15:18 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:18 provision: acme.go.tito.io: row is on the nested layout (db "/data/instances/acme.go.tito.io/acme.go.tito.io.db" socket "/run/carlos/instances/acme.go.tito.io/app.sock"); the record's shared paths are not drift
2026/10/24 23:15:18 provision: acme.go.tito.io: not minting a seeded instance: claim control is on for this box
2026/10/24 23:15:18 provision: acme.go.tito.io: not minting a seeded instance: this box does not mint nested (<nil>)
2026/10/24 23:15:18 provision: acme.go.tito.io: aborted seed sd_o2uwnrudtidrg775tdulhpp4pm: this box cannot read seed markers, and places no seed; nothing local is removed
2026/10/24 23:15:18 provision: acme.go.tito.io: aborted seed sd_o2uwnrudtidrg775tdulhpp4pm rolled back (no box had swapped it)
2026/10/24 23:15:18 provision: acme.go.tito.io: not minting a seeded instance: its record does not describe a hibernating instance
2026/10/24 23:15:18 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:18 provision: removed instance route acme.go.tito.io (its seed sd_uvps2xdu7g57rxpcwr5a3z5ata was aborted); the next pass rolls it back
2026/10/24 23:15:18 provision: acme.go.tito.io: aborted seed sd_uvps2xdu7g57rxpcwr5a3z5ata: this box cannot read seed markers, and places no seed; nothing local is removed
2026/10/24 23:15:18 provision: acme.go.tito.io: aborted seed sd_uvps2xdu7g57rxpcwr5a3z5ata rolled back (no box had swapped it)
2026/10/24 23:15:18 provision: acme.go.tito.io: aborted seed sd_wrnm2vztkuc7uxc7bppegiquia has a row this pass may not remove; leaving the seed aborted
2026/10/24 23:15:18 provision: acme.go.tito.io: aborted seed sd_fhn2ht5oerhxtxgeadcvs7g2mu rolled back (no box had swapped it)
2026/10/24 23:15:18 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:18 provision: removed instance route acme.go.tito.io (its seed sd_2dsjmjomn7ydj4jsgebri3zx7e was aborted); the next pass rolls it back
2026/10/24 23:15:18 provision: acme.go.tito.io: aborted seed sd_2dsjmjomn7ydj4jsgebri3zx7e has no route on this box: its local data is removed
2026/10/24 23:15:18 provision: acme.go.tito.io: aborted seed sd_2dsjmjomn7ydj4jsgebri3zx7e rolled back (no box had swapped it)
2026/10/24 23:15:18 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_4fkzhtaqrrowggmzanz2efifj4 (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_4fkzhtaqrrowggmzanz2efifj4 rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_4fkzhtaqrrowggmzanz2efifj4 is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_bkk43ulrknxottwwtutfvmidey (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_bkk43ulrknxottwwtutfvmidey rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_bkk43ulrknxottwwtutfvmidey is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_6ixhznhwjuktqatejttxet3poa (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_6ixhznhwjuktqatejttxet3poa rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_6ixhznhwjuktqatejttxet3poa: the host's replica is left alone: its record no longer names this seed
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_6ixhznhwjuktqatejttxet3poa is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_dzcyxluay3jrlvsxraki4iyyfm (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_dzcyxluay3jrlvsxraki4iyyfm rollback deferred: the host is not fenced and stopped yet (<nil>)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_dzcyxluay3jrlvsxraki4iyyfm rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_dzcyxluay3jrlvsxraki4iyyfm is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_nhpa3bdugq3jza546klw3knrpm (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_nhpa3bdugq3jza546klw3knrpm rollback deferred: the host is not fenced and stopped yet (stop unproven)
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_www5bpguj37hugg7jxhd6i6dcm (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_www5bpguj37hugg7jxhd6i6dcm is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_vq7x2rtsvhrq7usyhjo7u3gibi (the original route is journaled)
2026/10/24 23:15:18 provision: skipping record apps/bac/shop/instances/a.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_vq7x2rtsvhrq7usyhjo7u3gibi left alone this pass: its record could not be read
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_bsfh42gfqvag6mpugpptkt7nou (the original route is journaled)
2026/10/24 23:15:18 provision: skipping record apps/bac/shop/instances/a.shop.example.com.json: read failed: connection reset
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_bsfh42gfqvag6mpugpptkt7nou left alone this pass: its record could not be read
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_znhjzvo67cyfmx7c5ptal4u5aq (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_znhjzvo67cyfmx7c5ptal4u5aq: close the import gate: constraint failed: injected (1811)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_znhjzvo67cyfmx7c5ptal4u5aq rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_znhjzvo67cyfmx7c5ptal4u5aq is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_tvigbbzojdi56l7xuien2il4mi (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_tvigbbzojdi56l7xuien2il4mi: close the import gate: constraint failed: injected (1811)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_tvigbbzojdi56l7xuien2il4mi rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_tvigbbzojdi56l7xuien2il4mi is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_ipvmlt6reqxksupyqxhbqxvgke (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_ipvmlt6reqxksupyqxhbqxvgke rollback deferred: the host is not fenced and stopped yet (injected failure at fence)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_ipvmlt6reqxksupyqxhbqxvgke rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_ipvmlt6reqxksupyqxhbqxvgke is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_6t4h67n2nwrd2e4u3vtnpqb24a (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_6t4h67n2nwrd2e4u3vtnpqb24a rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_6t4h67n2nwrd2e4u3vtnpqb24a is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_pwoafc2ix3ipxkypwxhwhpbgre (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_pwoafc2ix3ipxkypwxhwhpbgre: retire its instance key: injected failure at retire-key
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_pwoafc2ix3ipxkypwxhwhpbgre rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_pwoafc2ix3ipxkypwxhwhpbgre is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_vcd27jbgw6lmkujehn3anxsj3y (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_vcd27jbgw6lmkujehn3anxsj3y rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_vcd27jbgw6lmkujehn3anxsj3y is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_vm45nzzmpmoy7fnvepvn3rxdu4 (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_vm45nzzmpmoy7fnvepvn3rxdu4: remove its local data: injected failure at remove-local
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_vm45nzzmpmoy7fnvepvn3rxdu4 rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_vm45nzzmpmoy7fnvepvn3rxdu4 is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_4wgkzsj5yffswfwbytn3v5eam4 (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_4wgkzsj5yffswfwbytn3v5eam4 rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_4wgkzsj5yffswfwbytn3v5eam4 is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_3tip3sy6gg6s47tl5ptfiavlte (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_3tip3sy6gg6s47tl5ptfiavlte: remove its local data: injected failure at remove-local-done
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_3tip3sy6gg6s47tl5ptfiavlte rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_3tip3sy6gg6s47tl5ptfiavlte is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_azsz2gseurqnbuelacmutgnlmu (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_azsz2gseurqnbuelacmutgnlmu rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_azsz2gseurqnbuelacmutgnlmu is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_6dn6bjbnhjpz7gbt3hv5iek5oq (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_6dn6bjbnhjpz7gbt3hv5iek5oq: restore the original route: constraint failed: injected (1811)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_6dn6bjbnhjpz7gbt3hv5iek5oq rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_6dn6bjbnhjpz7gbt3hv5iek5oq is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_6ydzrjpzkcmbvfxpvldiq2leuq (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_6ydzrjpzkcmbvfxpvldiq2leuq: restore the original route: constraint failed: injected (1811)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_6ydzrjpzkcmbvfxpvldiq2leuq rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_6ydzrjpzkcmbvfxpvldiq2leuq is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_orth55t2rvidyhgvcbnqtamh4u (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_orth55t2rvidyhgvcbnqtamh4u is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_vhgbes7fkdcrm32zj4jutmv4be (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_vhgbes7fkdcrm32zj4jutmv4be rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_vhgbes7fkdcrm32zj4jutmv4be: delete its snapshot: injected failure at delete-snapshot
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_vhgbes7fkdcrm32zj4jutmv4be is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_cvv4wp4u6motdyaxi6oj4lnsii (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_cvv4wp4u6motdyaxi6oj4lnsii rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_cvv4wp4u6motdyaxi6oj4lnsii is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_mk5rvp3xwmd2p7bzmgyprxlidy (the original route is journaled)
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_mk5rvp3xwmd2p7bzmgyprxlidy rolled back to its original route
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_mk5rvp3xwmd2p7bzmgyprxlidy: delete the host's replica: injected failure at delete-replica
2026/10/24 23:15:18 provision: a.shop.example.com: import sd_mk5rvp3xwmd2p7bzmgyprxlidy is cleaned up and its journal row retired
2026/10/24 23:15:18 provision: a.shop.example.com: swapped for import sd_p62hfr27iaboog53wiatyp7qzy (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_p62hfr27iaboog53wiatyp7qzy rolled back to its original route
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_p62hfr27iaboog53wiatyp7qzy is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_6o2hta36q7slx2mr2kidefjjhm (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_6o2hta36q7slx2mr2kidefjjhm rolled back to its original route
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_6o2hta36q7slx2mr2kidefjjhm: retire its journal row: constraint failed: injected (1811)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_6o2hta36q7slx2mr2kidefjjhm is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_bx7rjtjhsvkk5ytrmdfvimq65y (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_bx7rjtjhsvkk5ytrmdfvimq65y rolled back to its original route
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_bx7rjtjhsvkk5ytrmdfvimq65y: retire its journal row: constraint failed: injected (1811)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_bx7rjtjhsvkk5ytrmdfvimq65y is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_qzlu2kwwna5nugjv6gbjq3idx4 (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_qzlu2kwwna5nugjv6gbjq3idx4 rolled back to its original route
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_qzlu2kwwna5nugjv6gbjq3idx4 is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: a.shop.example.com: mark import sd_qzlu2kwwna5nugjv6gbjq3idx4 rolled back: injected failure at cas
2026/10/24 23:15:19 provision: a.shop.example.com: aborted seed sd_qzlu2kwwna5nugjv6gbjq3idx4 rolled back (no box had swapped it)
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_vgxorjxu4otox4qvgun77biq2i (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_vgxorjxu4otox4qvgun77biq2i rolled back to its original route
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_vgxorjxu4otox4qvgun77biq2i is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: a.shop.example.com: aborted seed sd_vgxorjxu4otox4qvgun77biq2i rolled back (no box had swapped it)
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_hyr2zej4rtyznek6eybcjbn6yi (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_hyr2zej4rtyznek6eybcjbn6yi rollback deferred: the host is not fenced and stopped yet (<nil>)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_hyr2zej4rtyznek6eybcjbn6yi rollback deferred: the host is not fenced and stopped yet (<nil>)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_hyr2zej4rtyznek6eybcjbn6yi rolled back to its original route
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_hyr2zej4rtyznek6eybcjbn6yi is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_f26hh2gi6laatiree7o4sxlqyq (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_f26hh2gi6laatiree7o4sxlqyq rolled back to its original route
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_f26hh2gi6laatiree7o4sxlqyq is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_7nsezo2yaiwclje2etfnvllfry (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_7nsezo2yaiwclje2etfnvllfry rolled back to its original route
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_7nsezo2yaiwclje2etfnvllfry is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_24swn6pareycpybin2yt5rxau4 (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_24swn6pareycpybin2yt5rxau4 rolled back to its original route
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_24swn6pareycpybin2yt5rxau4 is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_ipig7tlaose3qa5alpezu2oc7a (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_ipig7tlaose3qa5alpezu2oc7a rolled back to its original route
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_ipig7tlaose3qa5alpezu2oc7a is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_6pwbgkni5wazoh3pdycmbolsl4 (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_6pwbgkni5wazoh3pdycmbolsl4 rolled back to its original route
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_6pwbgkni5wazoh3pdycmbolsl4 is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: minted instance route a.shop.example.com (app "other" acct "bac")
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_mfr7jf22zdyqowcjrfch5wyhxu (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_mfr7jf22zdyqowcjrfch5wyhxu rolled back to its original route
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_mfr7jf22zdyqowcjrfch5wyhxu is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: minted instance route a.shop.example.com (app "other" acct "bac")
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_4p7whvpfqx73n3rmacs5nzuuzq (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_4p7whvpfqx73n3rmacs5nzuuzq rolled back to its original route
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_4p7whvpfqx73n3rmacs5nzuuzq is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: minted instance route a.shop.example.com (app "other" acct "bac")
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_3gffrhq5a53c4q4ehpbef3xx7m (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_3gffrhq5a53c4q4ehpbef3xx7m has no route on this box: its local data is removed and no route is put back
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_3gffrhq5a53c4q4ehpbef3xx7m is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_mqxfkkejytt7wei2mr2pnugsfm (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_mv74qodcorenpv5fiiaevfxrvy (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_gwxf7bd5od6n7ip4oqzcusvyta (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_gwxf7bd5od6n7ip4oqzcusvyta cannot roll back on this box: the activator is not wired; it stays journaled and gated
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_shvhhn2gdrcipw457db3fmnqoi (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_shvhhn2gdrcipw457db3fmnqoi is not rolled back: the route changed under the fence, so nothing there is touched
2026/10/24 23:15:19 provision: a.shop.example.com: import "../not-a-seed" names no snapshot and no replica; only its journal row is cleaned up
2026/10/24 23:15:19 provision: a.shop.example.com: import ../not-a-seed is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_z7vxkhk5ar36lahv73szbecuee (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_nvtvcbbgln34c5rh33kjumz3na (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_nq4fp4zcktmwlitrb2rrfeywfa (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_n54ajqzusntaxa7iu7bvqigsaq (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_bouax6daktoegd6ifcwgxzsoke (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_bouax6daktoegd6ifcwgxzsoke rollback deferred: the host is not fenced and stopped yet (stop evidence unreadable)
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_5tuhlvuc4tlb4hpis4igkkeh5q (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_5tuhlvuc4tlb4hpis4igkkeh5q has no route on this box: its local data is removed and no route is put back
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_5tuhlvuc4tlb4hpis4igkkeh5q is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_qy34iavt7ecsgfq5ru3yxopjbe (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_qy34iavt7ecsgfq5ru3yxopjbe: remove its local data: injected failure at remove-local
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_qy34iavt7ecsgfq5ru3yxopjbe is not rolled back: the route at the host is not the import's, so nothing there is touched
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_harfodijqwees64lf2vrlo3mx4 (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_harfodijqwees64lf2vrlo3mx4: a route appeared at the host, so its local database is left and the rollback waits
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_yph2irpzdienfdm6kmjkisufrm (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_yph2irpzdienfdm6kmjkisufrm rollback deferred: no fence generation: registry busy
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_5sqlawwismfyrfl6osb4ql3qza (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_5sqlawwismfyrfl6osb4ql3qza rollback deferred: no fence generation: the generation source answered 0
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_wpcuda3qfa5opcbrkrfkrcrdsi (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_64h7xtdjz4pugku5a3cf5k7kde (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_mys6c7l7hawpnepct4pz2fqk7u (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import deferred: this box cannot read the instance's env file
2026/10/24 23:15:19 provision: a.shop.example.com: import deferred: the instance's env file could not be read: a symlink
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_2vu3rvoiquwcky74p6sot7t5ra (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_2vu3rvoiquwcky74p6sot7t5ra rolled back to its original route
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_2vu3rvoiquwcky74p6sot7t5ra is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_arai4rewidrlb5c5gkdaetwpm4 (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_arai4rewidrlb5c5gkdaetwpm4 rolled back to its original route
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_arai4rewidrlb5c5gkdaetwpm4 is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_5dfmli3ot6fwoocec67yan3see (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_5dfmli3ot6fwoocec67yan3see rolled back to its original route
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_5dfmli3ot6fwoocec67yan3see is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_ycbm2fn44f5dsaqi7acoofwmpm (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_ycbm2fn44f5dsaqi7acoofwmpm: retire its instance key: the env file is a symlink
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_ycbm2fn44f5dsaqi7acoofwmpm rolled back to its original route
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_ycbm2fn44f5dsaqi7acoofwmpm is cleaned up and its journal row retired
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_geh3enkemnaiz5y6x4yitooc3y (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: row is on the nested layout (db "/data/instances/a.shop.example.com/a.shop.example.com.db" socket "/run/carlos/instances/a.shop.example.com/app.sock"); the record's shared paths are not drift
2026/10/24 23:15:19 provision: a.shop.example.com: swapped for import sd_gqznsfbhm7gvf7zsjb2orvfexa (the original route is journaled)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_mvmvgrpfjriabnaxzfjhiae4la refused: there is no route at a.shop.example.com to replace
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_4haxvjjki64domonr7ixjtophy refused: the route's address is 127.0.0.1:9, not 127.0.0.1:8401
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_qdar5jwunmulw6qhc2zodevywq refused: the route's address is 127.0.0.1:8401,127.0.0.1:8402, not 127.0.0.1:8401
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_7qdc747hn7454fpss4e44jqrwy refused: the route's address is 127.0.0.1:9, not 127.0.0.1:8401
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_klfhnrgjsfcfsauykex4mjbvgq refused: the route belongs to app other
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_ydxb6nur7qc6vpioqdlicvuuiy refused: the route is filed under another account
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_3jlhdfchlsrwa3xqbhebxfls54 refused: the route is filed under the operator account, and no assignment maps shop to this app
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_uxk2bc3aafoebxixu57ldvntym refused: the route is filed under the operator account, and no assignment maps shop to this app
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_p7ay2yng4u77lnotdbveb6fneu refused: the route is filed under the operator account, and no assignment maps shop to this app
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_wnvd2dwvi524oj26tswzj5obhy refused: the route is filed under the operator account, and no assignment maps shop to this app
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_6s7pyks6wm4axvyceit2pc6vou refused: the route is not an address route this import can take over (socket)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_7ycffky4obvmrw67a5zyh4n4wi refused: the route is not an address route this import can take over (no address)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_srqa4qqqzmhbaulodvk5lfpoie refused: the route is not an address route this import can take over (provisioned)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_k526744gkm2fwhfvol6pvfs6fe refused: the route is not an address route this import can take over (kind static)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_ycklsdlvdrxw52i6uilcoel54a refused: the route is not an address route this import can take over (backing)
2026/10/24 23:15:19 provision: a.shop.example.com: import sd_hhca6n3nszguj6g5js6wkhgrpy refused: the route is not an address route this import can take over (tunnel)
2026/10/24 23:15:20 provision: a.shop.example.com: import sd_pxnoorshy3lzal6c6wevdq6d7e refused: the route is not an address route this import can take over (caps)
2026/10/24 23:15:20 provision: a.shop.example.com: import sd_lko3fogv5h6p7xkjbwr5xxh65a refused: the route is not an address route this import can take over (platform)
2026/10/24 23:15:20 provision: a.shop.example.com: import sd_odqsch5wyhjckl7bww7lb74shm refused: the route is not an address route this import can take over (canary)
2026/10/24 23:15:20 provision: a.shop.example.com: import sd_tlqm4bxup4b577wpnz7kxhvsqm refused: the route is not an address route this import can take over (kind sidecar)
2026/10/24 23:15:20 provision: a.shop.example.com: import sd_kw3h6c6lklv2d76x2jxkq6ci54 refused: the route is not an address route this import can take over (region)
2026/10/24 23:15:20 provision: a.shop.example.com: import sd_c32q5tpg2hojmp3dyqid64mlua refused: the route is not an address route this import can take over (fleet_box)
2026/10/24 23:15:20 provision: a.shop.example.com: import sd_nfyigjjnfnd7f24urtagqtwua4 refused: the route is not an address route this import can take over (hibernate)
2026/10/24 23:15:20 provision: a.shop.example.com: import sd_kvdke5sdv26csvtxww3dnkfrem refused: the route is not an address route this import can take over (claim_owner)
2026/10/24 23:15:20 provision: a.shop.example.com: import sd_3xr23bu3qgutv73vfvnenr55vi refused: this box does not run instances nested
2026/10/24 23:15:20 provision: a.shop.example.com: import sd_2hi6qrzklgkmbyvt52fwsjtq2m refused: this box does not run instances nested
2026/10/24 23:15:20 provision: a.shop.example.com: import sd_i6lgne4un2zvhenjipeisj6jpi refused: claim control is on for this box
2026/10/24 23:15:20 provision: a.shop.example.com: swapped for import sd_k6yk3byzonsbmm3kbmnda2z75q (the original route is journaled)
2026/10/24 23:15:20 provision: a.shop.example.com: swapped for import sd_6n2x42qf44eoxntbgqqz3nextu (the original route is journaled)
2026/10/24 23:15:20 provision: a.shop.example.com: import deferred: this box cannot read the legacy route assignments
2026/10/24 23:15:20 provision: a.shop.example.com: import deferred: the legacy route assignments could not be read: store down
2026/10/24 23:15:20 provision: a.shop.example.com: not swapping for import sd_qcrzwpni7qargx3gv3il4axpgy: its verify hash is not a sha256
2026/10/24 23:15:20 provision: a.shop.example.com: not swapping for import sd_qhpy3th6rjlho4v4xqyouv6434: its verify hash is not a sha256
2026/10/24 23:15:20 provision: a.shop.example.com: not swapping for import sd_4w35xczzcan2sekdq7dwc6l5pq: its verify hash is not a sha256
2026/10/24 23:15:20 provision: a.shop.example.com: not swapping for import sd_../../x: its host or seed id is malformed (seeds: not a seed id)
2026/10/24 23:15:20 provision: A.shop.example.com/..: not swapping for import sd_zh3czyeyvv2wp5y3arg5bqntey: its host or seed id is malformed (seeds: not a host)
2026/10/24 23:15:20 provision: a.shop.example.com: not swapping for import sd_3vkizgoir7plhcyo7tdrhcav6e: its record does not describe a nested, hibernating instance
2026/10/24 23:15:20 provision: a.shop.example.com: not swapping for import sd_gdv3rjx3wrguhkst3srqh5mzwi: its record does not describe a nested, hibernating instance
2026/10/24 23:15:20 provision: a.shop.example.com: not swapping for import sd_6y7uuuyj4wwdgaoclw24mmuwdq: its record does not describe a nested, hibernating instance
2026/10/24 23:15:20 provision: a.shop.example.com: not swapping for import sd_msm6htmz4w2dt2feq4jst5ouoa: its record does not describe a nested, hibernating instance
2026/10/24 23:15:20 provision: a.shop.example.com: import deferred: the box's layout intent could not be read: store down
2026/10/24 23:15:20 provision: a.shop.example.com: swapped for import sd_ypdtzkkj2pyazyuaodpgnal2uu (the original route is journaled)
2026/10/24 23:15:20 provision: a.shop.example.com: import deferred: the box's nested probe did not answer: ready probe timed out
2026/10/24 23:15:20 provision: a.shop.example.com: swapped for import sd_i2iqaybveua5z3i7m76r4dzca4 (the original route is journaled)
2026/10/24 23:15:20 provision: a.shop.example.com: swapped for import sd_6wrgamlxyjcg53vo7rjoq6heyy (the original route is journaled)
2026/10/24 23:15:20 provision: a.shop.example.com: import deferred: the route is held by operation op_1
2026/10/24 23:15:20 provision: dry-run: would consider swapping a.shop.example.com for import sd_hlyfnkqkszwidu24wtwaj325w4
2026/10/24 23:15:20 provision: a.shop.example.com: import sd_6qsb76zes4gslccwcnhrhzjwmq rolled back to its original route
2026/10/24 23:15:20 provision: a.shop.example.com: import sd_6qsb76zes4gslccwcnhrhzjwmq: the host's replica is left alone: the record apps/bac/shop/instances/a.shop.example.com.json holds the host
2026/10/24 23:15:20 provision: a.shop.example.com: import sd_6qsb76zes4gslccwcnhrhzjwmq is cleaned up and its journal row retired
2026/10/24 23:15:20 provision: a.shop.example.com: import sd_ocrqfrmjop3qkssfjekxab4cfq left alone: the import journal holds seed sd_d64yn7og6oiuefedbkbc4p3oti at swapped
2026/10/24 23:15:20 provision: a.shop.example.com: not minting import sd_ek6bapthr2um2qfrqk7odxmn6u: it is swapped but not committed, and only its swap makes its row
2026/10/24 23:15:20 provision: a.shop.example.com: not minting import sd_gsc4m5qmej5ebr6dr36qbsfrwm: it is placed but not committed, and only its swap makes its row
2026/10/24 23:15:20 provision: a.shop.example.com: swapped for import sd_enmil6dnaunhcgak5xzay2sb4q (the original route is journaled)
2026/10/24 23:15:20 provision: a.shop.example.com: not minting import sd_enmil6dnaunhcgak5xzay2sb4q: it is swapped but not committed, and only its swap makes its row
2026/10/24 23:15:20 provision: a.shop.example.com: not minting import sd_enmil6dnaunhcgak5xzay2sb4q: it is placed but not committed, and only its swap makes its row
2026/10/24 23:15:20 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 23:15:20 provision: removed retired sidecar route gone.eleven.bac.sidecar.internal (record gone)
2026/10/24 23:15:20 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 23:15:20 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 23:15:20 provision: converged sidecar bot.eleven.bac.sidecar.internal args ["sidecar","run"] -> ["worker","run"]
2026/10/24 23:15:20 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 23:15:20 provision: converged sidecar bot.eleven.bac.sidecar.internal ceilings 300/3600 -> 60/120
2026/10/24 23:15:20 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 23:15:20 provision: converged sidecar bot.eleven.bac.sidecar.internal channel stable -> canary/eleven
2026/10/24 23:15:20 provision: converged sidecar bot.eleven.bac.sidecar.internal environment "other" -> "relay"
2026/10/24 23:15:20 provision: converged sidecar bot.eleven.bac.sidecar.internal hibernate true -> false
2026/10/24 23:15:20 provision: skipping sidecar record apps/bac/eleven/sidecars/bot.json: read failed: failStore: reads disabled under apps/bac/eleven/sidecars/
2026/10/24 23:15:20 provision: skipping sidecar record apps/bac/eleven/sidecars/bot.json: malformed: invalid character 'n' looking for beginning of object key string
2026/10/24 23:15:20 provision: not removing sidecar bot.eleven.bac.sidecar.internal: its record exists but could not be read cleanly this pass
2026/10/24 23:15:20 provision: skipping sidecar record apps/bac/eleven/sidecars/bot.json: empty channel
2026/10/24 23:15:20 provision: skipping sidecar record apps/bac/eleven/sidecars/held.json: empty channel
2026/10/24 23:15:20 provision: not removing sidecar held.eleven.bac.sidecar.internal: its record exists but could not be read cleanly this pass
2026/10/24 23:15:20 provision: removed retired sidecar route old.eleven.bac.sidecar.internal (record gone)
2026/10/24 23:15:20 provision: bac/eleven has sidecar records but no sidecars manifest — not minting
2026/10/24 23:15:20 provision: bac/eleven is in the trash — not minting sidecar routes for it
2026/10/24 23:15:20 provision: sidecar bot.eleven.bac.sidecar.internal is not placeable here: it asks for "no-inbound" placement and this box accepts inbound work (CARLOS_INBOUND="")
2026/10/24 23:15:20 provision: sidecar hub.relay.bac.sidecar.internal is not placeable here: it asks for "no-inbound" placement and this box accepts inbound work (CARLOS_INBOUND="")
2026/10/24 23:15:20 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 23:15:20 provision: minted sidecar route hub.relay.bac.sidecar.internal (app "relay" acct "bac" args ["relay"])
2026/10/24 23:15:20 provision: sidecar bot.eleven.bac.sidecar.internal is not placeable here: it asks for "no-inbound" placement and this box accepts inbound work (CARLOS_INBOUND="")
2026/10/24 23:15:20 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 23:15:20 provision: sidecar bot.eleven.bac.sidecar.internal is not placeable here: it asks for "no-inbound" placement and this box accepts inbound work (CARLOS_INBOUND="")
2026/10/24 23:15:20 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 23:15:20 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 23:15:20 provision: sidecar bot.eleven.bac.sidecar.internal is not placeable here: it asks for "no-inbound" placement and this box accepts inbound work (CARLOS_INBOUND="")
2026/10/24 23:15:20 provision: removed retired sidecar route bot.eleven.bac.sidecar.internal (record gone)
2026/10/24 23:15:20 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 23:15:20 provision: sidecar bot.eleven.bac.sidecar.internal is not placeable here: it asks for "no-inbound" placement and this box accepts inbound work (CARLOS_INBOUND="")
2026/10/24 23:15:20 provision: skipping sidecar record apps/bac/relay/sidecars/hub.json: read failed: failStore: reads disabled under apps/bac/relay/sidecars/
2026/10/24 23:15:20 provision: REFUSING to mint sidecar bot.eleven.bac.sidecar.internal: bot.eleven.bac.sidecar.internal-sidecar.env is staged on this box — the legacy file co-spawn and a native sidecar row are two mechanisms for one host; remove the file to migrate this host onto sidecar records
2026/10/24 23:15:20 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 23:15:20 provision: dry-run: would mint sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" channel "stable" args ["sidecar","run"])
2026/10/24 23:15:20 provision: dry-run: would remove retired sidecar route gone.eleven.bac.sidecar.internal (record gone)
2026/10/24 23:15:20 provision: bot.eleven.bac.sidecar.internal exists but is not a sidecar row this pass owns (kind "sidecar" provisioned false app "eleven" acct "bac") — leaving it alone
2026/10/24 23:15:20 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:20 provision: converged acme.go.tito.io update settings "{\"updates\":\"manual\",\"channel\":\"stable\"}" -> ""
2026/10/24 23:15:20 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:20 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:20 provision: manifest bac/tito: read failed: provision: manifest bac/tito: unexpected end of JSON input
2026/10/24 23:15:20 provision: manifest bac/tito: read failed: provision: manifest bac/tito: unexpected end of JSON input
2026/10/24 23:15:20 provision: acme.go.tito.io: not minted this pass: the app's update policy could not be read
2026/10/24 23:15:20 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 23:15:20 provision: manifest bac/tito: read failed: provision: manifest bac/tito: unexpected end of JSON input
2026/10/24 23:15:20 provision: acme.go.tito.io: not minted this pass: the app's update policy could not be read
2026/10/24 23:15:20 provision: minted instance route acme.go.tito.io held landing by mv_acme (app "tito" acct "bac")
2026/10/24 23:15:20 provision: record view: change index unusable (release: change index unreadable: store has no conditional read: unsupported operation): the walk records no generations
2026/10/24 23:15:20 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 23:15:20 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 23:15:20 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 23:15:20 provision: record view: change index unusable (release: change index malformed: invalid character 'n' looking for beginning of object key string): walking
2026/10/24 23:15:20 provision: record view: change index unusable (get refused): walking
2026/10/24 23:15:20 provision: record view: re-reading apps/bqc/shop failed: retrying on the next refresh
2026/10/24 23:15:20 provision: listing apps/bqc/shop/instances/: context canceled — its records are unseen this pass
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: record view: re-reading apps/bqc/shop failed: retrying on the next refresh
2026/10/24 23:15:20 provision: listing apps/bqc/shop/instances/: list refused — its records are unseen this pass
2026/10/24 23:15:20 provision: listing apps/bqc/shop/instances/: list refused — its records are unseen this pass
2026/10/24 23:15:20 provision: an app's records could not be listed: they are skipped
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping accounts/bqd/account.json: malformed account manifest: invalid character 'n' looking for beginning of object key string
2026/10/24 23:15:20 provision: skipping accounts/bqd/account.json: malformed account manifest: invalid character 'n' looking for beginning of object key string
2026/10/24 23:15:20 provision: skipping accounts/bqd/account.json: malformed account manifest: invalid character 'n' looking for beginning of object key string
2026/10/24 23:15:20 provision: record view: re-reading accounts/bqd failed: retrying on the next refresh
2026/10/24 23:15:20 provision: skipping accounts/bqd/account.json: read failed: list refused
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:20 provision: minted instance route one.example.com (app "shop" acct "bum")
2026/10/24 23:15:20 provision: minted instance route one.example.com (app "shop" acct "bum")
2026/10/24 23:15:20 provision: minted instance route one.example.com (app "shop" acct "bum")
2026/10/24 23:15:20 provision: removed retired instance route one.example.com (record gone)
2026/10/24 23:15:20 provision: skipping record apps/bum/shop/instances/one.example.com.json: empty channel
2026/10/24 23:15:20 provision: not removing one.example.com: its record exists but could not be read cleanly this pass
2026/10/24 23:15:20 provision: skipping record apps/bum/shop/instances/one.example.com.json: empty channel
2026/10/24 23:15:20 provision: removed retired instance route one.example.com (record gone)
2026/10/24 23:15:20 provision: not removing one.example.com: its record exists but could not be read cleanly this pass
2026/10/24 23:15:20 provision: record view: change index unusable (context deadline exceeded): walking
2026/10/24 23:15:20 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 23:15:21 provision: record view: change index unusable (context deadline exceeded): the walk records no generations
2026/10/24 23:15:21 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
--- FAIL: TestPlan14RootReadCensus (15.19s)
    plan14_root_reads_test.go:600: root read census: 55 discrepancies
        changed root read cli.go:runShip; review class, task, sites and digest
        changed root read cli.go:runShipAPI; review class, task, sites and digest
        changed root read internal/console/apicli.go:Server.handleAPIShip; review class, task, sites and digest
        changed root read internal/hostops/mutation_boundary_putfrom.go:conditionalRecordStore.PutFrom; review class, task, sites and digest
        changed root read internal/hostops/mutation_boundary_putfrom.go:mutationBoundary.PutFrom; review class, task, sites and digest
        changed root source envelope .
        changed root source envelope internal/console
        changed root source envelope internal/hostops
        changed root source envelope internal/release
        changed root source envelope internal/rootfsimage
        unclassified root read cli.go:shipNoteText file:ReadFile@223
        unclassified root read internal/console/apiship_rootfs.go:shipBody.Read file:Read@19,file:Read@398
        unclassified root read internal/console/apiship_rootfs.go:spoolRootfsPart file:OpenFile@114
        unclassified root read internal/release/rootfs.go:type Process file:Command@23
        unclassified root read internal/release/rootfs.go:validateProcess file:Command@242,file:Command@61,file:Command@80
        unclassified root read internal/release/rootfs_ship.go:hashSpooledFile file:Open@70
        unclassified root read internal/release/rootfs_ship.go:putImmutableFrom file:Open@106
        unclassified root read internal/rootfsimage/archive.go:OpenArchive file:Open@226,file:Stat@73
        unclassified root read internal/rootfsimage/dir.go:readDir file:EvalSymlinks@123,file:Readlink@1719,file:Stat@193,file:WalkDir@757
        unclassified root read internal/rootfsimage/errors.go:CommandError.Error file:Command@237
        unclassified root read internal/rootfsimage/errors.go:type CommandError file:Command@35
        unclassified root read internal/rootfsimage/flatten.go:boundedReader.Read file:Read@205,file:Read@24
        unclassified root read internal/rootfsimage/framework.go:FillConsole file:Command@897
        unclassified root read internal/rootfsimage/oci.go:OpenLayout file:OpenRoot@66
        unclassified root read internal/rootfsimage/oci.go:layoutStore.has file:Stat@57
        unclassified root read internal/rootfsimage/oci.go:layoutStore.open file:Open@345,file:Stat@116,file:Stat@449
        unclassified root read internal/rootfsimage/oci.go:ociReader.readBlob file:ReadAll@161
        unclassified root read internal/rootfsimage/oci.go:readFile file:ReadAll@279
        unclassified root read internal/rootfsimage/oci.go:verifier.Read file:Read@102,file:Read@19
        unclassified root read internal/rootfsimage/processes.go:ApplyImageConfig file:Command@549,file:Command@574
        unclassified root read internal/rootfsimage/processes.go:ResolveCommands file:Command@171,file:Command@230,file:Command@239
        unclassified root read internal/rootfsimage/processes.go:jitOf file:Command@56
        unclassified root read internal/rootfsimage/processes.go:shebangRuntime file:Open@60
        unclassified root read internal/rootfsimage/progarch.go:Tree.head file:Open@60
        unclassified root read internal/rootfsimage/squashfs.go:treeFS.Lstat file:Lstat@16,file:Stat@65
        unclassified root read internal/rootfsimage/squashfs.go:treeFS.Open file:Open@16,file:ReadFile@204
        unclassified root read internal/rootfsimage/squashfs.go:treeFS.ReadDir file:ReadDir@16
        unclassified root read internal/rootfsimage/squashfs.go:treeFS.ReadFile file:Open@139,file:Read@461,file:ReadFile@16
        unclassified root read internal/rootfsimage/squashfs.go:treeFS.Stat file:Stat@16
        unclassified root read internal/rootfsimage/squashfs.go:treeFile.Read file:Read@19
        unclassified root read internal/rootfsimage/squashfs.go:treeFile.Stat file:Stat@19
        unclassified root read internal/rootfsimage/squashfs.go:writeSquashfs file:Stat@1987
        unclassified root read internal/rootfsimage/tar.go:Tree.copyFile file:Open@67
        unclassified root read internal/rootfsimage/tree.go:Open file:Open@5,file:Stat@154,file:Stat@58
        unclassified root read internal/rootfsimage/tree.go:Tree.Open file:Open@15,file:Open@165
        unclassified root read internal/rootfsimage/tree.go:Tree.writeBlob file:OpenFile@285
        unclassified root read ship_rootfs.go:buildRootfs file:Command@1016,file:OpenFile@1379
        unclassified root read ship_rootfs.go:readProcessesFile file:ReadFile@87
        unclassified root read ship_runtime.go:execRunner file:CommandContext@135
        unclassified root read ship_runtime.go:openRootfsSource file:Open@268,file:Stat@146
        changed legacy declaration cli.go:runShip
        changed legacy declaration cli.go:runShipAPI
        changed legacy declaration internal/console/apicli.go:Server.handleAPIShip
        changed legacy declaration internal/hostops/mutation_boundary_putfrom.go:conditionalRecordStore.PutFrom
        changed legacy declaration internal/hostops/mutation_boundary_putfrom.go:mutationBoundary.PutFrom
        
        make census-card shows what changed; make census-propose NAME=<branch> CLAIMS=<file> writes the overlay and its approval card (AGENTS.md, The census)
FAIL
FAIL	github.com/carlosframework/platform/internal/provision	23.852s
ok  	github.com/carlosframework/platform/internal/publicrelease	0.010s
?   	github.com/carlosframework/platform/internal/regionname	[no test files]
ok  	github.com/carlosframework/platform/internal/registry	5.598s
ok  	github.com/carlosframework/platform/internal/relay	7.239s
ok  	github.com/carlosframework/platform/internal/release	27.001s
ok  	github.com/carlosframework/platform/internal/rollout	3.779s
ok  	github.com/carlosframework/platform/internal/rolloutwords	0.004s
ok  	github.com/carlosframework/platform/internal/rootaws	0.008s
ok  	github.com/carlosframework/platform/internal/rootfsimage	0.203s
ok  	github.com/carlosframework/platform/internal/rootparticipation	0.063s
ok  	github.com/carlosframework/platform/internal/rootstate	0.027s
ok  	github.com/carlosframework/platform/internal/runs	0.613s
ok  	github.com/carlosframework/platform/internal/s3compat	0.006s
ok  	github.com/carlosframework/platform/internal/safefile	0.011s
ok  	github.com/carlosframework/platform/internal/schedule	2.639s
ok  	github.com/carlosframework/platform/internal/seeds	0.012s
ok  	github.com/carlosframework/platform/internal/sim/engines	2.570s
ok  	github.com/carlosframework/platform/internal/sim/hostlife	10.572s
ok  	github.com/carlosframework/platform/internal/sim/litestreamfacts	4.083s
ok  	github.com/carlosframework/platform/internal/status	0.065s
ok  	github.com/carlosframework/platform/internal/steering	0.006s
ok  	github.com/carlosframework/platform/internal/stopevidence	0.287s
ok  	github.com/carlosframework/platform/internal/svcrole	0.006s
ok  	github.com/carlosframework/platform/internal/telemetry	0.004s
ok  	github.com/carlosframework/platform/internal/termfence	0.004s
ok  	github.com/carlosframework/platform/internal/tunnelclient	0.007s
ok  	github.com/carlosframework/platform/internal/unixdial	0.002s
ok  	github.com/carlosframework/platform/internal/updatewords	0.004s
ok  	github.com/carlosframework/platform/internal/usage	0.008s
ok  	github.com/carlosframework/platform/internal/version	0.002s
ok  	github.com/carlosframework/platform/internal/vet	1.700s
FAIL
=== internal_console@0 (83 s)
ok  	github.com/carlosframework/platform/internal/console	81.917s
=== internal_console@1 (41 s)
ok  	github.com/carlosframework/platform/internal/console	39.597s
=== internal_console@2 (38 s)
ok  	github.com/carlosframework/platform/internal/console	36.961s
=== internal_console@3 (42 s)
ok  	github.com/carlosframework/platform/internal/console	40.294s
=== internal_console@4 (43 s)
ok  	github.com/carlosframework/platform/internal/console	42.039s
=== internal_console@5 (44 s)
ok  	github.com/carlosframework/platform/internal/console	42.944s
=== internal_console@6 (39 s)
ok  	github.com/carlosframework/platform/internal/console	37.352s
=== internal_console@7 (50 s)
ok  	github.com/carlosframework/platform/internal/console	49.038s
=== root@0 (108 s)
ok  	github.com/carlosframework/platform	106.428s
=== root@1 (98 s)
ok  	github.com/carlosframework/platform	97.205s
=== root@2 (82 s)
ok  	github.com/carlosframework/platform	80.621s

FAILED: rest
make: *** [Makefile:19: test] Error 1

amadan: step gate failed: exit status 2

amadan: job failed at step gate — its output is above, not at the tail of this log
diff --git a/approved_rootfs_copy_test.go b/approved_rootfs_copy_test.go
index 6ebacb071..f6944ff71 100644
--- a/approved_rootfs_copy_test.go
+++ b/approved_rootfs_copy_test.go
@@ -25,7 +25,7 @@ const rootfsCopyRecordPath = "docs/superpowers/plans/2026-10-24-rootfs-apps-copy
var rootfsCopyIDPattern = regexp.MustCompile(`^RFS-[1-6]-C(0[1-9]|[1-9][0-9]{1,2})$`)
// rootfsCopyIDs is the deck's inventory, pinned as a literal list in the
-// deck's order: RFS-1-C01 to RFS-1-C87, then each later plan's rows. A
+// deck's order: RFS-1-C01 to RFS-1-C88, then each later plan's rows. A
// struck row stays in it: the deck keeps the row for history.
var rootfsCopyIDs = []string{
// Plan 1
@@ -50,7 +50,7 @@ var rootfsCopyIDs = []string{
"RFS-1-C73", "RFS-1-C74", "RFS-1-C75", "RFS-1-C76",
"RFS-1-C77", "RFS-1-C78", "RFS-1-C79", "RFS-1-C80",
"RFS-1-C81", "RFS-1-C82", "RFS-1-C83", "RFS-1-C84",
- "RFS-1-C85", "RFS-1-C86", "RFS-1-C87",
+ "RFS-1-C85", "RFS-1-C86", "RFS-1-C87", "RFS-1-C88",
// Plan 2
"RFS-2-C01", "RFS-2-C02", "RFS-2-C03", "RFS-2-C04",
"RFS-2-C05", "RFS-2-C06", "RFS-2-C07", "RFS-2-C08",
@@ -162,6 +162,8 @@ var rootfsCopyBuilt = []string{
"RFS-1-C22", "RFS-1-C23", "RFS-1-C24", "RFS-1-C25", "RFS-1-C26", "RFS-1-C27", "RFS-1-C28", "RFS-1-C29", "RFS-1-C79",
// Task 9: carlos ship --rootfs (cli.go, ship_rootfs.go, apimode_rootfs.go)
"RFS-1-C30", "RFS-1-C31", "RFS-1-C32", "RFS-1-C33", "RFS-1-C34", "RFS-1-C35", "RFS-1-C36", "RFS-1-C37", "RFS-1-C38", "RFS-1-C39", "RFS-1-C40", "RFS-1-C41", "RFS-1-C42", "RFS-1-C43", "RFS-1-C44", "RFS-1-C84",
+ // Task 10: the local container runtime (ship_runtime.go)
+ "RFS-1-C49", "RFS-1-C57", "RFS-1-C58", "RFS-1-C59", "RFS-1-C88",
}
func mustParseRootfsRecord(t *testing.T) []copyRow {
diff --git a/docs/superpowers/plans/2026-10-24-rootfs-apps-1-ship.md b/docs/superpowers/plans/2026-10-24-rootfs-apps-1-ship.md
index 0616aa6aa..fe3d83e77 100644
--- a/docs/superpowers/plans/2026-10-24-rootfs-apps-1-ship.md
+++ b/docs/superpowers/plans/2026-10-24-rootfs-apps-1-ship.md
@@ -214,8 +214,9 @@ Placeholders: `<app>` an app name; `<name>` a process name; `<var>` an environme
| RFS-1-C85 | ship_check.go | the <name> process runs <program>, which needs a JIT, and this release does not declare one. it passes here but stops at start on a box. ship it with --jit | approved |
| RFS-1-C86 | internal/rootfsimage/errors.go | the rootfs image is over 2 GiB, the most one release can carry. make the image smaller and ship again | approved |
| RFS-1-C87 | internal/rootfsimage/errors.go | <path> is over 2 GiB, the largest file a rootfs image can hold. make it smaller and ship again | approved |
+| RFS-1-C88 | ship_runtime.go | CARLOS_CONTAINER_RUNTIME must be docker or podman | approved |
-RFS-1-C78's `<digest>` is a `sha256:<hex>` digest. RFS-1-C80 to C83 are the first-ship forms of C18 to C21: the app has no other release, and its kind marker (deviation 10) names the ship that fixed its kind, which may not have published, so they never say "is one". RFS-1-C85 is a warning: it does not fail the check. Kept out of the table on purpose (diagnostics, not human text): the probe's one-line JSON on stdout, `validateManifest`'s existing terse messages, store errors wrapped for logs. RFS-1-C86 and C87 were added in the build (Task 6, the controller ruling on strings found in the build), for the Luna pass at the end of Plan 1: C86 is the writer's refusal when the image passes 2 GiB while it is written (the text of C26), C87 its refusal of a single file over 2 GiB before anything is written.
+RFS-1-C78's `<digest>` is a `sha256:<hex>` digest. RFS-1-C80 to C83 are the first-ship forms of C18 to C21: the app has no other release, and its kind marker (deviation 10) names the ship that fixed its kind, which may not have published, so they never say "is one". RFS-1-C85 is a warning: it does not fail the check. Kept out of the table on purpose (diagnostics, not human text): the probe's one-line JSON on stdout, `validateManifest`'s existing terse messages, store errors wrapped for logs. RFS-1-C86 and C87 were added in the build (Task 6, the controller ruling on strings found in the build), for the Luna pass at the end of Plan 1: C86 is the writer's refusal when the image passes 2 GiB while it is written (the text of C26), C87 its refusal of a single file over 2 GiB before anything is written. RFS-1-C88 was added in the build (Task 10, the controller ruling on strings found in the build): the refusal of a CARLOS_CONTAINER_RUNTIME that names neither runtime.
---
diff --git a/docs/superpowers/plans/2026-10-24-rootfs-apps-copy.md b/docs/superpowers/plans/2026-10-24-rootfs-apps-copy.md
index 8c051e7b2..855587df0 100644
--- a/docs/superpowers/plans/2026-10-24-rootfs-apps-copy.md
+++ b/docs/superpowers/plans/2026-10-24-rootfs-apps-copy.md
@@ -126,8 +126,9 @@ From the plan: Placeholders: `<app>` an app name; `<name>` a process name; `<var
| RFS-1-C85 | ship_check.go | the <name> process runs <program>, which needs a JIT, and this release does not declare one. it passes here but stops at start on a box. ship it with --jit | approved |
| RFS-1-C86 | internal/rootfsimage/errors.go | the rootfs image is over 2 GiB, the most one release can carry. make the image smaller and ship again | approved |
| RFS-1-C87 | internal/rootfsimage/errors.go | <path> is over 2 GiB, the largest file a rootfs image can hold. make it smaller and ship again | approved |
+| RFS-1-C88 | ship_runtime.go | CARLOS_CONTAINER_RUNTIME must be docker or podman | approved |
-From the plan: RFS-1-C78's `<digest>` is a `sha256:<hex>` digest. RFS-1-C80 to C83 are the first-ship forms of C18 to C21: the app has no other release, and its kind marker (deviation 10) names the ship that fixed its kind, which may not have published, so they never say "is one". RFS-1-C85 is a warning: it does not fail the check. Kept out of the table on purpose (diagnostics, not human text): the probe's one-line JSON on stdout, `validateManifest`'s existing terse messages, store errors wrapped for logs. RFS-1-C86 and C87 were added in the build (Task 6, the controller ruling on strings found in the build), for the Luna pass at the end of Plan 1: C86 is the writer's refusal when the image passes 2 GiB while it is written (the text of C26), C87 its refusal of a single file over 2 GiB before anything is written.
+From the plan: RFS-1-C78's `<digest>` is a `sha256:<hex>` digest. RFS-1-C80 to C83 are the first-ship forms of C18 to C21: the app has no other release, and its kind marker (deviation 10) names the ship that fixed its kind, which may not have published, so they never say "is one". RFS-1-C85 is a warning: it does not fail the check. Kept out of the table on purpose (diagnostics, not human text): the probe's one-line JSON on stdout, `validateManifest`'s existing terse messages, store errors wrapped for logs. RFS-1-C86 and C87 were added in the build (Task 6, the controller ruling on strings found in the build), for the Luna pass at the end of Plan 1: C86 is the writer's refusal when the image passes 2 GiB while it is written (the text of C26), C87 its refusal of a single file over 2 GiB before anything is written. RFS-1-C88 was added in the build (Task 10, the controller ruling on strings found in the build): the refusal of a CARLOS_CONTAINER_RUNTIME that names neither runtime.
## Plan 2: box isolation (`2026-10-24-rootfs-apps-2-box-isolation.md`)
diff --git a/internal/rootfsimage/tar.go b/internal/rootfsimage/tar.go
new file mode 100644
index 000000000..4fd216fdc
--- /dev/null
+++ b/internal/rootfsimage/tar.go
@@ -0,0 +1,87 @@
+package rootfsimage
+
+import (
+ "archive/tar"
+ "fmt"
+ "io"
+ "io/fs"
+)
+
+// WriteTar writes the tree as one tar stream, the form a container
+// runtime's import reads (rootfs apps Plan 1 Task 10, for carlos ship
+// --check).
+//
+// It calls Normalise first: the check container runs as an unprivileged
+// user, so it needs the same ownership and modes the box gets, and the tree
+// is changed in place. Entries are written in path order, so a directory
+// comes before what is in it. The root has no entry. Of the paths that
+// share one file's bytes, the first in path order carries them and the
+// others are hardlinks to it, as the tree holds them.
+func (t *Tree) WriteTar(w io.Writer) error {
+ t.Normalise()
+ tw := tar.NewWriter(w)
+ first := map[string]string{} // a file's spool name to the first path written for it
+ for _, e := range t.Entries() {
+ h := &tar.Header{
+ Name: e.Path,
+ Mode: tarMode(e.Mode),
+ Uid: int(e.UID),
+ Gid: int(e.GID),
+ ModTime: e.ModTime,
+ }
+ switch e.Type {
+ case TypeDir:
+ h.Typeflag = tar.TypeDir
+ h.Name += "/"
+ case TypeSymlink:
+ h.Typeflag, h.Linkname = tar.TypeSymlink, e.LinkTarget
+ case TypeFile:
+ if p, ok := first[e.src]; ok {
+ h.Typeflag, h.Linkname = tar.TypeLink, p
+ break
+ }
+ first[e.src] = e.Path
+ h.Typeflag, h.Size = tar.TypeReg, e.Size
+ default:
+ return fmt.Errorf("rootfsimage: %s has an unknown type", shown(e.Path))
+ }
+ if err := tw.WriteHeader(h); err != nil {
+ return err
+ }
+ if h.Typeflag != tar.TypeReg {
+ continue
+ }
+ if err := t.copyFile(tw, e); err != nil {
+ return err
+ }
+ }
+ return tw.Close()
+}
+
+func (t *Tree) copyFile(w io.Writer, e *Entry) error {
+ rc, err := t.Open(e)
+ if err != nil {
+ return err
+ }
+ _, err = io.CopyN(w, rc, e.Size)
+ if cerr := rc.Close(); err == nil {
+ err = cerr
+ }
+ return err
+}
+
+// tarMode is a mode as tar's mode field holds it: the permission bits plus
+// the setuid, setgid and sticky bits in their Unix positions.
+func tarMode(m fs.FileMode) int64 {
+ out := int64(m.Perm())
+ if m&fs.ModeSetuid != 0 {
+ out |= 0o4000
+ }
+ if m&fs.ModeSetgid != 0 {
+ out |= 0o2000
+ }
+ if m&fs.ModeSticky != 0 {
+ out |= 0o1000
+ }
+ return out
+}
diff --git a/internal/rootfsimage/tar_test.go b/internal/rootfsimage/tar_test.go
new file mode 100644
index 000000000..cdf3acb63
--- /dev/null
+++ b/internal/rootfsimage/tar_test.go
@@ -0,0 +1,144 @@
+package rootfsimage
+
+import (
+ "archive/tar"
+ "bytes"
+ "io"
+ "io/fs"
+ "testing"
+)
+
+func tarTree(t *testing.T) *Tree {
+ t.Helper()
+ tr := NewTree(t.TempDir())
+ apply(t, tr, layerTar(t,
+ tEntry{name: "./", typ: tar.TypeDir, mode: 0o700, uid: 5, gid: 5},
+ tEntry{name: "app/", typ: tar.TypeDir, mode: 0o750, uid: 1000, gid: 1000, mtime: 1_600_000_000},
+ tEntry{name: "app/config.ru", typ: tar.TypeReg, mode: 0o600, uid: 1000, gid: 1000, body: "run App\n", mtime: 1_600_000_001},
+ tEntry{name: "app/empty", typ: tar.TypeReg, mode: 0o644},
+ tEntry{name: "usr/bin/", typ: tar.TypeDir, mode: 0o755},
+ tEntry{name: "usr/bin/ruby", typ: tar.TypeReg, mode: 0o4755, body: "ruby 3.3"},
+ tEntry{name: "usr/bin/ruby2", typ: tar.TypeLink, link: "usr/bin/ruby"},
+ tEntry{name: "usr/bin/ruby3", typ: tar.TypeLink, link: "usr/bin/ruby"},
+ tEntry{name: "bin", typ: tar.TypeSymlink, mode: 0o755, link: "usr/bin"},
+ tEntry{name: "tmp/", typ: tar.TypeDir, mode: 0o1777},
+ ))
+ return tr
+}
+
+// The stream is what ApplyLayer reads: the tree it gives back has the same
+// entries, owners, modes, times, link targets, bytes and hardlink sharing,
+// as the tree stands after the normalisation WriteTar applies to it (the
+// check container runs as an unprivileged user, so it needs the box's
+// ownership and modes).
+func TestWriteTarRoundTripsThroughApplyLayer(t *testing.T) {
+ src := tarTree(t)
+ var buf bytes.Buffer
+ if err := src.WriteTar(&buf); err != nil {
+ t.Fatal(err)
+ }
+ // Normalised in place.
+ if e := mustLookup(t, src, "app/config.ru"); e.UID != 0 || e.Mode != 0o604 {
+ t.Errorf("app/config.ru = %d %v after WriteTar, want 0 0604", e.UID, e.Mode)
+ }
+ if e := mustLookup(t, src, "usr/bin/ruby"); e.Mode != 0o755 {
+ t.Errorf("usr/bin/ruby = %v after WriteTar, want setuid cleared", e.Mode)
+ }
+
+ got := NewTree(t.TempDir())
+ apply(t, got, buf.Bytes())
+
+ want := src.Entries()
+ have := got.Entries()
+ if len(have) != len(want) {
+ t.Fatalf("%d entries, want %d", len(have), len(want))
+ }
+ groups := func(es []*Entry) map[string]string { // a path to the first path sharing its bytes
+ first := map[string]string{}
+ out := map[string]string{}
+ for _, e := range es {
+ if e.Type != TypeFile {
+ continue
+ }
+ if _, ok := first[e.src]; !ok {
+ first[e.src] = e.Path
+ }
+ out[e.Path] = first[e.src]
+ }
+ return out
+ }
+ wg, hg := groups(want), groups(have)
+ for i, w := range want {
+ h := have[i]
+ if h.Path != w.Path || h.Type != w.Type || h.Mode != w.Mode || h.UID != w.UID || h.GID != w.GID ||
+ !h.ModTime.Equal(w.ModTime) || h.LinkTarget != w.LinkTarget || h.Size != w.Size {
+ t.Errorf("entry %d = %+v, want %+v", i, *h, *w)
+ }
+ if w.Type == TypeFile && readAll(t, got, h) != readAll(t, src, w) {
+ t.Errorf("%s has other bytes", w.Path)
+ }
+ if wg[w.Path] != hg[w.Path] {
+ t.Errorf("%s shares bytes with %q, want %q", w.Path, hg[w.Path], wg[w.Path])
+ }
+ }
+ if wg["usr/bin/ruby3"] != "usr/bin/ruby" || wg["usr/bin/ruby2"] != "usr/bin/ruby" {
+ t.Fatalf("the fixture has no hardlinks: %v", wg)
+ }
+}
+
+func TestWriteTarShape(t *testing.T) {
+ var buf bytes.Buffer
+ if err := tarTree(t).WriteTar(&buf); err != nil {
+ t.Fatal(err)
+ }
+ tr := tar.NewReader(&buf)
+ var names []string
+ types := map[string]byte{}
+ links := map[string]string{}
+ for {
+ h, err := tr.Next()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ t.Fatal(err)
+ }
+ names = append(names, h.Name)
+ types[h.Name] = h.Typeflag
+ links[h.Name] = h.Linkname
+ if h.Uid != 0 || h.Gid != 0 {
+ t.Errorf("%s is owned by %d:%d", h.Name, h.Uid, h.Gid)
+ }
+ if h.Typeflag == tar.TypeLink && h.Size != 0 {
+ t.Errorf("hardlink %s carries %d bytes", h.Name, h.Size)
+ }
+ }
+ wantNames := []string{"app/", "app/config.ru", "app/empty", "bin", "tmp/", "usr/", "usr/bin/", "usr/bin/ruby", "usr/bin/ruby2", "usr/bin/ruby3"}
+ if len(names) != len(wantNames) {
+ t.Fatalf("names = %q, want %q", names, wantNames)
+ }
+ for i := range names {
+ if names[i] != wantNames[i] {
+ t.Fatalf("names = %q, want %q", names, wantNames)
+ }
+ }
+ if types["usr/bin/ruby"] != tar.TypeReg || types["usr/bin/ruby2"] != tar.TypeLink || links["usr/bin/ruby2"] != "usr/bin/ruby" || links["usr/bin/ruby3"] != "usr/bin/ruby" {
+ t.Errorf("types = %v, links = %v", types, links)
+ }
+ if types["bin"] != tar.TypeSymlink || links["bin"] != "usr/bin" {
+ t.Errorf("bin = %v -> %q", types["bin"], links["bin"])
+ }
+}
+
+func TestWriteTarKeepsSticky(t *testing.T) {
+ tr := tarTree(t)
+ var buf bytes.Buffer
+ if err := tr.WriteTar(&buf); err != nil {
+ t.Fatal(err)
+ }
+ got := NewTree(t.TempDir())
+ apply(t, got, buf.Bytes())
+ if e := mustLookup(t, got, "tmp"); e.Mode != 0o777|fs.ModeSticky {
+ t.Errorf("tmp = %v, want 0777 sticky", e.Mode)
+ }
+}
diff --git a/ship_rootfs.go b/ship_rootfs.go
index c2e3eb6d7..43d2ceb4b 100644
--- a/ship_rootfs.go
+++ b/ship_rootfs.go
@@ -266,23 +266,20 @@ func readProcessesFile(path string) (map[string]release.Process, error) {
return nil, fmt.Errorf("--processes %s: %w", path, err)
}
-// buildRootfs opens src and makes it a rootfs release's image: the mount
-// points a box needs added, a directory's programs checked for arm64, the
-// image's config merged into procs, console filled in for a framework it
-// knows (RFS-1-C40), the processes validated, then their commands resolved
-// in the image. With write it writes the squashfs image to
-// <scratch>/rootfs.squashfs (RFS-1-C42). The tree's spool is under scratch,
-// which the caller removes.
+// buildRootfs opens src (a path, or a local image name exported with the
+// local container runtime: openRootfsSource) and makes it a rootfs release's
+// image: the mount points a box needs added, a directory's programs checked
+// for arm64, the image's config merged into procs, console filled in for a
+// framework it knows (RFS-1-C40), the processes validated, then their
+// commands resolved in the image. With write it writes the squashfs image to
+// <scratch>/rootfs.squashfs (RFS-1-C42). The tree's spool and any exported
+// image are under scratch, which the caller removes.
//
// The order matters: console is filled after the config is merged, so it
// is looked up on the image's PATH, and the processes are validated before
// anything reads a command's first word.
func buildRootfs(ctx context.Context, src string, procs map[string]release.Process, scratch string, write bool) (*builtRootfs, error) {
- spool := filepath.Join(scratch, "spool")
- if err := os.Mkdir(spool, 0o700); err != nil {
- return nil, err
- }
- t, err := rootfsimage.Open(src, spool)
+ t, err := openRootfsSource(ctx, src, scratch)
if err != nil {
return nil, err
}
diff --git a/ship_runtime.go b/ship_runtime.go
new file mode 100644
index 000000000..e29933cea
--- /dev/null
+++ b/ship_runtime.go
@@ -0,0 +1,169 @@
+package main
+
+import (
+ "bytes"
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "regexp"
+ "strings"
+
+ "github.com/carlosframework/platform/internal/rootfsimage"
+)
+
+// The local container runtime (rootfs apps Plan 1 Task 10): Docker or
+// Podman, found on this machine. carlos ship --rootfs needs one for two
+// things only: to export a local image named instead of saved (a source that
+// is not a path), and to run the image for --check. Shipping an OCI layout,
+// a save archive or a directory needs none.
+
+// errNoRuntime is --check's refusal when neither Docker nor Podman is
+// installed (RFS-1-C57).
+var errNoRuntime = errors.New("--check runs the image with Docker or Podman, and neither is installed here")
+
+// runnerFunc runs the runtime's binary with args, feeding it stdin (nil for
+// none), and answers its stdout. A failure carries the runtime's stderr.
+type runnerFunc func(ctx context.Context, stdin io.Reader, args ...string) ([]byte, error)
+
+// containerRuntime is the runtime found: name is "docker" or "podman", and
+// run runs its binary.
+type containerRuntime struct {
+ name string
+ run runnerFunc
+}
+
+// findContainerRuntime is the runtime to use: the one CARLOS_CONTAINER_RUNTIME
+// names, else docker on PATH, else podman. When none can be run it is
+// errNoRuntime.
+func findContainerRuntime() (containerRuntime, error) {
+ names := []string{"docker", "podman"}
+ if v := os.Getenv("CARLOS_CONTAINER_RUNTIME"); v != "" {
+ if v != "docker" && v != "podman" {
+ return containerRuntime{}, errors.New("CARLOS_CONTAINER_RUNTIME must be docker or podman")
+ }
+ names = []string{v}
+ }
+ for _, name := range names {
+ if bin, err := exec.LookPath(name); err == nil {
+ return containerRuntime{name: name, run: execRunner(bin)}, nil
+ }
+ }
+ return containerRuntime{}, errNoRuntime
+}
+
+// execRunner runs the binary at bin. Its error is the runtime's own
+// message, the last of its stderr, so a caller can show why it failed.
+func execRunner(bin string) runnerFunc {
+ return func(ctx context.Context, stdin io.Reader, args ...string) ([]byte, error) {
+ cmd := exec.CommandContext(ctx, bin, args...)
+ cmd.Stdin = stdin
+ var stdout, stderr bytes.Buffer
+ cmd.Stdout, cmd.Stderr = &stdout, &stderr
+ if err := cmd.Run(); err != nil {
+ if msg := strings.TrimSpace(stderr.String()); msg != "" {
+ return nil, errors.New(msg)
+ }
+ return nil, err
+ }
+ return stdout.Bytes(), nil
+ }
+}
+
+// saveImage exports the local image ref to the archive file out: docker
+// save writes the archive Docker makes, podman save an OCI archive.
+// Failure is RFS-1-C59.
+func (rt containerRuntime) saveImage(ctx context.Context, ref, out string) error {
+ args := []string{"save", "-o", out, ref}
+ if rt.name == "podman" {
+ args = []string{"save", "--format", "oci-archive", "-o", out, ref}
+ }
+ if _, err := rt.run(ctx, nil, args...); err != nil {
+ return fmt.Errorf("could not export %s with %s: %s", ref, rt.name, err)
+ }
+ return nil
+}
+
+// importTree imports t into the runtime as the image name, built for
+// linux/arm64: WriteTar piped to the runtime's import. The tree is
+// normalised in place by WriteTar.
+func (rt containerRuntime) importTree(ctx context.Context, t *rootfsimage.Tree, name string) error {
+ args := []string{"import", "--platform", "linux/arm64", "-", name}
+ if rt.name == "podman" {
+ args = []string{"import", "--os", "linux", "--arch", "arm64", "-", name}
+ }
+ pr, pw := io.Pipe()
+ done := make(chan error, 1)
+ go func() {
+ err := t.WriteTar(pw)
+ pw.CloseWithError(err) // nil closes it as EOF
+ done <- err
+ }()
+ _, err := rt.run(ctx, pr, args...)
+ // A runtime that stopped reading must not leave the writer blocked.
+ pr.CloseWithError(io.ErrClosedPipe)
+ if werr := <-done; err == nil && werr != nil && !errors.Is(werr, io.ErrClosedPipe) {
+ err = werr
+ }
+ return err
+}
+
+var (
+ // Docker's grammar for a reference, in the parts carlos accepts: a
+ // registry host with an optional port, lower-case path components, a
+ // tag and a sha256 digest.
+ imageRefHost = `[A-Za-z0-9]+([.-][A-Za-z0-9]+)*(:[0-9]+)?`
+ imageRefPath = `[a-z0-9]+([._-][a-z0-9]+)*(/[a-z0-9]+([._-][a-z0-9]+)*)*`
+ imageRefTag = `[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}`
+ imageRefDigest = `sha256:[0-9a-f]{64}`
+ imageRefRE = regexp.MustCompile(`^(` + imageRefHost + `/)?` + imageRefPath + `(:` + imageRefTag + `)?(@` + imageRefDigest + `)?$`)
+)
+
+// looksLikeImageRef reports whether s can name a local image: an optional
+// host[:port]/, path components of lower-case letters and digits joined by
+// ".", "_" or "-" and separated by "/", an optional :tag and an optional
+// @sha256:<digest>. It leaves out anything that starts like a path or a
+// flag ("./shop", "/abs", "-x").
+func looksLikeImageRef(s string) bool {
+ return imageRefRE.MatchString(s)
+}
+
+// openRootfsSource opens src as a tree: an existing path as
+// rootfsimage.Open does (an OCI layout, a save archive or a directory), else
+// a local image name, exported with the local runtime to <scratch>/image.tar
+// and opened from there. The tree's spool is <scratch>/spool. Everything it
+// writes is under scratch, which the caller removes.
+func openRootfsSource(ctx context.Context, src, scratch string) (*rootfsimage.Tree, error) {
+ spool := filepath.Join(scratch, "spool")
+ _, err := os.Stat(src)
+ switch {
+ case err == nil:
+ if err := os.Mkdir(spool, 0o700); err != nil {
+ return nil, err
+ }
+ return rootfsimage.Open(src, spool)
+ case !errors.Is(err, os.ErrNotExist):
+ return nil, err
+ case !looksLikeImageRef(src):
+ return nil, fmt.Errorf("%s is not a file, a directory or a local image", src)
+ }
+
+ rt, err := findContainerRuntime()
+ if err != nil {
+ if errors.Is(err, errNoRuntime) {
+ return nil, fmt.Errorf("%s is not a file or a directory, and there is no Docker or Podman here to export it as an image", src)
+ }
+ return nil, err
+ }
+ archive := filepath.Join(scratch, "image.tar")
+ if err := rt.saveImage(ctx, src, archive); err != nil {
+ return nil, err
+ }
+ if err := os.Mkdir(spool, 0o700); err != nil {
+ return nil, err
+ }
+ return rootfsimage.OpenArchive(archive, spool)
+}
diff --git a/ship_runtime_test.go b/ship_runtime_test.go
new file mode 100644
index 000000000..43f90219b
--- /dev/null
+++ b/ship_runtime_test.go
@@ -0,0 +1,419 @@
+package main
+
+import (
+ "archive/tar"
+ "bytes"
+ "context"
+ "crypto/sha256"
+ "encoding/hex"
+ "encoding/json"
+ "errors"
+ "io"
+ "os"
+ "path/filepath"
+ "reflect"
+ "runtime"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/carlosframework/platform/internal/rootfsimage"
+)
+
+// The tests never need Docker or Podman: the runtime is a stub script on a
+// scratch PATH (the stub exercises the production runner end to end) or a
+// recording runnerFunc.
+
+// stubRuntime writes an executable shell script called name into dir.
+func stubRuntime(t *testing.T, dir, name, script string) {
+ t.Helper()
+ if runtime.GOOS == "windows" {
+ t.Skip("runtime stubs are shell scripts")
+ }
+ if err := os.WriteFile(filepath.Join(dir, name), []byte("#!/bin/sh\nPATH=/usr/bin:/bin\n"+script), 0o755); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// onlyPath makes dir the whole PATH and leaves the runtime choice unset.
+func onlyPath(t *testing.T, dir string) {
+ t.Helper()
+ t.Setenv("PATH", dir)
+ t.Setenv("CARLOS_CONTAINER_RUNTIME", "")
+}
+
+func TestFindContainerRuntime(t *testing.T) {
+ dir := t.TempDir()
+ onlyPath(t, dir)
+ if _, err := findContainerRuntime(); !errors.Is(err, errNoRuntime) {
+ t.Fatalf("with neither: err = %v, want errNoRuntime", err)
+ }
+ if got, want := errNoRuntime.Error(), "--check runs the image with Docker or Podman, and neither is installed here"; got != want {
+ t.Errorf("errNoRuntime = %q", got)
+ }
+
+ stubRuntime(t, dir, "podman", "exit 0\n")
+ rt, err := findContainerRuntime()
+ if err != nil || rt.name != "podman" || rt.run == nil {
+ t.Fatalf("podman only: %+v, %v", rt, err)
+ }
+
+ stubRuntime(t, dir, "docker", "exit 0\n")
+ if rt, err = findContainerRuntime(); err != nil || rt.name != "docker" {
+ t.Fatalf("both: %+v, %v", rt, err)
+ }
+
+ t.Setenv("CARLOS_CONTAINER_RUNTIME", "podman")
+ if rt, err = findContainerRuntime(); err != nil || rt.name != "podman" {
+ t.Fatalf("CARLOS_CONTAINER_RUNTIME=podman with both: %+v, %v", rt, err)
+ }
+
+ // A named runtime that is not installed is not replaced by the other.
+ only := t.TempDir()
+ stubRuntime(t, only, "podman", "exit 0\n")
+ t.Setenv("PATH", only)
+ t.Setenv("CARLOS_CONTAINER_RUNTIME", "docker")
+ if _, err = findContainerRuntime(); !errors.Is(err, errNoRuntime) {
+ t.Fatalf("docker named, podman only: err = %v, want errNoRuntime", err)
+ }
+
+ t.Setenv("CARLOS_CONTAINER_RUNTIME", "nerdctl")
+ if _, err = findContainerRuntime(); err == nil || err.Error() != "CARLOS_CONTAINER_RUNTIME must be docker or podman" {
+ t.Fatalf("nerdctl: err = %v", err)
+ }
+}
+
+func TestLooksLikeImageRef(t *testing.T) {
+ digest := "sha256:" + strings.Repeat("ab12", 16)
+ for _, ok := range []string{
+ "shop", "shop:latest", "example.com:5000/team/shop:1.2", "shop@" + digest,
+ "team/shop", "localhost/shop:v1", "ghcr.io/team/my-shop_2.x:1.0-rc1", "shop:1.2@" + digest,
+ } {
+ if !looksLikeImageRef(ok) {
+ t.Errorf("%q refused", ok)
+ }
+ }
+ for _, bad := range []string{
+ "", "./shop", "../shop", "Shop", "shop:", "/abs", "a//b", "shop/", "-shop", "shop:-1",
+ "shop@sha256:abc", "shop@" + strings.ToUpper(digest), "shop:" + strings.Repeat("a", 129),
+ "team/Shop", "shop name", "shop\n",
+ } {
+ if looksLikeImageRef(bad) {
+ t.Errorf("%q accepted", bad)
+ }
+ }
+}
+
+// legacyArchive writes the pre-OCI docker save form with one layer holding
+// app/hello (the minimal builder of rootfsimage's tests, which this package
+// cannot import: preflight 1.23).
+func legacyArchive(t *testing.T, path string) {
+ t.Helper()
+ var layer bytes.Buffer
+ lw := tar.NewWriter(&layer)
+ mt := time.Unix(1_700_000_000, 0)
+ for _, h := range []*tar.Header{
+ {Name: "app/", Typeflag: tar.TypeDir, Mode: 0o755, ModTime: mt},
+ {Name: "app/hello", Typeflag: tar.TypeReg, Mode: 0o644, Size: 3, ModTime: mt},
+ } {
+ if err := lw.WriteHeader(h); err != nil {
+ t.Fatal(err)
+ }
+ if h.Typeflag == tar.TypeReg {
+ if _, err := lw.Write([]byte("hi\n")); err != nil {
+ t.Fatal(err)
+ }
+ }
+ }
+ if err := lw.Close(); err != nil {
+ t.Fatal(err)
+ }
+ cfg, err := json.Marshal(map[string]any{"architecture": "arm64", "os": "linux", "config": map[string]any{}})
+ if err != nil {
+ t.Fatal(err)
+ }
+ sum := sha256.Sum256(cfg)
+ cfgName := hex.EncodeToString(sum[:]) + ".json"
+ mj, err := json.Marshal([]map[string]any{{"Config": cfgName, "RepoTags": []string{"shop:latest"}, "Layers": []string{"l1/layer.tar"}}})
+ if err != nil {
+ t.Fatal(err)
+ }
+ var out bytes.Buffer
+ tw := tar.NewWriter(&out)
+ for _, f := range []struct {
+ name string
+ body []byte
+ }{{cfgName, cfg}, {"l1/layer.tar", layer.Bytes()}, {"manifest.json", mj}} {
+ if err := tw.WriteHeader(&tar.Header{Name: f.name, Typeflag: tar.TypeReg, Mode: 0o644, Size: int64(len(f.body)), ModTime: mt}); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := tw.Write(f.body); err != nil {
+ t.Fatal(err)
+ }
+ }
+ if err := tw.Close(); err != nil {
+ t.Fatal(err)
+ }
+ if err := os.WriteFile(path, out.Bytes(), 0o644); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// saveStub is a docker that logs its arguments to $FAKE_LOG and, for save,
+// copies $FAKE_ARCHIVE to the -o path.
+const saveStub = `echo "$@" >> "$FAKE_LOG"
+out=
+prev=
+for a in "$@"; do
+ if [ "$prev" = -o ]; then out=$a; fi
+ prev=$a
+done
+cat "$FAKE_ARCHIVE" > "$out"
+`
+
+func TestOpenRootfsSourceSavesAnImageName(t *testing.T) {
+ bin, work := t.TempDir(), t.TempDir()
+ stubRuntime(t, bin, "docker", saveStub)
+ onlyPath(t, bin)
+ archive, log := filepath.Join(work, "fixture.tar"), filepath.Join(work, "log")
+ legacyArchive(t, archive)
+ t.Setenv("FAKE_ARCHIVE", archive)
+ t.Setenv("FAKE_LOG", log)
+
+ scratch := t.TempDir()
+ tree, err := openRootfsSource(context.Background(), "shop:latest", scratch)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if e, ok := tree.Lookup("app/hello"); !ok || e.Type != rootfsimage.TypeFile || e.Size != 3 {
+ t.Errorf("app/hello = %+v, %v", e, ok)
+ }
+ got, err := os.ReadFile(log)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if want := "save -o " + filepath.Join(scratch, "image.tar") + " shop:latest\n"; string(got) != want {
+ t.Errorf("runtime saw %q, want %q", got, want)
+ }
+ // Everything it wrote is under the scratch the ship removes.
+ for _, name := range []string{"image.tar", "spool"} {
+ if _, err := os.Stat(filepath.Join(scratch, name)); err != nil {
+ t.Errorf("scratch lacks %s: %v", name, err)
+ }
+ }
+}
+
+func TestOpenRootfsSourceSavesWithPodman(t *testing.T) {
+ bin, work := t.TempDir(), t.TempDir()
+ stubRuntime(t, bin, "podman", saveStub)
+ onlyPath(t, bin)
+ archive, log := filepath.Join(work, "fixture.tar"), filepath.Join(work, "log")
+ legacyArchive(t, archive)
+ t.Setenv("FAKE_ARCHIVE", archive)
+ t.Setenv("FAKE_LOG", log)
+
+ scratch := t.TempDir()
+ if _, err := openRootfsSource(context.Background(), "shop", scratch); err != nil {
+ t.Fatal(err)
+ }
+ got, _ := os.ReadFile(log)
+ if want := "save --format oci-archive -o " + filepath.Join(scratch, "image.tar") + " shop\n"; string(got) != want {
+ t.Errorf("runtime saw %q, want %q", got, want)
+ }
+}
+
+func TestOpenRootfsSourceTakesAPathBeforeAName(t *testing.T) {
+ // No runtime at all: a directory named like an image is the directory.
+ onlyPath(t, t.TempDir())
+ dir := filepath.Join(t.TempDir(), "shop")
+ if err := os.Mkdir(dir, 0o755); err != nil {
+ t.Fatal(err)
+ }
+ if err := os.WriteFile(filepath.Join(dir, "f"), []byte("x"), 0o644); err != nil {
+ t.Fatal(err)
+ }
+ wd, _ := os.Getwd()
+ if err := os.Chdir(filepath.Dir(dir)); err != nil {
+ t.Fatal(err)
+ }
+ defer os.Chdir(wd)
+
+ scratch := t.TempDir()
+ for _, src := range []string{dir, "shop"} {
+ if err := os.RemoveAll(filepath.Join(scratch, "spool")); err != nil {
+ t.Fatal(err)
+ }
+ tree, err := openRootfsSource(context.Background(), src, scratch)
+ if err != nil {
+ if runtime.GOOS == "windows" {
+ t.Skip("a directory source needs Linux or macOS")
+ }
+ t.Fatalf("%s: %v", src, err)
+ }
+ if _, ok := tree.Lookup("f"); !ok {
+ t.Errorf("%s: f missing", src)
+ }
+ }
+}
+
+func TestOpenRootfsSourceSaveFailure(t *testing.T) {
+ bin := t.TempDir()
+ stubRuntime(t, bin, "docker", "echo 'Error response from daemon: No such image: shop:latest' >&2\nexit 1\n")
+ onlyPath(t, bin)
+ _, err := openRootfsSource(context.Background(), "shop:latest", t.TempDir())
+ want := "could not export shop:latest with docker: Error response from daemon: No such image: shop:latest"
+ if err == nil || err.Error() != want {
+ t.Errorf("err = %v, want %q", err, want)
+ }
+}
+
+func TestOpenRootfsSourceWithNoRuntime(t *testing.T) {
+ onlyPath(t, t.TempDir())
+ _, err := openRootfsSource(context.Background(), "shop:latest", t.TempDir())
+ want := "shop:latest is not a file or a directory, and there is no Docker or Podman here to export it as an image"
+ if err == nil || err.Error() != want {
+ t.Errorf("err = %v, want %q", err, want)
+ }
+}
+
+func TestOpenRootfsSourceWithNeitherPathNorName(t *testing.T) {
+ // A runtime is there; it must not be asked.
+ bin, work := t.TempDir(), t.TempDir()
+ stubRuntime(t, bin, "docker", saveStub)
+ onlyPath(t, bin)
+ t.Setenv("FAKE_LOG", filepath.Join(work, "log"))
+ for _, src := range []string{"./no-such-dir", "/no/such/path", "Shop"} {
+ _, err := openRootfsSource(context.Background(), src, t.TempDir())
+ if want := src + " is not a file, a directory or a local image"; err == nil || err.Error() != want {
+ t.Errorf("%s: err = %v, want %q", src, err, want)
+ }
+ }
+ if _, err := os.Stat(filepath.Join(work, "log")); err == nil {
+ t.Error("the runtime was run for something that is not an image name")
+ }
+}
+
+func TestImportTreeArgs(t *testing.T) {
+ for _, c := range []struct {
+ name string
+ want []string
+ }{
+ {"docker", []string{"import", "--platform", "linux/arm64", "-", "carlos-check:1"}},
+ {"podman", []string{"import", "--os", "linux", "--arch", "arm64", "-", "carlos-check:1"}},
+ } {
+ t.Run(c.name, func(t *testing.T) {
+ tree := rootfsimage.NewTree(t.TempDir())
+ if err := tree.ApplyLayer(bytes.NewReader(smallLayer(t))); err != nil {
+ t.Fatal(err)
+ }
+ var gotArgs []string
+ var names []string
+ rt := containerRuntime{name: c.name, run: func(ctx context.Context, stdin io.Reader, args ...string) ([]byte, error) {
+ gotArgs = args
+ tr := tar.NewReader(stdin)
+ for {
+ h, err := tr.Next()
+ if err == io.EOF {
+ return nil, nil
+ }
+ if err != nil {
+ return nil, err
+ }
+ names = append(names, h.Name)
+ }
+ }}
+ if err := rt.importTree(context.Background(), tree, "carlos-check:1"); err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(gotArgs, c.want) {
+ t.Errorf("argv = %q, want %q", gotArgs, c.want)
+ }
+ if want := []string{"app/", "app/hello"}; !reflect.DeepEqual(names, want) {
+ t.Errorf("tar entries = %q, want %q", names, want)
+ }
+ })
+ }
+}
+
+// A runtime that fails without reading its input must not leave the tar
+// writer blocked, and its error is the one returned.
+func TestImportTreeRuntimeFailsEarly(t *testing.T) {
+ tree := rootfsimage.NewTree(t.TempDir())
+ if err := tree.ApplyLayer(bytes.NewReader(smallLayer(t))); err != nil {
+ t.Fatal(err)
+ }
+ boom := errors.New("boom")
+ rt := containerRuntime{name: "docker", run: func(context.Context, io.Reader, ...string) ([]byte, error) { return nil, boom }}
+ done := make(chan error, 1)
+ go func() { done <- rt.importTree(context.Background(), tree, "x") }()
+ select {
+ case err := <-done:
+ if !errors.Is(err, boom) {
+ t.Errorf("err = %v, want boom", err)
+ }
+ case <-time.After(10 * time.Second):
+ t.Fatal("importTree is stuck")
+ }
+}
+
+// Through the production runner: the tar reaches the binary's stdin.
+func TestImportTreeThroughTheProductionRunner(t *testing.T) {
+ bin, work := t.TempDir(), t.TempDir()
+ stubRuntime(t, bin, "docker", "echo \"$@\" > \"$FAKE_LOG\"\ncat > \"$FAKE_STDIN\"\n")
+ onlyPath(t, bin)
+ t.Setenv("FAKE_LOG", filepath.Join(work, "log"))
+ t.Setenv("FAKE_STDIN", filepath.Join(work, "stdin.tar"))
+ tree := rootfsimage.NewTree(t.TempDir())
+ if err := tree.ApplyLayer(bytes.NewReader(smallLayer(t))); err != nil {
+ t.Fatal(err)
+ }
+ rt, err := findContainerRuntime()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := rt.importTree(context.Background(), tree, "carlos-check:1"); err != nil {
+ t.Fatal(err)
+ }
+ log, _ := os.ReadFile(filepath.Join(work, "log"))
+ if want := "import --platform linux/arm64 - carlos-check:1\n"; string(log) != want {
+ t.Errorf("runtime saw %q, want %q", log, want)
+ }
+ f, err := os.Open(filepath.Join(work, "stdin.tar"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+ back := rootfsimage.NewTree(t.TempDir())
+ if err := back.ApplyLayer(f); err != nil {
+ t.Fatalf("what the runtime read is not a layer: %v", err)
+ }
+ if e, ok := back.Lookup("app/hello"); !ok || e.UID != 0 || e.Mode != 0o644 {
+ t.Errorf("app/hello = %+v, %v", e, ok)
+ }
+}
+
+// smallLayer is one layer with app/hello, owned by an unprivileged user so
+// the import's normalisation shows.
+func smallLayer(t *testing.T) []byte {
+ t.Helper()
+ var buf bytes.Buffer
+ tw := tar.NewWriter(&buf)
+ mt := time.Unix(1_700_000_000, 0)
+ for _, h := range []*tar.Header{
+ {Name: "app/", Typeflag: tar.TypeDir, Mode: 0o700, Uid: 1000, Gid: 1000, ModTime: mt},
+ {Name: "app/hello", Typeflag: tar.TypeReg, Mode: 0o640, Uid: 1000, Gid: 1000, Size: 3, ModTime: mt},
+ } {
+ if err := tw.WriteHeader(h); err != nil {
+ t.Fatal(err)
+ }
+ if h.Typeflag == tar.TypeReg {
+ if _, err := tw.Write([]byte("hi\n")); err != nil {
+ t.Fatal(err)
+ }
+ }
+ }
+ if err := tw.Close(); err != nil {
+ t.Fatal(err)
+ }
+ return buf.Bytes()
+}