diff --git a/src/app/agentshield/page.tsx b/src/app/agentshield/page.tsx index 302c222..be3c643 100644 --- a/src/app/agentshield/page.tsx +++ b/src/app/agentshield/page.tsx @@ -16,6 +16,7 @@ import { Download, Check } from "lucide-react"; +import TeamCheckoutBanner from "@/components/TeamCheckoutBanner"; export default function AgentShieldPage() { const [copied, setCopied] = useState(null); @@ -327,23 +328,76 @@ export default function AgentShieldPage() { - {/* Pricing Pill */} -
-
-

Upgrade to AgentShield Pro

-

- Includes native macOS/Windows menu-bar GUI, cloud audit log backup, and centralized policy sync. -

-
- - View Pricing ($15 / mo) - -
-
-
+ ); diff --git a/src/app/dbshield/page.tsx b/src/app/dbshield/page.tsx index eeff54a..2b2be88 100644 --- a/src/app/dbshield/page.tsx +++ b/src/app/dbshield/page.tsx @@ -21,6 +21,7 @@ import { Lock, ArrowRight } from "lucide-react"; +import TeamCheckoutBanner from "@/components/TeamCheckoutBanner"; interface Scenario { id: string; @@ -578,6 +579,65 @@ export default function DBShieldPage() { + + ); } diff --git a/src/app/mcp-starter-kit/page.tsx b/src/app/mcp-starter-kit/page.tsx index 5b7177e..a12db16 100644 --- a/src/app/mcp-starter-kit/page.tsx +++ b/src/app/mcp-starter-kit/page.tsx @@ -16,6 +16,7 @@ import { Sparkles, Lock } from "lucide-react"; +import { buildTeamProductCheckoutUrl } from "@/lib/checkout-urls.js"; export default function McpStarterKitPage() { const checkoutUrl = "https://checkout.dodopayments.com/buy/pdt_0NrFWlIkkreo5fOBIJWxI?quantity=1&redirect_url=https%3A%2F%2Fritualdev.in%2Fmcp-starter-kit%2Fdownload"; @@ -210,6 +211,85 @@ export default function McpStarterKitPage() { + {/* Enterprise MCP Connector Packs ($39-$99) & DFY Builds */} +
+
+
+
+ Pre-Built Production Connector Packs (One-Time Code Delivery) +
+

+ Or Grab Vertical MCP Connector Packs ($39 – $99) +

+
+ + Need Us to Build Your Custom MCP in 48h ($349+)? + + +
+ +
+ {[ + { + key: "mcp_pack_fintech_39", + name: "Fintech & SaaS Pack", + price: "$39", + desc: "Production MCP tools for Stripe, Dodo Payments, HubSpot CRM & Slack incident webhooks.", + }, + { + key: "mcp_pack_database_49", + name: "Database & Warehouse Pack", + price: "$49", + desc: "Read-only sandboxed MCP connectors for Postgres, MongoDB, ClickHouse & Redis.", + }, + { + key: "mcp_pack_devops_49", + name: "Cloud & DevOps Pack", + price: "$49", + desc: "IAM-scoped tools for Kubernetes pods/logs, AWS S3/CloudWatch, Docker & GitHub Actions.", + }, + { + key: "mcp_pack_all_99", + name: "All-Access MCP Bundle", + price: "$99", + desc: "Includes Fintech, Database & DevOps packs plus lifetime connector updates.", + highlight: true, + }, + ].map((pack) => ( +
+
+
+ {pack.name} + {pack.price} +
+

{pack.desc}

+
+ + Buy Pack ({pack.price}) + + +
+ ))} +
+
+ ); } diff --git a/src/app/pricing/page.tsx b/src/app/pricing/page.tsx index ee7aa7d..9826299 100644 --- a/src/app/pricing/page.tsx +++ b/src/app/pricing/page.tsx @@ -14,8 +14,13 @@ import { KeyRound, CreditCard, Wrench, + Database, + Layers, + Heart, + Boxes, + Zap, } from "lucide-react"; -import { buildCloudOrPrivateCheckoutUrl } from "@/lib/checkout-urls.js"; +import { buildCloudOrPrivateCheckoutUrl, buildTeamProductCheckoutUrl } from "@/lib/checkout-urls.js"; export default function PricingPage() { const [githubUsername, setGithubUsername] = useState(""); @@ -368,6 +373,233 @@ export default function PricingPage() { + {/* Section 3: Complete All-Product Revenue & Billing Directory */} +
+
+
+ All RitualDev Lab Earning & Self-Serve Payment Channels +
+

+ Every Paid Tier & Checkout Across the Suite +

+

+ Jump directly to checkout or tool configuration for DevShelf spotlights, DBShield Team, AgentShield Fleet, SkillPrism Redis, WebSecAuditor, MCP Packs, Pro Tools, and Partner Affiliates. +

+
+ +
+ {/* 1. DevShelf Spotlights */} +
+
+
+ + $9 – $79/mo +
+

DevShelf Feature Your Tool

+

+ Starter ($9), Launch Spotlight ($19), Category Exclusive ($39/mo), MCP Pro ($49/mo), Category Combo Pack ($79/mo) & Custom Sponsor. +

+
+ + Reserve DevShelf Slot + + +
+ + {/* 2. DBShield Team */} +
+
+
+ + $29 – $99/mo +
+

DBShield Team Guardrails

+

+ Hosted Slack/MS Teams #db-approvals relay ($29/mo) & DBShield Team Hub + Shared Redis ($99/mo). +

+
+
+ + DBShield Team ($99/mo) + + + + Explore DBShield Sandbox & $29/mo Relay → + +
+
+ + {/* 3. AgentShield & WebSecAuditor Team/Fleet */} +
+
+
+ + $19 – $49/seat +
+

AgentShield & WebSec Team

+

+ Team CI/CD PR Gate on private repos ($19/seat/mo) or Enterprise Fleet with SIEM + SAML SSO ($49/seat/mo). +

+
+ +
+ + {/* 4. SkillPrism Team Redis */} +
+
+
+ + $99/mo Hosted +
+

SkillPrism Team Redis VPC

+

+ Managed shared Redis token compaction cluster cutting Claude Code & Cursor tool prompt cost by 96.7%. +

+
+
+ + Hosted Redis Hub ($99/mo) + + + + Calculate Team Token ROI → + +
+
+ + {/* 5. MCP Starter Kit & Packs */} +
+
+
+ + $39 – $99 Once +
+

MCP Kits & Connector Packs

+

+ MCP Monetization Starter Kit ($49), Fintech ($39), Database ($49), DevOps ($49), All-Access ($99) & Turnkey ($500+). +

+
+
+ + MCP Starter Kit ($49) + + + + View Connector Packs ($39–$99) → + +
+
+ + {/* 6. Desktop & Browser Pro Suite */} +
+
+
+ + Pro Suite +
+

PromptShield, MockForge & FinePrint

+

+ Commercial Pro license for browser DLP firewall, production DB masking & legal contract redlines. +

+
+
+ + Ritual Pro License ($15/mo) + + +
+ PromptShield ·{" "} + MockForge ·{" "} + FinePrint +
+
+
+ + {/* 7. Affiliates & Partner Perks */} +
+
+
+ + Rev-Share / Bounties +
+

Developer Cloud Affiliate Hub

+

+ Tracked /go/* links for DigitalOcean ($200 credit), Railway, PostHog, Cloudflare, Hetzner, Neon & Sentry. +

+
+ + Browse DevShelf & /go Links + + +
+ + {/* 8. Donations & Grants */} +
+
+
+ + $1+ / ₹10+ +
+

Grants, Bounties & Donations

+

+ Flexible one-time or recurring open-source patronage via Dodo Payments (Cards, Apple Pay & Indian UPI). +

+
+ + Sponsor / Donate Any Amount + + +
+
+
+ {/* Dodo Payments Merchant of Record Notice */}
diff --git a/src/app/pricing/success/page.tsx b/src/app/pricing/success/page.tsx index 8a2eb31..3623ea4 100644 --- a/src/app/pricing/success/page.tsx +++ b/src/app/pricing/success/page.tsx @@ -4,6 +4,7 @@ import { Suspense } from "react"; import Link from "next/link"; import { useSearchParams } from "next/navigation"; import { CheckCircle2, ShieldCheck, Mail, ArrowRight, Cloud, KeyRound } from "lucide-react"; +import { TEAM_PRODUCT_CONFIG } from "@/lib/checkout-urls.js"; function PricingSuccessContent() { const searchParams = useSearchParams(); @@ -11,13 +12,17 @@ function PricingSuccessContent() { const product = (searchParams.get("product") || "team_relay_29").toLowerCase(); const isPrivateKit = product.includes("private") || product.includes("compliance"); + const isMcpPack = product.includes("mcp_pack"); + const matchedCfg = TEAM_PRODUCT_CONFIG[product]; const isTeamHub = product.includes("hub") || product.includes("99"); - const title = isPrivateKit - ? "Private Enterprise Compliance & Deployment Kit" - : isTeamHub - ? "Hosted Team Hub + Shared Redis Cache" - : "Hosted Team Relay Starter"; + const title = + matchedCfg?.label || + (isPrivateKit + ? "Private Enterprise Compliance & Deployment Kit" + : isTeamHub + ? "Hosted Team Hub + Shared Redis Cache" + : "Hosted Team Relay Starter"); return (
@@ -62,10 +67,16 @@ function PricingSuccessContent() {
  • 2. If you included your GitHub username during checkout, a collaborator invitation to the private compliance repository is sent automatically.
  • 3. Did not add your GitHub username yet? Forward your Dodo receipt ID to hello@ritualdev.in and we will invite you within 2 hours.
  • + ) : isMcpPack ? ( +
      +
    • 1. Dodo Payments verifies your transaction and emails your PDF GST/VAT receipt.
    • +
    • 2. Your signed download archive and repository access for the selected MCP Connector Pack are dispatched to your checkout email.
    • +
    • 3. Need custom API endpoints wrapped too? Forward your receipt to hello@ritualdev.in or visit /mcp-builder.
    • +
    ) : (
      -
    • 1. Dodo Payments dispatches a signed verification webhook to provision your Hosted Team Relay tenant.
    • -
    • 2. Your tenant relay URL, Slack/Teams app webhook endpoint, and setup snippet are emailed to your checkout email address.
    • +
    • 1. Dodo Payments dispatches a signed verification webhook to provision your Hosted Team / Governance tenant.
    • +
    • 2. Your tenant relay URL, Slack/Teams approval endpoint, policy token, or Redis connection snippet are emailed to your checkout email address.
    • 3. Meanwhile, install the open-source CLI anywhere without keys: npx @ritualdev-lab/agentshield init-claude
    )} @@ -76,9 +87,9 @@ function PricingSuccessContent() { Need priority Slack setup? Email hello@ritualdev.in
    - + - AgentShield Docs + View All Plans & Products
    diff --git a/src/app/skillprism/page.tsx b/src/app/skillprism/page.tsx index 7f148c6..fc1f529 100644 --- a/src/app/skillprism/page.tsx +++ b/src/app/skillprism/page.tsx @@ -13,6 +13,7 @@ import { TrendingDown, Layers } from "lucide-react"; +import TeamCheckoutBanner from "@/components/TeamCheckoutBanner"; export default function SkillPrismPage() { const [copied, setCopied] = useState(null); @@ -182,6 +183,63 @@ export default function SkillPrismPage() {
    + + ); } diff --git a/src/app/web-sec-auditor/page.tsx b/src/app/web-sec-auditor/page.tsx index 341763e..2e1eae3 100644 --- a/src/app/web-sec-auditor/page.tsx +++ b/src/app/web-sec-auditor/page.tsx @@ -10,6 +10,7 @@ import { AlertTriangle, Code2 } from "lucide-react"; +import TeamCheckoutBanner from "@/components/TeamCheckoutBanner"; export default function WebSecAuditorPage() { return ( @@ -109,6 +110,62 @@ export default function WebSecAuditorPage() { + + ); } diff --git a/src/components/TeamCheckoutBanner.tsx b/src/components/TeamCheckoutBanner.tsx new file mode 100644 index 0000000..4401834 --- /dev/null +++ b/src/components/TeamCheckoutBanner.tsx @@ -0,0 +1,213 @@ +"use client"; + +import { useState } from "react"; +import Link from "next/link"; +import { ArrowRight, Check, CreditCard, Lock } from "lucide-react"; +import { buildTeamProductCheckoutUrl, type TeamProductTierId } from "@/lib/checkout-urls.js"; + +export interface TeamCheckoutPlan { + tierKey: TeamProductTierId; + name: string; + price: string; + period: string; + badge: string; + description: string; + features: string[]; + ctaLabel: string; + featured?: boolean; + accent?: "cyan" | "emerald" | "purple" | "amber" | "rose"; +} + +interface TeamCheckoutBannerProps { + eyebrow: string; + heading: string; + subheading: string; + plans: TeamCheckoutPlan[]; + secondaryHref?: string; + secondaryLabel?: string; +} + +const ACCENT_MAP: Record< + NonNullable, + { border: string; badge: string; check: string; button: string } +> = { + cyan: { + border: "border-brand-cyan/50 shadow-[0_0_25px_rgba(56,189,248,0.12)]", + badge: "bg-cyan-500/10 text-brand-cyan border-cyan-500/30", + check: "text-brand-cyan", + button: "bg-gradient-to-r from-brand-cyan to-blue-500 text-slate-950 hover:opacity-95", + }, + emerald: { + border: "border-emerald-500/50 shadow-[0_0_25px_rgba(16,185,129,0.12)]", + badge: "bg-emerald-500/10 text-emerald-300 border-emerald-500/30", + check: "text-brand-neon", + button: "bg-gradient-to-r from-brand-green to-emerald-500 text-slate-950 hover:opacity-95", + }, + purple: { + border: "border-purple-500/50 shadow-[0_0_25px_rgba(168,85,247,0.12)]", + badge: "bg-purple-500/10 text-purple-300 border-purple-500/30", + check: "text-purple-400", + button: "bg-purple-600 hover:bg-purple-500 text-white", + }, + amber: { + border: "border-amber-500/50 shadow-[0_0_25px_rgba(245,158,11,0.12)]", + badge: "bg-amber-500/10 text-amber-300 border-amber-500/30", + check: "text-amber-400", + button: "bg-amber-400 hover:bg-amber-300 text-slate-950", + }, + rose: { + border: "border-rose-500/50 shadow-[0_0_25px_rgba(244,63,94,0.12)]", + badge: "bg-rose-500/10 text-rose-300 border-rose-500/30", + check: "text-rose-400", + button: "bg-rose-500 hover:bg-rose-400 text-white", + }, +}; + +export default function TeamCheckoutBanner({ + eyebrow, + heading, + subheading, + plans, + secondaryHref = "/pricing/", + secondaryLabel = "Compare All Plans & Products", +}: TeamCheckoutBannerProps) { + const [workEmail, setWorkEmail] = useState(""); + const [githubUsername, setGithubUsername] = useState(""); + const [companyName, setCompanyName] = useState(""); + + const launchCheckout = (tierKey: TeamProductTierId) => { + const url = buildTeamProductCheckoutUrl({ + tier: tierKey, + customerEmail: workEmail, + githubUsername, + companyName, + }); + window.open(url, "_blank", "noopener,noreferrer"); + }; + + return ( +
    +
    +
    +
    + + {eyebrow} +
    +

    + {heading} +

    +

    + {subheading} +

    +
    + + + {secondaryLabel} + + +
    + + {/* Optional Pre-fill Inputs */} +
    +
    + + setWorkEmail(e.target.value)} + placeholder="team@company.com" + className="w-full px-3 py-2 rounded-xl bg-slate-950 border border-slate-800 text-white placeholder-slate-500 focus:outline-none focus:border-brand-cyan" + /> +
    +
    + + setCompanyName(e.target.value)} + placeholder="Acme Engineering" + className="w-full px-3 py-2 rounded-xl bg-slate-950 border border-slate-800 text-white placeholder-slate-500 focus:outline-none focus:border-brand-cyan" + /> +
    +
    + + setGithubUsername(e.target.value)} + placeholder="octocat" + className="w-full px-3 py-2 rounded-xl bg-slate-950 border border-slate-800 text-white placeholder-slate-500 focus:outline-none focus:border-brand-cyan" + /> +
    +
    + + {/* Plans Grid */} +
    = 4 + ? "md:grid-cols-2 xl:grid-cols-4" + : plans.length === 3 + ? "md:grid-cols-3" + : "md:grid-cols-2" + } gap-5`} + > + {plans.map((plan) => { + const style = ACCENT_MAP[plan.accent || (plan.featured ? "cyan" : "emerald")]; + return ( +
    +
    +
    + + {plan.badge} + +
    +

    {plan.name}

    +
    + {plan.price} + {plan.period} +
    +

    {plan.description}

    +
      + {plan.features.map((feat) => ( +
    • + + {feat} +
    • + ))} +
    +
    + + +
    + ); + })} +
    + +
    + + + CLI stays 100% open source ($0 forever). Payments processed via Dodo Payments (Cards, Apple Pay, Google Pay, UPI & GST invoices) with automated webhook provisioning at /api/webhooks/dodo. + +
    +
    + ); +} diff --git a/src/lib/checkout-urls.d.ts b/src/lib/checkout-urls.d.ts index 6c31ead..942164a 100644 --- a/src/lib/checkout-urls.d.ts +++ b/src/lib/checkout-urls.d.ts @@ -47,12 +47,45 @@ export interface PreparedPartnerOrder { summary?: string; } +export type TeamProductTierId = + | "team_relay_29" + | "team_hub_99" + | "private_compliance_kit" + | "dbshield_team_29" + | "dbshield_team_99" + | "skillprism_team_99" + | "agentshield_team_19" + | "agentshield_enterprise_49" + | "websec_team_19" + | "ritual_pro_15" + | "mcp_starter_49" + | "mcp_pack_fintech_39" + | "mcp_pack_database_49" + | "mcp_pack_devops_49" + | "mcp_pack_all_99" + | "turnkey_starter_250" + | "turnkey_pro_750" + | "turnkey_enterprise_1750"; + +export interface TeamProductCheckoutInput { + tier?: TeamProductTierId | string; + customerEmail?: string; + githubUsername?: string; + companyName?: string; +} + export interface CloudOrPrivateCheckoutInput { tier?: "team_relay_29" | "team_hub_99" | "private_compliance_kit"; customerEmail?: string; githubUsername?: string; } +export const DODO_PRODUCT_IDS: Record; +export const TEAM_PRODUCT_CONFIG: Record< + string, + { id: string; productId: string; flexAmountUsd?: string; extraParams?: Record; label: string; redirectUrl: string } +>; + export function resolvePartnerTierPricing( tier?: string, customAmountUsd?: number | string @@ -61,4 +94,5 @@ export function preparePartnerOrder(body: unknown): PreparedPartnerOrder; export function buildAuditCheckoutUrl(input: AuditCheckoutInput): string; export function buildMcpCheckoutUrl(input: McpCheckoutInput): string; export function buildPartnerCheckoutUrl(input: PartnerCheckoutInput): string; +export function buildTeamProductCheckoutUrl(input: TeamProductCheckoutInput): string; export function buildCloudOrPrivateCheckoutUrl(input: CloudOrPrivateCheckoutInput): string; diff --git a/src/lib/checkout-urls.js b/src/lib/checkout-urls.js index f3aea87..e17132d 100644 --- a/src/lib/checkout-urls.js +++ b/src/lib/checkout-urls.js @@ -7,6 +7,26 @@ const DODO_AUDIT_STARTER_199 = "pdt_0NrFWnRHHEI72iaB8AC9r"; const DODO_AUDIT_PRO_399 = "pdt_0NrFWnSQHfJhuHs4Y9Xmh"; const DODO_SERVICE_FLEX = "pdt_0NpjONGugY5QkrFDUaPva"; +const DODO_AGENTSHIELD_TEAM_19 = "pdt_0NpjONLXnMYR9e2SUlYJt"; +const DODO_AGENTSHIELD_ENTERPRISE_49 = "pdt_0NpjONNytUpW7gzjoDlYW"; +const DODO_RITUAL_PRO_15 = "pdt_0NrFSkF5XLgBppfQRxgXN"; +const DODO_RITUAL_TEAM_99 = "pdt_0NrFSmrXT8zU2u5BKGJ7y"; +const DODO_MCP_STARTER_49 = "pdt_0NrFWlIkkreo5fOBIJWxI"; +const DODO_MCP_PACK_FLEX = "pdt_0NpjONEJnu5OcWhncWF68"; +const DODO_TURNKEY_DEPOSIT = "pdt_0NpjOJVkkh7Mryrzm6ro9"; + +export const DODO_PRODUCT_IDS = { + DODO_AUDIT_STARTER_199, + DODO_AUDIT_PRO_399, + DODO_SERVICE_FLEX, + DODO_AGENTSHIELD_TEAM_19, + DODO_AGENTSHIELD_ENTERPRISE_49, + DODO_RITUAL_PRO_15, + DODO_RITUAL_TEAM_99, + DODO_MCP_STARTER_49, + DODO_MCP_PACK_FLEX, + DODO_TURNKEY_DEPOSIT, +}; export function buildAuditCheckoutUrl({ orderId, @@ -244,40 +264,170 @@ export function preparePartnerOrder(body) { }; } -export function buildCloudOrPrivateCheckoutUrl({ +export const TEAM_PRODUCT_CONFIG = { + team_relay_29: { + id: "team_relay_29", + productId: DODO_SERVICE_FLEX, + flexAmountUsd: "29", + label: "Hosted Team Relay ($29/mo)", + redirectUrl: "https://ritualdev.in/pricing/success/?product=team_relay_29", + }, + team_hub_99: { + id: "team_hub_99", + productId: DODO_RITUAL_TEAM_99, + label: "Hosted Team Hub + Shared Redis Cache ($99/mo)", + redirectUrl: "https://ritualdev.in/pricing/success/?product=team_hub_99", + }, + private_compliance_kit: { + id: "private_compliance_kit", + productId: DODO_AUDIT_STARTER_199, + label: "Private Compliance Pack ($199 one-time)", + redirectUrl: "https://ritualdev.in/pricing/success/?product=private_compliance_kit", + }, + dbshield_team_29: { + id: "dbshield_team_29", + productId: DODO_SERVICE_FLEX, + flexAmountUsd: "29", + label: "DBShield Team Slack/Teams Approval Relay ($29/mo)", + redirectUrl: "https://ritualdev.in/pricing/success/?product=dbshield_team_29", + }, + dbshield_team_99: { + id: "dbshield_team_99", + productId: DODO_RITUAL_TEAM_99, + label: "DBShield Team + Shared Redis Governance ($99/mo)", + redirectUrl: "https://ritualdev.in/pricing/success/?product=dbshield_team_99", + }, + skillprism_team_99: { + id: "skillprism_team_99", + productId: DODO_RITUAL_TEAM_99, + label: "SkillPrism Hosted Shared Redis VPC Cluster ($99/mo)", + redirectUrl: "https://ritualdev.in/pricing/success/?product=skillprism_team_99", + }, + agentshield_team_19: { + id: "agentshield_team_19", + productId: DODO_AGENTSHIELD_TEAM_19, + label: "AgentShield Team & CI/CD Gate ($19/seat/mo)", + redirectUrl: "https://ritualdev.in/pricing/success/?product=agentshield_team_19", + }, + agentshield_enterprise_49: { + id: "agentshield_enterprise_49", + productId: DODO_AGENTSHIELD_ENTERPRISE_49, + label: "AgentShield Enterprise Fleet ($49/seat/mo)", + redirectUrl: "https://ritualdev.in/pricing/success/?product=agentshield_enterprise_49", + }, + websec_team_19: { + id: "websec_team_19", + productId: DODO_AGENTSHIELD_TEAM_19, + label: "WebSecAuditor Team PR Review Gate ($19/seat/mo)", + redirectUrl: "https://ritualdev.in/pricing/success/?product=websec_team_19", + }, + ritual_pro_15: { + id: "ritual_pro_15", + productId: DODO_RITUAL_PRO_15, + label: "Ritual Pro Individual Suite License ($15/mo)", + redirectUrl: "https://ritualdev.in/pricing/success/?product=ritual_pro_15", + }, + mcp_starter_49: { + id: "mcp_starter_49", + productId: DODO_MCP_STARTER_49, + label: "MCP Monetization Starter Kit ($49 one-time)", + redirectUrl: "https://ritualdev.in/mcp-starter-kit/download", + }, + mcp_pack_fintech_39: { + id: "mcp_pack_fintech_39", + productId: DODO_MCP_PACK_FLEX, + extraParams: { pack: "fintech" }, + label: "Fintech & SaaS Connector MCP Pack ($39)", + redirectUrl: "https://ritualdev.in/pricing/success/?product=mcp_pack_fintech_39", + }, + mcp_pack_database_49: { + id: "mcp_pack_database_49", + productId: DODO_MCP_PACK_FLEX, + extraParams: { pack: "database" }, + label: "Enterprise Database & Warehouse MCP Pack ($49)", + redirectUrl: "https://ritualdev.in/pricing/success/?product=mcp_pack_database_49", + }, + mcp_pack_devops_49: { + id: "mcp_pack_devops_49", + productId: DODO_MCP_PACK_FLEX, + extraParams: { pack: "devops" }, + label: "Cloud & Kubernetes DevOps MCP Pack ($49)", + redirectUrl: "https://ritualdev.in/pricing/success/?product=mcp_pack_devops_49", + }, + mcp_pack_all_99: { + id: "mcp_pack_all_99", + productId: DODO_MCP_PACK_FLEX, + extraParams: { pack: "all_access" }, + label: "All-Access Enterprise MCP Bundle ($99)", + redirectUrl: "https://ritualdev.in/pricing/success/?product=mcp_pack_all_99", + }, + turnkey_starter_250: { + id: "turnkey_starter_250", + productId: DODO_TURNKEY_DEPOSIT, + extraParams: { tier: "starter", deposit: "250" }, + label: "Starter Turnkey MCP Deposit ($250 / $500 total)", + redirectUrl: "https://ritualdev.in/mcp-builder/?success=true&tier=turnkey_starter", + }, + turnkey_pro_750: { + id: "turnkey_pro_750", + productId: DODO_TURNKEY_DEPOSIT, + extraParams: { tier: "pro", deposit: "750" }, + label: "Pro Multi-API Turnkey MCP Deposit ($750 / $1,500 total)", + redirectUrl: "https://ritualdev.in/mcp-builder/?success=true&tier=turnkey_pro", + }, + turnkey_enterprise_1750: { + id: "turnkey_enterprise_1750", + productId: DODO_TURNKEY_DEPOSIT, + extraParams: { tier: "enterprise", deposit: "1750" }, + label: "Enterprise Custom MCP Deposit ($1,750 / $3,500 total)", + redirectUrl: "https://ritualdev.in/mcp-builder/?success=true&tier=turnkey_enterprise", + }, +}; + +export function buildTeamProductCheckoutUrl({ tier = "team_relay_29", customerEmail = "", githubUsername = "", + companyName = "", }) { - const amountMap = { - team_relay_29: "29", - team_hub_99: "99", - private_compliance_kit: "199", - }; - const amountUsd = amountMap[tier] || "29"; - const productId = tier === "private_compliance_kit" ? DODO_AUDIT_STARTER_199 : DODO_SERVICE_FLEX; + const cfg = TEAM_PRODUCT_CONFIG[tier] || TEAM_PRODUCT_CONFIG.team_relay_29; const params = new URLSearchParams(); params.set("quantity", "1"); - if (productId === DODO_SERVICE_FLEX) { - params.set("paymentAmount", amountUsd); - params.set("amount", amountUsd); + + if (cfg.flexAmountUsd) { + params.set("paymentAmount", cfg.flexAmountUsd); + params.set("amount", cfg.flexAmountUsd); params.set("paymentCurrency", "USD"); params.set("currency", "USD"); params.set("singlePage", "true"); params.set("product_type", "digital"); params.set("shipping_required", "false"); } + if (cfg.extraParams) { + for (const [k, v] of Object.entries(cfg.extraParams)) { + params.set(k, v); + } + } if (customerEmail) { params.set("email", customerEmail.trim().toLowerCase()); params.set("customer_email", customerEmail.trim().toLowerCase()); } + if (companyName) { + params.set("fullName", companyName.trim().slice(0, 120)); + params.set("metadata_company", companyName.trim().slice(0, 120)); + } if (githubUsername) { params.set("metadata_github_username", githubUsername.trim().replace(/^@/, "")); } - params.set("metadata_tier", tier); - params.set( - "redirect_url", - `https://ritualdev.in/pricing/success/?product=${encodeURIComponent(tier)}` - ); - return `https://checkout.dodopayments.com/buy/${productId}?${params.toString()}`; + params.set("metadata_tier", cfg.id); + params.set("redirect_url", cfg.redirectUrl); + return `https://checkout.dodopayments.com/buy/${cfg.productId}?${params.toString()}`; +} + +export function buildCloudOrPrivateCheckoutUrl({ + tier = "team_relay_29", + customerEmail = "", + githubUsername = "", +}) { + return buildTeamProductCheckoutUrl({ tier, customerEmail, githubUsername }); } diff --git a/src/lib/dodo-webhook.js b/src/lib/dodo-webhook.js index 1aa7fca..db16e8d 100644 --- a/src/lib/dodo-webhook.js +++ b/src/lib/dodo-webhook.js @@ -246,7 +246,8 @@ export async function handleDodoWebhookEvent({ rawBody, headers, env }) { metadata?.githubHandle || metadata?.sponsorHandle || metadata?.github; - const tier = metadata?.tier || metadata?.package || metadata?.plan || "hosted_relay"; + const productId = data?.product_id || data?.product_cart?.[0]?.product_id || ""; + const tier = metadata?.tier || metadata?.package || metadata?.plan || productId || "hosted_relay"; const toolName = metadata?.toolName || metadata?.tool_name; const toolUrl = metadata?.toolUrl || metadata?.tool_url || metadata?.url; const orderId = metadata?.orderId || ""; @@ -276,8 +277,34 @@ export async function handleDodoWebhookEvent({ rawBody, headers, env }) { fulfillmentNote = invite.invited ? `GitHub collaborator invited (@${invite.username} -> ${env.PRIVATE_COMPLIANCE_REPO})` : `GitHub invite skipped/failed: ${invite.reason || `HTTP ${invite.status}`}`; - } else if (tier.includes("relay") || tier.includes("team")) { - fulfillmentNote = `Provision Hosted Cloud Relay for ${customerEmail} (tier: ${tier})`; + } else if ( + tier.includes("dbshield") || + tier.includes("skillprism") || + tier.includes("relay") || + tier.includes("team") || + tier.includes("hub") || + tier.includes("enterprise") || + tier.includes("websec") || + productId === "pdt_0NpjONLXnMYR9e2SUlYJt" || + productId === "pdt_0NpjONNytUpW7gzjoDlYW" || + productId === "pdt_0NrFSmrXT8zU2u5BKGJ7y" + ) { + fulfillmentNote = `Provision Hosted Team Relay / Governance tenant for ${customerEmail} (tier: ${tier})`; + } else if ( + tier.includes("mcp") || + tier.includes("turnkey") || + productId === "pdt_0NrFWlIkkreo5fOBIJWxI" || + productId === "pdt_0NpjONEJnu5OcWhncWF68" || + productId === "pdt_0NpjOJVkkh7Mryrzm6ro9" + ) { + fulfillmentNote = `Deliver MCP Kit / Turnkey kickoff for ${customerEmail} (tier: ${tier})`; + } else if ( + tier.includes("audit") || + orderId.startsWith("AUDIT-") || + productId === "pdt_0NrFWnRHHEI72iaB8AC9r" || + productId === "pdt_0NrFWnSQHfJhuHs4Y9Xmh" + ) { + fulfillmentNote = `Queue Pre-Launch Security Audit for ${customerEmail} (tier: ${tier})`; } await dispatchOrderWebhook( diff --git a/tests/checkout-functions.test.mjs b/tests/checkout-functions.test.mjs index 5862310..94c942d 100644 --- a/tests/checkout-functions.test.mjs +++ b/tests/checkout-functions.test.mjs @@ -1,6 +1,6 @@ import assert from "node:assert/strict"; import { describe, it } from "node:test"; -import { buildAuditCheckoutUrl, buildMcpCheckoutUrl, buildPartnerCheckoutUrl, buildCloudOrPrivateCheckoutUrl } from "../src/lib/checkout-urls.js"; +import { buildAuditCheckoutUrl, buildMcpCheckoutUrl, buildPartnerCheckoutUrl, buildCloudOrPrivateCheckoutUrl, buildTeamProductCheckoutUrl } from "../src/lib/checkout-urls.js"; import { verifyDodoWebhookSignature, handleDodoWebhookEvent } from "../src/lib/dodo-webhook.js"; import { onRequestPost as mcpOrderPost } from "../functions/api/mcp-order.js"; import { onRequestPost as auditOrderPost } from "../functions/api/audit-order.js"; @@ -316,4 +316,65 @@ describe("Storefront Checkout URL Builders & Cloudflare Pages Functions", () => }); assert.equal(calledNext, true); }); + + it("builds team and suite checkout URLs for DBShield, AgentShield, SkillPrism, MCP Packs, and Turnkey deposits", async () => { + const db29 = buildTeamProductCheckoutUrl({ tier: "dbshield_team_29", customerEmail: "dba@acme.io" }); + assert.ok(db29.includes("paymentAmount=29")); + assert.ok(db29.includes("metadata_tier=dbshield_team_29")); + + const db99 = buildTeamProductCheckoutUrl({ tier: "dbshield_team_99", companyName: "Acme Corp" }); + assert.ok(db99.includes("pdt_0NrFSmrXT8zU2u5BKGJ7y")); + assert.ok(db99.includes("metadata_tier=dbshield_team_99")); + + const sp99 = buildTeamProductCheckoutUrl({ tier: "skillprism_team_99" }); + assert.ok(sp99.includes("pdt_0NrFSmrXT8zU2u5BKGJ7y")); + assert.ok(sp99.includes("skillprism_team_99")); + + const as19 = buildTeamProductCheckoutUrl({ tier: "agentshield_team_19" }); + assert.ok(as19.includes("pdt_0NpjONLXnMYR9e2SUlYJt")); + + const as49 = buildTeamProductCheckoutUrl({ tier: "agentshield_enterprise_49" }); + assert.ok(as49.includes("pdt_0NpjONNytUpW7gzjoDlYW")); + + const pack99 = buildTeamProductCheckoutUrl({ tier: "mcp_pack_all_99" }); + assert.ok(pack99.includes("pdt_0NpjONEJnu5OcWhncWF68")); + assert.ok(pack99.includes("pack=all_access")); + + const tk250 = buildTeamProductCheckoutUrl({ tier: "turnkey_starter_250" }); + assert.ok(tk250.includes("pdt_0NpjOJVkkh7Mryrzm6ro9")); + assert.ok(tk250.includes("deposit=250")); + + const pro15 = buildTeamProductCheckoutUrl({ tier: "ritual_pro_15" }); + assert.ok(pro15.includes("pdt_0NrFSkF5XLgBppfQRxgXN")); + + // Verify webhook recognizes product ID fallback even without explicit tier metadata + const crypto = await import("node:crypto"); + const rawSecret = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); + const secretB64 = `whsec_${Buffer.from(rawSecret).toString("base64")}`; + const webhookId = "msg_team_99"; + const ts = Math.floor(Date.now() / 1000).toString(); + const rawBody = JSON.stringify({ + type: "subscription.active", + data: { + subscription_id: "sub_db_99", + product_id: "pdt_0NrFSmrXT8zU2u5BKGJ7y", + total_amount: 9900, + currency: "USD", + customer: { email: "infra@acme.io" }, + metadata: {}, + }, + }); + const sig = crypto.createHmac("sha256", rawSecret).update(`${webhookId}.${ts}.${rawBody}`).digest("base64"); + const res = await handleDodoWebhookEvent({ + rawBody, + headers: new Headers({ + "webhook-id": webhookId, + "webhook-timestamp": ts, + "webhook-signature": `v1,${sig}`, + }), + env: { DODO_WEBHOOK_SECRET: secretB64 }, + }); + assert.equal(res.ok, true); + assert.ok(res.fulfillmentNote.includes("Provision Hosted Team Relay / Governance tenant")); + }); });