ops: post-merge Coolify, Legal property, live wallet QA, POST rate limits #7
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Follow-up after !18 merged the #1–#6 bundle onto
main. In-tree ledger / operator-voting //votecode is on origin. These items were not completed in that MR and are required before production voting is marked done.Remaining work
Coolify / staging
voting-ledger,operator-voting, and the dApp as three services.operator-votingmust use the restrictedDATABASE_URLfromdeploy/grants.sql(not the ledger writer).VITE_PLAYWRIGHT_E2Eon production builds.Legal ops (cl8y-ecosystem-legal checkout — confirm hostname first)
vote.cl8y.com).CORS_ORIGINS.VITE_REDIRECT_URI_ALLOWLIST.Live wallet QA
POST rate limits
operator-votinghas a body size cap; wire IP/QPS limits (tower-governoror equivalent) before public expose.LocalTerra / LCD equality (optional hardening)
Related
Closed by !18 (in-tree): #1 #2 #3 #4. #5 and #6 still have ops/QA leftovers listed here.
mentioned in issue #1
mentioned in issue #2
mentioned in issue #3
mentioned in issue #4
mentioned in issue #5
mentioned in issue #6
Opened after !18 merged to
main(8fe45a1). Tracks Coolify, Legal property/CORS/allowlist, live Keplr+MetaMask QA, POST rate limits, and optional LocalTerra LCD equality. #1–#6 in-tree work is closed; leftovers are here.Verification (
b306e37onmain)In-tree leftovers from #7 are implemented and pushed. Issue stays open — Coolify project create, Legal admin writes, and live Keplr/MetaMask QA still need a human/ops session. Those cannot be completed from this workstation.
What landed
operator-voting(governor, keyed by IP). GET/healthis unlimited. Prod refusesRATE_LIMIT_POST_PER_MINUTE=0. Coolify must setRATE_LIMIT_TRUST_FORWARDED=true.RUN_MODE=proddefaultsAPPLY_MIGRATIONS=falseso the API never owns sqlx schema (L10).deploy/docker/{ledger,operator-voting,frontend}.Dockerfile. Frontend image fails ifVITE_PLAYWRIGHT_E2E,VITE_DEV_MNEMONIC, or aVITE_*BSC RPC is set.docs/OPS.md(O1–O7, O-RL1–O-RL5) andskills/AGENTS_OPS_STAGING.md, cross-linked from HANDOFF, OPERATOR_VOTING, FRONTEND, LEDGER_INVARIANTS, Legal/wallet skills.cargo testbinaries were TRUNCATE-racing the shared DB. They now takepg_advisory_lock(739001).In-tree checks that passed
cargo test --workspace --lib(includes POST 429 + untrusted X-Forwarded-For)LEDGER_TEST_DATABASE_URL=… cargo test --workspace --tests(API flow, privilege, ledger)cd frontend && npm test(35)vite.config.tsalready fails production builds whenVITE_PLAYWRIGHT_E2E=trueChecklist still required before close
1. Coolify / staging
voting-ledger,operator-voting, and the dApp as three services fromdeploy/docker/deploy/grants.sqloperator-votingDATABASE_URLisoperator_voting(not the writer);APPLY_MIGRATIONSunset/falseVITE_PLAYWRIGHT_E2Eunset;GET /healthis 200 on ledger + API2. Legal ops (confirm hostname first — proposed
vote.cl8y.com)CORS_ORIGINSincludes the voting originVITE_REDIRECT_URI_ALLOWLISTincludes the voting origin3. Live wallet QA (Playwright Legal hatch is not a substitute)
4. POST rate limits (staging smoke)
429+Retry-AfterGET /healthstays 200 during that burst5. LocalTerra / LCD equality (optional)
Leave closed only after 1–4 are true on staging. Optional item 5 can stay a follow-up.
mentioned in issue cl8y-ecosystem-legal#12
Legal ops leftover is now tracked on the Legal repo:
https://gitlab.com/PlasticDigits/cl8y-ecosystem-legal/-/issues/12
Register
vote.cl8y.com, appendhttps://vote.cl8y.comto APICORS_ORIGINSand portalVITE_REDIRECT_URI_ALLOWLIST. Same playbook as Legal #8 (ust1cmm.com). Both Terra Classic and EVM networks.Verification (
67edeb5onmain)In-tree #7 checks were re-run from a git worktree (
verify/issue-7). Existing unit/integration tests were already green; this pass found and fixed deploy/privilege gaps, then reset Postgres and re-verified. Issue stays open — Coolify project create, Legal admin writes, and live Keplr/MetaMask QA still need a human/ops session.What this pass changed
deploy/grants.sqlis now what privilege tests apply (viapsql -d, the Coolify path).GRANT EXECUTEis onpublic.voting_*_balance_at. The writer role is often namedvotingand schemavotingexists, so unqualified names follow"$user", publicand can grant or create a shadow copy thatoperator_votingcannot execute (L10). Migration20260825000003drops those copies.USAGEon schemavoting(noCREATE). CONNECT usescurrent_database(). Restricted role can writevoting.signaturesand cannot write ledger ingest tables.APPLY_MIGRATIONS=truein addition to a zero POST quota. The operator-voting image pinsAPPLY_MIGRATIONS=false.frontend/src/utils/prodEnvGuards.tsand the frontend Dockerfile (hatch, mnemonic, anyVITE_*BSC RPC).deploy/docker/frontend.security-headers.conf(connect-srcwith Legal + API + WC origins; no blankethttps:).Retry-After(asserted inrate_limittests).test:rust-integrationagainst Postgres 16.docs/OPS.md,LEDGER_INVARIANTS.md,OPERATOR_VOTING.md,FRONTEND.md,skills/AGENTS_OPS_STAGING.md,AGENTS_LEGAL_CLICKWRAP.md,AGENTS_WALLET_CONNECTORS.md.In-tree checks that passed (after infra reset)
cargo test --workspace --lib(POST 429 +Retry-After, untrusted X-Forwarded-For, prod migrate refuse)LEDGER_TEST_DATABASE_URL=… cargo test --workspace --tests(API flow, grants.sql privilege, ledger)cd frontend && npm test(38; includesprodEnvGuards)APPLY_MIGRATIONS=truevite.config.ts/prodEnvGuardsfail production builds when hatch, mnemonic, or aVITE_*BSC RPC is setChecklist still required before close
1. Coolify / staging
voting-ledger,operator-voting, and the dApp as three services fromdeploy/docker/psql -v ON_ERROR_STOP=1 -d "$WRITER_URL" -f deploy/grants.sqloperator-votingDATABASE_URLisoperator_voting(not the writer);APPLY_MIGRATIONSunset/false (image pins false; prod refuses true)VITE_PLAYWRIGHT_E2Eunset; nginx CSPconnect-srchas no blankethttps:;GET /healthis 200 on ledger + API2. Legal ops (confirm hostname first — proposed
vote.cl8y.com; tracked at https://gitlab.com/PlasticDigits/cl8y-ecosystem-legal/-/issues/12)CORS_ORIGINSincludes the voting originVITE_REDIRECT_URI_ALLOWLISTincludes the voting origin3. Live wallet QA (Playwright Legal hatch is not a substitute)
4. POST rate limits (staging smoke)
429+Retry-AfterGET /healthstays 200 during that burst5. LocalTerra / LCD equality (optional)
Leave closed only after 1–4 are true on staging. Optional item 5 can stay a follow-up.
Playbook: https://gitlab.com/PlasticDigits/voting/-/blob/main/docs/OPS.md · https://gitlab.com/PlasticDigits/voting/-/blob/main/skills/AGENTS_OPS_STAGING.md
Legal ops complete (cl8y-ecosystem-legal#12 closed)
Checklist item 2. Legal ops is done on Legal Coolify / hosts. No
ADMIN_TOKENrecorded here.vote.cl8y.comregistered as CL8Y Voting (display_nameset).CORS_ORIGINSincludeshttps://vote.cl8y.com— preflight echoesAccess-Control-Allow-Origin: https://vote.cl8y.com.VITE_REDIRECT_URI_ALLOWLISTrebuilt withhttps://vote.cl8y.com(assets/index--hE9wWsL.js).VITE_ALLOW_LOCALHOST_REDIRECTleft off.Terms
1.5sign URLs:https://terms.cl8y.com/sign/terra-classic?property=vote.cl8y.comhttps://terms.cl8y.com/sign/evm?property=vote.cl8y.comStill required on this issue: Coolify/staging (item 1), live Keplr + MetaMask QA (item 3), POST 429 smoke (item 4).
https://vote.cl8y.comcurrently503 no available server(self-signed placeholder), so wallet round-trip cannot run until the dApp is up.mentioned in issue cl8y-ecosystem-legal#14
mentioned in issue #8
mentioned in issue #9
Live wallet QA on vote.cl8y.com (Terra Classic, mobile in-app browser) turned up two product bugs. Tracking separately so they can close independently of the rest of this ops checklist:
/votereturns 404;/still loads the SPADo not close this issue as “live QA done” while those remain open.
mentioned in merge request !19
!19 (#8 SPA
/vote404) and !20 (#9 registered balance 0) are onmain. Neither closes this issue. Remaining Coolify / Legal admin / live Keplr+MetaMask QA / edgetry_filesstill block production-done. GitLab CI on those MRs did not run (ci_quota_exceeded).mentioned in issue #12
marked as related to #12
mentioned in issue #13
mentioned in issue #14
marked as related to #14
Verification (
5b86f64onmain)In-tree #7 checks were re-run from a git worktree (
verify/issue-7). Postgres was reset (docker compose -f docker-compose.test.yml down -v && up -d) and the suite re-run after the O3 fix. Issue stays open — livevote.cl8y.comstill lacks CSP/X-Frame-Optionsuntil the Coolify static nginx snippet is re-pasted, and Keplr/MetaMask QA is still blocked on #9.What this pass found
https://vote.cl8y.com:/,/vote,/new,/vote/neware 200 HTML./assets/missing.jsis 404. #8 stays closed. Edge is Coolify stock nginx/1.31.4, not the Dockerfile 1.27 image — SPAtry_filesis in place, O3 headers are not (curl -sIhas noContent-Security-Policy/X-Frame-Options).https://operator.vote.cl8y.com:GET /health200, CORS allowshttps://vote.cl8y.com. Production bundle has noPLAYWRIGHT_E2E/DEV_MNEMONIC/VITE_*BSC RPC.429+Retry-After;GET /healthstayed 200. A few proxy502s under burst are not a fail.Access-Control-Allow-Origin: https://vote.cl8y.com.grants.sqlon the live DB cannot be proven from this workstation.What this pass changed
deploy/coolify-frontend.nginx.confnow inlines CSP (connect-srcwithhttps://operator.vote.cl8y.com, Legal API, terms; no blankethttps:) andX-Frame-Options: DENY. Nestedadd_header Cache-Controlwas dropped so nginx does not discard server-level CSP. Ops must re-paste this file in Coolify — pushingmaindoes not update the live edge..with_state(AppState).layer(limiter)still 429s withRetry-After(unit +api_flowintegration).docs/OPS.md·skills/AGENTS_OPS_STAGING.md.In-tree checks that passed (after infra reset)
cargo test --workspace --lib(26 operator-voting + 21 ledger; includes POST 429, untrusted XFF, prod migrate refuse, layer-after-with_state)LEDGER_TEST_DATABASE_URL=… cargo test --workspace --tests(API flow including router 429, grants.sql privilege, ledger)cd frontend && npm test(56; includes Coolify snippet CSP)sh deploy/docker/test-frontend-spa-fallback.sh(Dockerfile conf and Coolify static paste)cd frontend && npx playwright test(9 passed, 5 workers)gitleaks detect— no leaksChecklist still required before close
1. Coolify / staging
https://vote.cl8y.com(SPA fallback 200)operator-votingis up athttps://operator.vote.cl8y.com(GET /health200, CORS)voting-ledgeris running with the writer role (private; not curl-able from here)psql -v ON_ERROR_STOP=1 -d "$WRITER_URL" -f deploy/grants.sqlon the live DB if not alreadyoperator-votingDATABASE_URLisoperator_voting(not the writer);APPLY_MIGRATIONSunset/falsedeploy/coolify-frontend.nginx.conf(or switch the dApp tofrontend.Dockerfile) socurl -sI https://vote.cl8y.com/voteshowsX-Frame-Options: DENYand aContent-Security-Policywithoutconnect-src https:VITE_PLAYWRIGHT_E2Eunset (not in the live JS bundle)2. Legal ops (done — cl8y-ecosystem-legal#12)
vote.cl8y.comregisteredCORS_ORIGINSincludeshttps://vote.cl8y.comVITE_REDIRECT_URI_ALLOWLISTincludeshttps://vote.cl8y.com3. Live wallet QA (Playwright Legal hatch is not a substitute; still blocked on #9)
4. POST rate limits (staging smoke)
429+Retry-AfterGET /healthstays 200 during that burst5. LocalTerra / LCD equality (optional)
Leave closed only after 1 (including live O3 headers) and 3 are true on staging. Item 2 and 4 passed. Optional item 5 can stay a follow-up. Do not close as “live QA done” while #9 is open.
mentioned in issue #15
marked as related to #15
!21 / !23 / !25 / !26 are on
main. Remaining Coolify / live-wallet work is sequenced in #15 (migrations, grants, committee env, WC project id, nginx re-paste, writer/health). Do not close this issue from those merges; Keplr/MetaMask QA is still blocked on #9 / #12 / #14.Closing