Add POST /api/billing/portal for subscription management #782

Open
pook wants to merge 64 commits from agent-task/681 into main
Owner

Summary

  • Adds authenticated POST /api/billing/portal endpoint that creates a Stripe billing portal session
  • Validates Bearer token auth, looks up stripe_customer_id from DB, calls stripe.billingPortal.sessions.create, returns { url }
  • Returns 401 without auth, 404 if user not found or has no Stripe customer ID, 200 with portal URL on success
  • Registers billing router at /api/billing path prefix and excludes /api/billing/webhook from CSRF

Test plan

  • 7 unit tests covering all acceptance criteria (401, 404, 200 cases)
  • Tests pass in isolation and alongside all existing tests
  • Manual verification with real Stripe test keys

🤖 Generated with Claude Code

Closes #681

## Summary - Adds authenticated `POST /api/billing/portal` endpoint that creates a Stripe billing portal session - Validates Bearer token auth, looks up `stripe_customer_id` from DB, calls `stripe.billingPortal.sessions.create`, returns `{ url }` - Returns 401 without auth, 404 if user not found or has no Stripe customer ID, 200 with portal URL on success - Registers billing router at `/api/billing` path prefix and excludes `/api/billing/webhook` from CSRF ## Test plan - [x] 7 unit tests covering all acceptance criteria (401, 404, 200 cases) - [x] Tests pass in isolation and alongside all existing tests - [ ] Manual verification with real Stripe test keys 🤖 Generated with [Claude Code](https://claude.com/claude-code) Closes #681
Add POST /api/billing/portal endpoint for subscription management
Some checks are pending
CI Quality Gate / Lint / Typecheck / Test / Build (pull_request) Waiting to run
4bc1bcc82c
Adds an authenticated POST endpoint that creates a Stripe billing portal
session. The endpoint validates Bearer token auth, looks up the user's
stripe_customer_id from the database, and returns the portal URL.
Returns 401 without auth, 404 if user missing or has no Stripe customer ID.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
feat: issue #773 add-post-apibillingportal-that-creates-a (agent task liancebot773)
Some checks failed
CI Quality Gate / Lint / Typecheck / Test / Build (pull_request) Has been cancelled
94dabee7e5
Author
Owner

Review: PR #782 — POST /api/billing/portal

Code Review: PASS

The implementation is correct:

  • POST /api/billing/portal returns 401 without valid session ✓
  • Returns a valid Stripe portal session URL with authenticated user ✓
  • Portal session uses the user's stripe_customer_id (verified in stripe.ts:132-143) ✓
  • Test suite covers all scenarios (401 auth, 404 user/stripe_customer_id, 200 success) ✓

Tests: BLOCKED

bun test crashes on the review environment due to missing AVX CPU support (known Bun runtime bug, not a code issue).

Merge: BLOCKED — Conflicts

The PR branch (agent-task/681) has conflicts with current main in:

  • packages/api/src/index.ts
  • packages/api/src/routes/billing.ts
  • packages/api/tests/e2e/webhook.test.ts
  • .tldr/cache/call_graph.json
  • .tldr/languages.json

Action required: Rebase onto current main to resolve conflicts, then re-request merge.


Reviewed by agent-bot (issue #773 verification)

## Review: PR #782 — POST /api/billing/portal ### Code Review: PASS The implementation is correct: - POST /api/billing/portal returns 401 without valid session ✓ - Returns a valid Stripe portal session URL with authenticated user ✓ - Portal session uses the user's stripe_customer_id (verified in stripe.ts:132-143) ✓ - Test suite covers all scenarios (401 auth, 404 user/stripe_customer_id, 200 success) ✓ ### Tests: BLOCKED `bun test` crashes on the review environment due to missing AVX CPU support (known Bun runtime bug, not a code issue). ### Merge: BLOCKED — Conflicts The PR branch (agent-task/681) has conflicts with current main in: - packages/api/src/index.ts - packages/api/src/routes/billing.ts - packages/api/tests/e2e/webhook.test.ts - .tldr/cache/call_graph.json - .tldr/languages.json **Action required:** Rebase onto current main to resolve conflicts, then re-request merge. --- *Reviewed by agent-bot (issue #773 verification)*
Some checks failed
CI Quality Gate / Lint / Typecheck / Test / Build (pull_request) Has been cancelled
This pull request has changes conflicting with the target branch.
  • .forgejo/workflows/ci.yml
  • bun.lock
  • package.json
  • packages/api/src/db/schema.ts
  • packages/api/src/index.ts
  • packages/api/src/middleware/csrf.ts
  • packages/api/src/middleware/rate-limit.ts
  • packages/api/src/middleware/security-headers.ts
  • packages/api/src/routes/admin.ts
  • packages/api/src/routes/billing.ts
  • packages/api/src/routes/generate-tos.ts
  • packages/api/src/routes/generate.ts
  • packages/api/src/routes/health.ts
  • packages/api/src/routes/questionnaire.ts
  • packages/api/src/services/document-generator.ts
  • packages/api/src/services/llm.ts
  • packages/api/src/templates/index.ts
  • packages/api/tsconfig.json
  • packages/shared/src/types.ts
  • packages/web/src/app/questionnaire/page.tsx
  • packages/web/src/components/documents/DocumentList.tsx
  • packages/web/src/components/questionnaire/ReviewStep.tsx
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin agent-task/681:agent-task/681
git switch agent-task/681
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
pook/compliancebot!782
No description provided.