Base/pre 1221 - #1382
Merged
Merged
Conversation
Implements a request → approve/reject → apply state machine that prevents a single unreviewed request from executing a high-impact parameter override. ## What changed ### Core state machine (contracts/escrow/src/governance_proposal.rs) Four new entrypoints on the Escrow contract: - request_governance_proposal(kind) → proposal_id Admin-gated. Validates the payload immediately (same bounds as the live setter). Returns a monotonic ID and stores a Pending proposal. - approve_governance_proposal(proposal_id, approver) Approver must differ from the requester (GovernanceSelfApproval guard). Moves proposal from Pending → Approved. - reject_governance_proposal(proposal_id, approver) Same self-approval guard. Moves Pending → Rejected (terminal). - apply_governance_proposal(proposal_id) Admin-gated. Requires Approved state. Materialises the parameter change, then sets Applied (idempotency: a second call fails with GovernanceProposalInvalidState). Two read-only helpers: - get_governance_proposal(id) → Option<GovernanceProposal> - get_next_governance_proposal_id() → u64 ### Types (contracts/escrow/src/types.rs) - GovernanceProposalKind enum (SetProtocolFeeBps, SetGovernedParams, SetFeeWithdrawalCap, SetFeeWithdrawalCooldown, SetMaxMilestones) - GovernanceProposalState enum (Pending / Approved / Rejected / Applied) - GovernanceProposal struct with requester, approver, state, kind, expiry - DataKey variants: GovernanceProposal(u64) and NextGovernanceProposalId - Error codes: GovernanceProposalNotFound(77), GovernanceProposalInvalidState(78), GovernanceProposalExpired(79), GovernanceSelfApproval(80) ### TTL (contracts/escrow/src/ttl.rs) - GOVERNANCE_PROPOSAL_TTL_LEDGERS = LEDGERS_PER_DAY * 3 (~3 days) - GOVERNANCE_PROPOSAL_BUMP_THRESHOLD = LEDGERS_PER_DAY - set_governance_proposal_ttl() helper ### Tests (contracts/escrow/src/test/governance_proposal.rs) — 26 tests All 5 required edge cases from issue Talenttrust#1221: 1. request by operator — admin submits proposal; ID positive; Pending state 2. self-approval — requester cannot approve own proposal → GovernanceSelfApproval 3. expired request — any action past TTL → GovernanceProposalExpired 4. rejected request — Rejected terminal; approve/apply fail → GovernanceProposalInvalidState 5. apply twice — second apply → GovernanceProposalInvalidState Plus: happy-path round-trips for all 3 proposal kinds, not-found guards, expiry boundary (succeeds at boundary, fails one past), events for each transition, multiple independent proposals, approver identity recorded. ## Security notes - Self-approval is blocked at both approve and reject paths. - Expiry is checked on every mutable action; the 3-day window limits the blast radius of a forgotten or compromised pending proposal. - Rejection is terminal — a rejected proposal cannot be re-approved or applied; the admin must open a fresh proposal. - Applied proposals cannot be re-applied (idempotency guard on state). - Payload is validated at request time so invalid values never reach storage. Closes Talenttrust#1221
…-approval-1221 feat(governance): two-step approval workflow for high-impact overrides
13 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1346
#closes1221