carlos / platform Public

plan: self-serve moves 3, rev 7 (Astra review 6: fallback when no local exact ready upstream; Hosts() keeps its self-label guard)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 0826600b314ff25df45121214852967873cca7bf parent 36c425e
1 file changed, +5 −5
  • docs/superpowers/plans/2026-10-22-self-serve-moves-3-holding-page.md +5 −5

CI passed — run details

CI log
=== gate ===
.amadan/test-gate.sh
go: downloading github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.68.0
go: downloading github.com/aws/aws-sdk-go-v2/service/costexplorer v1.67.5
go: downloading github.com/aws/aws-sdk-go-v2 v1.44.0
go: downloading github.com/aws/smithy-go v1.28.1
go: downloading github.com/aws/aws-sdk-go-v2/service/s3 v1.105.0
go: downloading github.com/superfly/ltx v0.5.1
go: downloading golang.org/x/net v0.56.0
go: downloading modernc.org/sqlite v1.55.0
go: downloading github.com/benbjohnson/litestream v0.5.14
go: downloading github.com/aws/aws-sdk-go-v2/config v1.32.6
go: downloading github.com/aws/aws-sdk-go-v2/service/route53 v1.64.1
go: downloading golang.org/x/crypto v0.53.0
go: downloading github.com/aws/aws-sdk-go-v2/service/sns v1.43.0
go: downloading github.com/aws/aws-sdk-go-v2/service/autoscaling v1.74.0
go: downloading github.com/aws/aws-sdk-go-v2/service/ec2 v1.324.0
go: downloading github.com/aws/aws-sdk-go-v2/service/acm v1.45.0
go: downloading github.com/aws/aws-sdk-go-v2/service/iam v1.58.2
go: downloading github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.37.0
go: downloading github.com/aws/aws-sdk-go-v2/service/sts v1.45.6
go: downloading golang.org/x/sys v0.46.0
go: downloading github.com/aws/aws-sdk-go-v2/credentials v1.19.6
go: downloading github.com/oschwald/maxminddb-golang v1.13.1
go: downloading github.com/aws/aws-sdk-go-v2/service/sesv2 v1.66.6
go: downloading github.com/benbjohnson/litestream v0.5.14
go: downloading github.com/aws/aws-sdk-go-v2/service/ec2 v1.324.0
go: downloading modernc.org/sqlite v1.55.0
go: downloading github.com/aws/aws-sdk-go-v2/service/autoscaling v1.74.0
go: downloading github.com/aws/aws-sdk-go-v2/service/iam v1.58.2
go: downloading github.com/aws/aws-sdk-go-v2/service/ssm v1.74.0
go: downloading github.com/pion/logging v0.2.4
go: downloading github.com/pion/stun/v3 v3.0.1
go: downloading github.com/pion/turn/v4 v4.1.4
go: downloading github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16
go: downloading github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4
go: downloading github.com/aws/aws-sdk-go-v2/service/signin v1.0.4
go: downloading github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12
go: downloading github.com/aws/aws-sdk-go-v2/service/sso v1.30.8
go: downloading github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.40
go: downloading github.com/klauspost/compress v1.18.0
go: downloading github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.38
go: downloading github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.19
go: downloading github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.40
go: downloading github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.14
go: downloading github.com/pion/stun/v3 v3.0.1
go: downloading github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.23
go: downloading github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.31
go: downloading github.com/pierrec/lz4/v4 v4.1.22
go: downloading github.com/pion/randutil v0.1.0
go: downloading github.com/pion/transport/v4 v4.0.1
go: downloading github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.40
go: downloading github.com/pierrec/lz4/v4 v4.1.22
go: downloading github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.40
go: downloading github.com/pion/transport/v3 v3.0.8
go: downloading github.com/pion/dtls/v3 v3.0.7
go: downloading github.com/pion/transport/v3 v3.0.8
go: downloading github.com/pion/dtls/v3 v3.0.7
go: downloading github.com/wlynxg/anet v0.0.5
go: downloading github.com/wlynxg/anet v0.0.5
go: downloading github.com/prometheus/client_golang v1.17.0
go: downloading golang.org/x/sync v0.21.0
go: downloading github.com/lmittmann/tint v1.1.3
go: downloading github.com/mattn/go-isatty v0.0.20
go: downloading github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.20.18
go: downloading github.com/prometheus/client_golang v1.17.0
go: downloading golang.org/x/sync v0.21.0
go: downloading github.com/mattn/go-isatty v0.0.20
go: downloading github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.20.18
go: downloading github.com/lmittmann/tint v1.1.3
go: downloading github.com/prometheus/client_model v0.5.0
go: downloading github.com/beorn7/perks v1.0.1
go: downloading github.com/prometheus/procfs v0.12.0
go: downloading github.com/cespare/xxhash/v2 v2.3.0
go: downloading google.golang.org/protobuf v1.36.10
go: downloading github.com/prometheus/common v0.45.0
go: downloading github.com/cespare/xxhash/v2 v2.3.0
go: downloading github.com/prometheus/common v0.45.0
go: downloading github.com/prometheus/client_model v0.5.0
go: downloading google.golang.org/protobuf v1.36.10
go: downloading github.com/beorn7/perks v1.0.1
go: downloading github.com/prometheus/procfs v0.12.0
go: downloading github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0
go: downloading github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0
go: downloading golang.org/x/text v0.38.0
go: downloading golang.org/x/text v0.38.0
go: downloading modernc.org/libc v1.74.1
go: downloading modernc.org/libc v1.74.1
go: downloading modernc.org/memory v1.11.0
go: downloading modernc.org/mathutil v1.7.1
go: downloading github.com/google/uuid v1.6.0
go: downloading github.com/dustin/go-humanize v1.0.1
go: downloading github.com/google/uuid v1.6.0
go: downloading github.com/dustin/go-humanize v1.0.1
go: downloading modernc.org/mathutil v1.7.1
go: downloading modernc.org/memory v1.11.0
go: downloading github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec
go: downloading github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec
=== launchctx (3 s)
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]
=== vet (46 s)
go: downloading modernc.org/sqlite v1.55.0
go: downloading github.com/benbjohnson/litestream v0.5.14
go: downloading github.com/aws/aws-sdk-go-v2/service/ec2 v1.324.0
go: downloading github.com/aws/aws-sdk-go-v2/service/iam v1.58.2
go: downloading github.com/aws/aws-sdk-go-v2/service/ssm v1.74.0
go: downloading github.com/aws/aws-sdk-go-v2/service/autoscaling v1.74.0
go: downloading github.com/aws/aws-sdk-go-v2/service/sesv2 v1.66.6
go: downloading golang.org/x/tools v0.47.0
go: downloading github.com/pierrec/lz4/v4 v4.1.22
go: downloading github.com/klauspost/compress v1.18.0
go: downloading github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.40
go: downloading github.com/pion/dtls/v3 v3.0.7
go: downloading github.com/pion/transport/v3 v3.0.8
go: downloading github.com/wlynxg/anet v0.0.5
go: downloading github.com/prometheus/client_golang v1.17.0
go: downloading golang.org/x/sync v0.21.0
go: downloading github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.20.18
go: downloading github.com/mattn/go-isatty v0.0.20
go: downloading github.com/lmittmann/tint v1.1.3
go: downloading github.com/prometheus/common v0.45.0
go: downloading github.com/cespare/xxhash/v2 v2.3.0
go: downloading google.golang.org/protobuf v1.36.10
go: downloading github.com/prometheus/procfs v0.12.0
go: downloading github.com/beorn7/perks v1.0.1
go: downloading github.com/prometheus/client_model v0.5.0
go: downloading github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0
go: downloading golang.org/x/text v0.38.0
go: downloading golang.org/x/mod v0.37.0
go: downloading modernc.org/libc v1.74.1
go: downloading github.com/dustin/go-humanize v1.0.1
go: downloading github.com/google/uuid v1.6.0
go: downloading modernc.org/memory v1.11.0
go: downloading modernc.org/mathutil v1.7.1
go: downloading github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec
=== gofmt (0 s)
gofmt -l .: clean
=== rest (190 s)
?   	github.com/carlosframework/platform/cmd/changelog	[no test files]
ok  	github.com/carlosframework/platform/cmd/console	3.182s
ok  	github.com/carlosframework/platform/cmd/moveprobe	11.701s
ok  	github.com/carlosframework/platform/cmd/zddprobe	0.717s
ok  	github.com/carlosframework/platform/internal/activator	62.269s
ok  	github.com/carlosframework/platform/internal/agentsock	0.019s
ok  	github.com/carlosframework/platform/internal/alerting	0.006s
ok  	github.com/carlosframework/platform/internal/analytics	0.024s
ok  	github.com/carlosframework/platform/internal/appconfig	2.861s
ok  	github.com/carlosframework/platform/internal/apperr	0.096s
ok  	github.com/carlosframework/platform/internal/applog	0.166s
ok  	github.com/carlosframework/platform/internal/awsinv	0.007s
ok  	github.com/carlosframework/platform/internal/boxchoice	0.005s
ok  	github.com/carlosframework/platform/internal/boxid	0.777s
?   	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.010s
ok  	github.com/carlosframework/platform/internal/caps	0.016s
ok  	github.com/carlosframework/platform/internal/certwarm	0.004s
ok  	github.com/carlosframework/platform/internal/cgroup	0.727s
ok  	github.com/carlosframework/platform/internal/changelog	0.387s
ok  	github.com/carlosframework/platform/internal/claimactivation	1.017s
ok  	github.com/carlosframework/platform/internal/clamd	0.058s
?   	github.com/carlosframework/platform/internal/cliflag	[no test files]
?   	github.com/carlosframework/platform/internal/controlname	[no test files]
?   	github.com/carlosframework/platform/internal/controlsock	[no test files]
ok  	github.com/carlosframework/platform/internal/dbdoor	5.843s
ok  	github.com/carlosframework/platform/internal/dbdoor/dbdoortest	0.010s
ok  	github.com/carlosframework/platform/internal/dbverify	0.005s
ok  	github.com/carlosframework/platform/internal/dnsrec	0.004s
ok  	github.com/carlosframework/platform/internal/docsite	0.007s
ok  	github.com/carlosframework/platform/internal/domains	2.652s
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	49.123s
?   	github.com/carlosframework/platform/internal/edgeproof	[no test files]
ok  	github.com/carlosframework/platform/internal/edgesfile	0.020s
ok  	github.com/carlosframework/platform/internal/fleetapi	0.164s
ok  	github.com/carlosframework/platform/internal/gate	1.664s
ok  	github.com/carlosframework/platform/internal/genselect	0.023s
ok  	github.com/carlosframework/platform/internal/geo	0.030s
ok  	github.com/carlosframework/platform/internal/geoip	0.044s
ok  	github.com/carlosframework/platform/internal/historyreadback	0.197s
ok  	github.com/carlosframework/platform/internal/host	139.879s
ok  	github.com/carlosframework/platform/internal/hostactors	6.009s
ok  	github.com/carlosframework/platform/internal/hostactors/awsmembership	0.016s
ok  	github.com/carlosframework/platform/internal/hostbox	3.319s
ok  	github.com/carlosframework/platform/internal/hostclaim	0.763s
ok  	github.com/carlosframework/platform/internal/hostenv	0.014s
ok  	github.com/carlosframework/platform/internal/hostevidence	0.015s
ok  	github.com/carlosframework/platform/internal/hostexec	5.672s
ok  	github.com/carlosframework/platform/internal/hostfence	0.058s
ok  	github.com/carlosframework/platform/internal/hostfiles	10.469s
ok  	github.com/carlosframework/platform/internal/hostfloor	0.016s
ok  	github.com/carlosframework/platform/internal/hostguard	1.044s
ok  	github.com/carlosframework/platform/internal/hostops	2.055s
?   	github.com/carlosframework/platform/internal/hostops/fencerelease	[no test files]
ok  	github.com/carlosframework/platform/internal/hostops/internal/fencerelease	0.015s
ok  	github.com/carlosframework/platform/internal/hostquarantine	0.014s
ok  	github.com/carlosframework/platform/internal/hostrelocate	0.679s
ok  	github.com/carlosframework/platform/internal/hostresolve	0.221s
ok  	github.com/carlosframework/platform/internal/hostwrite	0.014s
ok  	github.com/carlosframework/platform/internal/infraview	0.013s
ok  	github.com/carlosframework/platform/internal/instancectl	5.245s
ok  	github.com/carlosframework/platform/internal/instanceexec	2.837s
ok  	github.com/carlosframework/platform/internal/instancefs	0.036s
ok  	github.com/carlosframework/platform/internal/instancekey	0.016s
ok  	github.com/carlosframework/platform/internal/instanceupdates	0.007s
ok  	github.com/carlosframework/platform/internal/layout	1.753s
ok  	github.com/carlosframework/platform/internal/lbhealth	0.007s
ok  	github.com/carlosframework/platform/internal/lease	10.082s
ok  	github.com/carlosframework/platform/internal/lease/leasetest	0.553s
ok  	github.com/carlosframework/platform/internal/ledger	0.041s
ok  	github.com/carlosframework/platform/internal/mail	0.269s
ok  	github.com/carlosframework/platform/internal/maintenance	0.107s
ok  	github.com/carlosframework/platform/internal/maintenanceexec	5.603s
ok  	github.com/carlosframework/platform/internal/maintenanceguard	0.148s
ok  	github.com/carlosframework/platform/internal/metrics	0.008s
ok  	github.com/carlosframework/platform/internal/moves	29.951s
ok  	github.com/carlosframework/platform/internal/moves/archive	1.058s
ok  	github.com/carlosframework/platform/internal/objstore	0.308s
ok  	github.com/carlosframework/platform/internal/ops	0.211s
ok  	github.com/carlosframework/platform/internal/park	0.300s
ok  	github.com/carlosframework/platform/internal/plans	0.006s
ok  	github.com/carlosframework/platform/internal/privatefile	0.003s
ok  	github.com/carlosframework/platform/internal/provision	49.358s
ok  	github.com/carlosframework/platform/internal/publicrelease	0.019s
?   	github.com/carlosframework/platform/internal/regionname	[no test files]
ok  	github.com/carlosframework/platform/internal/registry	5.836s
ok  	github.com/carlosframework/platform/internal/relay	4.228s
ok  	github.com/carlosframework/platform/internal/release	30.651s
ok  	github.com/carlosframework/platform/internal/rollout	4.102s
ok  	github.com/carlosframework/platform/internal/rolloutwords	0.005s
ok  	github.com/carlosframework/platform/internal/rootaws	0.008s
ok  	github.com/carlosframework/platform/internal/rootparticipation	0.059s
ok  	github.com/carlosframework/platform/internal/rootstate	0.028s
ok  	github.com/carlosframework/platform/internal/runs	0.605s
ok  	github.com/carlosframework/platform/internal/s3compat	0.007s
ok  	github.com/carlosframework/platform/internal/safefile	0.010s
ok  	github.com/carlosframework/platform/internal/schedule	2.857s
ok  	github.com/carlosframework/platform/internal/seeds	0.012s
ok  	github.com/carlosframework/platform/internal/sim/hostlife	11.325s
ok  	github.com/carlosframework/platform/internal/sim/litestreamfacts	3.627s
ok  	github.com/carlosframework/platform/internal/status	0.078s
ok  	github.com/carlosframework/platform/internal/steering	0.008s
ok  	github.com/carlosframework/platform/internal/stopevidence	0.259s
ok  	github.com/carlosframework/platform/internal/svcrole	0.003s
ok  	github.com/carlosframework/platform/internal/telemetry	0.005s
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.005s
ok  	github.com/carlosframework/platform/internal/updatewords	0.005s
ok  	github.com/carlosframework/platform/internal/usage	0.010s
ok  	github.com/carlosframework/platform/internal/version	0.004s
ok  	github.com/carlosframework/platform/internal/vet	1.680s
=== internal_console@0 (87 s)
ok  	github.com/carlosframework/platform/internal/console	85.764s
=== internal_console@1 (42 s)
ok  	github.com/carlosframework/platform/internal/console	40.664s
=== internal_console@2 (47 s)
ok  	github.com/carlosframework/platform/internal/console	45.332s
=== internal_console@3 (42 s)
ok  	github.com/carlosframework/platform/internal/console	40.317s
=== internal_console@4 (44 s)
ok  	github.com/carlosframework/platform/internal/console	42.446s
=== internal_console@5 (41 s)
ok  	github.com/carlosframework/platform/internal/console	39.568s
=== internal_console@6 (43 s)
ok  	github.com/carlosframework/platform/internal/console	41.967s
=== internal_console@7 (50 s)
ok  	github.com/carlosframework/platform/internal/console	48.689s
=== root@0 (38 s)
ok  	github.com/carlosframework/platform	36.480s
=== root@1 (47 s)
ok  	github.com/carlosframework/platform	45.167s
=== root@2 (45 s)
ok  	github.com/carlosframework/platform	43.886s
=== 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
linux/arm64 carlos binary: 50069666 bytes (ceiling 52000000)
--- 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.022s
=== RUN   TestT4StorageProbeMinio
2026/10/22 09:45:24 moves: T4: STORE: list: operation error S3: ListObjectsV2, https response error StatusCode: 403, RequestID: 18E0D0E2C0C8EE2E, 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.021s
minio contract: PASS
diff --git a/docs/superpowers/plans/2026-10-22-self-serve-moves-3-holding-page.md b/docs/superpowers/plans/2026-10-22-self-serve-moves-3-holding-page.md
index d64b18746..efbfd3aa0 100644
--- a/docs/superpowers/plans/2026-10-22-self-serve-moves-3-holding-page.md
+++ b/docs/superpowers/plans/2026-10-22-self-serve-moves-3-holding-page.md
@@ -2,7 +2,7 @@
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
-Rev 6, 2026-10-22. Rev 5's review (`selfserve-plan3-review5.md`) is answered: the kept dispatch exceptions are an **explicit step** over a local wildcard fallback captured in the decision with its table (N1), and the Global Constraint says what blocks the fallback (a live exact holding winner, not any hold); invariant (e) says "stamped, or not lower than any live same-target hold" (F1); an unlabelled box keeps today's split, refusing to **dial** while `KnownHost`, `Hosts`, `HoldingHosts` and `certNames` still see admitted remote candidates (N4); subscription to the holding view is one operation under `pubMu` that installs the callback and delivers the current snapshot (N5). Rev 4's review (`selfserve-plan3-review4.md`) is answered: the ready stage **calls the shared fold** and no longer restates it (F2); the invariants are scoped to the four stages and (e), (g), (h), (j) are qualified (F1); the holding stage is a **sorted fold** with a pinned three-hold witness (N2); hold rebuilds read the latest view snapshot and the registry under one mutex and are triggered by both the view and `Reload`, and the view publishes under its own mutex (F5); the dispatch exceptions for accepted hops, door requests and a failed backhaul over a local wildcard are preserved and tested (N1); the home map's wake compares the effective parent set including platform holds (N3); local ready aliases are never platform, `candCert` is constructed explicitly, the unlabelled-box refusal is kept, and the view snapshot crosses packages as an exported `edge.HoldSnapshot` (F4); `AliasPublishable` checks `a.Alias` (F7); the census overlay loads in `plan14_root_reads_test.go` before `compareRootReads` (F10). Reviews: rev 1 (`after236/selfserve-plan3-review.md`, 15 findings), rev 2 (`selfserve-plan3-review2.md`, 14), rev 3 (`selfserve-plan3-review3.md`, F1 to F10). Rev 4 answers rev 3's ten and is self-contained (nothing is "as rev 2"; F8). The ranking is restated so that it **cannot** disagree with plan 1's fold (F1, F2): a holding candidate's only power over ready candidates is to **suppress** the stale ready publications of its own target (same `targetHost`, unstamped, lower pair); the ready candidates that survive are folded by the **same function** `foldHomes` uses, so ready-only routing is plan 1's by construction and a differential test pins it; only when no ready candidate survives does a hold answer. The invariants are restated to be consistent with that algorithm and with §6.4 ("eligible under ordinary routing" = not a suppressed stale publication of the moving target); the "real hold beats a stamped alias" test is withdrawn as contradicting §6.4. The decision carries the whole local table it was resolved against (F3). Candidate construction is complete for local ready, local holding (aliases expanded through the writer's own predicate) and remote, with the existing admissions kept (F4). Local holds live in their own atomic snapshot that `Reload` never touches, and the view publishes revision and contents in one immutable value (F5). `Allowed` keeps the tunnel exception; a separate certificate-name enumeration covers holds for warming without making them served evidence (F6). `AliasPublishable` includes the primary, the name exclusions, and no owner parameter (F7). The countdown arithmetic and the inherited contracts are restated in full (F8). The discovery check includes `internal/steering` and a reviewed exclusion list (F9). The census names `internal/edgesfile` and the loader (F10).
+Rev 7, 2026-10-22. Rev 6's review (`selfserve-plan3-review6.md`: F1, N4, N5 closed; N1 and N6 remained) is answered: the fallback is captured when the exact name has no local exact **ready upstream** (a local hold that lost to a remote ready does not prevent it; the three-candidate witness is pinned), and `Hosts()` keeps today's self-label guard (nil on an unlabelled box) while `KnownHost`, `HoldingHosts` and `certNames` keep their membership view. Rev 5's review (`selfserve-plan3-review5.md`) is answered: the kept dispatch exceptions are an **explicit step** over a local wildcard fallback captured in the decision with its table (N1), and the Global Constraint says what blocks the fallback (a live exact holding winner, not any hold); invariant (e) says "stamped, or not lower than any live same-target hold" (F1); an unlabelled box keeps today's split, refusing to **dial** while `KnownHost`, `Hosts`, `HoldingHosts` and `certNames` still see admitted remote candidates (N4); subscription to the holding view is one operation under `pubMu` that installs the callback and delivers the current snapshot (N5). Rev 4's review (`selfserve-plan3-review4.md`) is answered: the ready stage **calls the shared fold** and no longer restates it (F2); the invariants are scoped to the four stages and (e), (g), (h), (j) are qualified (F1); the holding stage is a **sorted fold** with a pinned three-hold witness (N2); hold rebuilds read the latest view snapshot and the registry under one mutex and are triggered by both the view and `Reload`, and the view publishes under its own mutex (F5); the dispatch exceptions for accepted hops, door requests and a failed backhaul over a local wildcard are preserved and tested (N1); the home map's wake compares the effective parent set including platform holds (N3); local ready aliases are never platform, `candCert` is constructed explicitly, the unlabelled-box refusal is kept, and the view snapshot crosses packages as an exported `edge.HoldSnapshot` (F4); `AliasPublishable` checks `a.Alias` (F7); the census overlay loads in `plan14_root_reads_test.go` before `compareRootReads` (F10). Reviews: rev 1 (`after236/selfserve-plan3-review.md`, 15 findings), rev 2 (`selfserve-plan3-review2.md`, 14), rev 3 (`selfserve-plan3-review3.md`, F1 to F10). Rev 4 answers rev 3's ten and is self-contained (nothing is "as rev 2"; F8). The ranking is restated so that it **cannot** disagree with plan 1's fold (F1, F2): a holding candidate's only power over ready candidates is to **suppress** the stale ready publications of its own target (same `targetHost`, unstamped, lower pair); the ready candidates that survive are folded by the **same function** `foldHomes` uses, so ready-only routing is plan 1's by construction and a differential test pins it; only when no ready candidate survives does a hold answer. The invariants are restated to be consistent with that algorithm and with §6.4 ("eligible under ordinary routing" = not a suppressed stale publication of the moving target); the "real hold beats a stamped alias" test is withdrawn as contradicting §6.4. The decision carries the whole local table it was resolved against (F3). Candidate construction is complete for local ready, local holding (aliases expanded through the writer's own predicate) and remote, with the existing admissions kept (F4). Local holds live in their own atomic snapshot that `Reload` never touches, and the view publishes revision and contents in one immutable value (F5). `Allowed` keeps the tunnel exception; a separate certificate-name enumeration covers holds for warming without making them served evidence (F6). `AliasPublishable` includes the primary, the name exclusions, and no owner parameter (F7). The countdown arithmetic and the inherited contracts are restated in full (F8). The discovery check includes `internal/steering` and a reviewed exclusion list (F9). The census names `internal/edgesfile` and the loader (F10).
Builds on plan 1 (rev 10: `(incarnation, serving_seq)` on rows and publications, `target_host` on alias publications, the fold's pair rule in `dialBeats`/`foldHomes`, `edgesFileWriteClaims(..., lifetimes bool)`, the cutover gate) and plan 2 (rev 4: `SelfServeMove{DisplayName, OfflineAt, EstimateSeconds}`, `Participants`, `moveCfg.BoxID`, `probeTarget`).
@@ -19,7 +19,7 @@ Builds on plan 1 (rev 10: `(incarnation, serving_seq)` on rows and publications,
- `offline_moves` is never a reason to count a host as served (Task 4's inventory). The claims-on writer publishes no `offline_moves`.
- A remote holding candidate is believed only while `now.Sub(fetchedAt) < holdingValidity` (5 min; at exactly 5 m 0 s it is expired); expiry is applied at ranking time from the retained candidates, never by store I/O; the answer after expiry is what the remaining candidates give, including the wildcard fallback.
- **Exact resolution and request resolution are different questions.** `Allowed`, `KnownHost` and `ExactHome` use exact candidates only and reject `*.` names as today; request resolution tries the exact name and falls back to the wildcard parent only when the exact name has no **effective** routing candidate (a live exact holding winner blocks the fallback).
-- **Ready-only routing is plan 1's fold.** The remote ready stage **calls** the shared fold (`foldHomes`'s loop over `dialBeats`, with plan 1 Task 8's pair rule: stamps first, pairs only when both entries are unstamped and share a non-empty target); the plan never restates that rule. With no holding candidate in play, `rank` returns exactly what the fold plus the local-first rule return today (Task 3's differential test); local ready candidates win over remote ones as today (the upstream table is consulted first). The dispatch exceptions of today's `ServeHTTP` are kept as an explicit step (Task 2's `fallback`): when the exact name has no local candidate but a local wildcard upstream exists and the exact decision is `decRemote`, an accepted hop or a door request is served from that wildcard, and an ordinary request whose `backhaulTo` returns false for want of a signing key falls through to it (saturation and proxy failures are answered remotely, as today). What **blocks** the fallback is a **live exact holding winner** for the name (the exact decision is `decHolding`); a hold that lost to a surviving ready candidate blocks nothing.
+- **Ready-only routing is plan 1's fold.** The remote ready stage **calls** the shared fold (`foldHomes`'s loop over `dialBeats`, with plan 1 Task 8's pair rule: stamps first, pairs only when both entries are unstamped and share a non-empty target); the plan never restates that rule. With no holding candidate in play, `rank` returns exactly what the fold plus the local-first rule return today (Task 3's differential test); local ready candidates win over remote ones as today (the upstream table is consulted first). The dispatch exceptions of today's `ServeHTTP` are kept as an explicit step (Task 2's `fallback`): when the exact name has no local exact ready upstream (a losing local hold does not count) but a local wildcard upstream exists and the exact decision is `decRemote`, an accepted hop or a door request is served from that wildcard, and an ordinary request whose `backhaulTo` returns false for want of a signing key falls through to it (saturation and proxy failures are answered remotely, as today). What **blocks** the fallback is a **live exact holding winner** for the name (the exact decision is `decHolding`); a hold that lost to a surviving ready candidate blocks nothing.
- Local ready candidates are the entries of the upstream table `Reload` builds (`e.current()`): its eligibility (ready status, a usable backend, no sidecars, aliases whenever their primary has an upstream, shadowing) is unchanged. DNS pointing gates **publication** of aliases, not local service.
- Explicit aliases only in holding publications: the alias row is `Explicit` and `AliasPublishable` (below).
- The display name is the only request-supplied text on the page, rendered through `html/template`; no other request text (URL, headers, host) appears in the body.
@@ -66,7 +66,7 @@ Builds on plan 1 (rev 10: `(incarnation, serving_seq)` on rows and publications,
- `type candidate struct { kind candKind (candReady, candHolding, candCert); local bool; order int (the file's sorted index; local is -1); eip, box string; account, app string; alias, wildcard, platform bool; targetHost string; incarnation, servingSeq uint64; stamp int64; fetchedAt time.Time; hold *holdingView; up *upstream (local only); table map[string]upstream (local only: the table `up` came from) }`.
- **Remote constructors** (`buildCandidates`): the per-file admission is `foldHomes`'s today, unchanged: files iterated in sorted key order (`order` = index); `f.Box == ""` or `f.Box == self` skipped (own-box exclusion); `addr = dialAddress(f, own, ownKnown, privateDial)` (so same-region private dialling is retained); `hosts` entries: role `home` with `addr == ""` → a `candCert{wildcard: true, platform: h.Platform && !h.Alias && !h.Wildcard}` only when `h.Wildcard && strings.HasPrefix(host, "*.")`, else skipped; role `wildcard` → the same `candCert` only when `h.Wildcard && strings.HasPrefix(host, "*.")`, else skipped; unknown roles skipped (`candCert` is constructed explicitly in those two branches and nowhere else); role `home` with an address → a ready candidate `{candReady, eip: addr, box, account, app, alias: h.Alias, wildcard: h.Wildcard, platform: h.Platform && !h.Alias && !h.Wildcard, targetHost: h.TargetHost (plan 1; "" when absent) for an alias, the host itself for a route, incarnation/servingSeq (plan 1), stamp: h.Stamp, fetchedAt}`; `offline_moves` entries (only when `addr != ""`, the same requirement a dial target has): one `candHolding` for `Host` `{targetHost: Host, platform: entry.Platform, account/app: entry's, incarnation/servingSeq: entry's, alias: false, hold: &entry}` and one alias `candHolding` per listed alias `{alias: true, targetHost: Host, platform: false, the same owner and pair, hold: &entry}`; holds carry `stamp: 0` always.
- **Local constructors** (`Reload` for ready, `RefreshHolds` for holds): for every entry `(name, up)` of the table `Reload` just built: a `candReady{local: true, order: -1, alias: up.alias, targetHost: up.route.Host when up.alias else name, account/app: from up.route, incarnation/servingSeq: up.route's pair, platform: (up.route.Platform || up.route.Provisioned) && !up.alias && !wildcard (an alias is never a platform class, as `currentHosts` already rules), wildcard: strings.HasPrefix(name, "*."), stamp: 0 (local candidates' stamps are not consulted: local-first is the rule, as today), up: &up, table: the new table}`. Local holds: for every registry row the hold snapshot knows (`registry.IsHold(r.Status) && r.HoldOp == mv.ID`): one real `candHolding{local, targetHost: r.Host, platform: r.Platform || r.Provisioned, owner from the row, pair from the row, hold: a holdingView built from the row and the move}` and one alias `candHolding{alias: true, targetHost: r.Host, platform: false}` per `route_aliases` row with `a.Host == r.Host && a.Explicit && edgesfile.AliasPublishable(a, true, shadowed)` (the same predicate the writer uses, so the source box serves its own alias the page even though the home map excludes its own publication).
-- `type decision struct { kind decKind (decLocal, decRemote, decHolding, decNone); up *upstream; table map[string]upstream; eip, box, account, app string; stamp int64; platform, wildcard bool; hold *holdingView; fallback *localFallback }` with `type localFallback struct { up *upstream; table map[string]upstream }`: set by `Edge.resolve` when the exact name has no local candidate, the local table has the `*.<parent>` entry, and the exact decision is `decRemote`; captured from the **same** table snapshot the resolution read, so a reload between resolution and a failed backhaul cannot change the fallback's backend or owner.
+- `type decision struct { kind decKind (decLocal, decRemote, decHolding, decNone); up *upstream; table map[string]upstream; eip, box, account, app string; stamp int64; platform, wildcard bool; hold *holdingView; fallback *localFallback }` with `type localFallback struct { up *upstream; table map[string]upstream }`: set by `Edge.resolve` when the exact name has no local exact **ready** upstream in the table (a local exact hold may exist and have lost), the local table has the `*.<parent>` entry, and the exact decision is `decRemote`; captured from the **same** table snapshot the resolution read, so a reload between resolution and a failed backhaul cannot change the fallback's backend or owner.
- **`rank(name string, cands []candidate, now time.Time) decision`:**
1. remote `candHolding` with `now.Sub(fetchedAt) >= holdingValidity` are removed;
2. `platform`/`wildcard` are the OR over all candidates; `candCert` never decides; nothing else present → `decNone`;
@@ -74,13 +74,13 @@ Builds on plan 1 (rev 10: `(incarnation, serving_seq)` on rows and publications,
4. **ready:** if any `candReady` survives: a local one → `decLocal` with its `up` and `table` (local first, as today; the table has one entry per name); else the remote survivors go through **the shared fold** (`foldHomes`'s loop in `order`, deciding with `dialBeats` as plan 1 Task 8 defines it: the plan does not restate the rule; the fold is one function called from `foldHomes` and from here) → `decRemote` with the winner's `eip, box, account, app, stamp`;
5. **holding (a sorted fold):** no ready survives: iterate the `candHolding` survivors in `order` (local `-1` first); the first is the incumbent; a later candidate **replaces** the incumbent only when (it is real and the incumbent is an alias) or (both are the same kind, share a non-empty `targetHost`, and its pair is higher); otherwise the incumbent stays → `decHolding` with the winner's `hold`. (Witness: A-old alias `(1,1)` at 0, B alias at 1, A-new alias `(1,2)` at 2 → A-new.)
- **Invariants, scoped to the stages (Task 3 asserts them on the small model):** *suppression:* (d) a hold removes exactly the unstamped ready candidates sharing its non-empty target with a lower pair; (b) a stamped ready candidate is never suppressed; (f) an expired remote hold neither suppresses nor decides; (g) no pair is compared between candidates with different or empty targets, at any stage. *local precedence:* (l) a surviving local ready candidate wins over every remote candidate and every hold. *remote fold:* (a) with no live hold the remote answer equals `foldHomes`'s and the complete answer equals today's dispatch; (h) among the remote survivors a real ready beats an alias ready whatever the pairs and stamps (#287), as the fold's own rule; (c) a surviving ready of a different target than every hold beats every hold. *holding:* (e) a ready candidate of target T that survives suppression (it is stamped, or its pair is not lower than that of any live hold of T) beats every hold; (n) the holding winner is the sorted fold's and is independent of input order except through `order`. *classes and ownership:* (j) `platform`/`wildcard` are OR'd over the candidates (classes are facts about the name) while the owner, dial address, stamp and `up`/`table` come from the winner alone; an alias candidate never carries the platform class.
-- `func (m *homeMap) resolveExact(name string, now time.Time) decision` (the exact candidates; never a wildcard); **the unlabelled box keeps today's split**: `Home`, `ExactHome` and `Edge.resolve` refuse to **dial** (no `decRemote`, no `decHolding` from remote candidates) when `m.self == ""`, while the membership queries `KnownHost`, `Hosts`, `HoldingHosts` and `certNames` still inspect the admitted remote candidates, exactly as today's `Home == false && KnownHost == true` on an unlabelled edge; `func (m *homeMap) resolveRequest(name string, now time.Time) decision` (exact; if `decNone` and the exact name has no live `decHolding` → `rank` over `*.<parent>`'s candidates); `Home`/`ExactHome` answer only `decRemote` from `resolveRequest`/`resolveExact` as today's split; `Owner` from the same decision; `KnownHost(name, now)` = `resolveExact` is `decRemote` or `decHolding` and `name` is not a `*.` label; `Hosts()` adds a `decHolding` winner's host when `platform`; **the wake** (`refreshHosts`' `samePlatformSet`) compares the effective parent inputs, `hosts`' platform set **plus the platform real holds**, so a platform hold arriving while the ready fold is unchanged wakes the wildcard manager; `ServedHosts()` unchanged (ready winners only; **a hold is never served evidence**); `HoldingHosts(now)` new: the exact names (hosts and aliases) whose `resolveExact` is a live `decHolding`.
+- `func (m *homeMap) resolveExact(name string, now time.Time) decision` (the exact candidates; never a wildcard); **the unlabelled box keeps today's split**: `Home`, `ExactHome` and `Edge.resolve` refuse to **dial** (no `decRemote`, no `decHolding` from remote candidates) when `m.self == ""`, while the membership queries `KnownHost`, `HoldingHosts` and `certNames` still inspect the admitted remote candidates, exactly as today's `Home == false && KnownHost == true` on an unlabelled edge; `Hosts()` keeps today's guard and returns nil when `m.self == ""`, so an unlabelled box contributes no remote wildcard parent; `func (m *homeMap) resolveRequest(name string, now time.Time) decision` (exact; if `decNone` and the exact name has no live `decHolding` → `rank` over `*.<parent>`'s candidates); `Home`/`ExactHome` answer only `decRemote` from `resolveRequest`/`resolveExact` as today's split; `Owner` from the same decision; `KnownHost(name, now)` = `resolveExact` is `decRemote` or `decHolding` and `name` is not a `*.` label; `Hosts()` adds a `decHolding` winner's host when `platform`; **the wake** (`refreshHosts`' `samePlatformSet`) compares the effective parent inputs, `hosts`' platform set **plus the platform real holds**, so a platform hold arriving while the ready fold is unchanged wakes the wildcard manager; `ServedHosts()` unchanged (ready winners only; **a hold is never served evidence**); `HoldingHosts(now)` new: the exact names (hosts and aliases) whose `resolveExact` is a live `decHolding`.
- **The local edge:** `e.holdView atomic.Pointer[HoldSnapshot]` is set by `SetHoldView(s HoldSnapshot)` (the view's `onChange`), which then calls `RefreshHolds()`. `type holdSnapshot struct { cands map[string][]candidate }` in `e.holds atomic.Pointer[holdSnapshot]` is written **only** by `func (e *Edge) RefreshHolds()`: under `e.holdsMu` it reads the **latest** `e.holdView.Load()` and the registry's current rows and aliases, builds the local holding candidates (none when the view is nil or `Failed`), installs them, and after the lock sends the wildcard manager the same parent-set notification `Reload` sends after installing a new table. Because the inputs are read inside the same lock that installs, rebuilds install in the order they read, so no rebuild can install older inputs than one before it; there is no revision comparison. `RefreshHolds()` is called by `SetHoldView` (a view change) **and at the end of `Reload`** (a registry change: a row turning held, an alias detach, a provenance or DNS eligibility change), so a hold that the registry gains while the view is unchanged is installed on the next `Reload`. `Reload` writes `e.holds` only through that call. `func (e *Edge) resolve(host string, now time.Time) decision`: the exact candidates = `e.current()`'s entry for `host` (as a local ready candidate), `e.holds.Load().cands[host]`, and the home map's exact candidates; through `rank`; `decNone` and no live exact hold → the same over `*.<parent>` (the local wildcard entry and the remote wildcard candidates). **The handler uses `dec.up` and `dec.table`:** path-prefix selection runs over `dec.up.paths` and resolves the target hostname in `dec.table` (`selectUpstream(dec, r.URL.Path) *upstream`, preserving today's cleaned/raw segment matching, exact target lookup and one-hop selection); the login re-resolution looks its path up in the same `dec.table`; the door's `doorOwnsRoute` checks the **finally selected** upstream's route; a remote decision's owner is `dec.account/app`; `backhaulTo` is called with `dec.eip, dec.box`: one decision and one table for the whole request.
- **Request paths:** HTTPS `ServeHTTP`: after `acceptHop`: `decLocal` → the local path from `selectUpstream`; `decRemote` with `fallback != nil` → an accepted hop → the local path from `selectUpstream` over `fallback` (as today); a door → the local path over `fallback`, then `doorOwnsRoute` on the finally selected local route (as today); else `backhaulTo`, and when it returns false for want of a signing key → the local path over `fallback` (as today; saturation and proxy failures stay remote answers); `decRemote` without `fallback` → an accepted hop → `staleHopRefusal`; a door → `Owner` must match else `unknownHost`; else `backhaulTo`; `decHolding` → an accepted hop → the page (no forwarding); a door → the page only when `hold.Account/App` equal the door's and are non-empty, else `unknownHost`; else the page; `decNone` → an accepted hop → `staleHopRefusal`; else `unknownHost`. HTTP fallback: `decLocal`/`decRemote`/`decHolding` → the HTTPS redirect; `decNone` → today.
- **TLS (F6):** `Allowed(host)`: `*.` → false; the tunnel hostname (`e.tunnels != nil && host == e.tunnels.Host()`) → true, as today; else a local exact `candReady` or a local exact `candHolding` exists for `host`. `deploymentHost = Allowed || KnownHost`. `currentHosts()` = the platform/provisioned non-alias names among the local table **and** the local real holds (so wildcard parents persist through a hold). `func (e *Edge) certNames() []string` = the local hold names (hosts and aliases) plus `homes.HoldingHosts(now)`; `warmSet` considers `certNames()` after `ServedHosts()` under the same exclusions (apps domain, wildcard-covered, `*.`); the issuer election is unchanged. `ServedHosts` is not widened.
- The page: `func renderHoldingPage(displayName string, untilUnix int64, now time.Time) []byte` and `func (e *Edge) holdingAnswer(w, r, h *holdingView)` with `untilUnix = h.OfflineAt + int64(h.EstimateSeconds)` when both are non-zero, else 0; the sentences, N, the headers and the client's branches exactly as the Global Constraints state.
-- [ ] **Step 1: Write the failing tests**: `TestHoldingViewDecodesTheWriterFixture` (`internal/edgesfile/testdata/offline-moves.json`); `TestRankSuppressionAndFold` (the hold suppresses only its target's lower unstamped pairs; a retained unstamped `(1,2)` against a stamped `(0,0)` with no hold → the stamped one, as the fold; the three-hold sorted-fold witness → A-new; an old hold `(1,1)`, a ready `(1,2)` and a current hold `(2,1)` of one target → the ready is suppressed and the `(2,1)` hold answers; the F1 four-candidate set (A-ready `(1,0)`, A-hold `(1,1)`, B-ready `(1,0)`, B-hold `(1,1)`) → the lower-`order` hold; the F2 three-publication set (A-old `(1,0)` at 0, B-ready `(1,0)` at 1, A-new `(1,2)` at 2, no holds) → A-new, as `foldHomes`; `TestHomeMapAStampedAliasDoesNotBeatAnUnstampedRoute` still passing; a stamped alias against a real hold → the stamped alias (§6.4)); `TestResolveExactVersusRequest` (an expired exact hold → the wildcard; a live exact hold blocks it; a hold that lost to a surviving ready candidate blocks nothing; `KnownHost` false for an invented wildcard label; `Allowed` rejects `*.` and admits the tunnel host; **an unlabelled edge** with a remote `home` publication and no local route → `Home == false`, `KnownHost == true`, as today); `TestDecisionCarriesTheTable` (a prefix target and the login re-resolution come from `dec.table`; a reload between resolution and dispatch that changes the prefix target's owner and backend does not change what this request serves; the door check runs against the finally selected route); `TestLocalCandidatesAreTheUpstreamTable` (a non-pointing local alias serves; sidecars and backend-less rows absent); `TestLocalHoldsIncludeExplicitAliases` (the own publication excluded from the home map; the source's explicit pointing alias → the page; its non-pointing alias → serves as today; a derived alias → not held); `TestRemoteCandidatesKeepTheAdmissions` (own box excluded; `Box == ""` skipped; unknown role skipped; a file without an address yields cert-only wildcards and no holds; same-region private dialling); `TestLocalAndRemoteArbitrateTogether` (Review Focus 4); `TestEveryRequestPathHonoursTheDecision` (the table above including hops and doors with and without ownership and with an empty-owner hold; **the kept exceptions**: a local `*.example` upstream and a remote exact `x.example` publication: an accepted hop → served from the local wildcard, a door request → served from the local wildcard, an ordinary request with no mesh key whose backhaul fails → the local wildcard, exactly as today's `ServeHTTP`; the same three with a live hold for `x.example` → hop: the page; door: the page when owned; ordinary: the page; a reload between the remote resolution and the failed backhaul does not change the fallback's backend or owner); `TestLocalHoldsFollowTheViewAndTheRegistry` (a publication **before** the edge subscribes is delivered at subscription and the hold installs; a publication racing the subscription is delivered once, in order; a failed snapshot after an installed hold drops it; a view published while the row is still ready installs no hold, then the row turns held and `Reload` installs it with the view unchanged; an alias detach, a provenance change and a DNS eligibility change each rebuild on `Reload`; a slow rebuild that read view A overlapped by one that read view B installs in read order, so the installed holds are B's; success → failure → recovery without registry changes; two concurrent publishers never share a revision); `TestHoldingPageRendersEveryCase` (name, no name, no estimate, past `until`, N = ceil with minimum 1 at 61 s, 60 s, 59 s, 1 s, escaping of `<b>`, HEAD; the script's `until`, both cadences, the local sentence switch at `until`, the storage key and the try/catch asserted by text); `TestTLSCoverageForHoldingHosts` (real handshakes; a wildcard-only platform host held keeps its parent; a platform hold arriving on the home map after the wildcard manager started, with the ready fold unchanged, wakes it and the parent's certificate serves; an invented label gets no issuance and no challenge read; the tunnel host still admitted; a holding-only custom domain is in `certNames` and not in `ServedHosts`; an issuer warms it, then a non-issuer's handshake for it succeeds from the shared cache).
+- [ ] **Step 1: Write the failing tests**: `TestHoldingViewDecodesTheWriterFixture` (`internal/edgesfile/testdata/offline-moves.json`); `TestRankSuppressionAndFold` (the hold suppresses only its target's lower unstamped pairs; a retained unstamped `(1,2)` against a stamped `(0,0)` with no hold → the stamped one, as the fold; the three-hold sorted-fold witness → A-new; an old hold `(1,1)`, a ready `(1,2)` and a current hold `(2,1)` of one target → the ready is suppressed and the `(2,1)` hold answers; the F1 four-candidate set (A-ready `(1,0)`, A-hold `(1,1)`, B-ready `(1,0)`, B-hold `(1,1)`) → the lower-`order` hold; the F2 three-publication set (A-old `(1,0)` at 0, B-ready `(1,0)` at 1, A-new `(1,2)` at 2, no holds) → A-new, as `foldHomes`; `TestHomeMapAStampedAliasDoesNotBeatAnUnstampedRoute` still passing; a stamped alias against a real hold → the stamped alias (§6.4)); `TestResolveExactVersusRequest` (an expired exact hold → the wildcard; a live exact hold blocks it; a hold that lost to a surviving ready candidate blocks nothing; `KnownHost` false for an invented wildcard label; `Allowed` rejects `*.` and admits the tunnel host; **an unlabelled edge** with a remote `home` publication and no local route → `Home == false`, `KnownHost == true`, `Hosts()` empty, as today, for a platform publication under the apps domain too); `TestDecisionCarriesTheTable` (a prefix target and the login re-resolution come from `dec.table`; a reload between resolution and dispatch that changes the prefix target's owner and backend does not change what this request serves; the door check runs against the finally selected route); `TestLocalCandidatesAreTheUpstreamTable` (a non-pointing local alias serves; sidecars and backend-less rows absent); `TestLocalHoldsIncludeExplicitAliases` (the own publication excluded from the home map; the source's explicit pointing alias → the page; its non-pointing alias → serves as today; a derived alias → not held); `TestRemoteCandidatesKeepTheAdmissions` (own box excluded; `Box == ""` skipped; unknown role skipped; a file without an address yields cert-only wildcards and no holds; same-region private dialling); `TestLocalAndRemoteArbitrateTogether` (Review Focus 4); `TestEveryRequestPathHonoursTheDecision` (the table above including hops and doors with and without ownership and with an empty-owner hold; **the kept exceptions**: a local `*.example` upstream and a remote exact `x.example` publication: an accepted hop → served from the local wildcard, a door request → served from the local wildcard, an ordinary request with no mesh key whose backhaul fails → the local wildcard, exactly as today's `ServeHTTP`; the same three with a live hold for `x.example` → hop: the page; door: the page when owned; ordinary: the page; a reload between the remote resolution and the failed backhaul does not change the fallback's backend or owner; **the losing local hold**: local `*.example` to another app, a local exact hold for `x.example` at `(1,1)`, a remote exact ready for `x.example` at `(1,2)` → the exact decision is `decRemote` with `fallback` set: hop and door serve the wildcard, the ordinary request without a signing key falls back); `TestLocalHoldsFollowTheViewAndTheRegistry` (a publication **before** the edge subscribes is delivered at subscription and the hold installs; a publication racing the subscription is delivered once, in order; a failed snapshot after an installed hold drops it; a view published while the row is still ready installs no hold, then the row turns held and `Reload` installs it with the view unchanged; an alias detach, a provenance change and a DNS eligibility change each rebuild on `Reload`; a slow rebuild that read view A overlapped by one that read view B installs in read order, so the installed holds are B's; success → failure → recovery without registry changes; two concurrent publishers never share a revision); `TestHoldingPageRendersEveryCase` (name, no name, no estimate, past `until`, N = ceil with minimum 1 at 61 s, 60 s, 59 s, 1 s, escaping of `<b>`, HEAD; the script's `until`, both cadences, the local sentence switch at `until`, the storage key and the try/catch asserted by text); `TestTLSCoverageForHoldingHosts` (real handshakes; a wildcard-only platform host held keeps its parent; a platform hold arriving on the home map after the wildcard manager started, with the ready fold unchanged, wakes it and the parent's certificate serves; an invented label gets no issuance and no challenge read; the tunnel host still admitted; a holding-only custom domain is in `certNames` and not in `ServedHosts`; an issuer warms it, then a non-issuer's handshake for it succeeds from the shared cache).
- [ ] **Step 2: Run to verify they fail; Step 3: implement; Step 4: run** `go test ./internal/edge -run 'Rank|Holding|Resolve|Decision|LocalCandidates|LocalHolds|RemoteCandidates|LocalAndRemote|RequestPath|TLSCoverage|HomeMap' -count=1`.
- [ ] **Step 5: Commit** `edge: holds suppress their target's stale publications and the fold decides the rest; one decision and one table per request; local holds in their own snapshot`.