[dev] [claudfuen] feat/pentest-subscription-billing#2220
[dev] [claudfuen] feat/pentest-subscription-billing#2220github-actions[bot] wants to merge 10 commits intomainfrom
Conversation
Icons (AppShellWrapper — rail): - Compliance: CertificateCheck → Badge (certification badge) - Trust: CloudAuditing → Globe (public/global trust center) - Security: Security → ManageProtection (protection management) Icons (AppSidebar — compliance sidebar): - Auditor View: TaskComplete → DocumentSigned (auditors sign off) - Controls: Security → SettingsAdjust (adjustable params, no dupe) - Documents: Catalog → FolderDetails (folder of docs) - People: Group → UserMultiple (standard multi-user) - Risks: Warning → Scale (weighing risk) - Vendors: ShoppingBag → Partnership (business partners) - Questionnaire: Document → DocumentTasks (task-filled form) - Integrations: Integration → Connect (connecting systems) - Cloud Tests: Chemistry → TestTool (test tooling) Overview: - Replace <DraggableCards> with a plain 2-column grid - Delete DraggableCards.tsx, SortableCard.tsx, useCardOrder.ts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The id returned by the create API is the provider run ID stored in providerRunId, not the internal ptr... primary key. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ntest-subscription-billing
Show a locked marketing state when the org has no active pentest subscription. Includes a reusable ModuleGate component in @comp/ui with dark chrome-frame preview, and an animated pen-test demo that cycles through agents and reveals findings with severity badges. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PR SummaryHigh Risk Overview Billing flow is hardened and moved earlier in the run lifecycle. Server actions now require org admin/owner (not just membership), block duplicate active subscriptions, add Billing page and Stripe webhook coverage are expanded. The billing page is reworked into a subscriptions table (active/cancelled/past_due states, usage/renewal, manage/fix payment CTAs) with an expanded pentest usage section; Stripe pentest webhook now has comprehensive tests for checkout completion and subscription update/delete events. Data/API contract tweaks. Written by Cursor Bugbot for commit 1b06c7a. This will update automatically on new commits. Configure here. |
...pp/src/app/(app)/[orgId]/security/penetration-tests/components/pentest-preview-animation.tsx
Show resolved
Hide resolved
- Add preauthorize billing check before run creation (prevents unbilled runs) - Add dynamic pricing from Stripe (subscription + overage prices) - Add usage tracking in pentest page header and create dialog - Add overage confirmation dialog when included runs are exhausted - Add billing page with subscription table, usage details, and payment method - Add role-based auth (admin/owner only) for billing server actions - Add duplicate subscription guard in subscribeToPentestPlan - Add webhook unit tests (10 cases covering all event types) - Fix period boundary queries (lte → lt) to prevent double-counting - Fix payment method lookup to check subscription PM before customer PM - Fix PaymentIntent config (off_session instead of conflicting options) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
apps/app/src/app/(app)/[orgId]/security/penetration-tests/hooks/use-penetration-tests.ts
Outdated
Show resolved
Hide resolved
apps/app/src/app/(app)/[orgId]/security/penetration-tests/actions/billing.ts
Outdated
Show resolved
Hide resolved
- Fix animation interval spawning duplicate reset timers (added pausing flag) - Use stable nonce ref to prevent duplicate overage charges on retry - Remove dead getPentestUsage function and PentestUsage interface Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| }); | ||
| if (existingSub?.status === 'active') { | ||
| throw new Error('Organization already has an active pentest subscription.'); | ||
| } |
There was a problem hiding this comment.
Duplicate Stripe subscription possible for past-due status
High Severity
The duplicate-subscription guard in subscribeToPentestPlan only blocks active status, but past_due subscriptions are not blocked. The pentest page checks hasActiveSubscription (only true for active), so a past_due subscriber sees the "Get started" button which calls subscribeToPentestPlan. This creates a brand-new Stripe subscription while the old past_due one still exists. The DB record is overwritten via upsert, so the old subscription becomes untracked — the customer gets billed twice by Stripe with no way to cancel the orphaned subscription through the app.
Additional Locations (1)
| const authResult = await preauthorizePentestRun(organizationId, nonceRef.current); | ||
| if (!authResult.authorized) { | ||
| throw new Error(authResult.error ?? 'Billing authorization failed.'); | ||
| } |
There was a problem hiding this comment.
Pre-creation billing check introduces overage race condition
Medium Severity
Moving billing authorization before run creation introduces a TOCTOU race. Two concurrent requests can both call preauthorizePentestRun, both see the same runsThisPeriod count below the included limit, and both get authorized: true without overage. Both then create runs, exceeding the included limit without any overage charge. The previous post-creation check didn't have this issue because the run already existed in the DB when the count was performed.
Additional Locations (1)
Resolve conflicts by adopting main's API-based billing approach (pentest-billing controller/service) over branch's server actions. Removed billing.ts server action and updated page/test files accordingly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restructure to match current product messaging ("the agentic compliance
platform"), remove duplicate sections, add table of contents, monorepo
layout, and streamlined quick start guide.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…, update theme colors - Remove react-wrap-balancer dependency, use Tailwind text-balance utility - Add dotenv import to packages/db prisma.config.ts so migrations work - Update primary color and add proper dark mode theme Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>


Summary
Environment Variables
Three new env vars are required for pentest billing to function. All are optional — the app won't crash without them, but billing features will return descriptive errors.
STRIPE_PENTEST_SUBSCRIPTION_PRICE_IDprice_1T6vZa...STRIPE_PENTEST_OVERAGE_PRICE_IDprice_1T6va1...STRIPE_PENTEST_WEBHOOK_SECRET/api/webhooks/stripe-pentestendpointwhsec_...Stripe setup
STRIPE_PENTEST_SUBSCRIPTION_PRICE_IDSTRIPE_PENTEST_OVERAGE_PRICE_ID<app-url>/api/webhooks/stripe-pentestlistening for:customer.subscription.updatedcustomer.subscription.deletedinvoice.payment_failedSTRIPE_PENTEST_WEBHOOK_SECRETTest plan
🤖 Generated with Claude Code