db-region-forward-copy: Luna-approved copy for forwarded db reads, docs
Squashed from db-region-forward-copy into main.
10 files changed,
+103
−58
approved_db_forward_copy_test.go+9 −6cmd/console/dbforward_test.go+2 −4dbforward.go+13 −15dbforward_e2e_test.go+2 −2docs/site/cli.md+7 −4docs/superpowers/notes/census-proposal-db-region-forward-copy.md+30 −0docs/superpowers/plans/2026-10-22-db-region-forward-copy.md+21 −21internal/console/apidbforward.go+4 −6internal/provision/plan14_root_reads_test.go+12 −0internal/provision/testdata/plan14-root-reads-db-region-forward-copy.tsv+3 −0
CI passed — run details
CI log
=== gate ===
.amadan/test-gate.sh
=== launchctx (0 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 (17 s)
=== gofmt (0 s)
gofmt -l .: clean
=== rest (167 s)
? github.com/carlosframework/platform/cmd/changelog [no test files]
ok github.com/carlosframework/platform/cmd/console 3.651s
ok github.com/carlosframework/platform/cmd/moveprobe 11.878s
ok github.com/carlosframework/platform/cmd/zddprobe 0.785s
ok github.com/carlosframework/platform/internal/activator 59.639s
ok github.com/carlosframework/platform/internal/agentsock 0.022s
ok github.com/carlosframework/platform/internal/alerting 0.007s
ok github.com/carlosframework/platform/internal/analytics 0.043s
ok github.com/carlosframework/platform/internal/appconfig 2.870s
ok github.com/carlosframework/platform/internal/apperr 0.186s
ok github.com/carlosframework/platform/internal/applog 0.319s
ok github.com/carlosframework/platform/internal/awsinv 0.005s
ok github.com/carlosframework/platform/internal/boxchoice 0.007s
ok github.com/carlosframework/platform/internal/boxid 0.729s
? 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.020s
ok github.com/carlosframework/platform/internal/caps 0.023s
ok github.com/carlosframework/platform/internal/certwarm 0.006s
ok github.com/carlosframework/platform/internal/cgroup 0.814s
ok github.com/carlosframework/platform/internal/changelog 0.523s
ok github.com/carlosframework/platform/internal/claimactivation 1.205s
ok github.com/carlosframework/platform/internal/clamd 0.062s
? github.com/carlosframework/platform/internal/cliflag [no test files]
? github.com/carlosframework/platform/internal/controlname [no test files]
? github.com/carlosframework/platform/internal/controlsock [no test files]
ok github.com/carlosframework/platform/internal/dbdoor 8.291s
ok github.com/carlosframework/platform/internal/dbdoor/dbdoortest 0.016s
ok github.com/carlosframework/platform/internal/dbquery 0.010s
ok github.com/carlosframework/platform/internal/dbreads 2.150s
? github.com/carlosframework/platform/internal/dbreads/dbreadstest [no test files]
ok github.com/carlosframework/platform/internal/dbverify 0.015s
ok github.com/carlosframework/platform/internal/dnsrec 0.011s
ok github.com/carlosframework/platform/internal/docsite 0.017s
ok github.com/carlosframework/platform/internal/domains 2.897s
ok github.com/carlosframework/platform/internal/doorkey 0.015s
ok github.com/carlosframework/platform/internal/economics 0.004s
ok github.com/carlosframework/platform/internal/edge 45.518s
? 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.133s
ok github.com/carlosframework/platform/internal/gate 1.657s
ok github.com/carlosframework/platform/internal/genselect 0.015s
ok github.com/carlosframework/platform/internal/geo 0.017s
ok github.com/carlosframework/platform/internal/geoip 0.029s
ok github.com/carlosframework/platform/internal/historyreadback 0.159s
ok github.com/carlosframework/platform/internal/host 139.042s
ok github.com/carlosframework/platform/internal/hostactors 6.264s
ok github.com/carlosframework/platform/internal/hostactors/awsmembership 0.006s
ok github.com/carlosframework/platform/internal/hostbox 2.972s
ok github.com/carlosframework/platform/internal/hostclaim 0.799s
ok github.com/carlosframework/platform/internal/hostenv 0.005s
ok github.com/carlosframework/platform/internal/hostevidence 0.009s
ok github.com/carlosframework/platform/internal/hostexec 5.284s
ok github.com/carlosframework/platform/internal/hostfence 0.067s
ok github.com/carlosframework/platform/internal/hostfiles 10.319s
ok github.com/carlosframework/platform/internal/hostfloor 0.026s
ok github.com/carlosframework/platform/internal/hostguard 1.104s
ok github.com/carlosframework/platform/internal/hostops 1.957s
? github.com/carlosframework/platform/internal/hostops/fencerelease [no test files]
ok github.com/carlosframework/platform/internal/hostops/internal/fencerelease 0.005s
ok github.com/carlosframework/platform/internal/hostquarantine 0.004s
ok github.com/carlosframework/platform/internal/hostrelocate 0.646s
ok github.com/carlosframework/platform/internal/hostresolve 0.177s
ok github.com/carlosframework/platform/internal/hostwrite 0.006s
ok github.com/carlosframework/platform/internal/infraview 0.008s
ok github.com/carlosframework/platform/internal/instancectl 5.234s
ok github.com/carlosframework/platform/internal/instanceexec 2.789s
ok github.com/carlosframework/platform/internal/instancefs 0.016s
ok github.com/carlosframework/platform/internal/instancekey 0.016s
ok github.com/carlosframework/platform/internal/instanceupdates 0.024s
ok github.com/carlosframework/platform/internal/layout 1.829s
ok github.com/carlosframework/platform/internal/lbhealth 0.011s
ok github.com/carlosframework/platform/internal/lease 10.321s
ok github.com/carlosframework/platform/internal/lease/leasetest 0.558s
ok github.com/carlosframework/platform/internal/ledger 0.024s
ok github.com/carlosframework/platform/internal/mail 0.236s
ok github.com/carlosframework/platform/internal/maintenance 0.090s
ok github.com/carlosframework/platform/internal/maintenanceexec 5.581s
ok github.com/carlosframework/platform/internal/maintenanceguard 0.081s
ok github.com/carlosframework/platform/internal/metrics 0.005s
ok github.com/carlosframework/platform/internal/moves 22.492s
ok github.com/carlosframework/platform/internal/moves/archive 0.958s
ok github.com/carlosframework/platform/internal/objstore 0.270s
ok github.com/carlosframework/platform/internal/ops 0.184s
ok github.com/carlosframework/platform/internal/park 0.272s
ok github.com/carlosframework/platform/internal/plans 0.009s
ok github.com/carlosframework/platform/internal/privatefile 0.004s
ok github.com/carlosframework/platform/internal/provision 23.383s
ok github.com/carlosframework/platform/internal/publicrelease 0.015s
? github.com/carlosframework/platform/internal/regionname [no test files]
ok github.com/carlosframework/platform/internal/registry 5.590s
ok github.com/carlosframework/platform/internal/relay 7.240s
ok github.com/carlosframework/platform/internal/release 25.754s
ok github.com/carlosframework/platform/internal/rollout 3.794s
ok github.com/carlosframework/platform/internal/rolloutwords 0.008s
ok github.com/carlosframework/platform/internal/rootaws 0.006s
ok github.com/carlosframework/platform/internal/rootparticipation 0.062s
ok github.com/carlosframework/platform/internal/rootstate 0.036s
ok github.com/carlosframework/platform/internal/runs 0.574s
ok github.com/carlosframework/platform/internal/s3compat 0.005s
ok github.com/carlosframework/platform/internal/safefile 0.005s
ok github.com/carlosframework/platform/internal/schedule 2.612s
ok github.com/carlosframework/platform/internal/seeds 0.012s
ok github.com/carlosframework/platform/internal/sim/engines 2.613s
ok github.com/carlosframework/platform/internal/sim/hostlife 10.342s
ok github.com/carlosframework/platform/internal/sim/litestreamfacts 3.679s
ok github.com/carlosframework/platform/internal/status 0.081s
ok github.com/carlosframework/platform/internal/steering 0.007s
ok github.com/carlosframework/platform/internal/stopevidence 0.283s
ok github.com/carlosframework/platform/internal/svcrole 0.002s
ok github.com/carlosframework/platform/internal/telemetry 0.004s
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.007s
ok github.com/carlosframework/platform/internal/usage 0.007s
ok github.com/carlosframework/platform/internal/version 0.002s
ok github.com/carlosframework/platform/internal/vet 1.693s
=== internal_console@0 (84 s)
ok github.com/carlosframework/platform/internal/console 83.010s
=== internal_console@1 (41 s)
ok github.com/carlosframework/platform/internal/console 39.605s
=== internal_console@2 (45 s)
ok github.com/carlosframework/platform/internal/console 43.156s
=== internal_console@3 (43 s)
ok github.com/carlosframework/platform/internal/console 41.363s
=== internal_console@4 (45 s)
ok github.com/carlosframework/platform/internal/console 43.635s
=== internal_console@5 (42 s)
ok github.com/carlosframework/platform/internal/console 40.437s
=== internal_console@6 (40 s)
ok github.com/carlosframework/platform/internal/console 38.180s
=== internal_console@7 (36 s)
ok github.com/carlosframework/platform/internal/console 34.308s
=== root@0 (111 s)
ok github.com/carlosframework/platform 109.686s
=== root@1 (89 s)
ok github.com/carlosframework/platform 87.256s
=== root@2 (80 s)
ok github.com/carlosframework/platform 78.739s
=== 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: 50462882 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/23 08:21:25 moves: T4: STORE: list: operation error S3: ListObjectsV2, https response error StatusCode: 403, RequestID: 18E11AE2364786E9, 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.00s)
PASS
ok github.com/carlosframework/platform/internal/host 0.020s
=== RUN TestS3StoreMinioContract
=== RUN TestS3StoreMinioContract/conditional_get_and_etag_listing
=== RUN TestS3StoreMinioContract/bump_through_every_mutation_path
--- PASS: TestS3StoreMinioContract (0.02s)
--- PASS: TestS3StoreMinioContract/conditional_get_and_etag_listing (0.01s)
--- PASS: TestS3StoreMinioContract/bump_through_every_mutation_path (0.01s)
PASS
ok github.com/carlosframework/platform/internal/release 0.028s
Bucket created successfully `local/dbf-deploy`.
Bucket created successfully `local/dbf-data-ie`.
Bucket created successfully `local/dbf-data-uk`.
local/dbf-deploy versioning is enabled
Created policy `dbf-console` successfully.
Created policy `dbf-ukbox` successfully.
Added user `dbfconsole` successfully.
Added user `dbfukbox` successfully.
Attached Policies: [dbf-console]
To User: dbfconsole
Attached Policies: [dbf-ukbox]
To User: dbfukbox
=== RUN TestDBForwardMinio
2026/10/23 08:21:27 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000000 txid.db=0000000000000001
2026/10/23 08:21:27 INFO ltx file uploaded system=store db=source.db replica=file level=0 minTXID=0000000000000001 maxTXID=0000000000000001 size=720
2026/10/23 08:21:27 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000001 txid.db=0000000000000001
2026/10/23 08:21:27 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000000 txid.db=0000000000000001
2026/10/23 08:21:27 INFO ltx file uploaded system=store db=source.db replica=file level=0 minTXID=0000000000000001 maxTXID=0000000000000001 size=720
2026/10/23 08:21:27 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000001 txid.db=0000000000000001
2026/10/23 08:21:27 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000001 txid.db=0000000000000002
2026/10/23 08:21:27 INFO ltx file uploaded system=store db=source.db replica=file level=0 minTXID=0000000000000002 maxTXID=0000000000000002 size=370
2026/10/23 08:21:27 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000002 txid.db=0000000000000002
2026/10/23 08:21:27 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000002 txid.db=0000000000000003
2026/10/23 08:21:27 INFO ltx file uploaded system=store db=source.db replica=file level=0 minTXID=0000000000000003 maxTXID=0000000000000003 size=454
2026/10/23 08:21:27 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000003 txid.db=0000000000000003
2026/10/23 08:21:27 console: CARLOS_SECRETS_PUBKEY is unset, so no region outside the home can be chosen automatically
2026/10/23 08:21:27 console: could not notify member@example.com of a CLI token issue: keymail: lookup member@example.com: keymail: GET /api/federation/lookup?addr=member%40example.com&from=console%40127.0.0.1%3A43155: could not determine target mailbox
agent.go:123: dbreads: dbr_t7rt6cz2skxxvcxyc6pi5k53ny: planned 3 files (1544 bytes) and restored to 3 in 9ms
agent.go:123: dbreads: dbr_t7rt6cz2skxxvcxyc6pi5k53ny: output 5 bytes in 1 confirmed chunks in 1ms
2026/10/23 08:21:28 console: db read dbr_t7rt6cz2skxxvcxyc6pi5k53ny: relayed 1 chunks (102 bytes) in 1.003s, ended done
agent.go:123: dbreads: dbr_jlmlowivecbbtselb3kdzrpdse: planned 1 files (720 bytes) and restored to 1 in 8ms
agent.go:123: dbreads: dbr_jlmlowivecbbtselb3kdzrpdse: output 5 bytes in 1 confirmed chunks in 1ms
2026/10/23 08:21:29 console: db read dbr_jlmlowivecbbtselb3kdzrpdse: relayed 1 chunks (102 bytes) in 1.003s, ended done
=== RUN TestDBForwardMinio/by_disconnect
=== NAME TestDBForwardMinio
agent.go:123: dbreads: dbr_u5mbafx5mpndenfimuyhkdwhyq: planned 3 files (1544 bytes) and restored to 3 in 9ms
2026/10/23 08:21:29 console: db read dbr_u5mbafx5mpndenfimuyhkdwhyq: relayed 0 chunks (0 bytes) in 14ms, ended client gone
agent.go:123: dbreads: dbr_u5mbafx5mpndenfimuyhkdwhyq: output 5 bytes in 1 confirmed chunks in 43ms
=== RUN TestDBForwardMinio/by_timeout
=== NAME TestDBForwardMinio
agent.go:123: dbreads: dbr_dc72w7g7f2e7vorpukgz7oeceu: planned 3 files (1544 bytes) and restored to 3 in 9ms
2026/10/23 08:21:49 console: db read dbr_dc72w7g7f2e7vorpukgz7oeceu: relayed 0 chunks (0 bytes) in 19.021s, ended no-result
agent.go:123: dbreads: dbr_dc72w7g7f2e7vorpukgz7oeceu: output 5 bytes in 1 confirmed chunks in 19s
--- PASS: TestDBForwardMinio (21.37s)
--- PASS: TestDBForwardMinio/by_disconnect (0.16s)
--- PASS: TestDBForwardMinio/by_timeout (19.13s)
PASS
ok github.com/carlosframework/platform/internal/console 21.384s
minio contract: PASS
diff --git a/approved_db_forward_copy_test.go b/approved_db_forward_copy_test.go| index a13eedb37..fc172bf0e 100644 |
| --- a/approved_db_forward_copy_test.go |
| +++ b/approved_db_forward_copy_test.go |
| @@ -37,7 +37,11 @@ var dbForwardCopyIDs = func() []string { |
| // dbForwardCopyBuilt is every id whose text the code or docs carry. The task |
| // that writes a row's text adds its id here in the same commit, once Paul has |
| // approved the row. |
| -var dbForwardCopyBuilt = []string{} |
| +var dbForwardCopyBuilt = []string{ |
| + "DBF-1", "DBF-2", "DBF-14", "DBF-9", "DBF-10", "DBF-21", "DBF-22", // the console |
| + "DBF-3", "DBF-4", "DBF-5", "DBF-6", "DBF-7", "DBF-8", "DBF-11", "DBF-12", "DBF-13", "DBF-15", "DBF-16", "DBF-32", // the CLI |
| + "DBF-30", "DBF-31", // docs/site/cli.md |
| +} |
| // dbForwardCopyWired is every id whose PENDING text the code already |
| // carries, behind the console's CARLOS_DB_FORWARD switch, which is off |
| @@ -48,11 +52,10 @@ var dbForwardCopyBuilt = []string{} |
| // from a console that forwards, so none reaches a person on a deployment |
| // that has not turned forwarding on. The copy review moves each id from here |
| // to dbForwardCopyBuilt, applying Paul's edits in the same commit. Docs rows |
| -// are public the moment the site syncs, so they are never wired. |
| -var dbForwardCopyWired = []string{ |
| - "DBF-1", "DBF-2", "DBF-14", "DBF-9", "DBF-10", "DBF-21", "DBF-22", // the console |
| - "DBF-3", "DBF-4", "DBF-5", "DBF-6", "DBF-7", "DBF-8", "DBF-11", "DBF-12", "DBF-13", "DBF-15", "DBF-16", "DBF-32", // the CLI |
| -} |
| +// are public the moment the site syncs, so they are never wired. Luna |
| +// approved every row on 2026-10-23, so the list is empty and every row is |
| +// built. |
| +var dbForwardCopyWired = []string{} |
| func mustParseDBForwardRecord(t *testing.T) []copyRow { |
| t.Helper() |
diff --git a/cmd/console/dbforward_test.go b/cmd/console/dbforward_test.go| index 15dfa6c10..f72ea1c25 100644 |
| --- a/cmd/console/dbforward_test.go |
| +++ b/cmd/console/dbforward_test.go |
| @@ -2,10 +2,8 @@ package main |
| import "testing" |
| -// Forwarding is off unless CARLOS_DB_FORWARD is exactly 1: the switch the |
| -// pending DBF copy waits behind (approved_db_forward_copy_test.go, |
| -// dbForwardCopyWired) and the condition for answering byte-identically to |
| -// main (db region forward spec §9.2). |
| +// Forwarding is off unless CARLOS_DB_FORWARD is exactly 1: the condition for |
| +// answering byte-identically to main (db region forward spec §9.2). |
| func TestDBForwardIsOffUnlessSet(t *testing.T) { |
| t.Setenv("CARLOS_DB_FORWARD", "") |
| if dbForward() { |
diff --git a/dbforward.go b/dbforward.go| index 6e2b479b3..491df7887 100644 |
| --- a/dbforward.go |
| +++ b/dbforward.go |
| @@ -29,22 +29,20 @@ import ( |
| ) |
| // The forwarded read's CLI sentences (copy record DBF-3 to DBF-8, DBF-11 to |
| -// DBF-13, DBF-15, DBF-16, DBF-32). PENDING copy review: each is reached only |
| -// after a console with CARLOS_DB_FORWARD=1 answered the forward marker |
| -// (approved_db_forward_copy_test.go, dbForwardCopyWired). |
| +// DBF-13, DBF-15, DBF-16, DBF-32), approved by Luna on 2026-10-23. |
| const ( |
| - dbfNotPicked = "no server in region %s picked up the read within 60 seconds. try again in a few minutes." // DBF-3 |
| - dbfTooLarge = "%s's database is %s once restored. carlos db can query at most %s in region %s." // DBF-4 |
| - dbfNoRoom = "the server in region %s does not have room to restore %s's database right now. try again later." // DBF-5 |
| - dbfOutputCap = "the result was cut off at 64 MB. narrow the query with WHERE or LIMIT and run it again." // DBF-6 |
| - dbfTimeout = "the query ran for 5 minutes and was stopped. narrow it and run it again." // DBF-7 |
| - dbfNoPull = "%s keeps its data in region %s. carlos db pull cannot fetch a copy from there yet. carlos db query can read it." // DBF-8 |
| - dbfReading = "reading a copy of %s's database in region %s." // DBF-11 |
| - dbfUnfinished = "the read of %s's database in region %s did not finish, so nothing was printed. try again." // DBF-12 |
| - dbfUnchecked = "the answer from region %s did not check out, so carlos db showed none of it. try again." // DBF-13 |
| - dbfChanged = "%s changed while the read was waiting. try again." // DBF-15 |
| - dbfMovingCLI = "%s is moving between regions. read its database once the move has finished." // DBF-16 |
| - dbfNotUTF8 = "this query cannot be sent to region %s, because it holds bytes that are not UTF-8 text or the character U+FFFD. fix the query and run it again." // DBF-32 |
| + dbfNotPicked = "no server in region %s started the read within 60 seconds. try again in a few minutes." // DBF-3 |
| + dbfTooLarge = "the database for %s is %s once restored. carlos db can query at most %s in region %s." // DBF-4 |
| + dbfNoRoom = "the server in region %s does not have room to restore %s's database right now. try again later." // DBF-5 |
| + dbfOutputCap = "the result was cut off at 64 MB. narrow the query with WHERE or LIMIT and run it again." // DBF-6 |
| + dbfTimeout = "the query ran for 5 minutes and was stopped. narrow it and run it again." // DBF-7 |
| + dbfNoPull = "%s keeps its data in region %s. carlos db pull cannot fetch a copy from there yet. carlos db query can read it." // DBF-8 |
| + dbfReading = "reading a copy of %s's database in region %s." // DBF-11 |
| + dbfUnfinished = "the read of %s's database in region %s did not finish, so nothing was printed. try again." // DBF-12 |
| + dbfUnchecked = "the answer from region %s was invalid, so carlos db printed nothing. try again." // DBF-13 |
| + dbfChanged = "%s changed while the read was waiting. try again." // DBF-15 |
| + dbfMovingCLI = "%s is moving between regions. read its database once the move has finished." // DBF-16 |
| + dbfNotUTF8 = "this query cannot be sent to region %s, because it contains invalid UTF-8 or the replacement character U+FFFD. fix the query and run it again." // DBF-32 |
| ) |
| // errDBForward is the db door's forward marker, handed back by dbRestore so |
diff --git a/dbforward_e2e_test.go b/dbforward_e2e_test.go| index b57b98f16..e94c1ac38 100644 |
| --- a/dbforward_e2e_test.go |
| +++ b/dbforward_e2e_test.go |
| @@ -661,12 +661,12 @@ func TestDBForwardPrintsNothingForABadAnswer(t *testing.T) { |
| b.picked(time.Now().Add(time.Minute)) |
| b.chunk(1, false, "n\n") |
| b.result(1, "n\n") |
| - }, "did not check out"}, |
| + }, "was invalid, so carlos db printed nothing"}, |
| "a summary hash mismatch": {func(b *e2eScript) { |
| b.picked(time.Now().Add(time.Minute)) |
| b.chunk(1, true, "n\n31\n") |
| b.result(1, "n\n30\n") |
| - }, "did not check out"}, |
| + }, "was invalid, so carlos db printed nothing"}, |
| // The console waits the owner's deadline plus its 1-minute grace. |
| "no result": {func(b *e2eScript) { |
| b.picked(time.Now().Add(2 * time.Second)) |
diff --git a/docs/site/cli.md b/docs/site/cli.md| index a964ca5ab..f001dd39e 100644 |
| --- a/docs/site/cli.md |
| +++ b/docs/site/cli.md |
| @@ -536,10 +536,9 @@ own error, `attempt to write a readonly database`. That is on purpose. |
| Changing a copy would change nothing on the instance, and a command that |
| seemed to succeed would say otherwise. |
| -If the app has more than one instance, name one with `--instance`. Only |
| -instances that sleep have a replica. An instance on your own fleet, in |
| -another region, or in a pool cannot be read this way, and the command says |
| -which. |
| +If the app has more than one instance, name one with `--instance`. Only sleeping instances have a database copy. An instance on your own fleet or in a pool cannot be read this way, and the command says which. |
| + |
| +When an instance keeps its data in a different region from the console's, `carlos db query` runs in that region. A server there restores the copy, runs your query and sends back only the rows. The rows are encrypted for your terminal on the way, so nothing in between can read them, and nothing is printed until all of them have arrived and been checked. In that region, the copy can be at most 2 GB once restored, the query runs for at most 5 minutes, and the rows can total at most 64 MB. `carlos db pull` cannot fetch a copy from another region yet. |
| ### carlos run |
| @@ -2205,6 +2204,10 @@ image before starting `apply`, `recover`, `edge` or `console`. Once armed, |
| the local floor remains enforced independently of `CARLOS_HOST_CLAIM`. |
| The member command remains `carlos ops host resolve`. |
| +#### carlos system db-worker |
| + |
| +`carlos system db-worker` runs on platform boxes only. systemd starts it for each forwarded database query. You never run it yourself. |
| + |
| #### carlos system claims |
| `carlos system claims` prepares the dev claim mechanics trial. Run `help` for the commands and required inputs. `run` executes one revision-checked phase from a protected plan on the trusted signing host; `inspect` returns the verified roster and its signed envelope. Box installers run as root. Add `--dry-run` to preview an operation. |
diff --git a/docs/superpowers/notes/census-proposal-db-region-forward-copy.md b/docs/superpowers/notes/census-proposal-db-region-forward-copy.md| new file mode 100644 |
| index 000000000..6508a8c57 |
| --- /dev/null |
| +++ b/docs/superpowers/notes/census-proposal-db-region-forward-copy.md |
| @@ -0,0 +1,30 @@ |
| +# Census: db region forward copy (Luna's approved copy, 2026-10-23) |
| + |
| +Status: PROPOSED, for the census owner's ruling on #280. |
| + |
| +Branch `db-region-forward-copy`, cut from main at 6e8564ad. It applies Luna's |
| +copy verdicts for the forwarded db read (fourteen approved as drafted, seven |
| +rewritten: DBF-3, DBF-4, DBF-9, DBF-13, DBF-30, DBF-31, DBF-32), moves every |
| +DBF row to `dbForwardCopyBuilt`, and writes DBF-30 and DBF-31 into |
| +`docs/site/cli.md`. |
| + |
| +The code change is string constants only: five sentence constants in |
| +`dbforward.go` (the CLI) and one in `internal/console/apidbforward.go`, plus |
| +their comments. No read is added, removed or changed, and no census unit's |
| +digest moves. |
| + |
| +Root-read census: one overlay, |
| +`internal/provision/testdata/plan14-root-reads-db-region-forward-copy.tsv`, |
| +loaded last after `plans-3a-creation-caps`, holding only two envelope re-pins: |
| + |
| +| envelope | why | |
| +|---|---| |
| +| `.` | `dbforward.go`'s DBF-3, DBF-4, DBF-13 and DBF-32 constants | |
| +| `internal/console` | `apidbforward.go`'s DBF-9 constant | |
| + |
| +The legacy seal does not move |
| +(`dc7dbb4f562fe31556e7ed1e09fcfb380f551b45a444e94e72662f0b202c605b`, checked |
| +before the overlay loads and after it). |
| + |
| +Record-write census (9B8): unchanged. Claim routes: unchanged. go.mod: |
| +unchanged. |
diff --git a/docs/superpowers/plans/2026-10-22-db-region-forward-copy.md b/docs/superpowers/plans/2026-10-22-db-region-forward-copy.md| index b248786fc..8c7a8e5d1 100644 |
| --- a/docs/superpowers/plans/2026-10-22-db-region-forward-copy.md |
| +++ b/docs/superpowers/plans/2026-10-22-db-region-forward-copy.md |
| @@ -36,34 +36,34 @@ RFC 3339 time. |
| | id | file | text | status | |
| |---|---|---|---| |
| -| DBF-1 | internal/console/apidbforward.go | <host> keeps its data in region <region>. no server in that region can read databases yet, so carlos db cannot read it for now. | pending | |
| -| DBF-2 | internal/console/apidbforward.go | <host> keeps its data in region <region>. no server in that region is answering right now. try again in a few minutes. | pending | |
| -| DBF-9 | internal/console/apidbforward.go | too many database reads are open. wait a minute and try again. | pending | |
| -| DBF-10 | internal/console/apidbforward.go | <host> is moving between regions. read its database once the move has finished. | pending | |
| -| DBF-14 | internal/console/apidbforward.go | <host> keeps its data in region <region>. this version of carlos cannot read it from there. run carlos update, then try again. | pending | |
| -| DBF-21 | internal/console/apidbforward.go | forwarded a database query to region <region>. the query was <n> bytes, sha256 <sha> (cli) | pending | |
| -| DBF-22 | internal/console/apidbforward.go | forwarded a database query to region <region>, as of <time>. the query was <n> bytes, sha256 <sha> (cli) | pending | |
| +| DBF-1 | internal/console/apidbforward.go | <host> keeps its data in region <region>. no server in that region can read databases yet, so carlos db cannot read it for now. | approved | |
| +| DBF-2 | internal/console/apidbforward.go | <host> keeps its data in region <region>. no server in that region is answering right now. try again in a few minutes. | approved | |
| +| DBF-9 | internal/console/apidbforward.go | too many database reads are already running. wait a minute and try again. | approved | |
| +| DBF-10 | internal/console/apidbforward.go | <host> is moving between regions. read its database once the move has finished. | approved | |
| +| DBF-14 | internal/console/apidbforward.go | <host> keeps its data in region <region>. this version of carlos cannot read it from there. run carlos update, then try again. | approved | |
| +| DBF-21 | internal/console/apidbforward.go | forwarded a database query to region <region>. the query was <n> bytes, sha256 <sha> (cli) | approved | |
| +| DBF-22 | internal/console/apidbforward.go | forwarded a database query to region <region>, as of <time>. the query was <n> bytes, sha256 <sha> (cli) | approved | |
| ## CLI (plan 2) |
| | id | file | text | status | |
| |---|---|---|---| |
| -| DBF-3 | dbforward.go | no server in region <region> picked up the read within 60 seconds. try again in a few minutes. | pending | |
| -| DBF-4 | dbforward.go | <host>'s database is <size> once restored. carlos db can query at most <cap> in region <region>. | pending | |
| -| DBF-5 | dbforward.go | the server in region <region> does not have room to restore <host>'s database right now. try again later. | pending | |
| -| DBF-6 | dbforward.go | the result was cut off at 64 MB. narrow the query with WHERE or LIMIT and run it again. | pending | |
| -| DBF-7 | dbforward.go | the query ran for 5 minutes and was stopped. narrow it and run it again. | pending | |
| -| DBF-8 | dbforward.go | <host> keeps its data in region <region>. carlos db pull cannot fetch a copy from there yet. carlos db query can read it. | pending | |
| -| DBF-11 | dbforward.go | reading a copy of <host>'s database in region <region>. | pending | |
| -| DBF-12 | dbforward.go | the read of <host>'s database in region <region> did not finish, so nothing was printed. try again. | pending | |
| -| DBF-13 | dbforward.go | the answer from region <region> did not check out, so carlos db showed none of it. try again. | pending | |
| -| DBF-15 | dbforward.go | <host> changed while the read was waiting. try again. | pending | |
| -| DBF-16 | dbforward.go | <host> is moving between regions. read its database once the move has finished. | pending | |
| -| DBF-32 | dbforward.go | this query cannot be sent to region <region>, because it holds bytes that are not UTF-8 text or the character U+FFFD. fix the query and run it again. | pending | |
| +| DBF-3 | dbforward.go | no server in region <region> started the read within 60 seconds. try again in a few minutes. | approved | |
| +| DBF-4 | dbforward.go | the database for <host> is <size> once restored. carlos db can query at most <cap> in region <region>. | approved | |
| +| DBF-5 | dbforward.go | the server in region <region> does not have room to restore <host>'s database right now. try again later. | approved | |
| +| DBF-6 | dbforward.go | the result was cut off at 64 MB. narrow the query with WHERE or LIMIT and run it again. | approved | |
| +| DBF-7 | dbforward.go | the query ran for 5 minutes and was stopped. narrow it and run it again. | approved | |
| +| DBF-8 | dbforward.go | <host> keeps its data in region <region>. carlos db pull cannot fetch a copy from there yet. carlos db query can read it. | approved | |
| +| DBF-11 | dbforward.go | reading a copy of <host>'s database in region <region>. | approved | |
| +| DBF-12 | dbforward.go | the read of <host>'s database in region <region> did not finish, so nothing was printed. try again. | approved | |
| +| DBF-13 | dbforward.go | the answer from region <region> was invalid, so carlos db printed nothing. try again. | approved | |
| +| DBF-15 | dbforward.go | <host> changed while the read was waiting. try again. | approved | |
| +| DBF-16 | dbforward.go | <host> is moving between regions. read its database once the move has finished. | approved | |
| +| DBF-32 | dbforward.go | this query cannot be sent to region <region>, because it contains invalid UTF-8 or the replacement character U+FFFD. fix the query and run it again. | approved | |
| ## Docs |
| | id | file | text | status | |
| |---|---|---|---| |
| -| DBF-30 | docs/site/cli.md | If the app has more than one instance, name one with `--instance`. Only instances that sleep have a replica. An instance on your own fleet or in a pool cannot be read this way, and the command says which.\n\nWhen an instance keeps its data in another region than the console's, `carlos db query` runs in that region. A server there restores the copy, runs your query and sends back only the rows. The rows are encrypted for your terminal on the way, so nothing in between can read them, and nothing is printed until all of them have arrived and checked out. There, the copy can be at most 2 GB once restored, the query runs for at most 5 minutes, and the rows can come to at most 64 MB. `carlos db pull` cannot fetch a copy from another region yet. | pending | |
| -| DBF-31 | docs/site/cli.md | carlos system db-worker runs on platform boxes only. systemd starts it for each forwarded database query. you never run it yourself. | pending | |
| +| DBF-30 | docs/site/cli.md | If the app has more than one instance, name one with `--instance`. Only sleeping instances have a database copy. An instance on your own fleet or in a pool cannot be read this way, and the command says which.\n\nWhen an instance keeps its data in a different region from the console's, `carlos db query` runs in that region. A server there restores the copy, runs your query and sends back only the rows. The rows are encrypted for your terminal on the way, so nothing in between can read them, and nothing is printed until all of them have arrived and been checked. In that region, the copy can be at most 2 GB once restored, the query runs for at most 5 minutes, and the rows can total at most 64 MB. `carlos db pull` cannot fetch a copy from another region yet. | approved | |
| +| DBF-31 | docs/site/cli.md | `carlos system db-worker` runs on platform boxes only. systemd starts it for each forwarded database query. You never run it yourself. | approved | |
diff --git a/internal/console/apidbforward.go b/internal/console/apidbforward.go| index 2f06f0246..6a2181415 100644 |
| --- a/internal/console/apidbforward.go |
| +++ b/internal/console/apidbforward.go |
| @@ -106,9 +106,8 @@ func dbForwardEvidence(snap edgesSnapshot, err error, region string) string { |
| return "" |
| } |
| -// The console's forwarded-read sentences (copy record DBF-1, DBF-2, DBF-14). |
| -// PENDING copy review: wired behind CARLOS_DB_FORWARD, which is off unless a |
| -// deployment sets it (approved_db_forward_copy_test.go, dbForwardCopyWired). |
| +// The console's forwarded-read sentences (copy record DBF-1, DBF-2, DBF-14), |
| +// approved by Luna on 2026-10-23. |
| const ( |
| dbfNoCapable = "%s keeps its data in region %s. no server in that region can read databases yet, so carlos db cannot read it for now." |
| dbfNoneLive = "%s keeps its data in region %s. no server in that region is answering right now. try again in a few minutes." |
| @@ -150,10 +149,9 @@ func (s *Server) dbResidency(w http.ResponseWriter, r *http.Request, rec provisi |
| } |
| // The forwarded read's other console sentences (copy record DBF-9, DBF-10, |
| -// DBF-21, DBF-22). PENDING copy review, wired behind CARLOS_DB_FORWARD as |
| -// the three above are. |
| +// DBF-21, DBF-22), approved by Luna on 2026-10-23. |
| const ( |
| - dbfTooMany = "too many database reads are open. wait a minute and try again." |
| + dbfTooMany = "too many database reads are already running. wait a minute and try again." |
| dbfMoving = "%s is moving between regions. read its database once the move has finished." |
| dbfAudit = "forwarded a database query to region %s. the query was %d bytes, sha256 %s (cli)" |
| dbfAuditAt = "forwarded a database query to region %s, as of %s. the query was %d bytes, sha256 %s (cli)" |
diff --git a/internal/provision/plan14_root_reads_test.go b/internal/provision/plan14_root_reads_test.go| index ba87f3e80..26b190b37 100644 |
| --- a/internal/provision/plan14_root_reads_test.go |
| +++ b/internal/provision/plan14_root_reads_test.go |
| @@ -1395,6 +1395,18 @@ func TestPlan14RootReadCensus(t *testing.T) { |
| t.Fatal(err) |
| } |
| seal = "dc7dbb4f562fe31556e7ed1e09fcfb380f551b45a444e94e72662f0b202c605b" |
| + // Census overlay db-region-forward-copy (Luna's approved copy for the |
| + // forwarded db read, 2026-10-23), loaded last, after |
| + // plans-3a-creation-caps. Envelope re-pins only (. and internal/console: |
| + // changed sentence constants); no read is added, removed or changed, so |
| + // the seal does not move. PROPOSED-db-region-forward-copy |
| + // (docs/superpowers/notes/census-proposal-db-region-forward-copy.md). |
| + if errs := checkRootReadLegacy(inv, seal); len(errs) != 0 { |
| + t.Fatal(errs) |
| + } |
| + if err = loadRootReadInventory(filepath.Join(root, "internal/provision/testdata/plan14-root-reads-db-region-forward-copy.tsv"), &inv, true); err != nil { |
| + t.Fatal(err) |
| + } |
| 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-db-region-forward-copy.tsv b/internal/provision/testdata/plan14-root-reads-db-region-forward-copy.tsv| new file mode 100644 |
| index 000000000..5150558db |
| --- /dev/null |
| +++ b/internal/provision/testdata/plan14-root-reads-db-region-forward-copy.tsv |
| @@ -0,0 +1,3 @@ |
| +# Census overlay db-region-forward-copy (the Luna-approved copy for forwarded db reads, 2026-10-23: seven DBF sentences rewritten in dbforward.go and internal/console/apidbforward.go, and the CLI page), loaded LAST in TestPlan14RootReadCensus, after plans-3a-creation-caps, the overlay main loads last at 6e8564ad. Envelope re-pins only: string constants changed, no read was added, removed or changed, and no unit row changes, so the legacy seal does not move. rev3=PROPOSED-db-region-forward-copy, asked of the census owner (docs/superpowers/notes/census-proposal-db-region-forward-copy.md). |
| +@coverage . 75498b97f7b25e2271172bb4cefc673c457c5a7f35ef1b5ad42bbd16a619ceef |
| +@coverage internal/console f018180ef9eb83a66b739d6eea2cb26a1c14a6631997a62a0810f71ed4575aa3 |