@@ -102,6 +102,35 @@ type BillingConfig struct { |
| 102 | 102 | Enabled bool `toml:"enabled"` |
| 103 | 103 | GracePeriod time.Duration `toml:"grace_period"` |
| 104 | 104 | Stripe StripeBillingConfig `toml:"stripe"` |
| 105 | + // Enforce gates the per-feature flip from PRO05's report-only mode |
| 106 | + // to hard enforcement for user-kind principals. Each feature carries |
| 107 | + // its own knob so the launch can revert one feature without rolling |
| 108 | + // back the deploy (PRO07 pitfall: "do not enforce a feature you |
| 109 | + // can't unenforce"). Org-kind enforcement has been on since SP05 and |
| 110 | + // is not gated by this struct. |
| 111 | + Enforce EnforceConfig `toml:"enforce"` |
| 112 | +} |
| 113 | + |
| 114 | +// EnforceConfig is the PRO07 per-feature enforcement matrix. Defaults |
| 115 | +// (all false) keep production in report-only mode; operators flip |
| 116 | +// features individually after the 7-day telemetry soak ratifies that |
| 117 | +// no Free user is currently exercising the gate. The flag order and |
| 118 | +// names are stable — flipping any to true is a one-way deploy that |
| 119 | +// operators back out with the same knob, not by reverting code. |
| 120 | +type EnforceConfig struct { |
| 121 | + // UserAdvancedBranchProtection: when true, Free users on private |
| 122 | + // personal repos are blocked from setting prevent_force_push, |
| 123 | + // prevent_deletion, or require_signed_commits. |
| 124 | + UserAdvancedBranchProtection bool `toml:"user_advanced_branch_protection"` |
| 125 | + // UserRequiredReviewers: when true, Free users on private personal |
| 126 | + // repos are blocked from setting required_review_count > 0. |
| 127 | + UserRequiredReviewers bool `toml:"user_required_reviewers"` |
| 128 | + // UserProfilePinsBeyondFree: when true, Free users are blocked from |
| 129 | + // pinning more than the Free cap (6) profile repos. PRO07 ships this |
| 130 | + // gate without a report-only phase — the cap is small, the failure |
| 131 | + // mode is benign, and a Free user has no way to have exceeded the |
| 132 | + // cap before this knob existed. |
| 133 | + UserProfilePinsBeyondFree bool `toml:"user_profile_pins_beyond_free"` |
| 105 | 134 | } |
| 106 | 135 | |
| 107 | 136 | // StripeBillingConfig holds Stripe Billing API settings. Checkout and portal |