WIP claim Plan 14 track E checkpoint 17 (not for merge): E1 operator workflow
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 files changed,
+509
−13
internal/historyreadback/plan14_workflow_process_test.go+171 −0internal/historyreadback/plan14_workflow_test.go+167 −0internal/historyreadback/readback.go+18 −10internal/historyreadback/workflow.go+141 −0internal/provision/plan14_e_write_census_test.go+1 −0internal/provision/testdata/plan14-root-reads-e.tsv+11 −3
CI failed — run details
CI log
=== gate ===
cd launchctx && go vet ./... && go test ./... -count=1
ok amadan.net/carlos/platform.git/launchctx 0.011s
? amadan.net/carlos/platform.git/launchctx/controlname [no test files]
? amadan.net/carlos/platform.git/launchctx/wireid [no test files]
go vet ./...
gofmt -l .: clean
go test ./... -count=1 -timeout 30m
ok github.com/carlosframework/platform 352.551s
? github.com/carlosframework/platform/cmd/changelog [no test files]
ok github.com/carlosframework/platform/cmd/console 3.063s
ok github.com/carlosframework/platform/cmd/moveprobe 92.250s
ok github.com/carlosframework/platform/cmd/zddprobe 0.712s
ok github.com/carlosframework/platform/internal/activator 233.538s
ok github.com/carlosframework/platform/internal/agentsock 0.023s
ok github.com/carlosframework/platform/internal/alerting 0.004s
ok github.com/carlosframework/platform/internal/analytics 0.024s
ok github.com/carlosframework/platform/internal/appconfig 2.394s
ok github.com/carlosframework/platform/internal/apperr 0.079s
ok github.com/carlosframework/platform/internal/applog 0.140s
ok github.com/carlosframework/platform/internal/awsinv 0.004s
ok github.com/carlosframework/platform/internal/boxchoice 0.006s
ok github.com/carlosframework/platform/internal/boxid 0.675s
? 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.008s
ok github.com/carlosframework/platform/internal/caps 0.014s
ok github.com/carlosframework/platform/internal/certwarm 0.002s
ok github.com/carlosframework/platform/internal/cgroup 0.694s
ok github.com/carlosframework/platform/internal/changelog 0.322s
ok github.com/carlosframework/platform/internal/clamd 0.055s
? github.com/carlosframework/platform/internal/cliflag [no test files]
ok github.com/carlosframework/platform/internal/console 367.133s
? 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 5.708s
ok github.com/carlosframework/platform/internal/dbdoor/dbdoortest 0.009s
ok github.com/carlosframework/platform/internal/dbverify 0.004s
ok github.com/carlosframework/platform/internal/dnsrec 0.004s
ok github.com/carlosframework/platform/internal/docsite 0.004s
ok github.com/carlosframework/platform/internal/domains 2.151s
ok github.com/carlosframework/platform/internal/doorkey 0.006s
ok github.com/carlosframework/platform/internal/economics 0.005s
ok github.com/carlosframework/platform/internal/edge 26.315s
? github.com/carlosframework/platform/internal/edgeproof [no test files]
ok github.com/carlosframework/platform/internal/edgesfile 0.008s
ok github.com/carlosframework/platform/internal/fleetapi 0.126s
ok github.com/carlosframework/platform/internal/gate 1.679s
ok github.com/carlosframework/platform/internal/genselect 0.015s
ok github.com/carlosframework/platform/internal/geo 0.019s
ok github.com/carlosframework/platform/internal/geoip 0.032s
ok github.com/carlosframework/platform/internal/historyreadback 0.159s
ok github.com/carlosframework/platform/internal/host 133.007s
ok github.com/carlosframework/platform/internal/hostactors 0.336s
ok github.com/carlosframework/platform/internal/hostbox 2.160s
ok github.com/carlosframework/platform/internal/hostclaim 0.517s
ok github.com/carlosframework/platform/internal/hostevidence 0.014s
ok github.com/carlosframework/platform/internal/hostexec 4.989s
ok github.com/carlosframework/platform/internal/hostfence 0.032s
ok github.com/carlosframework/platform/internal/hostfiles 10.546s
ok github.com/carlosframework/platform/internal/hostfloor 0.014s
ok github.com/carlosframework/platform/internal/hostguard 0.964s
ok github.com/carlosframework/platform/internal/hostops 1.463s
? github.com/carlosframework/platform/internal/hostops/fencerelease [no test files]
ok github.com/carlosframework/platform/internal/hostops/internal/fencerelease 0.002s
ok github.com/carlosframework/platform/internal/hostquarantine 0.002s
ok github.com/carlosframework/platform/internal/hostrelocate 0.469s
ok github.com/carlosframework/platform/internal/hostresolve 0.141s
ok github.com/carlosframework/platform/internal/hostwrite 0.002s
ok github.com/carlosframework/platform/internal/infraview 0.002s
ok github.com/carlosframework/platform/internal/instancectl 1.815s
ok github.com/carlosframework/platform/internal/instanceexec 2.715s
ok github.com/carlosframework/platform/internal/instancefs 0.021s
ok github.com/carlosframework/platform/internal/instancekey 0.020s
ok github.com/carlosframework/platform/internal/instanceupdates 0.021s
ok github.com/carlosframework/platform/internal/layout 1.452s
ok github.com/carlosframework/platform/internal/lease 9.469s
ok github.com/carlosframework/platform/internal/lease/leasetest 0.014s
ok github.com/carlosframework/platform/internal/ledger 0.014s
ok github.com/carlosframework/platform/internal/mail 0.172s
ok github.com/carlosframework/platform/internal/maintenance 0.076s
ok github.com/carlosframework/platform/internal/maintenanceexec 5.535s
ok github.com/carlosframework/platform/internal/maintenanceguard 0.069s
ok github.com/carlosframework/platform/internal/metrics 0.007s
ok github.com/carlosframework/platform/internal/moves 21.108s
ok github.com/carlosframework/platform/internal/moves/archive 0.767s
ok github.com/carlosframework/platform/internal/objstore 0.175s
ok github.com/carlosframework/platform/internal/ops 0.161s
ok github.com/carlosframework/platform/internal/park 0.205s
ok github.com/carlosframework/platform/internal/privatefile 0.004s
2026/10/14 04:47:23 provision: listing apps/bab/blog/instances/: list refused — its records are unseen this pass
2026/10/14 04:47:23 provision: listing apps/bab/: listdirs refused — its records are unseen this pass
2026/10/14 04:47:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: listing apps/bac/tito/instances/: list refused — its records are unseen this pass
2026/10/14 04:47:23 provision: listing apps/bac/tito/instances/: list refused — its records are unseen this pass
2026/10/14 04:47:23 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/14 04:47:23 provision: remove retired instance route shop.example: provision: claim admission unavailable
2026/10/14 04:47:23 provision: remove retired instance route shop.example: provision: claim admission unavailable
2026/10/14 04:47:23 provision: remove retired sidecar route worker.sidecar.internal: provision: claim admission unavailable
2026/10/14 04:47:23 provision: remove retired sidecar route worker.sidecar.internal: provision: claim admission unavailable
2026/10/14 04:47:23 provision: claim install acme.go.tito.io: provision: claim admission unavailable
2026/10/14 04:47:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: claim install acme.go.tito.io: registry: claim row ownership changed or unknown
2026/10/14 04:47:23 provision: claim install bot.eleven.bac.sidecar.internal: provision: claim admission unavailable
2026/10/14 04:47:23 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/14 04:47:23 provision: claim install bot.eleven.bac.sidecar.internal: registry: claim row ownership changed or unknown
2026/10/14 04:47:23 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/14 04:47:23 provision: acme.go.tito.io: not minting this pass: the box's layout intent could not be read: no sealed config
2026/10/14 04:47:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 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/14 04:47:23 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/14 04:47:23 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/14 04:47:23 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/14 04:47:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 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/14 04:47:23 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/14 04:47:23 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/14 04:47:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: claim install acme.go.tito.io: registry: claim row ownership changed or unknown
2026/10/14 04:47:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: claim install acme.go.tito.io: registry: claim row ownership changed or unknown
2026/10/14 04:47:23 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/14 04:47:23 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["run"])
2026/10/14 04:47:23 provision: claim install bot.eleven.bac.sidecar.internal: registry: claim row ownership changed or unknown
2026/10/14 04:47:23 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/14 04:47:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/14 04:47:23 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/14 04:47:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/14 04:47:23 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/14 04:47:23 provision: skipping record apps/bac/tito/instances/new.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/14 04:47:23 provision: not removing acme.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/14 04:47:23 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/14 04:47:23 provision: skipping record apps/bac/tito/instances/new.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/14 04:47:23 provision: minted instance route rj.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route rk.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route rl.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route ra.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route rd.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route re.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route rf.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route rg.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route ri.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route rb.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route rc.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route rh.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route ra.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route rb.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route rc.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route rd.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: skipping record apps/bac/tito/instances/rb.go.tito.io.json: read failed: read refused
2026/10/14 04:47:23 provision: skipping record apps/bac/tito/instances/rb.go.tito.io.json: read failed: read refused
2026/10/14 04:47:23 provision: minted instance route re.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route x.appb.example (app "appb" acct "bac")
2026/10/14 04:47:23 provision: minted instance route x.appc.example (app "appc" acct "bac")
2026/10/14 04:47:23 provision: minted instance route x.appf.example (app "appf" acct "bac")
2026/10/14 04:47:23 provision: minted instance route x.apph.example (app "apph" acct "bac")
2026/10/14 04:47:23 provision: minted instance route x.appi.example (app "appi" acct "bac")
2026/10/14 04:47:23 provision: minted instance route x.appa.example (app "appa" acct "bac")
2026/10/14 04:47:23 provision: minted instance route x.appd.example (app "appd" acct "bac")
2026/10/14 04:47:23 provision: minted instance route x.appe.example (app "appe" acct "bac")
2026/10/14 04:47:23 provision: minted instance route x.appg.example (app "appg" acct "bac")
2026/10/14 04:47:23 provision: minted instance route x.appj.example (app "appj" acct "bac")
2026/10/14 04:47:23 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/14 04:47:23 provision: minted instance route r0020.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0089.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0100.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0118.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0060.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0087.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0111.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0004.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0075.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0105.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0033.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0080.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0119.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0063.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0095.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0098.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0106.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0127.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0006.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0011.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0036.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0071.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0101.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0062.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0102.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0123.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0003.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0026.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0035.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0070.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0084.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0121.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0081.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0103.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0027.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0040.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0042.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0058.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0059.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0064.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0032.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0034.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0048.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0090.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0072.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0126.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0000.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0055.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0079.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0086.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0128.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0038.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0065.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0073.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0022.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0051.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0057.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0010.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0046.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0056.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0096.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0107.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0108.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0112.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0117.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0054.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0005.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0021.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0029.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0043.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0067.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0008.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0110.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0001.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0002.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0012.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0023.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0049.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0109.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0044.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0052.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0053.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0074.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0078.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0093.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0104.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0113.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0017.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0025.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0028.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0069.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0114.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0129.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0066.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0077.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0088.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0091.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0120.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0024.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0039.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0061.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0068.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0082.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0094.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0009.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0018.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0124.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0014.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0015.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0013.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0016.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0037.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0045.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0050.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0076.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0085.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0031.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0083.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0097.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0122.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0041.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0047.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0099.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0115.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0116.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0125.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0019.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0030.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0092.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:23 provision: minted instance route r0007.go.tito.io (app "tito" acct "bac")
--- FAIL: TestPlan14RootReadCensus (10.49s)
plan14_root_reads_test.go:677: root read census: 7 discrepancies
changed root read proof_cli.go:runProof; review class, task, sites and digest
changed root source envelope .
stale root read history_cli.go:historyCommandWithSave
stale root read history_cli.go:historyReadFile
stale root read history_cli.go:historySave
stale root read history_cli.go:historySync
changed reclassified declaration proof_cli.go:runProof
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 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/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted service route svc.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted instance route whole.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted instance route console.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted service route ha.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted instance route shared.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: converged acme.go.tito.io channel stable -> edge
2026/10/14 04:47:35 provision: converged acme.go.tito.io channel edge -> canary/rehearsal
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: empty channel
2026/10/14 04:47:35 provision: not removing acme.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: converged acme.go.tito.io environment "" -> "staging"
2026/10/14 04:47:35 provision: converged acme.go.tito.io environment "staging" -> ""
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: converged acme.go.tito.io steering "" -> "latency"
2026/10/14 04:47:35 provision: converged acme.go.tito.io steering "latency" -> ""
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: converged acme.go.tito.io hibernate false -> true
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: converged acme.go.tito.io hibernate true -> false (replication "daily" cleared: only a hibernating route's rung is read)
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: converged acme.go.tito.io status-named false -> true
2026/10/14 04:47:35 provision: converged acme.go.tito.io status-named true -> false
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted service route ha.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 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/14 04:47:35 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/14 04:47:35 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/14 04:47:35 provision: minted service route whole.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 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/14 04:47:35 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/14 04:47:35 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/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted service route whole.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: skipping accounts/bac/account.json: malformed account manifest: invalid character 'o' in literal null (expecting 'u')
2026/10/14 04:47:35 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: manifest bac/tito: read failed: provision: manifest bac/tito: invalid character 'o' in literal null (expecting 'u')
2026/10/14 04:47:35 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/14 04:47:35 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/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 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/14 04:47:35 provision: not removing acme$evil.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/14 04:47:35 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/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 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/14 04:47:35 provision: not removing bad-service.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/14 04:47:35 provision: skipping record apps/bac/tito/instances/no-channel.go.tito.io.json: empty channel
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: skipping record apps/bac/tito/instances/no-channel.go.tito.io.json: empty channel
2026/10/14 04:47:35 provision: not removing no-channel.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: skipping record apps/bac/tito/instances/acme.go.tito.io.json: malformed: provision: invalid maintenance projection or protected fields
2026/10/14 04:47:35 provision: not removing acme.go.tito.io: its record exists but could not be read cleanly this pass
2026/10/14 04:47:35 provision: removed retired instance route ghost.go.tito.io (record gone)
2026/10/14 04:47:35 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/14 04:47:35 provision: minted instance route dup.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/14 04:47:35 provision: removed retired instance route acme.go.tito.io (app in the trash)
2026/10/14 04:47:35 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/14 04:47:35 provision: removed retired static route site.go.tito.io (app in the trash)
2026/10/14 04:47:35 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/14 04:47:35 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/14 04:47:35 provision: removed retired instance route acme.go.tito.io (app in the trash)
2026/10/14 04:47:35 provision: bac/tito is in the trash — not minting instance routes for it
2026/10/14 04:47:35 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/14 04:47:35 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/14 04:47:35 provision: converged acme.go.tito.io channel stable -> edge
2026/10/14 04:47:35 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/14 04:47:35 provision: converged acme.go.tito.io channel canary/rehearsal -> edge
2026/10/14 04:47:35 provision: converged acme.go.tito.io environment "staging" -> ""
2026/10/14 04:47:35 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/14 04:47:35 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/14 04:47:35 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/14 04:47:35 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/14 04:47:35 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/14 04:47:35 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/14 04:47:35 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/14 04:47:35 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/14 04:47:35 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/14 04:47:35 provision: dry-run: would mint instance route acme.go.tito.io (app "tito" acct "bac" channel "stable")
2026/10/14 04:47:35 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/14 04:47:35 provision: dry-run: would converge adopt.go.tito.io channel stable -> edge
2026/10/14 04:47:35 provision: dry-run: would converge adopt.go.tito.io environment "" -> "staging"
2026/10/14 04:47:35 provision: dry-run: would converge owned.go.tito.io channel stable -> edge
2026/10/14 04:47:35 provision: dry-run: would converge owned.go.tito.io environment "" -> "staging"
2026/10/14 04:47:35 provision: dry-run: would converge owned.go.tito.io hibernate false -> true
2026/10/14 04:47:35 provision: dry-run: would converge owned.go.tito.io seed
2026/10/14 04:47:35 provision: dry-run: would remove retired instance route gone.go.tito.io (record gone)
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: adopted existing route adopt.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/14 04:47:35 provision: converged adopt.go.tito.io channel stable -> edge
2026/10/14 04:47:35 provision: converged adopt.go.tito.io environment "" -> "staging"
2026/10/14 04:47:35 provision: converged owned.go.tito.io channel stable -> edge
2026/10/14 04:47:35 provision: converged owned.go.tito.io environment "" -> "staging"
2026/10/14 04:47:35 provision: converged owned.go.tito.io hibernate false -> true
2026/10/14 04:47:35 provision: removed retired instance route gone.go.tito.io (record gone)
2026/10/14 04:47:35 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: adopted existing route story.carlosframework.com (app "story" acct "bad") — this record now owns its channel and environment
2026/10/14 04:47:35 provision: story.carlosframework.com exists but is not the route this record describes (kind "instance"/"static") — leaving it alone
2026/10/14 04:47:35 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted service route pub.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted service route pubs.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted instance route exec.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted service route loop.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted service route named.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted service route priv.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:35 provision: minted instance route unit.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: minted static route pisite.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: minted static route site.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: removed retired static route site.go.tito.io (record gone)
2026/10/14 04:47:36 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: minted instance route acme-uk.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: converged acme.go.tito.io replicas "ie,uk" -> "uk"
2026/10/14 04:47:36 provision: converged acme.go.tito.io replicas "uk" -> ""
2026/10/14 04:47:36 provision: minted instance route acme-uk.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: converged acme-uk.go.tito.io replica mark true -> false
2026/10/14 04:47:36 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 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/14 04:47:36 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: minted instance route router.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: acme.go.tito.io: not minting this pass: the box's layout intent could not be read: store down
2026/10/14 04:47:36 provision: router.go.tito.io: not minting this pass: the box's layout intent could not be read: store down
2026/10/14 04:47:36 provision: adopted existing route acme.go.tito.io (app "tito" acct "bac") — this record now owns its channel and environment
2026/10/14 04:47:36 provision: converged acme.go.tito.io channel stable -> edge
2026/10/14 04:47:36 provision: minted instance route acme.go.tito.io held landing by mv_acme (app "tito" acct "bac")
2026/10/14 04:47:36 provision: not removing acme.go.tito.io (record gone): participant of a running operation
2026/10/14 04:47:36 provision: removed retired instance route acme.go.tito.io (record gone)
2026/10/14 04:47:36 provision: minted instance route acme.go.tito.io held landing by mv_acme (app "tito" acct "bac")
2026/10/14 04:47:36 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/14 04:47:36 provision: held acme.go.tito.io landing by mv_acme (was ready)
2026/10/14 04:47:36 provision: acme.go.tito.io: held restoring by rb_other, not by mv_acme; leaving it
2026/10/14 04:47:36 provision: acme.go.tito.io: the row is not this pass's (app "other" acct ""); not holding it for mv_acme
2026/10/14 04:47:36 provision: acme.go.tito.io exists but is not the route this record describes (app "other"/"tito") — leaving it alone
2026/10/14 04:47:36 provision: dry-run: would mint instance route acme.go.tito.io held landing by mv_acme (app "tito" acct "bac" channel "stable")
2026/10/14 04:47:36 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/14 04:47:36 provision: held acme.go.tito.io landing by mv_acme (was ready)
2026/10/14 04:47:36 provision: removed retired sidecar route gone.eleven.bac.sidecar.internal (record gone)
2026/10/14 04:47:36 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/14 04:47:36 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/14 04:47:36 provision: converged sidecar bot.eleven.bac.sidecar.internal args ["sidecar","run"] -> ["worker","run"]
2026/10/14 04:47:36 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/14 04:47:36 provision: converged sidecar bot.eleven.bac.sidecar.internal ceilings 300/3600 -> 60/120
2026/10/14 04:47:36 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/14 04:47:36 provision: converged sidecar bot.eleven.bac.sidecar.internal channel stable -> canary/eleven
2026/10/14 04:47:36 provision: converged sidecar bot.eleven.bac.sidecar.internal environment "other" -> "relay"
2026/10/14 04:47:36 provision: converged sidecar bot.eleven.bac.sidecar.internal hibernate true -> false
2026/10/14 04:47:36 provision: skipping sidecar record apps/bac/eleven/sidecars/bot.json: read failed: failStore: reads disabled under apps/bac/eleven/sidecars/
2026/10/14 04:47:36 provision: skipping sidecar record apps/bac/eleven/sidecars/bot.json: malformed: invalid character 'n' looking for beginning of object key string
2026/10/14 04:47:36 provision: not removing sidecar bot.eleven.bac.sidecar.internal: its record exists but could not be read cleanly this pass
2026/10/14 04:47:36 provision: skipping sidecar record apps/bac/eleven/sidecars/bot.json: empty channel
2026/10/14 04:47:36 provision: skipping sidecar record apps/bac/eleven/sidecars/held.json: empty channel
2026/10/14 04:47:36 provision: not removing sidecar held.eleven.bac.sidecar.internal: its record exists but could not be read cleanly this pass
2026/10/14 04:47:36 provision: removed retired sidecar route old.eleven.bac.sidecar.internal (record gone)
2026/10/14 04:47:36 provision: bac/eleven has sidecar records but no sidecars manifest — not minting
2026/10/14 04:47:36 provision: bac/eleven is in the trash — not minting sidecar routes for it
2026/10/14 04:47:36 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/14 04:47:36 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/14 04:47:36 provision: minted sidecar route hub.relay.bac.sidecar.internal (app "relay" acct "bac" args ["relay"])
2026/10/14 04:47:36 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/14 04:47:36 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/14 04:47:36 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/14 04:47:36 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/14 04:47:36 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/14 04:47:36 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/14 04:47:36 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/14 04:47:36 provision: removed retired sidecar route bot.eleven.bac.sidecar.internal (record gone)
2026/10/14 04:47:36 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/14 04:47:36 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/14 04:47:36 provision: skipping sidecar record apps/bac/relay/sidecars/hub.json: read failed: failStore: reads disabled under apps/bac/relay/sidecars/
2026/10/14 04:47:36 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/14 04:47:36 provision: minted sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" args ["sidecar","run"])
2026/10/14 04:47:36 provision: dry-run: would mint sidecar route bot.eleven.bac.sidecar.internal (app "eleven" acct "bac" channel "stable" args ["sidecar","run"])
2026/10/14 04:47:36 provision: dry-run: would remove retired sidecar route gone.eleven.bac.sidecar.internal (record gone)
2026/10/14 04:47:36 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/14 04:47:36 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: converged acme.go.tito.io update settings "{\"updates\":\"manual\",\"channel\":\"stable\"}" -> ""
2026/10/14 04:47:36 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: manifest bac/tito: read failed: provision: manifest bac/tito: unexpected end of JSON input
2026/10/14 04:47:36 provision: manifest bac/tito: read failed: provision: manifest bac/tito: unexpected end of JSON input
2026/10/14 04:47:36 provision: acme.go.tito.io: not minted this pass: the app's update policy could not be read
2026/10/14 04:47:36 provision: minted instance route acme.go.tito.io (app "tito" acct "bac")
2026/10/14 04:47:36 provision: manifest bac/tito: read failed: provision: manifest bac/tito: unexpected end of JSON input
2026/10/14 04:47:36 provision: acme.go.tito.io: not minted this pass: the app's update policy could not be read
2026/10/14 04:47:36 provision: minted instance route acme.go.tito.io held landing by mv_acme (app "tito" acct "bac")
FAIL
FAIL github.com/carlosframework/platform/internal/provision 13.917s
ok github.com/carlosframework/platform/internal/publicrelease 0.006s
? github.com/carlosframework/platform/internal/regionname [no test files]
ok github.com/carlosframework/platform/internal/registry 4.052s
ok github.com/carlosframework/platform/internal/relay 7.240s
ok github.com/carlosframework/platform/internal/release 20.758s
ok github.com/carlosframework/platform/internal/rollout 3.796s
ok github.com/carlosframework/platform/internal/rolloutwords 0.003s
ok github.com/carlosframework/platform/internal/rootaws 0.007s
ok github.com/carlosframework/platform/internal/rootparticipation 0.007s
ok github.com/carlosframework/platform/internal/rootstate 0.025s
ok github.com/carlosframework/platform/internal/s3compat 0.005s
ok github.com/carlosframework/platform/internal/safefile 0.004s
ok github.com/carlosframework/platform/internal/schedule 2.311s
ok github.com/carlosframework/platform/internal/sim/hostlife 9.976s
ok github.com/carlosframework/platform/internal/sim/litestreamfacts 4.231s
ok github.com/carlosframework/platform/internal/status 0.040s
ok github.com/carlosframework/platform/internal/steering 0.007s
ok github.com/carlosframework/platform/internal/stopevidence 0.234s
ok github.com/carlosframework/platform/internal/svcrole 0.002s
ok github.com/carlosframework/platform/internal/telemetry 0.005s
ok github.com/carlosframework/platform/internal/termfence 0.005s
ok github.com/carlosframework/platform/internal/tunnelclient 0.004s
ok github.com/carlosframework/platform/internal/unixdial 0.006s
ok github.com/carlosframework/platform/internal/updatewords 0.004s
ok github.com/carlosframework/platform/internal/usage 0.004s
ok github.com/carlosframework/platform/internal/version 0.001s
ok github.com/carlosframework/platform/internal/vet 1.566s
FAIL
make: *** [Makefile:18: 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/internal/historyreadback/plan14_workflow_process_test.go b/internal/historyreadback/plan14_workflow_process_test.go| new file mode 100644 |
| index 000000000..c8a9ea9bd |
| --- /dev/null |
| +++ b/internal/historyreadback/plan14_workflow_process_test.go |
| @@ -0,0 +1,171 @@ |
| +package historyreadback |
| + |
| +import ( |
| + "bytes" |
| + "context" |
| + "crypto/ed25519" |
| + "encoding/json" |
| + "errors" |
| + "os" |
| + "os/exec" |
| + "path/filepath" |
| + "strings" |
| + "testing" |
| + "time" |
| + |
| + "github.com/carlosframework/platform/internal/hostactors" |
| + "github.com/carlosframework/platform/internal/release" |
| + "github.com/carlosframework/platform/internal/safefile" |
| +) |
| + |
| +type workflowLedger string |
| + |
| +func (s workflowLedger) Read(k string) ([]byte, error) { |
| + return os.ReadFile(filepath.Join(string(s), k)) |
| +} |
| +func (s workflowLedger) Write(k string, b []byte) error { |
| + return safefile.WriteFile(filepath.Join(string(s), k), b, 0600) |
| +} |
| +func (s workflowLedger) Remove(k string) error { return os.Remove(filepath.Join(string(s), k)) } |
| +func (s workflowLedger) Names() ([]string, error) { |
| + rows, e := os.ReadDir(string(s)) |
| + var names []string |
| + for _, r := range rows { |
| + names = append(names, r.Name()) |
| + } |
| + return names, e |
| +} |
| +func (s workflowLedger) Lock(context.Context, string) (func(), error) { return func() {}, nil } |
| +func (s workflowLedger) Close() error { return nil } |
| + |
| +type workflowCrashStore struct { |
| + release.Store |
| + boundary string |
| +} |
| + |
| +func (s workflowCrashStore) Put(ctx context.Context, key string, raw []byte, tag string) (string, error) { |
| + request := strings.HasSuffix(key, "/request.json") |
| + if !request && s.boundary == "before grant" { |
| + os.Exit(76) |
| + } |
| + got, err := s.Store.Put(ctx, key, raw, tag) |
| + if err == nil && ((!request && s.boundary == "after grant") || (request && s.boundary == "after request")) { |
| + os.Exit(76) |
| + } |
| + return got, err |
| +} |
| + |
| +func TestPlan14HistoryWorkflowProcessCrash(t *testing.T) { |
| + if boundary := os.Getenv("PLAN14_WORKFLOW_CRASH"); boundary != "" { |
| + dir := os.Getenv("PLAN14_WORKFLOW_DIR") |
| + raw, err := os.ReadFile(filepath.Join(dir, "saved.json")) |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + var saved struct { |
| + Op Operation |
| + Pub ed25519.PublicKey |
| + Now time.Time |
| + } |
| + if err = json.Unmarshal(raw, &saved); err != nil { |
| + t.Fatal(err) |
| + } |
| + d := hostactors.Directory{Store: workflowCrashStore{Store: release.NewDirStore(filepath.Join(dir, "store")), boundary: boundary}, PublicKey: saved.Pub, Bucket: "bucket"} |
| + if err = saved.Op.Deliver(t.Context(), d, saved.Now); err != nil { |
| + t.Fatal(err) |
| + } |
| + t.Fatal("missed crash") |
| + } |
| + for _, boundary := range []string{"before grant", "after grant", "after request"} { |
| + t.Run(boundary, func(t *testing.T) { |
| + f := newFixture(t) |
| + dir := t.TempDir() |
| + store := release.NewDirStore(filepath.Join(dir, "store")) |
| + roster, _, err := f.directory.Store.Get(t.Context(), hostactors.Key) |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + if _, err = store.Put(t.Context(), hostactors.Key, roster, ""); err != nil { |
| + t.Fatal(err) |
| + } |
| + f.directory.Store = store |
| + ledger := workflowLedger(t.TempDir()) |
| + h := &release.RootHistory{Store: ledger} |
| + resolve := func(release.HistoryBinding) (string, error) { return "canonical", nil } |
| + before, err := h.MigrationStatus(f.scope.Binding, resolve) |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + g := release.HistoryReconstruction{Schema: 1, Kind: "carlos-release-history", Identity: before.Identity, Revision: before.Revision, Operation: "operator", IssuedAt: f.now, Account: "abc", App: "web", Hosts: []release.HistoryReconstructionHost{before.Hosts[0].HistoryReconstructionHost}, Holds: map[string]release.HistoryReconstructionHold{"stable": {Window: time.Hour, SetAt: f.now}}} |
| + op, err := PrepareOperation(t.Context(), f.directory, f.signer, f.scope, &g, nil, f.now) |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + saved := struct { |
| + Op Operation |
| + Pub ed25519.PublicKey |
| + Now time.Time |
| + }{op, f.directory.PublicKey, f.now} |
| + raw, err := json.Marshal(saved) |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + path := filepath.Join(dir, "saved.json") |
| + if err = safefile.WriteFile(path, raw, 0600); err != nil { |
| + t.Fatal(err) |
| + } |
| + cmd := exec.CommandContext(t.Context(), os.Args[0], "-test.run=^TestPlan14HistoryWorkflowProcessCrash$", "-test.count=1") |
| + cmd.Dir = t.TempDir() |
| + cmd.Env = append(os.Environ(), "PLAN14_WORKFLOW_CRASH="+boundary, "PLAN14_WORKFLOW_DIR="+dir) |
| + out, err := cmd.CombinedOutput() |
| + var exit *exec.ExitError |
| + if !errors.As(err, &exit) || exit.ExitCode() != 76 { |
| + t.Fatalf("child %v: %s", err, out) |
| + } |
| + // A new operator process reads the saved messages; a new root opener reads |
| + // its own ledger. Neither depends on an in-memory successful response. |
| + again, err := os.ReadFile(path) |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + if !bytes.Equal(raw, again) { |
| + t.Fatal("crash changed saved authorization") |
| + } |
| + if err = json.Unmarshal(again, &saved); err != nil { |
| + t.Fatal(err) |
| + } |
| + if err = saved.Op.Deliver(t.Context(), f.directory, f.now); err != nil { |
| + t.Fatal(err) |
| + } |
| + if _, err = saved.Op.Read(t.Context(), f.directory, f.now); err == nil { |
| + t.Fatal("delivery completed operation") |
| + } |
| + h = &release.RootHistory{Store: ledger} |
| + if err = h.ReceiveReconstruction(t.Context(), store, f.directory.PublicKey, f.scope.Binding, f.now, resolve); err != nil { |
| + t.Fatal(err) |
| + } |
| + if err = Respond(t.Context(), f.directory, f.scope, f.key, f.now, func(context.Context) (release.HistoryMigrationStatus, error) { |
| + return h.MigrationStatus(f.scope.Binding, resolve) |
| + }); err != nil { |
| + t.Fatal(err) |
| + } |
| + got, err := saved.Op.Read(t.Context(), f.directory, f.now) |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + if !got.Status.AppComplete || got.Status.Hosts[0].Programs.Complete { |
| + t.Fatal("wrong category migration", got.Status) |
| + } |
| + if err = saved.Op.Deliver(t.Context(), f.directory, f.now); err != nil { |
| + t.Fatal(err) |
| + } |
| + if err = h.ReceiveReconstruction(t.Context(), store, f.directory.PublicKey, f.scope.Binding, f.now, resolve); err != nil { |
| + t.Fatal(err) |
| + } |
| + final, err := h.ReconstructionStatus() |
| + if err != nil || final.Revision != g.Revision+1 { |
| + t.Fatal("replay advanced revision", final, err) |
| + } |
| + }) |
| + } |
| +} |
diff --git a/internal/historyreadback/plan14_workflow_test.go b/internal/historyreadback/plan14_workflow_test.go| new file mode 100644 |
| index 000000000..ca366b7e3 |
| --- /dev/null |
| +++ b/internal/historyreadback/plan14_workflow_test.go |
| @@ -0,0 +1,167 @@ |
| +package historyreadback |
| + |
| +import ( |
| + "bytes" |
| + "encoding/json" |
| + "errors" |
| + "os" |
| + "strings" |
| + "testing" |
| + |
| + "github.com/carlosframework/platform/internal/release" |
| +) |
| + |
| +func TestPlan14HistoryOperatorWorkflow(t *testing.T) { |
| + for _, kind := range []string{"status", "reconstruct", "retire"} { |
| + t.Run(kind, func(t *testing.T) { |
| + f := newFixture(t) |
| + var g *release.HistoryReconstruction |
| + var retire *release.HistoryRecoveryRetirement |
| + if kind == "reconstruct" { |
| + g = &release.HistoryReconstruction{Schema: 1, Kind: "carlos-release-history", Identity: f.status.Identity, Revision: 1, Operation: "operator", IssuedAt: f.now, Account: "abc", App: "web", Hosts: []release.HistoryReconstructionHost{f.status.Hosts[0].HistoryReconstructionHost}} |
| + f.status.Revision = 2 |
| + f.status.AppComplete, f.status.AppRevision, f.status.BakeComplete, f.status.BakeRevision = true, 1, 1, 1 |
| + f.status.Hosts[0].Revision, f.status.Hosts[0].RefusalStatus.Complete = 1, true |
| + f.status.LastReconstructionDigest = digest(g) |
| + } |
| + if kind == "retire" { |
| + retire = &release.HistoryRecoveryRetirement{Schema: 1, Kind: "carlos-release-recovery-retirement", Identity: f.status.Identity, Operation: "operator", IssuedAt: f.now, Binding: f.scope.Binding, Source: "canonical", AttemptID: "old", OutcomeDigest: strings.Repeat("d", 64), VerifiedID: "good", VerifiedDigest: strings.Repeat("e", 64)} |
| + f.status.RecoverySources = &release.HistoryRecoverySources{Known: true, Unresolved: []release.HistoryRecovery{{Binding: f.scope.Binding, Attempt: release.HistoryAttempt{ID: "unrelated"}}}} |
| + f.status.Hosts[0].RetiredRecoveries = []string{"old"} |
| + f.status.Hosts[0].RetirementDigests = map[string]string{"old": digest(retire)} |
| + f.status.Hosts[0].RecoveryDigests = map[string]string{"old": retire.OutcomeDigest, "good": retire.VerifiedDigest} |
| + } |
| + op, err := PrepareOperation(t.Context(), f.directory, f.signer, f.scope, g, retire, f.now) |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + if _, _, err := f.directory.Store.Get(t.Context(), RequestKey(f.scope)); !errors.Is(err, os.ErrNotExist) { |
| + t.Fatal("prepare published before durable save", err) |
| + } |
| + raw, _ := json.Marshal(op) |
| + var resumed Operation |
| + if err := json.Unmarshal(raw, &resumed); err != nil { |
| + t.Fatal(err) |
| + } |
| + for i := 0; i < 2; i++ { |
| + if err := resumed.Deliver(t.Context(), f.directory, f.now); err != nil { |
| + t.Fatal(err) |
| + } |
| + } |
| + if _, err := resumed.Read(t.Context(), f.directory, f.now); err == nil { |
| + t.Fatal("delivery counted as completion") |
| + } |
| + if err := Respond(t.Context(), f.directory, f.scope, f.key, f.now, f.snapshot); err != nil { |
| + t.Fatal(err) |
| + } |
| + got, err := resumed.Read(t.Context(), f.directory, f.now) |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + if kind == "retire" && len(got.Status.RecoverySources.Unresolved) != 1 { |
| + t.Fatal("lost unrelated original") |
| + } |
| + after, _ := json.Marshal(resumed) |
| + if !bytes.Equal(raw, after) { |
| + t.Fatal("resume changed authorization or challenge") |
| + } |
| + }) |
| + } |
| +} |
| + |
| +func TestPlan14HistoryOperatorConflicts(t *testing.T) { |
| + for _, fault := range []string{"changed grant", "wrong scope", "wrong signer", "changed request", "both", "expired", "delivery conflict", "replacement", "wrong replacement"} { |
| + t.Run(fault, func(t *testing.T) { |
| + f := newFixture(t) |
| + g := release.HistoryReconstruction{Schema: 1, Kind: "carlos-release-history", Identity: f.status.Identity, Revision: 1, Operation: "operator", IssuedAt: f.now, Account: "abc", App: "web", Hosts: []release.HistoryReconstructionHost{f.status.Hosts[0].HistoryReconstructionHost}} |
| + old := g |
| + old.Operation = "old" |
| + if fault == "replacement" { |
| + g.Replaces = digest(old) |
| + } |
| + if fault == "wrong replacement" { |
| + g.Replaces = strings.Repeat("f", 64) |
| + } |
| + op, err := PrepareOperation(t.Context(), f.directory, f.signer, f.scope, &g, nil, f.now) |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + switch fault { |
| + case "changed grant": |
| + op.Reconstruction = append(op.Reconstruction, 'x') |
| + case "changed request": |
| + op.Request = append(op.Request, 'x') |
| + case "wrong scope": |
| + g.Account = "xyz" |
| + op.Reconstruction, _ = release.SignRootEnvelope(f.signer, g) |
| + case "wrong signer": |
| + op.Reconstruction, _ = release.SignRootEnvelope(release.RootSigner(f.key), g) |
| + case "both": |
| + op.Retirement = op.Reconstruction |
| + case "expired": |
| + f.now = f.now.Add(25 * 60 * 60 * 1e9) |
| + case "delivery conflict", "replacement", "wrong replacement": |
| + if err := release.PublishHistoryReconstruction(t.Context(), f.directory.Store, f.signer, old); err != nil { |
| + t.Fatal(err) |
| + } |
| + } |
| + err = op.Deliver(t.Context(), f.directory, f.now) |
| + if fault == "replacement" { |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + return |
| + } |
| + if err == nil { |
| + t.Fatal("invalid operation delivered") |
| + } |
| + if _, _, err := f.directory.Store.Get(t.Context(), RequestKey(f.scope)); !errors.Is(err, os.ErrNotExist) { |
| + t.Fatal("refused operation published challenge", err) |
| + } |
| + }) |
| + } |
| +} |
| + |
| +func TestPlan14HistoryOperatorExactCompletion(t *testing.T) { |
| + for _, fault := range []string{"pending", "other authorization", "unknown category", "pending original"} { |
| + t.Run(fault, func(t *testing.T) { |
| + f := newFixture(t) |
| + g := release.HistoryReconstruction{Schema: 1, Kind: "carlos-release-history", Identity: f.status.Identity, Revision: 1, Operation: "operator", IssuedAt: f.now, Account: "abc", App: "web", Hosts: []release.HistoryReconstructionHost{f.status.Hosts[0].HistoryReconstructionHost}} |
| + var retire *release.HistoryRecoveryRetirement |
| + reconstruction := &g |
| + if fault == "pending original" { |
| + reconstruction = nil |
| + retire = &release.HistoryRecoveryRetirement{Schema: 1, Kind: "carlos-release-recovery-retirement", Identity: f.status.Identity, Operation: "operator", IssuedAt: f.now, Binding: f.scope.Binding, Source: "canonical", AttemptID: "old", OutcomeDigest: strings.Repeat("d", 64), VerifiedID: "good", VerifiedDigest: strings.Repeat("e", 64)} |
| + f.status.RecoverySources = &release.HistoryRecoverySources{Known: true, Unresolved: []release.HistoryRecovery{{Binding: f.scope.Binding, Attempt: release.HistoryAttempt{ID: "old"}}}} |
| + f.status.Hosts[0].RetiredRecoveries = []string{"old"} |
| + f.status.Hosts[0].RetirementDigests = map[string]string{"old": digest(retire)} |
| + f.status.Hosts[0].RecoveryDigests = map[string]string{"old": retire.OutcomeDigest, "good": retire.VerifiedDigest} |
| + } |
| + op, err := PrepareOperation(t.Context(), f.directory, f.signer, f.scope, reconstruction, retire, f.now) |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + if err = op.Deliver(t.Context(), f.directory, f.now); err != nil { |
| + t.Fatal(err) |
| + } |
| + f.status.Revision = 2 |
| + f.status.AppComplete, f.status.AppRevision, f.status.BakeComplete, f.status.BakeRevision = true, 1, 1, 1 |
| + f.status.Hosts[0].Revision, f.status.Hosts[0].RefusalStatus.Complete = 1, true |
| + f.status.LastReconstructionDigest = digest(g) |
| + switch fault { |
| + case "pending": |
| + f.status.Pending = true |
| + case "other authorization": |
| + f.status.LastReconstructionDigest = strings.Repeat("f", 64) |
| + case "unknown category": |
| + f.status.Hosts[0].RefusalStatus.Complete = false |
| + } |
| + if err = Respond(t.Context(), f.directory, f.scope, f.key, f.now, f.snapshot); err != nil { |
| + t.Fatal(err) |
| + } |
| + if _, err = op.Read(t.Context(), f.directory, f.now); err == nil { |
| + t.Fatal("incomplete operation reported success") |
| + } |
| + }) |
| + } |
| +} |
diff --git a/internal/historyreadback/readback.go b/internal/historyreadback/readback.go| index 321b7c6c0..e2c51d5d8 100644 |
| --- a/internal/historyreadback/readback.go |
| +++ b/internal/historyreadback/readback.go |
| @@ -104,33 +104,41 @@ func recheck(ctx context.Context, d hostactors.Directory, s Scope, before hostac |
| } |
| func RequestStatus(ctx context.Context, d hostactors.Directory, signer release.Signer, scope Scope, now time.Time) (Request, error) { |
| + q, wire, err := prepareStatus(ctx, d, signer, scope, now) |
| + if err != nil { |
| + return Request{}, err |
| + } |
| + if err := publish(ctx, d.Store, RequestKey(scope), wire); err != nil { |
| + return Request{}, err |
| + } |
| + return q, nil |
| +} |
| + |
| +func prepareStatus(ctx context.Context, d hostactors.Directory, signer release.Signer, scope Scope, now time.Time) (Request, []byte, error) { |
| q := Request{Schema: 1, Kind: "carlos-release-history-readback", Scope: scope, IssuedAt: now.UTC()} |
| if !bytes.Equal(signer.RootPublicKey(), d.PublicKey) { |
| - return Request{}, os.ErrPermission |
| + return Request{}, nil, os.ErrPermission |
| } |
| before, _, err := enrolled(ctx, d, scope, now) |
| if err != nil { |
| - return Request{}, err |
| + return Request{}, nil, err |
| } |
| nonce := make([]byte, 32) |
| if _, err := rand.Read(nonce); err != nil { |
| - return Request{}, err |
| + return Request{}, nil, err |
| } |
| q.ID = hex.EncodeToString(nonce) |
| if !validRequest(q, now) { |
| - return Request{}, os.ErrPermission |
| + return Request{}, nil, os.ErrPermission |
| } |
| wire, err := release.SignRootEnvelope(signer, q) |
| if err != nil { |
| - return Request{}, err |
| + return Request{}, nil, err |
| } |
| if err := recheck(ctx, d, scope, before, now); err != nil { |
| - return Request{}, err |
| + return Request{}, nil, err |
| } |
| - if err := publish(ctx, d.Store, RequestKey(scope), wire); err != nil { |
| - return Request{}, err |
| - } |
| - return q, nil |
| + return q, wire, nil |
| } |
| func validStatus(v release.HistoryMigrationStatus, b release.HistoryBinding) bool { |
diff --git a/internal/historyreadback/workflow.go b/internal/historyreadback/workflow.go| new file mode 100644 |
| index 000000000..db0972730 |
| --- /dev/null |
| +++ b/internal/historyreadback/workflow.go |
| @@ -0,0 +1,141 @@ |
| +package historyreadback |
| + |
| +import ( |
| + "bytes" |
| + "context" |
| + "encoding/json" |
| + "errors" |
| + "os" |
| + "time" |
| + |
| + "github.com/carlosframework/platform/internal/hostactors" |
| + "github.com/carlosframework/platform/internal/release" |
| +) |
| + |
| +// Operation retains the existing signed messages. Save it durably before |
| +// Deliver. Resume uses these exact bytes and never extends their lifetime. |
| +type Operation struct { |
| + Request json.RawMessage `json:"request"` |
| + Reconstruction json.RawMessage `json:"reconstruction,omitempty"` |
| + Retirement json.RawMessage `json:"retirement,omitempty"` |
| +} |
| + |
| +func PrepareOperation(ctx context.Context, d hostactors.Directory, signer release.Signer, scope Scope, g *release.HistoryReconstruction, retire *release.HistoryRecoveryRetirement, now time.Time) (Operation, error) { |
| + _, wire, err := prepareStatus(ctx, d, signer, scope, now) |
| + op := Operation{Request: wire} |
| + if err != nil { |
| + return Operation{}, err |
| + } |
| + if g != nil { |
| + op.Reconstruction, err = release.SignRootEnvelope(signer, *g) |
| + } |
| + if err == nil && retire != nil { |
| + op.Retirement, err = release.SignRootEnvelope(signer, *retire) |
| + } |
| + if err == nil { |
| + _, _, _, err = op.checked(d, now) |
| + } |
| + if err != nil { |
| + return Operation{}, err |
| + } |
| + return op, nil |
| +} |
| + |
| +func (op Operation) checked(d hostactors.Directory, now time.Time) (Request, *release.HistoryReconstruction, *release.HistoryRecoveryRetirement, error) { |
| + var q Request |
| + refuse := func() (Request, *release.HistoryReconstruction, *release.HistoryRecoveryRetirement, error) { |
| + return Request{}, nil, nil, os.ErrPermission |
| + } |
| + if release.VerifyRootEnvelope(d.PublicKey, op.Request, &q) != nil || !validRequest(q, now) || q.Scope.Bucket != d.Bucket || (len(op.Reconstruction) > 0 && len(op.Retirement) > 0) { |
| + return refuse() |
| + } |
| + fresh := func(at time.Time) bool { |
| + return !at.IsZero() && !at.Before(now.Add(-release.HostRetryGrantTTL)) && !at.After(now.Add(time.Minute)) |
| + } |
| + if len(op.Reconstruction) > 0 { |
| + var g release.HistoryReconstruction |
| + if release.VerifyRootEnvelope(d.PublicKey, op.Reconstruction, &g) != nil || g.Schema != 1 || g.Kind != "carlos-release-history" || !validHex(g.Identity, 32) || g.Revision == 0 || g.Revision == ^uint64(0) || g.Operation == "" || len(g.Operation) > 256 || !fresh(g.IssuedAt) || g.Account != q.Scope.Binding.Account || g.App != q.Scope.Binding.App || len(g.Hosts) == 0 || len(g.Hosts) > 256 || (g.Replaces != "" && !validHex(g.Replaces, 32)) { |
| + return refuse() |
| + } |
| + seen := map[string]bool{} |
| + for _, h := range g.Hosts { |
| + s := q.Scope |
| + s.Binding.Host = h.Host |
| + if !validScope(s) || h.Source == "" || seen[h.Host] { |
| + return refuse() |
| + } |
| + seen[h.Host] = true |
| + } |
| + if !seen[q.Scope.Binding.Host] { |
| + return refuse() |
| + } |
| + return q, &g, nil, nil |
| + } |
| + if len(op.Retirement) > 0 { |
| + var g release.HistoryRecoveryRetirement |
| + if release.VerifyRootEnvelope(d.PublicKey, op.Retirement, &g) != nil || g.Schema != 1 || g.Kind != "carlos-release-recovery-retirement" || !validHex(g.Identity, 32) || g.Operation == "" || len(g.Operation) > 256 || !fresh(g.IssuedAt) || g.Binding != q.Scope.Binding || g.Source == "" || g.AttemptID == "" || g.VerifiedID == "" || g.AttemptID == g.VerifiedID || !validHex(g.OutcomeDigest, 32) || !validHex(g.VerifiedDigest, 32) { |
| + return refuse() |
| + } |
| + return q, nil, &g, nil |
| + } |
| + return q, nil, nil, nil |
| +} |
| + |
| +// Deliver accepts an identical publication after a lost response. Replacing |
| +// another reconstruction requires its exact signed payload digest in Replaces. |
| +func (op Operation) Deliver(ctx context.Context, d hostactors.Directory, now time.Time) error { |
| + q, g, retire, err := op.checked(d, now) |
| + if err != nil { |
| + return err |
| + } |
| + before, _, err := enrolled(ctx, d, q.Scope, now) |
| + if err != nil { |
| + return err |
| + } |
| + if g != nil { |
| + err = op.deliverGrant(ctx, d, release.HistoryReconstructionKey(g.Account, g.App, g.Identity, g.Revision), op.Reconstruction, g.Replaces) |
| + } |
| + if retire != nil { |
| + err = op.deliverGrant(ctx, d, release.HistoryRecoveryRetirementKey(retire.Binding, retire.Identity, retire.OutcomeDigest), op.Retirement, "") |
| + } |
| + if err != nil { |
| + return err |
| + } |
| + if err = recheck(ctx, d, q.Scope, before, now); err != nil { |
| + return err |
| + } |
| + return publish(ctx, d.Store, RequestKey(q.Scope), op.Request) |
| +} |
| + |
| +func (op Operation) deliverGrant(ctx context.Context, d hostactors.Directory, key string, wire []byte, replaces string) error { |
| + old, tag, err := d.Store.Get(ctx, key) |
| + if err == nil { |
| + if bytes.Equal(old, wire) { |
| + return nil |
| + } |
| + var previous release.HistoryReconstruction |
| + if tag == "" || replaces == "" || release.VerifyRootEnvelope(d.PublicKey, old, &previous) != nil || digest(previous) != replaces { |
| + return os.ErrPermission |
| + } |
| + } else if !errors.Is(err, os.ErrNotExist) { |
| + return err |
| + } else { |
| + tag = "" |
| + } |
| + _, err = d.Store.Put(ctx, key, wire, tag) |
| + return err |
| +} |
| + |
| +func (op Operation) Read(ctx context.Context, d hostactors.Directory, now time.Time) (Receipt, error) { |
| + q, g, retire, err := op.checked(d, now) |
| + if err != nil { |
| + return Receipt{}, err |
| + } |
| + if g != nil { |
| + return ReadReconstruction(ctx, d, q, *g, now) |
| + } |
| + if retire != nil { |
| + return ReadRetirement(ctx, d, q, *retire, now) |
| + } |
| + return ReadStatus(ctx, d, q, now) |
| +} |
diff --git a/internal/provision/plan14_e_write_census_test.go b/internal/provision/plan14_e_write_census_test.go| index 95b7c3819..b99e6c4f8 100644 |
| --- a/internal/provision/plan14_e_write_census_test.go |
| +++ b/internal/provision/plan14_e_write_census_test.go |
| @@ -2,6 +2,7 @@ package provision |
| // Track E overlays the reviewed Part 1 write census without changing its baseline. |
| var plan14EWriteCensusOverlay = []censusEntry{ |
| + {"internal/historyreadback/workflow.go", "Operation.deliverGrant", "nonrecord", "sel:Put", "fb410ef6274ef7de0997a804c837ad1ecf29d8826ba1c4dcda00c2ae986fc434"}, |
| {"internal/host/rootinventory.go", "ClaimRootHTTP.commitRootInventoryPending", "key-site", "key:RecordKey", "cbc0c1fa8be968c6dd18a42ff200fe5765f25d35c07ed3ece3b18ad4d619d64c"}, |
| {"internal/host/rootinventory.go", "ClaimRootHTTP.recoverRootInventory", "key-site", "key:RecordKey", "a828684ad31a409d3e1fc306216d907681f514cb813302eb965a040e5084feda"}, |
| {"internal/host/roothistory_creation.go", "rootRestartRequestSource.creation", "key-site", "key:RecordKey", "af79a66b746b0f42388010b38ea8130dca6a8d29c4ba5623bfc9c3cc40dd9601"}, |
diff --git a/internal/provision/testdata/plan14-root-reads-e.tsv b/internal/provision/testdata/plan14-root-reads-e.tsv| index 9261e1ab8..9123f2813 100644 |
| --- a/internal/provision/testdata/plan14-root-reads-e.tsv |
| +++ b/internal/provision/testdata/plan14-root-reads-e.tsv |
| @@ -99,11 +99,9 @@ internal/release/roothistory_status.go type HistoryRecoverySources diagnostic E1 |
| internal/host/namedrecovery_pass.go namedUnitRecovery.passOption authority B3,E1 Production recovery wrapper preserves main exit status for per-host failures; only remaining named routes can probe the census for history selection. Ordinary routes make no census or binding-store reads. Fixtures: TestPlan14ERecoveryOrdinaryPass, TestPlan14Fix4AdoptPerHostFailureExitsZero, TestPlan14Fix5MainEquivalence. registry:Host@282,registry:Host@506,registry:Unit@459,registry:Unit@476,whole:Route@419,whole:Route@451 36ef7a4bf960574b35ea896c72612ce9b4a8ad7d2c249eec16f796344b5dd37e |
| internal/historyreadback/readback.go ReadStatus authority E1 Challenge-bound release-history readback authenticates the deployment request and active enrolled box key, rereads private history with original recovery restrictions, and rechecks roster/fence state. No status grants completeness or changes service effects. Fixtures: TestPlan14HistoryReadback, TestPlan14HistoryReadbackAuthority, TestPlan14HistoryReadbackReadRace, TestPlan14HistoryReadbackReenrollment, TestPlan14HistoryReadbackRequestRefusal, TestPlan14HistoryReadbackProduction, TestPlan14HistoryReadbackProcessCrash. 444d867657fd2502b13d6034a2f72719a228c27e18eeb7557e2675749fecb1b5 |
| internal/historyreadback/readback.go RequestKey authority E1 Challenge-bound release-history readback authenticates the deployment request and active enrolled box key, rereads private history with original recovery restrictions, and rechecks roster/fence state. No status grants completeness or changes service effects. Fixtures: TestPlan14HistoryReadback, TestPlan14HistoryReadbackAuthority, TestPlan14HistoryReadbackReadRace, TestPlan14HistoryReadbackReenrollment, TestPlan14HistoryReadbackRequestRefusal, TestPlan14HistoryReadbackProduction, TestPlan14HistoryReadbackProcessCrash. 0337fdbed358c618bf31d08764c61ba405e373f6cf55a0652171928ddb99d3cb |
| -internal/historyreadback/readback.go RequestStatus authority E1 Challenge-bound release-history readback authenticates the deployment request and active enrolled box key, rereads private history with original recovery restrictions, and rechecks roster/fence state. No status grants completeness or changes service effects. Fixtures: TestPlan14HistoryReadback, TestPlan14HistoryReadbackAuthority, TestPlan14HistoryReadbackReadRace, TestPlan14HistoryReadbackReenrollment, TestPlan14HistoryReadbackRequestRefusal, TestPlan14HistoryReadbackProduction, TestPlan14HistoryReadbackProcessCrash. file:Read@464 2d3f42686cbfcbe9ed62458e636dc445735aa1d15085752da8f534f00a8f88fc |
| internal/historyreadback/readback.go Respond authority E1 Challenge-bound release-history readback authenticates the deployment request and active enrolled box key, rereads private history with original recovery restrictions, and rechecks roster/fence state. No status grants completeness or changes service effects. Fixtures: TestPlan14HistoryReadback, TestPlan14HistoryReadbackAuthority, TestPlan14HistoryReadbackReadRace, TestPlan14HistoryReadbackReenrollment, TestPlan14HistoryReadbackRequestRefusal, TestPlan14HistoryReadbackProduction, TestPlan14HistoryReadbackProcessCrash. ec1bf8cb97a6ec617fd27959ac3d36dc34d3d9b91d1de1cea1be4069559a23c0 |
| internal/historyreadback/readback.go ResponseKey authority E1 Challenge-bound release-history readback authenticates the deployment request and active enrolled box key, rereads private history with original recovery restrictions, and rechecks roster/fence state. No status grants completeness or changes service effects. Fixtures: TestPlan14HistoryReadback, TestPlan14HistoryReadbackAuthority, TestPlan14HistoryReadbackReadRace, TestPlan14HistoryReadbackReenrollment, TestPlan14HistoryReadbackRequestRefusal, TestPlan14HistoryReadbackProduction, TestPlan14HistoryReadbackProcessCrash. e6145165f5efdc337eb6be970c632371ee051f843f51d5a2dc6f8de326bf07f8 |
| internal/historyreadback/readback.go digest authority E1 Challenge-bound release-history readback authenticates the deployment request and active enrolled box key, rereads private history with original recovery restrictions, and rechecks roster/fence state. No status grants completeness or changes service effects. Fixtures: TestPlan14HistoryReadback, TestPlan14HistoryReadbackAuthority, TestPlan14HistoryReadbackReadRace, TestPlan14HistoryReadbackReenrollment, TestPlan14HistoryReadbackRequestRefusal, TestPlan14HistoryReadbackProduction, TestPlan14HistoryReadbackProcessCrash. 1449061bba4baa9cd363a18f4b7163bd5ce59361c7932a9e1f290c550cfe0df2 |
| -internal/historyreadback/readback.go enrolled authority E1 Challenge-bound release-history readback authenticates the deployment request and active enrolled box key, rereads private history with original recovery restrictions, and rechecks roster/fence state. No status grants completeness or changes service effects. Fixtures: TestPlan14HistoryReadback, TestPlan14HistoryReadbackAuthority, TestPlan14HistoryReadbackReadRace, TestPlan14HistoryReadbackReenrollment, TestPlan14HistoryReadbackRequestRefusal, TestPlan14HistoryReadbackProduction, TestPlan14HistoryReadbackProcessCrash. file:Read@246 e3757fe212a53daaee48a445b80b252b6040630b8a4655c3857f6e06322b7ce4 |
| internal/historyreadback/readback.go publish authority E1 Challenge-bound release-history readback authenticates the deployment request and active enrolled box key, rereads private history with original recovery restrictions, and rechecks roster/fence state. No status grants completeness or changes service effects. Fixtures: TestPlan14HistoryReadback, TestPlan14HistoryReadbackAuthority, TestPlan14HistoryReadbackReadRace, TestPlan14HistoryReadbackReenrollment, TestPlan14HistoryReadbackRequestRefusal, TestPlan14HistoryReadbackProduction, TestPlan14HistoryReadbackProcessCrash. 2168932e34cc6f173fde4d4cf0e74a302217ade779c09cc2d1e850ffdab0cb48 |
| internal/historyreadback/readback.go recheck authority E1 Challenge-bound release-history readback authenticates the deployment request and active enrolled box key, rereads private history with original recovery restrictions, and rechecks roster/fence state. No status grants completeness or changes service effects. Fixtures: TestPlan14HistoryReadback, TestPlan14HistoryReadbackAuthority, TestPlan14HistoryReadbackReadRace, TestPlan14HistoryReadbackReenrollment, TestPlan14HistoryReadbackRequestRefusal, TestPlan14HistoryReadbackProduction, TestPlan14HistoryReadbackProcessCrash. 45c9698e4a43f22c2ab4c8d19af831e06bb4842b572b63fb9e42c6a9cdb788ca |
| internal/historyreadback/readback.go type Receipt authority E1 Challenge-bound release-history readback authenticates the deployment request and active enrolled box key, rereads private history with original recovery restrictions, and rechecks roster/fence state. No status grants completeness or changes service effects. Fixtures: TestPlan14HistoryReadback, TestPlan14HistoryReadbackAuthority, TestPlan14HistoryReadbackReadRace, TestPlan14HistoryReadbackReenrollment, TestPlan14HistoryReadbackRequestRefusal, TestPlan14HistoryReadbackProduction, TestPlan14HistoryReadbackProcessCrash. 1af476c27bda63fb423afcaa1964266cd850e8cd51b868d8efb82e170a15c6a3 |
| @@ -117,7 +115,6 @@ internal/host/roothistory_readback.go historyReadbackPublisher.publish authority |
| internal/host/roothistory_readback.go publishRootHistoryReadback authority E1 Challenge-bound release-history readback authenticates the deployment request and active enrolled box key, rereads private history with original recovery restrictions, and rechecks roster/fence state. No status grants completeness or changes service effects. Fixtures: TestPlan14HistoryReadback, TestPlan14HistoryReadbackAuthority, TestPlan14HistoryReadbackReadRace, TestPlan14HistoryReadbackReenrollment, TestPlan14HistoryReadbackRequestRefusal, TestPlan14HistoryReadbackProduction, TestPlan14HistoryReadbackProcessCrash. da8fc3789d39285f28722603c91a5549e77034d1ebb17e839b16b860bd75a425 |
| internal/host/roothistory_readback.go type historyReadbackPublisher authority E1 Challenge-bound release-history readback authenticates the deployment request and active enrolled box key, rereads private history with original recovery restrictions, and rechecks roster/fence state. No status grants completeness or changes service effects. Fixtures: TestPlan14HistoryReadback, TestPlan14HistoryReadbackAuthority, TestPlan14HistoryReadbackReadRace, TestPlan14HistoryReadbackReenrollment, TestPlan14HistoryReadbackRequestRefusal, TestPlan14HistoryReadbackProduction, TestPlan14HistoryReadbackProcessCrash. 0112fc221bb6f41afe48ca3775063fb2138886da6872a141a0e5b1b589f2f43e |
| internal/release/roothistory_status.go RootHistory.MigrationStatusWithSources authority E1 Exact completion binds the accepted authorization digest from durable private history to enrolled-root signed readback. Pending originals, changed evidence and canonical sources cannot supply retirement completion. Fixtures: TestPlan14HistoryReconstructionCompletion, TestPlan14HistoryRetirementCompletion, TestPlan14ReadReconstructionCompletion, TestPlan14ReadRetirementCompletion, TestPlan14RecoveryRetirementProductionCallback, TestPlan14RootHistoryReconstructionCrash, TestPlan14HistoryRetirementProcessCrash. b21c4f2d6ce984632726f7bd1a2d8d876764794a5e937075424ae15fdd97452e |
| -@coverage internal/historyreadback 4ef0528aa6c49e6d32e53f84456680b279d52313a69fdf9aaaceead54af2a8e8 |
| internal/historyreadback/completion.go ReadReconstruction authority E1 Exact completion binds the accepted authorization digest from durable private history to enrolled-root signed readback. Pending originals, changed evidence and canonical sources cannot supply retirement completion. Fixtures: TestPlan14HistoryReconstructionCompletion, TestPlan14HistoryRetirementCompletion, TestPlan14ReadReconstructionCompletion, TestPlan14ReadRetirementCompletion, TestPlan14RecoveryRetirementProductionCallback, TestPlan14RootHistoryReconstructionCrash, TestPlan14HistoryRetirementProcessCrash. 9f64ca3108a374d26c0f690cd62e3984f25d237175b75a4529a945fda41db5ee |
| internal/historyreadback/completion.go ReadRetirement authority E1 Exact completion binds the accepted authorization digest from durable private history to enrolled-root signed readback. Pending originals, changed evidence and canonical sources cannot supply retirement completion. Fixtures: TestPlan14HistoryReconstructionCompletion, TestPlan14HistoryRetirementCompletion, TestPlan14ReadReconstructionCompletion, TestPlan14ReadRetirementCompletion, TestPlan14RecoveryRetirementProductionCallback, TestPlan14RootHistoryReconstructionCrash, TestPlan14HistoryRetirementProcessCrash. 051995729c46c84bc96346ca6098c68a4b1317c1d3a2f25655b4d730079534b8 |
| internal/release/roothistory_retirement.go RootHistory.recoveryRetirementDigest authority E1 Exact completion binds the accepted authorization digest from durable private history to enrolled-root signed readback. Pending originals, changed evidence and canonical sources cannot supply retirement completion. Fixtures: TestPlan14HistoryReconstructionCompletion, TestPlan14HistoryRetirementCompletion, TestPlan14ReadReconstructionCompletion, TestPlan14ReadRetirementCompletion, TestPlan14RecoveryRetirementProductionCallback, TestPlan14RootHistoryReconstructionCrash, TestPlan14HistoryRetirementProcessCrash. file:Read@125 4bfcfe969b2230a094ecdf7f4d7653f8bf9f46c10f3e0419a054c0384c2971c8 |
| @@ -180,3 +177,14 @@ internal/release/roothistory_creation.go RootHistory.FreshInstallation authority |
| internal/release/roothistory_creation.go RootHistory.RecordCreation authority E1 E16: root first-registration creation evidence under release exclusion; exact installation identity is required for first-program adoption and is consumed before an attempt. Installed-program history comes from the verified claim launch. Fixtures: TestPlan14FreshInstallRegistration, TestPlan14FreshInstallProgramGate, TestPlan14FreshInstallCanonicalIdentity, TestPlan14FreshInstallLaunchObservation, TestPlan14InstalledLaunchProgramEvidence, TestPlan14FreshInstallProcessCrash, TestPlan14FreshInstallVisibleSync, TestClaimControlUnitInstallers. 0b545ab63902eb8f2c8988991786c964a2af53d65eff46d8e53a0747da492b6d |
| internal/host/rootinventory.go ClaimRootHTTP.recoverRootInventory authority C,E1 E16: root first-registration creation evidence under release exclusion; exact installation identity is required for first-program adoption and is consumed before an attempt. Installed-program history comes from the verified claim launch. Fixtures: TestPlan14FreshInstallRegistration, TestPlan14FreshInstallProgramGate, TestPlan14FreshInstallCanonicalIdentity, TestPlan14FreshInstallLaunchObservation, TestPlan14InstalledLaunchProgramEvidence, TestPlan14FreshInstallProcessCrash, TestPlan14FreshInstallVisibleSync, TestClaimControlUnitInstallers. file:Read@1371,file:Read@707 a828684ad31a409d3e1fc306216d907681f514cb813302eb965a040e5084feda |
| internal/host/rootinventory.go ClaimRootHTTP.withRootInventoryHistory authority E1 E16: root first-registration creation evidence under release exclusion; exact installation identity is required for first-program adoption and is consumed before an attempt. Installed-program history comes from the verified claim launch. Fixtures: TestPlan14FreshInstallRegistration, TestPlan14FreshInstallProgramGate, TestPlan14FreshInstallCanonicalIdentity, TestPlan14FreshInstallLaunchObservation, TestPlan14InstalledLaunchProgramEvidence, TestPlan14FreshInstallProcessCrash, TestPlan14FreshInstallVisibleSync, TestClaimControlUnitInstallers. 81bc65e0a2018fcdaa8933231d44579429801c2265e6c87c274e9fd8e096c202 |
| +history_cli.go historyCommandWithSave authority E1 E17: operator saves exact signed authorization and challenge before delivery, resumes without renewal, and verifies enrolled-root exact completion. Existing proof branches are unchanged. Tests: TestPlan14HistoryOperatorWorkflow, TestPlan14HistoryOperatorConflicts, TestPlan14HistoryOperatorExactCompletion, TestPlan14HistoryWorkflowProcessCrash, TestPlan14HistoryCommandResume, TestPlan14HistorySavedFiles, TestPlan14HistoryCLIDispatch. file:Read@2820 9d2f3a735e54cbc01cd4db714125aae9e491afad3d666495f3915de7d517aa2f |
| +history_cli.go historyReadFile authority E1 E17: operator saves exact signed authorization and challenge before delivery, resumes without renewal, and verifies enrolled-root exact completion. Existing proof branches are unchanged. Tests: TestPlan14HistoryOperatorWorkflow, TestPlan14HistoryOperatorConflicts, TestPlan14HistoryOperatorExactCompletion, TestPlan14HistoryWorkflowProcessCrash, TestPlan14HistoryCommandResume, TestPlan14HistorySavedFiles, TestPlan14HistoryCLIDispatch. file:OpenFile@75,file:ReadAll@178 890cbecced68e8ebec71ddbba5682becd5318fa6d5e29f6dc8e5203f9fef6a6a |
| +history_cli.go historySave authority E1 E17: operator saves exact signed authorization and challenge before delivery, resumes without renewal, and verifies enrolled-root exact completion. Existing proof branches are unchanged. Tests: TestPlan14HistoryOperatorWorkflow, TestPlan14HistoryOperatorConflicts, TestPlan14HistoryOperatorExactCompletion, TestPlan14HistoryWorkflowProcessCrash, TestPlan14HistoryCommandResume, TestPlan14HistorySavedFiles, TestPlan14HistoryCLIDispatch. file:OpenFile@142 b11dcef8d3e67c3a293959a62fa00a3e605b03490ef913f815af7e417a33d88e |
| +history_cli.go historySync authority E1 E17: operator saves exact signed authorization and challenge before delivery, resumes without renewal, and verifies enrolled-root exact completion. Existing proof branches are unchanged. Tests: TestPlan14HistoryOperatorWorkflow, TestPlan14HistoryOperatorConflicts, TestPlan14HistoryOperatorExactCompletion, TestPlan14HistoryWorkflowProcessCrash, TestPlan14HistoryCommandResume, TestPlan14HistorySavedFiles, TestPlan14HistoryCLIDispatch. file:OpenFile@225,file:Stat@332,file:Stat@385 9366574a1d0296e4e440bff34a701d143983708d25f2a8ac6560ca1f532748d3 |
| +internal/historyreadback/readback.go enrolled authority E1 E17: operator saves exact signed authorization and challenge before delivery, resumes without renewal, and verifies enrolled-root exact completion. Existing proof branches are unchanged. Tests: TestPlan14HistoryOperatorWorkflow, TestPlan14HistoryOperatorConflicts, TestPlan14HistoryOperatorExactCompletion, TestPlan14HistoryWorkflowProcessCrash, TestPlan14HistoryCommandResume, TestPlan14HistorySavedFiles, TestPlan14HistoryCLIDispatch. file:Read@246 e3757fe212a53daaee48a445b80b252b6040630b8a4655c3857f6e06322b7ce4 |
| +internal/historyreadback/readback.go prepareStatus authority E1 E17: operator saves exact signed authorization and challenge before delivery, resumes without renewal, and verifies enrolled-root exact completion. Existing proof branches are unchanged. Tests: TestPlan14HistoryOperatorWorkflow, TestPlan14HistoryOperatorConflicts, TestPlan14HistoryOperatorExactCompletion, TestPlan14HistoryWorkflowProcessCrash, TestPlan14HistoryCommandResume, TestPlan14HistorySavedFiles, TestPlan14HistoryCLIDispatch. file:Read@482 d4023efc32f25620dd2f81e831e7ee41085db366a8d9ac4095086be55bafd916 |
| +internal/historyreadback/workflow.go Operation.Read authority E1 E17: operator saves exact signed authorization and challenge before delivery, resumes without renewal, and verifies enrolled-root exact completion. Existing proof branches are unchanged. Tests: TestPlan14HistoryOperatorWorkflow, TestPlan14HistoryOperatorConflicts, TestPlan14HistoryOperatorExactCompletion, TestPlan14HistoryWorkflowProcessCrash, TestPlan14HistoryCommandResume, TestPlan14HistorySavedFiles, TestPlan14HistoryCLIDispatch. file:Read@20 26f08c521b5d8535f668c1b74e53e22e81719075fe494a0ed26e203f99533668 |
| +proof_cli.go runProof authority E1 E17: operator saves exact signed authorization and challenge before delivery, resumes without renewal, and verifies enrolled-root exact completion. Existing proof branches are unchanged. Tests: TestPlan14HistoryOperatorWorkflow, TestPlan14HistoryOperatorConflicts, TestPlan14HistoryOperatorExactCompletion, TestPlan14HistoryWorkflowProcessCrash, TestPlan14HistoryCommandResume, TestPlan14HistorySavedFiles, TestPlan14HistoryCLIDispatch. file:ReadFile@1297 a8fa03baf4704e098a54a2ee9712ef411efa8c95ab756c43ea8b85e371c68949 |
| +internal/historyreadback/readback.go RequestStatus authority E1 E17: operator saves exact signed authorization and challenge before delivery, resumes without renewal, and verifies enrolled-root exact completion. Existing proof branches are unchanged. Tests: TestPlan14HistoryOperatorWorkflow, TestPlan14HistoryOperatorConflicts, TestPlan14HistoryOperatorExactCompletion, TestPlan14HistoryWorkflowProcessCrash, TestPlan14HistoryCommandResume, TestPlan14HistorySavedFiles, TestPlan14HistoryCLIDispatch. d89052b0cdd12c8c8dcbc353e9ae995005caeb88d8e4c70974cb9e6f4bfd46d7 |
| +@coverage . 85921915751b89a3baf64b24fefeb4c036fa056819801d4d3950629a9616d605 |
| +@coverage internal/historyreadback eaca4d4caacf499db8a4c4e8044d565eec5bb42e0fc765b66f6c7559fbb04842 |