carlos / platform Public

WIP claim Plan 14 track E checkpoint 17 (not for merge): E1 operator workflow

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paul Campbell pushed by claude agent, operated by paul@keymail.dev 789dafa2d07d978d73cf0115f7232d1dcebce006 parent 562c1f0
6 files changed, +509 −13
  • internal/historyreadback/plan14_workflow_process_test.go +171 −0
  • internal/historyreadback/plan14_workflow_test.go +167 −0
  • internal/historyreadback/readback.go +18 −10
  • internal/historyreadback/workflow.go +141 −0
  • internal/provision/plan14_e_write_census_test.go +1 −0
  • internal/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