From 1bf1b851b0ada8c714d4aca5976df706022ddfd3 Mon Sep 17 00:00:00 2001 From: Waleed Date: Fri, 6 Nov 2026 12:07:57 -0800 Subject: [PATCH 1/3] fix(billing): refuse Stripe checkout for AWS Marketplace-billed customers (#9748) * fix(billing): refuse Stripe checkout for AWS Marketplace-billed customers AWS bills a Marketplace customer, and AWS's SaaS guidelines require a listed product to be billed entirely through its Marketplace dimensions. A Marketplace-billed organization or account looks Free to Stripe, so a Stripe checkout would start a second, real subscription. Until now only a client gate stood in the way, and it failed open: a failed license lookup reported "not Marketplace-billed" and showed Stripe plans, with no retry short of a reload. Server: authorizeSubscriptionReference (organization references) and assertPersonalCheckoutAllowed (personal references) now refuse an upgrade with 409 when the reference holds a Marketplace license that is not inactive, only where AWS_MARKETPLACE_PRODUCT_CODE is set. The personal check lives in assertPersonalCheckoutAllowed because the Better Auth Stripe plugin never calls authorizeReference for a personal reference, so a check there would never run for one. Other actions, and staff Enterprise provisioning, are unaffected. Client: useAwsMarketplaceBilling exposes isResolved, isError, isRetrying and retry, and an unknown billing state now gates plan changes. The billing page hides "Explore plans" until the lookup resolves; the upgrade page shows "Workspace plans unavailable" with a "Try again" chip when the lookup fails. * fix(billing): keep the Marketplace lookup retry stable across renders --- .../settings/components/billing/billing.tsx | 2 +- .../upgrade/hooks/use-upgrade-state.ts | 9 +- .../[workspaceId]/upgrade/upgrade.tsx | 20 ++- .../hooks/queries/aws-marketplace.test.tsx | 74 ++++++++ apps/sim/hooks/queries/aws-marketplace.ts | 14 +- apps/sim/lib/billing/authorization.ts | 31 +++- .../checkout-guard.integration.ts | 168 ++++++++++++++++++ .../lib/billing/aws-marketplace/repository.ts | 24 +++ 8 files changed, 331 insertions(+), 11 deletions(-) create mode 100644 apps/sim/hooks/queries/aws-marketplace.test.tsx create mode 100644 apps/sim/lib/billing/aws-marketplace/checkout-guard.integration.ts diff --git a/apps/sim/app/workspace/[workspaceId]/settings/components/billing/billing.tsx b/apps/sim/app/workspace/[workspaceId]/settings/components/billing/billing.tsx index d0fbd308b03..0105c89b89d 100644 --- a/apps/sim/app/workspace/[workspaceId]/settings/components/billing/billing.tsx +++ b/apps/sim/app/workspace/[workspaceId]/settings/components/billing/billing.tsx @@ -521,8 +521,8 @@ export function Billing({ scope, organizationId, creditUsageHref }: BillingProps {!subscription.isEnterprise && + marketplaceBilling.isResolved && !billedThroughMarketplace && - !marketplaceBilling.isPending && (canExplorePlans && upgradeHref ? (