Skip to content

feat(api): Extend license check response to distinguish trial / paid / expired paid status #29

Description

@Devsome

The current license validation endpoint returns only a boolean (valid). The silkpanel‑cms hard‑lock feature needs more granular information to decide whether to show a permanent lockout (paid license expired) or simply restrict updates (trial expired). The API must be extended to return:

  • status: string enum with values active_paid, expired_paid, trial, expired_trial, never_paid (or similar).
  • has_ever_paid: boolean – indicates if the user has at least one completed Stripe payment or a Stripe customer ID exists.
  • plan_tier: optional string (e.g., basic, pro) – for future feature flag usage.
  • expires_at: ISO 8601 date/time string – when the current paid period ends (null if never paid).
  • grace_period_days: integer – remaining days until hard lock if license expired (optional, could be calculated on CMS side).

Acceptance criteria for devso.me:

  • The license check endpoint returns the new fields alongside valid.
  • The logic to determine has_ever_paid is based on the existence of a Stripe customer ID linked to the user account and/or a successful payment history (at least one paid invoice).
  • A user who only ever used a trial returns has_ever_paid: false and status: trial or expired_trial.
  • A user whose paid subscription has expired returns has_ever_paid: true, status: expired_paid.
  • An active paid user returns status: active_paid.
  • The new response is backward‑compatible – existing CMS versions ignoring the extra fields must continue to work (the valid field remains the primary signal).
  • The implementation does not break any existing client relying on the old response format (additive change only).

Out of scope for devso.me sub‑ticket:

  • Changes to the purchasing flow or Stripe integration itself.
  • Returning full payment history – only the derived status flags are needed.
  • Any rate‑limiting changes (should be handled separately if required).

Acceptance criteria (main CMS ticket)

  • A paid license that expires causes the entire Filament admin panel to become inaccessible behind a permanent, non‑dismissable modal.
  • The lock takes effect on the next admin page load after the license is detected as expired.
  • Trial license expiration does not trigger this lock; trial behavior remains unchanged.
  • No admin route can bypass the modal – the middleware covers all registered admin paths.
  • The enforcement mechanism is delivered as the separate silkpanel/license-enforcement package.
  • Documentation is updated to reflect the new locking behavior and the difference between trial and paid license expiration.
  • A grace period for unreachable license servers prevents false lockouts (configurable).
  • There is no built‑in “super admin bypass” – support intervention requires direct server access.

Out of scope

  • Renewal or payment UI inside the CMS (all handled on devso.me).
  • Locking the public frontend – only the admin panel is affected.
  • Feature‑specific partial locks (e.g., keeping some pages accessible) – the entire panel is blocked.
  • Detailed design of the modal beyond the basic permanent overlay and message.

Metadata

Metadata

Assignees

Labels

featureNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions