Files
T
cgalo5758 662d48ab4b Finalize org type default change flow
Enforce defaults as a floor by removing the initiation opt-out. Batch
preview classification by org type, identify other position sources, and
cover grandfather sunset restoration. Archive the completed OpenSpec
change.
2026-07-12 13:50:53 -05:00

10 KiB

plan-downgrade

Purpose

Defines the member-facing Standard→Public downgrade contract: when a member's higher-tier plan provision ends, the pool returns to its org-type default tier (or goes off-ladder when no default is configured), tier reductions apply the clamp policy so resources already provisioned above a lowered limit are retained while new over-limit provisioning is refused, and the member is advised of any resulting over-limit state.

Requirements

Requirement: Downgrade returns the pool to its org-type default

When a member's active plan provision ends — whether via Stripe subscription cancellation (customer.subscription.deleted reconciled through the fulfillment path) or operator revocation — the system SHALL return the pool to its org-type default tier through the two-call model: entitlements.end_conferral resolved by the ending provision's source (which never re-mints the baseline itself), then the floor-guarded baseline restoration (ReapplyDefaultsForPool, invoked only when the pool is left with no live (active or suspended) plan-ladder attachment from any source on any ladder — a position held by any other source is never superseded, and the baseline is never conferred alongside a live plan position on a different ladder). When a default plan ladder is configured for the org type and the guard finds the pool without any live plan position, the pool SHALL be re-provisioned at that ladder's rank-0 product via a fresh system-authored default decree; the audit trail records an end transition for the ended position and an initiate transition for the restored default (the single-row downgrade classification belonged to the retired end-and-re-apply primitive). When no default is configured, the pool SHALL legitimately go off-ladder and only the end transition SHALL be recorded; no replacement provision is created.

Scenario: Downgrade with a configured default re-applies the rank-0 tier

  • WHEN a member on a higher rung has their active provision ended and the org type has a configured default plan ladder
  • THEN the system SHALL end the prior provision and every ladder rung it occupied, recording an end transition per rung
  • AND the system SHALL re-provision the pool at the default ladder's rank-0 product via the floor-guarded restoration
  • AND the restored position SHALL be recorded as an initiate transition sourced by a fresh system-authored default grant

Scenario: Downgrade with no configured default leaves the pool off-ladder

  • WHEN a member's active provision is ended and the org type has no configured default plan ladder
  • THEN the system SHALL end the prior provision
  • AND the system SHALL leave the pool off-ladder with no replacement provision
  • AND the system SHALL record an end transition

Scenario: Downgrade defers to a remaining plan on another ladder

  • WHEN a member's active provision is ended while the pool separately holds a live plan-ladder position from another source on a different ladder (e.g. a legacy grant from a grandfathered default)
  • THEN the floor guard SHALL find the pool occupied and confer nothing
  • AND only the end transition for the ended provision SHALL be recorded

Requirement: Tier reduction uses the clamp policy

clamp is the baseline tier-reduction policy: when a downgrade lowers a numeric entitlement limit below the pool's current usage, resources already provisioned above the new limit SHALL be retained and remain usable, and new provisioning that would exceed the limit SHALL be refused until usage falls back below the limit. For a counted resource whose provider supports a read-only lifecycle state (set_status), the system SHALL additionally apply the force_reduce policy — parking excess instances read-only to restore compliance (see "FedWiki site downgrade parks excess sites read-only"). When force_reduce is unavailable for a resource (the provider declares no read-only state, or parking is pending or has failed), clamp SHALL hold as the safety default and SHALL NOT delete or suspend existing resources. The configurable tier_reduction_policy of Decision 125 remains unimplemented; force_reduce is now implemented for FedWiki sites and is no longer out of scope.

Scenario: Clamp retains resources for a non-read-only-capable resource

  • WHEN a pool's limit for a counted resource whose provider declares no read-only state drops below current usage
  • THEN the existing over-limit resources SHALL remain present and usable
  • AND the system SHALL NOT delete or suspend them

Scenario: New provisioning is refused while over the limit

  • WHEN a member whose fedwiki_sites usage exceeds the active limit attempts to create a new site
  • THEN the system SHALL refuse the creation

Scenario: Provisioning is re-enabled once usage falls under the limit

  • WHEN a member over the limit reduces usage until current_usage is below resource_limit
  • THEN the system SHALL again permit creation up to the limit

Requirement: Member is advised of the over-limit state

