@@ -35,11 +35,28 @@ pub const STRIKE_DEACTIVATION_THRESHOLD: u32 = 3;
3535// Conversion: 1 ledger ≈ 5 s on Stellar Mainnet (Protocol 20+).
3636// See: https://developers.stellar.org/docs/learn/fundamentals/stellar-consensus-protocol
3737pub use crate :: ledger:: {
38- LEDGERS_PER_DAY , LEDGERS_PER_HOUR , LEDGERS_PER_MIN , LEDGERS_PER_WEEK , POLICY_DURATION_LEDGERS ,
38+ APPEAL_OPEN_WINDOW_LEDGERS , APPEAL_VOTE_WINDOW_LEDGERS , LEDGERS_PER_DAY , LEDGERS_PER_HOUR ,
39+ LEDGERS_PER_MIN , LEDGERS_PER_WEEK , MAX_APPEALS_PER_CLAIM , POLICY_DURATION_LEDGERS ,
3940 QUOTE_TTL_LEDGERS , RATE_LIMIT_WINDOW_LEDGERS , RENEWAL_WINDOW_LEDGERS , SECS_PER_LEDGER ,
4041 VOTE_WINDOW_LEDGERS ,
4142} ;
4243
44+ // ── Strike / rejection constants ──────────────────────────────────────────────
45+
46+ /// Number of rejected claims that automatically deactivates a policy.
47+ ///
48+ /// This is a **compile-time constant**, not a runtime admin parameter. Admin
49+ /// cannot flip it post-deployment, which prevents governance gaming where a
50+ /// large voter bloc rejects claims to deactivate rival policies.
51+ ///
52+ /// **Legal review:** Before changing this value, consult legal counsel on
53+ /// whether automatic policy cancellation triggers regulatory requirements
54+ /// (e.g., notice periods, appeal rights).
55+ ///
56+ /// **Appeal interaction:** Deactivation triggered by reaching this threshold
57+ /// can be reversed by a successful appeal that decrements strikes back below it.
58+ pub const STRIKE_DEACTIVATION_THRESHOLD : u32 = 3 ;
59+
4360// ── Enums ─────────────────────────────────────────────────────────────────────
4461
4562#[ contracttype]
@@ -76,10 +93,19 @@ pub enum CoverageType {
7693
7794/// Claim lifecycle state machine.
7895///
79- /// Transitions:
80- /// Processing → Approved (majority approve vote or deadline plurality)
81- /// Processing → Rejected (majority reject vote or deadline plurality/tie)
82- /// Approved → Paid (admin calls process_claim)
96+ /// Base-flow transitions:
97+ /// Processing → Approved (majority approve vote or deadline plurality)
98+ /// Processing → Rejected (majority reject vote or deadline plurality/tie)
99+ /// Approved → Paid (admin calls process_claim)
100+ ///
101+ /// Appeal-flow transitions (requires Rejected status + open appeal window):
102+ /// Rejected → UnderAppeal (claimant calls open_appeal within window)
103+ /// UnderAppeal → AppealApproved (majority approve appeal vote or deadline)
104+ /// UnderAppeal → AppealRejected (majority reject appeal vote or deadline)
105+ /// AppealApproved → Paid (admin calls process_claim — same as Approved)
106+ ///
107+ /// Terminal states (no further transitions): Paid, Rejected (after appeal window
108+ /// closes), AppealApproved (→ Paid only), AppealRejected.
83109#[ contracttype]
84110#[ derive( Clone , PartialEq , Eq , Debug ) ]
85111pub enum ClaimStatus {
@@ -88,13 +114,23 @@ pub enum ClaimStatus {
88114 Approved ,
89115 Paid ,
90116 Rejected ,
117+ /// Claimant has opened an appeal; fresh vote round in progress.
118+ UnderAppeal ,
119+ /// Appeal vote resolved in claimant's favour; awaits admin payout.
120+ AppealApproved ,
121+ /// Appeal vote rejected; claim is permanently closed.
122+ AppealRejected ,
91123}
92124
93125impl ClaimStatus {
94126 pub fn is_terminal ( & self ) -> bool {
95127 matches ! (
96128 self ,
97- ClaimStatus :: Approved | ClaimStatus :: Paid | ClaimStatus :: Rejected
129+ ClaimStatus :: Approved
130+ | ClaimStatus :: Paid
131+ | ClaimStatus :: Rejected
132+ | ClaimStatus :: AppealApproved
133+ | ClaimStatus :: AppealRejected
98134 )
99135 }
100136}
@@ -234,6 +270,18 @@ pub struct Claim {
234270 pub reject_votes : u32 ,
235271 /// Ledger sequence at which this claim was filed (voting window anchor).
236272 pub filed_at : u32 ,
273+ // ── Appeal fields ────────────────────────────────────────────────────────
274+ /// Ledger by which `open_appeal` must be called (0 if never rejected).
275+ /// Set to `rejected_at + APPEAL_OPEN_WINDOW_LEDGERS` when status → Rejected.
276+ pub appeal_open_deadline_ledger : u32 ,
277+ /// How many appeals have been opened for this claim (cap = MAX_APPEALS_PER_CLAIM).
278+ pub appeals_count : u32 ,
279+ /// Voting deadline for the current appeal round (0 if no appeal open).
280+ pub appeal_deadline_ledger : u32 ,
281+ /// Approve votes cast in the current appeal round.
282+ pub appeal_approve_votes : u32 ,
283+ /// Reject votes cast in the current appeal round.
284+ pub appeal_reject_votes : u32 ,
237285}
238286
239287#[ contracttype]
0 commit comments