Skip to content
This repository was archived by the owner on Aug 11, 2026. It is now read-only.

feat(tenant-lifecycle): enforce trial, active, grace, suspended, canceled, restore, and downgrade semantics #873

Description

@ahliweb

Parent epic: #868
Depends on: #869, #871, #872

Context

SaaS lifecycle state must be more precise than a generic tenant active flag. Trial expiry, payment grace, suspension, cancellation, restoration, and downgrade need deterministic access behavior while preserving tenant data and offline/LAN safety.

Objective

Implement a tenant-lifecycle capability with versioned transition rules, effective restrictions, restoration, scheduled jobs, and safe coordination with entitlements, sessions, modules, public routing, workers, and provisioning.

Scope

  • Add admitted module/extension descriptor, permissions, events, jobs, and admin navigation.
  • Add lifecycle records/history with states such as provisioning, trial, active, renewal_due, past_due, grace, suspended, canceled, restoring, and blocked/manual_review, subject to docs(saas-control-plane): decide module admission, control-plane boundary, trust model, and lifecycle contracts #869.
  • Implement validated state transitions, effective timestamps, reasons, actor/source, scheduled transition jobs, and optimistic/concurrency guards.
  • Define restriction profiles for:
    • authenticated admin access;
    • public site availability;
    • writes versus read-only access;
    • background jobs and provider dispatch;
    • data export and owner recovery;
    • entitlement/module behavior.
  • Ensure downgrade changes effective entitlements but never deletes data automatically.
  • Support restore/reactivate with reconciliation and explicit confirmation of unresolved provisioning/payment issues.
  • Integrate session invalidation/assurance decisions without creating account-enumeration leaks.
  • Emit versioned lifecycle events and update reporting projections.
  • Add admin UI for status, scheduled transition, reason, evidence, restore, and timeline.
  • Audit all high-risk lifecycle actions with mandatory reason.

Out of scope

Security and integrity requirements

  • Restriction policy is server-derived and fail-closed.
  • Suspension cannot be bypassed by direct API calls, stale sessions, public host routing, or background workers.
  • Owner recovery/export behavior must be explicit and separately authorized.
  • Platform operators need dedicated permissions; tenant admins cannot self-reactivate unless policy explicitly allows it.
  • Lifecycle transition and effective entitlement updates are atomic or reconciled through durable events.
  • Scheduled jobs are idempotent and safe under concurrent workers.
  • Data retention/deletion remains governed by data-lifecycle policies and legal hold, not lifecycle state alone.

Acceptance criteria

  • Every allowed transition is versioned, validated, audited, and concurrency-safe.
  • Invalid transitions return deterministic 409 responses.
  • Suspension restrictions apply consistently to SSR, API, public routing, and workers.
  • Downgrade preserves all tenant data and produces explainable entitlement changes.
  • Restore/reactivate runs reconciliation and does not silently overlook failed provisioning/provider state.
  • Scheduled trial/grace transitions are idempotent under multiple workers.
  • Tenant A lifecycle never changes tenant B.
  • LAN/offline deployment can use lifecycle without any online payment provider.
  • OpenAPI/AsyncAPI/UI/audit/docs are synchronized.

Testing

  • Unit tests for transition matrix, effective restrictions, downgrade, restore, and scheduling.
  • PostgreSQL integration tests for RLS, concurrency, idempotent scheduled transitions, and event same-commit behavior.
  • Cross-surface tests: API, SSR admin, public host, and worker behavior while suspended.
  • E2E trial → active → grace → suspended → restored.
  • Security tests for stale session and direct-route bypass.
  • Mutation test: remove the lifecycle gate from one surface and ensure parity tests fail.

Documentation

  • State/restriction matrix, ERD/data dictionary, OpenAPI/AsyncAPI, operator/tenant SOP, incident and restore runbook, retention/legal-hold relation, module README, and changeset.

Dependencies

Subscription billing #876 will request lifecycle transitions through this contract rather than mutating tenant state directly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:apiKontrak OpenAPI/RESTarea:authorizationRBAC and ABAC workarea:databaseSchema, migration, pooling, RLSarea:securitySecurity and 2FA workpriority:p1Prioritas tinggi - core domaintype:taskAtomic implementation task

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions