release: the rootfs kind, its processes and the shape rule (rootfs Plan 1 Task 2)
Every other reader of Manifest.Kind tolerates rootfs: stageFrom picks by the linux-arm64 key and skips a manifest without it, StampProgram skips a non-binary, signedhead and materialize are static-guarded, proofbinding requires binary, and carlos releases prints the kind.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 files changed,
+675
−4
approved_rootfs_copy_test.go+4 −1internal/release/golden_test.go+34 −0internal/release/release.go+20 −3internal/release/rootfs.go+220 −0internal/release/rootfs_test.go+391 −0internal/runs/runs_test.go+6 −0
CI failed — run details
CI log
=== gate ===
.amadan/test-gate.sh
go: downloading golang.org/x/net v0.60.0
go: downloading golang.org/x/crypto v0.57.0
go: downloading golang.org/x/sys v0.48.0
go: downloading github.com/pion/stun/v3 v3.1.5
go: downloading golang.org/x/sync v0.23.0
go: downloading github.com/pion/transport/v4 v4.0.2
go: downloading golang.org/x/text v0.42.0
go: downloading golang.org/x/text v0.42.0
go: downloading github.com/pion/dtls/v3 v3.1.4
go: downloading github.com/pion/dtls/v3 v3.1.4
=== launchctx (0 s)
ok amadan.net/carlos/platform.git/launchctx 0.018s
? amadan.net/carlos/platform.git/launchctx/controlname [no test files]
? amadan.net/carlos/platform.git/launchctx/wireid [no test files]
=== vet (24 s)
go: downloading golang.org/x/tools v0.49.0
go: downloading golang.org/x/text v0.42.0
go: downloading github.com/pion/dtls/v3 v3.1.4
go: downloading golang.org/x/mod v0.41.0
=== gofmt (0 s)
gofmt -l .: clean
=== rest (175 s)
? github.com/carlosframework/platform/cmd/changelog [no test files]
ok github.com/carlosframework/platform/cmd/console 3.662s
ok github.com/carlosframework/platform/cmd/moveprobe 11.996s
ok github.com/carlosframework/platform/cmd/zddprobe 0.806s
ok github.com/carlosframework/platform/internal/activator 57.740s
ok github.com/carlosframework/platform/internal/agentsock 0.040s
ok github.com/carlosframework/platform/internal/alerting 0.015s
ok github.com/carlosframework/platform/internal/analytics 0.042s
ok github.com/carlosframework/platform/internal/appconfig 2.847s
ok github.com/carlosframework/platform/internal/apperr 0.123s
ok github.com/carlosframework/platform/internal/applog 0.340s
ok github.com/carlosframework/platform/internal/awsinv 0.011s
ok github.com/carlosframework/platform/internal/boxchoice 0.006s
ok github.com/carlosframework/platform/internal/boxid 0.774s
? 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.013s
ok github.com/carlosframework/platform/internal/caps 0.027s
ok github.com/carlosframework/platform/internal/certwarm 0.004s
ok github.com/carlosframework/platform/internal/cgroup 0.833s
ok github.com/carlosframework/platform/internal/changelog 0.694s
ok github.com/carlosframework/platform/internal/claimactivation 1.295s
ok github.com/carlosframework/platform/internal/clamd 0.070s
? 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 8.339s
ok github.com/carlosframework/platform/internal/dbdoor/dbdoortest 0.011s
ok github.com/carlosframework/platform/internal/dbquery 0.008s
ok github.com/carlosframework/platform/internal/dbreads 2.088s
? github.com/carlosframework/platform/internal/dbreads/dbreadstest [no test files]
ok github.com/carlosframework/platform/internal/dbverify 0.005s
ok github.com/carlosframework/platform/internal/dnsrec 0.010s
ok github.com/carlosframework/platform/internal/docsite 0.008s
ok github.com/carlosframework/platform/internal/domains 2.989s
ok github.com/carlosframework/platform/internal/doorkey 0.014s
ok github.com/carlosframework/platform/internal/economics 0.010s
ok github.com/carlosframework/platform/internal/edge 45.681s
? 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.134s
ok github.com/carlosframework/platform/internal/gate 1.657s
ok github.com/carlosframework/platform/internal/genselect 0.015s
ok github.com/carlosframework/platform/internal/geo 0.014s
ok github.com/carlosframework/platform/internal/geoip 0.029s
ok github.com/carlosframework/platform/internal/historyreadback 0.154s
ok github.com/carlosframework/platform/internal/host 140.979s
ok github.com/carlosframework/platform/internal/hostactors 6.891s
ok github.com/carlosframework/platform/internal/hostactors/awsmembership 0.005s
ok github.com/carlosframework/platform/internal/hostbox 2.871s
ok github.com/carlosframework/platform/internal/hostclaim 0.798s
ok github.com/carlosframework/platform/internal/hostenv 0.005s
ok github.com/carlosframework/platform/internal/hostevidence 0.006s
ok github.com/carlosframework/platform/internal/hostexec 5.287s
ok github.com/carlosframework/platform/internal/hostfence 0.062s
ok github.com/carlosframework/platform/internal/hostfiles 10.383s
ok github.com/carlosframework/platform/internal/hostfloor 0.020s
ok github.com/carlosframework/platform/internal/hostguard 1.025s
ok github.com/carlosframework/platform/internal/hostops 1.925s
? github.com/carlosframework/platform/internal/hostops/fencerelease [no test files]
ok github.com/carlosframework/platform/internal/hostops/internal/fencerelease 0.002s
ok github.com/carlosframework/platform/internal/hostquarantine 0.002s
ok github.com/carlosframework/platform/internal/hostrelocate 0.646s
ok github.com/carlosframework/platform/internal/hostresolve 0.175s
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.227s
ok github.com/carlosframework/platform/internal/instanceexec 2.801s
ok github.com/carlosframework/platform/internal/instancefs 0.006s
ok github.com/carlosframework/platform/internal/instancekey 0.003s
ok github.com/carlosframework/platform/internal/instanceupdates 0.013s
ok github.com/carlosframework/platform/internal/layout 1.722s
ok github.com/carlosframework/platform/internal/lbhealth 0.006s
ok github.com/carlosframework/platform/internal/lease 10.190s
ok github.com/carlosframework/platform/internal/lease/leasetest 0.553s
ok github.com/carlosframework/platform/internal/ledger 0.027s
ok github.com/carlosframework/platform/internal/mail 0.208s
ok github.com/carlosframework/platform/internal/maintenance 0.101s
ok github.com/carlosframework/platform/internal/maintenanceexec 5.557s
ok github.com/carlosframework/platform/internal/maintenanceguard 0.125s
ok github.com/carlosframework/platform/internal/metrics 0.006s
ok github.com/carlosframework/platform/internal/moves 22.394s
ok github.com/carlosframework/platform/internal/moves/archive 1.042s
ok github.com/carlosframework/platform/internal/objstore 0.272s
ok github.com/carlosframework/platform/internal/ops 0.240s
ok github.com/carlosframework/platform/internal/park 0.269s
ok github.com/carlosframework/platform/internal/plans 0.011s
ok github.com/carlosframework/platform/internal/privatefile 0.005s
2026/10/24 20:29:39 provision: listing apps/bab/blog/instances/: list refused — its records are unseen this pass
2026/10/24 20:29:39 provision: listing apps/bab/: listdirs refused — its records are unseen this pass
2026/10/24 20:29:39 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:39 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:39 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:39 provision: listing apps/bac/tito/instances/: list refused — its records are unseen this pass
2026/10/24 20:29:39 provision: listing apps/bac/tito/instances/: list refused — its records are unseen this pass
2026/10/24 20:29:39 provision: skipping record apps/bac/tito/instances/one.example.com.json: unreadable: read refused
2026/10/24 20:29:39 provision: listing apps/bac/tito/instances/: list refused — its records are unseen this pass
2026/10/24 20:29:39 provision: an app's records could not be listed: they are skipped
2026/10/24 20:29:39 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 20:29:39 provision: remove retired instance route shop.example: provision: claim admission unavailable
2026/10/24 20:29:39 provision: remove retired instance route shop.example: provision: claim admission unavailable
2026/10/24 20:29:39 provision: remove retired sidecar route worker.sidecar.internal: provision: claim admission unavailable
2026/10/24 20:29:39 provision: remove retired sidecar route worker.sidecar.internal: provision: claim admission unavailable
2026/10/24 20:29:39 provision: claim install acme.go.tito.io: provision: claim admission unavailable
2026/10/24 20:29:39 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:39 provision: claim install acme.go.tito.io: registry: claim row ownership changed or unknown
2026/10/24 20:29:39 provision: claim install bot.eleven.bac.sidecar.internal: provision: claim admission unavailable
2026/10/24 20:29:39 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 20:29:39 provision: claim install bot.eleven.bac.sidecar.internal: registry: claim row ownership changed or unknown
2026/10/24 20:29:39 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 20:29:39 provision: acme.go.tito.io: not minting this pass: the box's layout intent could not be read: no sealed config
2026/10/24 20:29:39 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:39 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:39 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 20:29:39 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 20:29:39 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 20:29:39 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 20:29:39 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:39 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 20:29:39 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 20:29:39 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 20:29:39 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:39 provision: claim install acme.go.tito.io: registry: claim row ownership changed or unknown
2026/10/24 20:29:39 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:39 provision: claim install acme.go.tito.io: registry: claim row ownership changed or unknown
2026/10/24 20:29:39 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 20:29:39 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 20:29:39 provision: claim install bot.eleven.bac.sidecar.internal: registry: claim row ownership changed or unknown
2026/10/24 20:29:39 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 20:29:39 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:39 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 20:29:39 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 20:29:39 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:39 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:39 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:39 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 20:29:39 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:39 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:39 provision: skipping record apps/bac/tito/instances/new.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:39 provision: not removing acme.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 20:29:39 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:39 provision: skipping record apps/bac/tito/instances/new.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:40 provision: minted instance route ra.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route rb.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route rd.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route re.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route rf.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route ri.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route rk.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route rl.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route rc.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route rg.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route rh.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route rj.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route ra.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route rb.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route rc.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route rd.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: skipping record apps/bac/tito/instances/rb.go.tito.io.json: read failed: read refused
2026/10/24 20:29:40 provision: skipping record apps/bac/tito/instances/rb.go.tito.io.json: read failed: read refused
2026/10/24 20:29:40 provision: minted instance route re.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route x.appf.example (app "appf" acct "bac")
2026/10/24 20:29:40 provision: minted instance route x.appg.example (app "appg" acct "bac")
2026/10/24 20:29:40 provision: minted instance route x.apph.example (app "apph" acct "bac")
2026/10/24 20:29:40 provision: minted instance route x.appj.example (app "appj" acct "bac")
2026/10/24 20:29:40 provision: minted instance route x.appb.example (app "appb" acct "bac")
2026/10/24 20:29:40 provision: minted instance route x.appd.example (app "appd" acct "bac")
2026/10/24 20:29:40 provision: minted instance route x.appi.example (app "appi" acct "bac")
2026/10/24 20:29:40 provision: minted instance route x.appa.example (app "appa" acct "bac")
2026/10/24 20:29:40 provision: minted instance route x.appc.example (app "appc" acct "bac")
2026/10/24 20:29:40 provision: minted instance route x.appe.example (app "appe" acct "bac")
2026/10/24 20:29:40 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 20:29:40 provision: minted instance route r0023.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0084.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0087.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0113.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0111.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0006.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0014.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0017.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0030.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0033.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0091.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0107.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0022.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0028.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0034.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0037.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0058.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0066.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0071.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0116.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0049.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0051.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0079.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0090.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0105.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0123.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0127.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0018.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0021.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0089.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0040.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0045.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0063.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0098.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0122.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0110.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0053.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0097.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0010.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0011.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0039.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0042.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0065.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0069.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0072.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0073.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0015.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0044.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0074.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0083.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0082.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0120.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0121.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0125.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0060.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0119.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0108.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0129.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0038.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0052.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0056.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0070.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0092.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0104.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0117.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0003.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0088.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0095.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0032.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0055.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0062.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0124.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0002.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0057.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0046.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0020.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0048.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0075.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0106.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0096.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0000.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0025.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0054.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0081.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0093.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0050.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0064.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0067.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0118.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0005.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0026.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0027.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0103.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0043.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0080.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0115.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0128.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0024.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0059.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0031.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0001.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0007.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0019.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0035.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0061.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0076.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0078.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0109.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0029.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0094.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0101.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0126.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0004.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0008.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0047.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0068.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0077.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0086.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0036.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0085.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0100.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0112.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0114.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0012.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0041.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0099.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0102.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0009.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0013.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:40 provision: minted instance route r0016.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 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 20:29:41 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: minted instance route console.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: minted service route ha.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: minted service route svc.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: minted instance route whole.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: minted instance route shared.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: converged acme.go.tito.io channel stable -> edge
2026/10/24 20:29:41 provision: converged acme.go.tito.io channel edge -> canary/rehearsal
2026/10/24 20:29:41 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: empty channel
2026/10/24 20:29:41 provision: not removing acme.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 20:29:41 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: converged acme.go.tito.io environment "" -> "staging"
2026/10/24 20:29:41 provision: converged acme.go.tito.io environment "staging" -> ""
2026/10/24 20:29:41 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: converged acme.go.tito.io steering "" -> "latency"
2026/10/24 20:29:41 provision: converged acme.go.tito.io steering "latency" -> ""
2026/10/24 20:29:41 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: converged acme.go.tito.io hibernate false -> true
2026/10/24 20:29:41 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: converged acme.go.tito.io hibernate true -> false (replication "daily" cleared: only a hibernating route's rung is read)
2026/10/24 20:29:41 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: converged acme.go.tito.io status-named false -> true
2026/10/24 20:29:41 provision: converged acme.go.tito.io status-named true -> false
2026/10/24 20:29:41 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 provision: minted service route ha.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 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 20:29:41 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 20:29:41 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 20:29:41 provision: minted service route whole.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:41 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 20:29:41 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 20:29:41 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 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted service route whole.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: skipping accounts/bac/account.json: malformed account manifest: invalid character 'o' in literal null (expecting 'u')
2026/10/24 20:29:42 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: manifest bac/tito: read failed: provision: manifest bac/tito: invalid character 'o' in literal null (expecting 'u')
2026/10/24 20:29:42 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 20:29:42 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 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 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 20:29:42 provision: not removing acme$evil.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 20:29:42 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 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 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 20:29:42 provision: not removing bad-service.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 20:29:42 provision: skipping record apps/bac/tito/instances/no-channel.go.tito.io.json: empty channel
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: skipping record apps/bac/tito/instances/no-channel.go.tito.io.json: empty channel
2026/10/24 20:29:42 provision: not removing no-channel.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:42 provision: not removing acme.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 20:29:42 provision: removed retired instance route ghost.go.tito.io (record gone)
2026/10/24 20:29:42 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 20:29:42 provision: minted instance route dup.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 20:29:42 provision: removed retired instance route acme.go.tito.io (app in the trash)
2026/10/24 20:29:42 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 20:29:42 provision: removed retired static route site.go.tito.io (app in the trash)
2026/10/24 20:29:42 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 20:29:42 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 20:29:42 provision: removed retired instance route acme.go.tito.io (app in the trash)
2026/10/24 20:29:42 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 20:29:42 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 20:29:42 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 20:29:42 provision: converged acme.go.tito.io channel stable -> edge
2026/10/24 20:29:42 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 20:29:42 provision: converged acme.go.tito.io channel canary/rehearsal -> edge
2026/10/24 20:29:42 provision: converged acme.go.tito.io environment "staging" -> ""
2026/10/24 20:29:42 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 20:29:42 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 20:29:42 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 20:29:42 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 20:29:42 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 20:29:42 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 20:29:42 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 20:29:42 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 20:29:42 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 20:29:42 provision: dry-run: would mint instance route acme.go.tito.io (app "tito" acct "bac" channel "stable")
2026/10/24 20:29:42 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 20:29:42 provision: dry-run: would converge adopt.go.tito.io channel stable -> edge
2026/10/24 20:29:42 provision: dry-run: would converge adopt.go.tito.io environment "" -> "staging"
2026/10/24 20:29:42 provision: dry-run: would converge owned.go.tito.io channel stable -> edge
2026/10/24 20:29:42 provision: dry-run: would converge owned.go.tito.io environment "" -> "staging"
2026/10/24 20:29:42 provision: dry-run: would converge owned.go.tito.io hibernate false -> true
2026/10/24 20:29:42 provision: dry-run: would converge owned.go.tito.io seed
2026/10/24 20:29:42 provision: dry-run: would remove retired instance route gone.go.tito.io (record gone)
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: adopted existing route adopt.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 20:29:42 provision: converged adopt.go.tito.io channel stable -> edge
2026/10/24 20:29:42 provision: converged adopt.go.tito.io environment "" -> "staging"
2026/10/24 20:29:42 provision: converged owned.go.tito.io channel stable -> edge
2026/10/24 20:29:42 provision: converged owned.go.tito.io environment "" -> "staging"
2026/10/24 20:29:42 provision: converged owned.go.tito.io hibernate false -> true
2026/10/24 20:29:42 provision: removed retired instance route gone.go.tito.io (record gone)
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: adopted existing route story.carlosframework.com (app "story" acct "bad") — this record now owns its channel and environment
2026/10/24 20:29:42 provision: story.carlosframework.com exists but is not the route this record describes (kind "instance"/"static") — leaving it alone
2026/10/24 20:29:42 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted service route pub.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted service route pubs.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted service route named.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted service route priv.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted instance route unit.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted instance route exec.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted service route loop.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted static route pisite.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: removed retired static route site.go.tito.io (record gone)
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted instance route acme-uk.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: converged acme.go.tito.io replicas "ie,uk" -> "uk"
2026/10/24 20:29:42 provision: converged acme.go.tito.io replicas "uk" -> ""
2026/10/24 20:29:42 provision: minted instance route acme-uk.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: converged acme-uk.go.tito.io replica mark true -> false
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 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 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:42 provision: acme.go.tito.io: not minting this pass: the box's layout intent could not be read: store down
2026/10/24 20:29:42 provision: router.go.tito.io: not minting this pass: the box's layout intent could not be read: store down
2026/10/24 20:29:42 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 20:29:42 provision: converged acme.go.tito.io channel stable -> edge
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io held landing by mv_acme (app "tito" acct "bac")
2026/10/24 20:29:42 provision: not removing acme.go.tito.io (record gone): participant of a running operation
2026/10/24 20:29:42 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 20:29:42 provision: minted instance route acme.go.tito.io held landing by mv_acme (app "tito" acct "bac")
2026/10/24 20:29:42 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 20:29:42 provision: held acme.go.tito.io landing by mv_acme (was ready)
2026/10/24 20:29:42 provision: acme.go.tito.io: held restoring by rb_other, not by mv_acme; leaving it
2026/10/24 20:29:42 provision: acme.go.tito.io: the row is not this pass's (app "other" acct ""); not holding it for mv_acme
2026/10/24 20:29:42 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 20:29:42 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 20:29:43 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 20:29:43 provision: held acme.go.tito.io landing by mv_acme (was ready)
2026/10/24 20:29:43 provision: minted instance route acme.example.com (app "shop" acct "bac")
2026/10/24 20:29:43 provision: minted instance route plain.example.com (app "shop" acct "bac")
2026/10/24 20:29:43 provision: skipping record apps/bac/shop/instances/garbled.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:43 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 20:29:43 provision: skipping record apps/bac/shop/instances/garbled.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:43 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 20:29:43 provision: skipping record apps/bac/shop/instances/garbled.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:43 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 20:29:43 provision: skipping record apps/bac/shop/instances/garbled.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:43 provision: listing apps/bac/shop/instances/: list refused — its records are unseen this pass
2026/10/24 20:29:43 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:43 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:43 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 20:29:43 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:43 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 20:29:44 provision: minted sidecar route bot.shop.bac.sidecar.internal (app "shop" acct "bac" args ["run"])
2026/10/24 20:29:44 provision: removed retired sidecar route bot.shop.bac.sidecar.internal (record gone)
2026/10/24 20:29:44 provision: minted sidecar route bot.shop.bum.sidecar.internal (app "shop" acct "bum" args ["run"])
2026/10/24 20:29:44 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 20:29:44 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 20:29:44 provision: minted sidecar route bot.shop.bum.sidecar.internal (app "shop" acct "bum" args ["run"])
2026/10/24 20:29:44 provision: removed retired sidecar route bot.shop.bum.sidecar.internal (record gone)
2026/10/24 20:29:44 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 20:29:44 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 20:29:44 provision: removed retired sidecar route bot.shop.bum.sidecar.internal (record gone)
2026/10/24 20:29:44 provision: a.shop.example.com: swapped for import sd_g72jnxizizr4wcjmvts33imun4 (the original route is journaled)
2026/10/24 20:29:44 provision: a.shop.example.com: import sd_g72jnxizizr4wcjmvts33imun4 committed: its gate is cleared and its journal row dropped
2026/10/24 20:29:44 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 20:29:44 provision: a.shop.example.com: import sd_5u7qfneijweghpjdloi4gn6l2e rolled back to its original route
2026/10/24 20:29:44 provision: a.shop.example.com: import sd_5u7qfneijweghpjdloi4gn6l2e: the host's replica is left alone: the record apps/bac/shop/instances/a.shop.example.com.json holds the host
2026/10/24 20:29:44 provision: a.shop.example.com: import sd_5u7qfneijweghpjdloi4gn6l2e is cleaned up and its journal row retired
2026/10/24 20:29:44 provision: a.shop.example.com: import sd_eeothyfyldylzdopzcffo2erjm rolled back to its original route
2026/10/24 20:29:44 provision: a.shop.example.com: import sd_eeothyfyldylzdopzcffo2erjm: the host's replica is left alone: the record apps/bac/shop/instances/a.shop.example.com.json holds the host
2026/10/24 20:29:44 provision: a.shop.example.com: import sd_eeothyfyldylzdopzcffo2erjm is cleaned up and its journal row retired
2026/10/24 20:29:44 provision: dry-run: would redo a.shop.example.com's swap record CAS for import sd_zir3m3wlsw2yombh746in26a7m
2026/10/24 20:29:44 provision: dry-run: would clear a.shop.example.com's import gate
2026/10/24 20:29:44 provision: dry-run: would converge a.shop.example.com seed source
2026/10/24 20:29:44 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 20:29:44 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 20:29:44 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 20:29:44 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 20:29:44 provision: a.shop.example.com: import sd_iswdbddz67az3lc3pj34enwsyy cannot roll back on this box: the activator is not wired; it stays journaled and gated
2026/10/24 20:29:44 provision: a.shop.example.com: import sd_pbqh7ryfn7auw7bmdbfwmmvviy cannot roll back on this box: the activator is not wired; it stays journaled and gated
2026/10/24 20:29:44 provision: a.shop.example.com: import sd_oighk4o64ztwh7ycz2iyyrjxny is journaled, but this box cannot act on imports; its row is left alone
2026/10/24 20:29:44 provision: a.shop.example.com: import sd_yz4ij6bctrxvkfirok7mex6yhu is journaled, but this box cannot act on imports; its row is left alone
2026/10/24 20:29:44 provision: a.shop.example.com: import sd_6zi2cvcyfi7be7wevvlo3tav2u is journaled, but this box cannot act on imports; its row is left alone
2026/10/24 20:29:44 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 20:29:44 provision: b.shop.example.com: import sd_vrocfix6z67vtzx573yf6ucn7q left alone this pass: the import journal could not be read
2026/10/24 20:29:44 provision: c.shop.example.com: import sd_e6ycf3tsbgtz4yn6roekmsyice left alone this pass: the import journal could not be read
2026/10/24 20:29:44 provision: a.shop.example.com: import sd_vy3mucpz3datub7p34hpwnwtaa committed: its gate is cleared and its journal row dropped
2026/10/24 20:29:44 provision: a.shop.example.com: not converging import sd_ivigqljsfnqr73ghwozmv4coqq: it is swapped but not committed, and the row on this box has no import gate
2026/10/24 20:29:44 provision: a.shop.example.com: not converging import sd_m2upah33cfgesibrw6kq6cbpm4: it is swapped but not committed, and the row on this box has no import gate
2026/10/24 20:29:44 provision: a.shop.example.com: not converging import sd_5q4bjcayatgzsxxjxe6ceiqakm: it is placed but not committed, and the row on this box has no import gate
2026/10/24 20:29:44 provision: a.shop.example.com: not converging import sd_buc3ogszw2p2qmgce36pjtcgea: it is placed but not committed, and the row on this box has no import gate
2026/10/24 20:29:44 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 20:29:44 provision: converge seed source on a.shop.example.com: constraint failed: seed_source is read-only here (1811)
2026/10/24 20:29:44 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 20:29:45 provision: a.shop.example.com: import sd_chinkbf5frli7pgqbbmhpsbj2q committed: its gate is cleared and its journal row dropped
2026/10/24 20:29:45 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 20:29:45 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:45 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 20:29:45 provision: acme.go.tito.io: not minting a seeded instance: this box does not mint nested (<nil>)
2026/10/24 20:29:45 provision: acme.go.tito.io: not minting a seeded instance: claim control is on for this box
2026/10/24 20:29:45 provision: acme.go.tito.io: aborted seed sd_oqjraavya6j3bm5xljaccxzvye: this box cannot read seed markers, and places no seed; nothing local is removed
2026/10/24 20:29:45 provision: acme.go.tito.io: aborted seed sd_oqjraavya6j3bm5xljaccxzvye rolled back (no box had swapped it)
2026/10/24 20:29:45 provision: acme.go.tito.io: not minting a seeded instance: its record does not describe a hibernating instance
2026/10/24 20:29:45 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:45 provision: removed instance route acme.go.tito.io (its seed sd_tm6kwliwjssg42wxw26r2zybu4 was aborted); the next pass rolls it back
2026/10/24 20:29:45 provision: acme.go.tito.io: aborted seed sd_tm6kwliwjssg42wxw26r2zybu4: this box cannot read seed markers, and places no seed; nothing local is removed
2026/10/24 20:29:45 provision: acme.go.tito.io: aborted seed sd_tm6kwliwjssg42wxw26r2zybu4 rolled back (no box had swapped it)
2026/10/24 20:29:45 provision: acme.go.tito.io: aborted seed sd_5mz7b3eenvz5t7r564ljn3afeu has a row this pass may not remove; leaving the seed aborted
2026/10/24 20:29:45 provision: acme.go.tito.io: aborted seed sd_verknp37przx57g5rhjjs22wwm rolled back (no box had swapped it)
2026/10/24 20:29:45 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:45 provision: removed instance route acme.go.tito.io (its seed sd_mvpvnaopnj2rehz35qlkvedjhq was aborted); the next pass rolls it back
2026/10/24 20:29:45 provision: acme.go.tito.io: aborted seed sd_mvpvnaopnj2rehz35qlkvedjhq has no route on this box: its local data is removed
2026/10/24 20:29:45 provision: acme.go.tito.io: aborted seed sd_mvpvnaopnj2rehz35qlkvedjhq rolled back (no box had swapped it)
2026/10/24 20:29:45 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_gzdbjnzrexwf3jopfmtykorlmq (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_gzdbjnzrexwf3jopfmtykorlmq rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_gzdbjnzrexwf3jopfmtykorlmq is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_ahjg4ue6pdptdr2rpw5fnaxw3u (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_ahjg4ue6pdptdr2rpw5fnaxw3u rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_ahjg4ue6pdptdr2rpw5fnaxw3u is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_ur4zaz3u4vyk5oh67p4p3dsjbm (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_ur4zaz3u4vyk5oh67p4p3dsjbm rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_ur4zaz3u4vyk5oh67p4p3dsjbm: the host's replica is left alone: its record no longer names this seed
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_ur4zaz3u4vyk5oh67p4p3dsjbm is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_m5kpugdrnwhnbnl2mybfmkerwu (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_m5kpugdrnwhnbnl2mybfmkerwu rollback deferred: the host is not fenced and stopped yet (<nil>)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_m5kpugdrnwhnbnl2mybfmkerwu rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_m5kpugdrnwhnbnl2mybfmkerwu is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_zrzn45q3ueqrgjxw24rhg6cvma (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_zrzn45q3ueqrgjxw24rhg6cvma rollback deferred: the host is not fenced and stopped yet (stop unproven)
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_rcslyezncpjp3z7fecritleoqe (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_rcslyezncpjp3z7fecritleoqe is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_4hqmocwaoz7fmdhoq4tgyehxzy (the original route is journaled)
2026/10/24 20:29:45 provision: skipping record apps/bac/shop/instances/a.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_4hqmocwaoz7fmdhoq4tgyehxzy left alone this pass: its record could not be read
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_ne5s43nyak46j4fqir6cgb5mhy (the original route is journaled)
2026/10/24 20:29:45 provision: skipping record apps/bac/shop/instances/a.shop.example.com.json: read failed: connection reset
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_ne5s43nyak46j4fqir6cgb5mhy left alone this pass: its record could not be read
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_ps77ppzk4eivrhgl4vd727uknm (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_ps77ppzk4eivrhgl4vd727uknm: close the import gate: constraint failed: injected (1811)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_ps77ppzk4eivrhgl4vd727uknm rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_ps77ppzk4eivrhgl4vd727uknm is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_nwdjr4mvpa7whz3dyozpwounou (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_nwdjr4mvpa7whz3dyozpwounou: close the import gate: constraint failed: injected (1811)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_nwdjr4mvpa7whz3dyozpwounou rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_nwdjr4mvpa7whz3dyozpwounou is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_3ydoownjdipz7q5xjbyn7jwjua (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_3ydoownjdipz7q5xjbyn7jwjua rollback deferred: the host is not fenced and stopped yet (injected failure at fence)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_3ydoownjdipz7q5xjbyn7jwjua rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_3ydoownjdipz7q5xjbyn7jwjua is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_kooui3zh2xahdj4tqnlgab3ulu (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_kooui3zh2xahdj4tqnlgab3ulu rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_kooui3zh2xahdj4tqnlgab3ulu is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_mmnrj67kt36qpcq6gib6nrhrce (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_mmnrj67kt36qpcq6gib6nrhrce: retire its instance key: injected failure at retire-key
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_mmnrj67kt36qpcq6gib6nrhrce rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_mmnrj67kt36qpcq6gib6nrhrce is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_np7few46jweaujx6vmrpqjp52m (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_np7few46jweaujx6vmrpqjp52m rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_np7few46jweaujx6vmrpqjp52m is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_orlns6ujhbh3bbhqimxgwygmga (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_orlns6ujhbh3bbhqimxgwygmga: remove its local data: injected failure at remove-local
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_orlns6ujhbh3bbhqimxgwygmga rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_orlns6ujhbh3bbhqimxgwygmga is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_4lkn2zbwx57yfogtapf6sm23wy (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_4lkn2zbwx57yfogtapf6sm23wy rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_4lkn2zbwx57yfogtapf6sm23wy is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_fyhh6dpvzhfoqze27hbjviwryy (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_fyhh6dpvzhfoqze27hbjviwryy: remove its local data: injected failure at remove-local-done
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_fyhh6dpvzhfoqze27hbjviwryy rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_fyhh6dpvzhfoqze27hbjviwryy is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_m2k3gwlcyjmt2p7qdzj776rcse (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_m2k3gwlcyjmt2p7qdzj776rcse rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_m2k3gwlcyjmt2p7qdzj776rcse is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_zjxfawcvpt6mgf4grmvzid2v3a (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_zjxfawcvpt6mgf4grmvzid2v3a: restore the original route: constraint failed: injected (1811)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_zjxfawcvpt6mgf4grmvzid2v3a rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_zjxfawcvpt6mgf4grmvzid2v3a is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_hvd2mltadsvgq6tcfntflrh5yi (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_hvd2mltadsvgq6tcfntflrh5yi: restore the original route: constraint failed: injected (1811)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_hvd2mltadsvgq6tcfntflrh5yi rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_hvd2mltadsvgq6tcfntflrh5yi is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_nbficzadpvhiq7bkjywozmmmom (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_nbficzadpvhiq7bkjywozmmmom is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_y3fb6fhfwcj5vdkagd5ejcufr4 (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_y3fb6fhfwcj5vdkagd5ejcufr4 rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_y3fb6fhfwcj5vdkagd5ejcufr4: delete its snapshot: injected failure at delete-snapshot
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_y3fb6fhfwcj5vdkagd5ejcufr4 is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_2qk423nc2oefzwbrjubxsjx6aq (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_2qk423nc2oefzwbrjubxsjx6aq rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_2qk423nc2oefzwbrjubxsjx6aq is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_yovl7eyzauqfbcl3jz2bzbjaim (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_yovl7eyzauqfbcl3jz2bzbjaim rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_yovl7eyzauqfbcl3jz2bzbjaim: delete the host's replica: injected failure at delete-replica
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_yovl7eyzauqfbcl3jz2bzbjaim is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_5ze5vqqjhfi3y3ahbjkz4mxpbi (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_5ze5vqqjhfi3y3ahbjkz4mxpbi rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_5ze5vqqjhfi3y3ahbjkz4mxpbi is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_7gdgpuzqeakabahx65dsfrlw5y (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_7gdgpuzqeakabahx65dsfrlw5y rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_7gdgpuzqeakabahx65dsfrlw5y: retire its journal row: constraint failed: injected (1811)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_7gdgpuzqeakabahx65dsfrlw5y is cleaned up and its journal row retired
2026/10/24 20:29:45 provision: a.shop.example.com: swapped for import sd_f5dvvyke6n2prduzqndyypil2m (the original route is journaled)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_f5dvvyke6n2prduzqndyypil2m rolled back to its original route
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_f5dvvyke6n2prduzqndyypil2m: retire its journal row: constraint failed: injected (1811)
2026/10/24 20:29:45 provision: a.shop.example.com: import sd_f5dvvyke6n2prduzqndyypil2m is cleaned up and its journal row retired
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_os65ynxfrj5bcryjjejcap74ou (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_os65ynxfrj5bcryjjejcap74ou rolled back to its original route
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_os65ynxfrj5bcryjjejcap74ou is cleaned up and its journal row retired
2026/10/24 20:29:46 provision: a.shop.example.com: mark import sd_os65ynxfrj5bcryjjejcap74ou rolled back: injected failure at cas
2026/10/24 20:29:46 provision: a.shop.example.com: aborted seed sd_os65ynxfrj5bcryjjejcap74ou rolled back (no box had swapped it)
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_ksj2yooqnomnhmplly7hnd436m (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_ksj2yooqnomnhmplly7hnd436m rolled back to its original route
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_ksj2yooqnomnhmplly7hnd436m is cleaned up and its journal row retired
2026/10/24 20:29:46 provision: a.shop.example.com: aborted seed sd_ksj2yooqnomnhmplly7hnd436m rolled back (no box had swapped it)
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_ms2ryopli44c3vc6afouafrhom (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_ms2ryopli44c3vc6afouafrhom rollback deferred: the host is not fenced and stopped yet (<nil>)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_ms2ryopli44c3vc6afouafrhom rollback deferred: the host is not fenced and stopped yet (<nil>)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_ms2ryopli44c3vc6afouafrhom rolled back to its original route
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_ms2ryopli44c3vc6afouafrhom is cleaned up and its journal row retired
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_jfkzr3wguttoi3o73aktohoqfe (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_jfkzr3wguttoi3o73aktohoqfe rolled back to its original route
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_jfkzr3wguttoi3o73aktohoqfe is cleaned up and its journal row retired
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_kcyx4fauduhxblnvle32qxd3hi (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_kcyx4fauduhxblnvle32qxd3hi rolled back to its original route
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_kcyx4fauduhxblnvle32qxd3hi is cleaned up and its journal row retired
2026/10/24 20:29:46 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_perp4krxqktsqeuybe3pltgmey (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_perp4krxqktsqeuybe3pltgmey rolled back to its original route
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_perp4krxqktsqeuybe3pltgmey is cleaned up and its journal row retired
2026/10/24 20:29:46 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_rv2z3m3y6xhw2sgp5jglvu7exy (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_rv2z3m3y6xhw2sgp5jglvu7exy rolled back to its original route
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_rv2z3m3y6xhw2sgp5jglvu7exy is cleaned up and its journal row retired
2026/10/24 20:29:46 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_e32phwuplwivzxxl2ws25yd34y (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_e32phwuplwivzxxl2ws25yd34y rolled back to its original route
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_e32phwuplwivzxxl2ws25yd34y is cleaned up and its journal row retired
2026/10/24 20:29:46 provision: minted instance route a.shop.example.com (app "other" acct "bac")
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_zwql7wsgorpsj2donaogulujoa (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_zwql7wsgorpsj2donaogulujoa rolled back to its original route
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_zwql7wsgorpsj2donaogulujoa is cleaned up and its journal row retired
2026/10/24 20:29:46 provision: minted instance route a.shop.example.com (app "other" acct "bac")
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_tkdxdc7mqg6vn6wugdibsnslya (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_tkdxdc7mqg6vn6wugdibsnslya rolled back to its original route
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_tkdxdc7mqg6vn6wugdibsnslya is cleaned up and its journal row retired
2026/10/24 20:29:46 provision: minted instance route a.shop.example.com (app "other" acct "bac")
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_ffzzjplrwwwwdvc7g4puv7qyte (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_ffzzjplrwwwwdvc7g4puv7qyte has no route on this box: its local data is removed and no route is put back
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_ffzzjplrwwwwdvc7g4puv7qyte is cleaned up and its journal row retired
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_wqgm5r7nm4xkharp3t2cmyzm7e (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_rllokike7oebbbkutsrti7plpe (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_ivba7lemurmyfqfmubuxgsvqae (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_ivba7lemurmyfqfmubuxgsvqae cannot roll back on this box: the activator is not wired; it stays journaled and gated
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_jwabugjbyn6xujhb6aoexfvbu4 (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_jwabugjbyn6xujhb6aoexfvbu4 is not rolled back: the route changed under the fence, so nothing there is touched
2026/10/24 20:29:46 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 20:29:46 provision: a.shop.example.com: import ../not-a-seed is cleaned up and its journal row retired
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_lnuck5davcuhs7d3u2hzx446aa (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_sdeoba7hhz7jefcglcfv42gy64 (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_bqnhhyeimg3wawwxlarsqobdli (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_wvj4vppd32yljo6ma4xtz5rewq (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_ssrkxjwybyrfm6gqedeenfsenq (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_ssrkxjwybyrfm6gqedeenfsenq rollback deferred: the host is not fenced and stopped yet (stop evidence unreadable)
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_ph5legqtagnnrnzzfxxtcrwyze (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_ph5legqtagnnrnzzfxxtcrwyze has no route on this box: its local data is removed and no route is put back
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_ph5legqtagnnrnzzfxxtcrwyze is cleaned up and its journal row retired
2026/10/24 20:29:46 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_wiwtegshyia6jjecemmlp66mba (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_wiwtegshyia6jjecemmlp66mba: remove its local data: injected failure at remove-local
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_wiwtegshyia6jjecemmlp66mba is not rolled back: the route at the host is not the import's, so nothing there is touched
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_aflzkvq6xyosvtzecbk3sgj7vm (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_aflzkvq6xyosvtzecbk3sgj7vm: a route appeared at the host, so its local database is left and the rollback waits
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_u4gjyqygtjzekboqdcybabpj3q (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_u4gjyqygtjzekboqdcybabpj3q rollback deferred: no fence generation: registry busy
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_c57tqaydyk2qea5guur7pd4ylm (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_c57tqaydyk2qea5guur7pd4ylm rollback deferred: no fence generation: the generation source answered 0
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_cm5ipdhk5uzic53t2di7pm2on4 (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_vfdo6p3wkya6vwxvhyjac4hgwy (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_womlffc2kso75awibzemwxyczy (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import deferred: this box cannot read the instance's env file
2026/10/24 20:29:46 provision: a.shop.example.com: import deferred: the instance's env file could not be read: a symlink
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_gfnx73rmmtmf2he5c3qxiploqy (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_gfnx73rmmtmf2he5c3qxiploqy rolled back to its original route
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_gfnx73rmmtmf2he5c3qxiploqy is cleaned up and its journal row retired
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_hg4hliqejp2jv2mzryks3yo5em (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_hg4hliqejp2jv2mzryks3yo5em rolled back to its original route
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_hg4hliqejp2jv2mzryks3yo5em is cleaned up and its journal row retired
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_5abdwefialwll5765e5xlyt2na (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_5abdwefialwll5765e5xlyt2na rolled back to its original route
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_5abdwefialwll5765e5xlyt2na is cleaned up and its journal row retired
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_wqgckw3tqocg3fswnffyu65qs4 (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_wqgckw3tqocg3fswnffyu65qs4: retire its instance key: the env file is a symlink
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_wqgckw3tqocg3fswnffyu65qs4 rolled back to its original route
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_wqgckw3tqocg3fswnffyu65qs4 is cleaned up and its journal row retired
2026/10/24 20:29:46 provision: a.shop.example.com: swapped for import sd_mq4ame5ya4fbooevtzsbljbcsu (the original route is journaled)
2026/10/24 20:29:46 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 20:29:46 provision: a.shop.example.com: swapped for import sd_sfmrsgza57eotruwqtoob6nuwy (the original route is journaled)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_m4ivafxqzdrr4hdfxvrjcsdbvu refused: there is no route at a.shop.example.com to replace
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_bajlfu25t5cjjclxfv3yt7i55q refused: the route's address is 127.0.0.1:9, not 127.0.0.1:8401
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_lt5yvsvd4lvmug376jsz6pvlxi 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 20:29:46 provision: a.shop.example.com: import sd_72us3h44hkhw3bg7qbnrc3jnim refused: the route's address is 127.0.0.1:9, not 127.0.0.1:8401
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_s5zdrxtunlcjgwtfa52p2woluu refused: the route belongs to app other
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_rveowhay3vfeabkc4xqxha5uwe refused: the route is filed under another account
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_cg3qlzypoa55ejnsbgtq3yon7y refused: the route is filed under the operator account, and no assignment maps shop to this app
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_x3rquen74hnvftrve6saycex64 refused: the route is filed under the operator account, and no assignment maps shop to this app
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_lwgg7pkpk5prnx6pcm5juwasbi refused: the route is filed under the operator account, and no assignment maps shop to this app
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_yzp6zfytzaqr5gixr3r5umzlnu refused: the route is filed under the operator account, and no assignment maps shop to this app
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_rxrmfbk3rg5fytj46npcpau6ve refused: the route is not an address route this import can take over (socket)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_okmlfqoqx7dcpwtbcvkak2pd4u refused: the route is not an address route this import can take over (no address)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_gztyuv4lag43pc2yh54lfqm5u4 refused: the route is not an address route this import can take over (provisioned)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_d2b5zriejcvd422vu45t6njhyy refused: the route is not an address route this import can take over (kind static)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_srzqb5gxeb6v7z3y7i72zn6v7e refused: the route is not an address route this import can take over (backing)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_ioqu7mkzse6cby5wmpa554hwxy refused: the route is not an address route this import can take over (tunnel)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_yq4lvqoe6uedjjqxd7lplcynmm refused: the route is not an address route this import can take over (caps)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_znnvpshzidu2ag27r5bkzjv7ua refused: the route is not an address route this import can take over (platform)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_acni7txdqj236eojll2pz3j2xu refused: the route is not an address route this import can take over (canary)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_gkzy523k37lwfky3uhnrboxduu refused: the route is not an address route this import can take over (kind sidecar)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_qix4rsjo2dxge3iy7ldz33gsaa refused: the route is not an address route this import can take over (region)
2026/10/24 20:29:46 provision: a.shop.example.com: import sd_wam2vijiailcmhr7tbxvqnexiy refused: the route is not an address route this import can take over (fleet_box)
2026/10/24 20:29:47 provision: a.shop.example.com: import sd_v6mhznnlh2q3e7a4kga43xsrfu refused: the route is not an address route this import can take over (hibernate)
2026/10/24 20:29:47 provision: a.shop.example.com: import sd_24tvx5bmsktafbq7coda5nnvam refused: the route is not an address route this import can take over (claim_owner)
2026/10/24 20:29:47 provision: a.shop.example.com: import sd_sfv3trormygb6ye62eeaiks4mi refused: this box does not run instances nested
2026/10/24 20:29:47 provision: a.shop.example.com: import sd_fmunjgorspmlyax4kxpqnrur4i refused: this box does not run instances nested
2026/10/24 20:29:47 provision: a.shop.example.com: import sd_pzk6iosp2avszduiecm4hq5dka refused: claim control is on for this box
2026/10/24 20:29:47 provision: a.shop.example.com: swapped for import sd_shlvdstfpvqig5fqi4seh7c43y (the original route is journaled)
2026/10/24 20:29:47 provision: a.shop.example.com: swapped for import sd_pleoomsmhdem6ju7ypfptffnrm (the original route is journaled)
2026/10/24 20:29:47 provision: a.shop.example.com: import deferred: this box cannot read the legacy route assignments
2026/10/24 20:29:47 provision: a.shop.example.com: import deferred: the legacy route assignments could not be read: store down
2026/10/24 20:29:47 provision: a.shop.example.com: not swapping for import sd_g2cmulz6lofdgjuwvkccyduo4m: its verify hash is not a sha256
2026/10/24 20:29:47 provision: a.shop.example.com: not swapping for import sd_tpfnrkdsloppemdwtvnu4oe5je: its verify hash is not a sha256
2026/10/24 20:29:47 provision: a.shop.example.com: not swapping for import sd_luaj7nei4o4pmavqxvnjziu73u: its verify hash is not a sha256
2026/10/24 20:29:47 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 20:29:47 provision: A.shop.example.com/..: not swapping for import sd_64b42ght2wbattpvjza6xnnsyi: its host or seed id is malformed (seeds: not a host)
2026/10/24 20:29:47 provision: a.shop.example.com: not swapping for import sd_h5o5k5jq7qf24rcefp4ekj3cna: its record does not describe a nested, hibernating instance
2026/10/24 20:29:47 provision: a.shop.example.com: not swapping for import sd_uwsz2x7pzz5pc2gt5y6stbxuva: its record does not describe a nested, hibernating instance
2026/10/24 20:29:47 provision: a.shop.example.com: not swapping for import sd_c4m3hthqr3prppbkprotjc5l4y: its record does not describe a nested, hibernating instance
2026/10/24 20:29:47 provision: a.shop.example.com: not swapping for import sd_zgivefmmv7i42xrvaqu3g42ldy: its record does not describe a nested, hibernating instance
2026/10/24 20:29:47 provision: a.shop.example.com: import deferred: the box's layout intent could not be read: store down
2026/10/24 20:29:47 provision: a.shop.example.com: swapped for import sd_4lrihbq3p3t7vul5x25ipti6ki (the original route is journaled)
2026/10/24 20:29:47 provision: a.shop.example.com: import deferred: the box's nested probe did not answer: ready probe timed out
2026/10/24 20:29:47 provision: a.shop.example.com: swapped for import sd_wifb67lhgv6xy3x65jus442dky (the original route is journaled)
2026/10/24 20:29:47 provision: a.shop.example.com: swapped for import sd_rpkab5zuaboobfhrmi2laiakva (the original route is journaled)
2026/10/24 20:29:47 provision: a.shop.example.com: import deferred: the route is held by operation op_1
2026/10/24 20:29:47 provision: dry-run: would consider swapping a.shop.example.com for import sd_ktymb5rx43sohb6crfqwsqrfza
2026/10/24 20:29:47 provision: a.shop.example.com: import sd_z4wo2il6yzreg56g46ko2fb664 rolled back to its original route
2026/10/24 20:29:47 provision: a.shop.example.com: import sd_z4wo2il6yzreg56g46ko2fb664: the host's replica is left alone: the record apps/bac/shop/instances/a.shop.example.com.json holds the host
2026/10/24 20:29:47 provision: a.shop.example.com: import sd_z4wo2il6yzreg56g46ko2fb664 is cleaned up and its journal row retired
2026/10/24 20:29:47 provision: a.shop.example.com: import sd_72x64mw4fikc57ses7vwh2ewjm left alone: the import journal holds seed sd_457g3kvfetskrgb4amoj4purlm at swapped
2026/10/24 20:29:47 provision: a.shop.example.com: not minting import sd_hnkv2k2vz6kjjva6fu4nhrq2qq: it is swapped but not committed, and only its swap makes its row
2026/10/24 20:29:47 provision: a.shop.example.com: not minting import sd_yoekpuyubpryo4gijtn7p2erbe: it is placed but not committed, and only its swap makes its row
2026/10/24 20:29:47 provision: a.shop.example.com: swapped for import sd_mcl7qhxwwuehezqjkgsuyudere (the original route is journaled)
2026/10/24 20:29:47 provision: a.shop.example.com: not minting import sd_mcl7qhxwwuehezqjkgsuyudere: it is swapped but not committed, and only its swap makes its row
2026/10/24 20:29:47 provision: a.shop.example.com: not minting import sd_mcl7qhxwwuehezqjkgsuyudere: it is placed but not committed, and only its swap makes its row
2026/10/24 20:29:47 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 20:29:47 provision: removed retired sidecar route gone.eleven.bac.sidecar.internal (record gone)
2026/10/24 20:29:47 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 20:29:47 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 20:29:47 provision: converged sidecar bot.eleven.bac.sidecar.internal args ["sidecar","run"] -> ["worker","run"]
2026/10/24 20:29:47 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 20:29:47 provision: converged sidecar bot.eleven.bac.sidecar.internal ceilings 300/3600 -> 60/120
2026/10/24 20:29:47 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 20:29:47 provision: converged sidecar bot.eleven.bac.sidecar.internal channel stable -> canary/eleven
2026/10/24 20:29:47 provision: converged sidecar bot.eleven.bac.sidecar.internal environment "other" -> "relay"
2026/10/24 20:29:47 provision: converged sidecar bot.eleven.bac.sidecar.internal hibernate true -> false
2026/10/24 20:29:47 provision: skipping sidecar record apps/bac/eleven/sidecars/bot.json: read failed: failStore: reads disabled under apps/bac/eleven/sidecars/
2026/10/24 20:29:47 provision: skipping sidecar record apps/bac/eleven/sidecars/bot.json: malformed: invalid character 'n' looking for beginning of object key string
2026/10/24 20:29:47 provision: not removing sidecar bot.eleven.bac.sidecar.internal: its record exists but could not be read cleanly this pass
2026/10/24 20:29:47 provision: skipping sidecar record apps/bac/eleven/sidecars/bot.json: empty channel
2026/10/24 20:29:47 provision: skipping sidecar record apps/bac/eleven/sidecars/held.json: empty channel
2026/10/24 20:29:47 provision: not removing sidecar held.eleven.bac.sidecar.internal: its record exists but could not be read cleanly this pass
2026/10/24 20:29:47 provision: removed retired sidecar route old.eleven.bac.sidecar.internal (record gone)
2026/10/24 20:29:47 provision: bac/eleven has sidecar records but no sidecars manifest — not minting
2026/10/24 20:29:47 provision: bac/eleven is in the trash — not minting sidecar routes for it
2026/10/24 20:29:47 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 20:29:47 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 20:29:47 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 20:29:47 provision: minted sidecar route hub.relay.bac.sidecar.internal (app "relay" acct "bac" args ["relay"])
2026/10/24 20:29:47 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 20:29:47 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 20:29:47 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 20:29:47 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 20:29:47 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 20:29:47 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 20:29:47 provision: removed retired sidecar route bot.eleven.bac.sidecar.internal (record gone)
2026/10/24 20:29:47 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 20:29:47 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 20:29:47 provision: skipping sidecar record apps/bac/relay/sidecars/hub.json: read failed: failStore: reads disabled under apps/bac/relay/sidecars/
2026/10/24 20:29:47 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 20:29:47 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 20:29:47 provision: dry-run: would mint sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" channel "stable" args ["sidecar","run"])
2026/10/24 20:29:47 provision: dry-run: would remove retired sidecar route gone.eleven.bac.sidecar.internal (record gone)
2026/10/24 20:29:47 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 20:29:47 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:47 provision: converged acme.go.tito.io update settings "{\"updates\":\"manual\",\"channel\":\"stable\"}" -> ""
2026/10/24 20:29:47 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:47 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:47 provision: manifest bac/tito: read failed: provision: manifest bac/tito: unexpected end of JSON input
2026/10/24 20:29:47 provision: manifest bac/tito: read failed: provision: manifest bac/tito: unexpected end of JSON input
2026/10/24 20:29:47 provision: acme.go.tito.io: not minted this pass: the app's update policy could not be read
2026/10/24 20:29:47 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 20:29:47 provision: manifest bac/tito: read failed: provision: manifest bac/tito: unexpected end of JSON input
2026/10/24 20:29:47 provision: acme.go.tito.io: not minted this pass: the app's update policy could not be read
2026/10/24 20:29:47 provision: minted instance route acme.go.tito.io held landing by mv_acme (app "tito" acct "bac")
2026/10/24 20:29:47 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 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 20:29:47 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 20:29:47 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 20:29:47 provision: record view: change index unusable (release: change index malformed: invalid character 'n' looking for beginning of object key string): walking
2026/10/24 20:29:47 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 20:29:47 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 20:29:47 provision: record view: re-reading apps/bqc/shop failed: retrying on the next refresh
2026/10/24 20:29:47 provision: listing apps/bqc/shop/instances/: context canceled — its records are unseen this pass
2026/10/24 20:29:47 provision: record view: change index unusable (get refused): walking
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: record view: re-reading apps/bqc/shop failed: retrying on the next refresh
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: listing apps/bqc/shop/instances/: list refused — its records are unseen this pass
2026/10/24 20:29:47 provision: listing apps/bqc/shop/instances/: list refused — its records are unseen this pass
2026/10/24 20:29:47 provision: an app's records could not be listed: they are skipped
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping accounts/bqd/account.json: malformed account manifest: invalid character 'n' looking for beginning of object key string
2026/10/24 20:29:47 provision: skipping accounts/bqd/account.json: malformed account manifest: invalid character 'n' looking for beginning of object key string
2026/10/24 20:29:47 provision: skipping accounts/bqd/account.json: malformed account manifest: invalid character 'n' looking for beginning of object key string
2026/10/24 20:29:47 provision: record view: re-reading accounts/bqd failed: retrying on the next refresh
2026/10/24 20:29:47 provision: skipping accounts/bqd/account.json: read failed: list refused
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: minted instance route one.example.com (app "shop" acct "bum")
2026/10/24 20:29:47 provision: removed retired instance route one.example.com (record gone)
2026/10/24 20:29:47 provision: minted instance route one.example.com (app "shop" acct "bum")
2026/10/24 20:29:47 provision: minted instance route one.example.com (app "shop" acct "bum")
2026/10/24 20:29:47 provision: skipping record apps/bum/shop/instances/one.example.com.json: empty channel
2026/10/24 20:29:47 provision: not removing one.example.com: its record exists but could not be read cleanly this pass
2026/10/24 20:29:47 provision: skipping record apps/bum/shop/instances/one.example.com.json: empty channel
2026/10/24 20:29:47 provision: not removing one.example.com: its record exists but could not be read cleanly this pass
2026/10/24 20:29:47 provision: removed retired instance route one.example.com (record gone)
2026/10/24 20:29:47 provision: record view: change index unusable (context deadline exceeded): walking
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 20:29:47 provision: record view: change index unusable (context deadline exceeded): the walk records no generations
2026/10/24 20:29:47 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
--- FAIL: TestPlan14RootReadCensus (21.23s)
plan14_root_reads_test.go:600: root read census: 3 discrepancies
changed root source envelope internal/release
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
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 29.801s
ok github.com/carlosframework/platform/internal/publicrelease 0.009s
? github.com/carlosframework/platform/internal/regionname [no test files]
ok github.com/carlosframework/platform/internal/registry 5.566s
ok github.com/carlosframework/platform/internal/relay 7.238s
ok github.com/carlosframework/platform/internal/release 25.327s
ok github.com/carlosframework/platform/internal/rollout 3.755s
ok github.com/carlosframework/platform/internal/rolloutwords 0.004s
ok github.com/carlosframework/platform/internal/rootaws 0.007s
ok github.com/carlosframework/platform/internal/rootparticipation 0.064s
ok github.com/carlosframework/platform/internal/rootstate 0.028s
ok github.com/carlosframework/platform/internal/runs 0.580s
ok github.com/carlosframework/platform/internal/s3compat 0.004s
ok github.com/carlosframework/platform/internal/safefile 0.006s
ok github.com/carlosframework/platform/internal/schedule 2.659s
ok github.com/carlosframework/platform/internal/seeds 0.012s
ok github.com/carlosframework/platform/internal/sim/engines 2.569s
ok github.com/carlosframework/platform/internal/sim/hostlife 10.357s
ok github.com/carlosframework/platform/internal/sim/litestreamfacts 3.757s
ok github.com/carlosframework/platform/internal/status 0.077s
ok github.com/carlosframework/platform/internal/steering 0.006s
ok github.com/carlosframework/platform/internal/stopevidence 0.336s
ok github.com/carlosframework/platform/internal/svcrole 0.002s
ok github.com/carlosframework/platform/internal/telemetry 0.004s
ok github.com/carlosframework/platform/internal/termfence 0.005s
ok github.com/carlosframework/platform/internal/tunnelclient 0.004s
ok github.com/carlosframework/platform/internal/unixdial 0.002s
ok github.com/carlosframework/platform/internal/updatewords 0.004s
ok github.com/carlosframework/platform/internal/usage 0.005s
ok github.com/carlosframework/platform/internal/version 0.004s
ok github.com/carlosframework/platform/internal/vet 1.653s
FAIL
=== internal_console@0 (80 s)
ok github.com/carlosframework/platform/internal/console 77.833s
=== internal_console@1 (44 s)
ok github.com/carlosframework/platform/internal/console 42.025s
=== internal_console@2 (41 s)
ok github.com/carlosframework/platform/internal/console 38.580s
=== internal_console@3 (42 s)
ok github.com/carlosframework/platform/internal/console 39.773s
=== internal_console@4 (43 s)
ok github.com/carlosframework/platform/internal/console 40.605s
=== internal_console@5 (42 s)
ok github.com/carlosframework/platform/internal/console 39.753s
=== internal_console@6 (37 s)
ok github.com/carlosframework/platform/internal/console 35.280s
=== internal_console@7 (46 s)
ok github.com/carlosframework/platform/internal/console 43.748s
=== root@0 (105 s)
ok github.com/carlosframework/platform 103.046s
=== root@1 (82 s)
ok github.com/carlosframework/platform 80.078s
=== root@2 (98 s)
ok github.com/carlosframework/platform 96.492s
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 a8810501e..0af2d434f 100644 |
| --- a/approved_rootfs_copy_test.go |
| +++ b/approved_rootfs_copy_test.go |
| @@ -145,7 +145,10 @@ var rootfsCopyStatuses = []string{"pending", "approved", "struck"} |
| // rootfsCopyBuilt is every id whose text the code or docs carry. The task |
| // that writes a row's text adds its id here in the same commit, once Paul |
| // has approved the row. |
| -var rootfsCopyBuilt = []string{} |
| +var rootfsCopyBuilt = []string{ |
| + // Task 2: the manifest's rootfs kind (internal/release/rootfs.go) |
| + "RFS-1-C01", "RFS-1-C02", "RFS-1-C03", "RFS-1-C04", "RFS-1-C05", "RFS-1-C06", "RFS-1-C07", "RFS-1-C08", "RFS-1-C09", "RFS-1-C10", "RFS-1-C11", "RFS-1-C12", "RFS-1-C13", "RFS-1-C14", "RFS-1-C15", "RFS-1-C16", "RFS-1-C17", |
| +} |
| func mustParseRootfsRecord(t *testing.T) []copyRow { |
| t.Helper() |
diff --git a/internal/release/golden_test.go b/internal/release/golden_test.go| index 9dee0fc14..664ad7ace 100644 |
| --- a/internal/release/golden_test.go |
| +++ b/internal/release/golden_test.go |
| @@ -214,6 +214,40 @@ func TestAManifestWithFutureTopLevelKeysStillParses(t *testing.T) { |
| } |
| } |
| +// Yesterday's binary manifest has no processes, hibernate or jit keys. It must |
| +// keep parsing with all three at their zero values, and marshalling it back |
| +// must not grow them: a binary or static manifest stays byte for byte as it |
| +// was (rootfs apps Plan 1, additive wire shape). |
| +func TestYesterdaysManifestParsesWithNoProcesses(t *testing.T) { |
| + yesterday := `{ |
| + "schema": 1, |
| + "app": "kass", |
| + "version": "9f3c1ad", |
| + "kind": "binary", |
| + "commit": "9f3c1ad", |
| + "artifacts": { "linux-arm64": { "file": "linux-arm64", "sha256": "` + strings.Repeat("ab", 32) + `", "size": 12 } } |
| +}` |
| + var m Manifest |
| + if err := json.Unmarshal([]byte(yesterday), &m); err != nil { |
| + t.Fatalf("a manifest written before rootfs apps no longer parses: %v", err) |
| + } |
| + if m.Processes != nil || m.Hibernate || m.JIT { |
| + t.Fatalf("absent keys decoded as processes=%v hibernate=%v jit=%v", m.Processes, m.Hibernate, m.JIT) |
| + } |
| + if err := validateManifest(&m); err != nil { |
| + t.Fatalf("validate: %v", err) |
| + } |
| + out, err := json.MarshalIndent(m, "", " ") |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + for _, key := range []string{`"processes"`, `"hibernate"`, `"jit"`} { |
| + if bytes.Contains(out, []byte(key)) { |
| + t.Errorf("an empty %s leaked into the marshal:\n%s", key, out) |
| + } |
| + } |
| +} |
| + |
| // A manifest from BEFORE the release versioning spec (2026-08-08): no |
| // "label" or "notes" keys at all, same as every manifest already sitting in |
| // a production bucket today. It has to keep parsing, and Label/Notes have to |
diff --git a/internal/release/release.go b/internal/release/release.go| index d77987961..12913c3e1 100644 |
| --- a/internal/release/release.go |
| +++ b/internal/release/release.go |
| @@ -48,7 +48,7 @@ type Manifest struct { |
| Schema int `json:"schema"` // 1 |
| App string `json:"app"` |
| Version string `json:"version"` // git short sha |
| - Kind string `json:"kind"` // "binary" | "static" |
| + Kind string `json:"kind"` // "binary" | "static" | "rootfs" |
| Commit string `json:"commit,omitempty"` |
| BuiltBy string `json:"built_by,omitempty"` |
| BuiltAt string `json:"built_at,omitempty"` |
| @@ -104,6 +104,18 @@ type Manifest struct { |
| // rides the same trust chain as the bytes (signed pointer -> immutable |
| // manifest -> sha256). Spec §3a. |
| Capabilities *caps.Set `json:"capabilities,omitempty"` |
| + |
| + // Processes, Hibernate and JIT are the rootfs kind's fields (rootfs apps |
| + // Plan 1, spec §5): valid only when Kind is "rootfs" and absent from every |
| + // binary and static manifest, which marshal byte for byte as before |
| + // (omitempty). Processes names what the release runs (web, workers, |
| + // release, console). Hibernate is the app's opt-in to sleeping when idle |
| + // (default always on). JIT lifts MemoryDenyWriteExecute for every process |
| + // of the release, for runtimes that compile at run time; Plan 2 reads it |
| + // from the root-staged manifest. |
| + Processes map[string]Process `json:"processes,omitempty"` |
| + Hibernate bool `json:"hibernate,omitempty"` |
| + JIT bool `json:"jit,omitempty"` |
| } |
| // Artifact is one file of a release: its bucket file name and the sha256 |
| @@ -329,8 +341,13 @@ func validateManifest(m *Manifest) error { |
| if !ValidVersion(m.Version) || m.Version == "dev" { |
| return fmt.Errorf("invalid version %q", m.Version) |
| } |
| - if m.Kind != "binary" && m.Kind != "static" { |
| - return fmt.Errorf("invalid kind %q (binary | static)", m.Kind) |
| + switch m.Kind { |
| + case "binary", "static", KindRootfs: |
| + default: |
| + return fmt.Errorf("invalid kind %q (binary | static | rootfs)", m.Kind) |
| + } |
| + if err := validateRootfsShape(m); err != nil { |
| + return err |
| } |
| if len(m.Artifacts) == 0 { |
| return fmt.Errorf("manifest has no artifacts") |
diff --git a/internal/release/rootfs.go b/internal/release/rootfs.go| new file mode 100644 |
| index 000000000..6b20da8c4 |
| --- /dev/null |
| +++ b/internal/release/rootfs.go |
| @@ -0,0 +1,220 @@ |
| +package release |
| + |
| +import ( |
| + "bytes" |
| + "encoding/json" |
| + "errors" |
| + "fmt" |
| + "io" |
| + "path" |
| + "regexp" |
| + "slices" |
| + "strings" |
| + "time" |
| +) |
| + |
| +// The rootfs kind: a release whose artifact is a squashfs root filesystem and |
| +// whose manifest names the processes to run inside it (rootfs apps Plan 1, |
| +// spec §5). The manifest fields below are additive to schema 1 and valid only |
| +// when Kind is KindRootfs. |
| +const ( |
| + KindRootfs = "rootfs" |
| + RootfsArtifactKey = "rootfs-linux-arm64" |
| + RootfsArtifactFile = "rootfs.squashfs" |
| +) |
| + |
| +// The process names. web is required, release and console are optional and |
| +// at most one each, and workers take any other valid name (ValidWorkerName). |
| +const ( |
| + ProcessWeb = "web" |
| + ProcessRelease = "release" |
| + ProcessConsole = "console" |
| + MaxWorkers = 4 |
| +) |
| + |
| +const ( |
| + // DefaultReleaseTimeoutSec applies when the release process sets no |
| + // timeout_sec. MaxReleaseTimeoutSec is the carlos run maximum |
| + // (runs.MaxTimeout, pinned by a test in package runs). |
| + DefaultReleaseTimeoutSec = 600 |
| + MaxReleaseTimeoutSec = 6 * 60 * 60 |
| + // MaxProcessesBytes bounds the JSON encoding of the processes object. |
| + MaxProcessesBytes = 32 << 10 |
| + // MaxRootfsBytes bounds the rootfs image of one release. |
| + MaxRootfsBytes int64 = 2 << 30 |
| + // RootfsHealthTimeout is how long a rootfs web process has to answer its |
| + // first health check. |
| + RootfsHealthTimeout = 120 * time.Second |
| +) |
| + |
| +// Process is one command a rootfs release runs. |
| +type Process struct { |
| + Command []string `json:"command"` |
| + Env map[string]string `json:"env,omitempty"` |
| + WorkingDir string `json:"working_dir,omitempty"` |
| + TimeoutSec int `json:"timeout_sec,omitempty"` // release only |
| +} |
| + |
| +// ErrRootfsFieldsOnly refuses processes, hibernate or jit on a release that |
| +// is not a rootfs release. |
| +var ErrRootfsFieldsOnly = errors.New("processes, hibernate and jit belong to rootfs releases only") |
| + |
| +var ( |
| + errProcessesNull = errors.New("processes: null. a rootfs release needs its processes, starting with web") |
| + errProcessesMalformed = errors.New("malformed processes block. want the processes object: web, any workers, release and console") |
| + |
| + workerNameRe = regexp.MustCompile(`^[a-z][a-z0-9-]{0,15}$`) |
| + envNameRe = regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_]*$`) |
| +) |
| + |
| +// ValidWorkerName reports whether name can name a worker process: lower-case |
| +// letters, digits and hyphens, up to 16 characters, starting with a letter, |
| +// and not one of the names the platform keeps for itself. |
| +func ValidWorkerName(name string) bool { |
| + if !workerNameRe.MatchString(name) { |
| + return false |
| + } |
| + switch name { |
| + case ProcessWeb, ProcessRelease, ProcessConsole, "seed": |
| + return false |
| + } |
| + return true |
| +} |
| + |
| +func sortedKeys[V any](m map[string]V) []string { |
| + keys := make([]string, 0, len(m)) |
| + for k := range m { |
| + keys = append(keys, k) |
| + } |
| + slices.Sort(keys) |
| + return keys |
| +} |
| + |
| +// ValidateProcesses returns the first refusal for a processes object, or nil. |
| +// The order is fixed so one bad object always gets the same sentence: web, |
| +// the names, the worker count, each process in name order, then the size. |
| +func ValidateProcesses(procs map[string]Process) error { |
| + if _, ok := procs[ProcessWeb]; !ok { |
| + return errors.New("the processes declare no web process. a rootfs release needs exactly one, named web") |
| + } |
| + names := sortedKeys(procs) |
| + workers := 0 |
| + for _, name := range names { |
| + switch { |
| + case name == ProcessWeb, name == ProcessRelease, name == ProcessConsole: |
| + case name == "seed": |
| + return fmt.Errorf("%q is reserved, so no process can use that name", name) |
| + case ValidWorkerName(name): |
| + workers++ |
| + default: |
| + return fmt.Errorf("%q is not a process name. use web, release, console, or a worker name: lower-case letters, digits and hyphens, up to 16 characters, starting with a letter", name) |
| + } |
| + } |
| + if workers > MaxWorkers { |
| + return fmt.Errorf("a rootfs release can declare at most 4 worker processes, and this one declares %d", workers) |
| + } |
| + for _, name := range names { |
| + if err := validateProcess(name, procs[name]); err != nil { |
| + return err |
| + } |
| + } |
| + enc, err := json.Marshal(procs) |
| + if err != nil { |
| + return err |
| + } |
| + if len(enc) > MaxProcessesBytes { |
| + return fmt.Errorf("the processes are %d bytes, over the limit of %d", len(enc), MaxProcessesBytes) |
| + } |
| + return nil |
| +} |
| + |
| +func validateProcess(name string, p Process) error { |
| + if len(p.Command) == 0 || p.Command[0] == "" { |
| + return fmt.Errorf("the %s process needs a command: a list of words whose first word is not empty", name) |
| + } |
| + hasNUL := slices.ContainsFunc(p.Command, func(w string) bool { return strings.Contains(w, "\x00") }) || |
| + strings.Contains(p.WorkingDir, "\x00") |
| + for k, v := range p.Env { |
| + hasNUL = hasNUL || strings.Contains(k, "\x00") || strings.Contains(v, "\x00") |
| + } |
| + if hasNUL { |
| + return fmt.Errorf("the %s process contains a NUL byte, which no command or variable can hold", name) |
| + } |
| + for _, k := range sortedKeys(p.Env) { |
| + if !envNameRe.MatchString(k) { |
| + return fmt.Errorf("the %s process sets %q in env, which is not a variable name", name, k) |
| + } |
| + if strings.HasPrefix(k, "CARLOS_") { |
| + return fmt.Errorf("the %s process sets %s in env. names that start with CARLOS_ belong to the platform", name, k) |
| + } |
| + } |
| + if wd := p.WorkingDir; wd != "" && (!path.IsAbs(wd) || path.Clean(wd) != wd) { |
| + return fmt.Errorf("the %s process's working_dir must be an absolute path, and %q is not", name, wd) |
| + } |
| + if p.TimeoutSec != 0 { |
| + if name != ProcessRelease { |
| + return errors.New("only the release process takes timeout_sec") |
| + } |
| + if p.TimeoutSec < 1 || p.TimeoutSec > MaxReleaseTimeoutSec { |
| + return fmt.Errorf("the release process's timeout_sec must be between 1 and %d seconds", MaxReleaseTimeoutSec) |
| + } |
| + } |
| + return nil |
| +} |
| + |
| +// DecodeProcesses reads the processes object strictly: an unknown field, a |
| +// wrong type or trailing data is malformed. Empty input and null both mean |
| +// the object is missing, so the door and the CLI refuse a missing processes |
| +// block with one sentence (preflight 1.13). |
| +func DecodeProcesses(raw []byte) (map[string]Process, error) { |
| + if len(bytes.TrimSpace(raw)) == 0 { |
| + return nil, errProcessesNull |
| + } |
| + dec := json.NewDecoder(bytes.NewReader(raw)) |
| + dec.DisallowUnknownFields() |
| + var procs map[string]Process |
| + if err := dec.Decode(&procs); err != nil { |
| + return nil, errProcessesMalformed |
| + } |
| + if _, err := dec.Token(); err != io.EOF { |
| + return nil, errProcessesMalformed |
| + } |
| + if procs == nil { |
| + return nil, errProcessesNull |
| + } |
| + return procs, nil |
| +} |
| + |
| +// ProcessesEqual compares two processes objects by their canonical JSON |
| +// (encoding/json sorts map keys), as shipCapabilitiesMatch compares |
| +// capability blocks. |
| +func ProcessesEqual(a, b map[string]Process) bool { |
| + ja, errA := json.Marshal(a) |
| + jb, errB := json.Marshal(b) |
| + return errA == nil && errB == nil && bytes.Equal(ja, jb) |
| +} |
| + |
| +// validateRootfsShape is validateManifest's rule for the rootfs fields, run |
| +// right after the kind check. Another kind carries none of them. A rootfs |
| +// release carries exactly its image and its processes: no capability block |
| +// (Plan 5 widens that to egress) and no program stamp, which only a binary |
| +// has. |
| +func validateRootfsShape(m *Manifest) error { |
| + if m.Kind != KindRootfs { |
| + if m.Processes != nil || m.Hibernate || m.JIT { |
| + return ErrRootfsFieldsOnly |
| + } |
| + return nil |
| + } |
| + art, ok := m.Artifacts[RootfsArtifactKey] |
| + if len(m.Artifacts) != 1 || !ok || art.File != RootfsArtifactFile { |
| + return errors.New("a rootfs release carries one artifact, rootfs-linux-arm64, and nothing else") |
| + } |
| + if m.Capabilities != nil { |
| + return errors.New("a rootfs release cannot declare capabilities") |
| + } |
| + if m.Program != "" || m.ProgramChange { |
| + return errors.New("a rootfs release has no program stamp") |
| + } |
| + return ValidateProcesses(m.Processes) |
| +} |
diff --git a/internal/release/rootfs_test.go b/internal/release/rootfs_test.go| new file mode 100644 |
| index 000000000..2f7f6b7c0 |
| --- /dev/null |
| +++ b/internal/release/rootfs_test.go |
| @@ -0,0 +1,391 @@ |
| +package release |
| + |
| +import ( |
| + "bytes" |
| + "context" |
| + "encoding/json" |
| + "errors" |
| + "fmt" |
| + "go/ast" |
| + "go/parser" |
| + "go/printer" |
| + "go/token" |
| + "os" |
| + "os/exec" |
| + "strings" |
| + "testing" |
| + |
| + "github.com/carlosframework/platform/internal/caps" |
| +) |
| + |
| +func rootfsManifest() *Manifest { |
| + return &Manifest{Schema: 1, App: "shop", Version: "0.1.0-1", Kind: KindRootfs, |
| + Artifacts: map[string]Artifact{RootfsArtifactKey: {File: RootfsArtifactFile, SHA256: strings.Repeat("a", 64), Size: 1}}, |
| + Processes: map[string]Process{ |
| + "web": {Command: []string{"bundle", "exec", "puma", "-C", "config/puma.rb"}}, |
| + "worker": {Command: []string{"bin/jobs"}}, |
| + "release": {Command: []string{"bin/rails", "db:migrate"}, TimeoutSec: 900}, |
| + }} |
| +} |
| + |
| +// putRootfsRelease is putRawRelease's shape for a rootfs release: the image at |
| +// ArtifactKey(acct, app, ver, RootfsArtifactFile), then a manifest with kind |
| +// rootfs, the one rootfs-linux-arm64 artifact and a web process. hibernate |
| +// sets the manifest's hibernate flag (preflight 1.10). Returns the manifest |
| +// bytes exactly as stored. |
| +func putRootfsRelease(t *testing.T, s Store, acct, app, ver string, body []byte, hibernate bool) []byte { |
| + t.Helper() |
| + ctx := context.Background() |
| + if _, err := s.Put(ctx, ArtifactKey(acct, app, ver, RootfsArtifactFile), body, ""); err != nil { |
| + t.Fatalf("put artifact: %v", err) |
| + } |
| + m := Manifest{Schema: 1, App: app, Version: ver, Kind: KindRootfs, Hibernate: hibernate, |
| + Artifacts: map[string]Artifact{RootfsArtifactKey: {File: RootfsArtifactFile, SHA256: etagOf(body), Size: int64(len(body))}}, |
| + Processes: map[string]Process{ProcessWeb: {Command: []string{"bin/web"}}}} |
| + raw, err := json.Marshal(m) |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + if _, err := s.Put(ctx, ManifestKey(acct, app, ver), raw, ""); err != nil { |
| + t.Fatalf("put manifest: %v", err) |
| + } |
| + return raw |
| +} |
| + |
| +func TestPutRootfsReleaseReadsBack(t *testing.T) { |
| + s := NewDirStore(t.TempDir()) |
| + putRootfsRelease(t, s, "bab", "shop", "0.1.0-1", []byte("image"), true) |
| + m, err := GetManifest(context.Background(), s, "bab", "shop", "0.1.0-1") |
| + if err != nil { |
| + t.Fatalf("GetManifest: %v", err) |
| + } |
| + if m.Kind != KindRootfs || !m.Hibernate || len(m.Processes) != 1 { |
| + t.Fatalf("manifest = %+v", m) |
| + } |
| +} |
| + |
| +func TestValidWorkerName(t *testing.T) { |
| + for _, ok := range []string{"worker", "jobs", "a", "sidekiq-2", "q0123456789abcde"} { |
| + if !ValidWorkerName(ok) { |
| + t.Errorf("%q refused", ok) |
| + } |
| + } |
| + for _, bad := range []string{"", "web", "release", "console", "seed", "Worker", "2jobs", "-jobs", |
| + "jobs_2", "q0123456789abcdef", "jobs.1", "jöbs"} { |
| + if ValidWorkerName(bad) { |
| + t.Errorf("%q accepted", bad) |
| + } |
| + } |
| +} |
| + |
| +func TestValidateProcesses(t *testing.T) { |
| + web := Process{Command: []string{"bin/web"}} |
| + cases := []struct { |
| + name string |
| + procs map[string]Process |
| + want string // "" = valid; else the start of the deck row |
| + }{ |
| + {"web alone", map[string]Process{"web": web}, ""}, |
| + {"every kind", map[string]Process{"web": web, "release": {Command: []string{"bin/rails", "db:migrate"}}, |
| + "console": {Command: []string{"bin/rails", "console"}}, "jobs": {Command: []string{"bin/jobs"}}}, ""}, |
| + {"no web", map[string]Process{"jobs": web}, "the processes declare no web process"}, |
| + {"nil", nil, "the processes declare no web process"}, |
| + {"bad name", map[string]Process{"web": web, "Jobs": web}, `"Jobs" is not a process name`}, |
| + {"reserved", map[string]Process{"web": web, "seed": web}, `"seed" is reserved`}, |
| + {"five workers", map[string]Process{"web": web, "a": web, "b": web, "c": web, "d": web, "e": web}, "a rootfs release can declare at most 4 worker processes, and this one declares 5"}, |
| + {"empty command", map[string]Process{"web": {}}, "the web process needs a command"}, |
| + {"empty first word", map[string]Process{"web": {Command: []string{"", "x"}}}, "the web process needs a command"}, |
| + {"bad env name", map[string]Process{"web": {Command: web.Command, Env: map[string]string{"1X": "y"}}}, `the web process sets "1X" in env, which is not a variable name`}, |
| + {"platform env", map[string]Process{"web": {Command: web.Command, Env: map[string]string{"CARLOS_DB": "/x"}}}, "the web process sets CARLOS_DB in env. names that start with CARLOS_"}, |
| + {"relative dir", map[string]Process{"web": {Command: web.Command, WorkingDir: "app"}}, `the web process's working_dir must be an absolute path, and "app" is not`}, |
| + {"unclean dir", map[string]Process{"web": {Command: web.Command, WorkingDir: "/app/../x"}}, "the web process's working_dir must be an absolute path"}, |
| + {"timeout on web", map[string]Process{"web": {Command: web.Command, TimeoutSec: 5}}, "only the release process takes timeout_sec"}, |
| + {"timeout too long", map[string]Process{"web": web, "release": {Command: web.Command, TimeoutSec: MaxReleaseTimeoutSec + 1}}, "the release process's timeout_sec must be between 1 and 21600 seconds"}, |
| + {"negative timeout", map[string]Process{"web": web, "release": {Command: web.Command, TimeoutSec: -1}}, "the release process's timeout_sec must be between 1 and 21600 seconds"}, |
| + {"nul in arg", map[string]Process{"web": {Command: []string{"bin/web", "a\x00b"}}}, "the web process contains a NUL byte"}, |
| + {"nul in env value", map[string]Process{"web": {Command: web.Command, Env: map[string]string{"X": "a\x00"}}}, "the web process contains a NUL byte"}, |
| + {"nul in working dir", map[string]Process{"web": {Command: web.Command, WorkingDir: "/a\x00b"}}, "the web process contains a NUL byte"}, |
| + {"too big", map[string]Process{"web": {Command: web.Command, Env: map[string]string{"X": strings.Repeat("x", MaxProcessesBytes)}}}, "the processes are "}, |
| + } |
| + for _, c := range cases { |
| + err := ValidateProcesses(c.procs) |
| + switch { |
| + case c.want == "" && err != nil: |
| + t.Errorf("%s: refused: %v", c.name, err) |
| + case c.want != "" && (err == nil || !strings.HasPrefix(err.Error(), c.want)): |
| + t.Errorf("%s: err = %v, want %q", c.name, err, c.want) |
| + } |
| + } |
| +} |
| + |
| +func TestDecodeProcesses(t *testing.T) { |
| + procs, err := DecodeProcesses([]byte(`{"web":{"command":["bin/web"],"env":{"A":"b"},"working_dir":"/app"},"release":{"command":["bin/migrate"],"timeout_sec":30}}`)) |
| + if err != nil { |
| + t.Fatalf("a valid object refused: %v", err) |
| + } |
| + if got := procs["web"]; len(got.Command) != 1 || got.Env["A"] != "b" || got.WorkingDir != "/app" || procs["release"].TimeoutSec != 30 { |
| + t.Fatalf("decoded %+v", procs) |
| + } |
| + const c16 = "malformed processes block. want the processes object: web, any workers, release and console" |
| + const c17 = "processes: null. a rootfs release needs its processes, starting with web" |
| + for name, c := range map[string]struct{ raw, want string }{ |
| + "null": {`null`, c17}, |
| + "padded null": {" \n null \t", c17}, |
| + "empty": {``, c17}, |
| + "blank": {" \n", c17}, |
| + "an array": {`[]`, c16}, |
| + "a string": {`"web"`, c16}, |
| + "cut off": {`{"web":`, c16}, |
| + "unknown field": {`{"web":{"command":["x"],"cmd":"y"}}`, c16}, |
| + "trailing data": {`{"web":{"command":["x"]}} {}`, c16}, |
| + "wrong type": {`{"web":{"command":"x"}}`, c16}, |
| + } { |
| + if _, err := DecodeProcesses([]byte(c.raw)); err == nil || err.Error() != c.want { |
| + t.Errorf("%s: err = %v, want %q", name, err, c.want) |
| + } |
| + } |
| +} |
| + |
| +func TestProcessesEqual(t *testing.T) { |
| + a := map[string]Process{"web": {Command: []string{"bin/web"}, Env: map[string]string{"A": "1", "B": "2"}}, "jobs": {Command: []string{"bin/jobs"}}} |
| + b := map[string]Process{"jobs": {Command: []string{"bin/jobs"}}, "web": {Command: []string{"bin/web"}, Env: map[string]string{"B": "2", "A": "1"}}} |
| + if !ProcessesEqual(a, b) { |
| + t.Error("the same processes compare unequal") |
| + } |
| + for name, mut := range map[string]func(map[string]Process){ |
| + "command": func(m map[string]Process) { m["jobs"] = Process{Command: []string{"bin/jobs", "-v"}} }, |
| + "env": func(m map[string]Process) { p := m["web"]; p.Env = map[string]string{"A": "1"}; m["web"] = p }, |
| + "timeout": func(m map[string]Process) { m["jobs"] = Process{Command: []string{"bin/jobs"}, TimeoutSec: 1} }, |
| + "a name": func(m map[string]Process) { m["other"] = m["jobs"]; delete(m, "jobs") }, |
| + "a dir": func(m map[string]Process) { p := m["web"]; p.WorkingDir = "/app"; m["web"] = p }, |
| + "an extra": func(m map[string]Process) { m["x"] = Process{Command: []string{"x"}} }, |
| + } { |
| + c := map[string]Process{"web": a["web"], "jobs": a["jobs"]} |
| + mut(c) |
| + if ProcessesEqual(a, c) { |
| + t.Errorf("a changed %s compares equal", name) |
| + } |
| + } |
| +} |
| + |
| +func TestValidateManifestRootfsRules(t *testing.T) { |
| + if err := validateManifest(rootfsManifest()); err != nil { |
| + t.Fatalf("a valid rootfs manifest refused: %v", err) |
| + } |
| + withJIT := rootfsManifest() |
| + withJIT.JIT = true |
| + if err := validateManifest(withJIT); err != nil { |
| + t.Fatalf("a rootfs manifest with jit refused: %v", err) |
| + } |
| + for name, mut := range map[string]func(*Manifest){ |
| + "no processes": func(m *Manifest) { m.Processes = nil }, |
| + "binary key": func(m *Manifest) { m.Artifacts = map[string]Artifact{"linux-arm64": m.Artifacts[RootfsArtifactKey]} }, |
| + "a second key": func(m *Manifest) { m.Artifacts["linux-arm64"] = m.Artifacts[RootfsArtifactKey] }, |
| + "another file": func(m *Manifest) { |
| + a := m.Artifacts[RootfsArtifactKey] |
| + a.File = "image.sqfs" |
| + m.Artifacts[RootfsArtifactKey] = a |
| + }, |
| + "capabilities": func(m *Manifest) { m.Capabilities = &caps.Set{} }, |
| + "a program stamp": func(m *Manifest) { m.Program = "example.com/shop" }, |
| + "a program change": func(m *Manifest) { m.ProgramChange = true }, |
| + } { |
| + m := rootfsManifest() |
| + mut(m) |
| + if err := validateManifest(m); err == nil { |
| + t.Errorf("%s: accepted", name) |
| + } |
| + } |
| + bin := &Manifest{Schema: 1, App: "shop", Version: "0.1.0-1", Kind: "binary", |
| + Artifacts: map[string]Artifact{"linux-arm64": {File: "linux-arm64", SHA256: strings.Repeat("a", 64), Size: 1}}} |
| + for name, mut := range map[string]func(*Manifest){ |
| + "processes": func(m *Manifest) { m.Processes = rootfsManifest().Processes }, |
| + "hibernate": func(m *Manifest) { m.Hibernate = true }, |
| + "jit": func(m *Manifest) { m.JIT = true }, |
| + } { |
| + m := *bin |
| + mut(&m) |
| + if err := validateManifest(&m); !errors.Is(err, ErrRootfsFieldsOnly) { |
| + t.Errorf("binary with %s: err = %v, want ErrRootfsFieldsOnly", name, err) |
| + } |
| + } |
| + if err := validateManifest(bin); err != nil { |
| + t.Errorf("a plain binary manifest refused: %v", err) |
| + } |
| + if err := validateManifest(&Manifest{Schema: 1, App: "shop", Version: "0.1.0-1", Kind: "oci", Artifacts: bin.Artifacts}); err == nil { |
| + t.Error("an unknown kind accepted") |
| + } |
| +} |
| + |
| +// ---- the old adopters (spec C2) ---- |
| +// |
| +// An old box runs the rules below forever, while the current code changes |
| +// (Plan 2 stages rootfs images). So each rule is frozen here as a function of |
| +// its own, and TestFrozenRulesMatchTheBaseCommit compares the frozen |
| +// statements with the ones `git show 64a002c8:` holds, as printed Go syntax |
| +// (whitespace and comments do not matter, every token does). |
| + |
| +// legacyKindRule64a002c8 is validateManifest's kind check as main had it at |
| +// 64a002c8 (release.go:332), verbatim. Every box released before rootfs apps |
| +// runs it on every manifest it reads (GetManifestRaw), and a refusal there |
| +// fails ensureStaged: nothing is staged or pointed (spec C2). |
| +func legacyKindRule64a002c8(m *Manifest) error { |
| + if m.Kind != "binary" && m.Kind != "static" { |
| + return fmt.Errorf("invalid kind %q (binary | static)", m.Kind) |
| + } |
| + return nil |
| +} |
| + |
| +func TestTheOldKindRuleRefusesARootfsManifest(t *testing.T) { |
| + m := rootfsManifest() |
| + if err := validateManifest(m); err != nil { |
| + t.Fatalf("the new rule refuses the fixture: %v", err) |
| + } |
| + if err := legacyKindRule64a002c8(m); err == nil { |
| + t.Fatal("the old kind rule accepts a rootfs manifest") |
| + } |
| + for _, kind := range []string{"binary", "static"} { |
| + if err := legacyKindRule64a002c8(&Manifest{Kind: kind}); err != nil { |
| + t.Errorf("the frozen rule refuses kind %q: %v", kind, err) |
| + } |
| + } |
| +} |
| + |
| +// errLegacyNoBuild stands for the old stage pass's "no build for this |
| +// platform, skipping" refusal (the `if !hasBuild {` block of stageFrom, |
| +// adopt.go:2371-2376 at 64a002c8). |
| +var errLegacyNoBuild = errors.New("legacy stage rule: no build for this platform") |
| + |
| +// legacyStagePick64a002c8 is stageFrom's artifact pick as main had it at |
| +// 64a002c8 (adopt.go:2327 and the no-build block): the GOOS-GOARCH key and |
| +// nothing else, whatever the manifest's kind. Frozen here (Astra R2 finding |
| +// 6): an old box runs this rule forever, while Plan 2 changes the current |
| +// ensureStaged to stage rootfs images, so the old rule cannot be tested |
| +// through today's code. |
| +func legacyStagePick64a002c8(m *Manifest, platform string) (Artifact, error) { |
| + art, hasBuild := m.Artifacts[platform] |
| + if !hasBuild { |
| + return Artifact{}, errLegacyNoBuild |
| + } |
| + return art, nil |
| +} |
| + |
| +// C2's second half, against the frozen old rule: even an old box that |
| +// somehow parsed a rootfs manifest finds no build on any platform and |
| +// stages nothing. The current binary-row refusal is Plan 2 Task 3's, at the |
| +// adopt pass that receives the row. |
| +func TestTheOldStageRuleFindsNoBuildInARootfsManifest(t *testing.T) { |
| + m := rootfsManifest() |
| + for _, platform := range []string{"linux-arm64", "linux-amd64", "darwin-arm64"} { |
| + if _, err := legacyStagePick64a002c8(m, platform); !errors.Is(err, errLegacyNoBuild) { |
| + t.Errorf("%s: the old rule picked a build from a rootfs manifest: %v", platform, err) |
| + } |
| + } |
| + bin := &Manifest{Kind: "binary", Artifacts: map[string]Artifact{"linux-arm64": {File: "linux-arm64"}}} |
| + if a, err := legacyStagePick64a002c8(bin, "linux-arm64"); err != nil || a.File != "linux-arm64" { |
| + t.Fatalf("the frozen copy no longer picks a binary build: %+v %v", a, err) |
| + } |
| +} |
| + |
| +func printedGo(t *testing.T, fset *token.FileSet, n ast.Node) string { |
| + t.Helper() |
| + var b bytes.Buffer |
| + if err := printer.Fprint(&b, fset, n); err != nil { |
| + t.Fatal(err) |
| + } |
| + return b.String() |
| +} |
| + |
| +func parseGo(t *testing.T, name string, src []byte) (*token.FileSet, *ast.File) { |
| + t.Helper() |
| + fset := token.NewFileSet() |
| + f, err := parser.ParseFile(fset, name, src, parser.SkipObjectResolution) |
| + if err != nil { |
| + t.Fatalf("parse %s: %v", name, err) |
| + } |
| + return fset, f |
| +} |
| + |
| +func funcBody(t *testing.T, f *ast.File, name string) []ast.Stmt { |
| + t.Helper() |
| + for _, d := range f.Decls { |
| + if fd, ok := d.(*ast.FuncDecl); ok && fd.Name.Name == name && fd.Body != nil { |
| + return fd.Body.List |
| + } |
| + } |
| + t.Fatalf("no function %s", name) |
| + return nil |
| +} |
| + |
| +// gitShowBase is a file as the base commit held it. A checkout without the |
| +// commit (a shallow clone) skips the comparison; the frozen functions' own |
| +// tests above still run. |
| +func gitShowBase(t *testing.T, path string) []byte { |
| + t.Helper() |
| + out, err := exec.Command("git", "show", "64a002c8:"+path).Output() |
| + if err != nil { |
| + t.Skipf("the base commit is not in this checkout (a shallow clone?): %v", err) |
| + } |
| + return out |
| +} |
| + |
| +func TestFrozenRulesMatchTheBaseCommit(t *testing.T) { |
| + self, err := os.ReadFile("rootfs_test.go") |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + fsetSelf, fSelf := parseGo(t, "rootfs_test.go", self) |
| + |
| + t.Run("kind rule", func(t *testing.T) { |
| + fsetOld, fOld := parseGo(t, "release.go", gitShowBase(t, "internal/release/release.go")) |
| + var old string |
| + for _, st := range funcBody(t, fOld, "validateManifest") { |
| + if is, ok := st.(*ast.IfStmt); ok && strings.Contains(printedGo(t, fsetOld, is.Cond), "m.Kind") { |
| + old = printedGo(t, fsetOld, is) |
| + break |
| + } |
| + } |
| + if old == "" { |
| + t.Fatal("64a002c8's validateManifest has no check on m.Kind") |
| + } |
| + frozen := funcBody(t, fSelf, "legacyKindRule64a002c8")[0] |
| + if got := printedGo(t, fsetSelf, frozen); got != old { |
| + t.Fatalf("legacyKindRule64a002c8 no longer copies 64a002c8's rule.\nfrozen:\n%s\nbase:\n%s", got, old) |
| + } |
| + }) |
| + |
| + t.Run("stage pick", func(t *testing.T) { |
| + fsetOld, fOld := parseGo(t, "adopt.go", gitShowBase(t, "internal/release/adopt.go")) |
| + var oldPick, oldCond string |
| + var oldRefusal ast.Stmt |
| + for _, st := range funcBody(t, fOld, "stageFrom") { |
| + switch s := st.(type) { |
| + case *ast.AssignStmt: |
| + if p := printedGo(t, fsetOld, s); strings.HasPrefix(p, "art, hasBuild :=") { |
| + oldPick = p |
| + } |
| + case *ast.IfStmt: |
| + if c := printedGo(t, fsetOld, s.Cond); c == "!hasBuild" { |
| + oldCond = c |
| + oldRefusal = s.Body.List[len(s.Body.List)-1] |
| + } |
| + } |
| + } |
| + if oldPick == "" || oldCond == "" { |
| + t.Fatal("64a002c8's stageFrom no longer picks the build by `art, hasBuild := m.Artifacts[...]` and `if !hasBuild`") |
| + } |
| + body := funcBody(t, fSelf, "legacyStagePick64a002c8") |
| + frozenPick := printedGo(t, fsetSelf, body[0]) |
| + if want := strings.Replace(oldPick, "adoptPlatform", "platform", 1); frozenPick != want { |
| + t.Fatalf("the frozen pick is %q, the base commit's is %q (platform written for adoptPlatform)", frozenPick, want) |
| + } |
| + if got := printedGo(t, fsetSelf, body[1].(*ast.IfStmt).Cond); got != oldCond { |
| + t.Fatalf("the frozen condition is %q, the base commit's is %q", got, oldCond) |
| + } |
| + // The base commit's branch refuses: its last statement returns a nil |
| + // build and an error, as the frozen branch does with its sentinel. |
| + if rs, ok := oldRefusal.(*ast.ReturnStmt); !ok || len(rs.Results) != 2 || printedGo(t, fsetOld, rs.Results[0]) != "nil" { |
| + t.Fatalf("64a002c8's no-build branch no longer ends in `return nil, err`: %s", printedGo(t, fsetOld, oldRefusal)) |
| + } |
| + }) |
| +} |
diff --git a/internal/runs/runs_test.go b/internal/runs/runs_test.go| index 4f76a1a88..4bdb6a94e 100644 |
| --- a/internal/runs/runs_test.go |
| +++ b/internal/runs/runs_test.go |
| @@ -325,3 +325,9 @@ func (f *failDelete) Delete(ctx context.Context, key string) error { |
| } |
| return f.Store.Delete(ctx, key) |
| } |
| + |
| +func TestReleaseTimeoutMaxIsTheRunMax(t *testing.T) { |
| + if got := time.Duration(release.MaxReleaseTimeoutSec) * time.Second; got != MaxTimeout { |
| + t.Fatalf("release.MaxReleaseTimeoutSec = %v, runs.MaxTimeout = %v: spec §5.2.1 caps release at the carlos run maximum", got, MaxTimeout) |
| + } |
| +} |