When a pool's usage exceeds its active limit and clamp holds (no force_reduce parking), the member-facing UI SHALL surface the over-limit state — displaying the over-limit count (e.g. "3 of 1 sites used") and disabling the relevant create affordance with a clear reason. When force_reduce parks excess sites read-only, usage is restored to the limit and the UI SHALL instead advise which site remains active, that the remaining sites are read-only (content retained and readable), and how to change the selection.

Scenario: Over-limit advisory under clamp

  • WHEN a downgraded member with a clamped resource at usage 3 and limit 1 views their dashboard
  • THEN the UI SHALL display the over-limit count (e.g. "3 of 1 sites used")
  • AND the UI SHALL disable the create affordance with a clear reason

Scenario: Force-reduce advisory after sites are parked

  • WHEN a downgraded member's excess sites have been parked read-only by force_reduce
  • THEN the UI SHALL indicate which site is active and that the remaining sites are read-only
  • AND the UI SHALL offer a way to change which site is active

Requirement: FedWiki site downgrade parks excess sites read-only

When a downgrade lowers the fedwiki_sites limit below the count of active sites, the system SHALL park the excess sites read-only via set_status(readonly) so that active usage is restored to the new limit. The limit-many most-recently-modified sites (by observed last_modified_at) SHALL be kept active by default; parked sites SHALL be stamped with force_reduced_at. Read-only parking SHALL be non-destructive — content is retained and remains readable.

The member MAY change which sites are active, subject to a per-workspace cooldown that gates rotations — bringing a different site into the active set in place of one already there. A transition into active SHALL be a rotation when the activated site is force-reduced (force_reduced_at IS NOT NULL — a site this downgrade parked), OR when it is performed while active usage is at the limit (a swap that parks an incumbent to promote another). Restoring a site that is not force-reduced — the member's own incumbent, whether currently active or one they archived themselves — SHALL always be allowed and SHALL NOT consult the cooldown (it returns the status quo, not a rotation). The first rotation within a cooldown window SHALL be free and subsequent rotations SHALL be refused until the window elapses for that workspace; restoring an incumbent SHALL neither be refused nor start or extend the window. When a force-reduced site is rotated back into the active set, its force_reduced_at SHALL be cleared. The cooldown window SHALL be configurable, default 30 days, and any user-facing refusal message SHALL reflect the configured window.

When the limit later rises (re-upgrade), the system SHALL auto-reactivate force_reduced_at sites, most-recently-modified first, up to the new limit, clearing force_reduced_at; each reactivation SHALL be quota-gated.

Scenario: Downgrade parks excess sites and keeps the default active

  • WHEN a member with 3 active sites is downgraded so the fedwiki_sites limit becomes 1
  • THEN the most-recently-modified site SHALL remain active
  • AND the other 2 sites SHALL be set read-only and stamped force_reduced_at
  • AND active current_usage SHALL equal 1 (the new limit)

Scenario: Parked site content remains readable

  • WHEN a site has been parked read-only by force_reduce
  • THEN its pages SHALL remain served and readable
  • AND edits, forks, and new pages SHALL be blocked

Scenario: Member swaps the active site, second swap refused by cooldown

  • WHEN a member on a 1-site limit swaps which site is active for the first time
  • THEN the swap SHALL succeed (the chosen site becomes active, the prior one read-only)
  • WHEN the same member attempts a second swap before the cooldown elapses
  • THEN the swap SHALL be refused

Scenario: Restoring your incumbent active site is always free

  • WHEN a member archives the site that was active (not force-reduced) and then restores that same site
  • THEN the restore SHALL be allowed without consulting the cooldown
  • AND it SHALL NOT stamp or extend the cooldown window

Scenario: Rotating a downgrade-parked reserve in is gated

  • WHEN a member whose quota was reduced restores a force_reduced (parked) site for the first time within the window
  • THEN the restore SHALL succeed, clear that site's force_reduced_at, and stamp the cooldown
  • WHEN the member tries to rotate in another force_reduced site before the window elapses
  • THEN that rotation SHALL be refused
  • AND restoring their own (non-force-reduced) incumbent SHALL still be allowed during the window

Scenario: Cooldown window honors configuration

  • WHEN the configured cooldown window is changed from its default
  • THEN rotations SHALL be gated by the configured window
  • AND the user-facing refusal message SHALL reflect the configured window

Scenario: Re-upgrade reactivates parked sites up to the new limit

  • WHEN a member with 2 force_reduced read-only sites is upgraded so the limit becomes 3
  • THEN the system SHALL reactivate the force_reduced sites most-recently-modified first, up to the limit
  • AND the reactivated sites SHALL have force_reduced_at cleared