Conversation
…ner (#2204) * feat(app): show confirmation for submission deletion * feat(api): create a delete endpoint to remove a submission * feat(app): integrate delete-submission endpoint on documents page * fix(app): add delete submission with findings cache invalidation * fix(api): make delete-submission api endpoint accessible by admin/owner * fix(app): make delete-submission button visible only for admin/owner * fix(app): keep submission-delete dialog open until delete completes and show laoding state --------- Co-authored-by: chasprowebdev <chasgarciaprowebdev@gmail.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
PR SummaryHigh Risk Overview Penetration test provider integration was tightened and expanded. Maced client schemas were updated (nullable normalization, new fields like New operational tooling and workflows. Adds a scheduled/PR GitHub Action canary ( Includes assorted UI cleanups (security results “all passed” banner, sidebar icon tweaks, settings billing tab, context table pagination, only Written by Cursor Bugbot for commit caef0d9. This will update automatically on new commits. Configure here. |
…ntract fixes (#2208) * feat(security): align penetration test lifecycle with Maced contract * fix(security): remove empty-string defaults from Maced run parser * test(api): add Maced contract canary e2e and CI workflow * fix(security): make Maced run parser transition-safe for nullish runtime IDs * fix(security): align Maced client and types to canonical OpenAPI contract - Drop fields absent from spec: sandboxId, workflowId, sessionId, failedReason (from Maced), userId, organizationId, phase, agent, completedAgentNames from all schemas, interfaces and test fixtures - Add notificationEmail to PentestRun schema, CreatePentestRequest payload, app-side PentestRun interface and PentestCreateRequest - Move webhookToken to a dedicated CreatePentestRun schema (POST-only) - Progress cell now renders "In progress (x/y)" without phase prefix - Update canary assertions and all unit test mocks to match new shapes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(ci): skip prisma generate in maced contract canary workflow The shared bun-install action runs `bun prisma generate` which fails at the repo root since the Prisma schema lives in a sub-package. The canary only needs the HTTP client and has no Prisma dependency, so inline the install without the generate step. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add bulk automation failure notification endpoint and email template Add POST /v1/internal/tasks/notify-bulk-automation-failures endpoint with FailedTaskDto and NotifyBulkAutomationFailuresDto DTOs, add notifyBulkAutomationFailures service method (recipients: task assignees + org admins/owners), and add consolidated email template that lists failed tasks with (X/Y failed) counts capped at 15 items. * fix: remove unused title and assigneeId fields from bulk failures DB query
Add overflow-hidden to the card container, min-w-0 to the flex child, shrink-0 to the icon, and break-words to the reason text to prevent long text from pushing the UI off-screen.
Added fromYear/toYear props to the Calendar component so users can jump directly to a year via dropdown instead of clicking month by month all the way back to e.g. 2009. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…2213) Added a note on cloud integration cards and in the connect dialog making it clear that these integrations are only used for Cloud Security Tests and credentials are used for read-only scans. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The context table was loading all entries without pagination, which doesn't scale. The backend already supported pagination via search params but the frontend wasn't using it. Now uses URL-based pagination with the Table component's built-in pagination prop, matching the pattern used by VendorsTable.
When a cloud security scan completes and all checks pass with no issues, the page now shows a green "All checks passed" banner instead of just a table of green rows. Makes it immediately obvious to customers and auditors that everything is clean.
| ...(report as SecurityPenetrationTest), | ||
| failedReason, | ||
| }; | ||
| } |
There was a problem hiding this comment.
Webhook token leaks to client via object spread
High Severity
mapMacedRunToSecurityPenetrationTest uses ...(report as SecurityPenetrationTest) which spreads all runtime properties of the input object. When called from createReport with a MacedCreatePentestRun (which includes the sensitive webhookToken field), the token leaks into the serialized API response even though it was intentionally removed from the SecurityPenetrationTest interface. The type cast only hides the field from TypeScript — it does not strip it at runtime.
Additional Locations (1)
* feat(pentest): subscription-based billing model
Replaces the mock checkout redirect with an inline subscription billing
model. Organizations subscribe to a monthly plan (3 runs included) and
overage runs are charged immediately via Stripe PaymentIntent at run
creation time — no redirect required.
- Add PentestSubscription DB model (organization relation, period tracking)
- Add billing server actions: subscribeToPentestPlan, handleSubscriptionSuccess,
checkAndChargePentestBilling (blocks run creation on billing failure)
- Add /[orgId]/security/penetration-tests/subscription management page
- Add /api/webhooks/stripe-pentest webhook handler (subscription updated/deleted)
- Remove mockCheckout from API DTO and client types
- Update useCreatePenetrationTest to call billing check before API post
- Update page client: remove checkout redirect/search-param handling,
navigate directly to report detail on success
- Add STRIPE_PENTEST_SUBSCRIPTION_PRICE_ID, STRIPE_PENTEST_OVERAGE_PRICE_ID,
STRIPE_PENTEST_WEBHOOK_SECRET env vars
- Delete mock checkout page
- Update all tests to reflect new flow
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(billing): use SubscriptionItem for period dates in Stripe SDK v20+
In stripe@20.x with API version 2025-12-15.clover, current_period_start
and current_period_end were moved from the root Subscription type to
SubscriptionItem. Read them via subscription.items.data[0] instead.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(security): add Pentest Billing tab and Stripe billing portal
- Add "Pentest Billing" as a second tab in SecuritySidebar, pointing to
the existing subscription management page
- Fix active-tab detection so Penetration Tests doesn't stay highlighted
when on the Billing sub-page
- Add createBillingPortalSession server action so active subscribers can
manage their payment method via Stripe's hosted portal
- Fix return URL to use NEXT_PUBLIC_BETTER_AUTH_URL (was using
NEXT_PUBLIC_APP_URL which isn't defined)
- Fix subscribe button copy to reflect actual price ($99/month)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(pentest): address PR review findings
P1 — billing auth: validate session and org membership in
checkAndChargePentestBilling before any DB/Stripe calls, so a caller
cannot trigger billing against an org they don't belong to.
P1 — billing order: move checkAndChargePentestBilling to after successful
run creation so a transient provider failure never charges the customer
without delivering a run. Threshold adjusted from `<` to `<=` so the
included-run count is still respected once the new run is counted in DB.
P2 — GitHub token key: integration-platform GitHub connections use OAuth2
and store the token under `access_token`; fix getGithubTokenForOrg to
read that field instead of the legacy PAT key `GITHUB_TOKEN`.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor(billing): lift stripeCustomerId to OrganizationBilling + Settings > Billing hub
- Add OrganizationBilling model (one per org, owns stripeCustomerId) so
future subscription products share a single Stripe customer
- PentestSubscription now relates to OrganizationBilling via FK instead
of owning stripeCustomerId directly
- New Settings > Billing page as the single hub for all app subscriptions
- Remove Pentest Billing tab from Security sidebar
- Delete old /security/penetration-tests/subscription page
- Update "Manage subscription" link to /settings/billing
- Add requireOrgMember() guard to all four billing server actions
(subscribeToPentestPlan, handleSubscriptionSuccess, createBillingPortalSession
were previously missing the cross-tenant auth check)
- Validate Stripe session ownership in handleSubscriptionSuccess:
reject if session customer doesn't match existing org billing record
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(webhook): handle checkout.session.completed to activate subscription server-side
Previously, PentestSubscription was only created when the user returned to
the /settings/billing success URL. If they closed the tab or the browser
crashed after Stripe Checkout, the subscription would never activate.
The webhook is now the primary activation path:
- checkout.session.completed → look up OrganizationBilling by stripeCustomerId,
retrieve full subscription, upsert PentestSubscription
- handleSubscriptionSuccess on the return URL becomes an idempotent fallback
(safe to call again since both paths use upsert)
Note: checkout.session.completed must be added to the Stripe webhook's
event subscriptions in the dashboard.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(billing): harden Stripe customer binding and URL construction
- Remove findStripeCustomerByDomain fallback in subscribeToPentestPlan:
organization.website is tenant-controlled so domain-based customer
reuse could let a malicious org bind to another company's Stripe
customer. Always create a fresh customer when no billing row exists.
- Strengthen handleSubscriptionSuccess session ownership check:
previously only rejected mismatched customers when an OrganizationBilling
row already existed. Now if no row exists (edge case — subscribeToPentestPlan
always creates one first), verify the Stripe customer's metadata.organizationId
matches before accepting the session.
- Fix Stripe return URLs to always be absolute: derive origin from
NEXT_PUBLIC_BETTER_AUTH_URL with a request-header fallback so Stripe
never receives a relative URL when the env var is unset.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(billing): deduplicate concurrent overage charges + preserve manual repo URL input
- Add Stripe idempotency key to paymentIntents.create scoped to
orgId + period start + run number; concurrent creates at the quota
boundary now deduplicate to a single charge instead of double-billing
- Show manual URL input alongside the GitHub repo selector so users
with more than 100 repos (beyond the first-page fetch) can still
paste a repo URL directly
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(billing): use per-run ID for overage charge idempotency key
The previous key used `runsThisPeriod` (an aggregate count), meaning
two concurrent creates could observe the same count and share the same
key — Stripe would deduplicate to a single PaymentIntent even when two
separate overage runs were billed.
Replace with `pentest-overage-{orgId}-{runId}` so each run gets a
globally unique idempotency key, eliminating the underbilling race.
Also include Codex-added tests for the GitHub connection UI flow.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
| 'provisioning', | ||
| 'cloning', | ||
| 'running', | ||
| ]; |
There was a problem hiding this comment.
Delete endpoint description claims auditor role is allowed
Low Severity
The inProgressStatus array is defined but never referenced anywhere in the file. The code uses the isReportInProgress function imported from ../lib instead, making this constant dead code.
Additional Locations (1)
…buse (#2217) - Remove returnUrl/returnBaseUrl parameters from subscribeToPentestPlan and createBillingPortalSession; URLs are now computed server-side from env vars + request host, preventing open-redirect phishing via direct server action invocation - Validate runId in checkAndChargePentestBilling against the DB to ensure the run exists and belongs to the org, preventing repeated overage charges via arbitrary fabricated runId strings - Remove duplicate PageLayout/PageHeader from billing page (layout already provides them for all settings routes) Co-authored-by: Claudio Fuentes <claudio@trycomp.ai> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| } else { | ||
| checkoutUrl = response.data?.checkoutUrl ?? fallbackCheckoutUrl; | ||
| } | ||
| await checkAndChargePentestBilling(organizationId, reportId); |
There was a problem hiding this comment.
Billing enforcement only client-side, backend has none
High Severity
checkAndChargePentestBilling is only called from the client-side hook after the backend API has already created the run at the provider. The NestJS createReport service method performs no billing or subscription check whatsoever. Any authenticated org member can call the POST /v1/security-penetration-tests API directly (bypassing the frontend) to create unlimited pentest runs without being billed or subscription-gated.
Additional Locations (1)
#2218) * refactor(ui): improve nav icons + remove overview drag-and-drop 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> * revert(ui): restore original compliance sidebar icons Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(billing): look up run by providerRunId not internal id 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> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: chasprowebdev <chasgarciaprowebdev@gmail.com>
|
🎉 This PR is included in version 1.88.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |


This is an automated pull request to release the candidate branch into production, which will trigger a deployment.
It was created by the [Production PR] action.