Minted platform apexes carry their app's gate; layout report stops calling them external
The domains pass mints <app>.<sqid>.<apps-domain> by copying the first ready route's socket, but copied no Gate. An app whose instances were all password-gated therefore served the first one's process at its apex to anyone, and `carlos gate set -host <apex>` could not reach it (no record behind a minted row; a deleted row is re-minted). Seen live on jelly-demo, where the apex served a gated demo's /dev/mail sign-in links unauthenticated. The minted route now takes the gate of the route it serves from (same Socket, Addr, or static Channel), falling back to the first gate any other route of the app carries, so a mixed gated/ungated app fails closed. The fallback is a real hash rather than a "closed" sentinel because the gate cookie key is derived from the hash alone; a public value would be a key anyone could mint cookies with. It is set at mint and converged on every pass with SetGate (Upsert can never clear a gate), so set, change and clear on the source all reach the apex, on the domains loop's cadence. The layout report classified such a row as "external" (an unflagged socket route) and raised the mixed-layout warning on boxes where every process was nested. A Platform row proxying a socket another row of its app serves now reports the new word "platform", which layoutMixed and the downgrade guard already ignore on old consoles.
9 files changed,
+504
−8
docs/site/cli.md+6 −2internal/console/apistatuslayout.go+3 −1internal/console/apistatuslayout_test.go+79 −0internal/domains/reconcile.go+82 −0internal/domains/reconcile_test.go+144 −0internal/edge/gate_test.go+76 −0internal/host/agent_layout_test.go+66 −0internal/host/layoutleg.go+41 −0internal/status/snapshot.go+7 −5
CI failed — run details
CI log
=== gate ===
.amadan/test-gate.sh
=== launchctx (1 s)
ok amadan.net/carlos/platform.git/launchctx 0.014s
? amadan.net/carlos/platform.git/launchctx/controlname [no test files]
? amadan.net/carlos/platform.git/launchctx/wireid [no test files]
=== vet (35 s)
=== gofmt (2 s)
gofmt -l .: clean
=== rest (198 s)
? github.com/carlosframework/platform/cmd/changelog [no test files]
ok github.com/carlosframework/platform/cmd/console 6.711s
ok github.com/carlosframework/platform/cmd/moveprobe 12.860s
ok github.com/carlosframework/platform/cmd/zddprobe 0.915s
ok github.com/carlosframework/platform/internal/activator 64.241s
ok github.com/carlosframework/platform/internal/agentsock 0.052s
ok github.com/carlosframework/platform/internal/alerting 0.014s
ok github.com/carlosframework/platform/internal/analytics 0.128s
ok github.com/carlosframework/platform/internal/appconfig 4.189s
ok github.com/carlosframework/platform/internal/apperr 0.485s
ok github.com/carlosframework/platform/internal/applog 0.514s
ok github.com/carlosframework/platform/internal/awsinv 0.004s
ok github.com/carlosframework/platform/internal/boxchoice 0.013s
ok github.com/carlosframework/platform/internal/boxid 1.776s
? 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.028s
ok github.com/carlosframework/platform/internal/caps 0.032s
ok github.com/carlosframework/platform/internal/certwarm 0.009s
ok github.com/carlosframework/platform/internal/cgroup 0.826s
ok github.com/carlosframework/platform/internal/changelog 1.084s
ok github.com/carlosframework/platform/internal/claimactivation 1.884s
ok github.com/carlosframework/platform/internal/clamd 0.110s
? 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.570s
ok github.com/carlosframework/platform/internal/dbdoor/dbdoortest 0.017s
ok github.com/carlosframework/platform/internal/dbquery 0.010s
ok github.com/carlosframework/platform/internal/dbreads 2.103s
? github.com/carlosframework/platform/internal/dbreads/dbreadstest [no test files]
ok github.com/carlosframework/platform/internal/dbverify 0.009s
ok github.com/carlosframework/platform/internal/dnsrec 0.011s
ok github.com/carlosframework/platform/internal/docsite 0.014s
ok github.com/carlosframework/platform/internal/domains 5.207s
ok github.com/carlosframework/platform/internal/doorkey 0.024s
ok github.com/carlosframework/platform/internal/economics 0.010s
ok github.com/carlosframework/platform/internal/edge 48.183s
? github.com/carlosframework/platform/internal/edgeproof [no test files]
ok github.com/carlosframework/platform/internal/edgesfile 0.011s
ok github.com/carlosframework/platform/internal/fleetapi 0.173s
ok github.com/carlosframework/platform/internal/gate 1.890s
ok github.com/carlosframework/platform/internal/genselect 0.027s
ok github.com/carlosframework/platform/internal/geo 0.012s
ok github.com/carlosframework/platform/internal/geoip 0.042s
ok github.com/carlosframework/platform/internal/historyreadback 0.344s
ok github.com/carlosframework/platform/internal/host 147.218s
ok github.com/carlosframework/platform/internal/hostactors 8.977s
ok github.com/carlosframework/platform/internal/hostactors/awsmembership 0.011s
ok github.com/carlosframework/platform/internal/hostbox 4.780s
ok github.com/carlosframework/platform/internal/hostclaim 1.666s
ok github.com/carlosframework/platform/internal/hostenv 0.011s
ok github.com/carlosframework/platform/internal/hostevidence 0.010s
ok github.com/carlosframework/platform/internal/hostexec 9.520s
ok github.com/carlosframework/platform/internal/hostfence 0.161s
ok github.com/carlosframework/platform/internal/hostfiles 12.071s
ok github.com/carlosframework/platform/internal/hostfloor 0.094s
ok github.com/carlosframework/platform/internal/hostguard 1.146s
ok github.com/carlosframework/platform/internal/hostops 4.095s
? github.com/carlosframework/platform/internal/hostops/fencerelease [no test files]
ok github.com/carlosframework/platform/internal/hostops/internal/fencerelease 0.005s
ok github.com/carlosframework/platform/internal/hostquarantine 0.002s
ok github.com/carlosframework/platform/internal/hostrelocate 1.566s
ok github.com/carlosframework/platform/internal/hostresolve 0.558s
ok github.com/carlosframework/platform/internal/hostwrite 0.011s
ok github.com/carlosframework/platform/internal/infraview 0.007s
ok github.com/carlosframework/platform/internal/instancectl 5.345s
ok github.com/carlosframework/platform/internal/instanceexec 3.151s
ok github.com/carlosframework/platform/internal/instancefs 0.019s
ok github.com/carlosframework/platform/internal/instancekey 0.019s
ok github.com/carlosframework/platform/internal/instanceupdates 0.013s
ok github.com/carlosframework/platform/internal/layout 3.774s
ok github.com/carlosframework/platform/internal/lbhealth 0.012s
ok github.com/carlosframework/platform/internal/lease 10.530s
ok github.com/carlosframework/platform/internal/lease/leasetest 1.107s
ok github.com/carlosframework/platform/internal/ledger 0.061s
ok github.com/carlosframework/platform/internal/mail 0.687s
ok github.com/carlosframework/platform/internal/maintenance 0.137s
ok github.com/carlosframework/platform/internal/maintenanceexec 6.033s
ok github.com/carlosframework/platform/internal/maintenanceguard 0.323s
ok github.com/carlosframework/platform/internal/metrics 0.010s
ok github.com/carlosframework/platform/internal/moves 28.657s
ok github.com/carlosframework/platform/internal/moves/archive 2.124s
ok github.com/carlosframework/platform/internal/objstore 0.775s
ok github.com/carlosframework/platform/internal/ops 0.323s
ok github.com/carlosframework/platform/internal/park 0.678s
ok github.com/carlosframework/platform/internal/plans 0.007s
ok github.com/carlosframework/platform/internal/privatefile 0.010s
2026/10/24 00:23:16 provision: listing apps/bab/blog/instances/: list refused — its records are unseen this pass
2026/10/24 00:23:16 provision: listing apps/bab/: listdirs refused — its records are unseen this pass
2026/10/24 00:23:16 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:16 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:16 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:16 provision: listing apps/bac/tito/instances/: list refused — its records are unseen this pass
2026/10/24 00:23:16 provision: listing apps/bac/tito/instances/: list refused — its records are unseen this pass
2026/10/24 00:23:16 provision: skipping record apps/bac/tito/instances/one.example.com.json: unreadable: read refused
2026/10/24 00:23:16 provision: listing apps/bac/tito/instances/: list refused — its records are unseen this pass
2026/10/24 00:23:16 provision: an app's records could not be listed: they are skipped
2026/10/24 00:23:16 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 00:23:17 provision: remove retired instance route shop.example: provision: claim admission unavailable
2026/10/24 00:23:17 provision: remove retired instance route shop.example: provision: claim admission unavailable
2026/10/24 00:23:17 provision: remove retired sidecar route worker.sidecar.internal: provision: claim admission unavailable
2026/10/24 00:23:17 provision: remove retired sidecar route worker.sidecar.internal: provision: claim admission unavailable
2026/10/24 00:23:17 provision: claim install acme.go.tito.io: provision: claim admission unavailable
2026/10/24 00:23:17 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:17 provision: claim install acme.go.tito.io: registry: claim row ownership changed or unknown
2026/10/24 00:23:17 provision: claim install bot.eleven.bac.sidecar.internal: provision: claim admission unavailable
2026/10/24 00:23:17 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 00:23:17 provision: claim install bot.eleven.bac.sidecar.internal: registry: claim row ownership changed or unknown
2026/10/24 00:23:17 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 00:23:17 provision: acme.go.tito.io: not minting this pass: the box's layout intent could not be read: no sealed config
2026/10/24 00:23:17 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:17 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:17 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 00:23:17 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 00:23:17 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 00:23:17 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 00:23:17 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:17 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 00:23:17 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 00:23:17 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 00:23:17 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:17 provision: claim install acme.go.tito.io: registry: claim row ownership changed or unknown
2026/10/24 00:23:17 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:17 provision: claim install acme.go.tito.io: registry: claim row ownership changed or unknown
2026/10/24 00:23:17 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 00:23:18 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/24 00:23:18 provision: claim install bot.eleven.bac.sidecar.internal: registry: claim row ownership changed or unknown
2026/10/24 00:23:18 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 00:23:18 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 00:23:18 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 00:23:18 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 00:23:18 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:18 provision: skipping record apps/bac/tito/instances/new.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:18 provision: not removing acme.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 00:23:18 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:18 provision: skipping record apps/bac/tito/instances/new.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:18 provision: minted instance route ra.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted instance route rb.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted instance route rc.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted instance route rg.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted instance route rh.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted instance route ri.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted instance route rk.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted instance route rl.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted instance route rd.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted instance route re.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted instance route rf.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted instance route rj.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted instance route rb.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted instance route rc.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted instance route rd.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted instance route ra.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: skipping record apps/bac/tito/instances/rb.go.tito.io.json: read failed: read refused
2026/10/24 00:23:18 provision: skipping record apps/bac/tito/instances/rb.go.tito.io.json: read failed: read refused
2026/10/24 00:23:18 provision: minted instance route re.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:18 provision: minted instance route x.appj.example (app "appj" acct "bac")
2026/10/24 00:23:18 provision: minted instance route x.appb.example (app "appb" acct "bac")
2026/10/24 00:23:18 provision: minted instance route x.appd.example (app "appd" acct "bac")
2026/10/24 00:23:18 provision: minted instance route x.appe.example (app "appe" acct "bac")
2026/10/24 00:23:18 provision: minted instance route x.apph.example (app "apph" acct "bac")
2026/10/24 00:23:18 provision: minted instance route x.appi.example (app "appi" acct "bac")
2026/10/24 00:23:18 provision: minted instance route x.appa.example (app "appa" acct "bac")
2026/10/24 00:23:18 provision: minted instance route x.appc.example (app "appc" acct "bac")
2026/10/24 00:23:18 provision: minted instance route x.appf.example (app "appf" acct "bac")
2026/10/24 00:23:18 provision: minted instance route x.appg.example (app "appg" acct "bac")
2026/10/24 00:23:19 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 00:23:19 provision: minted instance route r0110.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0016.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0040.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0105.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0015.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0055.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0072.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0098.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0011.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0036.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0069.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0085.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0057.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0008.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0082.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0102.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0108.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0054.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0001.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0003.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0029.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0041.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0064.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0076.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0018.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0023.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0091.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0115.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0042.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0081.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0084.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0092.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0107.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0010.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0030.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0046.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0120.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0123.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0124.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0006.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0019.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0074.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0096.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0022.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0062.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0065.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0104.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0119.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0039.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0075.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0106.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0014.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0021.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0100.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0068.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0099.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0116.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0009.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0032.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0033.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0066.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0067.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0089.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0094.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0007.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0122.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0129.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0071.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0077.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0088.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0117.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0012.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0027.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0035.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0063.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0058.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0097.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0114.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0125.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0025.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0038.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0045.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0048.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0093.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0126.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0000.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0049.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0056.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0059.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0070.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0086.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0095.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0121.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0053.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0043.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0047.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0128.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0004.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0050.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0060.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0061.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0073.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0103.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0002.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0109.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0037.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0080.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0118.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0127.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0017.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0028.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0112.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0013.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0034.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0079.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0113.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0052.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0020.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0026.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0051.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0078.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0087.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0111.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0024.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0031.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0044.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0083.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0090.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0005.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:19 provision: minted instance route r0101.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 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 00:23:21 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: minted instance route console.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: minted service route ha.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: minted service route svc.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: minted instance route whole.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: minted instance route shared.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: converged acme.go.tito.io channel stable -> edge
2026/10/24 00:23:21 provision: converged acme.go.tito.io channel edge -> canary/rehearsal
2026/10/24 00:23:21 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: empty channel
2026/10/24 00:23:21 provision: not removing acme.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 00:23:21 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: converged acme.go.tito.io environment "" -> "staging"
2026/10/24 00:23:21 provision: converged acme.go.tito.io environment "staging" -> ""
2026/10/24 00:23:21 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: converged acme.go.tito.io steering "" -> "latency"
2026/10/24 00:23:21 provision: converged acme.go.tito.io steering "latency" -> ""
2026/10/24 00:23:21 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: converged acme.go.tito.io hibernate false -> true
2026/10/24 00:23:21 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:21 provision: converged acme.go.tito.io hibernate true -> false (replication "daily" cleared: only a hibernating route's rung is read)
2026/10/24 00:23:21 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: converged acme.go.tito.io status-named false -> true
2026/10/24 00:23:22 provision: converged acme.go.tito.io status-named true -> false
2026/10/24 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: minted service route ha.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 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 00:23:22 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 00:23:22 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 00:23:22 provision: minted service route whole.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 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 00:23:22 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 00:23:22 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 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: minted service route whole.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: skipping accounts/bac/account.json: malformed account manifest: invalid character 'o' in literal null (expecting 'u')
2026/10/24 00:23:22 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: manifest bac/tito: read failed: provision: manifest bac/tito: invalid character 'o' in literal null (expecting 'u')
2026/10/24 00:23:22 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 00:23:22 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 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 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 00:23:22 provision: not removing acme$evil.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 00:23:22 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 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 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 00:23:22 provision: not removing bad-service.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 00:23:22 provision: skipping record apps/bac/tito/instances/no-channel.go.tito.io.json: empty channel
2026/10/24 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: skipping record apps/bac/tito/instances/no-channel.go.tito.io.json: empty channel
2026/10/24 00:23:22 provision: not removing no-channel.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:22 provision: not removing acme.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/24 00:23:22 provision: removed retired instance route ghost.go.tito.io (record gone)
2026/10/24 00:23:22 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 00:23:22 provision: minted instance route dup.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 00:23:22 provision: removed retired instance route acme.go.tito.io (app in the trash)
2026/10/24 00:23:22 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 00:23:22 provision: removed retired static route site.go.tito.io (app in the trash)
2026/10/24 00:23:22 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 00:23:22 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 00:23:22 provision: removed retired instance route acme.go.tito.io (app in the trash)
2026/10/24 00:23:22 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 00:23:22 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 00:23:22 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 00:23:22 provision: converged acme.go.tito.io channel stable -> edge
2026/10/24 00:23:22 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 00:23:22 provision: converged acme.go.tito.io channel canary/rehearsal -> edge
2026/10/24 00:23:22 provision: converged acme.go.tito.io environment "staging" -> ""
2026/10/24 00:23:22 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 00:23:22 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 00:23:22 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 00:23:22 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 00:23:22 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 00:23:22 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 00:23:22 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 00:23:22 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 00:23:22 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 00:23:22 provision: dry-run: would mint instance route acme.go.tito.io (app "tito" acct "bac" channel "stable")
2026/10/24 00:23:22 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 00:23:22 provision: dry-run: would converge adopt.go.tito.io channel stable -> edge
2026/10/24 00:23:22 provision: dry-run: would converge adopt.go.tito.io environment "" -> "staging"
2026/10/24 00:23:22 provision: dry-run: would converge owned.go.tito.io channel stable -> edge
2026/10/24 00:23:22 provision: dry-run: would converge owned.go.tito.io environment "" -> "staging"
2026/10/24 00:23:22 provision: dry-run: would converge owned.go.tito.io hibernate false -> true
2026/10/24 00:23:22 provision: dry-run: would converge owned.go.tito.io seed
2026/10/24 00:23:22 provision: dry-run: would remove retired instance route gone.go.tito.io (record gone)
2026/10/24 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: adopted existing route adopt.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 00:23:22 provision: converged adopt.go.tito.io channel stable -> edge
2026/10/24 00:23:22 provision: converged adopt.go.tito.io environment "" -> "staging"
2026/10/24 00:23:22 provision: converged owned.go.tito.io channel stable -> edge
2026/10/24 00:23:22 provision: converged owned.go.tito.io environment "" -> "staging"
2026/10/24 00:23:22 provision: converged owned.go.tito.io hibernate false -> true
2026/10/24 00:23:22 provision: removed retired instance route gone.go.tito.io (record gone)
2026/10/24 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: adopted existing route story.carlosframework.com (app "story" acct "bad") — this record now owns its channel and environment
2026/10/24 00:23:22 provision: story.carlosframework.com exists but is not the route this record describes (kind "instance"/"static") — leaving it alone
2026/10/24 00:23:22 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: minted service route pubs.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: minted service route pub.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: minted instance route exec.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: minted service route loop.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: minted service route named.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: minted service route priv.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: minted instance route unit.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: minted static route pisite.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: removed retired static route site.go.tito.io (record gone)
2026/10/24 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:22 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:23 provision: minted instance route acme-uk.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:23 provision: converged acme.go.tito.io replicas "ie,uk" -> "uk"
2026/10/24 00:23:23 provision: converged acme.go.tito.io replicas "uk" -> ""
2026/10/24 00:23:23 provision: minted instance route acme-uk.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:23 provision: converged acme-uk.go.tito.io replica mark true -> false
2026/10/24 00:23:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:23 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:23 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 00:23:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:23 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:23 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:23 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:23 provision: acme.go.tito.io: not minting this pass: the box's layout intent could not be read: store down
2026/10/24 00:23:23 provision: router.go.tito.io: not minting this pass: the box's layout intent could not be read: store down
2026/10/24 00:23:23 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/24 00:23:23 provision: converged acme.go.tito.io channel stable -> edge
2026/10/24 00:23:23 provision: minted instance route acme.go.tito.io held landing by mv_acme (app "tito" acct "bac")
2026/10/24 00:23:23 provision: not removing acme.go.tito.io (record gone): participant of a running operation
2026/10/24 00:23:23 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 00:23:23 provision: minted instance route acme.go.tito.io held landing by mv_acme (app "tito" acct "bac")
2026/10/24 00:23:23 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 00:23:23 provision: held acme.go.tito.io landing by mv_acme (was ready)
2026/10/24 00:23:23 provision: acme.go.tito.io: held restoring by rb_other, not by mv_acme; leaving it
2026/10/24 00:23:23 provision: acme.go.tito.io: the row is not this pass's (app "other" acct ""); not holding it for mv_acme
2026/10/24 00:23:23 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/24 00:23:23 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 00:23:23 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 00:23:23 provision: held acme.go.tito.io landing by mv_acme (was ready)
2026/10/24 00:23:23 provision: minted instance route acme.example.com (app "shop" acct "bac")
2026/10/24 00:23:23 provision: minted instance route plain.example.com (app "shop" acct "bac")
2026/10/24 00:23:23 provision: skipping record apps/bac/shop/instances/garbled.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:23 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 00:23:23 provision: skipping record apps/bac/shop/instances/garbled.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:23 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 00:23:23 provision: skipping record apps/bac/shop/instances/garbled.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:23 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 00:23:23 provision: skipping record apps/bac/shop/instances/garbled.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:23 provision: listing apps/bac/shop/instances/: list refused — its records are unseen this pass
2026/10/24 00:23:25 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:25 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:25 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/24 00:23:25 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:25 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/24 00:23:25 provision: minted sidecar route bot.shop.bac.sidecar.internal (app "shop" acct "bac" args ["run"])
2026/10/24 00:23:25 provision: removed retired sidecar route bot.shop.bac.sidecar.internal (record gone)
2026/10/24 00:23:25 provision: minted sidecar route bot.shop.bum.sidecar.internal (app "shop" acct "bum" args ["run"])
2026/10/24 00:23:25 provision: minted sidecar route bot.shop.bum.sidecar.internal (app "shop" acct "bum" args ["run"])
2026/10/24 00:23:25 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 00:23:25 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 00:23:25 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 00:23:25 provision: removed retired sidecar route bot.shop.bum.sidecar.internal (record gone)
2026/10/24 00:23:25 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 00:23:25 provision: removed retired sidecar route bot.shop.bum.sidecar.internal (record gone)
2026/10/24 00:23:25 provision: a.shop.example.com: swapped for import sd_y4zzzxlmwmjtz4iwrtk4sjffja (the original route is journaled)
2026/10/24 00:23:25 provision: a.shop.example.com: import sd_y4zzzxlmwmjtz4iwrtk4sjffja committed: its gate is cleared and its journal row dropped
2026/10/24 00:23:25 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 00:23:26 provision: a.shop.example.com: import sd_7y5adbzu752vyvzejhjljejcdy rolled back to its original route
2026/10/24 00:23:26 provision: a.shop.example.com: import sd_7y5adbzu752vyvzejhjljejcdy: the host's replica is left alone: the record apps/bac/shop/instances/a.shop.example.com.json holds the host
2026/10/24 00:23:26 provision: a.shop.example.com: import sd_7y5adbzu752vyvzejhjljejcdy is cleaned up and its journal row retired
2026/10/24 00:23:26 provision: a.shop.example.com: import sd_wey62czvbzhljphkx7x5wr7wdi rolled back to its original route
2026/10/24 00:23:26 provision: a.shop.example.com: import sd_wey62czvbzhljphkx7x5wr7wdi: the host's replica is left alone: the record apps/bac/shop/instances/a.shop.example.com.json holds the host
2026/10/24 00:23:26 provision: a.shop.example.com: import sd_wey62czvbzhljphkx7x5wr7wdi is cleaned up and its journal row retired
2026/10/24 00:23:26 provision: dry-run: would redo a.shop.example.com's swap record CAS for import sd_mbqmuvf47mvjyp5z32252636mi
2026/10/24 00:23:26 provision: dry-run: would clear a.shop.example.com's import gate
2026/10/24 00:23:26 provision: dry-run: would converge a.shop.example.com seed source
2026/10/24 00:23:26 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 00:23:26 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 00:23:26 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 00:23:26 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 00:23:26 provision: a.shop.example.com: import sd_5p2au3tgowy6olfvjeglg35izi cannot roll back on this box: the activator is not wired; it stays journaled and gated
2026/10/24 00:23:26 provision: a.shop.example.com: import sd_ctrgju4fotq4d4wfdwtorzot5e cannot roll back on this box: the activator is not wired; it stays journaled and gated
2026/10/24 00:23:26 provision: a.shop.example.com: import sd_tdoc6l5kwcuheys7mmdplkbp74 is journaled, but this box cannot act on imports; its row is left alone
2026/10/24 00:23:26 provision: a.shop.example.com: import sd_bt5ruxxup64pncdwlcjb6knjbq is journaled, but this box cannot act on imports; its row is left alone
2026/10/24 00:23:26 provision: a.shop.example.com: import sd_scqdhphhpvvu77cgzciguceosu is journaled, but this box cannot act on imports; its row is left alone
2026/10/24 00:23:26 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 00:23:26 provision: b.shop.example.com: import sd_tngk7wq2caymj7xwil2jo2vidm left alone this pass: the import journal could not be read
2026/10/24 00:23:26 provision: c.shop.example.com: import sd_ekwgy4jzvfs4ndzwlmwtoalkka left alone this pass: the import journal could not be read
2026/10/24 00:23:26 provision: a.shop.example.com: import sd_ugeghkpopifshblda4xeksyctm committed: its gate is cleared and its journal row dropped
2026/10/24 00:23:26 provision: a.shop.example.com: not converging import sd_ebuhqdugnrbmnbob6rmtkokn5q: it is swapped but not committed, and the row on this box has no import gate
2026/10/24 00:23:26 provision: a.shop.example.com: not converging import sd_ix7vpzrjnecthz2iiavvzf7vwi: it is swapped but not committed, and the row on this box has no import gate
2026/10/24 00:23:26 provision: a.shop.example.com: not converging import sd_2zb6t35vmlp5jy2nxe7mjuyr3a: it is placed but not committed, and the row on this box has no import gate
2026/10/24 00:23:26 provision: a.shop.example.com: not converging import sd_kqcbt5svqtuzhspo7gsdcqupsu: it is placed but not committed, and the row on this box has no import gate
2026/10/24 00:23:26 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 00:23:26 provision: converge seed source on a.shop.example.com: constraint failed: seed_source is read-only here (1811)
2026/10/24 00:23:26 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 00:23:26 provision: a.shop.example.com: import sd_scpk74e4hlbhcdtarrru2xbwfu committed: its gate is cleared and its journal row dropped
2026/10/24 00:23:26 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 00:23:26 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:26 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 00:23:26 provision: acme.go.tito.io: not minting a seeded instance: this box does not mint nested (<nil>)
2026/10/24 00:23:26 provision: acme.go.tito.io: not minting a seeded instance: claim control is on for this box
2026/10/24 00:23:26 provision: acme.go.tito.io: aborted seed sd_5jgno3fgsutcophkvywkvh4oxi: this box cannot read seed markers, and places no seed; nothing local is removed
2026/10/24 00:23:26 provision: acme.go.tito.io: aborted seed sd_5jgno3fgsutcophkvywkvh4oxi rolled back (no box had swapped it)
2026/10/24 00:23:26 provision: acme.go.tito.io: not minting a seeded instance: its record does not describe a hibernating instance
2026/10/24 00:23:26 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:26 provision: removed instance route acme.go.tito.io (its seed sd_p5k3efpmun3k7n6qk3wldp645e was aborted); the next pass rolls it back
2026/10/24 00:23:26 provision: acme.go.tito.io: aborted seed sd_p5k3efpmun3k7n6qk3wldp645e: this box cannot read seed markers, and places no seed; nothing local is removed
2026/10/24 00:23:26 provision: acme.go.tito.io: aborted seed sd_p5k3efpmun3k7n6qk3wldp645e rolled back (no box had swapped it)
2026/10/24 00:23:26 provision: acme.go.tito.io: aborted seed sd_orcrvawya3md4myxed3gkaog7q has a row this pass may not remove; leaving the seed aborted
2026/10/24 00:23:26 provision: acme.go.tito.io: aborted seed sd_qxqc2olyak6vnkoyjlv2dya6fa rolled back (no box had swapped it)
2026/10/24 00:23:26 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:26 provision: removed instance route acme.go.tito.io (its seed sd_jvicqo2v4nz5ysw5a4v4cdx35q was aborted); the next pass rolls it back
2026/10/24 00:23:26 provision: acme.go.tito.io: aborted seed sd_jvicqo2v4nz5ysw5a4v4cdx35q has no route on this box: its local data is removed
2026/10/24 00:23:26 provision: acme.go.tito.io: aborted seed sd_jvicqo2v4nz5ysw5a4v4cdx35q rolled back (no box had swapped it)
2026/10/24 00:23:26 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:26 provision: a.shop.example.com: swapped for import sd_xxsg7ozqr37impfnli2npub4pm (the original route is journaled)
2026/10/24 00:23:26 provision: a.shop.example.com: import sd_xxsg7ozqr37impfnli2npub4pm rolled back to its original route
2026/10/24 00:23:26 provision: a.shop.example.com: import sd_xxsg7ozqr37impfnli2npub4pm is cleaned up and its journal row retired
2026/10/24 00:23:26 provision: a.shop.example.com: swapped for import sd_2dtqbsr4e3fpclxzzcszksycra (the original route is journaled)
2026/10/24 00:23:26 provision: a.shop.example.com: import sd_2dtqbsr4e3fpclxzzcszksycra rolled back to its original route
2026/10/24 00:23:26 provision: a.shop.example.com: import sd_2dtqbsr4e3fpclxzzcszksycra is cleaned up and its journal row retired
2026/10/24 00:23:26 provision: a.shop.example.com: swapped for import sd_4m6kpocmbxewqtzawp3mhvniyu (the original route is journaled)
2026/10/24 00:23:26 provision: a.shop.example.com: import sd_4m6kpocmbxewqtzawp3mhvniyu rolled back to its original route
2026/10/24 00:23:26 provision: a.shop.example.com: import sd_4m6kpocmbxewqtzawp3mhvniyu: the host's replica is left alone: its record no longer names this seed
2026/10/24 00:23:26 provision: a.shop.example.com: import sd_4m6kpocmbxewqtzawp3mhvniyu is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_mu7bdtl5mg4jjya3o62olo3ab4 (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_mu7bdtl5mg4jjya3o62olo3ab4 rollback deferred: the host is not fenced and stopped yet (<nil>)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_mu7bdtl5mg4jjya3o62olo3ab4 rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_mu7bdtl5mg4jjya3o62olo3ab4 is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_k7ywbiqldwxdahofb7v2gr2cmi (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_k7ywbiqldwxdahofb7v2gr2cmi rollback deferred: the host is not fenced and stopped yet (stop unproven)
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_ydwlio2zxeheaptl6c4utq3yg4 (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_ydwlio2zxeheaptl6c4utq3yg4 is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_npg4skhwvxispm63ywgspsadfe (the original route is journaled)
2026/10/24 00:23:27 provision: skipping record apps/bac/shop/instances/a.shop.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_npg4skhwvxispm63ywgspsadfe left alone this pass: its record could not be read
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_vmy57gyqnuboc2voaivvpx3tva (the original route is journaled)
2026/10/24 00:23:27 provision: skipping record apps/bac/shop/instances/a.shop.example.com.json: read failed: connection reset
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_vmy57gyqnuboc2voaivvpx3tva left alone this pass: its record could not be read
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_vgluimcrpqexub6cb4ak5jace4 (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_vgluimcrpqexub6cb4ak5jace4: close the import gate: constraint failed: injected (1811)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_vgluimcrpqexub6cb4ak5jace4 rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_vgluimcrpqexub6cb4ak5jace4 is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_i3acram2bt7t7lf4m3g7fjfe7y (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_i3acram2bt7t7lf4m3g7fjfe7y: close the import gate: constraint failed: injected (1811)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_i3acram2bt7t7lf4m3g7fjfe7y rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_i3acram2bt7t7lf4m3g7fjfe7y is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_4wbcvydhhww3lqliltjddivrza (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_4wbcvydhhww3lqliltjddivrza rollback deferred: the host is not fenced and stopped yet (injected failure at fence)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_4wbcvydhhww3lqliltjddivrza rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_4wbcvydhhww3lqliltjddivrza is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_bg24vososnqmk7h3p7u2m7sboq (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_bg24vososnqmk7h3p7u2m7sboq rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_bg24vososnqmk7h3p7u2m7sboq is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_dvjmtpgy7noofshwx3buaenemy (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_dvjmtpgy7noofshwx3buaenemy: retire its instance key: injected failure at retire-key
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_dvjmtpgy7noofshwx3buaenemy rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_dvjmtpgy7noofshwx3buaenemy is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_e6ldqgwclib2vxewais45j3a6e (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_e6ldqgwclib2vxewais45j3a6e rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_e6ldqgwclib2vxewais45j3a6e is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_hfw2ns2767k7zqtbbdhycxktxy (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_hfw2ns2767k7zqtbbdhycxktxy: remove its local data: injected failure at remove-local
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_hfw2ns2767k7zqtbbdhycxktxy rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_hfw2ns2767k7zqtbbdhycxktxy is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_ade3hirsb7dff6ng45pb46b6gi (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_ade3hirsb7dff6ng45pb46b6gi rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_ade3hirsb7dff6ng45pb46b6gi is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_5u62vqe4qrsd33gh6etren6y7i (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_5u62vqe4qrsd33gh6etren6y7i: remove its local data: injected failure at remove-local-done
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_5u62vqe4qrsd33gh6etren6y7i rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_5u62vqe4qrsd33gh6etren6y7i is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_khs3p5ck55zvrnmfqecfzswmvq (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_khs3p5ck55zvrnmfqecfzswmvq rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_khs3p5ck55zvrnmfqecfzswmvq is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_zdlndekr4yanj3ltjuap7g6nbe (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_zdlndekr4yanj3ltjuap7g6nbe: restore the original route: constraint failed: injected (1811)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_zdlndekr4yanj3ltjuap7g6nbe rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_zdlndekr4yanj3ltjuap7g6nbe is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_ybwkveyjsv4s436qfwmte5z5s4 (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_ybwkveyjsv4s436qfwmte5z5s4: restore the original route: constraint failed: injected (1811)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_ybwkveyjsv4s436qfwmte5z5s4 rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_ybwkveyjsv4s436qfwmte5z5s4 is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_ristbkko3e67xr675xfkwnywym (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_ristbkko3e67xr675xfkwnywym is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_e7ssq22x5moxbx55kb556shgxa (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_e7ssq22x5moxbx55kb556shgxa rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_e7ssq22x5moxbx55kb556shgxa: delete its snapshot: injected failure at delete-snapshot
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_e7ssq22x5moxbx55kb556shgxa is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_u5z4n4gb5hml6cdgo3bl37dcmm (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_u5z4n4gb5hml6cdgo3bl37dcmm rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_u5z4n4gb5hml6cdgo3bl37dcmm is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_o4kigmaua2qpbd7kv7wjitl2gu (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_o4kigmaua2qpbd7kv7wjitl2gu rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_o4kigmaua2qpbd7kv7wjitl2gu: delete the host's replica: injected failure at delete-replica
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_o4kigmaua2qpbd7kv7wjitl2gu is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_k43mpu3sy7njnamm64u6v4cj4y (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_k43mpu3sy7njnamm64u6v4cj4y rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_k43mpu3sy7njnamm64u6v4cj4y is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_iy7tkl6iwbpwfaqpjwytp7rhye (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_iy7tkl6iwbpwfaqpjwytp7rhye rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_iy7tkl6iwbpwfaqpjwytp7rhye: retire its journal row: constraint failed: injected (1811)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_iy7tkl6iwbpwfaqpjwytp7rhye is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_lvlteud3ivah3gdwotwt2rgogy (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_lvlteud3ivah3gdwotwt2rgogy rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_lvlteud3ivah3gdwotwt2rgogy: retire its journal row: constraint failed: injected (1811)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_lvlteud3ivah3gdwotwt2rgogy is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_vxlt52pottdmyofn5ddkco7v6u (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_vxlt52pottdmyofn5ddkco7v6u rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_vxlt52pottdmyofn5ddkco7v6u is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: mark import sd_vxlt52pottdmyofn5ddkco7v6u rolled back: injected failure at cas
2026/10/24 00:23:27 provision: a.shop.example.com: aborted seed sd_vxlt52pottdmyofn5ddkco7v6u rolled back (no box had swapped it)
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_pvxgmuuzh26cjqsayzxbin2a7u (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_pvxgmuuzh26cjqsayzxbin2a7u rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_pvxgmuuzh26cjqsayzxbin2a7u is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: aborted seed sd_pvxgmuuzh26cjqsayzxbin2a7u rolled back (no box had swapped it)
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_ntqhlipf7djt2jhavyx75tg4su (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_ntqhlipf7djt2jhavyx75tg4su rollback deferred: the host is not fenced and stopped yet (<nil>)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_ntqhlipf7djt2jhavyx75tg4su rollback deferred: the host is not fenced and stopped yet (<nil>)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_ntqhlipf7djt2jhavyx75tg4su rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_ntqhlipf7djt2jhavyx75tg4su is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_rdt6o3qporqbm4xzvtilu43h2a (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_rdt6o3qporqbm4xzvtilu43h2a rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_rdt6o3qporqbm4xzvtilu43h2a is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_bf4336vitxqmjaqpxwry4mrcz4 (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_bf4336vitxqmjaqpxwry4mrcz4 rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_bf4336vitxqmjaqpxwry4mrcz4 is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_wcn5s2spfsb3npsr3rfjimtjda (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_wcn5s2spfsb3npsr3rfjimtjda rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_wcn5s2spfsb3npsr3rfjimtjda is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_mbair5spviyqc34ehcw63r63di (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_mbair5spviyqc34ehcw63r63di rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_mbair5spviyqc34ehcw63r63di is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_nz3ronpmoyegl3hvhje453i3xa (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_nz3ronpmoyegl3hvhje453i3xa rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_nz3ronpmoyegl3hvhje453i3xa is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: minted instance route a.shop.example.com (app "other" acct "bac")
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_u43qsx6fpsubfx6bytg6icxi4i (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_u43qsx6fpsubfx6bytg6icxi4i rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_u43qsx6fpsubfx6bytg6icxi4i is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: minted instance route a.shop.example.com (app "other" acct "bac")
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_q5lycyk2e5sjveeplcj34u3gtm (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_q5lycyk2e5sjveeplcj34u3gtm rolled back to its original route
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_q5lycyk2e5sjveeplcj34u3gtm is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: minted instance route a.shop.example.com (app "other" acct "bac")
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_4ruwwlosa7d35vuy6ktdyi5uo4 (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_4ruwwlosa7d35vuy6ktdyi5uo4 has no route on this box: its local data is removed and no route is put back
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_4ruwwlosa7d35vuy6ktdyi5uo4 is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_mmjw56adwqtnenes4jx6wizime (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_xboprqphnvkh2gcqrahx2bwqf4 (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_dlwgap6ayr7mn5ecplbj2xt7pi (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_dlwgap6ayr7mn5ecplbj2xt7pi cannot roll back on this box: the activator is not wired; it stays journaled and gated
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_jcugzy5nmpoxn6xycs7sp3fi7a (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_jcugzy5nmpoxn6xycs7sp3fi7a is not rolled back: the route changed under the fence, so nothing there is touched
2026/10/24 00:23:27 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 00:23:27 provision: a.shop.example.com: import ../not-a-seed is cleaned up and its journal row retired
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_bxedusqqbk5y3zggwpmtoplyma (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_x57zaru6b4lmllcubspmizivou (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_ob5gsrf64afc6w22ycr4a56qmu (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_2dil3p4j5boe7wsvho53vedfdu (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: swapped for import sd_rvqjeibgzd57rvid57z3ic6l6m (the original route is journaled)
2026/10/24 00:23:27 provision: a.shop.example.com: import sd_rvqjeibgzd57rvid57z3ic6l6m rollback deferred: the host is not fenced and stopped yet (stop evidence unreadable)
2026/10/24 00:23:28 provision: a.shop.example.com: swapped for import sd_iyoyh3z7ftmzojdjgy2uyhzooa (the original route is journaled)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_iyoyh3z7ftmzojdjgy2uyhzooa has no route on this box: its local data is removed and no route is put back
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_iyoyh3z7ftmzojdjgy2uyhzooa is cleaned up and its journal row retired
2026/10/24 00:23:28 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 00:23:28 provision: a.shop.example.com: swapped for import sd_jnqq6a5kwd457fjj3r7sicpenu (the original route is journaled)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_jnqq6a5kwd457fjj3r7sicpenu: remove its local data: injected failure at remove-local
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_jnqq6a5kwd457fjj3r7sicpenu is not rolled back: the route at the host is not the import's, so nothing there is touched
2026/10/24 00:23:28 provision: a.shop.example.com: swapped for import sd_wnva2apbgw5f54nw76pnvrz2re (the original route is journaled)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_wnva2apbgw5f54nw76pnvrz2re: a route appeared at the host, so its local database is left and the rollback waits
2026/10/24 00:23:28 provision: a.shop.example.com: swapped for import sd_vsoiueiow4qybdokf25akjejka (the original route is journaled)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_vsoiueiow4qybdokf25akjejka rollback deferred: no fence generation: the generation source answered 0
2026/10/24 00:23:28 provision: a.shop.example.com: swapped for import sd_p5ukfin4azha2vad73muz3kp5e (the original route is journaled)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_p5ukfin4azha2vad73muz3kp5e rollback deferred: no fence generation: registry busy
2026/10/24 00:23:28 provision: a.shop.example.com: swapped for import sd_m654pfde5kf47zyzdckxt4s4xe (the original route is journaled)
2026/10/24 00:23:28 provision: a.shop.example.com: swapped for import sd_cc36vngkalw5swjr5lz3566mkm (the original route is journaled)
2026/10/24 00:23:28 provision: a.shop.example.com: swapped for import sd_4g6q7nsxexzt3uwhifuvlsesoe (the original route is journaled)
2026/10/24 00:23:28 provision: a.shop.example.com: import deferred: the instance's env file could not be read: a symlink
2026/10/24 00:23:28 provision: a.shop.example.com: import deferred: this box cannot read the instance's env file
2026/10/24 00:23:28 provision: a.shop.example.com: swapped for import sd_b2opijsxrttaiomypdygbgwseq (the original route is journaled)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_b2opijsxrttaiomypdygbgwseq rolled back to its original route
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_b2opijsxrttaiomypdygbgwseq is cleaned up and its journal row retired
2026/10/24 00:23:28 provision: a.shop.example.com: swapped for import sd_h63founlsytb6ctkzea4zj3lqa (the original route is journaled)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_h63founlsytb6ctkzea4zj3lqa rolled back to its original route
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_h63founlsytb6ctkzea4zj3lqa is cleaned up and its journal row retired
2026/10/24 00:23:28 provision: a.shop.example.com: swapped for import sd_nhaamt55lznywkbjjlzm3cwt7e (the original route is journaled)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_nhaamt55lznywkbjjlzm3cwt7e rolled back to its original route
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_nhaamt55lznywkbjjlzm3cwt7e is cleaned up and its journal row retired
2026/10/24 00:23:28 provision: a.shop.example.com: swapped for import sd_bkqaoyaia2tf37icn2xskwm6cu (the original route is journaled)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_bkqaoyaia2tf37icn2xskwm6cu: retire its instance key: the env file is a symlink
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_bkqaoyaia2tf37icn2xskwm6cu rolled back to its original route
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_bkqaoyaia2tf37icn2xskwm6cu is cleaned up and its journal row retired
2026/10/24 00:23:28 provision: a.shop.example.com: swapped for import sd_eq2su6kl7dzdkxllmir5hjw7fi (the original route is journaled)
2026/10/24 00:23:28 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 00:23:28 provision: a.shop.example.com: swapped for import sd_pxap6urawso5xihkybmkbv4lny (the original route is journaled)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_ntekyqtth2jojjkcx32cmvkxry refused: there is no route at a.shop.example.com to replace
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_4wupxvrs73gzvb646lp6t7ybu4 refused: the route's address is 127.0.0.1:9, not 127.0.0.1:8401
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_trnjc4mveyhk7idj5yvfsy7duq 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 00:23:28 provision: a.shop.example.com: import sd_heznkf7hknrrpx4kdx4f3tx5we refused: the route's address is 127.0.0.1:9, not 127.0.0.1:8401
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_ykmibhomx4zs5qx4atqy7jidba refused: the route belongs to app other
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_c5twtj4mbfb2optctyb3v6jf3m refused: the route is filed under another account
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_tdqecursvgxzbdkhdwivgmq73i refused: the route is filed under the operator account, and no assignment maps shop to this app
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_v33onduylnn2kuhrn3dbnol7gy refused: the route is filed under the operator account, and no assignment maps shop to this app
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_qjwr7urnuma7jpt5wbnvppageq refused: the route is filed under the operator account, and no assignment maps shop to this app
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_zk4eg2wtfhdqvhntjgu4jdnbgi refused: the route is filed under the operator account, and no assignment maps shop to this app
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_accnidnxxfkqahc3fj54fwbdcq refused: the route is not an address route this import can take over (socket)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_jjhidpvlyizx6ojjlpsovnx2hu refused: the route is not an address route this import can take over (no address)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_nmgnv23gi7vpmpo5ojiylqleue refused: the route is not an address route this import can take over (provisioned)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_lsp3k7ea2zko6r6tnaj4lxcoka refused: the route is not an address route this import can take over (kind static)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_3mot4duknojh5k3ahjplowodo4 refused: the route is not an address route this import can take over (backing)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_eeff4zzkqaittjbk2ckvv4hwsy refused: the route is not an address route this import can take over (tunnel)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_ywblw5xnxyfoxwbmqc36cqc73q refused: the route is not an address route this import can take over (caps)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_j5oitavwoj2qxgwtth7zkw7ooq refused: the route is not an address route this import can take over (platform)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_tclndaefgmi64gnu4eetusygwu refused: the route is not an address route this import can take over (canary)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_yhll2eogmvbzq7qiesszn7h76i refused: the route is not an address route this import can take over (kind sidecar)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_yoxw7ckzbhkil6avbu6fu7vx5q refused: the route is not an address route this import can take over (region)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_rkbxnhxnrsdrrsxl73sid7n3ja refused: the route is not an address route this import can take over (fleet_box)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_swbrgh6ifak6p6tmpnfewdqe2i refused: the route is not an address route this import can take over (hibernate)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_3vrnymqp4sy7uagdchnfkklx6q refused: the route is not an address route this import can take over (claim_owner)
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_syixzqdiqvbc2anp324ybeylzi refused: this box does not run instances nested
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_dhk2i7w4n2qzv47isbthjw4ih4 refused: this box does not run instances nested
2026/10/24 00:23:28 provision: a.shop.example.com: import sd_cg2473ntgzmtyt3mhkjn7rvmeu refused: claim control is on for this box
2026/10/24 00:23:28 provision: a.shop.example.com: swapped for import sd_vafxahuwwrh2wx4lqq3hkthllu (the original route is journaled)
2026/10/24 00:23:28 provision: a.shop.example.com: swapped for import sd_i25c3gzrbhrqaiz72azgn7nkda (the original route is journaled)
2026/10/24 00:23:28 provision: a.shop.example.com: import deferred: this box cannot read the legacy route assignments
2026/10/24 00:23:28 provision: a.shop.example.com: import deferred: the legacy route assignments could not be read: store down
2026/10/24 00:23:28 provision: a.shop.example.com: not swapping for import sd_7ixfkzcnfdhfb7wpu4aul5txoq: its verify hash is not a sha256
2026/10/24 00:23:28 provision: a.shop.example.com: not swapping for import sd_rka7omazziv6kce2rh5rkrw64a: its verify hash is not a sha256
2026/10/24 00:23:28 provision: a.shop.example.com: not swapping for import sd_la44qhwopr6lyrsrzqgomahthe: its verify hash is not a sha256
2026/10/24 00:23:28 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 00:23:28 provision: A.shop.example.com/..: not swapping for import sd_or2vjp7eh4csezskcvtnrx322e: its host or seed id is malformed (seeds: not a host)
2026/10/24 00:23:28 provision: a.shop.example.com: not swapping for import sd_2woxly3dkkebqmj36opiyprjhe: its record does not describe a nested, hibernating instance
2026/10/24 00:23:28 provision: a.shop.example.com: not swapping for import sd_i5xvlm5fa5v4kyamv2l6b2rkpu: its record does not describe a nested, hibernating instance
2026/10/24 00:23:28 provision: a.shop.example.com: not swapping for import sd_qbqv4a6igvfgqgjyqva5ccmckq: its record does not describe a nested, hibernating instance
2026/10/24 00:23:28 provision: a.shop.example.com: not swapping for import sd_nu6jkkmliemmrsihug5lqkj46a: its record does not describe a nested, hibernating instance
2026/10/24 00:23:28 provision: a.shop.example.com: import deferred: the box's layout intent could not be read: store down
2026/10/24 00:23:28 provision: a.shop.example.com: swapped for import sd_xlenl3fbcpn5xuhwfja3mrzfam (the original route is journaled)
2026/10/24 00:23:28 provision: a.shop.example.com: import deferred: the box's nested probe did not answer: ready probe timed out
2026/10/24 00:23:28 provision: a.shop.example.com: swapped for import sd_6wmpkkqv3hmwrxttrm2apsjdiu (the original route is journaled)
2026/10/24 00:23:28 provision: a.shop.example.com: swapped for import sd_n365r5mxc7zpgfn5yftullauqi (the original route is journaled)
2026/10/24 00:23:28 provision: a.shop.example.com: import deferred: the route is held by operation op_1
2026/10/24 00:23:29 provision: dry-run: would consider swapping a.shop.example.com for import sd_apf4dswstaptcwg2hxwsb3y4ha
2026/10/24 00:23:29 provision: a.shop.example.com: import sd_hkdeihutwnk6nt4ktofguguupq rolled back to its original route
2026/10/24 00:23:29 provision: a.shop.example.com: import sd_hkdeihutwnk6nt4ktofguguupq: the host's replica is left alone: the record apps/bac/shop/instances/a.shop.example.com.json holds the host
2026/10/24 00:23:29 provision: a.shop.example.com: import sd_hkdeihutwnk6nt4ktofguguupq is cleaned up and its journal row retired
2026/10/24 00:23:29 provision: a.shop.example.com: import sd_lu7afmkw5ll5tflg3o663h5kq4 left alone: the import journal holds seed sd_2c2nkdqftkyeyg5chd7cqk5oba at swapped
2026/10/24 00:23:29 provision: a.shop.example.com: not minting import sd_zyq5jyhiywngvmkipakxpnhvfe: it is swapped but not committed, and only its swap makes its row
2026/10/24 00:23:29 provision: a.shop.example.com: not minting import sd_54qzizmxu4zn3t6gz3a7ddyrqu: it is placed but not committed, and only its swap makes its row
2026/10/24 00:23:29 provision: a.shop.example.com: swapped for import sd_n3ga54aq4h5sojc3dexkga3igy (the original route is journaled)
2026/10/24 00:23:29 provision: a.shop.example.com: not minting import sd_n3ga54aq4h5sojc3dexkga3igy: it is swapped but not committed, and only its swap makes its row
2026/10/24 00:23:29 provision: a.shop.example.com: not minting import sd_n3ga54aq4h5sojc3dexkga3igy: it is placed but not committed, and only its swap makes its row
2026/10/24 00:23:29 provision: minted instance route a.shop.example.com (app "shop" acct "bac")
2026/10/24 00:23:29 provision: removed retired sidecar route gone.eleven.bac.sidecar.internal (record gone)
2026/10/24 00:23:29 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 00:23:29 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 00:23:29 provision: converged sidecar bot.eleven.bac.sidecar.internal args ["sidecar","run"] -> ["worker","run"]
2026/10/24 00:23:29 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 00:23:29 provision: converged sidecar bot.eleven.bac.sidecar.internal ceilings 300/3600 -> 60/120
2026/10/24 00:23:29 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 00:23:29 provision: converged sidecar bot.eleven.bac.sidecar.internal channel stable -> canary/eleven
2026/10/24 00:23:29 provision: converged sidecar bot.eleven.bac.sidecar.internal environment "other" -> "relay"
2026/10/24 00:23:29 provision: converged sidecar bot.eleven.bac.sidecar.internal hibernate true -> false
2026/10/24 00:23:29 provision: skipping sidecar record apps/bac/eleven/sidecars/bot.json: read failed: failStore: reads disabled under apps/bac/eleven/sidecars/
2026/10/24 00:23:29 provision: skipping sidecar record apps/bac/eleven/sidecars/bot.json: malformed: invalid character 'n' looking for beginning of object key string
2026/10/24 00:23:29 provision: not removing sidecar bot.eleven.bac.sidecar.internal: its record exists but could not be read cleanly this pass
2026/10/24 00:23:29 provision: skipping sidecar record apps/bac/eleven/sidecars/bot.json: empty channel
2026/10/24 00:23:29 provision: skipping sidecar record apps/bac/eleven/sidecars/held.json: empty channel
2026/10/24 00:23:29 provision: not removing sidecar held.eleven.bac.sidecar.internal: its record exists but could not be read cleanly this pass
2026/10/24 00:23:29 provision: removed retired sidecar route old.eleven.bac.sidecar.internal (record gone)
2026/10/24 00:23:29 provision: bac/eleven has sidecar records but no sidecars manifest — not minting
2026/10/24 00:23:29 provision: bac/eleven is in the trash — not minting sidecar routes for it
2026/10/24 00:23:29 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 00:23:29 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 00:23:29 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 00:23:29 provision: minted sidecar route hub.relay.bac.sidecar.internal (app "relay" acct "bac" args ["relay"])
2026/10/24 00:23:29 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 00:23:29 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 00:23:29 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 00:23:29 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 00:23:29 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 00:23:29 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 00:23:29 provision: removed retired sidecar route bot.eleven.bac.sidecar.internal (record gone)
2026/10/24 00:23:29 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 00:23:29 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 00:23:29 provision: skipping sidecar record apps/bac/relay/sidecars/hub.json: read failed: failStore: reads disabled under apps/bac/relay/sidecars/
2026/10/24 00:23:29 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 00:23:29 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/24 00:23:29 provision: dry-run: would mint sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" channel "stable" args ["sidecar","run"])
2026/10/24 00:23:29 provision: dry-run: would remove retired sidecar route gone.eleven.bac.sidecar.internal (record gone)
2026/10/24 00:23:29 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 00:23:29 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:29 provision: converged acme.go.tito.io update settings "{\"updates\":\"manual\",\"channel\":\"stable\"}" -> ""
2026/10/24 00:23:29 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:29 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:29 provision: manifest bac/tito: read failed: provision: manifest bac/tito: unexpected end of JSON input
2026/10/24 00:23:29 provision: manifest bac/tito: read failed: provision: manifest bac/tito: unexpected end of JSON input
2026/10/24 00:23:29 provision: acme.go.tito.io: not minted this pass: the app's update policy could not be read
2026/10/24 00:23:29 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/24 00:23:29 provision: manifest bac/tito: read failed: provision: manifest bac/tito: unexpected end of JSON input
2026/10/24 00:23:29 provision: acme.go.tito.io: not minted this pass: the app's update policy could not be read
2026/10/24 00:23:29 provision: minted instance route acme.go.tito.io held landing by mv_acme (app "tito" acct "bac")
2026/10/24 00:23:29 provision: record view: change index unusable (release: change index malformed: invalid character 'n' looking for beginning of object key string): walking
2026/10/24 00:23:29 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 00:23:29 provision: record view: re-reading apps/bqc/shop failed: retrying on the next refresh
2026/10/24 00:23:29 provision: listing apps/bqc/shop/instances/: list refused — its records are unseen this pass
2026/10/24 00:23:29 provision: listing apps/bqc/shop/instances/: list refused — its records are unseen this pass
2026/10/24 00:23:29 provision: an app's records could not be listed: they are skipped
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: record view: re-reading apps/bqc/shop failed: retrying on the next refresh
2026/10/24 00:23:29 provision: listing apps/bqc/shop/instances/: context canceled — its records are unseen this pass
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 00:23:29 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: listing apps/bqd/: listdirs refused — its records are unseen this pass
2026/10/24 00:23:29 provision: record view: change index unusable (get refused): walking
2026/10/24 00:23:29 provision: minted instance route one.example.com (app "shop" acct "bum")
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: removed retired instance route one.example.com (record gone)
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: skipping accounts/bqd/account.json: malformed account manifest: invalid character 'n' looking for beginning of object key string
2026/10/24 00:23:29 provision: minted instance route one.example.com (app "shop" acct "bum")
2026/10/24 00:23:29 provision: skipping accounts/bqd/account.json: malformed account manifest: invalid character 'n' looking for beginning of object key string
2026/10/24 00:23:29 provision: skipping accounts/bqd/account.json: malformed account manifest: invalid character 'n' looking for beginning of object key string
2026/10/24 00:23:29 provision: record view: re-reading accounts/bqd failed: retrying on the next refresh
2026/10/24 00:23:29 provision: skipping accounts/bqd/account.json: read failed: list refused
2026/10/24 00:23:29 provision: skipping record apps/bum/shop/instances/one.example.com.json: empty channel
2026/10/24 00:23:29 provision: not removing one.example.com: its record exists but could not be read cleanly this pass
2026/10/24 00:23:29 provision: skipping record apps/bum/shop/instances/one.example.com.json: empty channel
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: not removing one.example.com: its record exists but could not be read cleanly this pass
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: minted instance route one.example.com (app "shop" acct "bum")
2026/10/24 00:23:29 provision: removed retired instance route one.example.com (record gone)
2026/10/24 00:23:29 provision: record view: change index unusable (context deadline exceeded): walking
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/24 00:23:29 provision: record view: change index unusable (context deadline exceeded): the walk records no generations
2026/10/24 00:23:29 provision: skipping record apps/bqe/store/instances/bad.store.example.com.json: malformed: provision: invalid maintenance projection or protected fields
--- FAIL: TestPlan14RootReadCensus (20.36s)
plan14_root_reads_test.go:1447: root read census: 11 discrepancies
changed root read internal/domains/reconcile.go:Reconcile; review class, task, sites and digest
changed root read internal/host/layoutleg.go:layoutStatusReport; review class, task, sites and digest
changed root read internal/host/layoutleg.go:unmanagedLayoutReport; review class, task, sites and digest
changed root source envelope internal/console
changed root source envelope internal/domains
changed root source envelope internal/host
changed root source envelope internal/status
unclassified root read internal/domains/reconcile.go:platformGate registry:App@144,registry:Gate@242,registry:Gate@268,registry:Gate@314,registry:Platform@129,whole:Route@115,whole:Route@184,whole:Route@232,whole:Route@236
unclassified root read internal/domains/reconcile.go:servesSame registry:Addr@114,registry:Addr@137,registry:Addr@148,registry:Channel@213,registry:Channel@233,registry:Channel@247,registry:Kind@161,registry:Kind@190,registry:Socket@61,registry:Socket@86,registry:Socket@99
unclassified root read internal/host/layoutleg.go:mintedAliasOf registry:App@209,registry:App@218,registry:Host@188,registry:Host@198,registry:Host@262,registry:Platform@174,registry:Platform@85,registry:Socket@100,registry:Socket@228,registry:Socket@240,whole:Route@159
changed legacy declaration internal/domains/reconcile.go:Reconcile
FAIL
FAIL github.com/carlosframework/platform/internal/provision 33.102s
ok github.com/carlosframework/platform/internal/publicrelease 0.008s
? github.com/carlosframework/platform/internal/regionname [no test files]
ok github.com/carlosframework/platform/internal/registry 7.178s
ok github.com/carlosframework/platform/internal/relay 7.383s
ok github.com/carlosframework/platform/internal/release 32.777s
ok github.com/carlosframework/platform/internal/rollout 5.400s
ok github.com/carlosframework/platform/internal/rolloutwords 0.005s
ok github.com/carlosframework/platform/internal/rootaws 0.052s
ok github.com/carlosframework/platform/internal/rootparticipation 0.071s
ok github.com/carlosframework/platform/internal/rootstate 0.033s
ok github.com/carlosframework/platform/internal/runs 0.620s
ok github.com/carlosframework/platform/internal/s3compat 0.005s
ok github.com/carlosframework/platform/internal/safefile 0.015s
ok github.com/carlosframework/platform/internal/schedule 3.903s
ok github.com/carlosframework/platform/internal/seeds 0.027s
ok github.com/carlosframework/platform/internal/sim/engines 6.785s
ok github.com/carlosframework/platform/internal/sim/hostlife 23.739s
ok github.com/carlosframework/platform/internal/sim/litestreamfacts 4.707s
ok github.com/carlosframework/platform/internal/status 0.130s
ok github.com/carlosframework/platform/internal/steering 0.020s
ok github.com/carlosframework/platform/internal/stopevidence 0.536s
ok github.com/carlosframework/platform/internal/svcrole 0.009s
ok github.com/carlosframework/platform/internal/telemetry 0.008s
ok github.com/carlosframework/platform/internal/termfence 0.008s
ok github.com/carlosframework/platform/internal/tunnelclient 0.004s
ok github.com/carlosframework/platform/internal/unixdial 0.005s
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 2.013s
FAIL
=== internal_console@0 (89 s)
ok github.com/carlosframework/platform/internal/console 85.863s
=== internal_console@1 (52 s)
ok github.com/carlosframework/platform/internal/console 48.663s
=== internal_console@2 (49 s)
ok github.com/carlosframework/platform/internal/console 46.172s
=== internal_console@3 (51 s)
ok github.com/carlosframework/platform/internal/console 47.983s
=== internal_console@4 (46 s)
ok github.com/carlosframework/platform/internal/console 42.374s
=== internal_console@5 (47 s)
ok github.com/carlosframework/platform/internal/console 44.369s
=== internal_console@6 (54 s)
ok github.com/carlosframework/platform/internal/console 50.729s
=== internal_console@7 (53 s)
ok github.com/carlosframework/platform/internal/console 50.059s
=== root@0 (120 s)
ok github.com/carlosframework/platform 117.406s
=== root@1 (90 s)
ok github.com/carlosframework/platform 87.313s
=== root@2 (101 s)
ok github.com/carlosframework/platform 98.027s
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/docs/site/cli.md b/docs/site/cli.md| index 0a8e384f2..1cd16415e 100644 |
| --- a/docs/site/cli.md |
| +++ b/docs/site/cli.md |
| @@ -1187,8 +1187,12 @@ carlos gate clear --app site |
| stdin, so it need not land in your shell history. Without `--host` the |
| change applies to every instance of the app; name one to narrow it. Changing |
| or clearing the password signs every visitor out at once. Custom domains |
| -attached to the app are gated along with the platform hostname. This is a |
| -curtain in front of the whole hostname, not accounts for the app's own |
| +attached to the app are gated along with the platform hostname. So is the |
| +app's own domain (`<app>.<account>.<apps-domain>`), which serves one of its |
| +instances: it takes that instance's password, or, if that one has none and |
| +another instance does, the other's, so it is never the open way round a |
| +gated instance. It follows a password change within a few minutes rather |
| +than seconds. This is a curtain in front of the whole hostname, not accounts for the app's own |
| users; an app with real sign-in keeps doing that itself. |
| ### carlos logs |
diff --git a/internal/console/apistatuslayout.go b/internal/console/apistatuslayout.go| index 9471f25e4..c06b0fbe0 100644 |
| --- a/internal/console/apistatuslayout.go |
| +++ b/internal/console/apistatuslayout.go |
| @@ -60,7 +60,9 @@ type apiStatusLayoutBox struct { |
| // half (plan 5) keeps the warning loud for a box that has gone nested but |
| // whose only remaining rows are the ones the pass cannot move: with no |
| // nested row left to stand beside, they would otherwise read as clean. |
| -// Fenced and conflict rows are stopped and count for neither side. |
| +// Fenced and conflict rows are stopped and count for neither side, and a |
| +// platform row (a minted domain proxying another row's socket) runs no |
| +// process of its own, so it counts for neither side either. |
| func layoutMixed(mode string, rows []apiStatusLayoutRow) bool { |
| nested, unisolated := mode == "nested", false |
| for _, r := range rows { |
diff --git a/internal/console/apistatuslayout_test.go b/internal/console/apistatuslayout_test.go| index c0f81efb9..e71fcce4f 100644 |
| --- a/internal/console/apistatuslayout_test.go |
| +++ b/internal/console/apistatuslayout_test.go |
| @@ -208,3 +208,82 @@ func TestLayoutMixedNeedsANestedAndAFlatRow(t *testing.T) { |
| } |
| } |
| } |
| + |
| +// A platform row (a minted domain proxying another row's socket) runs no |
| +// process of its own: it never makes a box mixed, but an external one does. |
| +func TestLayoutMixedIgnoresPlatformRows(t *testing.T) { |
| + row := func(host, layout string) apiStatusLayoutRow { |
| + return apiStatusLayoutRow{Host: host, Layout: layout} |
| + } |
| + nested := row("a.example.com", "nested") |
| + if layoutMixed("nested", []apiStatusLayoutRow{nested, row("example.com", "platform")}) { |
| + t.Error("nested + platform under a nested intent is mixed") |
| + } |
| + if layoutMixed("flat", []apiStatusLayoutRow{nested, row("example.com", "platform")}) { |
| + t.Error("nested + platform under a flat intent is mixed") |
| + } |
| + if layoutMixed("nested", []apiStatusLayoutRow{row("example.com", "platform")}) { |
| + t.Error("a lone platform row is mixed") |
| + } |
| + if !layoutMixed("nested", []apiStatusLayoutRow{nested, row("example.com", "platform"), row("x.example.com", "external")}) { |
| + t.Error("an external row beside nested and platform is not mixed") |
| + } |
| +} |
| + |
| +// Through the door: a box of nested rows plus a platform apex is not Mixed, |
| +// and the platform row's word and reason come through. |
| +func TestAPIStatusLayoutPlatformRowIsNotMixed(t *testing.T) { |
| + fx := newConsoleFixture(t) |
| + token := cliToken(t, fx, "paul@keymail.dev", "code-apistatuslayoutplatform") |
| + if err := fx.st.SetOperator("paul@keymail.dev", true); err != nil { |
| + t.Fatal(err) |
| + } |
| + seedLayoutBox(t, fx.rel, "platform-box", time.Now(), &status.LayoutReport{ |
| + Mode: "nested", |
| + Rows: map[string]status.RowLayout{ |
| + "app.example.com": {Layout: "nested"}, |
| + "example.com": {Layout: "platform", Reason: "platform domain: proxies app.example.com; runs no process of its own"}, |
| + }, |
| + }) |
| + seedLayoutBox(t, fx.rel, "external-box", time.Now(), &status.LayoutReport{ |
| + Mode: "nested", |
| + Rows: map[string]status.RowLayout{ |
| + "app.example.com": {Layout: "nested"}, |
| + "example.com": {Layout: "platform"}, |
| + "ext.example.com": {Layout: "external"}, |
| + }, |
| + }) |
| + code, body := getBearer(t, fx.ts.URL+"/api/cli/status/layout", token) |
| + if code != http.StatusOK { |
| + t.Fatalf("GET /api/cli/status/layout = %d %q", code, body) |
| + } |
| + var out struct { |
| + Boxes []apiStatusLayoutBox `json:"boxes"` |
| + } |
| + if err := json.Unmarshal(body, &out); err != nil { |
| + t.Fatalf("unreadable: %v: %s", err, body) |
| + } |
| + byLabel := map[string]apiStatusLayoutBox{} |
| + for _, b := range out.Boxes { |
| + byLabel[b.Box] = b |
| + } |
| + pb, ok := byLabel["platform-box"] |
| + if !ok { |
| + t.Fatalf("boxes = %+v, want platform-box", out.Boxes) |
| + } |
| + if pb.Mixed { |
| + t.Errorf("platform-box = %+v, want not Mixed", pb) |
| + } |
| + var found bool |
| + for _, r := range pb.Rows { |
| + if r.Host == "example.com" { |
| + found = r.Layout == "platform" && r.Reason != "" |
| + } |
| + } |
| + if !found { |
| + t.Errorf("platform-box rows = %+v, want the platform row with its reason", pb.Rows) |
| + } |
| + if !byLabel["external-box"].Mixed { |
| + t.Errorf("external-box = %+v, want Mixed", byLabel["external-box"]) |
| + } |
| +} |
diff --git a/internal/domains/reconcile.go b/internal/domains/reconcile.go| index cd69ca76a..9bd49b3ff 100644 |
| --- a/internal/domains/reconcile.go |
| +++ b/internal/domains/reconcile.go |
| @@ -310,6 +310,9 @@ func Reconcile(ctx context.Context, s release.Store, reg *registry.Registry, cfg |
| continue // nothing serving to copy an upstream from; next pass |
| } |
| nr := mintedRoute(host, k.app, k.acct, *src) |
| + // Born gated when it must be (section 6 keeps it so): an apex |
| + // minted open and gated a moment later is open for that moment. |
| + nr.Gate = platformGate(routes, k, nr) |
| if err := reg.Upsert(nr); err != nil { |
| log.Printf("domains: mint %s: %v", host, err) |
| continue |
| @@ -373,6 +376,7 @@ func Reconcile(ctx context.Context, s release.Store, reg *registry.Registry, cfg |
| nr := mintedRoute(host, app, acct, *src) |
| nr.Channel = channel |
| nr.Canary = true |
| + nr.Gate = platformGate(routes, k, nr) |
| if err := reg.Upsert(nr); err != nil { |
| log.Printf("domains: mint canary %s: %v", host, err) |
| continue |
| @@ -404,6 +408,31 @@ func Reconcile(ctx context.Context, s release.Store, reg *registry.Registry, cfg |
| } |
| routes = kept |
| + // --- 6. gates on minted routes --------------------------------------------- |
| + // A minted route proxies a socket (or serves a channel) that one of the |
| + // app's own routes already serves, so it must not be a way round that |
| + // route's password: the apex of an app whose instances are all gated |
| + // served the first one's process, /dev/mail and all, to anyone who |
| + // asked. Converged on every pass, not stamped at mint alone, because a |
| + // gate is set, changed and cleared on the instance record long after |
| + // the apex exists; SetGate rather than Upsert, because Upsert keeps a |
| + // set gate against an empty one and so could never clear it. |
| + for _, rt := range routes { |
| + if !rt.Platform { |
| + continue |
| + } |
| + k := appKey{release.RouteAccount(rt), rt.App} |
| + want := platformGate(routes, k, rt) |
| + if rt.Gate == want { |
| + continue |
| + } |
| + if err := reg.SetGate(rt.Host, want); err != nil { |
| + log.Printf("domains: converge gate on %s: %v", rt.Host, err) |
| + continue |
| + } |
| + log.Printf("domains: converged %s gate %s -> %s", rt.Host, gateWord(rt.Gate), gateWord(want)) |
| + } |
| + |
| // Sections 4 and 5 — the per-box health stamps — live in StampHealth |
| // (#303): they write THIS box's registry and must run on every box, not |
| // only on the housekeeper this pass is gated to. The agent runs it once |
| @@ -900,6 +929,59 @@ func mintedRoute(host, app, account string, src registry.Route) registry.Route { |
| return rt |
| } |
| +// platformGate is the gate a minted route p of app k must carry: the gate |
| +// of the route it serves from — the app's own route with the same Socket, |
| +// the same Addr or, for a static route, the same Channel — and, when that |
| +// one is open, the first gate any other route of the app carries, in host |
| +// order. Open only when every route of the app is open. |
| +// |
| +// The fallback is what makes it fail closed. A source can be ungated while |
| +// a sibling is gated (the operator gated some instances and not others, or |
| +// the source is unidentifiable: a fleet-placed mint copies no socket), and |
| +// "the app has a password" is the stronger statement about the apex than |
| +// "the process it happens to proxy has none". The fallback is a REAL hash, |
| +// never a sentinel: internal/gate derives the cookie key from the hash |
| +// alone, so a well-known "closed" value would be a key anybody could mint |
| +// a valid cookie with. |
| +func platformGate(routes []registry.Route, k appKey, p registry.Route) string { |
| + sibling := "" |
| + for _, rt := range routes { |
| + if rt.Platform || rt.App != k.app || release.RouteAccount(rt) != k.acct { |
| + continue |
| + } |
| + if servesSame(rt, p) && rt.Gate != "" { |
| + return rt.Gate |
| + } |
| + if sibling == "" { |
| + sibling = rt.Gate |
| + } |
| + } |
| + return sibling |
| +} |
| + |
| +// servesSame reports whether minted route p was copied from rt: the same |
| +// proxy upstream, or for a static route the same channel (mintedRoute's |
| +// copy rules). |
| +func servesSame(rt, p registry.Route) bool { |
| + switch { |
| + case p.Socket != "": |
| + return rt.Socket == p.Socket |
| + case p.Addr != "": |
| + return rt.Addr == p.Addr |
| + case p.Kind == "static": |
| + return rt.Kind == "static" && rt.Channel != "" && rt.Channel == p.Channel |
| + } |
| + return false |
| +} |
| + |
| +// gateWord names a gate in a log line without printing the hash. |
| +func gateWord(hash string) string { |
| + if hash == "" { |
| + return "open" |
| + } |
| + return "gated" |
| +} |
| + |
| // hostCertExpiry resolves host's cert expiry from the acme cache dir as the |
| // LATER of the per-host autocert entry and the covering wildcard's PEM |
| // (wildcard-<parent>.pem). Two reasons a bare per-host lookup isn't enough: a |
diff --git a/internal/domains/reconcile_test.go b/internal/domains/reconcile_test.go| index 4e72b2936..ca04fba92 100644 |
| --- a/internal/domains/reconcile_test.go |
| +++ b/internal/domains/reconcile_test.go |
| @@ -24,6 +24,7 @@ import ( |
| "time" |
| "github.com/carlosframework/platform/internal/domains" |
| + "github.com/carlosframework/platform/internal/gate" |
| "github.com/carlosframework/platform/internal/registry" |
| "github.com/carlosframework/platform/internal/release" |
| ) |
| @@ -1442,3 +1443,146 @@ func TestAccountManifestSqidIgnoresLimitsRecord(t *testing.T) { |
| t.Fatal("accounts/abc/limits.json parsed as an account manifest") |
| } |
| } |
| + |
| +// gatedInstance is a ready instance route on its own socket, with the given |
| +// gate ("" = open). |
| +func gatedInstance(host, app, sock, hash string) registry.Route { |
| + return registry.Route{Host: host, Kind: "instance", App: app, Status: "ready", |
| + Socket: sock, Gate: hash} |
| +} |
| + |
| +func reconcileOnce(t *testing.T, s release.Store, reg *registry.Registry) { |
| + t.Helper() |
| + if err := domains.Reconcile(ctx, s, reg, cfg(t)); err != nil { |
| + t.Fatal(err) |
| + } |
| +} |
| + |
| +// The apex is born gated: checked after the FIRST pass, not a later one. |
| +func TestReconcileMintedApexCarriesTheSourceGate(t *testing.T) { |
| + s, reg := dirStore(t), regWith(t, gatedInstance("kass.training", "kass", "/run/kass.sock", "$2a$10$sourcehash")) |
| + reconcileOnce(t, s, reg) |
| + got := mustGet(t, reg, "kass.bab.oncarlos.test") |
| + if !got.Platform || got.Socket != "/run/kass.sock" { |
| + t.Fatalf("minted route = %+v", got) |
| + } |
| + if got.Gate != "$2a$10$sourcehash" { |
| + t.Errorf("apex Gate after first pass = %q, want the source's", got.Gate) |
| + } |
| +} |
| + |
| +// A real bcrypt hash travels verbatim. |
| +func TestReconcileMintedApexCarriesARealBcryptHash(t *testing.T) { |
| + hash, err := gate.Hash("correct horse battery") |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + s, reg := dirStore(t), regWith(t, gatedInstance("kass.training", "kass", "/run/kass.sock", hash)) |
| + reconcileOnce(t, s, reg) |
| + got := mustGet(t, reg, "kass.bab.oncarlos.test") |
| + if got.Gate != hash || !strings.HasPrefix(got.Gate, "$2") { |
| + t.Errorf("apex Gate = %q, want %q", got.Gate, hash) |
| + } |
| +} |
| + |
| +// Set, change and clear on the source all reach the apex; clearing is the |
| +// path Upsert cannot do. |
| +func TestReconcileMintedApexGateConverges(t *testing.T) { |
| + s, reg := dirStore(t), regWith(t, gatedInstance("kass.training", "kass", "/run/kass.sock", "")) |
| + reconcileOnce(t, s, reg) |
| + if g := mustGet(t, reg, "kass.bab.oncarlos.test").Gate; g != "" { |
| + t.Fatalf("apex Gate before any gate is set = %q, want open", g) |
| + } |
| + for _, step := range []struct{ set, want string }{ |
| + {"hashA", "hashA"}, |
| + {"hashB", "hashB"}, |
| + {"", ""}, |
| + } { |
| + if err := reg.SetGate("kass.training", step.set); err != nil { |
| + t.Fatal(err) |
| + } |
| + reconcileOnce(t, s, reg) |
| + if g := mustGet(t, reg, "kass.bab.oncarlos.test").Gate; g != step.want { |
| + t.Errorf("source gate %q: apex Gate = %q, want %q", step.set, g, step.want) |
| + } |
| + } |
| +} |
| + |
| +// The minted source (first ready in host order) is open while a sibling is |
| +// gated: the apex takes the sibling's real hash rather than staying open. |
| +func TestReconcileMintedApexFailsClosedOnMixedGates(t *testing.T) { |
| + t.Run("mint", func(t *testing.T) { |
| + s, reg := dirStore(t), regWith(t, |
| + gatedInstance("a.kass.training", "kass", "/run/a.sock", ""), |
| + gatedInstance("b.kass.training", "kass", "/run/b.sock", "hashB"), |
| + ) |
| + reconcileOnce(t, s, reg) |
| + got := mustGet(t, reg, "kass.bab.oncarlos.test") |
| + if got.Socket != "/run/a.sock" { |
| + t.Fatalf("minted from socket %q, want the first host's /run/a.sock", got.Socket) |
| + } |
| + if got.Gate != "hashB" { |
| + t.Errorf("apex Gate = %q, want the sibling's hashB", got.Gate) |
| + } |
| + }) |
| + t.Run("converge", func(t *testing.T) { |
| + s, reg := dirStore(t), regWith(t, |
| + gatedInstance("a.kass.training", "kass", "/run/a.sock", ""), |
| + gatedInstance("b.kass.training", "kass", "/run/b.sock", "hashB"), |
| + registry.Route{Host: "kass.bab.oncarlos.test", Kind: "instance", App: "kass", |
| + Status: "ready", Socket: "/run/a.sock", Platform: true, Account: "bab"}, |
| + ) |
| + reconcileOnce(t, s, reg) |
| + if g := mustGet(t, reg, "kass.bab.oncarlos.test").Gate; g != "hashB" { |
| + t.Errorf("existing apex Gate = %q, want the sibling's hashB", g) |
| + } |
| + }) |
| + t.Run("own source wins", func(t *testing.T) { |
| + // The apex serves b's socket, so b's gate beats a's earlier one. |
| + s, reg := dirStore(t), regWith(t, |
| + gatedInstance("a.kass.training", "kass", "/run/a.sock", "hashA"), |
| + gatedInstance("b.kass.training", "kass", "/run/b.sock", "hashB"), |
| + registry.Route{Host: "kass.bab.oncarlos.test", Kind: "instance", App: "kass", |
| + Status: "ready", Socket: "/run/b.sock", Platform: true, Account: "bab"}, |
| + ) |
| + reconcileOnce(t, s, reg) |
| + if g := mustGet(t, reg, "kass.bab.oncarlos.test").Gate; g != "hashB" { |
| + t.Errorf("apex Gate = %q, want its own source's hashB", g) |
| + } |
| + }) |
| +} |
| + |
| +func TestReconcileMintedApexStaysOpenWhenNothingIsGated(t *testing.T) { |
| + s, reg := dirStore(t), regWith(t, |
| + gatedInstance("a.kass.training", "kass", "/run/a.sock", ""), |
| + gatedInstance("b.kass.training", "kass", "/run/b.sock", ""), |
| + ) |
| + reconcileOnce(t, s, reg) |
| + reconcileOnce(t, s, reg) |
| + if g := mustGet(t, reg, "kass.bab.oncarlos.test").Gate; g != "" { |
| + t.Errorf("apex Gate = %q, want open", g) |
| + } |
| +} |
| + |
| +// One app's gate never reaches another app's apex, in the same account or |
| +// under the same app name in another account. |
| +func TestReconcileMintedApexGateDoesNotLeakAcrossApps(t *testing.T) { |
| + s := dirStore(t) |
| + other := writeAccountManifest(t, s, 793481920157, "Other") |
| + x := gatedInstance("x.training", "x", "/run/x.sock", "hashX") |
| + y := gatedInstance("y.training", "y", "/run/y.sock", "") |
| + // Same app name as x, different account, open. |
| + x2 := gatedInstance("x.other.training", "x", "/run/x2.sock", "") |
| + x2.Account = other |
| + reg := regWith(t, x, y, x2) |
| + reconcileOnce(t, s, reg) |
| + if g := mustGet(t, reg, "x.bab.oncarlos.test").Gate; g != "hashX" { |
| + t.Errorf("x apex Gate = %q, want hashX", g) |
| + } |
| + if g := mustGet(t, reg, "y.bab.oncarlos.test").Gate; g != "" { |
| + t.Errorf("y apex Gate = %q, want open: another app's gate leaked", g) |
| + } |
| + if g := mustGet(t, reg, "x."+other+".oncarlos.test").Gate; g != "" { |
| + t.Errorf("other account's x apex Gate = %q, want open: another account's gate leaked", g) |
| + } |
| +} |
diff --git a/internal/edge/gate_test.go b/internal/edge/gate_test.go| index dbeb39b26..4adfb6003 100644 |
| --- a/internal/edge/gate_test.go |
| +++ b/internal/edge/gate_test.go |
| @@ -6,6 +6,7 @@ import ( |
| "net/http/httptest" |
| "net/url" |
| "strings" |
| + "sync/atomic" |
| "testing" |
| "time" |
| @@ -506,3 +507,78 @@ func TestUngatedRouteUnchanged(t *testing.T) { |
| t.Fatalf("ungated route touched: %d cookie=%q", resp.StatusCode, *seen) |
| } |
| } |
| + |
| +// A platform-minted apex row carries its source instance's gate. Cookies |
| +// are host-bound, so the source's cookie does not open the apex; only a |
| +// login on the apex itself does. |
| +func TestPlatformApexRowCarryingTheSourceGateIsGatedOnItsOwn(t *testing.T) { |
| + var hits atomic.Int32 |
| + backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| + hits.Add(1) |
| + io.WriteString(w, "secret page") |
| + })) |
| + t.Cleanup(backend.Close) |
| + h, err := gate.Hash("correct horse") |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + addr := backend.Listener.Addr().String() |
| + reg := openReg(t) |
| + for _, rt := range []registry.Route{ |
| + {Host: "app.example.com", App: "shop", Kind: "instance", Addr: addr, Status: "ready", Gate: h}, |
| + {Host: "example.com", App: "shop", Kind: "instance", Addr: addr, Status: "ready", Gate: h, Platform: true}, |
| + } { |
| + if err := reg.Upsert(rt); err != nil { |
| + t.Fatal(err) |
| + } |
| + } |
| + e, err := New(reg, refusingActivator{t: t}) |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + srv := httptest.NewServer(e) |
| + t.Cleanup(srv.Close) |
| + |
| + for _, path := range []string{"/", "/dev/mail"} { |
| + if resp := doHost(t, srv, http.MethodGet, "example.com", path, ""); resp.StatusCode != http.StatusUnauthorized { |
| + t.Fatalf("apex %s without cookie = %d, want 401", path, resp.StatusCode) |
| + } |
| + } |
| + if hits.Load() != 0 { |
| + t.Fatalf("backend hit %d times without a cookie", hits.Load()) |
| + } |
| + |
| + login := postLogin(t, srv, "app.example.com", "correct horse", "/") |
| + srcCookie := gateCookie(login) |
| + if login.StatusCode != http.StatusSeeOther || srcCookie == "" { |
| + t.Fatalf("source login = %d, cookie %q", login.StatusCode, srcCookie) |
| + } |
| + if resp := doHost(t, srv, http.MethodGet, "app.example.com", "/", gate.CookieName+"="+srcCookie); resp.StatusCode != http.StatusOK { |
| + t.Fatalf("source with its own cookie = %d, want 200", resp.StatusCode) |
| + } |
| + hits.Store(0) |
| + if resp := doHost(t, srv, http.MethodGet, "example.com", "/dev/mail", gate.CookieName+"="+srcCookie); resp.StatusCode != http.StatusUnauthorized { |
| + t.Fatalf("apex with the source's cookie = %d, want 401", resp.StatusCode) |
| + } |
| + if hits.Load() != 0 { |
| + t.Fatalf("backend hit %d times with the source's cookie on the apex", hits.Load()) |
| + } |
| + |
| + wrong := postLogin(t, srv, "example.com", "wrong", "/") |
| + if gateCookie(wrong) != "" || wrong.StatusCode == http.StatusSeeOther { |
| + t.Fatalf("apex login with a wrong password = %d, cookie %q", wrong.StatusCode, gateCookie(wrong)) |
| + } |
| + apexLogin := postLogin(t, srv, "example.com", "correct horse", "/dev/mail") |
| + apexCookie := gateCookie(apexLogin) |
| + if apexLogin.StatusCode != http.StatusSeeOther || apexLogin.Header.Get("Location") != "/dev/mail" || apexCookie == "" { |
| + t.Fatalf("apex login = %d -> %q, cookie %q", apexLogin.StatusCode, apexLogin.Header.Get("Location"), apexCookie) |
| + } |
| + if !gate.Verify(apexCookie, "example.com", h, time.Now()) || gate.Verify(apexCookie, "app.example.com", h, time.Now()) { |
| + t.Fatal("apex cookie must verify for the apex host only") |
| + } |
| + resp := doHost(t, srv, http.MethodGet, "example.com", "/dev/mail", gate.CookieName+"="+apexCookie) |
| + b, _ := io.ReadAll(resp.Body) |
| + if resp.StatusCode != http.StatusOK || string(b) != "secret page" || hits.Load() != 1 { |
| + t.Fatalf("apex with its own cookie = %d %q (hits %d), want 200 and one backend hit", resp.StatusCode, b, hits.Load()) |
| + } |
| +} |
diff --git a/internal/host/agent_layout_test.go b/internal/host/agent_layout_test.go| index 849a38bc0..2334ecaf3 100644 |
| --- a/internal/host/agent_layout_test.go |
| +++ b/internal/host/agent_layout_test.go |
| @@ -671,6 +671,72 @@ func TestLayoutStatusReportRowsCoverOnlyInstanceKindRoutes(t *testing.T) { |
| } |
| } |
| +// platformPair is a nested source row and the Platform apex row minted onto |
| +// its socket (different host, same app). |
| +func platformPair(dd string) (src, apex registry.Route) { |
| + src = registry.Route{Host: "app.example.com", App: "shop", Kind: "instance", Hibernate: true, |
| + DBPath: provision.NestedDBPath(dd, "app.example.com"), Socket: provision.NestedSocket("app.example.com")} |
| + apex = registry.Route{Host: "example.com", App: "shop", Kind: "instance", Platform: true, |
| + Socket: src.Socket} |
| + return src, apex |
| +} |
| + |
| +// A Platform row proxying a sibling's socket is "platform" in the unmanaged |
| +// report; one whose socket nobody else has keeps its old classification. |
| +func TestUnmanagedLayoutReportPlatformRowProxiesItsSource(t *testing.T) { |
| + resetLayoutGlobals(t) |
| + t.Setenv("CARLOS_DATA_DIR", "/data") |
| + src, apex := platformPair("/data") |
| + orphan := registry.Route{Host: "orphan.example.com", App: "shop", Kind: "instance", Platform: true, |
| + Socket: provision.DefaultSocket("orphan.example.com")} |
| + got := layoutStatusReport([]registry.Route{src, apex, orphan}) |
| + if got == nil || got.Mode != LayoutModeUnmanaged { |
| + t.Fatalf("report = %+v, want unmanaged", got) |
| + } |
| + if r := got.Rows[src.Host]; r.Layout != "nested" { |
| + t.Errorf("source = %+v, want nested", r) |
| + } |
| + r := got.Rows[apex.Host] |
| + if r.Layout != LayoutPlatform || !strings.Contains(r.Reason, src.Host) { |
| + t.Errorf("apex = %+v, want platform with a reason naming %s", r, src.Host) |
| + } |
| + if r := got.Rows[orphan.Host]; r.Layout != "external" { |
| + t.Errorf("orphan = %+v, want external", r) |
| + } |
| +} |
| + |
| +// The same with a pass armed: the apex is "platform", not "external". |
| +// Armed the way TestLayoutStatusReportRowsCoverOnlyInstanceKindRoutes does. |
| +func TestLayoutStatusReportPlatformRowProxiesItsSource(t *testing.T) { |
| + resetLayoutGlobals(t) |
| + dd, sd := t.TempDir(), t.TempDir() |
| + armedLayoutPass.Store(&layout.Pass{DataDir: dd, SocketDir: sd}) |
| + noteLayoutIntent(release.LayoutModeNested) |
| + src, apex := platformPair(dd) |
| + orphan := registry.Route{Host: "orphan.example.com", App: "shop", Kind: "instance", Platform: true, |
| + Socket: "/elsewhere/orphan.sock"} |
| + // Same socket as the source but another app: not its alias. |
| + other := registry.Route{Host: "other.example.com", App: "blog", Kind: "instance", Platform: true, |
| + Socket: src.Socket} |
| + |
| + got := layoutStatusReport([]registry.Route{src, apex, orphan, other}) |
| + if got == nil || got.Mode != "nested" { |
| + t.Fatalf("report = %+v, want mode nested", got) |
| + } |
| + r := got.Rows[apex.Host] |
| + if r.Layout != LayoutPlatform || !strings.Contains(r.Reason, src.Host) { |
| + t.Errorf("apex = %+v, want platform with a reason naming %s", r, src.Host) |
| + } |
| + if r := got.Rows[src.Host]; r.Layout == LayoutPlatform || r.Layout == "" { |
| + t.Errorf("source = %+v, want its own Classify word", r) |
| + } |
| + for _, host := range []string{orphan.Host, other.Host} { |
| + if r := got.Rows[host]; r.Layout != "external" { |
| + t.Errorf("%s = %+v, want external", host, r) |
| + } |
| + } |
| +} |
| + |
| // Landing follow-up 3: a held host makes the leg come back on its own, so |
| // an operator who clears the reason on a quiet fleet waits awakeRetry and |
| // not the next serial move; an all-quiet result does not. |
diff --git a/internal/host/layoutleg.go b/internal/host/layoutleg.go| index 37d3b88b5..7dca9c0c2 100644 |
| --- a/internal/host/layoutleg.go |
| +++ b/internal/host/layoutleg.go |
| @@ -197,6 +197,10 @@ func layoutStatusReport(routes []registry.Route) *status.LayoutReport { |
| if rt.Kind != "instance" { |
| continue |
| } |
| + if src, ok := mintedAliasOf(rt, routes); ok { |
| + rows[rt.Host] = platformRowLayout(src) |
| + continue |
| + } |
| switch { |
| case activator.ActivatorManaged(rt): |
| word, reason := pass.Classify(rt, routes) |
| @@ -236,6 +240,10 @@ func unmanagedLayoutReport(routes []registry.Route) *status.LayoutReport { |
| if rt.Kind != "instance" { |
| continue |
| } |
| + if src, ok := mintedAliasOf(rt, routes); ok { |
| + rows[rt.Host] = platformRowLayout(src) |
| + continue |
| + } |
| switch { |
| case layout.JournalPresent(dd, rt.Host): |
| rows[rt.Host] = status.RowLayout{Layout: string(activator.LayoutFenced), Reason: "layout migration in flight; see " + provision.LayoutJournalPath(dd, rt.Host) + " (no activator on this box to recover it)"} |
| @@ -252,6 +260,39 @@ func unmanagedLayoutReport(routes []registry.Route) *status.LayoutReport { |
| return &status.LayoutReport{Mode: LayoutModeUnmanaged, Rows: rows} |
| } |
| +// LayoutPlatform is the report word for a platform-minted route (the |
| +// domains pass's app apex) that proxies another of the box's routes' |
| +// socket. It spawns nothing and runs nothing: the process behind it is the |
| +// source row's, reported under the source's own host. Before this word it |
| +// fell through to "external" (an unflagged socket route), which counted |
| +// toward the mixed-layout warning and told the operator that nested |
| +// isolation was not in force on a box where every process was nested. Old |
| +// consoles ignore a word they do not know in both the warning |
| +// (layoutMixed) and the downgrade guard, which is the right answer for it |
| +// in each. |
| +const LayoutPlatform = "platform" |
| + |
| +// mintedAliasOf names the route whose socket platform-minted rt proxies, |
| +// when it is one: Platform, a socket, and that socket served by a |
| +// non-platform row of the same app on this box. A Platform row matching |
| +// none keeps its old classification, because then nothing on the box |
| +// accounts for whatever is listening there. |
| +func mintedAliasOf(rt registry.Route, routes []registry.Route) (string, bool) { |
| + if !rt.Platform || rt.Socket == "" { |
| + return "", false |
| + } |
| + for _, o := range routes { |
| + if !o.Platform && o.Host != rt.Host && o.App == rt.App && o.Socket == rt.Socket { |
| + return o.Host, true |
| + } |
| + } |
| + return "", false |
| +} |
| + |
| +func platformRowLayout(src string) status.RowLayout { |
| + return status.RowLayout{Layout: LayoutPlatform, Reason: "platform domain: proxies " + src + "; runs no process of its own"} |
| +} |
| + |
| // reloadRouting asks the live edge to rebuild its routes now, if there is |
| // one yet. |
| func reloadRouting() { |
diff --git a/internal/status/snapshot.go b/internal/status/snapshot.go| index 4dd9ef44a..868515ed5 100644 |
| --- a/internal/status/snapshot.go |
| +++ b/internal/status/snapshot.go |
| @@ -222,11 +222,13 @@ type HostUpdates struct { |
| // RowLayout is one instance-kind route's layout, as the box's layout pass |
| // classified it (activator.Classify): Layout is one of flat, nested, |
| -// fenced, conflict, foreign or external, and Reason carries the detail for |
| -// anything but flat and nested — a path, or another row's host — which is |
| -// why it is never shown on the console's instance page (see |
| -// instancepage.go's handleAppInstance): a member sees the word, an operator |
| -// reading status/boxes/<label>.json sees the reason too. |
| +// fenced, conflict, foreign or external, or platform (a minted route that |
| +// proxies another row's socket and runs nothing, host.LayoutPlatform), and |
| +// Reason carries the detail for anything but flat and nested — a path, or |
| +// another row's host — which is why it is never shown on the console's |
| +// instance page (see instancepage.go's handleAppInstance): a member sees |
| +// the word, an operator reading status/boxes/<label>.json sees the reason |
| +// too. |
| type RowLayout struct { |
| Layout string `json:"layout"` |
| Reason string `json:"reason,omitempty"` |