hotfix #281: a held request whose upstream recovery moved is answered as still waking
Astra r2 P2: a request held through startup carries the proxy the edge chose before layout recovery ran. If recovery moved the host's socket or address, it now gets the wake-timeout 503 (Retry-After: 5) instead of a proxy to the old socket, and the retry is routed afresh. Regression test, mutation-checked. Census: Service.serve re-recorded under census-ruling-hotfix281 (agent-side, deny-only), activatorStart.Run basis wording (Opus N5), seal re-pinned.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4 files changed,
+71
−6
internal/activator/activator.go+16 −0internal/activator/startup_test.go+49 −0internal/provision/plan14_root_reads_test.go+1 −1internal/provision/testdata/plan14-root-reads-hotfix281.tsv+5 −5
CI passed — run details
CI log
=== gate ===
cd launchctx && go vet ./... && go test ./... -count=1
ok amadan.net/carlos/platform.git/launchctx 0.014s
? amadan.net/carlos/platform.git/launchctx/controlname [no test files]
? amadan.net/carlos/platform.git/launchctx/wireid [no test files]
go vet ./...
gofmt -l .: clean
go test ./... -count=1 -timeout 30m
ok github.com/carlosframework/platform 373.100s
? github.com/carlosframework/platform/cmd/changelog [no test files]
ok github.com/carlosframework/platform/cmd/console 4.209s
ok github.com/carlosframework/platform/cmd/moveprobe 94.010s
ok github.com/carlosframework/platform/cmd/zddprobe 0.419s
ok github.com/carlosframework/platform/internal/activator 229.721s
ok github.com/carlosframework/platform/internal/agentsock 0.024s
ok github.com/carlosframework/platform/internal/alerting 0.005s
ok github.com/carlosframework/platform/internal/analytics 0.023s
ok github.com/carlosframework/platform/internal/appconfig 2.907s
ok github.com/carlosframework/platform/internal/apperr 0.120s
ok github.com/carlosframework/platform/internal/applog 0.174s
ok github.com/carlosframework/platform/internal/awsinv 0.014s
ok github.com/carlosframework/platform/internal/boxchoice 0.013s
ok github.com/carlosframework/platform/internal/boxid 0.880s
? 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.012s
ok github.com/carlosframework/platform/internal/caps 0.012s
ok github.com/carlosframework/platform/internal/certwarm 0.006s
ok github.com/carlosframework/platform/internal/cgroup 0.809s
ok github.com/carlosframework/platform/internal/changelog 0.404s
ok github.com/carlosframework/platform/internal/clamd 0.057s
? github.com/carlosframework/platform/internal/cliflag [no test files]
ok github.com/carlosframework/platform/internal/console 373.372s
? 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.930s
ok github.com/carlosframework/platform/internal/dbdoor/dbdoortest 0.014s
ok github.com/carlosframework/platform/internal/dbverify 0.005s
ok github.com/carlosframework/platform/internal/dnsrec 0.003s
ok github.com/carlosframework/platform/internal/docsite 0.010s
ok github.com/carlosframework/platform/internal/domains 2.471s
ok github.com/carlosframework/platform/internal/doorkey 0.007s
ok github.com/carlosframework/platform/internal/economics 0.005s
ok github.com/carlosframework/platform/internal/edge 28.485s
? github.com/carlosframework/platform/internal/edgeproof [no test files]
ok github.com/carlosframework/platform/internal/edgesfile 0.009s
ok github.com/carlosframework/platform/internal/fleetapi 0.162s
ok github.com/carlosframework/platform/internal/gate 1.696s
ok github.com/carlosframework/platform/internal/genselect 0.019s
ok github.com/carlosframework/platform/internal/geo 0.020s
ok github.com/carlosframework/platform/internal/geoip 0.039s
ok github.com/carlosframework/platform/internal/host 103.552s
ok github.com/carlosframework/platform/internal/hostactors 0.632s
ok github.com/carlosframework/platform/internal/hostbox 3.237s
ok github.com/carlosframework/platform/internal/hostclaim 1.273s
ok github.com/carlosframework/platform/internal/hostevidence 0.011s
ok github.com/carlosframework/platform/internal/hostexec 8.281s
ok github.com/carlosframework/platform/internal/hostfence 0.107s
ok github.com/carlosframework/platform/internal/hostfiles 11.653s
ok github.com/carlosframework/platform/internal/hostfloor 0.040s
ok github.com/carlosframework/platform/internal/hostguard 1.112s
ok github.com/carlosframework/platform/internal/hostops 2.579s
? 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.005s
ok github.com/carlosframework/platform/internal/hostrelocate 1.005s
ok github.com/carlosframework/platform/internal/hostresolve 0.275s
ok github.com/carlosframework/platform/internal/hostwrite 0.008s
ok github.com/carlosframework/platform/internal/infraview 0.004s
ok github.com/carlosframework/platform/internal/instancectl 1.863s
ok github.com/carlosframework/platform/internal/instanceexec 2.861s
ok github.com/carlosframework/platform/internal/instancefs 0.012s
ok github.com/carlosframework/platform/internal/instancekey 0.004s
ok github.com/carlosframework/platform/internal/instanceupdates 0.011s
ok github.com/carlosframework/platform/internal/layout 2.060s
ok github.com/carlosframework/platform/internal/lease 9.742s
ok github.com/carlosframework/platform/internal/lease/leasetest 0.018s
ok github.com/carlosframework/platform/internal/ledger 0.056s
ok github.com/carlosframework/platform/internal/mail 0.469s
ok github.com/carlosframework/platform/internal/maintenance 0.146s
ok github.com/carlosframework/platform/internal/maintenanceexec 5.791s
ok github.com/carlosframework/platform/internal/maintenanceguard 0.206s
ok github.com/carlosframework/platform/internal/metrics 0.010s
ok github.com/carlosframework/platform/internal/moves 24.547s
ok github.com/carlosframework/platform/internal/moves/archive 1.511s
ok github.com/carlosframework/platform/internal/objstore 0.527s
ok github.com/carlosframework/platform/internal/ops 0.248s
ok github.com/carlosframework/platform/internal/park 0.516s
ok github.com/carlosframework/platform/internal/privatefile 0.003s
ok github.com/carlosframework/platform/internal/provision 18.459s
ok github.com/carlosframework/platform/internal/publicrelease 0.007s
? github.com/carlosframework/platform/internal/regionname [no test files]
ok github.com/carlosframework/platform/internal/registry 4.925s
ok github.com/carlosframework/platform/internal/relay 7.435s
ok github.com/carlosframework/platform/internal/release 23.234s
ok github.com/carlosframework/platform/internal/rollout 4.907s
ok github.com/carlosframework/platform/internal/rolloutwords 0.010s
ok github.com/carlosframework/platform/internal/rootaws 0.008s
ok github.com/carlosframework/platform/internal/rootparticipation 0.008s
ok github.com/carlosframework/platform/internal/rootstate 0.031s
ok github.com/carlosframework/platform/internal/s3compat 0.006s
ok github.com/carlosframework/platform/internal/safefile 0.005s
ok github.com/carlosframework/platform/internal/schedule 2.666s
ok github.com/carlosframework/platform/internal/sim/hostlife 21.494s
ok github.com/carlosframework/platform/internal/sim/litestreamfacts 4.232s
ok github.com/carlosframework/platform/internal/status 0.098s
ok github.com/carlosframework/platform/internal/steering 0.013s
ok github.com/carlosframework/platform/internal/stopevidence 0.297s
ok github.com/carlosframework/platform/internal/svcrole 0.002s
ok github.com/carlosframework/platform/internal/telemetry 0.006s
ok github.com/carlosframework/platform/internal/termfence 0.004s
ok github.com/carlosframework/platform/internal/tunnelclient 0.004s
ok github.com/carlosframework/platform/internal/unixdial 0.003s
ok github.com/carlosframework/platform/internal/updatewords 0.007s
ok github.com/carlosframework/platform/internal/usage 0.005s
ok github.com/carlosframework/platform/internal/version 0.003s
ok github.com/carlosframework/platform/internal/vet 1.694s
=== cross ===
--- shard 0 of 5 ---
cross-compiling darwin/arm64
--- shard 1 of 5 ---
cross-compiling darwin/amd64
--- shard 2 of 5 ---
cross-compiling linux/arm64
--- shard 3 of 5 ---
cross-compiling windows/amd64
--- shard 4 of 5 ---
cross-compiling windows/arm64
=== minio-contract ===
minio contract: arm64, minio RELEASE.2025-09-07T16-13-09Z, mc RELEASE.2025-08-13T08-35-41Z
minio: cached, digest verified
mc: cached, digest verified
minio healthy on 127.0.0.1:20999
Added `local` successfully.
Bucket created successfully `local/contract-bucket`.
Bucket created successfully `local/denied-bucket`.
Created policy `contract-only` successfully.
Added user `scopeduser` successfully.
Attached Policies: [contract-only]
To User: scopeduser
buckets and scoped user ready
=== RUN TestDeliveredContractMinio
=== RUN TestDeliveredContractMinio/put
=== RUN TestDeliveredContractMinio/get_round-trips_the_body
=== RUN TestDeliveredContractMinio/list_shows_the_key
=== RUN TestDeliveredContractMinio/head_and_list_agree_on_the_version
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_its_own_object
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/not_by_PutObjectTagging
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/and_not_by_x-amz-tagging_on_upload
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CreateMultipartUpload
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CopyObject_with_a_REPLACE_tagging_directive
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/but_multipart_itself_is_allowed
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_copy_itself_is_allowed
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/a_POST-policy_forged_tag_with_a_matching_version_is_still_not_a_verdict
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_an_ordinary_tagged-with-something-else_upload_is_allowed
=== RUN TestDeliveredContractMinio/delete_removes_it
=== RUN TestDeliveredContractMinio/cross-bucket_denial
--- PASS: TestDeliveredContractMinio (0.02s)
--- PASS: TestDeliveredContractMinio/put (0.00s)
--- PASS: TestDeliveredContractMinio/get_round-trips_the_body (0.00s)
--- PASS: TestDeliveredContractMinio/list_shows_the_key (0.00s)
--- PASS: TestDeliveredContractMinio/head_and_list_agree_on_the_version (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_its_own_object (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/not_by_PutObjectTagging (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/and_not_by_x-amz-tagging_on_upload (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route (0.01s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CreateMultipartUpload (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CopyObject_with_a_REPLACE_tagging_directive (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/but_multipart_itself_is_allowed (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_copy_itself_is_allowed (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/a_POST-policy_forged_tag_with_a_matching_version_is_still_not_a_verdict (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_an_ordinary_tagged-with-something-else_upload_is_allowed (0.00s)
--- PASS: TestDeliveredContractMinio/delete_removes_it (0.00s)
--- PASS: TestDeliveredContractMinio/cross-bucket_denial (0.00s)
PASS
ok github.com/carlosframework/platform/internal/objstore 0.023s
=== RUN TestT4StorageProbeMinio
2026/10/13 21:01:52 moves: T4: STORE: list: operation error S3: ListObjectsV2, https response error StatusCode: 403, RequestID: 18DE3293EAF238A7, HostID: 7c420053e0fbcd7f41653fdd92ffa2802c903d05303b1aa15adc2e8bb65d183f, api error SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your key and signing method.
--- PASS: TestT4StorageProbeMinio (0.01s)
PASS
ok github.com/carlosframework/platform/internal/host 0.022s
minio contract: PASS
diff --git a/internal/activator/activator.go b/internal/activator/activator.go| index 5c2f1780e..c6604f55b 100644 |
| --- a/internal/activator/activator.go |
| +++ b/internal/activator/activator.go |
| @@ -4983,12 +4983,28 @@ func (a *Service) ServeScheduled(w http.ResponseWriter, r *http.Request, rt regi |
| func (a *Service) serve(w http.ResponseWriter, r *http.Request, rt registry.Route, proxy http.Handler, stamp bool) bool { |
| if rt.Kind == "instance" && rt.Hibernate && a.Startup != nil { |
| + waited := false |
| + select { |
| + case <-a.Startup: |
| + default: |
| + waited = true |
| + } |
| deadline := time.NewTimer(wakeWaitBound) |
| err := a.awaitStartup(r.Context(), deadline.C) |
| deadline.Stop() |
| if err != nil { |
| return a.serveWakeError(w, r, rt, err) |
| } |
| + // The edge chose rt and its proxy before startup recovery ran. If |
| + // recovery moved this host's upstream (a layout journal finished), |
| + // that proxy points at the old socket: answer as a wake still in |
| + // progress, and the retry is routed afresh. |
| + if waited && a.Routes != nil { |
| + if fresh, ferr := a.Routes.Get(rt.Host); ferr == nil && fresh != nil && |
| + (fresh.Socket != rt.Socket || fresh.Addr != rt.Addr) { |
| + return a.serveWakeError(w, r, rt, errWakeTimeout) |
| + } |
| + } |
| } |
| a.mu.Lock() |
diff --git a/internal/activator/startup_test.go b/internal/activator/startup_test.go| index 91563b3ca..17e25129c 100644 |
| --- a/internal/activator/startup_test.go |
| +++ b/internal/activator/startup_test.go |
| @@ -75,3 +75,52 @@ func TestStartupShutdownAnswersServiceUnavailable(t *testing.T) { |
| }) |
| } |
| } |
| + |
| +type startupRoutes map[string]registry.Route |
| + |
| +func (s startupRoutes) Get(host string) (*registry.Route, error) { |
| + rt, ok := s[host] |
| + if !ok { |
| + return nil, nil |
| + } |
| + return &rt, nil |
| +} |
| + |
| +// A request held through startup carries the proxy the edge chose before |
| +// recovery ran. When recovery moved the host's socket, it is answered as a |
| +// wake in progress, so the retry is routed afresh, never sent to the old |
| +// socket. |
| +func TestStartupHeldRequestRefusesStaleUpstream(t *testing.T) { |
| + for _, moved := range []bool{false, true} { |
| + a := New(Config{}, &fakeBackend{}, nil) |
| + ready := make(chan struct{}) |
| + a.Startup = ready |
| + rt := registry.Route{Host: "shop.example.com", Kind: "instance", Hibernate: true, Socket: "/run/carlos/shop.example.com.sock"} |
| + fresh := rt |
| + if moved { |
| + fresh.Socket = "/run/carlos/instances/shop.example.com/app.sock" |
| + } |
| + a.Routes = startupRoutes{rt.Host: fresh} |
| + proxied := false |
| + proxy := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { proxied = true }) |
| + w := httptest.NewRecorder() |
| + done := make(chan struct{}) |
| + go func() { |
| + defer close(done) |
| + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) |
| + defer cancel() |
| + a.ServeHTTP(w, httptest.NewRequest(http.MethodGet, "http://shop.example.com/", nil).WithContext(ctx), rt, proxy) |
| + }() |
| + time.Sleep(20 * time.Millisecond) |
| + close(ready) |
| + <-done |
| + a.lifeStop() |
| + if moved { |
| + if proxied || w.Code != http.StatusServiceUnavailable || w.Header().Get("Retry-After") != "5" { |
| + t.Fatalf("moved socket: proxied=%v code=%d", proxied, w.Code) |
| + } |
| + } else if w.Code == http.StatusServiceUnavailable && w.Body.String() == "instance is waking; retry shortly\n" { |
| + t.Fatalf("unchanged socket was refused as stale") |
| + } |
| + } |
| +} |
diff --git a/internal/provision/plan14_root_reads_test.go b/internal/provision/plan14_root_reads_test.go| index 4cea48bd2..4142e3494 100644 |
| --- a/internal/provision/plan14_root_reads_test.go |
| +++ b/internal/provision/plan14_root_reads_test.go |
| @@ -657,7 +657,7 @@ func TestPlan14RootReadCensus(t *testing.T) { |
| if err = loadRootReadInventory(filepath.Join(root, "internal/provision/testdata/plan14-root-reads-hotfix281.tsv"), &inv, true); err != nil { |
| t.Fatal(err) |
| } |
| - seal = "4b12ba7e94ff1fbc7f2313dbcfb79c5ac1f0455f248f214a8257c08805c1a70f" |
| + seal = "264f9a39233de58dbc13bff700e6e5353f8c72b3f266fe00b86d003759531724" |
| errs := append(compareRootReads(got, inv), checkRootReadLegacy(inv, seal)...) |
| errs = append(errs, checkRootReadDeclarations(got, inv)...) |
| if len(errs) > 0 { |
diff --git a/internal/provision/testdata/plan14-root-reads-hotfix281.tsv b/internal/provision/testdata/plan14-root-reads-hotfix281.tsv| index a46eb8992..da5893e6b 100644 |
| --- a/internal/provision/testdata/plan14-root-reads-hotfix281.tsv |
| +++ b/internal/provision/testdata/plan14-root-reads-hotfix281.tsv |
| @@ -5,14 +5,14 @@ internal/activator/activator.go Service.BeginSidecarRequest legacy accepted-lega |
| internal/activator/activator.go Service.WakeWorker legacy accepted-legacy accepted-legacy;rev3=census-ruling-hotfix281;basis=The same host and route reads follow a bounded startup wait; no new source or authority. registry:Host@1242,registry:Host@1652,registry:Host@834,registry:Host@864,whole:Route@1225 bda1e33466a92d540eeb724284aa431550a323e7dbb432cc7b8872498929bec9 |
| @legacy b3e3b36908d945c5c486c57073c911b113966f1cc2fb93347e0057059b4750be internal/activator/activator.go Service.begin legacy accepted-legacy accepted-legacy;rev3=census-ruling-hotfix281;basis=The same host and route reads follow a bounded startup wait; no new source or authority. registry:Host@1197,registry:Host@1276,registry:Host@326,registry:Host@405,whole:Route@1206,whole:Route@1213 642ece8b785a5654dc04d4461995b77dffa2073bcad44897581cfa0a390b6016 |
| internal/activator/activator.go Service.begin legacy accepted-legacy accepted-legacy;rev3=census-ruling-hotfix281;basis=The same host and route reads follow a bounded startup wait; no new source or authority. registry:Host@1197,registry:Host@1276,registry:Host@326,registry:Host@405,whole:Route@1206,whole:Route@1213 642ece8b785a5654dc04d4461995b77dffa2073bcad44897581cfa0a390b6016 |
| -@legacy aa4915f25d4d2cb1bc7f896b9808ecfd25fe9c4b5cbb050976e896947a1476aa internal/activator/activator.go Service.serve legacy accepted-legacy accepted-legacy;rev3=census-ruling-hotfix281;basis=Startup repeats the existing Kind and Hibernate checks; error logging moved to serveWakeError. The same route fields and sources are read. registry:Hibernate@151,registry:Hibernate@788,registry:Host@397,registry:Kind@126,registry:Kind@762,whole:Route@1907,whole:Route@2876,whole:Route@2936,whole:Route@347 44becc931aec04495ff7daae2154fbbf500c4e6d4df65b328a790e33cfa3a0ac |
| -internal/activator/activator.go Service.serve legacy accepted-legacy accepted-legacy;rev3=census-ruling-hotfix281;basis=Startup repeats the existing Kind and Hibernate checks; error logging moved to serveWakeError. The same route fields and sources are read. registry:Hibernate@151,registry:Hibernate@788,registry:Host@397,registry:Kind@126,registry:Kind@762,whole:Route@1907,whole:Route@2876,whole:Route@2936,whole:Route@347 44becc931aec04495ff7daae2154fbbf500c4e6d4df65b328a790e33cfa3a0ac |
| +@legacy 7ee0c5cbf9ee48c401057756d3c6d37b8acabc1ff5570d0bce917ece9e616002 internal/activator/activator.go Service.serve legacy accepted-legacy accepted-legacy;rev3=census-ruling-hotfix281;basis=Startup repeats the existing Kind and Hibernate checks; error logging moved to serveWakeError. A request held through startup re-reads its own route's Socket and Addr and can only refuse (wake-timeout 503) when recovery moved them; agent-side, deny-only, no root decision. registry:Addr@837,registry:Addr@851,registry:Hibernate@1353,registry:Hibernate@151,registry:Host@762,registry:Host@962,registry:Kind@126,registry:Kind@1327,registry:Socket@808,registry:Socket@824,whole:Route@2472,whole:Route@3441,whole:Route@3501,whole:Route@428,whole:Route@787,whole:Route@896 dbb435e9058b510bc7348511b209f1bbcf3b54f6fa9df3506ad4783f5ff070e4 |
| +internal/activator/activator.go Service.serve legacy accepted-legacy accepted-legacy;rev3=census-ruling-hotfix281;basis=Startup repeats the existing Kind and Hibernate checks; error logging moved to serveWakeError. A request held through startup re-reads its own route's Socket and Addr and can only refuse (wake-timeout 503) when recovery moved them; agent-side, deny-only, no root decision. registry:Addr@837,registry:Addr@851,registry:Hibernate@1353,registry:Hibernate@151,registry:Host@762,registry:Host@962,registry:Kind@126,registry:Kind@1327,registry:Socket@808,registry:Socket@824,whole:Route@2472,whole:Route@3441,whole:Route@3501,whole:Route@428,whole:Route@787,whole:Route@896 dbb435e9058b510bc7348511b209f1bbcf3b54f6fa9df3506ad4783f5ff070e4 |
| @legacy bf4ca1db43d8023db08187eb3afdcfbd4599b3f6966c81274b60e2752b6c5fac internal/activator/activator.go Service.serveWakeError legacy accepted-legacy accepted-legacy;rev3=census-ruling-hotfix281;basis=Extracted unchanged error mapping and Host log read from Service.serve; no new source or authority. registry:Host@1364 e4ad730f8b463cf112c59bd061c7384ff4afe626d2bedd7f90ccd3df791333ba |
| internal/activator/activator.go Service.serveWakeError legacy accepted-legacy accepted-legacy;rev3=census-ruling-hotfix281;basis=Extracted unchanged error mapping and Host log read from Service.serve; no new source or authority. registry:Host@1364 e4ad730f8b463cf112c59bd061c7384ff4afe626d2bedd7f90ccd3df791333ba |
| internal/host/agent.go runAgent authority B,C,D,F rev3=census-ruling-hotfix281;basis=Only activator startup and dependent duties run asynchronously; shutdown cancels their child context before the join, preserving the agent lifetime through child and rollout drain. Registry, route, data-directory and backend inputs are unchanged; B,C,D,F authority is retained. file:Exec@13674,file:Open@731,registry:App@10065,whole:Route@10057,whole:Route@21396 5d8ca6215a4f7eddc85fd05a6696494d22922e8c23eab4d4eb91605377d2277c |
| @legacy daa120f77654cd1238b494d92b7a4db9ee115f4f56945243b26a7ebe02e584db internal/host/instancekeys.go backfillInstanceKeys legacy accepted-legacy accepted-legacy;rev3=census-ruling-hotfix281;basis=Cancellation stops the loop early; route reads, per-host preparation and key sources are unchanged. registry:Host@553,registry:Host@701,registry:Host@867,whole:Route@251,whole:Route@320,whole:Route@399 b4d7ba9a5dc32cb04c214adc69184d91bc65d2487c661150fed899f1deba676d |
| internal/host/instancekeys.go backfillInstanceKeys legacy accepted-legacy accepted-legacy;rev3=census-ruling-hotfix281;basis=Cancellation stops the loop early; route reads, per-host preparation and key sources are unchanged. registry:Host@553,registry:Host@701,registry:Host@867,whole:Route@251,whole:Route@320,whole:Route@399 b4d7ba9a5dc32cb04c214adc69184d91bc65d2487c661150fed899f1deba676d |
| -@legacy 8f772c7c43dec1102a01dbe4a945b8eb0c751f0e2f6efe05dc437e13b21daede internal/host/layoutleg.go activatorStart.Run legacy accepted-legacy accepted-legacy;rev3=census-ruling-hotfix281;basis=Legacy sweep, recovery and key pass run under the agent lifetime in the background. The same route list and callbacks are used; claim boxes retain Start alone. whole:Route@803 e93d0c33f6ac39f9c644b7bfa2463c30a9980dfd0e23a515ba87f356e8899c57 |
| -internal/host/layoutleg.go activatorStart.Run legacy accepted-legacy accepted-legacy;rev3=census-ruling-hotfix281;basis=Legacy sweep, recovery and key pass run under the agent lifetime in the background. The same route list and callbacks are used; claim boxes retain Start alone. whole:Route@803 e93d0c33f6ac39f9c644b7bfa2463c30a9980dfd0e23a515ba87f356e8899c57 |
| -@coverage internal/activator af5b4506d7b3146462790223d541f6caca55b0606055734733e79accaad9440a |
| +@legacy 8884dca0e95b3cdd016d6c150db8f74a6ad64cc8aa4f0d2fdbfc935fa4947ed2 internal/host/layoutleg.go activatorStart.Run legacy accepted-legacy accepted-legacy;rev3=census-ruling-hotfix281;basis=Legacy sweep, recovery and key pass run in the background under a startup context that is a child of the agent lifetime. The same route list and callbacks are used; claim boxes retain Start alone. whole:Route@803 e93d0c33f6ac39f9c644b7bfa2463c30a9980dfd0e23a515ba87f356e8899c57 |
| +internal/host/layoutleg.go activatorStart.Run legacy accepted-legacy accepted-legacy;rev3=census-ruling-hotfix281;basis=Legacy sweep, recovery and key pass run in the background under a startup context that is a child of the agent lifetime. The same route list and callbacks are used; claim boxes retain Start alone. whole:Route@803 e93d0c33f6ac39f9c644b7bfa2463c30a9980dfd0e23a515ba87f356e8899c57 |
| +@coverage internal/activator 7a8d6707d50423081a86913d5f173064df2f6af884698d19e653ee985409fe75 |
| @coverage internal/host ee4e46a4efcbea38cbc81fcdcab7ac4dc5eac2eeecb9ed879aecc4968315cf74 |