Skip to content

[Phase 0e] Subscription lifecycle: cancel-subscription + resume-subscription (~3h) #105

@TortoiseWolfe

Description

@TortoiseWolfe

Part of epic #100.

Functions to ship

Both functions branch on subscriptions.provider to dispatch to the right SDK.

1. cancel-subscription (~1.5h)

  • Browser caller: src/components/payment/SubscriptionManager/SubscriptionManager.tsx:87
  • Request body: { subscription_id: string } (the internal subscriptions table row id, NOT the provider's id)
  • Logic:
    1. CORS + auth
    2. Load subscriptions row, verify owner
    3. Branch on provider:
      • Stripe: stripe.subscriptions.cancel(provider_subscription_id) (immediate) or stripe.subscriptions.update(id, { cancel_at_period_end: true }) (graceful)
      • PayPal: POST /v1/billing/subscriptions/{provider_id}/cancel with { reason }
    4. Update local subscriptions.status to cancelled or cancel-at-period-end
    5. Return updated row

2. resume-subscription (~1.5h)

  • Browser caller: src/components/payment/SubscriptionManager/SubscriptionManager.tsx:126
  • Request body: { subscription_id: string }
  • Logic:
    1. Same auth + load
    2. Branch on provider:
      • Stripe: stripe.subscriptions.update(id, { cancel_at_period_end: false }) — only valid if status was cancel-at-period-end
      • PayPal: POST /v1/billing/subscriptions/{provider_id}/activate
    3. Update local subscriptions.status to active
    4. Return updated row

Tests

  • Deno unit tests mocking both SDKs
  • Un-skip cancel/resume E2E tests under tests/e2e/payment/

Acceptance

  • Both functions exist
  • Deno tests pass
  • Deploy succeeds
  • SubscriptionManager Cancel + Resume buttons work for both Stripe and PayPal sandbox subscriptions

🤖 Created from audit on 2026-05-20

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestgap-auditIdentified during 2026-04-25 planned-vs-shipped auditpriority:p1High — fix soon (stability hotspot, low-hanging fruit, single-decision unlocks)

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions