feat(voting): add bounded closing, advisory results and explicit governance policy disclosures #45
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?
Scope and source
Priority: P1. Gap coverage: GAP-027, GAP-028, GAP-045. Derived from GAP_1791945837.md, reviewed code commit
f8dbe93df953a78b17cb3304b717dcf84c4cd517. Currente476a68da09645c2308cbf47b90211fcaffcb7afadds only the report, so implementation findings remain applicable. Report evidence is local reproduction/source inspection unless explicitly proposed; no production exploit or current live-readiness claim.Coverage and sequencing: gap backlog tracker. Workstream 10. Dependencies: 05, 08, 09.
Current codebase
Schema permits draft/open only and votes never expire. Tallies exist in API/DB but dApp list/detail do not show them. Running tallies and any address-specific ballot are public unauthenticated reads. No quorum/pass denominator, roll-renewal lifecycle or delegation/edit policy exists; current ballots are immutable one vote per address.
Why this implementation is needed
Users need a defined participation window and durable results without mistaking advisory token-weighted polling for executable governance or secret ballots.
Relevant files
ledger/migrations/20260830000002_draft_lifecycle.sqloperator-voting/src/api.rsoperator-voting/src/db.rsoperator-voting/src/payload.rsfrontend/src/pages/VoteListPage.tsxfrontend/src/pages/VoteDetailPage.tsxfrontend/src/services/operatorVoting.tsdocs/GOVERNANCE_RESEARCH.mddocs/OPERATOR_VOTING.mddocs/FRONTEND.mdRecommended solution
Record finite duration/close authority and withdrawal/rejection semantics before implementing schema/API/UI changes; bind duration/end intent to signed revision/approval and derive actual close consistently from actual opening. Enforce the deadline in the voting transaction even if a worker is late; materialize idempotent closed state/archive. Show raw weighted For/Against/Abstain, voter counts, dates, per-chain context and frozen eligible denominator only if turnout is displayed. Keep public ballot visibility and immutable voting as documented defaults. Record GAP-045 decisions: no invented quorum/pass label, roll TTL/pruning, delegation, vote editing or veto/execution powers. Any future policy change requires separately versioned rules frozen with the proposal. Add opener/reviewer/reason/history/outcome attribution using audit receipts; do not require optional policy features to release raw results.
Constraints and guardrails
Preserve standalone offchain advisory voting, no new smart contracts or archive-node dependency, BSC as a core electorate, raw 18-decimal integer balances and separate Terra/BSC address identities. Keep Legal fail-closed transactional UI and the proven DEX Terra/Bridge EVM connectors; no browser BSC balance RPC, seed/key prompt or embedded admin/model credential. API must retain a restricted role separate from the ledger writer. Freeze at actual opening, never at draft creation or a client-supplied height. Agents own design, implementation, review and evidence under repository guidance; do not shift approvals/tests to the human or invent PASS evidence.
Acceptance criteria
Votes at/after deadline are rejected atomically and valid earlier votes retain immutable weight. Closed results survive reload/restart and reconcile with DB tallies; running/closed views clearly remain advisory. Zero votes, abstention and chain-specific weights render accurately without floating-point loss or false passed/secret claims. Withdrawal/rejection rights/reasons and defaults are documented.
Test plan: supported paths, failure paths and concurrency
Before/at/after close; vote/close race, delayed worker, duplicate close, restart and timezone display. Empty/single/mixed-chain tallies, abstain, large raw integers, late registration and unchanged frozen power after sale. Authorized/unauthorized withdrawal/rejection in each allowed state. Anonymous/public ballot reads and per-address queries follow the stated visibility rule. Migration of indefinite legacy polls requires explicit disclosed policy, not silent retroactive closure.
Test plan: attack, hack and abuse vectors
Forged/client-backdated times, expired vote replay, close authority escalation, tally/turnout manipulation, nonexistent denominator, private-ballot claims and withdrawal intended to erase cast ballots. Attempt cross-chain identity summing and snapshot rewrite; verify immutable evidence and no automatic fund execution.
Verification and completion criteria
Attach signed lifecycle policy and close-boundary concurrency tests, tally reconciliation fixtures and browser results for both chains. Update governance/API/user docs and verify legacy migration plus real deployed behavior separately; future quorum/privacy/delegation opportunities stay explicitly deferred unless separately specified.
Record commit and pinned toolchain, commands/results and sanitized artifacts. Relevant Rust changes require
cargo test --workspace --libplus isolated Postgres integration (explicit guarded LEDGER_TEST_DATABASE_URL); frontend changes requirenpm testand production build plus relevant browser cases. Run secret scanning for new fixtures/config. Exercise fresh/upgrade migrations when schema/grants change; report skipped/live-only checks explicitly.