import type { LighthouseStrategy } from "@/server/lib/audit/types"; import { DEFAULT_AUDIT_PAGES, FREE_MAX_AUDIT_PAGES, MIN_AUDIT_PAGES, PAID_MAX_AUDIT_PAGES, } from "@/shared/audit-limits"; export type AuditLimitTier = "free" | "paid" | "self_hosted"; // The crawler runs on our Workers compute and isn't credit-metered, so these // per-tier bounds are the abuse control: free accounts cost nothing to create, // so they get one small audit at a time and a modest total budget. Paid gets // bounds sized for real sites rather than abuse (a payment method on file is // the deterrent). The cumulative bound is a hosted commercial policy, while // the per-audit page limit is also a technical Workflow/database ceiling. export const AUDIT_LIMITS: Record< AuditLimitTier, { maxPagesPerAudit: number; maxCapacityUnits: number; maxRunningAudits: number; } > = { free: { maxPagesPerAudit: FREE_MAX_AUDIT_PAGES, maxCapacityUnits: 2_000, maxRunningAudits: 1, }, paid: { maxPagesPerAudit: PAID_MAX_AUDIT_PAGES, maxCapacityUnits: 100_000, maxRunningAudits: Number.POSITIVE_INFINITY, }, self_hosted: { maxPagesPerAudit: PAID_MAX_AUDIT_PAGES, maxCapacityUnits: Number.POSITIVE_INFINITY, maxRunningAudits: Number.POSITIVE_INFINITY, }, }; export function clampAuditMaxPages(maxPages?: number) { return Math.min( Math.max(maxPages ?? DEFAULT_AUDIT_PAGES, MIN_AUDIT_PAGES), PAID_MAX_AUDIT_PAGES, ); } export function getEstimatedAuditCapacity(input: { maxPages?: number; lighthouseStrategy?: LighthouseStrategy; }) { const pagesTotal = clampAuditMaxPages(input.maxPages); const lighthouseStrategy = input.lighthouseStrategy ?? "auto"; // "auto" samples up to 10 pages, checked on mobile + desktop. const lighthouseChecks = lighthouseStrategy === "auto" ? 20 : 0; return { pagesTotal, lighthouseTotal: lighthouseChecks, total: pagesTotal + lighthouseChecks, }; }