V4: Vendor — Suspend a tenant who hasn't paid #43

Open
opened 2026-04-09 21:24:13 +02:00 by claude · 0 comments
Owner

User Story: As a vendor, I want to suspend a tenant who hasn't paid.

Revised approach: Instead of stopping containers, enforce read-only access via a suspension flag. Users keep viewing their data but cannot make changes.

Acceptance Criteria:

  • Suspend: set suspended_at on TenantEntity, tenant status → SUSPENDED
  • TenantIsolationInterceptor rejects POST/PUT/DELETE with 423 Locked when suspended_at is set (GET still allowed → read-only)
  • Containers stay running — no service disruption
  • Reactivate: clear suspended_at, tenant status → ACTIVE, instant effect
  • Suspended tenants visible in vendor list with amber status badge
  • Customer sees "Account suspended" banner in SaaS UI (detect 423 responses)
  • Server dashboard remains accessible in read-only mode (VIEWER-equivalent)
  • Audit log: TENANT_SUSPEND / TENANT_ACTIVATE

Why not Logto role manipulation:
Logto Management API has no "remove specific role" method — only add role or remove user entirely. Storing/restoring original roles per user is fragile and requires Logto round-trips. The suspension flag approach is atomic (single DB write), instantly reversible, and works even if Logto is down.

Implementation:

  1. Add suspended_at TIMESTAMP column to tenants table (migration)
  2. Update TenantIsolationInterceptor to check suspended_at and reject mutating requests with 423
  3. Update VendorTenantService.suspend() / activate() to set/clear suspended_at (remove container stop/start)
  4. SaaS UI: global 423 handler shows "Account suspended" banner
  5. Audit logging for suspend/activate actions

Spec: docs/superpowers/specs/2026-04-09-platform-redesign.md
API: POST /api/vendor/tenants/{id}/suspend, POST /api/vendor/tenants/{id}/activate

**User Story:** As a vendor, I want to suspend a tenant who hasn't paid. **Revised approach:** Instead of stopping containers, enforce read-only access via a suspension flag. Users keep viewing their data but cannot make changes. **Acceptance Criteria:** - Suspend: set `suspended_at` on TenantEntity, tenant status → SUSPENDED - `TenantIsolationInterceptor` rejects POST/PUT/DELETE with **423 Locked** when `suspended_at` is set (GET still allowed → read-only) - Containers stay running — no service disruption - Reactivate: clear `suspended_at`, tenant status → ACTIVE, instant effect - Suspended tenants visible in vendor list with amber status badge - Customer sees "Account suspended" banner in SaaS UI (detect 423 responses) - Server dashboard remains accessible in read-only mode (VIEWER-equivalent) - Audit log: TENANT_SUSPEND / TENANT_ACTIVATE **Why not Logto role manipulation:** Logto Management API has no "remove specific role" method — only add role or remove user entirely. Storing/restoring original roles per user is fragile and requires Logto round-trips. The suspension flag approach is atomic (single DB write), instantly reversible, and works even if Logto is down. **Implementation:** 1. Add `suspended_at TIMESTAMP` column to tenants table (migration) 2. Update `TenantIsolationInterceptor` to check `suspended_at` and reject mutating requests with 423 3. Update `VendorTenantService.suspend()` / `activate()` to set/clear `suspended_at` (remove container stop/start) 4. SaaS UI: global 423 handler shows "Account suspended" banner 5. Audit logging for suspend/activate actions **Spec:** `docs/superpowers/specs/2026-04-09-platform-redesign.md` **API:** `POST /api/vendor/tenants/{id}/suspend`, `POST /api/vendor/tenants/{id}/activate`
claude added the platformday-1 labels 2026-04-09 21:24:13 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: cameleer/cameleer-saas#43