Skip to content

Implement Proposal Timelock: Queued State, Veto, and Execution Countdown (#586)#897

Merged
Anuoluwapo25 merged 859 commits into
bakeronchain:mainfrom
DSOTec:feat/proposal-timelock
May 29, 2026
Merged

Implement Proposal Timelock: Queued State, Veto, and Execution Countdown (#586)#897
Anuoluwapo25 merged 859 commits into
bakeronchain:mainfrom
DSOTec:feat/proposal-timelock

Conversation

@DSOTec
Copy link
Copy Markdown
Contributor

@DSOTec DSOTec commented May 27, 2026

Summary

This PR adds a configurable timelock delay to the governance proposal lifecycle. After a proposal passes voting, it enters a Queued state for a configurable period (default 48 hours) before it can be executed. It also introduces a veto mechanism and updates the frontend to display the queued status with a countdown timer.

Type of Change

  • New feature
  • Smart contract change

Solution Implemented

  • Contract (scholarship_treasury):

    • Added Queued and Executed variants to ProposalStatus
    • Added DEFAULT_TIMELOCK_LEDGERS constant (48 hours)
    • Extended Proposal struct with queued_at, executed, and veto_votes
    • Added ProposalQueued and ProposalExecuted events
    • finalize_proposal now transitions passed proposals to Queued and records the timelock
    • execute_proposal requires Queued state and timelock expiry
    • Added veto_proposal / object_to_proposal for admin or 2/3 supermajority veto
    • Extended cancel_proposal to allow cancellation during the queued period
    • Added timelock getter/setter functions
  • Backend:

    • Added migration 006_add_timelock.sql with queued_at and execution_ready_at columns
    • Updated governance.controller.ts deriveProposalState to map queued"queued", approved"executed"
    • Updated cancelProposal endpoint to allow cancelling queued proposals
    • Updated OpenAPI schema and JSDoc enums to include "queued"
  • Frontend:

    • Added "Queued" and "Executed" to Proposal.status and Vote.status
    • Updated useProposals to map queued"In Timelock" and surface queuedAt / executionReadyAt
    • Updated useGovernance to fetch queued proposals from the contract and map their status
    • Updated DaoProposals page with a Queued filter, status badge, and execution countdown timer
    • Updated ProposalCard and ActiveVotes components with queued status colors (warning / brand-amber)
  • E2E:

    • Added "queued" to MockProposal status union in mock-dao-api.ts

Testing

  • npx tsc --noEmit passes cleanly
  • npx prettier --check passes on all modified files
  • vitest run src/hooks/useProposals.test.tsx src/hooks/useGovernance.test.tsx passes
  • Contract unit tests added for:
    • Timelock enforcement on execute_proposal
    • Veto by admin and supermajority
    • Cancellation during queued state
    • Timelock delay getter/setter

Potential Conflicts / Edge Cases

  • Legacy proposals with status = 'approved' in the database will be surfaced as "executed" by deriveProposalState, preserving backwards compatibility
  • The contract proposal_status helper maps legacy Approved enum variant to Queued or Executed based on the executed flag
  • Pre-existing any-type lint errors in server/src/routes/governance.routes.ts are unrelated to this PR and existed before these changes

Related Issues

iammrjude and others added 30 commits March 29, 2026 00:05
…ao-proposals-backend

feat: wire DAO proposals pages to backend API
…uorum/approval

- Add ProposalExecuted and ProposalCancelled events
- Add executed/cancelled fields to Proposal struct
- Add VotingClosed and VotingNotClosed errors
- Add quorum_threshold and approval_bps storage with getters/setters
- Implement execute_proposal with deadline and state checks
- Implement cancel_proposal for admin before deadline
- Update vote to reject cancelled/executed proposals
- Update finalize_proposal to use configurable thresholds
- Add internal disburse_internal used by execute_proposal
- Add comprehensive tests for execute/cancel paths
- Update existing tests for new initialize signature and errors

Closes bakeronchain#416 bakeronchain#417 bakeronchain#420
- Add GOVMinted, GOVTransferred, GOVApproved contract events
- Emit events in mint, transfer, transfer_from, approve
- Fix approve moved-value bug by cloning owner/spender for storage key
- Add derive traits to event structs for observability

Closes bakeronchain#419
- milestone_escrow: mint enough tokens for fuzzed escrow amounts
- scholarship_treasury: mint enough tokens for fuzzed deposits and constrain amount to avoid overflow

Closes #0
…e-debug-507

fix: remove production debug statements (bakeronchain#507)
…urriculum-506

fix: replace placeholder lesson curriculum (bakeronchain#506)
…-cancel-quorum-events

Feat/treasury execute cancel quorum events
jerrymusaga and others added 26 commits April 25, 2026 03:50
…ctive components

- Add skip-to-content link visible on focus for keyboard-only users
- Add global focus-visible CSS for consistent visible focus rings
- WalletInfoModal: Escape key closes modal, focus trapped inside, focus restored on close
- NotificationBell: Escape key closes panel, focus trapped, focus returns to bell button
- GlobalSearch: Escape closes dropdown, ArrowUp/ArrowDown navigates results, Enter selects, combobox ARIA roles
- NavBar: Escape key closes mobile slide-out menu
- ThreadList: convert non-semantic div[onClick] to accessible <button> elements
…visual progress bar

- New useLessonProgress hook: persists read lessons to localStorage keyed by
  course slug, syncs best-effort to /api/me/lesson-progress, retries on
  window 'online' event for offline-first UX
- LessonContent: IntersectionObserver sentinel at the bottom of content fires
  onScrolledToBottom once per lesson load; resets on lesson change
- LessonView: two-layer progress bar at the top (soft cyan = locally read,
  emerald = server-confirmed); wires onScrolledToBottom to markLessonRead;
  passes readLessonIds down to both sidebar instances
- LessonSidebar: accepts readLessonIds prop; renders outlined soft checkmark
  for locally-read-but-not-completed lessons (vs. filled checkmark for
  server-confirmed); two-layer progress bar matches LessonView styling
feat: E2E test — comment system (post, edit, vote, delete
…-deploy-workflow

chore: add staging deployment workflow triggered on main
…g-742

perf: implement React code splitting for all route-level components (bakeronchain#742)
…merge-conflict

Feat/resolve merge conflict
…-review-system

Feat/add peer review system
…d-navigation

feat(bakeronchain#727): add keyboard navigation support to all interactive compon…
…progress-tracker

feat(bakeronchain#657): add interactive lesson progress tracker with visual progr…
…int-service-details

fix: expand health endpoint with db redis and horizon diagnostics
…rol-audit

 security: audit contract access control and add treasury admin auth negative tests (bakeronchain#724)
…or-rate-limiting-middleware

feat: implement comprehensive rate limiting tests
…or-CORS-middleware

test: implement CORS configuration tests and refactor config
…ile-API

feat: implement rich user profiles API
…rformance-analytics

fix: add validator performance analytics API and admin dashboard metrics
…shold-positive

fix(scholarship_treasury): require positive quorum threshold to prevent low-participation execution
@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented May 27, 2026

@DSOTec Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Anuoluwapo25
Copy link
Copy Markdown
Contributor

hi @DSOTec please can you pull from upstream, I made alot of changes from the last wave because it was too heavy.

@Anuoluwapo25 Anuoluwapo25 merged commit 9916004 into bakeronchain:main May 29, 2026
2 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.