carlos / platform Public

rootfsimage: image env, command lookup and the console fill-in (rootfs Plan 1 Task 7)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 9db3202123cb194b73b974283578c1d701e04812 parent 20d38b5
6 files changed, +766 −0
  • approved_rootfs_copy_test.go +2 −0
  • internal/rootfsimage/errors.go +17 −0
  • internal/rootfsimage/framework.go +86 −0
  • internal/rootfsimage/framework_test.go +141 −0
  • internal/rootfsimage/processes.go +236 −0
  • internal/rootfsimage/processes_test.go +284 −0

CI failed — run details

CI log
=== gate ===
.amadan/test-gate.sh
=== launchctx (0 s)
ok  	amadan.net/carlos/platform.git/launchctx	0.017s
?   	amadan.net/carlos/platform.git/launchctx/controlname	[no test files]
?   	amadan.net/carlos/platform.git/launchctx/wireid	[no test files]
=== vet (6 s)
=== gofmt (0 s)
gofmt -l .: clean
=== rest (145 s)
?   	github.com/carlosframework/platform/cmd/changelog	[no test files]
ok  	github.com/carlosframework/platform/cmd/console	4.379s
ok  	github.com/carlosframework/platform/cmd/moveprobe	11.942s
ok  	github.com/carlosframework/platform/cmd/zddprobe	0.771s
ok  	github.com/carlosframework/platform/internal/activator	57.877s
ok  	github.com/carlosframework/platform/internal/agentsock	0.024s
ok  	github.com/carlosframework/platform/internal/alerting	0.005s
ok  	github.com/carlosframework/platform/internal/analytics	0.023s
ok  	github.com/carlosframework/platform/internal/appconfig	3.274s
ok  	github.com/carlosframework/platform/internal/apperr	0.170s
ok  	github.com/carlosframework/platform/internal/applog	0.360s
ok  	github.com/carlosframework/platform/internal/awsinv	0.008s
ok  	github.com/carlosframework/platform/internal/boxchoice	0.005s
ok  	github.com/carlosframework/platform/internal/boxid	0.641s
?   	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.010s
ok  	github.com/carlosframework/platform/internal/caps	0.016s
ok  	github.com/carlosframework/platform/internal/certwarm	0.002s
ok  	github.com/carlosframework/platform/internal/cgroup	0.813s
ok  	github.com/carlosframework/platform/internal/changelog	0.664s
ok  	github.com/carlosframework/platform/internal/claimactivation	1.533s
ok  	github.com/carlosframework/platform/internal/clamd	0.071s
?   	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.636s
ok  	github.com/carlosframework/platform/internal/dbdoor/dbdoortest	0.009s
ok  	github.com/carlosframework/platform/internal/dbquery	0.006s
ok  	github.com/carlosframework/platform/internal/dbreads	2.204s
?   	github.com/carlosframework/platform/internal/dbreads/dbreadstest	[no test files]
ok  	github.com/carlosframework/platform/internal/dbverify	0.006s
ok  	github.com/carlosframework/platform/internal/dnsrec	0.018s
ok  	github.com/carlosframework/platform/internal/docsite	0.016s
ok  	github.com/carlosframework/platform/internal/domains	3.223s
ok  	github.com/carlosframework/platform/internal/doorkey	0.009s
ok  	github.com/carlosframework/platform/internal/economics	0.005s
ok  	github.com/carlosframework/platform/internal/edge	45.423s
?   	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.258s
ok  	github.com/carlosframework/platform/internal/gate	2.030s
ok  	github.com/carlosframework/platform/internal/genselect	0.046s
ok  	github.com/carlosframework/platform/internal/geo	0.023s
ok  	github.com/carlosframework/platform/internal/geoip	0.040s
ok  	github.com/carlosframework/platform/internal/historyreadback	0.268s
ok  	github.com/carlosframework/platform/internal/host	141.724s
ok  	github.com/carlosframework/platform/internal/hostactors	5.792s
ok  	github.com/carlosframework/platform/internal/hostactors/awsmembership	0.008s
ok  	github.com/carlosframework/platform/internal/hostbox	3.551s
ok  	github.com/carlosframework/platform/internal/hostclaim	0.946s
ok  	github.com/carlosframework/platform/internal/hostenv	0.007s
ok  	github.com/carlosframework/platform/internal/hostevidence	0.016s
ok  	github.com/carlosframework/platform/internal/hostexec	5.836s
ok  	github.com/carlosframework/platform/internal/hostfence	0.057s
ok  	github.com/carlosframework/platform/internal/hostfiles	10.194s
ok  	github.com/carlosframework/platform/internal/hostfloor	0.022s
ok  	github.com/carlosframework/platform/internal/hostguard	1.108s
ok  	github.com/carlosframework/platform/internal/hostops	2.353s
?   	github.com/carlosframework/platform/internal/hostops/fencerelease	[no test files]
ok  	github.com/carlosframework/platform/internal/hostops/internal/fencerelease	0.004s
ok  	github.com/carlosframework/platform/internal/hostquarantine	0.003s
ok  	github.com/carlosframework/platform/internal/hostrelocate	0.786s
ok  	github.com/carlosframework/platform/internal/hostresolve	0.235s
ok  	github.com/carlosframework/platform/internal/hostwrite	0.002s
ok  	github.com/carlosframework/platform/internal/infraview	0.004s
ok  	github.com/carlosframework/platform/internal/instancectl	5.240s
ok  	github.com/carlosframework/platform/internal/instanceexec	2.881s
ok  	github.com/carlosframework/platform/internal/instancefs	0.007s
ok  	github.com/carlosframework/platform/internal/instancekey	0.006s
ok  	github.com/carlosframework/platform/internal/instanceupdates	0.017s
ok  	github.com/carlosframework/platform/internal/layout	1.997s
ok  	github.com/carlosframework/platform/internal/lbhealth	0.005s
ok  	github.com/carlosframework/platform/internal/lease	10.088s
ok  	github.com/carlosframework/platform/internal/lease/leasetest	0.589s
ok  	github.com/carlosframework/platform/internal/ledger	0.022s
ok  	github.com/carlosframework/platform/internal/mail	0.256s
ok  	github.com/carlosframework/platform/internal/maintenance	0.105s
ok  	github.com/carlosframework/platform/internal/maintenanceexec	5.665s
ok  	github.com/carlosframework/platform/internal/maintenanceguard	0.082s
ok  	github.com/carlosframework/platform/internal/metrics	0.007s
ok  	github.com/carlosframework/platform/internal/moves	21.707s
ok  	github.com/carlosframework/platform/internal/moves/archive	1.255s
ok  	github.com/carlosframework/platform/internal/objstore	0.333s
ok  	github.com/carlosframework/platform/internal/ops	0.289s
ok  	github.com/carlosframework/platform/internal/park	0.361s
ok  	github.com/carlosframework/platform/internal/plans	0.008s
ok  	github.com/carlosframework/platform/internal/privatefile	0.004s
2026/10/24 22:09:00 provision: listing apps/bab/blog/instances/: list refused — its records are unseen this pass
2026/10/24 22:09:00 provision: listing apps/bab/: listdirs refused — its records are unseen this pass
2026/10/24 22:09:00 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:00 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:00 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:00 provision: listing apps/bac/tito/instances/: list refused — its records are unseen this pass
2026/10/24 22:09:00 provision: listing apps/bac/tito/instances/: list refused — its records are unseen this pass
2026/10/24 22:09:00 provision: skipping record apps/bac/tito/instances/one.example.com.json: unreadable: read refused
2026/10/24 22:09:00 provision: listing apps/bac/tito/instances/: list refused — its records are unseen this pass
2026/10/24 22:09:00 provision: an app's records could not be listed: they are skipped
2026/10/24 22:09:00 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 22:09:00 provision: remove retired instance route shop.example: provision: claim admission unavailable
2026/10/24 22:09:00 provision: remove retired instance route shop.example: provision: claim admission unavailable
2026/10/24 22:09:00 provision: remove retired sidecar route worker.sidecar.internal: provision: claim admission unavailable
2026/10/24 22:09:00 provision: remove retired sidecar route worker.sidecar.internal: provision: claim admission unavailable
2026/10/24 22:09:00 provision: claim install acme.go.tito.io: provision: claim admission unavailable
2026/10/24 22:09:00 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:00 provision: claim install acme.go.tito.io: registry: claim row ownership changed or unknown
2026/10/24 22:09:00 provision: claim install bot.eleven.bac.sidecar.internal: provision: claim admission unavailable
2026/10/24 22:09:00 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 22:09:00 provision: claim install bot.eleven.bac.sidecar.internal: registry: claim row ownership changed or unknown
2026/10/24 22:09:00 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 22:09:00 provision: acme.go.tito.io: not minting this pass: the box's layout intent could not be read: no sealed config
2026/10/24 22:09:00 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:00 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:00 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 22:09:00 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 22:09:00 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 22:09:00 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 22:09:00 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:00 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 22:09:00 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 22:09:00 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 22:09:00 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:00 provision: claim install acme.go.tito.io: registry: claim row ownership changed or unknown
2026/10/24 22:09:00 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:00 provision: claim install acme.go.tito.io: registry: claim row ownership changed or unknown
2026/10/24 22:09:00 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 22:09:00 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 22:09:00 provision: claim install bot.eleven.bac.sidecar.internal: registry: claim row ownership changed or unknown
2026/10/24 22:09:00 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 22:09:00 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:00 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 22:09:00 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 22:09:00 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:00 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:00 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 22:09:01 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:01 provision: skipping record apps/bac/tito/instances/new.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:01 provision: not removing acme.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 22:09:01 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:01 provision: skipping record apps/bac/tito/instances/new.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:01 provision: minted instance route re.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route rf.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route rh.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route rb.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route rc.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route rd.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route rg.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route ri.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route rj.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route rk.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route rl.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route ra.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route rb.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route rc.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route rd.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route ra.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: skipping record apps/bac/tito/instances/rb.go.tito.io.json: read failed: read refused
2026/10/24 22:09:01 provision: skipping record apps/bac/tito/instances/rb.go.tito.io.json: read failed: read refused
2026/10/24 22:09:01 provision: minted instance route re.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route x.appa.example (app "appa" acct "bac")
2026/10/24 22:09:01 provision: minted instance route x.appb.example (app "appb" acct "bac")
2026/10/24 22:09:01 provision: minted instance route x.apph.example (app "apph" acct "bac")
2026/10/24 22:09:01 provision: minted instance route x.appc.example (app "appc" acct "bac")
2026/10/24 22:09:01 provision: minted instance route x.appd.example (app "appd" acct "bac")
2026/10/24 22:09:01 provision: minted instance route x.appe.example (app "appe" acct "bac")
2026/10/24 22:09:01 provision: minted instance route x.appf.example (app "appf" acct "bac")
2026/10/24 22:09:01 provision: minted instance route x.appg.example (app "appg" acct "bac")
2026/10/24 22:09:01 provision: minted instance route x.appi.example (app "appi" acct "bac")
2026/10/24 22:09:01 provision: minted instance route x.appj.example (app "appj" acct "bac")
2026/10/24 22:09:01 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 22:09:01 provision: minted instance route r0027.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0100.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0101.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0118.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0126.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0020.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0072.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0087.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0109.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0111.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0026.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0069.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0094.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0018.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0081.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0099.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0106.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0000.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0124.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0129.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0002.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0029.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0038.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0039.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0052.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0059.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0070.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0112.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0023.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0007.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0010.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0024.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0048.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0063.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0116.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0117.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0120.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0050.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0091.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0128.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0022.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0041.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0016.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0042.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0060.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0085.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0005.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0034.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0044.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0068.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0095.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0045.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0049.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0119.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0035.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0009.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0051.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0074.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0098.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0105.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0013.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0017.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0043.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0055.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0061.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0064.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0073.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0076.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0080.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0031.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0110.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0114.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0004.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0083.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0088.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0011.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0012.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0103.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0108.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0089.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0125.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0036.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0090.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0102.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0104.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0062.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0113.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0047.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0058.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0066.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0053.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0067.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0092.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0093.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0096.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0001.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0006.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0019.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0033.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0079.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0097.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0030.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0054.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0077.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0107.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0121.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0015.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0021.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0028.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0037.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0071.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0115.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0122.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0003.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0040.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0056.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0075.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0025.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0046.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0123.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0127.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0008.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0032.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0057.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0065.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0078.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0082.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0084.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0086.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:01 provision: minted instance route r0014.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 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 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: minted instance route console.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: minted service route ha.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: minted service route svc.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: minted instance route whole.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: minted instance route shared.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: converged acme.go.tito.io channel stable -> edge
2026/10/24 22:09:03 provision: converged acme.go.tito.io channel edge -> canary/rehearsal
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: empty channel
2026/10/24 22:09:03 provision: not removing acme.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: converged acme.go.tito.io environment "" -> "staging"
2026/10/24 22:09:03 provision: converged acme.go.tito.io environment "staging" -> ""
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: converged acme.go.tito.io steering "" -> "latency"
2026/10/24 22:09:03 provision: converged acme.go.tito.io steering "latency" -> ""
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: converged acme.go.tito.io hibernate false -> true
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: converged acme.go.tito.io hibernate true -> false (replication "daily" cleared: only a hibernating route's rung is read)
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: converged acme.go.tito.io status-named false -> true
2026/10/24 22:09:03 provision: converged acme.go.tito.io status-named true -> false
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: minted service route ha.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 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 22:09:03 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 22:09:03 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 22:09:03 provision: minted service route whole.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 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 22:09:03 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 22:09:03 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 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: minted service route whole.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: skipping accounts/bac/account.json: malformed account manifest: invalid character 'o' in literal null (expecting 'u')
2026/10/24 22:09:03 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: manifest bac/tito: read failed: provision: manifest bac/tito: invalid character 'o' in literal null (expecting 'u')
2026/10/24 22:09:03 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 22:09:03 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 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 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 22:09:03 provision: not removing acme$evil.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 22:09:03 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 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 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 22:09:03 provision: not removing bad-service.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 22:09:03 provision: skipping record apps/bac/tito/instances/no-channel.go.tito.io.json: empty channel
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: skipping record apps/bac/tito/instances/no-channel.go.tito.io.json: empty channel
2026/10/24 22:09:03 provision: not removing no-channel.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:03 provision: not removing acme.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 22:09:03 provision: removed retired instance route ghost.go.tito.io (record gone)
2026/10/24 22:09:03 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 22:09:03 provision: minted instance route dup.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 22:09:03 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 22:09:03 provision: removed retired instance route acme.go.tito.io (app in the trash)
2026/10/24 22:09:03 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:03 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 22:09:03 provision: removed retired static route site.go.tito.io (app in the trash)
2026/10/24 22:09:03 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 22:09:03 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 22:09:03 provision: removed retired instance route acme.go.tito.io (app in the trash)
2026/10/24 22:09:03 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 22:09:03 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 22:09:03 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 22:09:03 provision: converged acme.go.tito.io channel stable -> edge
2026/10/24 22:09:03 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 22:09:03 provision: converged acme.go.tito.io channel canary/rehearsal -> edge
2026/10/24 22:09:03 provision: converged acme.go.tito.io environment "staging" -> ""
2026/10/24 22:09:03 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 22:09:03 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 22:09:03 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 22:09:03 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 22:09:03 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 22:09:03 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 22:09:03 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 22:09:03 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 22:09:03 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 22:09:04 provision: dry-run: would mint instance route acme.go.tito.io (app "tito" acct "bac" channel "stable")
2026/10/24 22:09:04 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 22:09:04 provision: dry-run: would converge adopt.go.tito.io channel stable -> edge
2026/10/24 22:09:04 provision: dry-run: would converge adopt.go.tito.io environment "" -> "staging"
2026/10/24 22:09:04 provision: dry-run: would converge owned.go.tito.io channel stable -> edge
2026/10/24 22:09:04 provision: dry-run: would converge owned.go.tito.io environment "" -> "staging"
2026/10/24 22:09:04 provision: dry-run: would converge owned.go.tito.io hibernate false -> true
2026/10/24 22:09:04 provision: dry-run: would converge owned.go.tito.io seed
2026/10/24 22:09:04 provision: dry-run: would remove retired instance route gone.go.tito.io (record gone)
2026/10/24 22:09:04 provision: adopted existing route adopt.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 22:09:04 provision: converged adopt.go.tito.io channel stable -> edge
2026/10/24 22:09:04 provision: converged adopt.go.tito.io environment "" -> "staging"
2026/10/24 22:09:04 provision: converged owned.go.tito.io channel stable -> edge
2026/10/24 22:09:04 provision: converged owned.go.tito.io environment "" -> "staging"
2026/10/24 22:09:04 provision: converged owned.go.tito.io hibernate false -> true
2026/10/24 22:09:04 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: removed retired instance route gone.go.tito.io (record gone)
2026/10/24 22:09:04 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: adopted existing route story.carlosframework.com (app "story" acct "bad") — this record now owns its channel and environment
2026/10/24 22:09:04 provision: story.carlosframework.com exists but is not the route this record describes (kind "instance"/"static") — leaving it alone
2026/10/24 22:09:04 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted service route pub.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted service route pubs.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted service route named.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted service route priv.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted instance route unit.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted instance route exec.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted service route loop.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted static route pisite.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: removed retired static route site.go.tito.io (record gone)
2026/10/24 22:09:04 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted instance route acme-uk.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: converged acme.go.tito.io replicas "ie,uk" -> "uk"
2026/10/24 22:09:04 provision: converged acme.go.tito.io replicas "uk" -> ""
2026/10/24 22:09:04 provision: minted instance route acme-uk.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: converged acme-uk.go.tito.io replica mark true -> false
2026/10/24 22:09:04 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 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 22:09:04 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:04 provision: acme.go.tito.io: not minting this pass: the box's layout intent could not be read: store down
2026/10/24 22:09:04 provision: router.go.tito.io: not minting this pass: the box's layout intent could not be read: store down
2026/10/24 22:09:04 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 22:09:04 provision: converged acme.go.tito.io channel stable -> edge
2026/10/24 22:09:04 provision: minted instance route acme.go.tito.io held landing by mv_acme (app "tito" acct "bac")
2026/10/24 22:09:04 provision: not removing acme.go.tito.io (record gone): participant of a running operation
2026/10/24 22:09:04 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 22:09:04 provision: minted instance route acme.go.tito.io held landing by mv_acme (app "tito" acct "bac")
2026/10/24 22:09:04 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 22:09:04 provision: held acme.go.tito.io landing by mv_acme (was ready)
2026/10/24 22:09:04 provision: acme.go.tito.io: held restoring by rb_other, not by mv_acme; leaving it
2026/10/24 22:09:04 provision: acme.go.tito.io: the row is not this pass's (app "other" acct ""); not holding it for mv_acme
2026/10/24 22:09:04 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 22:09:04 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 22:09:04 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 22:09:04 provision: held acme.go.tito.io landing by mv_acme (was ready)
2026/10/24 22:09:04 provision: minted instance route acme.example.com (app "shop" acct "bac")
2026/10/24 22:09:04 provision: minted instance route plain.example.com (app "shop" acct "bac")
2026/10/24 22:09:04 provision: skipping record apps/bac/shop/instances/garbled.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:04 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 22:09:04 provision: skipping record apps/bac/shop/instances/garbled.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:04 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 22:09:04 provision: skipping record apps/bac/shop/instances/garbled.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:04 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 22:09:04 provision: skipping record apps/bac/shop/instances/garbled.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:04 provision: listing apps/bac/shop/instances/: list refused — its records are unseen this pass
2026/10/24 22:09:05 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:05 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:05 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 22:09:05 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:05 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 22:09:05 provision: minted sidecar route bot.shop.bac.sidecar.internal (app "shop" acct "bac" args ["run"])
2026/10/24 22:09:05 provision: removed retired sidecar route bot.shop.bac.sidecar.internal (record gone)
2026/10/24 22:09:05 provision: minted sidecar route bot.shop.bum.sidecar.internal (app "shop" acct "bum" args ["run"])
2026/10/24 22:09:05 provision: minted sidecar route bot.shop.bum.sidecar.internal (app "shop" acct "bum" args ["run"])
2026/10/24 22:09:05 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 22:09:05 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 22:09:05 provision: removed retired sidecar route bot.shop.bum.sidecar.internal (record gone)
2026/10/24 22:09:05 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 22:09:05 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 22:09:05 provision: removed retired sidecar route bot.shop.bum.sidecar.internal (record gone)
2026/10/24 22:09:05 provision: a.shop.example.com: swapped for import sd_hmq74kxhsbo4jzuythjhc7mgqq (the original route is journaled)
2026/10/24 22:09:05 provision: a.shop.example.com: import sd_hmq74kxhsbo4jzuythjhc7mgqq committed: its gate is cleared and its journal row dropped
2026/10/24 22:09:05 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 22:09:06 provision: a.shop.example.com: import sd_dcjtdngzhpm6wxfibdmgsfwpua rolled back to its original route
2026/10/24 22:09:06 provision: a.shop.example.com: import sd_dcjtdngzhpm6wxfibdmgsfwpua: the host's replica is left alone: the record apps/bac/shop/instances/a.shop.example.com.json holds the host
2026/10/24 22:09:06 provision: a.shop.example.com: import sd_dcjtdngzhpm6wxfibdmgsfwpua is cleaned up and its journal row retired
2026/10/24 22:09:06 provision: a.shop.example.com: import sd_mtwaih3a67pqfjd2hyrpx7zjiq rolled back to its original route
2026/10/24 22:09:06 provision: a.shop.example.com: import sd_mtwaih3a67pqfjd2hyrpx7zjiq: the host's replica is left alone: the record apps/bac/shop/instances/a.shop.example.com.json holds the host
2026/10/24 22:09:06 provision: a.shop.example.com: import sd_mtwaih3a67pqfjd2hyrpx7zjiq is cleaned up and its journal row retired
2026/10/24 22:09:06 provision: dry-run: would redo a.shop.example.com's swap record CAS for import sd_f6eevw6wsjzdkhzzmc4jtysyya
2026/10/24 22:09:06 provision: dry-run: would clear a.shop.example.com's import gate
2026/10/24 22:09:06 provision: dry-run: would converge a.shop.example.com seed source
2026/10/24 22:09:06 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 22:09:06 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 22:09:06 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 22:09:06 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 22:09:06 provision: a.shop.example.com: import sd_sofpaxp4wz3k3pyll4kiqky3x4 cannot roll back on this box: the activator is not wired; it stays journaled and gated
2026/10/24 22:09:06 provision: a.shop.example.com: import sd_mpoius5vfxbuwce2f5kr5vw3ma cannot roll back on this box: the activator is not wired; it stays journaled and gated
2026/10/24 22:09:06 provision: a.shop.example.com: import sd_igzwhfsfs27jreadomukrmld2a is journaled, but this box cannot act on imports; its row is left alone
2026/10/24 22:09:06 provision: a.shop.example.com: import sd_i6hjouqwvtlpj7fbqgerpflzla is journaled, but this box cannot act on imports; its row is left alone
2026/10/24 22:09:06 provision: a.shop.example.com: import sd_dohq7pnqncyoeiat7zdgo7nxhm is journaled, but this box cannot act on imports; its row is left alone
2026/10/24 22:09:06 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 22:09:06 provision: b.shop.example.com: import sd_hwu3ccfhvz2f3veh5vycorqvua left alone this pass: the import journal could not be read
2026/10/24 22:09:06 provision: c.shop.example.com: import sd_dx4bviklui43hq3rtoqgde7xaq left alone this pass: the import journal could not be read
2026/10/24 22:09:06 provision: a.shop.example.com: import sd_z4ulied3jhtszftun2smrg7pvi committed: its gate is cleared and its journal row dropped
2026/10/24 22:09:06 provision: a.shop.example.com: not converging import sd_dkimyjku2lood4n4lgsp226hqq: it is swapped but not committed, and the row on this box has no import gate
2026/10/24 22:09:06 provision: a.shop.example.com: not converging import sd_2lcchtw2y2rce3ysghnb56kr4m: it is swapped but not committed, and the row on this box has no import gate
2026/10/24 22:09:06 provision: a.shop.example.com: not converging import sd_yoi5vcvnt2hisnmxsdnsehfwuy: it is placed but not committed, and the row on this box has no import gate
2026/10/24 22:09:06 provision: a.shop.example.com: not converging import sd_cg7xk6vdl6xlpdou5el26h3esm: it is placed but not committed, and the row on this box has no import gate
2026/10/24 22:09:06 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 22:09:06 provision: converge seed source on a.shop.example.com: constraint failed: seed_source is read-only here (1811)
2026/10/24 22:09:06 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 22:09:06 provision: a.shop.example.com: import sd_xwjj3qf3fnc4xpzt3atiso62pq committed: its gate is cleared and its journal row dropped
2026/10/24 22:09:06 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 22:09:06 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:06 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 22:09:06 provision: acme.go.tito.io: not minting a seeded instance: this box does not mint nested (<nil>)
2026/10/24 22:09:06 provision: acme.go.tito.io: not minting a seeded instance: claim control is on for this box
2026/10/24 22:09:06 provision: acme.go.tito.io: aborted seed sd_5achozk7ua6gsp3fm5vnwyseqq: this box cannot read seed markers, and places no seed; nothing local is removed
2026/10/24 22:09:06 provision: acme.go.tito.io: aborted seed sd_5achozk7ua6gsp3fm5vnwyseqq rolled back (no box had swapped it)
2026/10/24 22:09:06 provision: acme.go.tito.io: not minting a seeded instance: its record does not describe a hibernating instance
2026/10/24 22:09:06 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:06 provision: removed instance route acme.go.tito.io (its seed sd_fpl4mgkdwntfcrnagkrjzczoxi was aborted); the next pass rolls it back
2026/10/24 22:09:06 provision: acme.go.tito.io: aborted seed sd_fpl4mgkdwntfcrnagkrjzczoxi: this box cannot read seed markers, and places no seed; nothing local is removed
2026/10/24 22:09:06 provision: acme.go.tito.io: aborted seed sd_fpl4mgkdwntfcrnagkrjzczoxi rolled back (no box had swapped it)
2026/10/24 22:09:06 provision: acme.go.tito.io: aborted seed sd_jjwqfec5ubrcgz5pzvh7ycr7uq has a row this pass may not remove; leaving the seed aborted
2026/10/24 22:09:06 provision: acme.go.tito.io: aborted seed sd_inwrwnrkcbbuu3t3gm6khq3ub4 rolled back (no box had swapped it)
2026/10/24 22:09:06 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:06 provision: removed instance route acme.go.tito.io (its seed sd_bgvelipvqygmtsdvuahqmjwwcu was aborted); the next pass rolls it back
2026/10/24 22:09:06 provision: acme.go.tito.io: aborted seed sd_bgvelipvqygmtsdvuahqmjwwcu has no route on this box: its local data is removed
2026/10/24 22:09:06 provision: acme.go.tito.io: aborted seed sd_bgvelipvqygmtsdvuahqmjwwcu rolled back (no box had swapped it)
2026/10/24 22:09:06 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:06 provision: a.shop.example.com: swapped for import sd_jvx32m6vqefp4iuzzoxipg7z3u (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_jvx32m6vqefp4iuzzoxipg7z3u rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_jvx32m6vqefp4iuzzoxipg7z3u is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_qdvwbdqcdr5tl2rra4x7d2tnce (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_qdvwbdqcdr5tl2rra4x7d2tnce rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_qdvwbdqcdr5tl2rra4x7d2tnce is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_qiygs7say6pwrnsklomahf2m3a (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_qiygs7say6pwrnsklomahf2m3a rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_qiygs7say6pwrnsklomahf2m3a: the host's replica is left alone: its record no longer names this seed
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_qiygs7say6pwrnsklomahf2m3a is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_slrzzcjz7wgwt5mq43vxmexc6a (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_slrzzcjz7wgwt5mq43vxmexc6a rollback deferred: the host is not fenced and stopped yet (<nil>)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_slrzzcjz7wgwt5mq43vxmexc6a rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_slrzzcjz7wgwt5mq43vxmexc6a is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_kce6iefhkvuewxykfpbv4r5hq4 (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_kce6iefhkvuewxykfpbv4r5hq4 rollback deferred: the host is not fenced and stopped yet (stop unproven)
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_c74vdepz3qwitzbmlec4zqolcy (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_c74vdepz3qwitzbmlec4zqolcy is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_fog56j3uvuowhstvbqo3yyiwnq (the original route is journaled)
2026/10/24 22:09:07 provision: skipping record apps/bac/shop/instances/a.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_fog56j3uvuowhstvbqo3yyiwnq left alone this pass: its record could not be read
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_5sq42s6hg75daledyfv3afkfqm (the original route is journaled)
2026/10/24 22:09:07 provision: skipping record apps/bac/shop/instances/a.shop.example.com.json: read failed: connection reset
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_5sq42s6hg75daledyfv3afkfqm left alone this pass: its record could not be read
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_sjwwloar55so5uxv56fpkbeq4u (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_sjwwloar55so5uxv56fpkbeq4u: close the import gate: constraint failed: injected (1811)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_sjwwloar55so5uxv56fpkbeq4u rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_sjwwloar55so5uxv56fpkbeq4u is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_angmzsz6zlgf7teb3yjjxtyelm (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_angmzsz6zlgf7teb3yjjxtyelm: close the import gate: constraint failed: injected (1811)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_angmzsz6zlgf7teb3yjjxtyelm rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_angmzsz6zlgf7teb3yjjxtyelm is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_hb6vzmfijxwie276ikvaficxhi (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_hb6vzmfijxwie276ikvaficxhi rollback deferred: the host is not fenced and stopped yet (injected failure at fence)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_hb6vzmfijxwie276ikvaficxhi rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_hb6vzmfijxwie276ikvaficxhi is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_zeiddia64hnv5hydmfkpkcu2kq (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_zeiddia64hnv5hydmfkpkcu2kq rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_zeiddia64hnv5hydmfkpkcu2kq is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_m6siq6z4tatjhwvbwedgyh2rlq (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_m6siq6z4tatjhwvbwedgyh2rlq: retire its instance key: injected failure at retire-key
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_m6siq6z4tatjhwvbwedgyh2rlq rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_m6siq6z4tatjhwvbwedgyh2rlq is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_fnchx7vinrprfgnljf7e46jn7y (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_fnchx7vinrprfgnljf7e46jn7y rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_fnchx7vinrprfgnljf7e46jn7y is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_q3pgonyi3f7huj4dh2c2wbcdie (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_q3pgonyi3f7huj4dh2c2wbcdie: remove its local data: injected failure at remove-local
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_q3pgonyi3f7huj4dh2c2wbcdie rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_q3pgonyi3f7huj4dh2c2wbcdie is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_koq5dyikdy5zkm7qx6ed4ic4ta (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_koq5dyikdy5zkm7qx6ed4ic4ta rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_koq5dyikdy5zkm7qx6ed4ic4ta is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_s7ieko2xg6uthrxwxvu7r7czsu (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_s7ieko2xg6uthrxwxvu7r7czsu: remove its local data: injected failure at remove-local-done
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_s7ieko2xg6uthrxwxvu7r7czsu rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_s7ieko2xg6uthrxwxvu7r7czsu is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_n2a5tjdjjmx3hxkx2twjopddpy (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_n2a5tjdjjmx3hxkx2twjopddpy rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_n2a5tjdjjmx3hxkx2twjopddpy is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_z6zurukaaooklkh6tejdkxhwka (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_z6zurukaaooklkh6tejdkxhwka: restore the original route: constraint failed: injected (1811)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_z6zurukaaooklkh6tejdkxhwka rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_z6zurukaaooklkh6tejdkxhwka is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_r4zjphf63gkaqs4va6q7d6iybi (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_r4zjphf63gkaqs4va6q7d6iybi: restore the original route: constraint failed: injected (1811)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_r4zjphf63gkaqs4va6q7d6iybi rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_r4zjphf63gkaqs4va6q7d6iybi is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_r2ar5i2fmls5rxfpjk3vhnnepy (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_r2ar5i2fmls5rxfpjk3vhnnepy is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_zyqwuj5fmjyja6vyrp5hy6nvuq (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_zyqwuj5fmjyja6vyrp5hy6nvuq rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_zyqwuj5fmjyja6vyrp5hy6nvuq: delete its snapshot: injected failure at delete-snapshot
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_zyqwuj5fmjyja6vyrp5hy6nvuq is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_lqnyun3qmybyref6ft3yo4xlfe (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_lqnyun3qmybyref6ft3yo4xlfe rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_lqnyun3qmybyref6ft3yo4xlfe is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_7xwyk4itikz6wa3a3ztb46p7iu (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_7xwyk4itikz6wa3a3ztb46p7iu rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_7xwyk4itikz6wa3a3ztb46p7iu: delete the host's replica: injected failure at delete-replica
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_7xwyk4itikz6wa3a3ztb46p7iu is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_wyzn5c2mshkmiboo5v6abwuj7u (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_wyzn5c2mshkmiboo5v6abwuj7u rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_wyzn5c2mshkmiboo5v6abwuj7u is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_ljpg4ta6dav7ippi4phx34q3ye (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_ljpg4ta6dav7ippi4phx34q3ye rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_ljpg4ta6dav7ippi4phx34q3ye: retire its journal row: constraint failed: injected (1811)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_ljpg4ta6dav7ippi4phx34q3ye is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_alln2mpy7y3znqu3tmwgsjlzg4 (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_alln2mpy7y3znqu3tmwgsjlzg4 rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_alln2mpy7y3znqu3tmwgsjlzg4: retire its journal row: constraint failed: injected (1811)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_alln2mpy7y3znqu3tmwgsjlzg4 is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_46gwdsb5x7eczqaxewvw7qn2uq (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_46gwdsb5x7eczqaxewvw7qn2uq rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_46gwdsb5x7eczqaxewvw7qn2uq is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: mark import sd_46gwdsb5x7eczqaxewvw7qn2uq rolled back: injected failure at cas
2026/10/24 22:09:07 provision: a.shop.example.com: aborted seed sd_46gwdsb5x7eczqaxewvw7qn2uq rolled back (no box had swapped it)
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_x6d6cjw4dj22rz52umtl2ecrla (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_x6d6cjw4dj22rz52umtl2ecrla rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_x6d6cjw4dj22rz52umtl2ecrla is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: aborted seed sd_x6d6cjw4dj22rz52umtl2ecrla rolled back (no box had swapped it)
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_ilqud2nqqly32iqagkiguwe2qm (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_ilqud2nqqly32iqagkiguwe2qm rollback deferred: the host is not fenced and stopped yet (<nil>)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_ilqud2nqqly32iqagkiguwe2qm rollback deferred: the host is not fenced and stopped yet (<nil>)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_ilqud2nqqly32iqagkiguwe2qm rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_ilqud2nqqly32iqagkiguwe2qm is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_do5zdbrokunsmshnj3fbbg2ewe (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_do5zdbrokunsmshnj3fbbg2ewe rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_do5zdbrokunsmshnj3fbbg2ewe is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_3ly7dj74e5uaygv57p6ropffuu (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_3ly7dj74e5uaygv57p6ropffuu rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_3ly7dj74e5uaygv57p6ropffuu is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_mb7bscmazdxdillblgjdndx4xu (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_mb7bscmazdxdillblgjdndx4xu rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_mb7bscmazdxdillblgjdndx4xu is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_ehe2wck6v6dbey2bx5ldnczrte (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_ehe2wck6v6dbey2bx5ldnczrte rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_ehe2wck6v6dbey2bx5ldnczrte is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_ink3hp24klcjzubrjyg4kqhqsm (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_ink3hp24klcjzubrjyg4kqhqsm rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_ink3hp24klcjzubrjyg4kqhqsm is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: minted instance route a.shop.example.com (app "other" acct "bac")
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_4dap53bpn2slnyysdwjsym2kaq (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_4dap53bpn2slnyysdwjsym2kaq rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_4dap53bpn2slnyysdwjsym2kaq is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: minted instance route a.shop.example.com (app "other" acct "bac")
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_w7z7hyc4gfafwgb6ok7465id4y (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_w7z7hyc4gfafwgb6ok7465id4y rolled back to its original route
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_w7z7hyc4gfafwgb6ok7465id4y is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: minted instance route a.shop.example.com (app "other" acct "bac")
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_g5cwju7k2xoymgq25laj6mfmye (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_g5cwju7k2xoymgq25laj6mfmye has no route on this box: its local data is removed and no route is put back
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_g5cwju7k2xoymgq25laj6mfmye is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_33sukwpqkgtlu3fyv753nnjs3a (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_sldq3w5ul7zm7v6iuzzwzh5lom (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_xqgelvxtrsobxl6r6vz3rmhcn4 (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_xqgelvxtrsobxl6r6vz3rmhcn4 cannot roll back on this box: the activator is not wired; it stays journaled and gated
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_u63ddilpo3oer5waw7blc3zcsm (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_u63ddilpo3oer5waw7blc3zcsm is not rolled back: the route changed under the fence, so nothing there is touched
2026/10/24 22:09:07 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 22:09:07 provision: a.shop.example.com: import ../not-a-seed is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_uc2lzhswpuco556hqzousmaxkm (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_wipaqg5o2vx3brboktbpq7zznu (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_ydsyxxtcb5plvf6ru67753pvue (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_uubfhmlfpdah5b6ztkrq73eftq (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_uonrzps4ijqufls2pnjdwvf5eq (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_uonrzps4ijqufls2pnjdwvf5eq rollback deferred: the host is not fenced and stopped yet (stop evidence unreadable)
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_uclxksrcbbkc3twtcrqlgbchwq (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_uclxksrcbbkc3twtcrqlgbchwq has no route on this box: its local data is removed and no route is put back
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_uclxksrcbbkc3twtcrqlgbchwq is cleaned up and its journal row retired
2026/10/24 22:09:07 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_s4dtho54finm3t3zi6qoszjq6y (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_s4dtho54finm3t3zi6qoszjq6y: remove its local data: injected failure at remove-local
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_s4dtho54finm3t3zi6qoszjq6y is not rolled back: the route at the host is not the import's, so nothing there is touched
2026/10/24 22:09:07 provision: a.shop.example.com: swapped for import sd_ec67tllnhtmglfgfn3jhzcnffi (the original route is journaled)
2026/10/24 22:09:07 provision: a.shop.example.com: import sd_ec67tllnhtmglfgfn3jhzcnffi: a route appeared at the host, so its local database is left and the rollback waits
2026/10/24 22:09:08 provision: a.shop.example.com: swapped for import sd_gftrv3h6dn236awqxx3ks4bhqm (the original route is journaled)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_gftrv3h6dn236awqxx3ks4bhqm rollback deferred: no fence generation: registry busy
2026/10/24 22:09:08 provision: a.shop.example.com: swapped for import sd_ttt3esv54ocrscfjev5tsfzvgy (the original route is journaled)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_ttt3esv54ocrscfjev5tsfzvgy rollback deferred: no fence generation: the generation source answered 0
2026/10/24 22:09:08 provision: a.shop.example.com: swapped for import sd_ky2fdu6zqfaqrfksd5r6be7y2m (the original route is journaled)
2026/10/24 22:09:08 provision: a.shop.example.com: swapped for import sd_dkbf6stk2mqv5gc5nqw65uvpxe (the original route is journaled)
2026/10/24 22:09:08 provision: a.shop.example.com: swapped for import sd_m2i4ttcodrcajtqkgsd3xz6k3m (the original route is journaled)
2026/10/24 22:09:08 provision: a.shop.example.com: import deferred: the instance's env file could not be read: a symlink
2026/10/24 22:09:08 provision: a.shop.example.com: import deferred: this box cannot read the instance's env file
2026/10/24 22:09:08 provision: a.shop.example.com: swapped for import sd_xsg4wu5awy5pngo2roov4i6d74 (the original route is journaled)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_xsg4wu5awy5pngo2roov4i6d74 rolled back to its original route
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_xsg4wu5awy5pngo2roov4i6d74 is cleaned up and its journal row retired
2026/10/24 22:09:08 provision: a.shop.example.com: swapped for import sd_wlexccetbyoarark5tzc4bznxq (the original route is journaled)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_wlexccetbyoarark5tzc4bznxq rolled back to its original route
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_wlexccetbyoarark5tzc4bznxq is cleaned up and its journal row retired
2026/10/24 22:09:08 provision: a.shop.example.com: swapped for import sd_lsoi6ojbtfr5zbsymtotxhnhkm (the original route is journaled)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_lsoi6ojbtfr5zbsymtotxhnhkm rolled back to its original route
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_lsoi6ojbtfr5zbsymtotxhnhkm is cleaned up and its journal row retired
2026/10/24 22:09:08 provision: a.shop.example.com: swapped for import sd_epqdscpi6beofwvj5mj2ezhkim (the original route is journaled)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_epqdscpi6beofwvj5mj2ezhkim: retire its instance key: the env file is a symlink
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_epqdscpi6beofwvj5mj2ezhkim rolled back to its original route
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_epqdscpi6beofwvj5mj2ezhkim is cleaned up and its journal row retired
2026/10/24 22:09:08 provision: a.shop.example.com: swapped for import sd_wnl2h6yqcdqczbtjfq6gg5xrbq (the original route is journaled)
2026/10/24 22:09:08 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 22:09:08 provision: a.shop.example.com: swapped for import sd_we2pcod6ubdlun3bnktzoigphm (the original route is journaled)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_sayoo5tcpjk7ntph3sgvkhs2mq refused: there is no route at a.shop.example.com to replace
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_peuhjpacy6wn3cxhrgl4tksq5m refused: the route's address is 127.0.0.1:9, not 127.0.0.1:8401
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_tuhdrh2kwc6g3kbayrr5xq54m4 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 22:09:08 provision: a.shop.example.com: import sd_sa367ar7ucvluibcuvnve3lyyq refused: the route's address is 127.0.0.1:9, not 127.0.0.1:8401
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_a2ogvepikrrgrkxilof5y6iafm refused: the route belongs to app other
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_miuhbsd5yxn36wktqzjmo2df34 refused: the route is filed under another account
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_zgzvesbymqgk6yolqaqavdett4 refused: the route is filed under the operator account, and no assignment maps shop to this app
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_cin7umfay33lpetzavwlx35gnq refused: the route is filed under the operator account, and no assignment maps shop to this app
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_azipifxct2rf3yi3jxdzureriy refused: the route is filed under the operator account, and no assignment maps shop to this app
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_dj4klier3mub43plvjcu77efmq refused: the route is filed under the operator account, and no assignment maps shop to this app
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_zhpb5iwntsyawiyftgus3sh774 refused: the route is not an address route this import can take over (socket)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_nomaotxid5rg5qbsjyvcsvmo7e refused: the route is not an address route this import can take over (no address)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_mfrzigvu456naxsfa6uxkhuwni refused: the route is not an address route this import can take over (provisioned)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_mxovb5uc4ggr7f6ygtnlrbozru refused: the route is not an address route this import can take over (kind static)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_mb5l2gaqcwlbk45ucpnurxgj54 refused: the route is not an address route this import can take over (backing)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_b6wsg6omjx36imttn2fnzh4m3q refused: the route is not an address route this import can take over (tunnel)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_ocdu7cuzkj53e5nit2mfyu77hy refused: the route is not an address route this import can take over (caps)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_o2p53z2pme2opdirtzdqvcsv6a refused: the route is not an address route this import can take over (platform)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_72m7ftilbjuczfqzsd3xekm6cq refused: the route is not an address route this import can take over (canary)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_v2a3gro3yhjpbxytmsg6czoeue refused: the route is not an address route this import can take over (kind sidecar)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_4cbtfasqe5nvjfvawvvhyimavq refused: the route is not an address route this import can take over (region)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_5ffoegwevwudpnqyf4r3thipj4 refused: the route is not an address route this import can take over (fleet_box)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_3oe3jjwqqwd22eidkfoz7b7lem refused: the route is not an address route this import can take over (hibernate)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_dw7ebh5y5s2qq7cv54j2o4zl3u refused: the route is not an address route this import can take over (claim_owner)
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_kiqvcjkhk53wvirfpn7aoktuta refused: this box does not run instances nested
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_kjecvu4yekeucp7oruy2iufhgi refused: this box does not run instances nested
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_skbdzzxqdiqwkrt6bxexal4lri refused: claim control is on for this box
2026/10/24 22:09:08 provision: a.shop.example.com: swapped for import sd_hgclg4svfoe3b2rau7dt237vbe (the original route is journaled)
2026/10/24 22:09:08 provision: a.shop.example.com: swapped for import sd_m3jeephapm6taz35mu32qil2za (the original route is journaled)
2026/10/24 22:09:08 provision: a.shop.example.com: import deferred: this box cannot read the legacy route assignments
2026/10/24 22:09:08 provision: a.shop.example.com: import deferred: the legacy route assignments could not be read: store down
2026/10/24 22:09:08 provision: a.shop.example.com: not swapping for import sd_khw4juio5yzdshvo4qibt5ixfm: its verify hash is not a sha256
2026/10/24 22:09:08 provision: a.shop.example.com: not swapping for import sd_4jqmk6ylqd6ah7ojn4eiflmbz4: its verify hash is not a sha256
2026/10/24 22:09:08 provision: a.shop.example.com: not swapping for import sd_l33ehxkud7j2x4xyldsdjfadta: its verify hash is not a sha256
2026/10/24 22:09:08 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 22:09:08 provision: A.shop.example.com/..: not swapping for import sd_on5yywmatuenkqv4l5eawpjz3m: its host or seed id is malformed (seeds: not a host)
2026/10/24 22:09:08 provision: a.shop.example.com: not swapping for import sd_b7u7gwmnxrz44m5nyuikihyu2u: its record does not describe a nested, hibernating instance
2026/10/24 22:09:08 provision: a.shop.example.com: not swapping for import sd_gqgwhnp7supwieafwyvkl2btz4: its record does not describe a nested, hibernating instance
2026/10/24 22:09:08 provision: a.shop.example.com: not swapping for import sd_4sx5lfco5g5uawa6s2ii2hmpxu: its record does not describe a nested, hibernating instance
2026/10/24 22:09:08 provision: a.shop.example.com: not swapping for import sd_uu6rzjhiq5uoph356tben7zlu4: its record does not describe a nested, hibernating instance
2026/10/24 22:09:08 provision: a.shop.example.com: import deferred: the box's layout intent could not be read: store down
2026/10/24 22:09:08 provision: a.shop.example.com: swapped for import sd_gheszji5jnttoxpoktw6ciw62m (the original route is journaled)
2026/10/24 22:09:08 provision: a.shop.example.com: import deferred: the box's nested probe did not answer: ready probe timed out
2026/10/24 22:09:08 provision: a.shop.example.com: swapped for import sd_xodlhlu7vmoulxhbdwjfdjwm2u (the original route is journaled)
2026/10/24 22:09:08 provision: a.shop.example.com: swapped for import sd_mrhfkelshhskctlaromwhvhwse (the original route is journaled)
2026/10/24 22:09:08 provision: a.shop.example.com: import deferred: the route is held by operation op_1
2026/10/24 22:09:08 provision: dry-run: would consider swapping a.shop.example.com for import sd_nkpqs3ub4i735rk63at36ywscu
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_yjfhunhdpraj5lmw36bvqmqmjq rolled back to its original route
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_yjfhunhdpraj5lmw36bvqmqmjq: the host's replica is left alone: the record apps/bac/shop/instances/a.shop.example.com.json holds the host
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_yjfhunhdpraj5lmw36bvqmqmjq is cleaned up and its journal row retired
2026/10/24 22:09:08 provision: a.shop.example.com: import sd_w2pp5g2d4olrwh3bfutbqyq36m left alone: the import journal holds seed sd_2um7ns7bxnvw5zisww66v7ypli at swapped
2026/10/24 22:09:08 provision: a.shop.example.com: not minting import sd_jf6lps6ghhlb66rbpt54ela2lq: it is swapped but not committed, and only its swap makes its row
2026/10/24 22:09:08 provision: a.shop.example.com: not minting import sd_zvsfu53kcsdpz3ve57xd6cee2u: it is placed but not committed, and only its swap makes its row
2026/10/24 22:09:08 provision: a.shop.example.com: swapped for import sd_p32qhn2wnocq74thhkahjdxdkm (the original route is journaled)
2026/10/24 22:09:08 provision: a.shop.example.com: not minting import sd_p32qhn2wnocq74thhkahjdxdkm: it is swapped but not committed, and only its swap makes its row
2026/10/24 22:09:08 provision: a.shop.example.com: not minting import sd_p32qhn2wnocq74thhkahjdxdkm: it is placed but not committed, and only its swap makes its row
2026/10/24 22:09:08 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 22:09:09 provision: removed retired sidecar route gone.eleven.bac.sidecar.internal (record gone)
2026/10/24 22:09:09 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 22:09:09 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 22:09:09 provision: converged sidecar bot.eleven.bac.sidecar.internal args ["sidecar","run"] -> ["worker","run"]
2026/10/24 22:09:09 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 22:09:09 provision: converged sidecar bot.eleven.bac.sidecar.internal ceilings 300/3600 -> 60/120
2026/10/24 22:09:09 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 22:09:09 provision: converged sidecar bot.eleven.bac.sidecar.internal channel stable -> canary/eleven
2026/10/24 22:09:09 provision: converged sidecar bot.eleven.bac.sidecar.internal environment "other" -> "relay"
2026/10/24 22:09:09 provision: converged sidecar bot.eleven.bac.sidecar.internal hibernate true -> false
2026/10/24 22:09:09 provision: skipping sidecar record apps/bac/eleven/sidecars/bot.json: read failed: failStore: reads disabled under apps/bac/eleven/sidecars/
2026/10/24 22:09:09 provision: skipping sidecar record apps/bac/eleven/sidecars/bot.json: malformed: invalid character 'n' looking for beginning of object key string
2026/10/24 22:09:09 provision: not removing sidecar bot.eleven.bac.sidecar.internal: its record exists but could not be read cleanly this pass
2026/10/24 22:09:09 provision: skipping sidecar record apps/bac/eleven/sidecars/bot.json: empty channel
2026/10/24 22:09:09 provision: skipping sidecar record apps/bac/eleven/sidecars/held.json: empty channel
2026/10/24 22:09:09 provision: not removing sidecar held.eleven.bac.sidecar.internal: its record exists but could not be read cleanly this pass
2026/10/24 22:09:09 provision: removed retired sidecar route old.eleven.bac.sidecar.internal (record gone)
2026/10/24 22:09:09 provision: bac/eleven has sidecar records but no sidecars manifest — not minting
2026/10/24 22:09:09 provision: bac/eleven is in the trash — not minting sidecar routes for it
2026/10/24 22:09:09 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 22:09:09 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 22:09:09 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 22:09:09 provision: minted sidecar route hub.relay.bac.sidecar.internal (app "relay" acct "bac" args ["relay"])
2026/10/24 22:09:09 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 22:09:09 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 22:09:09 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 22:09:09 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 22:09:09 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 22:09:09 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 22:09:09 provision: removed retired sidecar route bot.eleven.bac.sidecar.internal (record gone)
2026/10/24 22:09:09 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 22:09:09 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 22:09:09 provision: skipping sidecar record apps/bac/relay/sidecars/hub.json: read failed: failStore: reads disabled under apps/bac/relay/sidecars/
2026/10/24 22:09:09 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 22:09:09 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 22:09:09 provision: dry-run: would mint sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" channel "stable" args ["sidecar","run"])
2026/10/24 22:09:09 provision: dry-run: would remove retired sidecar route gone.eleven.bac.sidecar.internal (record gone)
2026/10/24 22:09:09 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 22:09:09 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:09 provision: converged acme.go.tito.io update settings "{\"updates\":\"manual\",\"channel\":\"stable\"}" -> ""
2026/10/24 22:09:09 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:09 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:09 provision: manifest bac/tito: read failed: provision: manifest bac/tito: unexpected end of JSON input
2026/10/24 22:09:09 provision: manifest bac/tito: read failed: provision: manifest bac/tito: unexpected end of JSON input
2026/10/24 22:09:09 provision: acme.go.tito.io: not minted this pass: the app's update policy could not be read
2026/10/24 22:09:09 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 22:09:09 provision: manifest bac/tito: read failed: provision: manifest bac/tito: unexpected end of JSON input
2026/10/24 22:09:09 provision: acme.go.tito.io: not minted this pass: the app's update policy could not be read
2026/10/24 22:09:09 provision: minted instance route acme.go.tito.io held landing by mv_acme (app "tito" acct "bac")
2026/10/24 22:09:09 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 22:09:09 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 22:09:09 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 22:09:09 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 22:09:09 provision: record view: re-reading apps/bqc/shop failed: retrying on the next refresh
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 22:09:09 provision: listing apps/bqc/shop/instances/: context canceled — its records are unseen this pass
2026/10/24 22:09:09 provision: record view: change index unusable (release: change index malformed: invalid character 'n' looking for beginning of object key string): walking
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: record view: change index unusable (get refused): walking
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: record view: re-reading apps/bqc/shop failed: retrying on the next refresh
2026/10/24 22:09:09 provision: listing apps/bqc/shop/instances/: list refused — its records are unseen this pass
2026/10/24 22:09:09 provision: listing apps/bqc/shop/instances/: list refused — its records are unseen this pass
2026/10/24 22:09:09 provision: an app's records could not be listed: they are skipped
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping accounts/bqd/account.json: malformed account manifest: invalid character 'n' looking for beginning of object key string
2026/10/24 22:09:09 provision: skipping accounts/bqd/account.json: malformed account manifest: invalid character 'n' looking for beginning of object key string
2026/10/24 22:09:09 provision: skipping accounts/bqd/account.json: malformed account manifest: invalid character 'n' looking for beginning of object key string
2026/10/24 22:09:09 provision: record view: re-reading accounts/bqd failed: retrying on the next refresh
2026/10/24 22:09:09 provision: skipping accounts/bqd/account.json: read failed: list refused
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: minted instance route one.example.com (app "shop" acct "bum")
2026/10/24 22:09:09 provision: minted instance route one.example.com (app "shop" acct "bum")
2026/10/24 22:09:09 provision: skipping record apps/bum/shop/instances/one.example.com.json: empty channel
2026/10/24 22:09:09 provision: not removing one.example.com: its record exists but could not be read cleanly this pass
2026/10/24 22:09:09 provision: skipping record apps/bum/shop/instances/one.example.com.json: empty channel
2026/10/24 22:09:09 provision: removed retired instance route one.example.com (record gone)
2026/10/24 22:09:09 provision: not removing one.example.com: its record exists but could not be read cleanly this pass
2026/10/24 22:09:09 provision: minted instance route one.example.com (app "shop" acct "bum")
2026/10/24 22:09:09 provision: removed retired instance route one.example.com (record gone)
2026/10/24 22:09:09 provision: record view: change index unusable (context deadline exceeded): walking
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 22:09:09 provision: record view: change index unusable (context deadline exceeded): the walk records no generations
2026/10/24 22:09:09 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
--- FAIL: TestPlan14RootReadCensus (5.54s)
    plan14_root_reads_test.go:600: root read census: 40 discrepancies
        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/hostops
        changed root source envelope internal/release
        changed root source envelope internal/rootfsimage
        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/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
        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	14.942s
ok  	github.com/carlosframework/platform/internal/publicrelease	0.020s
?   	github.com/carlosframework/platform/internal/regionname	[no test files]
ok  	github.com/carlosframework/platform/internal/registry	5.829s
ok  	github.com/carlosframework/platform/internal/relay	7.187s
ok  	github.com/carlosframework/platform/internal/release	26.064s
ok  	github.com/carlosframework/platform/internal/rollout	3.938s
ok  	github.com/carlosframework/platform/internal/rolloutwords	0.007s
ok  	github.com/carlosframework/platform/internal/rootaws	0.012s
ok  	github.com/carlosframework/platform/internal/rootfsimage	0.373s
ok  	github.com/carlosframework/platform/internal/rootparticipation	0.065s
ok  	github.com/carlosframework/platform/internal/rootstate	0.033s
ok  	github.com/carlosframework/platform/internal/runs	0.550s
ok  	github.com/carlosframework/platform/internal/s3compat	0.017s
ok  	github.com/carlosframework/platform/internal/safefile	0.009s
ok  	github.com/carlosframework/platform/internal/schedule	2.747s
ok  	github.com/carlosframework/platform/internal/seeds	0.012s
ok  	github.com/carlosframework/platform/internal/sim/engines	3.020s
ok  	github.com/carlosframework/platform/internal/sim/hostlife	10.350s
ok  	github.com/carlosframework/platform/internal/sim/litestreamfacts	3.828s
ok  	github.com/carlosframework/platform/internal/status	0.105s
ok  	github.com/carlosframework/platform/internal/steering	0.013s
ok  	github.com/carlosframework/platform/internal/stopevidence	0.185s
ok  	github.com/carlosframework/platform/internal/svcrole	0.004s
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.011s
ok  	github.com/carlosframework/platform/internal/unixdial	0.003s
ok  	github.com/carlosframework/platform/internal/updatewords	0.005s
ok  	github.com/carlosframework/platform/internal/usage	0.005s
ok  	github.com/carlosframework/platform/internal/version	0.002s
ok  	github.com/carlosframework/platform/internal/vet	1.617s
FAIL
=== internal_console@0 (87 s)
ok  	github.com/carlosframework/platform/internal/console	84.453s
=== internal_console@1 (44 s)
ok  	github.com/carlosframework/platform/internal/console	41.608s
=== internal_console@2 (42 s)
ok  	github.com/carlosframework/platform/internal/console	39.406s
=== internal_console@3 (41 s)
ok  	github.com/carlosframework/platform/internal/console	38.415s
=== internal_console@4 (43 s)
ok  	github.com/carlosframework/platform/internal/console	40.380s
=== internal_console@5 (42 s)
ok  	github.com/carlosframework/platform/internal/console	39.603s
=== internal_console@6 (38 s)
ok  	github.com/carlosframework/platform/internal/console	34.592s
=== internal_console@7 (47 s)
ok  	github.com/carlosframework/platform/internal/console	43.923s
=== root@0 (105 s)
ok  	github.com/carlosframework/platform	103.072s
=== root@1 (82 s)
ok  	github.com/carlosframework/platform	80.260s
=== root@2 (97 s)
ok  	github.com/carlosframework/platform	95.446s

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 b6ff162af..8d2793212 100644
--- a/approved_rootfs_copy_test.go
+++ b/approved_rootfs_copy_test.go
@@ -156,6 +156,8 @@ var rootfsCopyBuilt = []string{
"RFS-1-C47", "RFS-1-C52", "RFS-1-C56",
// Task 6: the squashfs writer's size refusals (internal/rootfsimage/errors.go)
"RFS-1-C86", "RFS-1-C87",
+ // Task 7: processes meet the image (internal/rootfsimage/errors.go)
+ "RFS-1-C48", "RFS-1-C54",
}
func mustParseRootfsRecord(t *testing.T) []copyRow {
diff --git a/internal/rootfsimage/errors.go b/internal/rootfsimage/errors.go
index f3dfe6288..7f2c8e625 100644
--- a/internal/rootfsimage/errors.go
+++ b/internal/rootfsimage/errors.go
@@ -107,6 +107,23 @@ func (e FileTooLargeError) Error() string {
return fmt.Sprintf("%s is over 2 GiB, the largest file a rootfs image can hold. make it smaller and ship again", shown(e.Path))
}
+// ImageEnvError refuses an image whose config sets a name the platform keeps
+// for itself (RFS-1-C54). Name is the variable, such as CARLOS_DB.
+type ImageEnvError struct{ Name string }
+
+func (e ImageEnvError) Error() string {
+ return fmt.Sprintf("the image sets %s in its environment. names that start with CARLOS_ belong to the platform, so remove it from the image", shown(e.Name))
+}
+
+// CommandError refuses a process whose command the image does not have
+// (RFS-1-C48). Process is the process's name and Command its first word as
+// declared.
+type CommandError struct{ Process, Command string }
+
+func (e CommandError) Error() string {
+ return fmt.Sprintf("the %s process runs %s, which the image does not have. commands are looked up in the process's PATH, or from its working_dir when they contain a slash", shown(e.Process), shown(e.Command))
+}
+
// errTooLarge is wrapped by the refusal of a tree past its bounds (maxBytes,
// maxHeaders) and of a JSON document past maxJSONBytes. carlos ship's own
// size refusal (RFS-1-C43) speaks for the built image; this one stops a
diff --git a/internal/rootfsimage/framework.go b/internal/rootfsimage/framework.go
new file mode 100644
index 000000000..7a2443edf
--- /dev/null
+++ b/internal/rootfsimage/framework.go
@@ -0,0 +1,86 @@
+package rootfsimage
+
+import (
+ "maps"
+ "path"
+
+ "github.com/carlosframework/platform/internal/release"
+)
+
+// Framework is a web framework whose console the platform knows how to
+// start.
+type Framework string
+
+const (
+ Rails Framework = "Rails"
+ Laravel Framework = "Laravel"
+ Django Framework = "Django"
+)
+
+// FillConsole is procs with a console process added when the image looks
+// like a Rails, Laravel or Django app and none is declared, and the
+// framework it found. It looks under web's WorkingDir (the root when unset)
+// and the first match wins:
+//
+// Rails: bin/rails (an executable) and config/application.rb
+// -> bin/rails console
+// Laravel: artisan, and php resolves -> php artisan tinker
+// Django: manage.py, and python resolves (else python3)
+// -> <that> manage.py shell
+//
+// The filled process copies web's WorkingDir and Env, so it runs in the same
+// place with the same settings. A declared console, a missing web, or an
+// image that matches nothing leaves procs as it was and answers "". The
+// result is a new map; procs is not changed. A Laravel or Django console
+// needs its interpreter to resolve, so a console that could not start is
+// never filled in.
+func FillConsole(t *Tree, procs map[string]release.Process) (map[string]release.Process, Framework) {
+ out := maps.Clone(procs)
+ web, ok := procs[release.ProcessWeb]
+ if _, has := procs[release.ProcessConsole]; has || !ok {
+ return out, ""
+ }
+ dir, _ := t.Resolve(workDir(web))
+ var command []string
+ var fw Framework
+ switch {
+ case isFile(t, dir, "bin/rails", true) && isFile(t, dir, "config/application.rb", false):
+ command, fw = []string{"bin/rails", "console"}, Rails
+ case isFile(t, dir, "artisan", false) && resolves(t, web, "php"):
+ command, fw = []string{"php", "artisan", "tinker"}, Laravel
+ case isFile(t, dir, "manage.py", false):
+ for _, py := range []string{"python", "python3"} {
+ if resolves(t, web, py) {
+ command, fw = []string{py, "manage.py", "shell"}, Django
+ break
+ }
+ }
+ }
+ if fw == "" {
+ return out, ""
+ }
+ out[release.ProcessConsole] = release.Process{
+ Command: command,
+ WorkingDir: web.WorkingDir,
+ Env: maps.Clone(web.Env),
+ }
+ return out, fw
+}
+
+// isFile reports whether rel, under dir, is a regular file once symlinks are
+// followed, with an exec bit when exec is set.
+func isFile(t *Tree, dir, rel string, exec bool) bool {
+ final, ok := t.Resolve(path.Join("/", dir, rel))
+ if !ok {
+ return false
+ }
+ e, ok := t.Lookup(final)
+ return ok && e.Type == TypeFile && (!exec || e.Mode&0o111 != 0)
+}
+
+// resolves reports whether command is found for p as ResolveCommands would
+// find it.
+func resolves(t *Tree, p release.Process, command string) bool {
+ _, _, ok := lookupCommand(t, p, command)
+ return ok
+}
diff --git a/internal/rootfsimage/framework_test.go b/internal/rootfsimage/framework_test.go
new file mode 100644
index 000000000..7072ad993
--- /dev/null
+++ b/internal/rootfsimage/framework_test.go
@@ -0,0 +1,141 @@
+package rootfsimage
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/carlosframework/platform/internal/release"
+)
+
+func TestFillConsoleForRails(t *testing.T) {
+ tr := treeWith(t, map[string]string{"rails/bin/rails": "x", "rails/config/application.rb": "x"}, 0o755)
+ procs := map[string]release.Process{"web": {Command: []string{"bin/rails", "server"}, WorkingDir: "/rails", Env: map[string]string{"RAILS_ENV": "production"}}}
+ out, fw := FillConsole(tr, procs)
+ if fw != Rails {
+ t.Fatalf("framework = %q", fw)
+ }
+ want := release.Process{Command: []string{"bin/rails", "console"}, WorkingDir: "/rails", Env: map[string]string{"RAILS_ENV": "production"}}
+ if !reflect.DeepEqual(out["console"], want) {
+ t.Fatalf("console = %+v", out["console"])
+ }
+ if _, had := procs["console"]; had {
+ t.Fatal("FillConsole changed its input")
+ }
+ if !reflect.DeepEqual(out["web"], procs["web"]) {
+ t.Fatalf("web = %+v", out["web"])
+ }
+ out["console"].Env["RAILS_ENV"] = "changed"
+ if procs["web"].Env["RAILS_ENV"] != "production" {
+ t.Fatal("the console shares its env with web")
+ }
+}
+
+func TestFillConsoleForLaravel(t *testing.T) {
+ tr := treeWith(t, map[string]string{"var/www/artisan": "x", "usr/local/bin/php": "x"}, 0o755)
+ procs := map[string]release.Process{"web": {Command: []string{"php", "artisan", "serve"}, WorkingDir: "/var/www"}}
+ out, fw := FillConsole(tr, procs)
+ if fw != Laravel {
+ t.Fatalf("framework = %q", fw)
+ }
+ want := release.Process{Command: []string{"php", "artisan", "tinker"}, WorkingDir: "/var/www"}
+ if !reflect.DeepEqual(out["console"], want) {
+ t.Fatalf("console = %+v", out["console"])
+ }
+}
+
+func TestFillConsoleForDjangoPrefersPython(t *testing.T) {
+ tr := treeWith(t, map[string]string{"srv/manage.py": "x", "usr/bin/python": "x", "usr/bin/python3": "x"}, 0o755)
+ procs := map[string]release.Process{"web": {Command: []string{"gunicorn", "app"}, WorkingDir: "/srv"}}
+ out, fw := FillConsole(tr, procs)
+ if fw != Django {
+ t.Fatalf("framework = %q", fw)
+ }
+ if got, want := out["console"].Command, []string{"python", "manage.py", "shell"}; !reflect.DeepEqual(got, want) {
+ t.Fatalf("command = %v", got)
+ }
+}
+
+func TestFillConsoleForDjangoFallsBackToPython3(t *testing.T) {
+ tr := treeWith(t, map[string]string{"srv/manage.py": "x", "usr/bin/python3": "x"}, 0o755)
+ procs := map[string]release.Process{"web": {Command: []string{"gunicorn", "app"}, WorkingDir: "/srv"}}
+ out, fw := FillConsole(tr, procs)
+ if fw != Django {
+ t.Fatalf("framework = %q", fw)
+ }
+ if got, want := out["console"].Command, []string{"python3", "manage.py", "shell"}; !reflect.DeepEqual(got, want) {
+ t.Fatalf("command = %v", got)
+ }
+}
+
+func TestFillConsoleLooksForPythonOnTheWebsPath(t *testing.T) {
+ tr := treeWith(t, map[string]string{"srv/manage.py": "x", "venv/bin/python": "x"}, 0o755)
+ procs := map[string]release.Process{"web": {Command: []string{"gunicorn", "app"}, WorkingDir: "/srv", Env: map[string]string{"PATH": "/venv/bin"}}}
+ out, fw := FillConsole(tr, procs)
+ if fw != Django || out["console"].Command[0] != "python" {
+ t.Fatalf("got %v, %+v", fw, out["console"])
+ }
+}
+
+func TestFillConsoleLeavesADeclaredConsole(t *testing.T) {
+ tr := treeWith(t, map[string]string{"rails/bin/rails": "x", "rails/config/application.rb": "x"}, 0o755)
+ procs := map[string]release.Process{
+ "web": {Command: []string{"bin/rails", "server"}, WorkingDir: "/rails"},
+ "console": {Command: []string{"bin/rails", "runner"}, WorkingDir: "/rails"},
+ }
+ out, fw := FillConsole(tr, procs)
+ if fw != "" {
+ t.Fatalf("framework = %q", fw)
+ }
+ if !reflect.DeepEqual(out, procs) {
+ t.Fatalf("out = %+v", out)
+ }
+}
+
+func TestFillConsoleFindsNothingWithoutTheFiles(t *testing.T) {
+ for name, files := range map[string]map[string]string{
+ "artisan but no php": {"var/www/artisan": "x"},
+ "rails without application": {"var/www/bin/rails": "x"},
+ "rails without bin/rails": {"var/www/config/application.rb": "x"},
+ "manage.py but no python": {"var/www/manage.py": "x", "usr/bin/ruby": "x"},
+ "nothing": {"var/www/app.rb": "x"},
+ "a php that is not a binary": {"var/www/artisan": "x", "usr/local/bin/php": "x"},
+ } {
+ t.Run(name, func(t *testing.T) {
+ mode := int64(0o755)
+ if name == "a php that is not a binary" {
+ mode = 0o644
+ }
+ tr := treeWith(t, files, mode)
+ procs := map[string]release.Process{"web": {Command: []string{"x"}, WorkingDir: "/var/www"}}
+ out, fw := FillConsole(tr, procs)
+ if fw != "" || !reflect.DeepEqual(out, procs) {
+ t.Fatalf("got %q, %+v", fw, out)
+ }
+ })
+ }
+}
+
+func TestFillConsoleLooksUnderWebsWorkingDir(t *testing.T) {
+ tr := treeWith(t, map[string]string{"bin/rails": "x", "config/application.rb": "x"}, 0o755)
+ procs := map[string]release.Process{"web": {Command: []string{"x"}, WorkingDir: "/app"}}
+ out, fw := FillConsole(tr, procs)
+ if fw != "" || !reflect.DeepEqual(out, procs) {
+ t.Fatalf("got %q, %+v", fw, out)
+ }
+ // With no working dir, the root is where it looks.
+ procs["web"] = release.Process{Command: []string{"x"}}
+ if _, fw := FillConsole(tr, procs); fw != Rails {
+ t.Fatalf("framework = %q", fw)
+ }
+}
+
+func TestFillConsoleFirstMatchWins(t *testing.T) {
+ tr := treeWith(t, map[string]string{
+ "app/bin/rails": "x", "app/config/application.rb": "x", "app/artisan": "x", "app/manage.py": "x",
+ "usr/bin/php": "x", "usr/bin/python": "x",
+ }, 0o755)
+ procs := map[string]release.Process{"web": {Command: []string{"x"}, WorkingDir: "/app"}}
+ if _, fw := FillConsole(tr, procs); fw != Rails {
+ t.Fatalf("framework = %q", fw)
+ }
+}
diff --git a/internal/rootfsimage/processes.go b/internal/rootfsimage/processes.go
new file mode 100644
index 000000000..4b3927873
--- /dev/null
+++ b/internal/rootfsimage/processes.go
@@ -0,0 +1,236 @@
+package rootfsimage
+
+import (
+ "io"
+ "maps"
+ "path"
+ "slices"
+ "strings"
+
+ "github.com/carlosframework/platform/internal/release"
+)
+
+// DefaultPath is the PATH a process gets when neither its env nor the
+// image's config sets one. Boxes resolve and run commands with the same
+// value (rootfs apps Plan 2), so the two sides must not drift: a test on
+// each side pins it.
+const DefaultPath = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+
+// platformEnvPrefix starts the names the platform keeps for itself.
+const platformEnvPrefix = "CARLOS_"
+
+// ApplyImageConfig is procs with the image's config merged in, as a new map
+// (procs and the slices and maps in it are not changed). Each process's Env
+// is the config's Env, parsed as KEY=VALUE with a later entry winning and an
+// entry without "=" or with an empty name ignored, overlaid by the process's
+// own Env. An empty WorkingDir takes the config's, made absolute from the
+// root as the OCI runtimes do. A config name starting CARLOS_ is
+// ImageEnvError: the platform sets those, and an image must not.
+func ApplyImageConfig(procs map[string]release.Process, cfg ImageConfig) (map[string]release.Process, error) {
+ imgEnv := map[string]string{}
+ for _, kv := range cfg.Env {
+ name, value, ok := strings.Cut(kv, "=")
+ if !ok || name == "" {
+ continue
+ }
+ if strings.HasPrefix(name, platformEnvPrefix) {
+ return nil, ImageEnvError{Name: name}
+ }
+ imgEnv[name] = value
+ }
+ workDir := ""
+ if cfg.WorkingDir != "" {
+ workDir = path.Join("/", cfg.WorkingDir)
+ }
+ out := make(map[string]release.Process, len(procs))
+ for name, p := range procs {
+ p.Command = slices.Clone(p.Command)
+ env := maps.Clone(imgEnv)
+ maps.Copy(env, p.Env)
+ if len(env) == 0 {
+ env = nil
+ }
+ p.Env = env
+ if p.WorkingDir == "" {
+ p.WorkingDir = workDir
+ }
+ out[name] = p
+ }
+ return out, nil
+}
+
+// ResolveCommands checks that each process's command is in the image, in
+// name order, and answers CommandError for the first that is not. The
+// command resolves as execve would inside the image: with a slash, against
+// the process's WorkingDir (the root when unset); without one, through each
+// entry of the process's PATH (DefaultPath when its env sets none), where an
+// empty or relative entry is taken from the working dir. Symlinks are
+// followed with Tree.Resolve, so they stay inside the image, and the end
+// must be a regular file with an exec bit. The host's filesystem is never
+// consulted.
+func ResolveCommands(t *Tree, procs map[string]release.Process) error {
+ for _, name := range sortedNames(procs) {
+ p := procs[name]
+ if _, _, ok := lookupCommand(t, p, p.Command[0]); !ok {
+ return CommandError{Process: name, Command: p.Command[0]}
+ }
+ }
+ return nil
+}
+
+// sortedNames is the keys of procs in name order.
+func sortedNames(procs map[string]release.Process) []string {
+ names := make([]string, 0, len(procs))
+ for n := range procs {
+ names = append(names, n)
+ }
+ slices.Sort(names)
+ return names
+}
+
+// lookupCommand finds cmd for process p as ResolveCommands says, answering
+// the file's final path in the tree and its entry.
+func lookupCommand(t *Tree, p release.Process, cmd string) (string, *Entry, bool) {
+ if cmd == "" {
+ return "", nil, false
+ }
+ dir, _ := t.Resolve(workDir(p))
+ if strings.Contains(cmd, "/") {
+ return executable(t, absolute(dir, cmd))
+ }
+ pathEnv, set := p.Env["PATH"]
+ if !set {
+ pathEnv = DefaultPath
+ }
+ for _, entry := range strings.Split(pathEnv, ":") {
+ if entry == "" {
+ entry = "."
+ }
+ if final, e, ok := executable(t, absolute(dir, entry+"/"+cmd)); ok {
+ return final, e, true
+ }
+ }
+ return "", nil, false
+}
+
+// workDir is where p starts: its WorkingDir, else the root.
+func workDir(p release.Process) string {
+ if p.WorkingDir == "" {
+ return "/"
+ }
+ return p.WorkingDir
+}
+
+// absolute is p as a path from the root, a relative p taken from dir (a
+// path Tree.Resolve answered, "." for the root).
+func absolute(dir, p string) string {
+ if strings.HasPrefix(p, "/") {
+ return p
+ }
+ return path.Join("/", dir, p)
+}
+
+// executable resolves p and answers the entry there when it is a regular
+// file with an exec bit.
+func executable(t *Tree, p string) (string, *Entry, bool) {
+ final, ok := t.Resolve(p)
+ if !ok {
+ return "", nil, false
+ }
+ e, ok := t.Lookup(final)
+ if !ok || e.Type != TypeFile || e.Mode&0o111 == 0 {
+ return "", nil, false
+ }
+ return final, e, true
+}
+
+// The programs that need a JIT (spec §5.11, R11). jitRuntimes are the
+// interpreters; jitLaunchers are the commands that start one.
+var (
+ jitRuntimes = []string{"node", "nodejs", "bun", "deno"}
+ jitLaunchers = []string{"npm", "npx", "yarn", "pnpm", "bunx"}
+)
+
+// shebangBytes is how much of a file JITProgram reads to see its first line.
+const shebangBytes = 256
+
+// JITProgram answers the first process, in name order, that runs Node, Bun
+// or Deno, and the program's name. A process runs one when the base name of
+// its Command[0], or of the file it resolves to (symlinks followed), is node,
+// nodejs, bun or deno; when Command[0] is named npm, npx, yarn, pnpm or
+// bunx; or when the resolved file starts with "#!" and its first line names
+// one of the four (#!/usr/bin/env node, #!/usr/local/bin/bun). The name
+// answered is the one that matched, Command[0]'s first. It reads at most
+// the first 256 bytes of one file per process and runs nothing. Only
+// carlos ship --check uses it, to warn about a missing --jit: a local
+// runtime does not apply MemoryDenyWriteExecute, so the check passes where a
+// box would stop the process. The platform never reads it.
+func JITProgram(t *Tree, procs map[string]release.Process) (process, program string, ok bool) {
+ for _, name := range sortedNames(procs) {
+ if prog := jitOf(t, procs[name]); prog != "" {
+ return name, prog, true
+ }
+ }
+ return "", "", false
+}
+
+func jitOf(t *Tree, p release.Process) string {
+ cmd := p.Command[0]
+ if base := path.Base(cmd); slices.Contains(jitRuntimes, base) || slices.Contains(jitLaunchers, base) {
+ return base
+ }
+ final, e, ok := lookupCommand(t, p, cmd)
+ if !ok {
+ return ""
+ }
+ if base := path.Base(final); slices.Contains(jitRuntimes, base) {
+ return base
+ }
+ return shebangRuntime(t, e)
+}
+
+// shebangRuntime is the runtime a script's "#!" line names, or "".
+func shebangRuntime(t *Tree, e *Entry) string {
+ rc, err := t.Open(e)
+ if err != nil {
+ return ""
+ }
+ defer rc.Close()
+ buf := make([]byte, shebangBytes)
+ n, err := io.ReadFull(rc, buf)
+ if err != nil && err != io.ErrUnexpectedEOF && err != io.EOF {
+ return ""
+ }
+ line := string(buf[:n])
+ if !strings.HasPrefix(line, "#!") {
+ return ""
+ }
+ cut := false
+ if i := strings.IndexByte(line, '\n'); i >= 0 {
+ line = line[:i]
+ } else {
+ cut = n == shebangBytes
+ }
+ fields := strings.Fields(line[2:])
+ if cut && len(fields) > 0 && !strings.HasSuffix(line, " ") && !strings.HasSuffix(line, "\t") {
+ fields = fields[:len(fields)-1] // the last word may have been cut short
+ }
+ if len(fields) == 0 {
+ return ""
+ }
+ interp := path.Base(fields[0])
+ if interp == "env" {
+ interp = ""
+ for _, f := range fields[1:] {
+ if strings.HasPrefix(f, "-") || strings.Contains(f, "=") {
+ continue
+ }
+ interp = path.Base(f)
+ break
+ }
+ }
+ if slices.Contains(jitRuntimes, interp) {
+ return interp
+ }
+ return ""
+}
diff --git a/internal/rootfsimage/processes_test.go b/internal/rootfsimage/processes_test.go
new file mode 100644
index 000000000..f7ca7d4e2
--- /dev/null
+++ b/internal/rootfsimage/processes_test.go
@@ -0,0 +1,284 @@
+package rootfsimage
+
+import (
+ "archive/tar"
+ "errors"
+ "reflect"
+ "sort"
+ "testing"
+
+ "github.com/carlosframework/platform/internal/release"
+)
+
+// treeWith is a tree holding files (path to body), every one with mode.
+func treeWith(t *testing.T, files map[string]string, mode int64) *Tree {
+ t.Helper()
+ names := make([]string, 0, len(files))
+ for n := range files {
+ names = append(names, n)
+ }
+ sort.Strings(names)
+ es := make([]tEntry, 0, len(names))
+ for _, n := range names {
+ es = append(es, tEntry{name: n, typ: tar.TypeReg, mode: mode, body: files[n]})
+ }
+ return archTree(t, es...)
+}
+
+func TestApplyImageConfigMergesEnvAndWorkdir(t *testing.T) {
+ procs := map[string]release.Process{
+ "web": {Command: []string{"bin/server"}, Env: map[string]string{"RAILS_ENV": "staging"}},
+ "worker": {Command: []string{"bin/jobs"}, WorkingDir: "/jobs"},
+ }
+ cfg := ImageConfig{
+ Env: []string{"PATH=/usr/local/bundle/bin:/usr/bin", "RAILS_ENV=production", "NOEQUALS", "A=1", "A=2", "EMPTY="},
+ WorkingDir: "/rails",
+ }
+ got, err := ApplyImageConfig(procs, cfg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ want := map[string]release.Process{
+ "web": {Command: []string{"bin/server"}, WorkingDir: "/rails", Env: map[string]string{
+ "PATH": "/usr/local/bundle/bin:/usr/bin", "RAILS_ENV": "staging", "A": "2", "EMPTY": "",
+ }},
+ "worker": {Command: []string{"bin/jobs"}, WorkingDir: "/jobs", Env: map[string]string{
+ "PATH": "/usr/local/bundle/bin:/usr/bin", "RAILS_ENV": "production", "A": "2", "EMPTY": "",
+ }},
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Fatalf("got %+v\nwant %+v", got, want)
+ }
+ if procs["web"].WorkingDir != "" || len(procs["web"].Env) != 1 || procs["worker"].Env != nil {
+ t.Fatalf("ApplyImageConfig changed its input: %+v", procs)
+ }
+ got["web"].Command[0] = "changed"
+ if procs["web"].Command[0] != "bin/server" {
+ t.Fatal("the result shares its command with the input")
+ }
+}
+
+func TestApplyImageConfigKeepsAProcessWithoutAnyEnvEmpty(t *testing.T) {
+ procs := map[string]release.Process{"web": {Command: []string{"x"}}}
+ got, err := ApplyImageConfig(procs, ImageConfig{})
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(got, procs) {
+ t.Fatalf("got %+v", got)
+ }
+}
+
+func TestApplyImageConfigTakesARelativeWorkdirFromTheRoot(t *testing.T) {
+ procs := map[string]release.Process{"web": {Command: []string{"x"}}}
+ got, err := ApplyImageConfig(procs, ImageConfig{WorkingDir: "app/./srv/"})
+ if err != nil {
+ t.Fatal(err)
+ }
+ if wd := got["web"].WorkingDir; wd != "/app/srv" {
+ t.Fatalf("working dir = %q", wd)
+ }
+}
+
+func TestApplyImageConfigRefusesPlatformNames(t *testing.T) {
+ procs := map[string]release.Process{"web": {Command: []string{"x"}}}
+ _, err := ApplyImageConfig(procs, ImageConfig{Env: []string{"PATH=/bin", "CARLOS_DB=/x"}})
+ if want := (ImageEnvError{"CARLOS_DB"}); !errors.Is(err, want) {
+ t.Fatalf("err = %v, want %v", err, want)
+ }
+ // A name that only contains CARLOS_ is the image's own.
+ if _, err := ApplyImageConfig(procs, ImageConfig{Env: []string{"MY_CARLOS_DB=/x"}}); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestImageEnvErrorAndCommandErrorSpeakTheDeck(t *testing.T) {
+ if got, want := (ImageEnvError{"CARLOS_DB"}).Error(), "the image sets CARLOS_DB in its environment. names that start with CARLOS_ belong to the platform, so remove it from the image"; got != want {
+ t.Errorf("%q\nwant %q", got, want)
+ }
+ if got, want := (CommandError{"worker", "bin/jobs"}).Error(), "the worker process runs bin/jobs, which the image does not have. commands are looked up in the process's PATH, or from its working_dir when they contain a slash"; got != want {
+ t.Errorf("%q\nwant %q", got, want)
+ }
+}
+
+func commandTree(t *testing.T) *Tree {
+ return archTree(t,
+ tEntry{name: "usr/local/bundle/bin/rails", typ: tar.TypeReg, mode: 0o755, body: "x"},
+ tEntry{name: "rails/bin/thrust", typ: tar.TypeReg, mode: 0o755, body: "x"},
+ tEntry{name: "rails/bin/plain", typ: tar.TypeReg, mode: 0o644, body: "x"},
+ tEntry{name: "rails/bin", typ: tar.TypeDir, mode: 0o755},
+ tEntry{name: "usr/bin/ruby3.3", typ: tar.TypeReg, mode: 0o755, body: "x"},
+ tEntry{name: "usr/bin/ruby", typ: tar.TypeSymlink, link: "ruby3.3"},
+ tEntry{name: "bin/sh", typ: tar.TypeSymlink, link: "/usr/bin/ruby3.3"},
+ tEntry{name: "usr/bin/loop", typ: tar.TypeSymlink, link: "loop"},
+ tEntry{name: "usr/bin/dir/x", typ: tar.TypeReg, mode: 0o755, body: "x"},
+ tEntry{name: "opt/escape", typ: tar.TypeSymlink, link: "../../../../usr/bin/ruby3.3"},
+ )
+}
+
+func TestResolveCommands(t *testing.T) {
+ tr := commandTree(t)
+ path := map[string]string{"PATH": "/usr/local/bundle/bin:/usr/bin"}
+ for _, c := range []struct {
+ name string
+ p release.Process
+ ok bool
+ }{
+ {"a PATH lookup through the config's PATH", release.Process{Command: []string{"rails", "server"}, Env: path}, true},
+ {"a PATH lookup falls to the next entry", release.Process{Command: []string{"ruby3.3"}, Env: path}, true},
+ {"the default PATH", release.Process{Command: []string{"sh"}}, true},
+ {"relative to the working dir", release.Process{Command: []string{"./bin/thrust"}, WorkingDir: "/rails"}, true},
+ {"relative without slash-dot", release.Process{Command: []string{"bin/thrust"}, WorkingDir: "/rails"}, true},
+ {"relative to the root without a working dir", release.Process{Command: []string{"rails/bin/thrust"}}, true},
+ {"relative to the wrong dir", release.Process{Command: []string{"bin/thrust"}}, false},
+ {"an absolute path", release.Process{Command: []string{"/usr/local/bundle/bin/rails"}}, true},
+ {"through a symlink", release.Process{Command: []string{"/usr/bin/ruby"}}, true},
+ {"an absolute symlink target is the image's root", release.Process{Command: []string{"/bin/sh"}}, true},
+ {"a relative symlink cannot climb out of the root", release.Process{Command: []string{"/opt/escape"}}, true},
+ {"a file without an exec bit", release.Process{Command: []string{"/rails/bin/plain"}}, false},
+ {"a file without an exec bit on PATH", release.Process{Command: []string{"plain"}, Env: map[string]string{"PATH": "/rails/bin"}}, false},
+ {"a directory", release.Process{Command: []string{"/usr/bin/dir"}}, false},
+ {"a symlink loop", release.Process{Command: []string{"/usr/bin/loop"}}, false},
+ {"missing", release.Process{Command: []string{"bin/jobs"}}, false},
+ {"not on the PATH", release.Process{Command: []string{"rails"}, Env: map[string]string{"PATH": "/usr/bin"}}, false},
+ {"an empty PATH entry is the working dir", release.Process{Command: []string{"thrust"}, WorkingDir: "/rails/bin", Env: map[string]string{"PATH": ":/nowhere"}}, true},
+ {"a relative PATH entry is under the working dir", release.Process{Command: []string{"thrust"}, WorkingDir: "/rails", Env: map[string]string{"PATH": "bin"}}, true},
+ } {
+ t.Run(c.name, func(t *testing.T) {
+ err := ResolveCommands(tr, map[string]release.Process{"web": c.p})
+ if c.ok && err != nil {
+ t.Fatalf("err = %v", err)
+ }
+ if !c.ok {
+ want := CommandError{"web", c.p.Command[0]}
+ if !errors.Is(err, want) {
+ t.Fatalf("err = %v, want %v", err, want)
+ }
+ }
+ })
+ }
+}
+
+func TestResolveCommandsNamesTheFirstMissInNameOrder(t *testing.T) {
+ tr := commandTree(t)
+ procs := map[string]release.Process{
+ "web": {Command: []string{"/usr/bin/ruby"}},
+ "worker": {Command: []string{"bin/jobs"}},
+ "mailer": {Command: []string{"bin/mail"}},
+ }
+ err := ResolveCommands(tr, procs)
+ if want := (CommandError{"mailer", "bin/mail"}); !errors.Is(err, want) {
+ t.Fatalf("err = %v, want %v", err, want)
+ }
+ procs["mailer"] = release.Process{Command: []string{"/usr/bin/ruby"}}
+ err = ResolveCommands(tr, procs)
+ if want := (CommandError{"worker", "bin/jobs"}); !errors.Is(err, want) {
+ t.Fatalf("err = %v, want %v", err, want)
+ }
+}
+
+func TestResolveCommandsFollowsASymlinkedWorkingDir(t *testing.T) {
+ tr := archTree(t,
+ tEntry{name: "srv/app/bin/run", typ: tar.TypeReg, mode: 0o755, body: "x"},
+ tEntry{name: "app", typ: tar.TypeSymlink, link: "/srv/app"},
+ )
+ procs := map[string]release.Process{"web": {Command: []string{"bin/run"}, WorkingDir: "/app"}}
+ if err := ResolveCommands(tr, procs); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestJITProgram(t *testing.T) {
+ tr := archTree(t,
+ tEntry{name: "usr/local/bin/node", typ: tar.TypeReg, mode: 0o755, body: "x"},
+ tEntry{name: "usr/local/bin/npm", typ: tar.TypeReg, mode: 0o755, body: "x"},
+ tEntry{name: "usr/local/bin/deno", typ: tar.TypeReg, mode: 0o755, body: "x"},
+ tEntry{name: "usr/bin/bun-1.1", typ: tar.TypeReg, mode: 0o755, body: "x"},
+ tEntry{name: "usr/bin/bun", typ: tar.TypeSymlink, link: "bun-1.1"},
+ tEntry{name: "app/bin/www", typ: tar.TypeReg, mode: 0o755, body: "#!/usr/bin/env node\nrequire('x')\n"},
+ tEntry{name: "app/bin/flagged", typ: tar.TypeReg, mode: 0o755, body: "#!/usr/bin/env -S bun run\n"},
+ tEntry{name: "app/bin/direct", typ: tar.TypeReg, mode: 0o755, body: "#! /usr/local/bin/bun --smol\n"},
+ tEntry{name: "app/bin/rails", typ: tar.TypeReg, mode: 0o755, body: "#!/usr/bin/env ruby\n"},
+ tEntry{name: "app/bin/sh-node", typ: tar.TypeReg, mode: 0o755, body: "#!/bin/sh\nexec node x.js\n"},
+ tEntry{name: "app/bin/nodefake", typ: tar.TypeReg, mode: 0o755, body: "#!/usr/bin/env nodemon\n"},
+ tEntry{name: "app/bin/runner", typ: tar.TypeSymlink, link: "/usr/local/bin/node"},
+ tEntry{name: "usr/bin/ruby", typ: tar.TypeReg, mode: 0o755, body: "x"},
+ tEntry{name: "usr/bin/bundle", typ: tar.TypeReg, mode: 0o755, body: "x"},
+ )
+ for _, c := range []struct {
+ name string
+ cmd []string
+ dir string
+ program string
+ }{
+ {"node", []string{"node", "server.js"}, "", "node"},
+ {"npm", []string{"npm", "start"}, "", "npm"},
+ {"a node script", []string{"bin/www"}, "/app", "node"},
+ {"a bun script after env flags", []string{"bin/flagged"}, "/app", "bun"},
+ {"a bun script by path", []string{"bin/direct"}, "/app", "bun"},
+ {"bun through a symlink to bun-1.1", []string{"/usr/bin/bun", "run", "start"}, "", "bun"},
+ {"deno", []string{"deno", "serve"}, "", "deno"},
+ {"a link named something else to node", []string{"bin/runner"}, "/app", "node"},
+ {"a command named like a package manager, in the tree or not", []string{"pnpm", "start"}, "", "pnpm"},
+ {"a command that is not found is still named", []string{"/opt/bin/bunx", "x"}, "", "bunx"},
+ {"ruby", []string{"bundle", "exec", "puma"}, "", ""},
+ {"a ruby script", []string{"bin/rails", "server"}, "/app", ""},
+ {"a shell script that runs node", []string{"bin/sh-node"}, "/app", ""},
+ {"a similar name", []string{"bin/nodefake"}, "/app", ""},
+ } {
+ t.Run(c.name, func(t *testing.T) {
+ procs := map[string]release.Process{"web": {Command: c.cmd, WorkingDir: c.dir}}
+ name, program, ok := JITProgram(tr, procs)
+ if c.program == "" {
+ if ok {
+ t.Fatalf("ok with %q in %q", program, name)
+ }
+ return
+ }
+ if !ok || name != "web" || program != c.program {
+ t.Fatalf("got (%q, %q, %v), want (web, %q, true)", name, program, ok, c.program)
+ }
+ })
+ }
+}
+
+func TestJITProgramIgnoresAnImageWhoseProcessesDoNotRunIt(t *testing.T) {
+ tr := archTree(t,
+ tEntry{name: "usr/local/bin/node", typ: tar.TypeReg, mode: 0o755, body: "x"},
+ tEntry{name: "usr/bin/ruby", typ: tar.TypeReg, mode: 0o755, body: "x"},
+ )
+ procs := map[string]release.Process{"web": {Command: []string{"ruby", "app.rb"}}}
+ if name, program, ok := JITProgram(tr, procs); ok {
+ t.Fatalf("ok with %q in %q", program, name)
+ }
+}
+
+func TestJITProgramAnswersTheFirstProcessInNameOrder(t *testing.T) {
+ tr := archTree(t,
+ tEntry{name: "usr/bin/ruby", typ: tar.TypeReg, mode: 0o755, body: "x"},
+ tEntry{name: "usr/bin/node", typ: tar.TypeReg, mode: 0o755, body: "x"},
+ tEntry{name: "usr/bin/deno", typ: tar.TypeReg, mode: 0o755, body: "x"},
+ )
+ procs := map[string]release.Process{
+ "web": {Command: []string{"ruby"}},
+ "worker": {Command: []string{"node"}},
+ "jobs": {Command: []string{"deno"}},
+ }
+ name, program, ok := JITProgram(tr, procs)
+ if !ok || name != "jobs" || program != "deno" {
+ t.Fatalf("got (%q, %q, %v)", name, program, ok)
+ }
+}
+
+func TestJITProgramReadsOnlyTheFirstBytes(t *testing.T) {
+ // The interpreter sits past byte 256, so the line is not read that far.
+ pad := make([]byte, 300)
+ for i := range pad {
+ pad[i] = ' '
+ }
+ tr := archTree(t, tEntry{name: "app/run", typ: tar.TypeReg, mode: 0o755, body: "#!/usr/bin/env" + string(pad) + "node\n"})
+ procs := map[string]release.Process{"web": {Command: []string{"/app/run"}}}
+ if name, program, ok := JITProgram(tr, procs); ok {
+ t.Fatalf("ok with %q in %q", program, name)
+ }
+}