@api-doctor/cli 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/install.ts","../src/providers/resend/manifest.ts","../src/providers/supabase/manifest.ts","../src/providers/auth0/manifest.ts","../src/providers/firebase/manifest.ts","../src/providers/lovable/manifest.ts","../src/providers/browserbase/manifest.ts","../src/providers/openai-cua/manifest.ts","../src/providers/index.ts","../src/reporter/animate.ts","../src/reporter/json-writer.ts","../src/constants.ts","../src/providers/resend/rules/webhook-signature.ts","../src/providers/resend/rules/api-key-hardcoded.ts","../src/providers/resend/rules/api-key-in-client-bundle.ts","../src/providers/resend/utils.ts","../src/providers/resend/rules/marketing-via-batch-send.ts","../src/providers/resend/rules/marketing-missing-unsubscribe.ts","../src/providers/resend/rules/test-domain-in-production-path.ts","../src/providers/resend/rules/from-address-not-friendly-format.ts","../src/providers/resend/rules/batch-size-not-enforced.ts","../src/providers/resend/rules/missing-idempotency-key.ts","../src/providers/resend/rules/no-error-code-mapping.ts","../src/providers/resend/rules/webhook-no-idempotency.ts","../src/providers/resend/rules/missing-tags.ts","../src/providers/resend/rules/request-id-not-logged.ts","../src/providers/supabase/utils.ts","../src/providers/supabase/rules/scope-queries-by-tenant-column.ts","../src/providers/supabase/rules/validate-uuid-columns.ts","../src/providers/supabase/rules/order-by-timestamp-not-identity.ts","../src/providers/supabase/rules/consistent-input-length-limits.ts","../src/providers/supabase/rules/idempotent-mutations.ts","../src/providers/supabase/rules/fail-fast-env-validation.ts","../src/providers/supabase/rules/no-user-metadata-authz.ts","../src/providers/supabase/rules/single-without-error-check.ts","../src/providers/supabase/rules/non-atomic-replace-pattern.ts","../src/providers/supabase/rules/unchecked-mutation-error.ts","../src/providers/supabase/rules/realtime-missing-filter.ts","../src/providers/supabase/rules/storage-error-not-surfaced.ts","../src/providers/auth0/rules/required-audience-validation.ts","../src/providers/auth0/rules/no-account-link-without-verified-email.ts","../src/providers/auth0/rules/dead-claim-verification-check.ts","../src/providers/auth0/rules/jwks-refresh-on-unknown-kid.ts","../src/providers/firebase/utils.ts","../src/providers/firebase/rules/missing-app-check.ts","../src/providers/firebase/rules/unhandled-auth-popup-rejection.ts","../src/providers/firebase/rules/rtdb-list-read-for-single-item.ts","../src/providers/firebase/rules/unvalidated-external-data-to-rtdb.ts","../src/providers/firebase/rules/rtdb-batch-write-not-atomic.ts","../src/providers/firebase/rules/rtdb-listener-error-not-handled.ts","../src/providers/firebase/rules/effect-deps-whole-user-object.ts","../src/providers/firebase/rules/rtdb-write-promise-not-handled.ts","../src/providers/lovable/utils.ts","../src/providers/lovable/rules/no-client-side-secret-fetch.ts","../src/providers/lovable/rules/paid-flag-without-edge-function.ts","../src/providers/lovable/rules/expiry-column-never-checked.ts","../src/providers/lovable/rules/silent-catch-on-provider-call.ts","../src/providers/browserbase/utils.ts","../src/providers/browserbase/rules/no-conditional-authz-on-anonymous-user.ts","../src/providers/browserbase/rules/no-connect-url-in-api-response.ts","../src/providers/browserbase/rules/session-id-requires-ownership-check.ts","../src/providers/browserbase/rules/no-concurrent-shared-context.ts","../src/providers/browserbase/rules/mobile-device-requires-os-setting.ts","../src/providers/browserbase/rules/use-typed-exception-status-not-substring.ts","../src/providers/browserbase/rules/release-session-on-connect-failure.ts","../src/providers/browserbase/rules/dont-stack-custom-retry-on-sdk-retry.ts","../src/providers/browserbase/rules/no-overbroad-error-substring-match.ts","../src/providers/browserbase/rules/use-sdk-not-raw-requests.ts","../src/providers/browserbase/rules/centralize-request-release.ts","../src/providers/openai-cua/rules/no-domain-allowlist.ts","../src/providers/openai-cua/rules/scroll-delta-default-zero.ts","../src/providers/openai-cua/rules/structured-step-metadata-not-text-json.ts","../src/providers/openai-cua/rules/no-blind-safety-check-ack.ts","../src/providers/openai-cua/utils.ts","../src/providers/openai-cua/rules/retry-transient-turn-errors.ts","../src/providers/openai-cua/rules/check-response-status-incomplete.ts","../src/providers/openai-cua/rules/set-safety-identifier.ts","../src/plugin/index.ts","../src/plugin/rule-registry.ts","../src/reporter/snippet.ts","../src/types.ts","../src/reporter/report-builder.ts","../src/scanner.ts","../src/detector.ts","../src/reporter/markdown.ts","../src/reporter/terminal.ts","../src/reporter/verbose.ts","../src/unsupported-packages.ts","../src/reporter/index.ts","../src/telemetry.ts","../src/run-history.ts"],"sourcesContent":["/**\n * CLI entry point: parses arguments with commander, runs the scan, emits output\n * in the requested mode, and exits with a CI-friendly status code.\n *\n * Exit codes (ESLint convention):\n * 0 — no errors, and warnings within the --max-warnings threshold\n * 1 — errors found, or warnings exceeded --max-warnings\n * 2 — tool-level failure (unreadable directory, oxlint crash, bad flag)\n */\nimport { Command } from 'commander';\nimport { readFileSync } from 'node:fs';\nimport { dirname, join, relative, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { installAgentFiles } from './install.js';\nimport { providers } from './providers/index.js';\nimport { createSpinner } from './reporter/animate.js';\nimport {\n DEFAULT_REPORT_DIR,\n DEFAULT_REPORT_FILE,\n} from './reporter/json-writer.js';\nimport { buildReport } from './reporter/report-builder.js';\nimport { countErrors, emitReport, type OutputFormat } from './reporter/index.js';\nimport { scan, ScanError } from './scanner.js';\nimport { trackError, trackInstall, trackRun } from './telemetry.js';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pkg = JSON.parse(\n readFileSync(join(__dirname, '../package.json'), 'utf-8'),\n) as { version: string };\n\nconst VALID_FORMATS: OutputFormat[] = ['json', 'markdown'];\n\ninterface CliOptions {\n quiet?: boolean;\n verbose?: boolean;\n format?: string;\n output?: string;\n /** commander sets this to false when --no-report is passed. */\n report?: boolean;\n maxWarnings?: string;\n provider?: string;\n listProviders?: boolean;\n /** commander sets this to false when --no-telemetry is passed. */\n telemetry?: boolean;\n}\n\nfunction fail(message: string): never {\n console.error(`api-doctor: ${message}`);\n process.exit(2);\n}\n\nconst program = new Command();\n\nprogram\n .name('api-doctor')\n .description('Verification rules for AI-generated API integrations')\n .version(pkg.version)\n .argument('[directory]', 'Project directory to scan', '.')\n .option('--quiet', 'Print only the score and report path')\n .option('--verbose', 'Print every finding inline with code snippets')\n .option('--format <format>', 'Emit structured output to stdout (json|markdown)')\n .option('--output <path>', `Report file location (default: ${DEFAULT_REPORT_DIR}/${DEFAULT_REPORT_FILE})`)\n .option('--no-report', 'Do not write the report file')\n .option('--max-warnings <n>', 'Exit with code 1 if warnings exceed this number')\n .option('--provider <names>', 'Comma-separated providers to scan (e.g. resend)')\n .option('--list-providers', 'List supported Node.js API providers')\n .option('--no-telemetry', 'Disable anonymous usage telemetry')\n .action(async (directory: string, opts: CliOptions) => {\n const noTelemetry = opts.telemetry === false;\n\n if (opts.listProviders) {\n for (const p of providers) {\n console.log(`${p.name} — ${p.displayName}`);\n }\n process.exit(0);\n }\n\n let format: OutputFormat | undefined;\n if (opts.format) {\n if (!VALID_FORMATS.includes(opts.format as OutputFormat)) {\n fail(`unknown --format \"${opts.format}\" (expected json or markdown)`);\n }\n format = opts.format as OutputFormat;\n }\n\n let maxWarnings: number | undefined;\n if (opts.maxWarnings !== undefined) {\n maxWarnings = Number(opts.maxWarnings);\n if (!Number.isInteger(maxWarnings) || maxWarnings < 0) {\n fail(`--max-warnings expects a non-negative integer, got \"${opts.maxWarnings}\"`);\n }\n }\n\n const onlyProviders = opts.provider\n ? opts.provider.split(',').map((s) => s.trim()).filter(Boolean)\n : undefined;\n\n const start = performance.now();\n\n try {\n const spinner = createSpinner('Scanning for API integrations…');\n let scanOutput;\n try {\n scanOutput = await scan(directory, { onlyProviders });\n } finally {\n spinner.stop();\n }\n const { results, detected, rawPackages, directory: scannedDir, filesScanned, filesContent } = scanOutput;\n const elapsedMs = performance.now() - start;\n\n const report = buildReport({\n results,\n detected,\n directory: scannedDir,\n filesScanned,\n filesContent,\n durationMs: elapsedMs,\n version: pkg.version,\n });\n\n const outputPath = opts.output\n ? resolve(opts.output)\n : join(scannedDir, DEFAULT_REPORT_DIR, DEFAULT_REPORT_FILE);\n const rel = relative(scannedDir, outputPath);\n const reportDisplayPath = rel.startsWith('..') ? outputPath : rel;\n\n await emitReport(results, detected, report, {\n quiet: opts.quiet,\n verbose: opts.verbose,\n format,\n noReport: opts.report === false,\n outputPath,\n reportDisplayPath,\n elapsedMs,\n rawPackages,\n });\n\n const errors = countErrors(results);\n const warningsExceeded =\n maxWarnings !== undefined && report.summary.warnings > maxWarnings;\n\n await trackRun({\n version: pkg.version,\n results,\n detected,\n score: report.summary.score,\n durationMs: elapsedMs,\n noTelemetry,\n projectDir: scannedDir,\n });\n\n process.exit(errors > 0 || warningsExceeded ? 1 : 0);\n } catch (err) {\n if (err instanceof ScanError) {\n await trackError(err, noTelemetry, pkg.version);\n fail(err.message);\n }\n await trackError(err, noTelemetry, pkg.version);\n throw err;\n }\n });\n\nprogram\n .command('install')\n .description('Install api-doctor as a skill/rule for Claude Code, Cursor, Codex, and other agents')\n .argument('[directory]', 'Project directory to install into', '.')\n .option('--force', 'Overwrite an existing skills/api-doctor/SKILL.md from the package')\n .option('--no-telemetry', 'Disable anonymous usage telemetry')\n .action(async (directory: string, options: { force?: boolean; telemetry?: boolean }) => {\n const noTelemetry = options.telemetry === false;\n const { created, updated, skipped } = installAgentFiles(resolve(directory), {\n force: options.force,\n });\n for (const path of created) console.log(`api-doctor: created ${path}`);\n for (const path of updated) console.log(`api-doctor: updated ${path}`);\n for (const path of skipped) {\n console.log(`api-doctor: skipped ${path} (already exists; use --force to refresh)`);\n }\n console.log(\n 'api-doctor: edit skills/api-doctor/SKILL.md — all agents reference that file.',\n );\n await trackInstall({\n version: pkg.version,\n filesCreated: created.length,\n filesUpdated: updated.length,\n filesSkipped: skipped.length,\n force: options.force ?? false,\n noTelemetry,\n });\n });\n\nprogram.parse();\n","/**\n * Installs api-doctor as an agent skill so coding agents read\n * `.api-doctor/report.json` and fix findings without being told to.\n *\n * One canonical skill file is copied to `skills/api-doctor/SKILL.md`.\n * Claude Code, Cursor, and AGENTS.md each point at that same file.\n */\nimport {\n copyFileSync,\n existsSync,\n mkdirSync,\n readFileSync,\n symlinkSync,\n unlinkSync,\n writeFileSync,\n} from 'node:fs';\nimport { dirname, join, relative } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/** Canonical skill path inside the user's project (single source of truth). */\nexport const SKILL_RELATIVE_PATH = join('skills', 'api-doctor', 'SKILL.md');\n\n/** True when `install` has already copied the canonical skill into `directory`. */\nexport function isAgentSkillInstalled(directory: string): boolean {\n return existsSync(join(directory, SKILL_RELATIVE_PATH));\n}\n\nexport const INSTALL_COMMAND = 'npx @api-doctor/cli install';\n\nconst AGENTS_MARKER_START = '<!-- api-doctor:start -->';\nconst AGENTS_MARKER_END = '<!-- api-doctor:end -->';\n\ninterface AgentPointer {\n path: string;\n content: string;\n}\n\nfunction bundledSkillPath(): string {\n const packageRoot = join(dirname(fileURLToPath(import.meta.url)), '..');\n const skillPath = join(packageRoot, SKILL_RELATIVE_PATH);\n if (!existsSync(skillPath)) {\n throw new Error(`Bundled skill not found at ${skillPath}`);\n }\n return skillPath;\n}\n\nfunction cursorRule(): AgentPointer {\n return {\n path: join('.cursor', 'rules', 'api-doctor.mdc'),\n content: `---\ndescription: api-doctor — handle integration audit findings\nalwaysApply: false\n---\n\n@skills/api-doctor/SKILL.md\n`,\n };\n}\n\nfunction agentsSection(): string {\n return `${AGENTS_MARKER_START}\n## api-doctor\n\nFollow [skills/api-doctor/SKILL.md](skills/api-doctor/SKILL.md).\n${AGENTS_MARKER_END}`;\n}\n\nexport interface InstallResult {\n created: string[];\n updated: string[];\n skipped: string[];\n}\n\nexport interface InstallOptions {\n /** Overwrite an existing \\`skills/api-doctor/SKILL.md\\` from the package bundle. */\n force?: boolean;\n}\n\nfunction installCanonicalSkill(\n directory: string,\n force: boolean,\n created: string[],\n updated: string[],\n skipped: string[],\n): void {\n const destPath = join(directory, SKILL_RELATIVE_PATH);\n mkdirSync(dirname(destPath), { recursive: true });\n\n if (existsSync(destPath) && !force) {\n skipped.push(SKILL_RELATIVE_PATH);\n return;\n }\n\n const isNew = !existsSync(destPath);\n copyFileSync(bundledSkillPath(), destPath);\n (isNew ? created : updated).push(SKILL_RELATIVE_PATH);\n}\n\nfunction installClaudeSymlink(directory: string, updated: string[]): void {\n const claudeDir = join(directory, '.claude', 'skills', 'api-doctor');\n const claudeSkillPath = join(claudeDir, 'SKILL.md');\n const canonicalPath = join(directory, SKILL_RELATIVE_PATH);\n const linkTarget = relative(claudeDir, canonicalPath);\n\n mkdirSync(claudeDir, { recursive: true });\n\n if (existsSync(claudeSkillPath)) {\n try {\n unlinkSync(claudeSkillPath);\n } catch {\n // Fall through to symlink attempt.\n }\n }\n\n try {\n symlinkSync(linkTarget, claudeSkillPath, 'file');\n updated.push(`${join('.claude', 'skills', 'api-doctor', 'SKILL.md')} → ${SKILL_RELATIVE_PATH}`);\n } catch {\n const fallback = `---\nname: api-doctor\ndescription: Check AI-generated API integration code for silent bugs before shipping.\n---\n\nRead and follow [skills/api-doctor/SKILL.md](../../../skills/api-doctor/SKILL.md).\n`;\n writeFileSync(claudeSkillPath, fallback, 'utf-8');\n updated.push(join('.claude', 'skills', 'api-doctor', 'SKILL.md'));\n }\n}\n\n/** Installs the canonical skill and agent pointers into \\`directory\\`. */\nexport function installAgentFiles(\n directory: string,\n options: InstallOptions = {},\n): InstallResult {\n const { force = false } = options;\n const created: string[] = [];\n const updated: string[] = [];\n const skipped: string[] = [];\n\n installCanonicalSkill(directory, force, created, updated, skipped);\n installClaudeSymlink(directory, updated);\n\n for (const file of [cursorRule()]) {\n const fullPath = join(directory, file.path);\n mkdirSync(dirname(fullPath), { recursive: true });\n const isNew = !existsSync(fullPath);\n writeFileSync(fullPath, file.content, 'utf-8');\n (isNew ? created : updated).push(file.path);\n }\n\n const agentsPath = join(directory, 'AGENTS.md');\n const section = agentsSection();\n if (existsSync(agentsPath)) {\n const existing = readFileSync(agentsPath, 'utf-8');\n const startIdx = existing.indexOf(AGENTS_MARKER_START);\n const endIdx = existing.indexOf(AGENTS_MARKER_END);\n const next =\n startIdx !== -1 && endIdx !== -1\n ? existing.slice(0, startIdx) +\n section +\n existing.slice(endIdx + AGENTS_MARKER_END.length)\n : `${existing.trimEnd()}\\n\\n${section}\\n`;\n writeFileSync(agentsPath, next, 'utf-8');\n updated.push('AGENTS.md');\n } else {\n writeFileSync(agentsPath, `# Agent instructions\\n\\n${section}\\n`, 'utf-8');\n created.push('AGENTS.md');\n }\n\n return { created, updated, skipped };\n}\n","import type { ProviderManifest } from '../../types.js';\n\nexport const resendManifest: ProviderManifest = {\n name: 'resend',\n displayName: 'Resend',\n detect: {\n packages: ['resend'],\n imports: ['resend'],\n urlPatterns: ['api.resend.com'],\n },\n oxlintRules: [\n {\n key: 'resend-webhook-signature',\n resultRule: 'resend/webhook-signature-missing',\n message:\n 'This webhook handler appears to process Resend events without verifying the webhook signature.',\n fix: 'Verify incoming webhooks with Svix (Resend uses Svix signatures). Validate headers and payload before handling events.',\n docsUrl: 'https://resend.com/docs/dashboard/webhooks/introduction#verify-webhook-signatures',\n severity: 'error',\n },\n {\n key: 'resend-api-key-hardcoded',\n resultRule: 'resend/security/api-key-hardcoded',\n message: 'Hardcoded Resend API key found in source code.',\n fix: 'Move the key to an environment variable and read it via process.env.RESEND_API_KEY.',\n docsUrl: 'https://resend.com/docs/send-with-nextjs#prerequisites',\n severity: 'error',\n },\n {\n key: 'resend-api-key-in-client-bundle',\n resultRule: 'resend/security/api-key-in-client-bundle',\n message: 'Resend SDK imported into client-bundled code, which can leak the API key.',\n fix: 'Import and use Resend only in server code (route handlers, server actions, server components).',\n docsUrl: 'https://resend.com/docs/send-with-nextjs',\n severity: 'error',\n },\n {\n key: 'resend-marketing-via-batch-send',\n resultRule: 'resend/correctness/marketing-via-batch-send',\n message: 'Marketing email sent via resend.batch.send instead of the Broadcasts API.',\n fix: 'Use the Broadcasts API (resend.broadcasts.*) or the Dashboard Broadcasts workflow for marketing sends.',\n docsUrl: 'https://resend.com/docs/dashboard/emails/batch-sending',\n severity: 'error',\n },\n {\n key: 'resend-marketing-missing-unsubscribe',\n resultRule: 'resend/correctness/marketing-missing-unsubscribe',\n message: 'Marketing email has no unsubscribe mechanism.',\n fix: 'Add a List-Unsubscribe header (RFC 8058) or include {{{RESEND_UNSUBSCRIBE_URL}}} in the HTML, or send via Broadcasts.',\n docsUrl: 'https://resend.com/docs/dashboard/broadcasts/introduction',\n severity: 'error',\n },\n {\n key: 'resend-test-domain-in-production-path',\n resultRule: 'resend/correctness/test-domain-in-production-path',\n message: 'Test-only sender onboarding@resend.dev used in production code.',\n fix: 'Send from a verified domain configured via process.env.RESEND_FROM_EMAIL.',\n docsUrl: 'https://resend.com/docs/send-with-nextjs',\n severity: 'warning',\n },\n {\n key: 'resend-from-address-not-friendly-format',\n resultRule: 'resend/integration/from-address-not-friendly-format',\n message: 'From address is a bare email rather than the \"Name <email>\" format.',\n fix: 'Use a friendly-name sender, e.g. \"Acme <onboarding@acme.com>\".',\n docsUrl: 'https://resend.com/docs/api-reference/emails/send-email',\n severity: 'info',\n },\n {\n key: 'resend-batch-size-not-enforced',\n resultRule: 'resend/reliability/batch-size-not-enforced',\n message: 'resend.batch.send called without enforcing the 100-email limit.',\n fix: 'Guard the array length (max 100) before calling batch.send, or chunk the array.',\n docsUrl: 'https://resend.com/docs/api-reference/emails/send-batch-emails',\n severity: 'warning',\n },\n {\n key: 'resend-missing-idempotency-key',\n resultRule: 'resend/reliability/missing-idempotency-key',\n message: 'Resend send/batch call has no idempotencyKey.',\n fix: 'Pass an idempotencyKey (e.g. welcome/${userId}) to prevent duplicate sends on retry.',\n docsUrl: 'https://resend.com/docs/send-with-nextjs',\n severity: 'warning',\n },\n {\n key: 'resend-no-error-code-mapping',\n resultRule: 'resend/reliability/no-error-code-mapping',\n message: 'Resend errors are returned as a blanket HTTP 500.',\n fix: 'Map Resend error codes (400/401/403/422/429) to appropriate HTTP statuses instead of always 500.',\n docsUrl: 'https://resend.com/docs/ai-onboarding',\n severity: 'warning',\n },\n {\n key: 'resend-webhook-no-idempotency',\n resultRule: 'resend/reliability/webhook-no-idempotency',\n message: 'Resend webhook handler does not deduplicate retried events.',\n fix: 'Track processed event ids (e.g. event.data.email_id) in a store or set, since Resend retries for 24h.',\n docsUrl: 'https://resend.com/docs/dashboard/webhooks/introduction',\n severity: 'warning',\n },\n {\n key: 'resend-missing-tags',\n resultRule: 'resend/integration/missing-tags',\n message: 'Resend send has no tags for deliverability segmentation.',\n fix: 'Add tags, e.g. tags: [{ name: \"category\", value: \"welcome\" }].',\n docsUrl: 'https://resend.com/docs/dashboard/emails/tags',\n severity: 'info',\n },\n {\n key: 'resend-request-id-not-logged',\n resultRule: 'resend/integration/request-id-not-logged',\n message: 'Resend error handler does not log the request id.',\n fix: 'Log error.headers?.[\"x-request-id\"] (or x-resend-request-id) alongside error.message.',\n docsUrl: 'https://resend.com/docs/api-reference/errors',\n severity: 'info',\n },\n ],\n};\n","import type { ProviderManifest } from '../../types.js';\n\nexport const supabaseManifest: ProviderManifest = {\n name: 'supabase',\n displayName: 'Supabase',\n detect: {\n packages: ['@supabase/supabase-js'],\n imports: ['@supabase/supabase-js'],\n urlPatterns: ['supabase.co'],\n },\n oxlintRules: [\n {\n key: 'supabase-scope-queries-by-tenant-column',\n resultRule: 'supabase/correctness/scope-queries-by-tenant-column',\n message: 'Query selects a tenant column but never filters by it.',\n fix: 'Add .eq(\"<column>\", value) (or .match()/.filter()) to scope results to the caller.',\n docsUrl: 'https://supabase.com/docs/reference/javascript/eq',\n severity: 'error',\n },\n {\n key: 'supabase-validate-uuid-columns',\n resultRule: 'supabase/correctness/validate-uuid-columns',\n message: 'Value passed to a uuid-typed column is only checked with typeof === \"string\".',\n fix: 'Validate UUID shape with a regex (e.g. /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i) before insert/upsert.',\n docsUrl: 'https://supabase.com/docs/guides/database/tables#data-types',\n severity: 'info',\n },\n {\n key: 'supabase-order-by-timestamp-not-identity',\n resultRule: 'supabase/correctness/order-by-timestamp-not-identity',\n message: 'Query orders by \"id\" instead of a selected timestamp column.',\n fix: 'Order by the timestamp column (e.g. .order(\"created_at\", { ascending: false })) instead of the surrogate key.',\n docsUrl: 'https://supabase.com/docs/reference/javascript/order',\n severity: 'info',\n },\n {\n key: 'supabase-consistent-input-length-limits',\n resultRule: 'supabase/correctness/consistent-input-length-limits',\n message: 'A sibling string field in this insert has no length cap, unlike the others.',\n fix: 'Apply the same length cap pattern used for the other fields, e.g. field.length > 2000.',\n docsUrl: 'https://supabase.com/docs/guides/database/tables',\n severity: 'warning',\n },\n {\n key: 'supabase-idempotent-mutations',\n resultRule: 'supabase/reliability/idempotent-mutations',\n message: 'Insert has no idempotency/dedupe key, so a retry can create a duplicate row.',\n fix: 'Add a client-generated idempotency key field backed by a unique constraint, or use .upsert(..., { onConflict: \"<key column>\" }).',\n docsUrl: 'https://supabase.com/docs/reference/javascript/upsert',\n severity: 'warning',\n },\n {\n key: 'supabase-fail-fast-env-validation',\n resultRule: 'supabase/reliability/fail-fast-env-validation',\n message: 'createClient is called with env vars that have no presence check.',\n fix: 'Throw a clear error (e.g. if (!url || !key) throw new Error(...)) before calling createClient.',\n docsUrl: 'https://supabase.com/docs/reference/javascript/initializing',\n severity: 'warning',\n },\n {\n key: 'supabase-no-user-metadata-authz',\n resultRule: 'supabase/security/no-user-metadata-authz',\n message: 'Authorization data is read from or written to user_metadata, which clients can modify.',\n fix: 'Store roles in app_metadata via a trusted server path, or in an RLS-protected profiles table — never user_metadata.',\n docsUrl: 'https://supabase.com/docs/guides/database/postgres/row-level-security',\n severity: 'error',\n },\n {\n key: 'supabase-single-without-error-check',\n resultRule: 'supabase/correctness/single-without-error-check',\n message: 'A .single() query ignores the returned error field.',\n fix: 'Destructure and check error, or use .maybeSingle() and handle a missing row explicitly.',\n docsUrl: 'https://supabase.com/docs/reference/javascript/single',\n severity: 'warning',\n },\n {\n key: 'supabase-non-atomic-replace-pattern',\n resultRule: 'supabase/correctness/non-atomic-replace-pattern',\n message: 'Child rows are replaced via delete-then-insert without checking errors.',\n fix: 'Wrap delete+insert in a Postgres RPC (single transaction) and surface error from each step.',\n docsUrl: 'https://supabase.com/docs/guides/database/functions',\n severity: 'warning',\n },\n {\n key: 'supabase-unchecked-mutation-error',\n resultRule: 'supabase/correctness/unchecked-mutation-error',\n message: 'A Supabase insert/update/delete never checks the returned error field.',\n fix: 'Destructure { error } from every mutation and revert optimistic UI or show a toast on failure.',\n docsUrl: 'https://supabase.com/docs/reference/javascript/insert',\n severity: 'warning',\n },\n {\n key: 'supabase-realtime-missing-filter',\n resultRule: 'supabase/reliability/realtime-missing-filter',\n message: 'A Realtime postgres_changes subscription listens to an entire table with no filter.',\n fix: 'Add a filter option scoped to the current user (e.g. filter: `receiver_id=eq.${user.id}`).',\n docsUrl: 'https://supabase.com/docs/guides/realtime/postgres-changes#filtering',\n severity: 'error',\n },\n {\n key: 'supabase-storage-error-not-surfaced',\n resultRule: 'supabase/reliability/storage-error-not-surfaced',\n message: 'A storage upload failure is ignored and execution continues.',\n fix: 'On uploadError, stop and show an error instead of saving a stale URL.',\n docsUrl: 'https://supabase.com/docs/reference/javascript/storage-from-upload',\n severity: 'warning',\n },\n ],\n};\n","import type { ProviderManifest } from '../../types.js';\n\nexport const auth0Manifest: ProviderManifest = {\n name: 'auth0',\n displayName: 'Auth0',\n detect: {\n packages: ['jsonwebtoken', 'jwks-rsa', 'express-jwt'],\n imports: ['jsonwebtoken', 'jwks-rsa', 'express-jwt'],\n urlPatterns: ['auth0.com'],\n },\n oxlintRules: [\n {\n key: 'auth0-required-audience-validation',\n resultRule: 'auth0/security/required-audience-validation',\n message:\n 'Auth0 JWT verification is configured without (or only conditionally with) audience validation.',\n fix: 'Require AUTH0_AUDIENCE and fail closed if it is unset, then always pass `audience` to jwt.verify()/express-jwt so a token issued for a different API cannot authenticate here.',\n docsUrl: 'https://auth0.com/docs/secure/tokens/json-web-tokens/validate-json-web-tokens',\n severity: 'error',\n },\n {\n key: 'auth0-no-account-link-without-verified-email',\n resultRule: 'auth0/security/no-account-link-without-verified-email',\n message:\n 'Account lookup is keyed on an email claim without checking email_verified first.',\n fix: 'Require claims.email_verified (or the namespaced equivalent) before using the email claim to look up or re-link an existing account; otherwise create a new, unlinked account.',\n docsUrl: 'https://auth0.com/docs/manage-users/user-accounts/user-account-linking',\n severity: 'error',\n },\n {\n key: 'auth0-dead-claim-verification-check',\n resultRule: 'auth0/correctness/dead-claim-verification-check',\n message: 'Stringified boolean claim is checked with .includes() against a substring it can never contain.',\n fix: 'Compare the claim directly, e.g. `if (!claims.email_verified) { ... }`, instead of stringifying it and checking for a substring.',\n docsUrl: 'https://auth0.com/docs/secure/tokens/json-web-tokens/json-web-token-claims',\n severity: 'error',\n },\n {\n key: 'auth0-jwks-refresh-on-unknown-kid',\n resultRule: 'auth0/reliability/jwks-refresh-on-unknown-kid',\n message: 'JWKS kid lookup has no retry-with-forced-refresh path on a cache miss.',\n fix: 'On a kid miss, force a fresh JWKS fetch and retry the lookup once before failing, instead of failing immediately against a possibly-stale cache.',\n docsUrl: 'https://auth0.com/docs/get-started/tenant-settings/signing-keys/rotate-signing-keys',\n severity: 'warning',\n },\n ],\n};\n","import type { ProviderManifest } from '../../types.js';\n\nexport const firebaseManifest: ProviderManifest = {\n name: 'firebase',\n displayName: 'Firebase',\n detect: {\n packages: ['firebase'],\n imports: ['firebase/app', 'firebase/auth', 'firebase/database', 'firebase/app-check'],\n urlPatterns: ['firebaseio.com', 'firebaseapp.com'],\n },\n oxlintRules: [\n {\n key: 'firebase-missing-app-check',\n resultRule: 'firebase/security/missing-app-check',\n message: 'Firebase app is initialized with no App Check configured.',\n fix: 'Call initializeAppCheck(app, { provider: new ReCaptchaV3Provider(SITE_KEY), isTokenAutoRefreshEnabled: true }) alongside initializeApp.',\n docsUrl: 'https://firebase.google.com/docs/database/web/start',\n severity: 'warning',\n },\n {\n key: 'firebase-unhandled-auth-popup-rejection',\n resultRule: 'firebase/correctness/unhandled-auth-popup-rejection',\n message: 'signInWithPopup is called with no try/catch and no chained .catch.',\n fix: 'Wrap the call in try/catch (and finally, to clear loading state) — popup-closed-by-user and popup-blocked are expected rejections.',\n docsUrl: 'https://firebase.google.com/docs/auth/web/google-signin',\n severity: 'error',\n },\n {\n key: 'firebase-rtdb-list-read-for-single-item',\n resultRule: 'firebase/correctness/rtdb-list-read-for-single-item',\n message: 'A whole collection is subscribed to and then searched for one item by a route id param.',\n fix: 'Read/subscribe to the single node directly, e.g. ref(db, `path/${id}`), instead of finding it in the full list.',\n docsUrl: 'https://firebase.google.com/docs/database/web/read-and-write',\n severity: 'warning',\n },\n {\n key: 'firebase-unvalidated-external-data-to-rtdb',\n resultRule: 'firebase/correctness/unvalidated-external-data-to-rtdb',\n message: 'Parsed external data is written to the Realtime Database with no validation.',\n fix: 'Validate shape/values (e.g. regex-check date fields) before calling set()/update()/push(), and surface a parse-quality warning for skipped items.',\n docsUrl: 'https://firebase.google.com/docs/database/web/read-and-write',\n severity: 'error',\n },\n {\n key: 'firebase-rtdb-batch-write-not-atomic',\n resultRule: 'firebase/correctness/rtdb-batch-write-not-atomic',\n message: 'Promise.all over per-item push()+set() calls is not atomic.',\n fix: 'Build one update() call against the parent ref with all generated keys as fields — Firebase commits multi-path updates atomically.',\n docsUrl: 'https://firebase.google.com/docs/database/web/read-and-write',\n severity: 'warning',\n },\n {\n key: 'firebase-rtdb-listener-error-not-handled',\n resultRule: 'firebase/reliability/rtdb-listener-error-not-handled',\n message: 'onValue is called with no error/cancel callback.',\n fix: 'Pass a 3rd argument to onValue (e.g. (error) => console.error(error)) so PERMISSION_DENIED and dropped connections surface.',\n docsUrl: 'https://firebase.google.com/docs/reference/js/database.md#onvalue',\n severity: 'warning',\n },\n {\n key: 'firebase-effect-deps-whole-user-object',\n resultRule: 'firebase/reliability/effect-deps-whole-user-object',\n message: 'useEffect depends on the whole user object but only reads user.uid.',\n fix: 'Depend on user?.uid instead of user — onAuthStateChanged delivers a new object reference on every token refresh even when uid is unchanged.',\n docsUrl: 'https://firebase.google.com/docs/reference/js/auth.md#onauthstatechanged',\n severity: 'warning',\n },\n {\n key: 'firebase-rtdb-write-promise-not-handled',\n resultRule: 'firebase/reliability/rtdb-write-promise-not-handled',\n message: 'A Realtime Database write promise is neither awaited in a try/catch nor .catch-handled.',\n fix: 'Wrap state-changing writes in try/catch and surface failures; do not navigate away on a write whose result was never checked.',\n docsUrl: 'https://firebase.google.com/docs/database/web/read-and-write',\n severity: 'error',\n },\n ],\n};\n","import type { ProviderManifest } from '../../types.js';\n\nexport const lovableManifest: ProviderManifest = {\n name: 'lovable',\n displayName: 'Lovable',\n detect: {\n packages: ['lovable-tagger'],\n imports: ['lovable-tagger'],\n urlPatterns: ['lovable.dev', 'lovable.app'],\n },\n oxlintRules: [\n {\n key: 'lovable-no-client-side-secret-fetch',\n resultRule: 'lovable/security/no-client-side-secret-fetch',\n message:\n 'A third-party LLM provider is called directly from client code with a key read from import.meta.env.VITE_*, which ships into the browser bundle.',\n fix: 'Move this call into a Lovable Cloud Edge Function and keep the provider key in Secrets — the browser should call your own Edge Function, never the provider directly.',\n docsUrl: 'https://docs.lovable.dev/features/security',\n severity: 'error',\n },\n {\n key: 'lovable-paid-flag-without-edge-function',\n resultRule: 'lovable/security/paid-flag-without-edge-function',\n message:\n 'A paid-looking flag is set via a direct database update with no payment-provider or Edge Function call.',\n fix: 'Move the purchase behind an Edge Function that creates a payment-provider checkout session, and only flip the flag from a server-side webhook after payment is confirmed.',\n docsUrl: 'https://docs.lovable.dev/features/cloud',\n severity: 'error',\n },\n {\n key: 'lovable-expiry-column-never-checked',\n resultRule: 'lovable/correctness/expiry-column-never-checked',\n message: 'An expiry column is written but never compared against the current time anywhere in this file.',\n fix: 'Filter or sort by the expiry column against the current time, or add a scheduled Edge Function / pg_cron job that clears the flag once it passes.',\n docsUrl: 'https://docs.lovable.dev/features/cloud',\n severity: 'warning',\n },\n {\n key: 'lovable-silent-catch-on-provider-call',\n resultRule: 'lovable/correctness/silent-catch-on-provider-call',\n message: 'A catch block around an LLM provider call has no logging, so failures look like \"no key configured.\"',\n fix: 'console.error (or log to your error tracker) the failure reason — status code and error body — before falling through.',\n docsUrl: 'https://docs.lovable.dev/features/cloud',\n severity: 'warning',\n },\n ],\n};\n","import type { ProviderManifest } from '../../types.js';\n\nexport const browserbaseManifest: ProviderManifest = {\n name: 'browserbase',\n displayName: 'Browserbase',\n detect: {\n packages: ['@browserbasehq/sdk'],\n imports: ['@browserbasehq/sdk'],\n urlPatterns: ['api.browserbase.com'],\n },\n oxlintRules: [\n {\n key: 'browserbase-no-conditional-authz-on-anonymous-user',\n resultRule: 'browserbase/security/no-conditional-authz-on-anonymous-user',\n message: 'A Browserbase live-view/recording resource is gated only by a conditional authz check.',\n fix: 'Add an unconditional `if (!user) return ...` guard before the ownership check, so anonymous callers are rejected, not skipped past.',\n docsUrl: 'https://docs.browserbase.com/reference/api/session-live-urls',\n severity: 'error',\n },\n {\n key: 'browserbase-no-connect-url-in-api-response',\n resultRule: 'browserbase/security/no-connect-url-in-api-response',\n message: 'connectUrl (a bearer credential for the live browser) is included in an HTTP response.',\n fix: 'Omit connectUrl from the response body — keep it server-side only. Share debuggerFullscreenUrl from sessions.debug() instead.',\n docsUrl: 'https://docs.browserbase.com/reference/api/create-a-session',\n severity: 'error',\n },\n {\n key: 'browserbase-session-id-requires-ownership-check',\n resultRule: 'browserbase/security/session-id-requires-ownership-check',\n message: 'sessionId flows into a live-view/recording call with no ownership check.',\n fix: 'Look up the owning project/org by sessionId and verify the requesting user has access before calling sessions.debug()/recording.retrieve().',\n docsUrl: 'https://docs.browserbase.com/features/session-live-view',\n severity: 'warning',\n },\n {\n key: 'browserbase-no-concurrent-shared-context',\n resultRule: 'browserbase/correctness/no-concurrent-shared-context',\n message: 'The same Context id is passed into every session in a concurrent Promise.all batch.',\n fix: 'Serialize sessions that share a context id, or create a fresh Context per concurrent run.',\n docsUrl: 'https://docs.browserbase.com/features/contexts',\n severity: 'error',\n },\n {\n key: 'browserbase-mobile-device-requires-os-setting',\n resultRule: 'browserbase/correctness/mobile-device-requires-os-setting',\n message: 'A \"mobile\" device branch resizes the viewport but never sets browserSettings.os.',\n fix: \"Set browserSettings.os = 'mobile' (or 'tablet') alongside the viewport resize — the Node SDK's device-emulation lever is `os`, not a fingerprint object.\",\n docsUrl: 'https://docs.browserbase.com/features/stealth-mode',\n severity: 'error',\n },\n {\n key: 'browserbase-use-typed-exception-status-not-substring',\n resultRule: 'browserbase/correctness/use-typed-exception-status-not-substring',\n message: 'Error handling matches a substring of the stringified error instead of err.status.',\n fix: 'Check err.status (or `instanceof Browserbase.APIError`/`NotFoundError`) instead of matching message text.',\n docsUrl: 'https://docs.browserbase.com/reference/api/session-live-urls',\n severity: 'info',\n },\n {\n key: 'browserbase-release-session-on-connect-failure',\n resultRule: 'browserbase/reliability/release-session-on-connect-failure',\n message: 'A connect call after session creation has no catch that releases the session on failure.',\n fix: 'Wrap the connect call in try/catch and call sessions.update(id, { status: \"REQUEST_RELEASE\" }) on failure.',\n docsUrl: 'https://docs.browserbase.com/reference/api/update-a-session',\n severity: 'error',\n },\n {\n key: 'browserbase-dont-stack-custom-retry-on-sdk-retry',\n resultRule: 'browserbase/reliability/dont-stack-custom-retry-on-sdk-retry',\n message: 'sessions.create() is called inside a custom retry loop without disabling the SDK\\'s own retry.',\n fix: 'Pass { maxRetries: 0 } to sessions.create() so the outer loop is the only thing retrying.',\n docsUrl: 'https://docs.browserbase.com/optimizations/concurrency/overview',\n severity: 'warning',\n },\n {\n key: 'browserbase-no-overbroad-error-substring-match',\n resultRule: 'browserbase/reliability/no-overbroad-error-substring-match',\n message: 'An error-message OR-chain includes an overly broad resource-name substring.',\n fix: 'Match on err.status/`instanceof` instead of a generic word like \"session\" that matches almost any error from this call.',\n docsUrl: 'https://docs.browserbase.com/reference/api/session-live-urls',\n severity: 'error',\n },\n {\n key: 'browserbase-use-sdk-not-raw-requests',\n resultRule: 'browserbase/integration/use-sdk-not-raw-requests',\n message: 'A raw HTTP request targets a Browserbase API endpoint instead of using the SDK.',\n fix: 'Replace the raw fetch/axios/http call with the equivalent installed-SDK method.',\n docsUrl: 'https://docs.browserbase.com/reference/sdk/nodejs',\n severity: 'info',\n },\n {\n key: 'browserbase-centralize-request-release',\n resultRule: 'browserbase/integration/centralize-request-release',\n message: 'REQUEST_RELEASE is hand-rolled inline instead of going through a shared abstraction.',\n fix: 'Route this call through a single designated release/provider method instead of inlining sessions.update(..., { status: \"REQUEST_RELEASE\" }).',\n docsUrl: 'https://docs.browserbase.com/reference/api/update-a-session',\n severity: 'warning',\n },\n ],\n};\n","import type { ProviderManifest } from '../../types.js';\n\nexport const openaiCuaManifest: ProviderManifest = {\n name: 'openai-cua',\n displayName: 'OpenAI Computer Use',\n detect: {\n packages: ['openai'],\n imports: ['openai'],\n urlPatterns: ['api.openai.com'],\n },\n oxlintRules: [\n {\n key: 'openai-cua-no-domain-allowlist',\n resultRule: 'openai-cua/security/no-domain-allowlist',\n message: 'Computer-use actions execute against the current page with no domain/origin allowlist check.',\n fix: 'Check the page origin against a configured allowlist before executing click/type/fill actions, and require explicit opt-in for cross-domain navigation.',\n docsUrl: 'https://developers.openai.com/api/docs/guides/tools-computer-use',\n severity: 'error',\n },\n {\n key: 'openai-cua-scroll-delta-default-zero',\n resultRule: 'openai-cua/correctness/scroll-delta-default-zero',\n message: 'A missing vertical scroll delta defaults to a non-zero value instead of 0.',\n fix: 'Default the missing scroll delta to 0 on both axes, matching the reference scroll handler.',\n docsUrl: 'https://developers.openai.com/api/docs/guides/tools-computer-use',\n severity: 'error',\n },\n {\n key: 'openai-cua-structured-step-metadata-not-text-json',\n resultRule: 'openai-cua/correctness/structured-step-metadata-not-text-json',\n message: 'Step metadata is extracted by brace-hunting in free text instead of structured tool output.',\n fix: 'Add a function tool (e.g. report_step) or use structured output (text.format) instead of parsing JSON found via indexOf/lastIndexOf in the message text.',\n docsUrl: 'https://developers.openai.com/api/docs/guides/tools-computer-use',\n severity: 'warning',\n },\n {\n key: 'openai-cua-no-blind-safety-check-ack',\n resultRule: 'openai-cua/correctness/no-blind-safety-check-ack',\n message: 'Pending safety checks are acknowledged by a filter that never inspects .code or .message.',\n fix: 'Evaluate each check\\'s code/message against an actual policy before acknowledging it, or omit acknowledged_safety_checks entirely if you rely on harness-level confirmation instead.',\n docsUrl: 'https://developers.openai.com/api/docs/guides/tools-computer-use',\n severity: 'warning',\n },\n {\n key: 'openai-cua-retry-transient-turn-errors',\n resultRule: 'openai-cua/reliability/retry-transient-turn-errors',\n message: 'responses.create() has no turn-level retry, so a transient error ends the entire run.',\n fix: 'Catch typed transient exceptions (RateLimitError, APIConnectionError, InternalServerError) and retry that turn with backoff before falling back to ending the run.',\n docsUrl: 'https://developers.openai.com/api/docs/guides/tools-computer-use',\n severity: 'error',\n },\n {\n key: 'openai-cua-check-response-status-incomplete',\n resultRule: 'openai-cua/reliability/check-response-status-incomplete',\n message: 'A completion check treats \"no tool calls\" as success without checking response.status === \"incomplete\".',\n fix: 'Check response.status === \"incomplete\" before treating a tool-call-free response as a successful completion; retry with a larger token budget or fail the run explicitly otherwise.',\n docsUrl: 'https://developers.openai.com/api/docs/guides/tools-computer-use',\n severity: 'error',\n },\n {\n key: 'openai-cua-set-safety-identifier',\n resultRule: 'openai-cua/integration/set-safety-identifier',\n message: 'responses.create() call has no safety_identifier (or user) parameter.',\n fix: 'Thread a stable, hashed per-customer identifier through to every responses.create() call as safety_identifier.',\n docsUrl: 'https://help.openai.com/en/articles/5428082-how-to-incorporate-a-safety-identifier',\n severity: 'warning',\n },\n ],\n};\n","/**\n * Central registry of API providers. Each manifest declares how to detect\n * the SDK in a project and which oxlint rules to enable when found.\n */\nimport type { ProviderManifest } from '../types.js';\nimport { resendManifest } from './resend/manifest.js';\nimport { supabaseManifest } from './supabase/manifest.js';\nimport { auth0Manifest } from './auth0/manifest.js';\nimport { firebaseManifest } from './firebase/manifest.js';\nimport { lovableManifest } from './lovable/manifest.js';\nimport { browserbaseManifest } from './browserbase/manifest.js';\nimport { openaiCuaManifest } from './openai-cua/manifest.js';\n\nexport const providers: ProviderManifest[] = [\n resendManifest,\n supabaseManifest,\n auth0Manifest,\n firebaseManifest,\n lovableManifest,\n browserbaseManifest,\n openaiCuaManifest,\n];\n","/**\n * Minimal terminal animation primitives: a frame-based spinner and a small\n * per-line reveal delay. Both are no-ops unless stdout is an interactive TTY\n * (and `CI` is unset), so piped output, --format/--quiet modes, and tests\n * are never affected — only a human watching a real terminal sees them.\n */\n\nconst SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\nconst SPINNER_INTERVAL_MS = 80;\n/** Pause between major reveals: a detected provider, a finding group, the header. */\nconst GROUP_DELAY_MS = 220;\n/** Pause between minor sub-lines within a reveal: a header line, a file location. */\nconst LINE_DELAY_MS = 45;\n\nexport function isAnimated(): boolean {\n return Boolean(process.stdout.isTTY) && !process.env.CI;\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** Pause between revealed groups (providers, finding groups); instant when not animated. */\nexport async function revealDelay(): Promise<void> {\n if (!isAnimated()) return;\n await sleep(GROUP_DELAY_MS);\n}\n\n/** Shorter pause between sub-lines inside a reveal; instant when not animated. */\nexport async function lineDelay(): Promise<void> {\n if (!isAnimated()) return;\n await sleep(LINE_DELAY_MS);\n}\n\nexport interface Spinner {\n stop(): void;\n}\n\n/** Animated braille spinner on stderr; a no-op when output isn't an interactive TTY. */\nexport function createSpinner(label: string): Spinner {\n if (!isAnimated()) {\n return { stop() {} };\n }\n\n let frame = 0;\n const render = (): void => {\n process.stderr.write(`\\r${SPINNER_FRAMES[frame % SPINNER_FRAMES.length]} ${label}`);\n frame += 1;\n };\n render();\n const timer = setInterval(render, SPINNER_INTERVAL_MS);\n\n return {\n stop(): void {\n clearInterval(timer);\n process.stderr.write(`\\r${' '.repeat(label.length + 2)}\\r`);\n },\n };\n}\n","/**\n * Writes the structured Report to disk. When writing into the default\n * `.api-doctor/` directory, seeds a `.gitignore` (`*`) so the report folder is\n * ignored by default; users can opt in to committing it.\n */\nimport { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { basename, dirname } from 'node:path';\nimport type { Report } from '../types.js';\n\nexport const DEFAULT_REPORT_DIR = '.api-doctor';\nexport const DEFAULT_REPORT_FILE = 'report.json';\n\nexport function writeReport(report: Report, outputPath: string): void {\n const dir = dirname(outputPath);\n mkdirSync(dir, { recursive: true });\n\n // Seed `.gitignore` only inside our own `.api-doctor/` directory, and only once.\n if (basename(dir) === DEFAULT_REPORT_DIR) {\n const gitignorePath = `${dir}/.gitignore`;\n if (!existsSync(gitignorePath)) {\n writeFileSync(gitignorePath, '*\\n', 'utf-8');\n }\n }\n\n writeFileSync(outputPath, `${JSON.stringify(report, null, 2)}\\n`, 'utf-8');\n}\n","/** Oxlint plugin name — must match `meta.name` in src/plugin/index.ts */\nexport const PLUGIN_NAME = '@api-doctor/cli';\n","/**\n * First oxlint rule scaffold for v1: validates Resend webhook handlers\n * verify signatures before processing webhook payload.\n */\n// Implemented with an ESLint-compatible visitor model (string matching avoided).\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Resend webhook handlers must verify signatures before processing payloads',\n category: 'security',\n cwe: 'CWE-345',\n owasp: 'API2:2023 Broken Authentication',\n rationale:\n 'Webhook endpoints are public URLs, so anyone who learns the path can POST a forged payload. Without verifying the Svix signature first, an attacker can fake delivery, bounce, or complaint events and drive your application into the wrong state. Validating the signature against your webhook secret before reading the body ensures the event genuinely came from Resend.',\n docsUrl: 'https://resend.com/docs/dashboard/webhooks/introduction#verify-webhook-signatures',\n recommended: true,\n },\n messages: {\n missingVerification:\n 'This webhook handler processes Resend events without verifying the signature first.',\n },\n },\n // eslint-style rule API: `create(context)` returns visitor map.\n create(context: any) {\n let importsResend = false;\n const svixImports = new Set<string>();\n\n type Pos = { offset: number; line: number; column: number };\n type Handler = {\n node: any;\n start: Pos;\n end: Pos;\n firstBodyPos?: Pos;\n firstVerifyPos?: Pos;\n };\n\n const postHandlers: Handler[] = [];\n\n function nodeStartPos(n: any): Pos {\n const rangeStart = typeof n?.range?.[0] === 'number' ? n.range[0] : null;\n const line = n?.loc?.start?.line ?? 1;\n const column = n?.loc?.start?.column ?? 0;\n // Fallback ordering when range isn't available.\n const offset = rangeStart ?? line * 1_000_000 + column;\n return { offset, line, column };\n }\n\n function nodeEndPos(n: any): Pos {\n const rangeEnd = typeof n?.range?.[1] === 'number' ? n.range[1] : null;\n const line = n?.loc?.end?.line ?? n?.loc?.start?.line ?? 1;\n const column = n?.loc?.end?.column ?? n?.loc?.start?.column ?? 0;\n const offset = rangeEnd ?? line * 1_000_000 + column;\n return { offset, line, column };\n }\n\n function within(handler: Handler, n: any): boolean {\n const p = nodeStartPos(n);\n return p.offset >= handler.start.offset && p.offset <= handler.end.offset;\n }\n\n function isExportedPostHandler(fnNode: any): boolean {\n // FunctionDeclaration: `function POST() {}`\n if (fnNode?.type === 'FunctionDeclaration') return fnNode?.id?.name === 'POST';\n\n // VariableDeclaration init: `export const POST = async () => {}`\n return fnNode?.type === 'ArrowFunctionExpression' || fnNode?.type === 'FunctionExpression';\n }\n\n function getHandlerFromExportNamedDeclaration(node: any): Handler[] {\n const handlers: Handler[] = [];\n const decl = node?.declaration;\n if (!decl) return handlers;\n\n if (decl.type === 'FunctionDeclaration') {\n if (decl.id?.name === 'POST') {\n handlers.push({\n node: decl,\n start: nodeStartPos(decl),\n end: nodeEndPos(decl),\n firstBodyPos: undefined,\n firstVerifyPos: undefined,\n });\n }\n return handlers;\n }\n\n if (decl.type === 'VariableDeclaration') {\n for (const d of decl.declarations ?? []) {\n const idName = d?.id?.type === 'Identifier' ? d.id.name : null;\n if (idName !== 'POST') continue;\n const init = d?.init;\n if (!init) continue;\n if (!isExportedPostHandler(init)) continue;\n handlers.push({\n node: init,\n start: nodeStartPos(init),\n end: nodeEndPos(init),\n firstBodyPos: undefined,\n firstVerifyPos: undefined,\n });\n }\n }\n\n return handlers;\n }\n\n function isReqJsonCall(n: any): boolean {\n if (n?.type !== 'CallExpression') return false;\n const callee = n.callee;\n if (callee?.type !== 'MemberExpression') return false;\n const prop = callee.property;\n if (prop?.type !== 'Identifier' || prop.name !== 'json') return false;\n const obj = callee.object;\n return obj?.type === 'Identifier' && (obj.name === 'req' || obj.name === 'request');\n }\n\n function isBodyMember(n: any): boolean {\n if (n?.type !== 'MemberExpression') return false;\n const prop = n.property;\n if (prop?.type !== 'Identifier' || prop.name !== 'body') return false;\n const obj = n.object;\n return obj?.type === 'Identifier' && (obj.name === 'req' || obj.name === 'request');\n }\n\n function isCryptoCreateHmacCall(n: any): boolean {\n if (n?.type !== 'CallExpression') return false;\n const callee = n.callee;\n if (callee?.type !== 'MemberExpression') return false;\n const prop = callee.property;\n if (prop?.type !== 'Identifier' || prop.name !== 'createHmac') return false;\n // Prefer `crypto.createHmac`, but accept any `*.createHmac` to reduce false negatives.\n return callee.object?.type === 'Identifier' || callee.object?.type === 'MemberExpression';\n }\n\n function isSvixVerifyCall(n: any): boolean {\n if (n?.type !== 'CallExpression') return false;\n const callee = n.callee;\n if (callee?.type !== 'MemberExpression') return false;\n const prop = callee.property;\n if (prop?.type !== 'Identifier' || prop.name !== 'verify') return false;\n const obj = callee.object;\n return obj?.type === 'Identifier' && svixImports.has(obj.name);\n }\n\n function recordFirst(posKey: keyof Handler, handler: Handler, pos: Pos): void {\n // `firstBodyPos` and `firstVerifyPos` use Pos objects.\n const existing = handler[posKey as 'firstBodyPos' | 'firstVerifyPos'] as Pos | undefined;\n if (!existing) {\n (handler as any)[posKey] = pos;\n return;\n }\n if (pos.offset < existing.offset) {\n (handler as any)[posKey] = pos;\n }\n }\n\n return {\n ImportDeclaration(node: any) {\n const importSource = node?.source?.value;\n if (importSource === 'resend') importsResend = true;\n\n if (importSource === 'svix') {\n for (const s of node.specifiers ?? []) {\n // `import { Webhook as MyHook } from 'svix'`\n if (s?.type === 'ImportSpecifier' && s.local?.type === 'Identifier') {\n svixImports.add(s.local.name);\n }\n // `import Webhook from 'svix'` or `import * as svix from 'svix'`\n if ((s?.type === 'ImportDefaultSpecifier' || s?.type === 'ImportNamespaceSpecifier') && s.local?.type === 'Identifier') {\n svixImports.add(s.local.name);\n }\n }\n }\n },\n\n ExportNamedDeclaration(node: any) {\n const handlers = getHandlerFromExportNamedDeclaration(node);\n for (const h of handlers) postHandlers.push(h);\n },\n\n CallExpression(node: any) {\n if (postHandlers.length === 0) return;\n\n const pos = nodeStartPos(node);\n\n for (const handler of postHandlers) {\n if (!within(handler, node)) continue;\n\n if (isReqJsonCall(node)) recordFirst('firstBodyPos', handler, pos);\n if (isSvixVerifyCall(node)) recordFirst('firstVerifyPos', handler, pos);\n if (isCryptoCreateHmacCall(node)) recordFirst('firstVerifyPos', handler, pos);\n }\n },\n\n MemberExpression(node: any) {\n if (postHandlers.length === 0) return;\n if (!isBodyMember(node)) return;\n const pos = nodeStartPos(node);\n for (const handler of postHandlers) {\n if (!within(handler, node)) continue;\n recordFirst('firstBodyPos', handler, pos);\n }\n },\n\n 'Program:exit'() {\n if (!importsResend) return;\n for (const handler of postHandlers) {\n if (!handler.firstVerifyPos) {\n context.report({ node: handler.node, messageId: 'missingVerification' });\n continue;\n }\n\n if (handler.firstBodyPos && handler.firstVerifyPos.offset > handler.firstBodyPos.offset) {\n context.report({ node: handler.node, messageId: 'missingVerification' });\n }\n }\n },\n };\n },\n};\n\nexport const resendWebhookSignatureRule = rule;\n\n","/**\n * resend-api-key-hardcoded (security)\n *\n * Flags Resend API key literals (`re_...`) embedded directly in source code.\n * Keys must come from `process.env.RESEND_API_KEY`.\n *\n * Detection is AST-based: it inspects string `Literal` and `TemplateElement`\n * VALUES only, so the same token appearing in a comment is never a node and is\n * naturally ignored. A leading word boundary keeps the pattern from matching\n * inside unrelated identifiers like `pre_release`.\n */\n\n// Resend secret keys are prefixed with `re_`. Word boundary avoids `pre_...`.\nconst RESEND_KEY_PATTERN = /\\bre_[A-Za-z0-9_]+/;\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Resend API keys must not be hardcoded; load them from environment variables',\n category: 'security',\n cwe: 'CWE-798',\n owasp: 'API8:2023 Security Misconfiguration',\n rationale:\n 'A hardcoded API key gets committed to version control, where it lives in git history forever and is exposed to anyone with repository access. Leaked Resend keys let attackers send mail from your domain, damaging sender reputation and deliverability. Reading the key from process.env.RESEND_API_KEY keeps the secret out of source code and lets you rotate it without a redeploy.',\n docsUrl: 'https://resend.com/docs/send-with-nextjs#prerequisites',\n recommended: true,\n },\n messages: {\n hardcodedApiKey:\n 'Hardcoded Resend API key detected. Load the key from process.env.RESEND_API_KEY instead.',\n },\n schema: [],\n },\n create(context: any) {\n return {\n Literal(node: any) {\n if (typeof node.value !== 'string') return;\n if (RESEND_KEY_PATTERN.test(node.value)) {\n context.report({ node, messageId: 'hardcodedApiKey' });\n }\n },\n\n TemplateElement(node: any) {\n const cooked = node?.value?.cooked ?? node?.value?.raw;\n if (typeof cooked !== 'string') return;\n if (RESEND_KEY_PATTERN.test(cooked)) {\n context.report({ node, messageId: 'hardcodedApiKey' });\n }\n },\n };\n },\n};\n\nexport const resendApiKeyHardcodedRule = rule;\nexport default rule;\n","/**\n * resend-api-key-in-client-bundle (security)\n *\n * The Resend SDK is server-only; importing it into client-bundled code risks\n * shipping the API key to the browser (Resend's docs say keys belong in\n * server env only). Flags a value import from `resend` when the file\n * is client code:\n * - it carries a top-level \"use client\" directive, OR\n * - it lives under a `components/` path and renders JSX.\n *\n * Type-only imports (`import type { ... } from 'resend'`) are erased at build\n * time and are not flagged.\n */\n\nfunction isComponentsPath(filename: string): boolean {\n return /[\\\\/]components[\\\\/]/.test(filename);\n}\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'The Resend SDK must not be imported into client-bundled code',\n category: 'security',\n cwe: 'CWE-200',\n owasp: 'API8:2023 Security Misconfiguration',\n rationale:\n 'The Resend SDK is server-only and is initialized with your secret API key. Importing it into a \"use client\" component or other browser-bundled code ships that key to every visitor, where it can be read straight from the page source. Keeping Resend imports in server code (route handlers, server actions, server components) ensures the key never reaches the client.',\n docsUrl: 'https://resend.com/docs/send-with-nextjs',\n recommended: true,\n },\n messages: {\n clientBundleImport:\n 'Resend is imported into client-bundled code. Keep Resend (and its API key) on the server.',\n },\n schema: [],\n },\n create(context: any) {\n let resendImportNode: any = null;\n let hasUseClient = false;\n let hasJsx = false;\n\n return {\n Program(node: any) {\n for (const stmt of node.body ?? []) {\n if (stmt?.type !== 'ExpressionStatement') continue;\n const directive =\n stmt.directive ??\n (stmt.expression?.type === 'Literal' ? stmt.expression.value : undefined);\n if (directive === 'use client') {\n hasUseClient = true;\n break;\n }\n }\n },\n\n ImportDeclaration(node: any) {\n if (node?.source?.value !== 'resend') return;\n // Skip type-only imports — they are stripped from the bundle.\n if (node.importKind === 'type') return;\n const allSpecifiersAreType =\n Array.isArray(node.specifiers) &&\n node.specifiers.length > 0 &&\n node.specifiers.every((s: any) => s.importKind === 'type');\n if (allSpecifiersAreType) return;\n resendImportNode = node;\n },\n\n JSXElement() {\n hasJsx = true;\n },\n JSXFragment() {\n hasJsx = true;\n },\n\n 'Program:exit'() {\n if (!resendImportNode) return;\n const inClientBundle =\n hasUseClient || (isComponentsPath(String(context.filename ?? '')) && hasJsx);\n if (inClientBundle) {\n context.report({ node: resendImportNode, messageId: 'clientBundleImport' });\n }\n },\n };\n },\n};\n\nexport const resendApiKeyInClientBundleRule = rule;\nexport default rule;\n","/**\n * Shared AST helpers for Resend rules. Kept intentionally small; extend only\n * when logic is genuinely reused across rules.\n *\n * Send calls are matched by the `.emails.send(...)` / `.batch.send(...)` member\n * shape rather than the base identifier name, so a client stored as `resend`,\n * `client`, etc. is still recognized.\n */\n\n/** True for `<obj>.emails.send(...)`. */\nexport function isResendEmailsSendCall(node: any): boolean {\n if (node?.type !== 'CallExpression') return false;\n const callee = node.callee;\n if (callee?.type !== 'MemberExpression') return false;\n if (callee.property?.type !== 'Identifier' || callee.property.name !== 'send') return false;\n const obj = callee.object;\n return (\n obj?.type === 'MemberExpression' &&\n obj.property?.type === 'Identifier' &&\n obj.property.name === 'emails'\n );\n}\n\n/** True for `<obj>.batch.send(...)`. */\nexport function isResendBatchSendCall(node: any): boolean {\n if (node?.type !== 'CallExpression') return false;\n const callee = node.callee;\n if (callee?.type !== 'MemberExpression') return false;\n if (callee.property?.type !== 'Identifier' || callee.property.name !== 'send') return false;\n const obj = callee.object;\n return (\n obj?.type === 'MemberExpression' &&\n obj.property?.type === 'Identifier' &&\n obj.property.name === 'batch'\n );\n}\n\n/** True for either Resend send variant. */\nexport function isResendSendCall(node: any): boolean {\n return isResendEmailsSendCall(node) || isResendBatchSendCall(node);\n}\n\n/** Returns `arguments[index]` if it is an ObjectExpression, else null. */\nexport function getObjectArg(node: any, index: number): any | null {\n const arg = node?.arguments?.[index];\n return arg?.type === 'ObjectExpression' ? arg : null;\n}\n\n/**\n * Returns the per-email option object(s) for a send call:\n * - emails.send(payload) -> [payload]\n * - batch.send([email, email]) -> [email, email] (literal array only)\n * Returns [] when the relevant argument is not a plain object/array literal.\n */\nexport function getSendOptionObjects(node: any): any[] {\n if (isResendEmailsSendCall(node)) {\n const opts = getObjectArg(node, 0);\n return opts ? [opts] : [];\n }\n if (isResendBatchSendCall(node)) {\n const arr = node?.arguments?.[0];\n if (arr?.type !== 'ArrayExpression') return [];\n return (arr.elements ?? []).filter((el: any) => el?.type === 'ObjectExpression');\n }\n return [];\n}\n\n/** Returns the Property node named `name` on an ObjectExpression, else undefined. */\nexport function findProperty(objectExpression: any, name: string): any | undefined {\n if (objectExpression?.type !== 'ObjectExpression') return undefined;\n return objectExpression.properties?.find(\n (p: any) =>\n p?.type === 'Property' &&\n ((p.key?.type === 'Identifier' && p.key.name === name) ||\n (p.key?.type === 'Literal' && p.key.value === name)),\n );\n}\n\n/** True when the file path looks like a test file. */\nexport function isInsideTestFile(filename: string): boolean {\n return /(^|[\\\\/])__tests__[\\\\/]|\\.(test|spec)\\.[cm]?[jt]sx?$/.test(filename);\n}\n\n/** Best-effort absolute start offset of a node (range → start → loc fallback). */\nexport function startOffset(n: any): number {\n if (typeof n?.range?.[0] === 'number') return n.range[0];\n if (typeof n?.start === 'number') return n.start;\n return (n?.loc?.start?.line ?? 0) * 1_000_000 + (n?.loc?.start?.column ?? 0);\n}\n\n/** Best-effort absolute end offset of a node (range → end → loc fallback). */\nexport function endOffset(n: any): number {\n if (typeof n?.range?.[1] === 'number') return n.range[1];\n if (typeof n?.end === 'number') return n.end;\n return (n?.loc?.end?.line ?? n?.loc?.start?.line ?? 0) * 1_000_000 + (n?.loc?.end?.column ?? 0);\n}\n\n/** True when `outer`'s range fully contains `inner`'s start position. */\nexport function contains(outer: any, inner: any): boolean {\n const s = startOffset(inner);\n return s >= startOffset(outer) && s <= endOffset(outer);\n}\n","/**\n * resend-marketing-via-batch-send (correctness)\n *\n * Promotional content sent with `resend.batch.send` (the transactional batch\n * API) is the wrong tool — Resend's docs direct marketing sends to Broadcasts,\n * not batch send.\n *\n * Detection: a `.batch.send(...)` call in a file whose path indicates marketing\n * (campaign/marketing/newsletter/promotion/broadcast), e.g.\n * `app/api/emails/campaign/route.ts`.\n */\nimport { isResendBatchSendCall } from '../utils.js';\n\nconst MARKETING_PATH = /marketing|campaign|newsletter|promotion|broadcast/i;\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Marketing emails should use the Broadcasts API, not resend.batch.send',\n category: 'correctness',\n rationale:\n 'resend.batch.send is the transactional batch API; Resend documents Broadcasts as the correct feature for marketing and campaign sends. Using batch send for promotional mail skips audience management, consent tracking, and the automatic unsubscribe handling that Broadcasts provide, which puts you out of step with CAN-SPAM/CASL. Sending campaigns through Broadcasts (or the Dashboard) keeps deliverability and compliance intact.',\n docsUrl: 'https://resend.com/docs/dashboard/emails/batch-sending',\n recommended: true,\n },\n messages: {\n marketingViaBatch:\n 'Marketing/campaign email sent via resend.batch.send. Use the Broadcasts API for marketing sends.',\n },\n schema: [],\n },\n create(context: any) {\n const isMarketingFile = MARKETING_PATH.test(String(context.filename ?? ''));\n\n return {\n CallExpression(node: any) {\n if (!isMarketingFile) return;\n if (isResendBatchSendCall(node)) {\n context.report({ node, messageId: 'marketingViaBatch' });\n }\n },\n };\n },\n};\n\nexport const resendMarketingViaBatchSendRule = rule;\nexport default rule;\n","/**\n * resend-marketing-missing-unsubscribe (correctness)\n *\n * Marketing emails must give recipients a way to unsubscribe (CAN-SPAM /\n * CASL). Flags a Resend send whose `tags` mark it as\n * marketing while the same call provides neither a `List-Unsubscribe` header\n * nor the `{{{RESEND_UNSUBSCRIBE_URL}}}` placeholder in its HTML.\n */\nimport { findProperty, getSendOptionObjects } from '../utils.js';\n\nconst MARKETING_TAG = /marketing|campaign|newsletter|promotion/i;\nconst UNSUBSCRIBE_PLACEHOLDER = '{{{RESEND_UNSUBSCRIBE_URL}}}';\n\nfunction literalString(node: any): string | undefined {\n if (node?.type === 'Literal' && typeof node.value === 'string') return node.value;\n if (node?.type === 'TemplateLiteral') {\n return (node.quasis ?? [])\n .map((q: any) => q?.value?.cooked ?? q?.value?.raw ?? '')\n .join(' ');\n }\n return undefined;\n}\n\nfunction hasMarketingTag(opts: any): boolean {\n const tagsProp = findProperty(opts, 'tags');\n const arr = tagsProp?.value;\n if (arr?.type !== 'ArrayExpression') return false;\n for (const el of arr.elements ?? []) {\n if (el?.type !== 'ObjectExpression') continue;\n const valueProp = findProperty(el, 'value');\n const v = literalString(valueProp?.value);\n if (typeof v === 'string' && MARKETING_TAG.test(v)) return true;\n }\n return false;\n}\n\nfunction hasListUnsubscribeHeader(opts: any): boolean {\n const headersProp = findProperty(opts, 'headers');\n const obj = headersProp?.value;\n if (obj?.type !== 'ObjectExpression') return false;\n return (obj.properties ?? []).some((p: any) => {\n if (p?.type !== 'Property') return false;\n const key =\n p.key?.type === 'Literal'\n ? String(p.key.value)\n : p.key?.type === 'Identifier'\n ? p.key.name\n : '';\n return key.toLowerCase() === 'list-unsubscribe';\n });\n}\n\nfunction htmlHasUnsubscribePlaceholder(opts: any): boolean {\n const htmlProp = findProperty(opts, 'html');\n const text = literalString(htmlProp?.value);\n return typeof text === 'string' && text.includes(UNSUBSCRIBE_PLACEHOLDER);\n}\n\nfunction hasUnsubscribeMechanism(opts: any): boolean {\n return hasListUnsubscribeHeader(opts) || htmlHasUnsubscribePlaceholder(opts);\n}\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Marketing emails must include an unsubscribe mechanism',\n category: 'correctness',\n rationale:\n 'Marketing email is regulated by laws like CAN-SPAM (US) and CASL (Canada), which require recipients to be able to opt out. A campaign with only static \"you opted in\" text and no working unsubscribe path exposes you to legal penalties and gets flagged as spam, hurting deliverability for all your mail. Adding a List-Unsubscribe header (RFC 8058) or the {{{RESEND_UNSUBSCRIBE_URL}}} placeholder gives recipients a real way to opt out.',\n docsUrl: 'https://resend.com/docs/dashboard/broadcasts/introduction',\n recommended: true,\n },\n messages: {\n missingUnsubscribe:\n 'Marketing email has no unsubscribe mechanism (List-Unsubscribe header or {{{RESEND_UNSUBSCRIBE_URL}}}).',\n },\n schema: [],\n },\n create(context: any) {\n return {\n CallExpression(node: any) {\n for (const opts of getSendOptionObjects(node)) {\n if (hasMarketingTag(opts) && !hasUnsubscribeMechanism(opts)) {\n context.report({ node, messageId: 'missingUnsubscribe' });\n return;\n }\n }\n },\n };\n },\n};\n\nexport const resendMarketingMissingUnsubscribeRule = rule;\nexport default rule;\n","/**\n * resend-test-domain-in-production-path (correctness)\n *\n * `onboarding@resend.dev` is for testing only and must not be used as a\n * production from address (it 403s to non-owner recipients).\n * Flags the literal anywhere in non-test source, which also covers the\n * `process.env.RESEND_FROM_EMAIL ?? \"onboarding@resend.dev\"` fallback (the\n * fallback's right-hand side is the same string literal).\n *\n * Test files are skipped — using the test domain in tests is expected.\n */\nimport { isInsideTestFile } from '../utils.js';\n\nconst TEST_DOMAIN = 'onboarding@resend.dev';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Do not use the onboarding@resend.dev test domain in production code',\n category: 'correctness',\n rationale:\n 'onboarding@resend.dev is a shared test sender that only delivers to the account owner; sending from it to any other recipient returns a 403 error. Shipping it to production — including as a `?? \"onboarding@resend.dev\"` fallback — means real users silently never receive their email. Sending from a verified domain configured via process.env.RESEND_FROM_EMAIL is the documented production requirement.',\n docsUrl: 'https://resend.com/docs/send-with-nextjs',\n recommended: true,\n },\n messages: {\n testDomain:\n 'onboarding@resend.dev is a test-only sender. Use a verified domain (via process.env) in production.',\n },\n schema: [],\n },\n create(context: any) {\n if (isInsideTestFile(String(context.filename ?? ''))) return {};\n\n return {\n Literal(node: any) {\n if (typeof node.value === 'string' && node.value.includes(TEST_DOMAIN)) {\n context.report({ node, messageId: 'testDomain' });\n }\n },\n TemplateElement(node: any) {\n const cooked = node?.value?.cooked ?? node?.value?.raw;\n if (typeof cooked === 'string' && cooked.includes(TEST_DOMAIN)) {\n context.report({ node, messageId: 'testDomain' });\n }\n },\n };\n },\n};\n\nexport const resendTestDomainInProductionPathRule = rule;\nexport default rule;\n","/**\n * resend-from-address-not-friendly-format (integration)\n *\n * Resend doc examples use the friendly-name form\n * `Acme <onboarding@acme.com>`. Flags a `from` value that is a bare email\n * literal with no display name. Advisory only (info).\n */\nimport { findProperty, getSendOptionObjects } from '../utils.js';\n\n// Bare email: has an `@`, and no angle brackets (no \"Name <...>\" wrapper).\nconst BARE_EMAIL = /^[^<>]+@[^<>]+$/;\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Resend from addresses should use the friendly-name format \"Name <email>\"',\n category: 'integration',\n rationale:\n 'Every Resend doc example uses the friendly-name form \"Acme <onboarding@acme.com>\" rather than a bare email. A bare from address shows up in inboxes as a raw email string, which looks less trustworthy and can hurt open rates and brand recognition. Wrapping the address with a display name is a one-line change that matches the documented convention.',\n docsUrl: 'https://resend.com/docs/api-reference/emails/send-email',\n recommended: true,\n },\n messages: {\n bareFromAddress:\n 'From address is a bare email. Use the friendly format \"Name <email@domain>\" as shown in the docs.',\n },\n schema: [],\n },\n create(context: any) {\n return {\n CallExpression(node: any) {\n for (const opts of getSendOptionObjects(node)) {\n const fromProp = findProperty(opts, 'from');\n const value = fromProp?.value;\n if (\n value?.type === 'Literal' &&\n typeof value.value === 'string' &&\n BARE_EMAIL.test(value.value.trim())\n ) {\n context.report({ node: value, messageId: 'bareFromAddress' });\n }\n }\n },\n };\n },\n};\n\nexport const resendFromAddressNotFriendlyFormatRule = rule;\nexport default rule;\n","/**\n * resend-batch-size-not-enforced (reliability)\n *\n * resend.batch.send accepts at most 100 emails per call. Flags\n * `batch.send(<variable>)` when the enclosing function has no\n * `<variable>.length` guard.\n *\n * To avoid false positives on chunking, calls inside a loop are skipped (the\n * loop typically slices the array into <=100-sized chunks). Calls with a\n * literal array argument are also skipped (size is statically known).\n */\nimport { contains, isResendBatchSendCall, startOffset } from '../utils.js';\n\nconst FUNCTION_TYPES = new Set([\n 'FunctionDeclaration',\n 'FunctionExpression',\n 'ArrowFunctionExpression',\n]);\nconst LOOP_TYPES = new Set([\n 'ForStatement',\n 'ForOfStatement',\n 'ForInStatement',\n 'WhileStatement',\n 'DoWhileStatement',\n]);\nconst COMPARISON_OPERATORS = new Set(['>', '>=', '<', '<=', '===', '!==', '==', '!=']);\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Enforce the 100-email batch limit before calling resend.batch.send',\n category: 'reliability',\n rationale:\n 'resend.batch.send accepts at most 100 emails per call. Passing a user- or data-driven array without a length guard means the request fails outright once the list grows past 100, so an entire batch of notifications silently never sends. Guarding the array length (or chunking it into <=100-sized slices) keeps the send reliable as volume scales.',\n docsUrl: 'https://resend.com/docs/api-reference/emails/send-batch-emails',\n recommended: true,\n },\n messages: {\n batchSizeNotEnforced:\n 'resend.batch.send has a 100-email limit. Guard the array length (e.g. if (items.length > 100)) before sending.',\n },\n schema: [],\n },\n create(context: any) {\n const functions: any[] = [];\n const loops: any[] = [];\n // name -> list of nodes where `<name>.length` is compared against a number.\n const lengthChecks = new Map<string, any[]>();\n const batchCalls: { node: any; argName: string }[] = [];\n\n function isLengthOfName(member: any): string | null {\n if (member?.type !== 'MemberExpression') return null;\n if (member.property?.type !== 'Identifier' || member.property.name !== 'length') return null;\n if (member.object?.type !== 'Identifier') return null;\n return member.object.name;\n }\n\n return {\n FunctionDeclaration(node: any) {\n functions.push(node);\n },\n FunctionExpression(node: any) {\n functions.push(node);\n },\n ArrowFunctionExpression(node: any) {\n functions.push(node);\n },\n ForStatement(node: any) {\n loops.push(node);\n },\n ForOfStatement(node: any) {\n loops.push(node);\n },\n ForInStatement(node: any) {\n loops.push(node);\n },\n WhileStatement(node: any) {\n loops.push(node);\n },\n DoWhileStatement(node: any) {\n loops.push(node);\n },\n\n BinaryExpression(node: any) {\n if (!COMPARISON_OPERATORS.has(node.operator)) return;\n // Look for `<id>.length <op> <number>` (either side).\n for (const side of [node.left, node.right]) {\n const name = isLengthOfName(side);\n if (name) {\n const list = lengthChecks.get(name) ?? [];\n list.push(node);\n lengthChecks.set(name, list);\n }\n }\n },\n\n CallExpression(node: any) {\n if (!isResendBatchSendCall(node)) return;\n const arg = node.arguments?.[0];\n if (arg?.type !== 'Identifier') return; // literal arrays / expressions: out of scope\n batchCalls.push({ node, argName: arg.name });\n },\n\n 'Program:exit'() {\n for (const { node, argName } of batchCalls) {\n // Skip calls inside any loop (chunking pattern).\n if (loops.some((loop) => contains(loop, node))) continue;\n\n // Find the smallest enclosing function for the call.\n const enclosing = functions\n .filter((fn) => contains(fn, node))\n .sort((a, b) => startOffset(b) - startOffset(a))[0];\n\n // A length check on the same identifier inside the enclosing function counts.\n const checks = lengthChecks.get(argName) ?? [];\n const guarded = enclosing\n ? checks.some((chk) => contains(enclosing, chk))\n : checks.length > 0;\n\n if (!guarded) {\n context.report({ node, messageId: 'batchSizeNotEnforced' });\n }\n }\n },\n };\n },\n};\n\nexport const resendBatchSizeNotEnforcedRule = rule;\nexport default rule;\n","/**\n * resend-missing-idempotency-key (reliability)\n *\n * Send/batch calls should pass an idempotencyKey to prevent duplicate emails\n * on retries. Flags a Resend send call when no object\n * argument carries an `idempotencyKey` property. Checking every object argument\n * accepts the key whether it sits in the payload or a separate options arg.\n */\nimport { findProperty, isResendSendCall } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Resend send/batch calls should include an idempotencyKey',\n category: 'reliability',\n rationale:\n 'Without an idempotency key, if a network retry or webhook redelivery occurs, Resend will send the email multiple times. This causes duplicate charges, duplicate user notifications, and damaged sender reputation. Adding an idempotency key (a unique string per logical operation, like `welcome/${userId}`) makes the send safely retryable.',\n docsUrl: 'https://resend.com/docs/send-with-nextjs',\n recommended: true,\n },\n messages: {\n missingIdempotencyKey:\n 'Resend send call has no idempotencyKey. Add one to prevent duplicate sends on retry.',\n },\n schema: [],\n },\n create(context: any) {\n return {\n CallExpression(node: any) {\n if (!isResendSendCall(node)) return;\n const hasKey = (node.arguments ?? []).some(\n (arg: any) => arg?.type === 'ObjectExpression' && findProperty(arg, 'idempotencyKey'),\n );\n if (!hasKey) {\n context.report({ node, messageId: 'missingIdempotencyKey' });\n }\n },\n };\n },\n};\n\nexport const resendMissingIdempotencyKeyRule = rule;\nexport default rule;\n","/**\n * resend-no-error-code-mapping (reliability)\n *\n * Returning HTTP 500 for every Resend error is wrong — 400/401/403/422 are\n * client errors that should not be retried as 500s.\n *\n * Flags `if (error) { return ...500... }` where `error` is destructured from a\n * Resend send call in the same function, and the branch returns a hardcoded\n * 500 via `NextResponse.json(..., { status: 500 })` or `res.status(500)`.\n */\nimport {\n contains,\n findProperty,\n isResendSendCall,\n startOffset,\n} from '../utils.js';\n\nconst FUNCTION_TYPES = new Set([\n 'FunctionDeclaration',\n 'FunctionExpression',\n 'ArrowFunctionExpression',\n]);\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Resend errors should map to appropriate HTTP status codes, not a blanket 500',\n category: 'reliability',\n rationale:\n 'Resend returns different error classes that callers must treat differently: 400/422 mean fix the params and do not retry, 401/403 mean fix the key or domain, and 429/500 mean retry with backoff. Collapsing all of them into a blanket HTTP 500 tells the client to retry errors that will never succeed and hides the real cause from logs and monitoring. Mapping the SDK error code to the right status makes the API honest and lets clients react correctly.',\n docsUrl: 'https://resend.com/docs/ai-onboarding',\n recommended: true,\n },\n messages: {\n noErrorCodeMapping:\n 'Resend errors are returned as a blanket HTTP 500. Map 400/401/403/422 to non-500 statuses.',\n },\n schema: [],\n },\n create(context: any) {\n const functions: any[] = [];\n // `error` identifiers destructured from a Resend send call: { name, pos }.\n const resendErrorBindings: { name: string; pos: number }[] = [];\n // `if (<identifier>) {...}` statements with an Identifier test.\n const ifErrorStatements: { node: any; name: string; consequent: any }[] = [];\n // Positions of hardcoded-500 response expressions.\n const fiveHundredNodes: any[] = [];\n\n function initIsResendSend(init: any): boolean {\n if (!init) return false;\n const expr = init.type === 'AwaitExpression' ? init.argument : init;\n return isResendSendCall(expr);\n }\n\n function isNextResponse500(node: any): boolean {\n // <X>.json(body, { status: 500 })\n const callee = node.callee;\n if (callee?.type !== 'MemberExpression') return false;\n if (callee.property?.type !== 'Identifier' || callee.property.name !== 'json') return false;\n const opts = node.arguments?.[1];\n const statusProp = findProperty(opts, 'status');\n return statusProp?.value?.type === 'Literal' && statusProp.value.value === 500;\n }\n\n function isResStatus500(node: any): boolean {\n // res.status(500)\n const callee = node.callee;\n if (callee?.type !== 'MemberExpression') return false;\n if (callee.property?.type !== 'Identifier' || callee.property.name !== 'status') return false;\n const arg = node.arguments?.[0];\n return arg?.type === 'Literal' && arg.value === 500;\n }\n\n return {\n FunctionDeclaration(node: any) {\n functions.push(node);\n },\n FunctionExpression(node: any) {\n functions.push(node);\n },\n ArrowFunctionExpression(node: any) {\n functions.push(node);\n },\n\n VariableDeclarator(node: any) {\n if (!initIsResendSend(node.init)) return;\n if (node.id?.type !== 'ObjectPattern') return;\n const errorProp = (node.id.properties ?? []).find(\n (p: any) => p?.type === 'Property' && p.key?.type === 'Identifier' && p.key.name === 'error',\n );\n if (!errorProp) return;\n const localName =\n errorProp.value?.type === 'Identifier' ? errorProp.value.name : 'error';\n resendErrorBindings.push({ name: localName, pos: startOffset(node) });\n },\n\n IfStatement(node: any) {\n if (node.test?.type === 'Identifier') {\n ifErrorStatements.push({ node, name: node.test.name, consequent: node.consequent });\n }\n },\n\n CallExpression(node: any) {\n if (isNextResponse500(node) || isResStatus500(node)) {\n fiveHundredNodes.push(node);\n }\n },\n\n 'Program:exit'() {\n for (const { node, name, consequent } of ifErrorStatements) {\n // The branch must return a hardcoded 500.\n const has500 = fiveHundredNodes.some((five) => contains(consequent, five));\n if (!has500) continue;\n\n // The `error` must be bound from a Resend send call in the same function.\n const enclosing = functions\n .filter((fn) => contains(fn, node))\n .sort((a, b) => startOffset(b) - startOffset(a))[0];\n const boundFromResend = resendErrorBindings.some(\n (b) => b.name === name && (enclosing ? contains(enclosing, { range: [b.pos, b.pos] }) : true),\n );\n if (boundFromResend) {\n context.report({ node, messageId: 'noErrorCodeMapping' });\n }\n }\n },\n };\n },\n};\n\nexport const resendNoErrorCodeMappingRule = rule;\nexport default rule;\n","/**\n * resend-webhook-no-idempotency (reliability)\n *\n * Resend retries failed webhooks for up to 24 hours, so handlers must\n * deduplicate events. A file is treated as a\n * Resend webhook handler only when it imports `svix` (Resend's webhook\n * verification library) and exports a POST handler. The handler is flagged when\n * it contains no deduplication signal:\n * - new Map() / new Set()\n * - a call on a store-like object (redis, kv, db, prisma, supabase, cache)\n * - a dedup method (has/add/sadd/sismember/exists/findUnique/findFirst/upsert)\n * - a reference to an event id (e.g. event.data.email_id)\n */\nimport { endOffset, startOffset } from '../utils.js';\n\nconst DEDUP_OBJECTS = new Set(['redis', 'kv', 'db', 'prisma', 'supabase', 'cache', 'store']);\nconst DEDUP_METHODS = new Set([\n 'has',\n 'add',\n 'sadd',\n 'sismember',\n 'exists',\n 'findUnique',\n 'findFirst',\n 'upsert',\n]);\nconst EVENT_ID_PROPS = new Set(['email_id', 'eventId', 'event_id']);\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Resend webhook handlers should deduplicate retried events',\n category: 'reliability',\n rationale:\n 'Resend retries failed webhook deliveries for up to 24 hours, so the same event can legitimately arrive more than once. A handler that acts on every delivery without deduplication will double-process events — sending duplicate downstream notifications, double-counting metrics, or corrupting state. Tracking processed event ids (e.g. event.data.email_id) in a store or set and skipping ones already seen makes the handler safely idempotent.',\n docsUrl: 'https://resend.com/docs/dashboard/webhooks/introduction',\n recommended: true,\n },\n messages: {\n noIdempotency:\n 'Resend webhook handler has no deduplication. Resend retries for 24h; track processed event ids.',\n },\n schema: [],\n },\n create(context: any) {\n let importsSvix = false;\n const postHandlers: any[] = [];\n const dedupSignals: any[] = [];\n\n function collectPostHandler(decl: any): void {\n if (!decl) return;\n if (decl.type === 'FunctionDeclaration' && decl.id?.name === 'POST') {\n postHandlers.push(decl);\n return;\n }\n if (decl.type === 'VariableDeclaration') {\n for (const d of decl.declarations ?? []) {\n if (\n d?.id?.type === 'Identifier' &&\n d.id.name === 'POST' &&\n (d.init?.type === 'ArrowFunctionExpression' || d.init?.type === 'FunctionExpression')\n ) {\n postHandlers.push(d.init);\n }\n }\n }\n }\n\n return {\n ImportDeclaration(node: any) {\n if (node?.source?.value === 'svix') importsSvix = true;\n },\n\n ExportNamedDeclaration(node: any) {\n collectPostHandler(node.declaration);\n },\n\n NewExpression(node: any) {\n if (node.callee?.type === 'Identifier' && (node.callee.name === 'Map' || node.callee.name === 'Set')) {\n dedupSignals.push(node);\n }\n },\n\n CallExpression(node: any) {\n const callee = node.callee;\n if (callee?.type !== 'MemberExpression') return;\n const objName =\n callee.object?.type === 'Identifier' ? callee.object.name : undefined;\n const methodName = callee.property?.type === 'Identifier' ? callee.property.name : undefined;\n if ((objName && DEDUP_OBJECTS.has(objName)) || (methodName && DEDUP_METHODS.has(methodName))) {\n dedupSignals.push(node);\n }\n },\n\n MemberExpression(node: any) {\n if (node.property?.type === 'Identifier' && EVENT_ID_PROPS.has(node.property.name)) {\n dedupSignals.push(node);\n }\n },\n\n 'Program:exit'() {\n if (!importsSvix) return;\n for (const handler of postHandlers) {\n const hasDedup = dedupSignals.some(\n (sig) => startOffset(sig) >= startOffset(handler) && endOffset(sig) <= endOffset(handler),\n );\n if (!hasDedup) {\n context.report({ node: handler, messageId: 'noIdempotency' });\n }\n }\n },\n };\n },\n};\n\nexport const resendWebhookNoIdempotencyRule = rule;\nexport default rule;\n","/**\n * resend-missing-tags (integration)\n *\n * Tags power deliverability segmentation in the Resend dashboard. Flags a\n * Resend send whose statically-visible email option object(s) omit a `tags`\n * property. Dynamic argument shapes (e.g. batch built via `.map()`) are skipped\n * to avoid false positives. Advisory only (info).\n */\nimport { findProperty, getSendOptionObjects, isResendSendCall } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Resend sends should include tags for deliverability segmentation',\n category: 'integration',\n rationale:\n 'Tags are how Resend segments and filters email in the dashboard and analytics, so sends without them collapse into one undifferentiated stream. When deliverability dips or you need to trace a specific campaign, untagged mail gives you nothing to slice on. Adding tags such as [{ name: \"category\", value: \"welcome\" }] makes monitoring and debugging across email types possible.',\n docsUrl: 'https://resend.com/docs/dashboard/emails/tags',\n recommended: true,\n },\n messages: {\n missingTags:\n 'Resend send has no tags. Add tags (e.g. [{ name: \"category\", value: \"welcome\" }]) for segmentation.',\n },\n schema: [],\n },\n create(context: any) {\n return {\n CallExpression(node: any) {\n if (!isResendSendCall(node)) return;\n const optionObjects = getSendOptionObjects(node);\n if (optionObjects.length === 0) return; // dynamic shape: cannot tell\n const someMissingTags = optionObjects.some((opts) => !findProperty(opts, 'tags'));\n if (someMissingTags) {\n context.report({ node, messageId: 'missingTags' });\n }\n },\n };\n },\n};\n\nexport const resendMissingTagsRule = rule;\nexport default rule;\n","/**\n * resend-request-id-not-logged (integration)\n *\n * When handling a Resend error, logging the request id makes\n * support/debugging far easier. Flags an error-handling block\n * (a `catch` clause or an `if (error)` block) in a file that imports `resend`,\n * which references `<error>.message` but never references a request-id header\n * (`x-request-id` or `x-resend-request-id`). Advisory only (info).\n */\nimport { endOffset, startOffset } from '../utils.js';\n\nconst REQUEST_ID_HEADERS = new Set(['x-request-id', 'x-resend-request-id']);\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Log the Resend request id when handling errors',\n category: 'integration',\n rationale:\n 'Every Resend API response carries a request id (x-request-id / x-resend-request-id) that uniquely identifies the call on their side. When something goes wrong, logging only error.message leaves you and Resend support with no way to find the exact failed request. Logging the request id alongside the message turns a vague \"send failed\" into a traceable incident that support can look up directly.',\n docsUrl: 'https://resend.com/docs/api-reference/errors',\n recommended: true,\n },\n messages: {\n requestIdNotLogged:\n 'Error handler logs error.message but not the Resend request id (x-request-id / x-resend-request-id).',\n },\n schema: [],\n },\n create(context: any) {\n let importsResend = false;\n const scopes: { node: any; name: string; range: [number, number] }[] = [];\n const messageAccesses: { name: string; pos: number }[] = [];\n const requestIdPositions: number[] = [];\n\n function within(range: [number, number], pos: number): boolean {\n return pos >= range[0] && pos <= range[1];\n }\n\n return {\n ImportDeclaration(node: any) {\n if (node?.source?.value === 'resend') importsResend = true;\n },\n\n CatchClause(node: any) {\n const param = node.param;\n if (param?.type === 'Identifier' && node.body) {\n scopes.push({\n node,\n name: param.name,\n range: [startOffset(node.body), endOffset(node.body)],\n });\n }\n },\n\n IfStatement(node: any) {\n if (node.test?.type === 'Identifier' && node.consequent) {\n scopes.push({\n node,\n name: node.test.name,\n range: [startOffset(node.consequent), endOffset(node.consequent)],\n });\n }\n },\n\n MemberExpression(node: any) {\n // `<name>.message`\n if (\n node.property?.type === 'Identifier' &&\n node.property.name === 'message' &&\n node.object?.type === 'Identifier'\n ) {\n messageAccesses.push({ name: node.object.name, pos: startOffset(node) });\n }\n },\n\n Literal(node: any) {\n if (typeof node.value === 'string' && REQUEST_ID_HEADERS.has(node.value.toLowerCase())) {\n requestIdPositions.push(startOffset(node));\n }\n },\n\n 'Program:exit'() {\n if (!importsResend) return;\n for (const scope of scopes) {\n const logsMessage = messageAccesses.some(\n (m) => m.name === scope.name && within(scope.range, m.pos),\n );\n if (!logsMessage) continue;\n const logsRequestId = requestIdPositions.some((pos) => within(scope.range, pos));\n if (!logsRequestId) {\n context.report({ node: scope.node, messageId: 'requestIdNotLogged' });\n }\n }\n },\n };\n },\n};\n\nexport const resendRequestIdNotLoggedRule = rule;\nexport default rule;\n","/**\n * Shared AST helpers for Supabase rules. Kept intentionally small; extend\n * only when logic is genuinely reused across rules.\n */\n\n/** Returns the property name of a (possibly computed) MemberExpression callee, e.g. `obj[\"select\"]()` -> 'select'. */\nexport function memberPropName(node: any): string | undefined {\n if (node?.type !== 'CallExpression') return undefined;\n const callee = node.callee;\n if (callee?.type !== 'MemberExpression') return undefined;\n const prop = callee.property;\n if (!callee.computed && prop?.type === 'Identifier') return prop.name;\n if (callee.computed && prop?.type === 'Literal' && typeof prop.value === 'string') {\n return prop.value;\n }\n return undefined;\n}\n\n/** The CallExpression this call is chained onto (`<this>.method()`), or null if the base isn't itself a call. */\nexport function chainObjectCall(node: any): any | null {\n const obj = node?.callee?.object;\n return obj?.type === 'CallExpression' ? obj : null;\n}\n\n/** Splits a Supabase `.select(\"a, b, c\")` string literal argument into trimmed column names. */\nexport function parseSelectColumns(arg: any): string[] {\n if (arg?.type !== 'Literal' || typeof arg.value !== 'string') return [];\n return arg.value\n .split(',')\n .map((c: string) => c.trim())\n .filter(Boolean);\n}\n\n/** True for column names that look like a tenant/ownership scoping key, e.g. `session_id`, `user_id` (not the bare `id` PK). */\nexport function isTenantColumnName(name: string): boolean {\n return /^[a-z][a-z0-9]*_id$/i.test(name) && name.toLowerCase() !== 'id';\n}\n\n/** True for column names that look like a timestamp, e.g. `created_at`, `updated_at`. */\nexport function isTimestampColumnName(name: string): boolean {\n return /^[a-z][a-z0-9]*_at$/i.test(name);\n}\n\n/** True when `node` is the `.from(\"table\")` base of a Supabase query chain. */\nexport function isSupabaseFromCall(node: any): boolean {\n return memberPropName(node) === 'from' && node?.callee?.object?.type === 'Identifier';\n}\n\n/** Returns the table name from a `.from(\"table\")` call anywhere in the chain. */\nexport function fromTableName(node: any): string | undefined {\n let current: any | null = node;\n while (current?.type === 'CallExpression') {\n if (memberPropName(current) === 'from') {\n const arg = current.arguments?.[0];\n return arg?.type === 'Literal' && typeof arg.value === 'string' ? arg.value : undefined;\n }\n current = chainObjectCall(current);\n }\n return undefined;\n}\n\n/** True when a chained Supabase call includes `.single()`. */\nexport function chainHasMethod(node: any, method: string): boolean {\n let current: any | null = node;\n while (current?.type === 'CallExpression') {\n if (memberPropName(current) === method) return true;\n current = chainObjectCall(current);\n }\n return false;\n}\n\nexport function isSupabaseMutationKind(\n node: any,\n kind: 'delete' | 'insert' | 'update' | 'upsert',\n): boolean {\n if (!chainHasMethod(node, kind)) return false;\n let current: any | null = node;\n while (current?.type === 'CallExpression') {\n if (memberPropName(current) === 'from') return true;\n current = chainObjectCall(current);\n }\n return false;\n}\n\n/** Property names on `user_metadata` that should never gate authorization. */\nconst USER_METADATA_AUTHZ_KEYS = new Set([\n 'role',\n 'roles',\n 'admin',\n 'is_admin',\n 'permission',\n 'permissions',\n]);\n\n/** True when `node` reads an auth-sensitive field from `user_metadata`. */\nexport function isUserMetadataAuthzRead(node: any): boolean {\n if (node?.type !== 'MemberExpression') return false;\n const parts: string[] = [];\n let current: any = node;\n while (current?.type === 'MemberExpression') {\n const prop = current.property;\n const name =\n !current.computed && prop?.type === 'Identifier'\n ? prop.name\n : prop?.type === 'Literal' && typeof prop.value === 'string'\n ? prop.value\n : undefined;\n if (name) parts.unshift(name);\n current = current.object;\n }\n const metaIdx = parts.indexOf('user_metadata');\n if (metaIdx === -1) return false;\n const field = parts[metaIdx + 1];\n return typeof field === 'string' && USER_METADATA_AUTHZ_KEYS.has(field);\n}\n\n/** Returns binding names destructured from `pattern` (ObjectPattern or Identifier). */\nexport function destructuredNames(pattern: any): Set<string> {\n const names = new Set<string>();\n if (!pattern) return names;\n if (pattern.type === 'Identifier') {\n names.add(pattern.name);\n return names;\n }\n if (pattern.type !== 'ObjectPattern') return names;\n for (const prop of pattern.properties ?? []) {\n if (prop?.type === 'Property') {\n if (prop.value?.type === 'Identifier') names.add(prop.value.name);\n else if (prop.key?.type === 'Identifier' && prop.shorthand) names.add(prop.key.name);\n else if (prop.key?.type === 'Identifier' && prop.value?.type === 'Identifier') {\n names.add(prop.value.name);\n }\n } else if (prop?.type === 'RestElement' && prop.argument?.type === 'Identifier') {\n names.add(prop.argument.name);\n }\n }\n return names;\n}\n\n/**\n * Resolves the source identifier name backing an insert/upsert object\n * property's value: shorthand (`{ x }`), a bare identifier (`{ x: y }`), or\n * an identifier guarded by `??`/`||` (`{ x: y ?? null }`, common for\n * optional fields) — the left side of the fallback is what was validated.\n */\nexport function resolvePropertyValueName(prop: any): string | undefined {\n if (prop?.shorthand && prop.key?.type === 'Identifier') return prop.key.name;\n const value = prop?.value;\n if (value?.type === 'Identifier') return value.name;\n if (value?.type === 'LogicalExpression' && (value.operator === '??' || value.operator === '||')) {\n if (value.left?.type === 'Identifier') return value.left.name;\n }\n return undefined;\n}\n\n/** If `node` is `typeof <ident> === \"string\"` (or `!==`), returns `<ident>`'s name. */\nexport function typeofStringCheckTarget(node: any): string | undefined {\n if (node?.type !== 'BinaryExpression') return undefined;\n if (node.operator !== '===' && node.operator !== '!==') return undefined;\n const sides = [node.left, node.right];\n const typeofSide = sides.find(\n (s: any) =>\n s?.type === 'UnaryExpression' && s.operator === 'typeof' && s.argument?.type === 'Identifier',\n );\n const litSide = sides.find((s: any) => s?.type === 'Literal' && s.value === 'string');\n if (!typeofSide || !litSide) return undefined;\n return typeofSide.argument.name;\n}\n","/**\n * supabase-scope-queries-by-tenant-column (correctness)\n *\n * A `.from(table).select(...)` query that selects a tenant/ownership-style\n * column (e.g. `session_id`, `user_id`) but never filters by it (`.eq()`,\n * `.match()`, `.filter()`) reads every row across every tenant instead of\n * scoping to the caller's own data.\n *\n * Detection walks each query chain bottom-up (`CallExpression:exit`, so\n * inner calls are visited before the calls built on top of them) and\n * threads a shared chain-state object outward through `chainObjectCall`,\n * so a `.eq()` two links up the chain is still recorded against the\n * `.select()` that introduced the tenant column.\n */\nimport { chainObjectCall, isTenantColumnName, memberPropName, parseSelectColumns } from '../utils.js';\n\ninterface ChainState {\n selectNode: any;\n tenantColumns: string[];\n filteredColumns: Set<string>;\n}\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Supabase queries that select a tenant column must filter by it',\n category: 'correctness',\n rationale:\n 'A column like session_id or user_id existing in the schema (and being selected) signals intent to scope rows to one caller, but selecting it is not the same as filtering by it. Without an .eq()/.match()/.filter() on that column, the query returns every row for every tenant, turning a per-user feed into a single shared, cross-user one.',\n docsUrl: 'https://supabase.com/docs/reference/javascript/eq',\n recommended: true,\n },\n messages: {\n missingTenantFilter:\n 'This query selects \"{{column}}\" but never filters by it. Add .eq(\"{{column}}\", ...) (or .match()/.filter()) to scope results to the caller.',\n },\n schema: [],\n },\n create(context: any) {\n const chainStates = new Map<any, ChainState>();\n const selectStates: ChainState[] = [];\n\n function recordFilteredColumn(state: ChainState, name: unknown) {\n if (typeof name === 'string') state.filteredColumns.add(name);\n else state.filteredColumns.add('*');\n }\n\n return {\n 'CallExpression:exit'(node: any) {\n const prop = memberPropName(node);\n if (!prop) return;\n\n const objCall = chainObjectCall(node);\n\n if (prop === 'select' && objCall && memberPropName(objCall) === 'from') {\n const columns = parseSelectColumns(node.arguments?.[0]);\n const tenantColumns = columns.filter(isTenantColumnName);\n if (tenantColumns.length === 0) return;\n const state: ChainState = { selectNode: node, tenantColumns, filteredColumns: new Set() };\n chainStates.set(node, state);\n selectStates.push(state);\n return;\n }\n\n const state = objCall ? chainStates.get(objCall) : undefined;\n if (!state) return;\n\n if (prop === 'eq' || prop === 'filter') {\n const colArg = node.arguments?.[0];\n recordFilteredColumn(state, colArg?.type === 'Literal' ? colArg.value : undefined);\n } else if (prop === 'match') {\n const objArg = node.arguments?.[0];\n if (objArg?.type === 'ObjectExpression') {\n for (const p of objArg.properties ?? []) {\n if (p?.type !== 'Property') continue;\n const name =\n p.key?.type === 'Identifier'\n ? p.key.name\n : p.key?.type === 'Literal'\n ? p.key.value\n : undefined;\n recordFilteredColumn(state, name);\n }\n } else {\n recordFilteredColumn(state, undefined);\n }\n }\n\n chainStates.set(node, state);\n },\n\n 'Program:exit'() {\n for (const state of selectStates) {\n if (state.filteredColumns.has('*')) continue;\n const missing = state.tenantColumns.find((c) => !state.filteredColumns.has(c));\n if (missing) {\n context.report({\n node: state.selectNode,\n messageId: 'missingTenantFilter',\n data: { column: missing },\n });\n }\n }\n },\n };\n },\n};\n\nexport const supabaseScopeQueriesByTenantColumnRule = rule;\nexport default rule;\n","/**\n * supabase-validate-uuid-columns (correctness)\n *\n * A value validated only with `typeof x === \"string\"` (or `!== \"string\"`)\n * before being inserted/upserted into a uuid-typed column passes app\n * validation for any non-UUID string, then fails at the database with a\n * Postgres type-cast error — surfacing a client-correctable 400 as a\n * generic 500.\n *\n * Tracks, per file, which identifiers have been typeof-string-checked and\n * which have separately passed a UUID-shaped regex `.test()` call, then at\n * each `.from(table).insert(...)`/`.upsert(...)` call cross-references the\n * inserted object's tenant/id-style columns (e.g. `session_id`) against\n * that state.\n */\nimport {\n chainObjectCall,\n isTenantColumnName,\n memberPropName,\n resolvePropertyValueName,\n typeofStringCheckTarget,\n} from '../utils.js';\n\ninterface VarValidation {\n typeofOnly: boolean;\n uuidChecked: boolean;\n}\n\n// Loose heuristic for \"this regex checks UUID shape\": hex-looking character\n// classes combined with a literal hyphen, regardless of the regex's variable\n// name (so `UUID_RE` and a differently-named-but-equivalent pattern both count).\nfunction regexSourceLooksUuidShaped(pattern: string): boolean {\n return /[0-9a-f]{2,}/i.test(pattern) && pattern.includes('-');\n}\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Columns typed uuid must be validated for UUID shape, not just typeof string',\n category: 'correctness',\n rationale:\n 'typeof === \"string\" accepts any string, including malformed UUIDs like \"abc\". When the underlying column is typed uuid, the database rejects it with a generic type-cast error that the app then has to collapse into an opaque 500 — masking a client-correctable 400 as a server failure. Validating the UUID shape (e.g. with a regex) before the insert lets the app return a precise 400 instead.',\n docsUrl: 'https://supabase.com/docs/guides/database/tables#data-types',\n recommended: true,\n },\n messages: {\n missingUuidValidation:\n 'Column \"{{column}}\" looks UUID-typed but the value is only checked with typeof === \"string\", not a UUID-shape regex. Validate the format before insert/upsert.',\n },\n schema: [],\n },\n create(context: any) {\n const validations = new Map<string, VarValidation>();\n const regexVarPatterns = new Map<string, string>();\n\n function markValidation(name: string, key: keyof VarValidation) {\n let v = validations.get(name);\n if (!v) {\n v = { typeofOnly: false, uuidChecked: false };\n validations.set(name, v);\n }\n v[key] = true;\n }\n\n return {\n VariableDeclarator(node: any) {\n if (node.id?.type === 'Identifier' && node.init?.type === 'Literal' && node.init.regex) {\n regexVarPatterns.set(node.id.name, node.init.regex.pattern);\n }\n },\n\n BinaryExpression(node: any) {\n const varName = typeofStringCheckTarget(node);\n if (varName) markValidation(varName, 'typeofOnly');\n },\n\n CallExpression(node: any) {\n const prop = memberPropName(node);\n\n if (prop === 'test') {\n const objNode = node.callee.object;\n let pattern: string | undefined;\n if (objNode?.type === 'Literal' && objNode.regex) {\n pattern = objNode.regex.pattern;\n } else if (objNode?.type === 'Identifier' && regexVarPatterns.has(objNode.name)) {\n pattern = regexVarPatterns.get(objNode.name);\n }\n if (pattern && regexSourceLooksUuidShaped(pattern)) {\n const arg = node.arguments?.[0];\n if (arg?.type === 'Identifier') markValidation(arg.name, 'uuidChecked');\n }\n return;\n }\n\n if (prop !== 'insert' && prop !== 'upsert') return;\n const objCall = chainObjectCall(node);\n if (!objCall || memberPropName(objCall) !== 'from') return;\n\n const arg = node.arguments?.[0];\n if (arg?.type !== 'ObjectExpression') return;\n\n for (const p of arg.properties ?? []) {\n if (p?.type !== 'Property') continue;\n const keyName =\n p.key?.type === 'Identifier'\n ? p.key.name\n : p.key?.type === 'Literal'\n ? p.key.value\n : undefined;\n if (typeof keyName !== 'string' || !isTenantColumnName(keyName)) continue;\n\n const valueName = resolvePropertyValueName(p);\n if (!valueName) continue;\n\n const v = validations.get(valueName);\n if (v?.typeofOnly && !v.uuidChecked) {\n context.report({ node: p, messageId: 'missingUuidValidation', data: { column: keyName } });\n }\n }\n },\n };\n },\n};\n\nexport const supabaseValidateUuidColumnsRule = rule;\nexport default rule;\n","/**\n * supabase-order-by-timestamp-not-identity (correctness)\n *\n * `.order(\"id\", ...)` \"works\" only because a `bigint identity always` PK\n * happens to be monotonic with insert order today — a correctness smell\n * that breaks under any future bulk-insert/backfill/replication scenario.\n * When the same query already selects a purpose-built timestamp column\n * (e.g. `created_at`), that column — not the surrogate key — should drive\n * the ordering.\n *\n * Like scope-queries-by-tenant-column, this walks each query chain\n * bottom-up (`CallExpression:exit`) so the `.select()` that introduced the\n * candidate timestamp column(s) is already recorded by the time the\n * `.order()` built on top of it is visited.\n */\nimport { chainObjectCall, isTimestampColumnName, memberPropName, parseSelectColumns } from '../utils.js';\n\ninterface ChainState {\n timestampColumns: string[];\n}\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Order by a selected timestamp column instead of the identity column',\n category: 'correctness',\n rationale:\n 'Ordering by a bigint identity PK only produces correct chronological order because the PK happens to be monotonic with insert order today. That assumption breaks under bulk inserts, backfills, or replication where PK order and time order can diverge. When the query already selects a timestamp column built for this purpose, order by it instead of the surrogate key.',\n docsUrl: 'https://supabase.com/docs/reference/javascript/order',\n recommended: true,\n },\n messages: {\n orderByIdentity:\n 'This query selects \"{{column}}\" but orders by \"id\" instead. Order by \"{{column}}\" so result order does not depend on PK/insert-order coincidence.',\n },\n schema: [],\n },\n create(context: any) {\n const chainStates = new Map<any, ChainState>();\n\n return {\n 'CallExpression:exit'(node: any) {\n const prop = memberPropName(node);\n if (!prop) return;\n\n const objCall = chainObjectCall(node);\n\n if (prop === 'select' && objCall && memberPropName(objCall) === 'from') {\n const columns = parseSelectColumns(node.arguments?.[0]);\n const timestampColumns = columns.filter(isTimestampColumnName);\n chainStates.set(node, { timestampColumns });\n return;\n }\n\n const state = objCall ? chainStates.get(objCall) : undefined;\n if (!state) return;\n\n if (prop === 'order') {\n const colArg = node.arguments?.[0];\n const orderColumn = colArg?.type === 'Literal' ? colArg.value : undefined;\n if (\n typeof orderColumn === 'string' &&\n orderColumn.toLowerCase() === 'id' &&\n state.timestampColumns.length > 0\n ) {\n context.report({\n node,\n messageId: 'orderByIdentity',\n data: { column: state.timestampColumns[0] },\n });\n }\n }\n\n chainStates.set(node, state);\n },\n };\n },\n};\n\nexport const supabaseOrderByTimestampNotIdentityRule = rule;\nexport default rule;\n","/**\n * supabase-consistent-input-length-limits (correctness)\n *\n * When several string fields are inserted together (e.g. all properties of\n * one `.insert(...)` call), and some of them are validated with an explicit\n * `.length > N` cap while at least one sibling field is only type-checked,\n * the uncapped field is usually the one the agent forgot — not a field that\n * was deliberately left unbounded. Flags the inconsistency, not \"missing a\n * cap\" in isolation (a single uncapped field with no capped siblings is out\n * of scope for this rule).\n */\nimport { chainObjectCall, memberPropName, resolvePropertyValueName, typeofStringCheckTarget } from '../utils.js';\n\ninterface VarValidation {\n typeofStringChecked: boolean;\n hasLengthCap: boolean;\n}\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Sibling string fields inserted together should share the same length cap discipline',\n category: 'correctness',\n rationale:\n 'A field with no length cap on an otherwise-validated, unauthenticated insert path lets a client persist arbitrarily large payloads repeatedly, growing storage with no bound. When sibling fields in the same insert already have explicit length caps, an uncapped field next to them is usually an oversight rather than an intentional choice.',\n docsUrl: 'https://supabase.com/docs/guides/database/tables',\n recommended: true,\n },\n messages: {\n inconsistentLengthLimit:\n 'Field \"{{field}}\" has no length cap, but sibling field \"{{cappedField}}\" in the same insert does. Add a .length check for \"{{field}}\" too.',\n },\n schema: [],\n },\n create(context: any) {\n const validations = new Map<string, VarValidation>();\n\n function markValidation(name: string, key: keyof VarValidation) {\n let v = validations.get(name);\n if (!v) {\n v = { typeofStringChecked: false, hasLengthCap: false };\n validations.set(name, v);\n }\n v[key] = true;\n }\n\n function lengthCapTarget(node: any): string | undefined {\n if (node?.type !== 'BinaryExpression') return undefined;\n if (node.operator !== '>' && node.operator !== '>=') return undefined;\n const left = node.left;\n const right = node.right;\n if (left?.type !== 'MemberExpression') return undefined;\n if (left.property?.type !== 'Identifier' || left.property.name !== 'length') return undefined;\n if (left.object?.type !== 'Identifier') return undefined;\n if (right?.type !== 'Literal' || typeof right.value !== 'number') return undefined;\n return left.object.name;\n }\n\n return {\n BinaryExpression(node: any) {\n const typeofVar = typeofStringCheckTarget(node);\n if (typeofVar) markValidation(typeofVar, 'typeofStringChecked');\n\n const lengthVar = lengthCapTarget(node);\n if (lengthVar) markValidation(lengthVar, 'hasLengthCap');\n },\n\n CallExpression(node: any) {\n const prop = memberPropName(node);\n if (prop !== 'insert' && prop !== 'upsert') return;\n const objCall = chainObjectCall(node);\n if (!objCall || memberPropName(objCall) !== 'from') return;\n\n const arg = node.arguments?.[0];\n if (arg?.type !== 'ObjectExpression') return;\n\n const stringFields: { propNode: any; field: string; varName: string }[] = [];\n for (const p of arg.properties ?? []) {\n if (p?.type !== 'Property') continue;\n const field =\n p.key?.type === 'Identifier'\n ? p.key.name\n : p.key?.type === 'Literal'\n ? p.key.value\n : undefined;\n if (typeof field !== 'string') continue;\n const varName = resolvePropertyValueName(p);\n if (!varName) continue;\n const v = validations.get(varName);\n if (v?.typeofStringChecked) stringFields.push({ propNode: p, field, varName });\n }\n\n const capped = stringFields.filter((f) => validations.get(f.varName)?.hasLengthCap);\n const uncapped = stringFields.filter((f) => !validations.get(f.varName)?.hasLengthCap);\n if (capped.length === 0 || uncapped.length === 0) return;\n\n for (const f of uncapped) {\n context.report({\n node: f.propNode,\n messageId: 'inconsistentLengthLimit',\n data: { field: f.field, cappedField: capped[0].field },\n });\n }\n },\n };\n },\n};\n\nexport const supabaseConsistentInputLengthLimitsRule = rule;\nexport default rule;\n","/**\n * supabase-idempotent-mutations (reliability)\n *\n * `.insert(...)` with no idempotency/dedupe key field is not safely\n * retryable: a flaky network retry, double-click, or browser replay creates\n * a duplicate row. `.upsert(..., { onConflict: ... })` is the documented\n * fix and is exempt — only plain `.insert()` calls are checked.\n */\nimport { chainObjectCall, memberPropName } from '../utils.js';\n\nfunction objectHasIdempotencyKey(objectExpression: any): boolean {\n if (objectExpression?.type !== 'ObjectExpression') return false;\n return (objectExpression.properties ?? []).some((p: any) => {\n if (p?.type !== 'Property') return false;\n const name =\n p.key?.type === 'Identifier' ? p.key.name : p.key?.type === 'Literal' ? p.key.value : undefined;\n return typeof name === 'string' && /idempot|dedupe/i.test(name);\n });\n}\n\nfunction insertPayloadHasIdempotencyKey(arg: any): boolean {\n if (arg?.type === 'ObjectExpression') return objectHasIdempotencyKey(arg);\n if (arg?.type === 'ArrayExpression') {\n return (arg.elements ?? []).some((el: any) => objectHasIdempotencyKey(el));\n }\n return false;\n}\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Supabase insert calls should be retry-safe via an idempotency key',\n category: 'reliability',\n rationale:\n 'Nothing prevents a duplicate row if the client fetch behind an insert is retried (flaky network, double-click, browser replay) — there is no unique constraint or dedupe key visible in the payload, and no upsert semantics. Generate a client-side idempotency key per logical action and either include it as a field guarded by a unique constraint, or use .upsert(..., { onConflict: \"<key column>\" }).',\n docsUrl: 'https://supabase.com/docs/reference/javascript/upsert',\n recommended: true,\n },\n messages: {\n missingIdempotencyKey:\n 'This insert has no idempotency/dedupe key field, so a retried request can create a duplicate row. Add one, or use .upsert(..., { onConflict: \"<key column>\" }).',\n },\n schema: [],\n },\n create(context: any) {\n return {\n CallExpression(node: any) {\n const prop = memberPropName(node);\n if (prop !== 'insert') return;\n\n const objCall = chainObjectCall(node);\n if (!objCall || memberPropName(objCall) !== 'from') return;\n\n const arg = node.arguments?.[0];\n if (!arg) return;\n if (insertPayloadHasIdempotencyKey(arg)) return;\n\n context.report({ node, messageId: 'missingIdempotencyKey' });\n },\n };\n },\n};\n\nexport const supabaseIdempotentMutationsRule = rule;\nexport default rule;\n","/**\n * supabase-fail-fast-env-validation (reliability)\n *\n * `createClient(process.env.X, process.env.Y)` doesn't throw on `undefined`\n * args — the failure surfaces later, deep in a fetch call, as an opaque\n * error rather than a clear \"missing required env var\" message at startup.\n *\n * Tracks (in source order, since guards precede the call they protect):\n * - which local name `createClient` was imported as\n * - which local variables were assigned directly from `process.env.X`\n * - which variables/env-vars an `if (!x || ...) throw/return` guard covers\n * then, at the `createClient(...)` call, flags any argument that resolves\n * to a `process.env` value with no matching guard.\n */\n\nfunction unwrapNonNull(node: any): any {\n return node?.type === 'TSNonNullExpression' ? node.expression : node;\n}\n\nfunction processEnvMemberName(node: any): string | undefined {\n const n = unwrapNonNull(node);\n if (n?.type !== 'MemberExpression' || n.computed) return undefined;\n const obj = n.object;\n if (obj?.type !== 'MemberExpression' || obj.computed) return undefined;\n if (obj.object?.type !== 'Identifier' || obj.object.name !== 'process') return undefined;\n if (obj.property?.type !== 'Identifier' || obj.property.name !== 'env') return undefined;\n if (n.property?.type !== 'Identifier') return undefined;\n return n.property.name;\n}\n\nfunction hasThrowOrReturn(node: any): boolean {\n if (!node) return false;\n if (node.type === 'ThrowStatement' || node.type === 'ReturnStatement') return true;\n if (node.type === 'BlockStatement') {\n return (node.body ?? []).some((s: any) => s.type === 'ThrowStatement' || s.type === 'ReturnStatement');\n }\n return false;\n}\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'createClient must fail fast when required env vars are missing',\n category: 'reliability',\n rationale:\n 'createClient does not throw on undefined arguments — a missing env var surfaces later as an opaque error deep in a fetch call rather than a clear message at startup. Checking presence before calling createClient turns a confusing runtime failure (e.g. on a misconfigured second service) into an immediate, actionable one.',\n docsUrl: 'https://supabase.com/docs/reference/javascript/initializing',\n recommended: true,\n },\n messages: {\n missingEnvValidation:\n 'createClient is called with {{vars}} with no presence check beforehand. Throw if it/they are unset before calling createClient.',\n },\n schema: [],\n },\n create(context: any) {\n let createClientLocalName: string | undefined;\n const envVarOfVariable = new Map<string, string>();\n const validatedVarNames = new Set<string>();\n const validatedEnvNames = new Set<string>();\n\n function addTarget(node: any) {\n const n = unwrapNonNull(node);\n if (n?.type === 'Identifier') {\n validatedVarNames.add(n.name);\n return;\n }\n const envName = processEnvMemberName(n);\n if (envName) validatedEnvNames.add(envName);\n }\n\n function collectGuardTargets(node: any) {\n if (!node) return;\n if (node.type === 'LogicalExpression' && node.operator === '||') {\n collectGuardTargets(node.left);\n collectGuardTargets(node.right);\n return;\n }\n if (node.type === 'UnaryExpression' && node.operator === '!') {\n addTarget(node.argument);\n return;\n }\n if (node.type === 'BinaryExpression' && (node.operator === '==' || node.operator === '===')) {\n const sides = [node.left, node.right];\n const isNullish = (n: any) =>\n (n?.type === 'Literal' && n.value === null) || (n?.type === 'Identifier' && n.name === 'undefined');\n const target = sides.find((s: any) => !isNullish(s));\n const nullSide = sides.find(isNullish);\n if (target && nullSide) addTarget(target);\n }\n }\n\n return {\n ImportDeclaration(node: any) {\n if (node.source?.value !== '@supabase/supabase-js') return;\n for (const s of node.specifiers ?? []) {\n if (\n s?.type === 'ImportSpecifier' &&\n s.imported?.type === 'Identifier' &&\n s.imported.name === 'createClient' &&\n s.local?.type === 'Identifier'\n ) {\n createClientLocalName = s.local.name;\n }\n }\n },\n\n VariableDeclarator(node: any) {\n if (node.id?.type !== 'Identifier') return;\n const envName = processEnvMemberName(node.init);\n if (envName) envVarOfVariable.set(node.id.name, envName);\n },\n\n IfStatement(node: any) {\n if (!hasThrowOrReturn(node.consequent)) return;\n collectGuardTargets(node.test);\n },\n\n CallExpression(node: any) {\n if (!createClientLocalName) return;\n if (node.callee?.type !== 'Identifier' || node.callee.name !== createClientLocalName) return;\n\n const missing: string[] = [];\n for (const rawArg of node.arguments ?? []) {\n const arg = unwrapNonNull(rawArg);\n let envName: string | undefined;\n let isValidated: boolean;\n\n if (arg?.type === 'Identifier') {\n envName = envVarOfVariable.get(arg.name);\n if (!envName) continue;\n isValidated = validatedVarNames.has(arg.name);\n } else {\n envName = processEnvMemberName(arg);\n if (!envName) continue;\n isValidated = validatedEnvNames.has(envName);\n }\n\n if (!isValidated) missing.push(envName);\n }\n\n if (missing.length > 0) {\n context.report({ node, messageId: 'missingEnvValidation', data: { vars: missing.join(', ') } });\n }\n },\n };\n },\n};\n\nexport const supabaseFailFastEnvValidationRule = rule;\nexport default rule;\n","/**\n * supabase-no-user-metadata-authz (security)\n *\n * `raw_user_meta_data` is client-writable — using `user_metadata` for roles\n * lets any authenticated user self-promote via updateUser({ data: { role } }).\n */\nimport { isUserMetadataAuthzRead, memberPropName } from '../utils.js';\n\nconst AUTHZ_DATA_KEYS = new Set(['role', 'roles', 'admin', 'is_admin', 'permission', 'permissions']);\n\nfunction objectHasAuthzDataKey(objectExpression: any): boolean {\n if (objectExpression?.type !== 'ObjectExpression') return false;\n return (objectExpression.properties ?? []).some((p: any) => {\n if (p?.type !== 'Property') return false;\n const name =\n p.shorthand && p.key?.type === 'Identifier'\n ? p.key.name\n : p.key?.type === 'Identifier'\n ? p.key.name\n : p.key?.type === 'Literal'\n ? p.key.value\n : undefined;\n return typeof name === 'string' && AUTHZ_DATA_KEYS.has(name);\n });\n}\n\nfunction findAuthDataPayload(args: any[]): any | null {\n for (const arg of args) {\n if (arg?.type !== 'ObjectExpression') continue;\n for (const p of arg.properties ?? []) {\n if (p?.type !== 'Property') continue;\n const key =\n p.key?.type === 'Identifier' ? p.key.name : p.key?.type === 'Literal' ? p.key.value : undefined;\n if (key === 'data' && p.value?.type === 'ObjectExpression') return p.value;\n if (key === 'options' && p.value?.type === 'ObjectExpression') {\n for (const opt of p.value.properties ?? []) {\n if (opt?.type !== 'Property') continue;\n const optKey =\n opt.key?.type === 'Identifier'\n ? opt.key.name\n : opt.key?.type === 'Literal'\n ? opt.key.value\n : undefined;\n if (optKey === 'data' && opt.value?.type === 'ObjectExpression') return opt.value;\n }\n }\n }\n }\n return null;\n}\n\nfunction isAuthUserMetadataWrite(node: any): boolean {\n const prop = memberPropName(node);\n if (prop !== 'signUp' && prop !== 'updateUser') return false;\n const dataPayload = findAuthDataPayload(node.arguments ?? []);\n return dataPayload ? objectHasAuthzDataKey(dataPayload) : false;\n}\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Do not store or read authorization data from user_metadata',\n category: 'security',\n cwe: 'CWE-285',\n owasp: 'A01:2021 Broken Access Control',\n rationale:\n 'Supabase documents raw_user_meta_data as client-writable and unsuitable for authorization. Reading user_metadata.role (or writing role into signUp/updateUser data) lets any signed-in user self-assign privileged roles from the browser. Store roles in app_metadata via a trusted server path, or in an RLS-protected profiles table.',\n docsUrl: 'https://supabase.com/docs/guides/database/postgres/row-level-security',\n recommended: true,\n },\n messages: {\n userMetadataAuthzRead:\n 'Authorization is read from user_metadata, which the client can modify. Use app_metadata or a server-side role table instead.',\n userMetadataAuthzWrite:\n 'Authorization data is written to user_metadata via signUp/updateUser, which the client can change later. Use app_metadata or a server-side role table instead.',\n },\n schema: [],\n },\n create(context: any) {\n return {\n MemberExpression(node: any) {\n if (isUserMetadataAuthzRead(node)) {\n context.report({ node, messageId: 'userMetadataAuthzRead' });\n }\n },\n CallExpression(node: any) {\n if (isAuthUserMetadataWrite(node)) {\n context.report({ node, messageId: 'userMetadataAuthzWrite' });\n }\n },\n };\n },\n};\n\nexport const supabaseNoUserMetadataAuthzRule = rule;\nexport default rule;\n","/**\n * supabase-single-without-error-check (correctness)\n *\n * `.single()` returns `{ data, error }` — zero or multiple rows set `error`\n * (PGRST116) without throwing. Ignoring `error` leaves the UI stuck loading.\n */\nimport { chainHasMethod, destructuredNames, memberPropName } from '../utils.js';\n\nfunction isSingleSupabaseQuery(awaitArg: any): boolean {\n return awaitArg?.type === 'CallExpression' && chainHasMethod(awaitArg, 'single');\n}\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Supabase .single() calls must inspect the returned error field',\n category: 'correctness',\n rationale:\n '.single() signals zero-or-one-row intent via the error field (PGRST116), not by leaving data undefined silently. Destructuring only data and never reading error produces infinite spinners on deleted rows, bad IDs, or RLS-denied reads. Prefer .maybeSingle() or branch on error before rendering.',\n docsUrl: 'https://supabase.com/docs/reference/javascript/single',\n recommended: true,\n },\n messages: {\n missingErrorCheck:\n 'This .single() result ignores error — a missing or denied row will look like a perpetual load. Destructure error or use .maybeSingle().',\n },\n schema: [],\n },\n create(context: any) {\n function checkAwaitBinding(node: any, pattern: any, awaitExpr: any) {\n if (!isSingleSupabaseQuery(awaitExpr.argument)) return;\n const names = destructuredNames(pattern);\n if (names.has('error')) return;\n context.report({ node, messageId: 'missingErrorCheck' });\n }\n\n return {\n VariableDeclarator(node: any) {\n if (node.init?.type !== 'AwaitExpression') return;\n checkAwaitBinding(node, node.id, node.init);\n },\n AssignmentExpression(node: any) {\n if (node.right?.type !== 'AwaitExpression') return;\n checkAwaitBinding(node, node.left, node.right);\n },\n ExpressionStatement(node: any) {\n const expr = node.expression;\n if (expr?.type !== 'AwaitExpression') return;\n if (!isSingleSupabaseQuery(expr.argument)) return;\n if (memberPropName(expr.argument) === 'single') {\n context.report({ node, messageId: 'missingErrorCheck' });\n }\n },\n };\n },\n};\n\nexport const supabaseSingleWithoutErrorCheckRule = rule;\nexport default rule;\n","/**\n * supabase-non-atomic-replace-pattern (correctness)\n *\n * Client-side delete-all-then-insert-all child rows without checking either\n * step's error can silently wipe data when a mid-loop insert fails.\n */\nimport { fromTableName, isSupabaseMutationKind, destructuredNames } from '../utils.js';\n\ninterface MutationSite {\n node: any;\n table: string | undefined;\n kind: 'delete' | 'insert';\n checksError: boolean;\n}\n\nfunction isSupabaseTableMutation(node: any, kind: 'delete' | 'insert'): boolean {\n return isSupabaseMutationKind(node, kind);\n}\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Supabase delete-then-insert replace patterns should check errors or use RPC',\n category: 'correctness',\n rationale:\n 'Replacing child rows by deleting all rows for a user then re-inserting is a common Supabase pattern, but sequential client calls are not transactional. If delete succeeds and a later insert fails, existing rows are gone with no error shown. Wrap both steps in a Postgres RPC function or check error after each call.',\n docsUrl: 'https://supabase.com/docs/guides/database/functions',\n recommended: true,\n },\n messages: {\n nonAtomicReplace:\n 'This function deletes then re-inserts rows without checking errors — a failed insert after a successful delete loses data silently.',\n },\n schema: [],\n },\n create(context: any) {\n const fnStack: any[] = [];\n const mutationsByFunction = new Map<any, MutationSite[]>();\n\n function currentFunction() {\n return fnStack[fnStack.length - 1];\n }\n\n function recordMutation(node: any, awaitExpr: any, pattern: any | undefined, kind: 'delete' | 'insert') {\n const fn = currentFunction();\n if (!fn) return;\n if (!isSupabaseTableMutation(awaitExpr.argument, kind)) return;\n const checksError = pattern ? destructuredNames(pattern).has('error') : false;\n const list = mutationsByFunction.get(fn) ?? [];\n list.push({ node, table: fromTableName(awaitExpr.argument), kind, checksError });\n mutationsByFunction.set(fn, list);\n }\n\n function enterFunction(node: any) {\n fnStack.push(node);\n }\n\n function exitFunction(node: any) {\n const sites = mutationsByFunction.get(node);\n if (sites) {\n const deletes = sites.filter((s) => s.kind === 'delete');\n const inserts = sites.filter((s) => s.kind === 'insert');\n if (deletes.length > 0 && inserts.length > 0) {\n const uncheckedDelete = deletes.some((d) => !d.checksError);\n const uncheckedInsert = inserts.some((i) => !i.checksError);\n const sameTable =\n uncheckedDelete &&\n uncheckedInsert &&\n deletes.some((d) => inserts.some((i) => d.table && i.table && d.table === i.table));\n if (sameTable) {\n context.report({ node: inserts[0]!.node, messageId: 'nonAtomicReplace' });\n }\n }\n mutationsByFunction.delete(node);\n }\n fnStack.pop();\n }\n\n return {\n FunctionDeclaration(node: any) {\n enterFunction(node);\n },\n 'FunctionDeclaration:exit'(node: any) {\n exitFunction(node);\n },\n FunctionExpression(node: any) {\n enterFunction(node);\n },\n 'FunctionExpression:exit'(node: any) {\n exitFunction(node);\n },\n ArrowFunctionExpression(node: any) {\n enterFunction(node);\n },\n 'ArrowFunctionExpression:exit'(node: any) {\n exitFunction(node);\n },\n VariableDeclarator(node: any) {\n if (node.init?.type !== 'AwaitExpression') return;\n const arg = node.init.argument;\n if (isSupabaseTableMutation(arg, 'delete')) recordMutation(node, node.init, node.id, 'delete');\n if (isSupabaseTableMutation(arg, 'insert')) recordMutation(node, node.init, node.id, 'insert');\n },\n ExpressionStatement(node: any) {\n const expr = node.expression;\n if (expr?.type !== 'AwaitExpression') return;\n const arg = expr.argument;\n if (isSupabaseTableMutation(arg, 'delete')) recordMutation(node, expr, undefined, 'delete');\n if (isSupabaseTableMutation(arg, 'insert')) recordMutation(node, expr, undefined, 'insert');\n },\n };\n },\n};\n\nexport const supabaseNonAtomicReplacePatternRule = rule;\nexport default rule;\n","/**\n * supabase-unchecked-mutation-error (correctness)\n *\n * Supabase insert/update/delete resolve to `{ data, error }` — RLS and\n * constraint failures land in `error`, not as thrown exceptions.\n */\nimport { destructuredNames, isSupabaseMutationKind } from '../utils.js';\n\nconst MUTATIONS = ['insert', 'update', 'delete', 'upsert'] as const;\n\nfunction isSupabaseMutationCall(node: any): boolean {\n return MUTATIONS.some((kind) => isSupabaseMutationKind(node, kind));\n}\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Supabase mutations must check the returned error field',\n category: 'correctness',\n rationale:\n 'Unlike fetch(), Supabase client mutations return { data, error } and resolve even when RLS denies the write or a constraint fails. Fire-and-forget awaits or destructuring only data lets optimistic UI state diverge from the database with no toast or rollback.',\n docsUrl: 'https://supabase.com/docs/reference/javascript/insert',\n recommended: true,\n },\n messages: {\n uncheckedMutation:\n 'This Supabase mutation never checks error — RLS denials and constraint failures will be silent.',\n },\n schema: [],\n },\n create(context: any) {\n function checkMutationAwait(node: any, pattern: any | undefined, awaitExpr: any) {\n if (!isSupabaseMutationCall(awaitExpr.argument)) return;\n if (!pattern) {\n context.report({ node, messageId: 'uncheckedMutation' });\n return;\n }\n const names = destructuredNames(pattern);\n if (!names.has('error')) {\n context.report({ node, messageId: 'uncheckedMutation' });\n }\n }\n\n return {\n ExpressionStatement(node: any) {\n const expr = node.expression;\n if (expr?.type !== 'AwaitExpression') return;\n checkMutationAwait(node, undefined, expr);\n },\n VariableDeclarator(node: any) {\n if (node.init?.type !== 'AwaitExpression') return;\n checkMutationAwait(node, node.id, node.init);\n },\n AssignmentExpression(node: any) {\n if (node.right?.type !== 'AwaitExpression') return;\n checkMutationAwait(node, node.left, node.right);\n },\n };\n },\n};\n\nexport const supabaseUncheckedMutationErrorRule = rule;\nexport default rule;\n","/**\n * supabase-realtime-missing-filter (reliability)\n *\n * A Realtime `postgres_changes` subscription on a whole table (no `filter`)\n * refetches for every row change app-wide — O(active users) fan-out per write.\n */\nimport { memberPropName } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Supabase Realtime postgres_changes subscriptions should use a filter',\n category: 'reliability',\n rationale:\n 'Listening to postgres_changes on an entire table without a filter means every insert/update/delete by any user triggers the callback on every connected client. RLS still scopes the data, but the refetch storm scales with concurrent users and will degrade under real load. Scope subscriptions with the documented filter option (e.g. receiver_id=eq.{id}).',\n docsUrl: 'https://supabase.com/docs/guides/realtime/postgres-changes#filtering',\n recommended: true,\n },\n messages: {\n missingFilter:\n 'This Realtime postgres_changes subscription has no filter and will fire on every row change in the table.',\n },\n schema: [],\n },\n create(context: any) {\n return {\n CallExpression(node: any) {\n if (memberPropName(node) !== 'on') return;\n const eventArg = node.arguments?.[0];\n if (eventArg?.type !== 'Literal' || eventArg.value !== 'postgres_changes') return;\n\n const options = node.arguments?.[1];\n if (options?.type !== 'ObjectExpression') return;\n\n const hasFilter = (options.properties ?? []).some((p: any) => {\n if (p?.type !== 'Property') return false;\n const key =\n p.key?.type === 'Identifier'\n ? p.key.name\n : p.key?.type === 'Literal'\n ? p.key.value\n : undefined;\n return key === 'filter';\n });\n\n if (!hasFilter) {\n context.report({ node, messageId: 'missingFilter' });\n }\n },\n };\n },\n};\n\nexport const supabaseRealtimeMissingFilterRule = rule;\nexport default rule;\n","/**\n * supabase-storage-error-not-surfaced (reliability)\n *\n * Storage `.upload()` failures return `{ error }` — `if (!uploadError) { ... }`\n * with no else branch silently continues with a stale URL.\n */\nimport { chainObjectCall, memberPropName } from '../utils.js';\n\nfunction isStorageUploadCall(node: any): boolean {\n let current: any = node;\n let sawStorage = false;\n let sawUpload = false;\n while (current?.type === 'CallExpression') {\n const prop = memberPropName(current);\n if (prop === 'storage') sawStorage = true;\n if (prop === 'upload') sawUpload = true;\n current = chainObjectCall(current);\n }\n return sawStorage && sawUpload;\n}\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Supabase storage upload errors must be surfaced to the user',\n category: 'reliability',\n rationale:\n 'Storage uploads return { error } without throwing. An if (!uploadError) block with no else lets the caller fall through to a profile save and success toast even when the file never uploaded — the user only notices later that their avatar or resume did not change.',\n docsUrl: 'https://supabase.com/docs/reference/javascript/storage-from-upload',\n recommended: true,\n },\n messages: {\n uploadErrorNotSurfaced:\n 'Storage upload failure is ignored when uploadError is set — add an else branch to stop and show an error.',\n },\n schema: [],\n },\n create(context: any) {\n const uploadAwaitVars = new Set<string>();\n\n return {\n VariableDeclarator(node: any) {\n if (node.init?.type !== 'AwaitExpression') return;\n if (!isStorageUploadCall(node.init.argument)) return;\n if (node.id?.type === 'ObjectPattern') {\n for (const p of node.id.properties ?? []) {\n if (p?.type !== 'Property') continue;\n if (p.key?.type === 'Identifier' && p.key.name === 'error' && p.value?.type === 'Identifier') {\n uploadAwaitVars.add(p.value.name);\n }\n }\n }\n },\n IfStatement(node: any) {\n const test = node.test;\n if (test?.type !== 'UnaryExpression' || test.operator !== '!') return;\n const arg = test.argument;\n if (arg?.type !== 'Identifier') return;\n if (!uploadAwaitVars.has(arg.name) && !/uploadError|uploadErr/i.test(arg.name)) return;\n if (node.alternate) return;\n context.report({ node, messageId: 'uploadErrorNotSurfaced' });\n },\n 'Program:exit'() {\n uploadAwaitVars.clear();\n },\n };\n },\n};\n\nexport const supabaseStorageErrorNotSurfacedRule = rule;\nexport default rule;\n","/**\n * Flags manual Auth0 JWT verification (jsonwebtoken + jwks-rsa, or express-jwt)\n * configured with RS256 + issuer but no unconditional `audience` check.\n */\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Auth0 JWT verification must require audience validation, not skip it when unconfigured',\n category: 'security',\n cwe: 'CWE-345',\n owasp: 'API2:2023 Broken Authentication',\n rationale:\n 'Signature and issuer checks alone only prove a token was signed by the Auth0 tenant — they do not prove the token was issued for this API. Without a mandatory audience check, any validly signed token from the same tenant (including one issued for a completely different application) will authenticate successfully. If the audience check is only applied when a config value happens to be set, a misconfiguration silently disables it instead of failing closed.',\n docsUrl: 'https://auth0.com/docs/secure/tokens/json-web-tokens/validate-json-web-tokens',\n recommended: true,\n },\n messages: {\n missingAudience:\n 'Auth0 JWT verification is configured without an audience check — any token signed by this tenant, regardless of which API it was issued for, will be accepted.',\n conditionalAudience:\n 'Audience validation is only applied conditionally here — if the underlying config value is ever unset, the check silently disappears instead of failing closed.',\n },\n },\n create(context: any) {\n const jwtImportNames = new Set<string>();\n const expressJwtImportNames = new Set<string>();\n\n function isRS256Algorithms(node: any): boolean {\n if (node?.type !== 'ArrayExpression') return false;\n return (node.elements ?? []).some(\n (el: any) => el?.type === 'Literal' && el.value === 'RS256',\n );\n }\n\n function isAuth0StyleOptions(objectExpr: any): boolean {\n if (objectExpr?.type !== 'ObjectExpression') return false;\n let hasRS256 = false;\n let hasIssuer = false;\n for (const prop of objectExpr.properties ?? []) {\n if (prop?.type !== 'Property') continue;\n const keyName = prop.key?.type === 'Identifier' ? prop.key.name : prop.key?.value;\n if (keyName === 'algorithms' && isRS256Algorithms(prop.value)) hasRS256 = true;\n if (keyName === 'issuer') hasIssuer = true;\n }\n return hasRS256 && hasIssuer;\n }\n\n function checkAudience(objectExpr: any): 'ok' | 'missing' | 'conditional' {\n let sawAudienceProperty = false;\n let sawConditionalSpread = false;\n for (const prop of objectExpr.properties ?? []) {\n if (prop?.type === 'Property') {\n const keyName = prop.key?.type === 'Identifier' ? prop.key.name : prop.key?.value;\n if (keyName === 'audience') sawAudienceProperty = true;\n }\n if (prop?.type === 'SpreadElement' && prop.argument?.type === 'ConditionalExpression') {\n sawConditionalSpread = true;\n }\n }\n if (sawAudienceProperty) return 'ok';\n if (sawConditionalSpread) return 'conditional';\n return 'missing';\n }\n\n function reportIfBad(objectExpr: any, reportNode: any) {\n if (!isAuth0StyleOptions(objectExpr)) return;\n const result = checkAudience(objectExpr);\n if (result === 'missing') {\n context.report({ node: reportNode, messageId: 'missingAudience' });\n } else if (result === 'conditional') {\n context.report({ node: reportNode, messageId: 'conditionalAudience' });\n }\n }\n\n return {\n ImportDeclaration(node: any) {\n const importSource = node?.source?.value;\n if (importSource === 'jsonwebtoken') {\n for (const s of node.specifiers ?? []) {\n if (\n (s?.type === 'ImportDefaultSpecifier' || s?.type === 'ImportNamespaceSpecifier') &&\n s.local?.type === 'Identifier'\n ) {\n jwtImportNames.add(s.local.name);\n }\n }\n }\n if (importSource === 'express-jwt') {\n for (const s of node.specifiers ?? []) {\n if (s?.local?.type === 'Identifier') expressJwtImportNames.add(s.local.name);\n }\n }\n },\n\n CallExpression(node: any) {\n const callee = node?.callee;\n\n // jwt.verify(token, key, options)\n if (\n callee?.type === 'MemberExpression' &&\n callee.property?.type === 'Identifier' &&\n callee.property.name === 'verify' &&\n callee.object?.type === 'Identifier' &&\n jwtImportNames.has(callee.object.name)\n ) {\n const optionsArg = node.arguments?.[2];\n if (optionsArg) reportIfBad(optionsArg, node);\n return;\n }\n\n // expressjwt({ ... }) / jwt({ ... }) imported from express-jwt\n if (callee?.type === 'Identifier' && expressJwtImportNames.has(callee.name)) {\n const optionsArg = node.arguments?.[0];\n if (optionsArg) reportIfBad(optionsArg, node);\n }\n },\n };\n },\n};\n\nexport const auth0RequiredAudienceValidationRule = rule;\n","/**\n * Flags account-linking lookups (findOne/findUnique/findFirst keyed on\n * `email`) fed by an unverified OIDC `email` claim, within a function that\n * never checks `email_verified` anywhere.\n */\nconst CLAIMS_LIKE_NAMES = new Set([\n 'claims',\n 'decoded',\n 'payload',\n 'profile',\n 'userinfo',\n 'userInfo',\n 'idTokenClaims',\n 'tokenClaims',\n]);\n\nconst LOOKUP_METHODS = new Set(['findOne', 'findUnique', 'findFirst']);\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Account-linking lookups keyed on an email claim must verify email_verified first',\n category: 'security',\n cwe: 'CWE-290',\n owasp: 'API2:2023 Broken Authentication',\n rationale:\n 'By default, Auth0 access tokens carry no email claim at all — the email most apps trust arrives via a custom namespaced claim or the /userinfo fallback, neither of which is cryptographically tied to proof of ownership the way `sub` is. Using that email to look up and re-link an existing account, without first checking `email_verified`, lets an attacker who controls (or can register) an Auth0 identity with an unverified or spoofed email silently take over any existing account that happens to share it.',\n docsUrl: 'https://auth0.com/docs/manage-users/user-accounts/user-account-linking',\n recommended: true,\n },\n messages: {\n unverifiedEmailLink:\n 'This account lookup is keyed on an email claim, but nothing in this function checks email_verified first — an unverified or attacker-supplied email can silently take over an existing account.',\n },\n },\n create(context: any) {\n type FnState = { sawLookup: boolean; lookupNode: any; sawVerified: boolean };\n const stack: any[] = [];\n const states = new Map<any, FnState>();\n\n function ensureState(fn: any): FnState {\n let s = states.get(fn);\n if (!s) {\n s = { sawLookup: false, lookupNode: null, sawVerified: false };\n states.set(fn, s);\n }\n return s;\n }\n\n function top(): any {\n return stack[stack.length - 1];\n }\n\n function pushScope(node: any) {\n stack.push(node);\n ensureState(node);\n }\n\n function popScope() {\n stack.pop();\n }\n\n function propName(node: any): string | undefined {\n if (!node) return undefined;\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'Literal' && typeof node.value === 'string') return node.value;\n return undefined;\n }\n\n function isEmailFromClaims(node: any): boolean {\n if (node?.type !== 'MemberExpression') return false;\n const propertyName = node.computed ? propName(node.property) : node.property?.name;\n if (propertyName !== 'email') return false;\n const obj = node.object;\n return obj?.type === 'Identifier' && CLAIMS_LIKE_NAMES.has(obj.name);\n }\n\n function objectHasEmailFromClaims(objExpr: any): boolean {\n if (objExpr?.type !== 'ObjectExpression') return false;\n for (const prop of objExpr.properties ?? []) {\n if (prop?.type !== 'Property') continue;\n const keyName = propName(prop.key);\n if (keyName === 'email' && isEmailFromClaims(prop.value)) return true;\n if (keyName === 'where' && objectHasEmailFromClaims(prop.value)) return true;\n }\n return false;\n }\n\n function markVerifiedSeen(name: string | undefined) {\n if (!name || !name.includes('email_verified')) return;\n const fn = top();\n if (fn) ensureState(fn).sawVerified = true;\n }\n\n return {\n Program(node: any) {\n pushScope(node);\n },\n 'Program:exit'() {\n for (const state of states.values()) {\n if (state.sawLookup && !state.sawVerified) {\n context.report({ node: state.lookupNode, messageId: 'unverifiedEmailLink' });\n }\n }\n },\n\n FunctionDeclaration(node: any) {\n pushScope(node);\n },\n 'FunctionDeclaration:exit'() {\n popScope();\n },\n FunctionExpression(node: any) {\n pushScope(node);\n },\n 'FunctionExpression:exit'() {\n popScope();\n },\n ArrowFunctionExpression(node: any) {\n pushScope(node);\n },\n 'ArrowFunctionExpression:exit'() {\n popScope();\n },\n\n CallExpression(node: any) {\n const callee = node?.callee;\n if (callee?.type !== 'MemberExpression') return;\n const methodName = callee.property?.name;\n if (!methodName || !LOOKUP_METHODS.has(methodName)) return;\n const arg = node.arguments?.[0];\n if (!objectHasEmailFromClaims(arg)) return;\n const fn = top();\n if (!fn) return;\n const state = ensureState(fn);\n state.sawLookup = true;\n state.lookupNode = node;\n },\n\n MemberExpression(node: any) {\n const propertyName = node.computed ? propName(node.property) : node.property?.name;\n markVerifiedSeen(propertyName);\n },\n\n Literal(node: any) {\n if (typeof node.value === 'string') markVerifiedSeen(node.value);\n },\n };\n },\n};\n\nexport const auth0NoAccountLinkWithoutVerifiedEmailRule = rule;\n","/**\n * Flags `String(claims.foo_verified).includes('x')` / `claims.foo_verified.toString().includes('x')`\n * checks against a boolean OIDC claim — stringifying a boolean produces\n * only \"true\" or \"false\", so any substring check other than those two\n * literal strings can never match and the guard is dead code.\n */\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'A stringified boolean OIDC claim is checked with .includes() against a substring it can never contain',\n category: 'correctness',\n rationale:\n 'Boolean OIDC claims like email_verified/phone_verified stringify to exactly \"true\" or \"false\". A .includes() check against any other substring is always false, so the guard this code appears to implement never runs — silently disabling whatever verification it was meant to perform.',\n docsUrl: 'https://auth0.com/docs/secure/tokens/json-web-tokens/json-web-token-claims',\n recommended: true,\n },\n messages: {\n deadVerificationCheck:\n 'Stringifying this boolean claim only ever produces \"true\" or \"false\" — checking .includes(\"{{substring}}\") against it is always false and never executes its guarded branch.',\n },\n },\n create(context: any) {\n function propName(node: any): string | undefined {\n if (!node) return undefined;\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'Literal' && typeof node.value === 'string') return node.value;\n return undefined;\n }\n\n function isBooleanClaimMember(node: any): boolean {\n if (node?.type !== 'MemberExpression') return false;\n const name = propName(node.property);\n return typeof name === 'string' && name.toLowerCase().endsWith('_verified');\n }\n\n // String(claims.email_verified) / String(claims.email_verified ?? '')\n function stringifiedClaimArg(callExpr: any): boolean {\n if (callExpr?.type !== 'CallExpression') return false;\n if (callExpr.callee?.type !== 'Identifier' || callExpr.callee.name !== 'String') return false;\n const arg = callExpr.arguments?.[0];\n if (isBooleanClaimMember(arg)) return true;\n // String(claims.email_verified ?? '')\n if (arg?.type === 'LogicalExpression' && arg.operator === '??') {\n return isBooleanClaimMember(arg.left);\n }\n return false;\n }\n\n // claims.email_verified.toString()\n function isClaimToStringCall(callExpr: any): boolean {\n if (callExpr?.type !== 'CallExpression') return false;\n const callee = callExpr.callee;\n if (callee?.type !== 'MemberExpression') return false;\n if (callee.property?.name !== 'toString') return false;\n return isBooleanClaimMember(callee.object);\n }\n\n return {\n CallExpression(node: any) {\n const callee = node?.callee;\n if (callee?.type !== 'MemberExpression') return;\n if (callee.property?.name !== 'includes') return;\n\n const subject = callee.object;\n const isDeadShape = stringifiedClaimArg(subject) || isClaimToStringCall(subject);\n if (!isDeadShape) return;\n\n const substringArg = node.arguments?.[0];\n if (substringArg?.type !== 'Literal' || typeof substringArg.value !== 'string') return;\n\n // \"true\"/\"false\" are the only strings a stringified boolean can ever\n // contain, so a check against exactly one of those is functional\n // (if unidiomatic), not dead.\n if (substringArg.value === 'true' || substringArg.value === 'false') return;\n\n context.report({\n node,\n messageId: 'deadVerificationCheck',\n data: { substring: substringArg.value },\n });\n },\n };\n },\n};\n\nexport const auth0DeadClaimVerificationCheckRule = rule;\n","/**\n * Flags a hand-rolled JWKS key resolver (TTL-cached fetch + `.find(k => k.kid\n * === header.kid)`) that never retries with a forced refresh when the kid\n * lookup misses — Auth0 key rotation then causes failures until the cache\n * naturally expires.\n */\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'A hand-rolled JWKS key resolver must retry with a forced refresh when a kid is not found in the cache',\n category: 'reliability',\n rationale:\n \"On signing-key rotation, Auth0 immediately starts issuing tokens signed with a new key while the old key stays valid in parallel. A worker whose local JWKS cache predates the rotation has the old key but not the new one, so every newly issued token fails to validate until that worker's cache naturally expires — up to the full TTL. Retrying with a forced refresh on a kid miss (instead of failing immediately) closes that window.\",\n docsUrl: 'https://auth0.com/docs/get-started/tenant-settings/signing-keys/rotate-signing-keys',\n recommended: true,\n },\n messages: {\n noRefreshOnMiss:\n 'This kid lookup has no retry-with-forced-refresh path. If the cached JWKS predates a key rotation, every token signed with the new key fails until the cache naturally expires.',\n },\n },\n create(context: any) {\n type Pos = { offset: number; line: number; column: number };\n type FnState = {\n node: any;\n start: Pos;\n end: Pos;\n findCallNode: any;\n sawKidComparison: boolean;\n fetchCallCount: number;\n sawForceRefresh: boolean;\n };\n\n const fnStates: FnState[] = [];\n\n function nodeStartPos(n: any): Pos {\n const rangeStart = typeof n?.range?.[0] === 'number' ? n.range[0] : null;\n const line = n?.loc?.start?.line ?? 1;\n const column = n?.loc?.start?.column ?? 0;\n return { offset: rangeStart ?? line * 1_000_000 + column, line, column };\n }\n\n function nodeEndPos(n: any): Pos {\n const rangeEnd = typeof n?.range?.[1] === 'number' ? n.range[1] : null;\n const line = n?.loc?.end?.line ?? n?.loc?.start?.line ?? 1;\n const column = n?.loc?.end?.column ?? n?.loc?.start?.column ?? 0;\n return { offset: rangeEnd ?? line * 1_000_000 + column, line, column };\n }\n\n function within(state: FnState, n: any): boolean {\n const p = nodeStartPos(n);\n return p.offset >= state.start.offset && p.offset <= state.end.offset;\n }\n\n function collectTopLevelFunctions(programNode: any): any[] {\n const fns: any[] = [];\n for (const stmt of programNode.body ?? []) {\n const decl = stmt?.type === 'ExportNamedDeclaration' && stmt.declaration ? stmt.declaration : stmt;\n if (decl?.type === 'FunctionDeclaration') {\n fns.push(decl);\n } else if (decl?.type === 'VariableDeclaration') {\n for (const d of decl.declarations ?? []) {\n if (d?.init?.type === 'ArrowFunctionExpression' || d?.init?.type === 'FunctionExpression') {\n fns.push(d.init);\n }\n }\n }\n }\n return fns;\n }\n\n function propName(node: any): string | undefined {\n if (!node) return undefined;\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'Literal' && typeof node.value === 'string') return node.value;\n return undefined;\n }\n\n function isKidMember(node: any): boolean {\n if (node?.type !== 'MemberExpression') return false;\n return propName(node.property) === 'kid';\n }\n\n function isJwksFetchCallee(node: any): boolean {\n return node?.type === 'Identifier' && /jwks/i.test(node.name);\n }\n\n function callIndicatesForceRefresh(node: any): boolean {\n for (const arg of node.arguments ?? []) {\n if (arg?.type === 'Literal' && arg.value === true) return true;\n if (arg?.type === 'ObjectExpression') {\n for (const prop of arg.properties ?? []) {\n if (prop?.type !== 'Property') continue;\n const keyName = propName(prop.key);\n if (\n (keyName === 'forceRefresh' || keyName === 'force' || keyName === 'bypassCache') &&\n prop.value?.type === 'Literal' &&\n prop.value.value === true\n ) {\n return true;\n }\n }\n }\n }\n return false;\n }\n\n function stateFor(node: any): FnState | undefined {\n return fnStates.find((s) => within(s, node));\n }\n\n return {\n Program(node: any) {\n for (const fn of collectTopLevelFunctions(node)) {\n fnStates.push({\n node: fn,\n start: nodeStartPos(fn),\n end: nodeEndPos(fn),\n findCallNode: null,\n sawKidComparison: false,\n fetchCallCount: 0,\n sawForceRefresh: false,\n });\n }\n },\n\n CallExpression(node: any) {\n const state = stateFor(node);\n if (!state) return;\n\n const callee = node.callee;\n if (callee?.type === 'MemberExpression' && callee.property?.name === 'find') {\n if (!state.findCallNode) state.findCallNode = node;\n }\n\n if (isJwksFetchCallee(callee)) {\n state.fetchCallCount += 1;\n if (callIndicatesForceRefresh(node)) state.sawForceRefresh = true;\n }\n },\n\n BinaryExpression(node: any) {\n if (node.operator !== '===' && node.operator !== '==') return;\n const state = stateFor(node);\n if (!state) return;\n if (isKidMember(node.left) || isKidMember(node.right)) {\n state.sawKidComparison = true;\n }\n },\n\n 'Program:exit'() {\n for (const state of fnStates) {\n if (!state.findCallNode || !state.sawKidComparison) continue;\n if (state.sawForceRefresh) continue;\n if (state.fetchCallCount >= 2) continue;\n context.report({ node: state.findCallNode, messageId: 'noRefreshOnMiss' });\n }\n },\n };\n },\n};\n\nexport const auth0JwksRefreshOnUnknownKidRule = rule;\n","/**\n * Shared AST helpers for Firebase rules. Kept intentionally small; extend\n * only when logic is genuinely reused across rules.\n *\n * The modular Firebase JS SDK (v9+) exposes free functions (`initializeApp`,\n * `onValue`, `set`, `update`, `push`, `signInWithPopup`, ...) rather than\n * instance methods, so most call-site matching here is \"imported name,\n * called as a bare identifier\" rather than member-expression matching.\n */\n\n/** Map of imported name -> local name for every named import from `sourceValue` on this ImportDeclaration. */\nexport function namedImportsFrom(node: any, sourceValue: string): Map<string, string> {\n const map = new Map<string, string>();\n if (node?.type !== 'ImportDeclaration' || node.source?.value !== sourceValue) return map;\n for (const s of node.specifiers ?? []) {\n if (s?.type === 'ImportSpecifier' && s.imported?.type === 'Identifier' && s.local?.type === 'Identifier') {\n map.set(s.imported.name, s.local.name);\n }\n }\n return map;\n}\n\n/** Local binding name for a namespace import (`import * as ns from 'source'`) from `sourceValue`, if present. */\nexport function namespaceImportFrom(node: any, sourceValue: string): string | undefined {\n if (node?.type !== 'ImportDeclaration' || node.source?.value !== sourceValue) return undefined;\n for (const s of node.specifiers ?? []) {\n if (s?.type === 'ImportNamespaceSpecifier' && s.local?.type === 'Identifier') return s.local.name;\n }\n return undefined;\n}\n\n/** True for `<name>(...)` — a CallExpression whose callee is the bare identifier `name`. */\nexport function isIdentifierCall(node: any, name: string | undefined): boolean {\n if (!name) return false;\n return node?.type === 'CallExpression' && node.callee?.type === 'Identifier' && node.callee.name === name;\n}\n\n/** True for `<obj>.<name>(...)` where `obj` is the bare identifier `objName`. */\nexport function isNamespaceMemberCall(node: any, objName: string | undefined, name: string): boolean {\n if (!objName) return false;\n if (node?.type !== 'CallExpression' || node.callee?.type !== 'MemberExpression') return false;\n const callee = node.callee;\n if (callee.computed) return false;\n return (\n callee.object?.type === 'Identifier' &&\n callee.object.name === objName &&\n callee.property?.type === 'Identifier' &&\n callee.property.name === name\n );\n}\n\n/** Returns the called method name for `<chain>.<name>(...)`, handling computed string-literal access. */\nexport function memberPropName(node: any): string | undefined {\n if (node?.type !== 'CallExpression') return undefined;\n const callee = node.callee;\n if (callee?.type !== 'MemberExpression') return undefined;\n const prop = callee.property;\n if (!callee.computed && prop?.type === 'Identifier') return prop.name;\n if (callee.computed && prop?.type === 'Literal' && typeof prop.value === 'string') return prop.value;\n return undefined;\n}\n\n/** The CallExpression this call is chained onto (`<this>.method()`), or null if the base isn't itself a call. */\nexport function chainObjectCall(node: any): any | null {\n const obj = node?.callee?.object;\n return obj?.type === 'CallExpression' ? obj : null;\n}\n\n/** Every CallExpression link in a member chain, starting at `node` and walking down to the base call. */\nexport function chainLinks(node: any): any[] {\n const links: any[] = [];\n let current: any = node;\n while (current?.type === 'CallExpression') {\n links.push(current);\n current = chainObjectCall(current);\n }\n return links;\n}\n\n/** Best-effort absolute start offset of a node (range -> start -> loc fallback). */\nexport function startOffset(n: any): number {\n if (typeof n?.range?.[0] === 'number') return n.range[0];\n if (typeof n?.start === 'number') return n.start;\n return (n?.loc?.start?.line ?? 0) * 1_000_000 + (n?.loc?.start?.column ?? 0);\n}\n\n/** Best-effort absolute end offset of a node (range -> end -> loc fallback). */\nexport function endOffset(n: any): number {\n if (typeof n?.range?.[1] === 'number') return n.range[1];\n if (typeof n?.end === 'number') return n.end;\n return (n?.loc?.end?.line ?? n?.loc?.start?.line ?? 0) * 1_000_000 + (n?.loc?.end?.column ?? 0);\n}\n\n/** True when `outer`'s range fully contains `inner`'s start position. */\nexport function contains(outer: any, inner: any): boolean {\n const s = startOffset(inner);\n return s >= startOffset(outer) && s <= endOffset(outer);\n}\n\n/** Depth-first search over the AST rooted at `node` for any descendant matching `predicate`. */\nexport function someDescendant(node: any, predicate: (n: any) => boolean): boolean {\n let found = false;\n function visit(n: any) {\n if (found || !n || typeof n !== 'object') return;\n if (Array.isArray(n)) {\n for (const item of n) visit(item);\n return;\n }\n if (typeof n.type !== 'string') return;\n if (predicate(n)) {\n found = true;\n return;\n }\n for (const key of Object.keys(n)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n visit(n[key]);\n }\n }\n visit(node);\n return found;\n}\n\n/** True for `<objName>.uid` / `<objName>?.uid` member access. */\nexport function isUidMemberAccess(node: any, objName: string): boolean {\n const n = node?.type === 'ChainExpression' ? node.expression : node;\n if (n?.type !== 'MemberExpression' || n.computed) return false;\n return n.object?.type === 'Identifier' && n.object.name === objName && n.property?.type === 'Identifier' && n.property.name === 'uid';\n}\n\n/** True when `node` is a BinaryExpression (`===`/`==`) with `name` as one operand. */\nexport function comparesIdentifier(node: any, name: string): boolean {\n if (node?.type !== 'BinaryExpression') return false;\n if (node.operator !== '===' && node.operator !== '==') return false;\n return [node.left, node.right].some((s: any) => s?.type === 'Identifier' && s.name === name);\n}\n\n/** True when the file path looks like a test file. */\nexport function isInsideTestFile(filename: string): boolean {\n return /(^|[\\\\/])__tests__[\\\\/]|\\.(test|spec)\\.[cm]?[jt]sx?$/.test(filename);\n}\n","/**\n * firebase-missing-app-check (security)\n *\n * A file that initializes the Firebase app (`initializeApp(...)`) but never\n * calls `initializeAppCheck` anywhere in the same file is flagged. The\n * Firebase web API key is public by design — Security Rules and App Check\n * are the only things gating access, so an app-init file with no App Check\n * call leaves the project open to any client presenting a valid project\n * config, not just this app.\n */\nimport { isIdentifierCall, isInsideTestFile, isNamespaceMemberCall, namedImportsFrom, namespaceImportFrom } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Firebase app initialization should configure App Check',\n category: 'security',\n cwe: 'CWE-285',\n owasp: 'A04:2021 Insecure Design',\n rationale:\n 'Firebase web API keys are public by design and only identify the project to Google\\'s backend — they are not a secret. The only things standing between an attacker who clones the client config and your database/auth quota are Security Rules and App Check. A file that calls initializeApp but never initializeAppCheck leaves App Check unconfigured, so any client presenting a valid project config (not necessarily yours) can reach Firebase Auth and, subject to rules, the database.',\n docsUrl: 'https://firebase.google.com/docs/database/web/start',\n recommended: true,\n },\n messages: {\n missingAppCheck:\n 'This file initializes the Firebase app but never calls initializeAppCheck. Without App Check, only Security Rules gate access to a publicly-knowable project config.',\n },\n schema: [],\n },\n create(context: any) {\n if (isInsideTestFile(String(context.filename ?? ''))) {\n return {};\n }\n\n let initializeAppLocalName: string | undefined;\n let initializeAppCheckLocalName: string | undefined;\n let appCheckNamespace: string | undefined;\n let initializeAppCallNode: any | undefined;\n let sawAppCheckCall = false;\n\n return {\n ImportDeclaration(node: any) {\n const appImports = namedImportsFrom(node, 'firebase/app');\n if (appImports.has('initializeApp')) initializeAppLocalName = appImports.get('initializeApp');\n\n const appCheckImports = namedImportsFrom(node, 'firebase/app-check');\n if (appCheckImports.has('initializeAppCheck')) {\n initializeAppCheckLocalName = appCheckImports.get('initializeAppCheck');\n }\n const ns = namespaceImportFrom(node, 'firebase/app-check');\n if (ns) appCheckNamespace = ns;\n },\n CallExpression(node: any) {\n if (!initializeAppCallNode && isIdentifierCall(node, initializeAppLocalName)) {\n initializeAppCallNode = node;\n }\n if (isIdentifierCall(node, initializeAppCheckLocalName)) sawAppCheckCall = true;\n if (isNamespaceMemberCall(node, appCheckNamespace, 'initializeAppCheck')) sawAppCheckCall = true;\n },\n 'Program:exit'() {\n if (initializeAppCallNode && !sawAppCheckCall) {\n context.report({ node: initializeAppCallNode, messageId: 'missingAppCheck' });\n }\n },\n };\n },\n};\n\nexport const firebaseMissingAppCheckRule = rule;\nexport default rule;\n","/**\n * firebase-unhandled-auth-popup-rejection (correctness)\n *\n * `signInWithPopup` rejects on common, expected, non-exceptional outcomes\n * (auth/popup-closed-by-user, auth/popup-blocked, auth/cancelled-popup-request).\n * A call with no try/catch and no chained .catch leaves the rejection\n * unhandled — loading state never clears and the user has no way to retry\n * without reloading the page.\n */\nimport { chainLinks, contains, isIdentifierCall, memberPropName, namedImportsFrom } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'signInWithPopup calls must handle rejection',\n category: 'correctness',\n rationale:\n 'signInWithPopup rejects with auth/popup-closed-by-user, auth/popup-blocked, and auth/cancelled-popup-request — all common, expected outcomes, not edge cases. Without a try/catch (or a chained .catch), the rejection is unhandled: loading state set before the call never clears, and the user has no way to retry without reloading the page.',\n docsUrl: 'https://firebase.google.com/docs/auth/web/google-signin',\n recommended: true,\n },\n messages: {\n unhandledPopupRejection:\n 'signInWithPopup is called with no try/catch and no chained .catch. Popup-closed and popup-blocked are expected rejections, not edge cases.',\n },\n schema: [],\n },\n create(context: any) {\n let signInLocalName: string | undefined;\n const calls: any[] = [];\n const tryBlocks: any[] = [];\n const caughtCalls = new Set<any>();\n\n return {\n ImportDeclaration(node: any) {\n const imports = namedImportsFrom(node, 'firebase/auth');\n if (imports.has('signInWithPopup')) signInLocalName = imports.get('signInWithPopup');\n },\n TryStatement(node: any) {\n if (node.block) tryBlocks.push(node.block);\n },\n CallExpression(node: any) {\n if (isIdentifierCall(node, signInLocalName)) {\n calls.push(node);\n return;\n }\n const prop = memberPropName(node);\n const isCatch = prop === 'catch';\n const isTwoArgThen = prop === 'then' && (node.arguments ?? []).length >= 2;\n if (!isCatch && !isTwoArgThen) return;\n for (const link of chainLinks(node)) {\n if (isIdentifierCall(link, signInLocalName)) caughtCalls.add(link);\n }\n },\n 'Program:exit'() {\n for (const call of calls) {\n if (caughtCalls.has(call)) continue;\n if (tryBlocks.some((block) => contains(block, call))) continue;\n context.report({ node: call, messageId: 'unhandledPopupRejection' });\n }\n },\n };\n },\n};\n\nexport const firebaseUnhandledAuthPopupRejectionRule = rule;\nexport default rule;\n","/**\n * firebase-rtdb-list-read-for-single-item (correctness)\n *\n * A page keyed by a single route param (e.g. `taskId` from `useParams()`)\n * that subscribes to the whole collection and then does\n * `items.find((item) => item.id === taskId)` downloads every row the user\n * has just to read one, and renders a false \"not found\" state until the\n * full list streams in.\n */\nimport { comparesIdentifier, someDescendant } from '../utils.js';\n\nfunction isSetterName(name: string): boolean {\n return /^set[A-Z]/.test(name);\n}\n\nfunction stateVarFromSetter(name: string): string {\n return name.slice(3, 4).toLowerCase() + name.slice(4);\n}\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Pages keyed by a single id should not subscribe to the whole collection',\n category: 'correctness',\n rationale:\n 'Subscribing to an entire collection and then Array.prototype.find()-ing by a route id param means the page renders a false \"not found\" state until the full list streams in, and downloads every row the user has just to read one. Use a single-node read/subscribe (ref(db, `path/${id}`)) instead.',\n docsUrl: 'https://firebase.google.com/docs/database/web/read-and-write',\n recommended: true,\n },\n messages: {\n listReadForSingleItem:\n 'This subscribes to a whole collection and finds one item by a route id param. Read/subscribe to that single node directly instead.',\n },\n schema: [],\n },\n create(context: any) {\n let idParamName: string | undefined;\n const listStateVars = new Set<string>();\n const findCalls: Array<{ node: any; objectName: string; callback: any }> = [];\n\n return {\n VariableDeclarator(node: any) {\n if (\n node.init?.type === 'CallExpression' &&\n node.init.callee?.type === 'Identifier' &&\n node.init.callee.name === 'useParams' &&\n node.id?.type === 'ObjectPattern'\n ) {\n for (const p of node.id.properties ?? []) {\n if (p?.type === 'Property' && p.value?.type === 'Identifier' && /id$/i.test(p.value.name)) {\n idParamName = p.value.name;\n }\n }\n }\n },\n CallExpression(node: any) {\n for (const arg of node.arguments ?? []) {\n if (arg?.type === 'Identifier' && isSetterName(arg.name)) {\n listStateVars.add(stateVarFromSetter(arg.name));\n }\n }\n\n if (node.callee?.type !== 'MemberExpression' || node.callee.computed) return;\n if (node.callee.property?.type !== 'Identifier' || node.callee.property.name !== 'find') return;\n const obj = node.callee.object;\n if (obj?.type !== 'Identifier') return;\n findCalls.push({ node, objectName: obj.name, callback: node.arguments?.[0] });\n },\n 'Program:exit'() {\n if (!idParamName) return;\n for (const { node, objectName, callback } of findCalls) {\n if (!listStateVars.has(objectName)) continue;\n if (!callback) continue;\n if (someDescendant(callback, (n) => comparesIdentifier(n, idParamName as string))) {\n context.report({ node, messageId: 'listReadForSingleItem' });\n }\n }\n },\n };\n },\n};\n\nexport const firebaseRtdbListReadForSingleItemRule = rule;\nexport default rule;\n","/**\n * firebase-unvalidated-external-data-to-rtdb (correctness)\n *\n * RTDB has no schema enforcement on the client — data is written exactly as\n * given. When a function parses an external response (JSON.parse, or\n * `response.json()`) and forwards it into set()/update()/push() with no\n * validation call in between, a malformed field from the upstream source\n * (e.g. an LLM response) silently corrupts data with no error surfaced.\n */\nimport { endOffset, isIdentifierCall, namedImportsFrom, startOffset } from '../utils.js';\n\nfunction isJsonParseCall(node: any): boolean {\n return (\n node?.type === 'CallExpression' &&\n node.callee?.type === 'MemberExpression' &&\n !node.callee.computed &&\n node.callee.object?.type === 'Identifier' &&\n node.callee.object.name === 'JSON' &&\n node.callee.property?.type === 'Identifier' &&\n node.callee.property.name === 'parse'\n );\n}\n\nfunction isResponseJsonCall(node: any): boolean {\n return (\n node?.type === 'CallExpression' &&\n node.callee?.type === 'MemberExpression' &&\n !node.callee.computed &&\n node.callee.property?.type === 'Identifier' &&\n node.callee.property.name === 'json' &&\n (node.arguments ?? []).length === 0\n );\n}\n\nfunction isValidationLikeCall(node: any): boolean {\n if (node?.type !== 'CallExpression') return false;\n const callee = node.callee;\n const name =\n callee?.type === 'Identifier'\n ? callee.name\n : callee?.type === 'MemberExpression' && !callee.computed && callee.property?.type === 'Identifier'\n ? callee.property.name\n : undefined;\n if (!name) return false;\n return /valid|^test$|check|assert|schema/i.test(name);\n}\n\ntype FnScope = { node: any; start: number; end: number; parsePos?: number; validatePos?: number; writePos?: number; writeNode?: any };\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Parsed external data must be validated before an RTDB write',\n category: 'correctness',\n rationale:\n 'Realtime Database has no client-side schema enforcement — data is written exactly as given. When a function parses an external response (e.g. an LLM completion) and forwards the result straight into set()/update()/push() with no validation call in between, a malformed or missing field silently corrupts the stored data with no error surfaced anywhere.',\n docsUrl: 'https://firebase.google.com/docs/database/web/read-and-write',\n recommended: true,\n },\n messages: {\n unvalidatedWrite:\n 'Parsed external data flows into a Realtime Database write with no validation call in between. Validate shape/values before writing.',\n },\n schema: [],\n },\n create(context: any) {\n const writeLocalNames = new Set<string>();\n const scopes: FnScope[] = [];\n\n function registerScope(node: any) {\n scopes.push({ node, start: startOffset(node), end: endOffset(node) });\n }\n\n function innermostScope(pos: number): FnScope | undefined {\n let best: FnScope | undefined;\n for (const scope of scopes) {\n if (pos < scope.start || pos > scope.end) continue;\n if (!best || scope.end - scope.start < best.end - best.start) best = scope;\n }\n return best;\n }\n\n function enclosingScopes(pos: number): FnScope[] {\n return scopes.filter((scope) => pos >= scope.start && pos <= scope.end);\n }\n\n return {\n ImportDeclaration(node: any) {\n const imports = namedImportsFrom(node, 'firebase/database');\n for (const name of ['set', 'update', 'push']) {\n const local = imports.get(name);\n if (local) writeLocalNames.add(local);\n }\n },\n FunctionDeclaration(node: any) {\n registerScope(node);\n },\n FunctionExpression(node: any) {\n registerScope(node);\n },\n ArrowFunctionExpression(node: any) {\n registerScope(node);\n },\n CallExpression(node: any) {\n const pos = startOffset(node);\n\n // Validation may happen inside a nested callback (e.g. `.filter(t => regex.test(t.dueDate))`),\n // so it counts toward every enclosing function scope, not just the innermost one.\n if (isValidationLikeCall(node)) {\n for (const scope of enclosingScopes(pos)) {\n if (scope.validatePos === undefined || pos < scope.validatePos) scope.validatePos = pos;\n }\n return;\n }\n\n const scope = innermostScope(pos);\n if (!scope) return;\n\n if (isJsonParseCall(node) || isResponseJsonCall(node)) {\n if (scope.parsePos === undefined || pos < scope.parsePos) scope.parsePos = pos;\n return;\n }\n if (writeLocalNames.size > 0 && [...writeLocalNames].some((n) => isIdentifierCall(node, n))) {\n if (scope.writePos === undefined || pos < scope.writePos) {\n scope.writePos = pos;\n scope.writeNode = node;\n }\n }\n },\n 'Program:exit'() {\n for (const scope of scopes) {\n if (scope.parsePos === undefined || scope.writePos === undefined) continue;\n if (scope.writePos < scope.parsePos) continue;\n const validatedBetween =\n scope.validatePos !== undefined && scope.validatePos > scope.parsePos && scope.validatePos < scope.writePos;\n if (!validatedBetween) {\n context.report({ node: scope.writeNode, messageId: 'unvalidatedWrite' });\n }\n }\n },\n };\n },\n};\n\nexport const firebaseUnvalidatedExternalDataToRtdbRule = rule;\nexport default rule;\n","/**\n * firebase-rtdb-batch-write-not-atomic (correctness)\n *\n * `Promise.all(items.map((item) => { const ref = push(parent); return set(ref, item); }))`\n * fires N independent network writes. If item 7 of 14 fails mid-batch, 1-6\n * are already committed and 8-14 may or may not be — there is no atomicity.\n * One `update()` call against the parent ref with all keys as fields commits\n * atomically instead.\n */\nimport { isIdentifierCall, namedImportsFrom, someDescendant } from '../utils.js';\n\nfunction isPromiseAllCall(node: any): boolean {\n return (\n node?.type === 'CallExpression' &&\n node.callee?.type === 'MemberExpression' &&\n !node.callee.computed &&\n node.callee.object?.type === 'Identifier' &&\n node.callee.object.name === 'Promise' &&\n node.callee.property?.type === 'Identifier' &&\n node.callee.property.name === 'all'\n );\n}\n\nfunction isMapCall(node: any): boolean {\n return (\n node?.type === 'CallExpression' &&\n node.callee?.type === 'MemberExpression' &&\n !node.callee.computed &&\n node.callee.property?.type === 'Identifier' &&\n node.callee.property.name === 'map'\n );\n}\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Promise.all over per-item push+set is not atomic',\n category: 'correctness',\n rationale:\n 'push() to generate a client-side unique key is correct, but firing one set() per item under Promise.all means N independent network writes. A partial failure mid-batch (permission revoked, connection drop) leaves some items committed and others not, with no atomicity. Building one update() call against the parent ref with all generated keys as fields commits the whole batch atomically instead.',\n docsUrl: 'https://firebase.google.com/docs/database/web/read-and-write',\n recommended: true,\n },\n messages: {\n batchWriteNotAtomic:\n 'This batches per-item push()+set() calls under Promise.all, which is not atomic. Build one update() call against the parent ref instead.',\n },\n schema: [],\n },\n create(context: any) {\n let pushLocalName: string | undefined;\n let setLocalName: string | undefined;\n const mapCallsByVarName = new Map<string, any>();\n\n function isAtomicBatchMapCall(mapCallNode: any): boolean {\n if (!isMapCall(mapCallNode)) return false;\n const callback = mapCallNode.arguments?.[mapCallNode.arguments.length - 1];\n if (!callback) return false;\n const hasPush = someDescendant(callback, (n) => isIdentifierCall(n, pushLocalName));\n const hasSet = someDescendant(callback, (n) => isIdentifierCall(n, setLocalName));\n return hasPush && hasSet;\n }\n\n return {\n ImportDeclaration(node: any) {\n const imports = namedImportsFrom(node, 'firebase/database');\n if (imports.has('push')) pushLocalName = imports.get('push');\n if (imports.has('set')) setLocalName = imports.get('set');\n },\n VariableDeclarator(node: any) {\n if (node.id?.type === 'Identifier' && isMapCall(node.init)) {\n mapCallsByVarName.set(node.id.name, node.init);\n }\n },\n CallExpression(node: any) {\n if (!isPromiseAllCall(node)) return;\n const arg = node.arguments?.[0];\n\n // `Promise.all(items.map(...))` — inline.\n if (isAtomicBatchMapCall(arg)) {\n context.report({ node, messageId: 'batchWriteNotAtomic' });\n return;\n }\n\n // `const writes = items.map(...); Promise.all(writes)` — via a variable.\n if (arg?.type === 'Identifier') {\n const mapCall = mapCallsByVarName.get(arg.name);\n if (mapCall && isAtomicBatchMapCall(mapCall)) {\n context.report({ node, messageId: 'batchWriteNotAtomic' });\n }\n }\n },\n };\n },\n};\n\nexport const firebaseRtdbBatchWriteNotAtomicRule = rule;\nexport default rule;\n","/**\n * firebase-rtdb-listener-error-not-handled (reliability)\n *\n * `onValue`'s documented signature accepts a 3rd argument (a cancel/error\n * callback, or listen options). A 2-argument call drops that error path\n * entirely, so a PERMISSION_DENIED or dropped connection produces no UI\n * feedback and no console output.\n */\nimport { isIdentifierCall, namedImportsFrom } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'onValue listeners should handle the error callback',\n category: 'reliability',\n rationale:\n \"onValue's callback signature includes a documented error callback specifically for permission-denied and connection-loss cases. A call with only the success callback (2 arguments) silently drops that path, so a PERMISSION_DENIED or offline event produces no UI feedback and no console output.\",\n docsUrl: 'https://firebase.google.com/docs/reference/js/database.md#onvalue',\n recommended: true,\n },\n messages: {\n listenerErrorNotHandled:\n 'onValue is called with no error/cancel callback. Pass a 3rd argument so PERMISSION_DENIED and dropped connections surface somewhere.',\n },\n schema: [],\n },\n create(context: any) {\n let onValueLocalName: string | undefined;\n\n return {\n ImportDeclaration(node: any) {\n const imports = namedImportsFrom(node, 'firebase/database');\n if (imports.has('onValue')) onValueLocalName = imports.get('onValue');\n },\n CallExpression(node: any) {\n if (!isIdentifierCall(node, onValueLocalName)) return;\n if ((node.arguments ?? []).length < 3) {\n context.report({ node, messageId: 'listenerErrorNotHandled' });\n }\n },\n };\n },\n};\n\nexport const firebaseRtdbListenerErrorNotHandledRule = rule;\nexport default rule;\n","/**\n * firebase-effect-deps-whole-user-object (reliability)\n *\n * `onAuthStateChanged` delivers a new `user` object reference on every\n * internal token refresh (roughly hourly), even when `uid` is unchanged.\n * An effect that only reads `user.uid` but depends on the whole `user`\n * object tears down and re-establishes its RTDB listener on every refresh.\n */\nimport { isUidMemberAccess, someDescendant } from '../utils.js';\n\nfunction isUseEffectCall(node: any): boolean {\n return node?.type === 'CallExpression' && node.callee?.type === 'Identifier' && node.callee.name === 'useEffect';\n}\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'useEffect should depend on user?.uid, not the whole user object',\n category: 'reliability',\n rationale:\n \"onAuthStateChanged delivers a new user object reference on every internal token refresh (roughly hourly) even when uid is unchanged. An effect that only reads user.uid but lists the whole user object in its dependency array tears down and re-establishes its RTDB listener on every refresh — an avoidable unsubscribe/resubscribe cycle that briefly clears local state.\",\n docsUrl: 'https://firebase.google.com/docs/reference/js/auth.md#onauthstatechanged',\n recommended: true,\n },\n messages: {\n wholeUserObjectDep:\n 'This effect only reads {{name}}.uid but depends on the whole {{name}} object, which gets a new reference on every token refresh. Depend on {{name}}?.uid instead.',\n },\n schema: [],\n },\n create(context: any) {\n return {\n CallExpression(node: any) {\n if (!isUseEffectCall(node)) return;\n const [callback, depsArg] = node.arguments ?? [];\n if (!callback || depsArg?.type !== 'ArrayExpression') return;\n\n for (const el of depsArg.elements ?? []) {\n if (el?.type !== 'Identifier') continue;\n const name = el.name;\n if (someDescendant(callback, (n) => isUidMemberAccess(n, name))) {\n context.report({ node, messageId: 'wholeUserObjectDep', data: { name } });\n }\n }\n },\n };\n },\n};\n\nexport const firebaseEffectDepsWholeUserObjectRule = rule;\nexport default rule;\n","/**\n * firebase-rtdb-write-promise-not-handled (reliability)\n *\n * set()/update()/remove() return promises specifically so a rejected write\n * (offline, permission-denied, rules-rejected) can be handled. A bare\n * fire-and-forget call, or an awaited call with no surrounding try/catch,\n * means the caller proceeds (and may navigate away) as if the write\n * succeeded.\n */\nimport { chainLinks, contains, isIdentifierCall, memberPropName, namedImportsFrom } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Realtime Database write promises must be handled',\n category: 'reliability',\n rationale:\n 'set()/update()/remove() return promises specifically so a rejected write (offline, permission-denied, rules-rejected) can be handled. A bare fire-and-forget call, or an awaited call with no surrounding try/catch, means the caller proceeds — and may navigate away — as if the write succeeded, while the rejection is silently dropped.',\n docsUrl: 'https://firebase.google.com/docs/database/web/read-and-write',\n recommended: true,\n },\n messages: {\n writePromiseNotHandled:\n 'This Realtime Database write is neither awaited inside a try/catch nor given a .catch handler. A rejected write will be silently dropped.',\n },\n schema: [],\n },\n create(context: any) {\n const writeLocalNames = new Set<string>();\n const writeCalls = new Set<any>();\n const safeReturns = new Set<any>();\n const awaitedCalls = new Set<any>();\n const caughtCalls = new Set<any>();\n const tryBlocks: any[] = [];\n\n // Nodes are visited parent-before-child, so a ReturnStatement/AwaitExpression\n // is seen before the CallExpression it wraps — evaluate the predicate\n // directly here rather than checking membership in `writeCalls`.\n function isWriteCall(node: any): boolean {\n return [...writeLocalNames].some((n) => isIdentifierCall(node, n));\n }\n\n return {\n ImportDeclaration(node: any) {\n const imports = namedImportsFrom(node, 'firebase/database');\n for (const name of ['set', 'update', 'remove']) {\n const local = imports.get(name);\n if (local) writeLocalNames.add(local);\n }\n },\n TryStatement(node: any) {\n if (node.block) tryBlocks.push(node.block);\n },\n ReturnStatement(node: any) {\n if (isWriteCall(node.argument)) safeReturns.add(node.argument);\n },\n AwaitExpression(node: any) {\n if (isWriteCall(node.argument)) awaitedCalls.add(node.argument);\n },\n CallExpression(node: any) {\n if (isWriteCall(node)) writeCalls.add(node);\n\n const prop = memberPropName(node);\n const isCatch = prop === 'catch';\n const isTwoArgThen = prop === 'then' && (node.arguments ?? []).length >= 2;\n if (isCatch || isTwoArgThen) {\n for (const link of chainLinks(node)) {\n if (isWriteCall(link)) caughtCalls.add(link);\n }\n }\n },\n 'Program:exit'() {\n for (const call of writeCalls) {\n if (safeReturns.has(call)) continue;\n if (caughtCalls.has(call)) continue;\n if (awaitedCalls.has(call)) {\n if (tryBlocks.some((block) => contains(block, call))) continue;\n }\n context.report({ node: call, messageId: 'writePromiseNotHandled' });\n }\n },\n };\n },\n};\n\nexport const firebaseRtdbWritePromiseNotHandledRule = rule;\nexport default rule;\n","/** Shared AST helpers for Lovable rules. */\nexport const LLM_HOST_PATTERN = /api\\.anthropic\\.com|api\\.openai\\.com/;\n\n/** True if a string/template-literal AST node's text matches a known LLM provider host. */\nexport function containsKnownLlmHost(node: any): boolean {\n if (node?.type === 'Literal' && typeof node.value === 'string') {\n return LLM_HOST_PATTERN.test(node.value);\n }\n if (node?.type === 'TemplateLiteral') {\n return (node.quasis ?? []).some((q: any) => LLM_HOST_PATTERN.test(q.value?.raw ?? ''));\n }\n return false;\n}\n","/**\n * Flags a direct `fetch()` to a known LLM provider host carrying an API key\n * read from `import.meta.env.VITE_*` — VITE_-prefixed values are inlined\n * into the browser bundle at build time, so the key ships to every visitor.\n */\nimport { containsKnownLlmHost } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'LLM provider calls must not run client-side with a VITE_-exposed API key',\n category: 'security',\n cwe: 'CWE-522',\n owasp: 'A02:2021 – Cryptographic Failures',\n rationale:\n 'Anything read from import.meta.env.VITE_* is inlined into the production JS bundle at build time and is visible to every site visitor via the Network tab or by reading the bundle — no git access required. Lovable documents Edge Functions specifically so the provider key stays server-side in Secrets and the browser calls your own Edge Function instead of the provider directly.',\n docsUrl: 'https://docs.lovable.dev/features/security',\n recommended: true,\n },\n messages: {\n clientSideSecretFetch:\n 'This fetch() calls an LLM provider directly with a key sourced from import.meta.env.VITE_* — that key ships into the browser bundle and is visible to every visitor.',\n },\n },\n create(context: any) {\n const viteVars = new Set<string>();\n\n function propName(node: any): string | undefined {\n if (!node) return undefined;\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'Literal' && typeof node.value === 'string') return node.value;\n return undefined;\n }\n\n function isImportMetaEnvViteAccess(node: any): boolean {\n if (node?.type !== 'MemberExpression' || node.computed) return false;\n const propertyName = node.property?.name;\n if (typeof propertyName !== 'string' || !propertyName.startsWith('VITE_')) return false;\n const envMember = node.object;\n if (envMember?.type !== 'MemberExpression' || envMember.computed) return false;\n if (envMember.property?.name !== 'env') return false;\n const metaProp = envMember.object;\n return (\n metaProp?.type === 'MetaProperty' &&\n metaProp.meta?.name === 'import' &&\n metaProp.property?.name === 'meta'\n );\n }\n\n function referencesViteSecret(node: any): boolean {\n if (!node) return false;\n if (isImportMetaEnvViteAccess(node)) return true;\n if (node.type === 'Identifier' && viteVars.has(node.name)) return true;\n if (node.type === 'TemplateLiteral') {\n return (node.expressions ?? []).some((e: any) => referencesViteSecret(e));\n }\n return false;\n }\n\n return {\n VariableDeclarator(node: any) {\n if (node.id?.type === 'Identifier' && isImportMetaEnvViteAccess(node.init)) {\n viteVars.add(node.id.name);\n }\n },\n\n CallExpression(node: any) {\n const callee = node.callee;\n if (callee?.type !== 'Identifier' || callee.name !== 'fetch') return;\n\n const urlArg = node.arguments?.[0];\n if (!containsKnownLlmHost(urlArg)) return;\n\n const optsArg = node.arguments?.[1];\n if (optsArg?.type !== 'ObjectExpression') return;\n\n const headersProp = (optsArg.properties ?? []).find(\n (p: any) => p?.type === 'Property' && propName(p.key) === 'headers',\n );\n if (!headersProp || headersProp.value?.type !== 'ObjectExpression') return;\n\n for (const hp of headersProp.value.properties ?? []) {\n if (hp?.type !== 'Property') continue;\n const keyName = propName(hp.key)?.toLowerCase();\n if (keyName !== 'x-api-key' && keyName !== 'authorization') continue;\n if (referencesViteSecret(hp.value)) {\n context.report({ node, messageId: 'clientSideSecretFetch' });\n return;\n }\n }\n },\n };\n },\n};\n\nexport const lovableNoClientSideSecretFetchRule = rule;\n","/**\n * Flags a function that sets a boolean \"paid\"/\"premium\"/\"boosted\"-style flag\n * via a direct Supabase `.update()` call, in a file that advertises a price,\n * with no payment-provider or Edge Function call anywhere in that function.\n */\nconst PRICE_PATTERN = /\\$\\s?\\d/;\nconst FLAG_PROPERTY_PATTERN = /^is_[a-z0-9_]+$/i;\nconst FLAG_SUFFIX_PATTERN = /_(unlocked|active|enabled)$/i;\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'A paid feature flag must not be set by a direct database update with no payment-provider call',\n category: 'security',\n cwe: 'CWE-840',\n owasp: 'A04:2021 – Insecure Design',\n rationale:\n 'Lovable documents payment processing as Edge Function territory specifically so purchase/premium-access flags are only ever set after a payment provider confirms payment server-side. A handler that writes a paid-looking flag straight from the client with no payment call in between either never actually charges anyone, or — even if a charge happens elsewhere — leaves the flag itself freely settable by any caller with write access to the row.',\n docsUrl: 'https://docs.lovable.dev/features/cloud',\n recommended: true,\n },\n messages: {\n paidFlagWithoutPayment:\n 'This sets a paid-looking flag via a direct database update, but nothing in this function calls a payment provider or Edge Function first — the flag can be set without anyone paying.',\n },\n },\n create(context: any) {\n type FnState = { sawFlagUpdate: boolean; updateNode: any; sawPaymentCall: boolean };\n const stack: any[] = [];\n const states = new Map<any, FnState>();\n let sawPriceLabel = false;\n\n function ensureState(fn: any): FnState {\n let s = states.get(fn);\n if (!s) {\n s = { sawFlagUpdate: false, updateNode: null, sawPaymentCall: false };\n states.set(fn, s);\n }\n return s;\n }\n\n function top(): any {\n return stack[stack.length - 1];\n }\n\n function pushScope(node: any) {\n stack.push(node);\n ensureState(node);\n }\n\n function popScope() {\n stack.pop();\n }\n\n function propName(node: any): string | undefined {\n if (!node) return undefined;\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'Literal' && typeof node.value === 'string') return node.value;\n return undefined;\n }\n\n function isBooleanFlagProperty(name: string | undefined): boolean {\n if (!name) return false;\n return FLAG_PROPERTY_PATTERN.test(name) || FLAG_SUFFIX_PATTERN.test(name);\n }\n\n function isSupabaseUpdateCall(node: any): boolean {\n if (node?.type !== 'CallExpression') return false;\n const callee = node.callee;\n return callee?.type === 'MemberExpression' && callee.property?.name === 'update';\n }\n\n function updateSetsBooleanFlag(node: any): boolean {\n const arg = node.arguments?.[0];\n if (arg?.type !== 'ObjectExpression') return false;\n return (arg.properties ?? []).some(\n (p: any) => p?.type === 'Property' && isBooleanFlagProperty(propName(p.key)),\n );\n }\n\n function memberChainNames(node: any, names: string[] = []): string[] {\n if (node?.type === 'MemberExpression') {\n memberChainNames(node.object, names);\n const n = propName(node.property);\n if (n) names.push(n);\n } else if (node?.type === 'Identifier') {\n names.push(node.name);\n } else if (node?.type === 'CallExpression') {\n memberChainNames(node.callee, names);\n }\n return names;\n }\n\n function isPaymentRelatedCall(node: any): boolean {\n if (node?.type !== 'CallExpression') return false;\n const chain = memberChainNames(node.callee).join('.').toLowerCase();\n if (/stripe|checkout|payment/.test(chain)) return true;\n if (chain.includes('functions') && chain.endsWith('.invoke')) return true;\n if (node.callee?.type === 'Identifier' && node.callee.name === 'fetch') {\n const urlArg = node.arguments?.[0];\n if (urlArg?.type === 'Literal' && typeof urlArg.value === 'string') {\n return urlArg.value.includes('/functions/');\n }\n if (urlArg?.type === 'TemplateLiteral') {\n return (urlArg.quasis ?? []).some((q: any) => (q.value?.raw ?? '').includes('/functions/'));\n }\n }\n return false;\n }\n\n return {\n Program(node: any) {\n pushScope(node);\n },\n 'Program:exit'() {\n if (!sawPriceLabel) return;\n for (const state of states.values()) {\n if (state.sawFlagUpdate && !state.sawPaymentCall) {\n context.report({ node: state.updateNode, messageId: 'paidFlagWithoutPayment' });\n }\n }\n },\n\n FunctionDeclaration(node: any) {\n pushScope(node);\n },\n 'FunctionDeclaration:exit'() {\n popScope();\n },\n FunctionExpression(node: any) {\n pushScope(node);\n },\n 'FunctionExpression:exit'() {\n popScope();\n },\n ArrowFunctionExpression(node: any) {\n pushScope(node);\n },\n 'ArrowFunctionExpression:exit'() {\n popScope();\n },\n\n Literal(node: any) {\n if (typeof node.value === 'string' && PRICE_PATTERN.test(node.value)) sawPriceLabel = true;\n },\n JSXText(node: any) {\n if (typeof node.value === 'string' && PRICE_PATTERN.test(node.value)) sawPriceLabel = true;\n },\n TemplateElement(node: any) {\n if (PRICE_PATTERN.test(node.value?.raw ?? '')) sawPriceLabel = true;\n },\n\n CallExpression(node: any) {\n const fn = top();\n if (!fn) return;\n const state = ensureState(fn);\n\n if (isSupabaseUpdateCall(node) && updateSetsBooleanFlag(node) && !state.sawFlagUpdate) {\n state.sawFlagUpdate = true;\n state.updateNode = node;\n }\n\n if (isPaymentRelatedCall(node)) {\n state.sawPaymentCall = true;\n }\n },\n };\n },\n};\n\nexport const lovablePaidFlagWithoutEdgeFunctionRule = rule;\n","/**\n * Flags an `*_until`/`*_expires_at`/`*_expiry` column written via a Supabase\n * `.update()` call that is never compared against the current time anywhere\n * else in the same file — the expiry is recorded but nothing ever acts on it.\n */\nconst EXPIRY_COLUMN_PATTERN = /_(until|expires?_at|expiry)$/i;\nconst DATE_COMPARISON_OPERATORS = new Set(['>', '<', '>=', '<=']);\nconst FILTER_METHODS = new Set(['gt', 'gte', 'lt', 'lte']);\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'An expiry column must be checked against the current time somewhere',\n category: 'correctness',\n rationale:\n \"Writing a *_until/*_expires_at column without ever comparing it to the current time anywhere in the codebase means the expiry is purely cosmetic — whatever it was meant to gate (a boost, a trial, a temporary unlock) never actually expires once granted, whether it was granted legitimately or through an unrelated bug.\",\n docsUrl: 'https://docs.lovable.dev/features/cloud',\n recommended: true,\n },\n messages: {\n expiryNeverChecked:\n 'The \"{{column}}\" column is written here but is never compared against the current time anywhere in this file, so it never actually expires anything.',\n },\n },\n create(context: any) {\n const writtenColumns = new Map<string, any>();\n const readColumns = new Set<string>();\n\n function propName(node: any): string | undefined {\n if (!node) return undefined;\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'Literal' && typeof node.value === 'string') return node.value;\n return undefined;\n }\n\n function isSupabaseUpdateCall(node: any): boolean {\n if (node?.type !== 'CallExpression') return false;\n const callee = node.callee;\n return callee?.type === 'MemberExpression' && callee.property?.name === 'update';\n }\n\n function containsDateNowOrNewDate(node: any, depth = 0): boolean {\n if (!node || typeof node !== 'object' || depth > 6) return false;\n if (node.type === 'NewExpression' && node.callee?.type === 'Identifier' && node.callee.name === 'Date') {\n return true;\n }\n if (\n node.type === 'CallExpression' &&\n node.callee?.type === 'MemberExpression' &&\n node.callee.object?.type === 'Identifier' &&\n node.callee.object.name === 'Date' &&\n node.callee.property?.name === 'now'\n ) {\n return true;\n }\n if (node.type === 'MemberExpression') {\n return containsDateNowOrNewDate(node.object, depth + 1) || containsDateNowOrNewDate(node.callee, depth + 1);\n }\n if (node.type === 'CallExpression') {\n return containsDateNowOrNewDate(node.callee, depth + 1);\n }\n return false;\n }\n\n function memberPropertyName(node: any): string | undefined {\n if (node?.type !== 'MemberExpression') return undefined;\n return propName(node.property);\n }\n\n return {\n CallExpression(node: any) {\n if (isSupabaseUpdateCall(node)) {\n const arg = node.arguments?.[0];\n if (arg?.type === 'ObjectExpression') {\n for (const prop of arg.properties ?? []) {\n if (prop?.type !== 'Property') continue;\n const keyName = propName(prop.key);\n if (keyName && EXPIRY_COLUMN_PATTERN.test(keyName) && !writtenColumns.has(keyName)) {\n writtenColumns.set(keyName, node);\n }\n }\n }\n }\n\n // Supabase/PostgREST filter read: .gt('boosted_until', nowIso)\n const callee = node.callee;\n if (callee?.type === 'MemberExpression' && FILTER_METHODS.has(callee.property?.name)) {\n const colArg = node.arguments?.[0];\n const colName = colArg?.type === 'Literal' ? propName(colArg) : undefined;\n if (colName && EXPIRY_COLUMN_PATTERN.test(colName)) {\n readColumns.add(colName);\n }\n }\n },\n\n BinaryExpression(node: any) {\n if (!DATE_COMPARISON_OPERATORS.has(node.operator)) return;\n const leftCol = memberPropertyName(node.left);\n const rightCol = memberPropertyName(node.right);\n if (leftCol && EXPIRY_COLUMN_PATTERN.test(leftCol) && containsDateNowOrNewDate(node.right)) {\n readColumns.add(leftCol);\n }\n if (rightCol && EXPIRY_COLUMN_PATTERN.test(rightCol) && containsDateNowOrNewDate(node.left)) {\n readColumns.add(rightCol);\n }\n },\n\n 'Program:exit'() {\n for (const [column, node] of writtenColumns) {\n if (!readColumns.has(column)) {\n context.report({ node, messageId: 'expiryNeverChecked', data: { column } });\n }\n }\n },\n };\n },\n};\n\nexport const lovableExpiryColumnNeverCheckedRule = rule;\n","/**\n * Flags a try/catch around a `fetch()` to a known LLM provider host whose\n * catch block has no logging call — any failure (bad key, rate limit,\n * network error) becomes indistinguishable from \"no key configured.\"\n */\nimport { containsKnownLlmHost } from '../utils.js';\n\nconst LOGGING_CONSOLE_METHODS = new Set(['error', 'warn', 'log', 'info']);\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'A catch block around an LLM provider call must log the failure',\n category: 'correctness',\n rationale:\n 'Returning null/undefined from a bare catch with no logging makes every failure mode — missing key, expired key, rate limit, malformed response, network error — look identical to \"no key configured.\" If a deployment\\'s provider key starts failing in production, this is invisible: there is nothing in the browser or error-tracking logs to distinguish a real outage from an intentionally-unconfigured feature.',\n docsUrl: 'https://docs.lovable.dev/features/cloud',\n recommended: true,\n },\n messages: {\n silentCatch:\n 'This catch block swallows a failed LLM provider call with no logging — a real failure (expired key, rate limit, network error) is indistinguishable from \"no key configured.\"',\n },\n },\n create(context: any) {\n function findFetchToLlmHost(node: any, depth = 0): any {\n if (!node || typeof node !== 'object' || depth > 12) return null;\n if (Array.isArray(node)) {\n for (const n of node) {\n const found = findFetchToLlmHost(n, depth + 1);\n if (found) return found;\n }\n return null;\n }\n if (node.type === 'CallExpression' && node.callee?.type === 'Identifier' && node.callee.name === 'fetch') {\n const urlArg = node.arguments?.[0];\n if (containsKnownLlmHost(urlArg)) return node;\n }\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = (node as any)[key];\n if (val && typeof val === 'object') {\n const found = findFetchToLlmHost(val, depth + 1);\n if (found) return found;\n }\n }\n return null;\n }\n\n function containsLoggingCall(node: any, depth = 0): boolean {\n if (!node || typeof node !== 'object' || depth > 12) return false;\n if (Array.isArray(node)) return node.some((n) => containsLoggingCall(n, depth + 1));\n if (node.type === 'CallExpression') {\n const callee = node.callee;\n if (callee?.type === 'MemberExpression') {\n const objName = callee.object?.type === 'Identifier' ? callee.object.name : undefined;\n const propertyName = callee.property?.name;\n if (objName === 'console' && LOGGING_CONSOLE_METHODS.has(propertyName)) return true;\n if (propertyName === 'captureException') return true;\n }\n if (callee?.type === 'Identifier' && callee.name === 'reportError') return true;\n }\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = (node as any)[key];\n if (val && typeof val === 'object') {\n if (containsLoggingCall(val, depth + 1)) return true;\n }\n }\n return false;\n }\n\n return {\n TryStatement(node: any) {\n const fetchNode = findFetchToLlmHost(node.block);\n if (!fetchNode) return;\n\n const handler = node.handler;\n if (!handler) return;\n\n if (!containsLoggingCall(handler.body)) {\n context.report({ node: handler, messageId: 'silentCatch' });\n }\n },\n };\n },\n};\n\nexport const lovableSilentCatchOnProviderCallRule = rule;\n","/**\n * Shared AST helpers for Browserbase rules. Kept intentionally small; extend\n * only when logic is genuinely reused across rules.\n *\n * The Node SDK (`@browserbasehq/sdk`, Stainless-generated) exposes a\n * `client.sessions.*` / `client.contexts.*` resource API, so most call-site\n * matching here is member-expression based (`<client>.sessions.create(...)`)\n * rather than free-function matching like some other providers.\n */\n\n/** Returns the called method name for `<chain>.<name>(...)`, handling computed string-literal access. */\nexport function memberPropName(node: any): string | undefined {\n if (node?.type !== 'CallExpression') return undefined;\n const callee = node.callee;\n if (callee?.type !== 'MemberExpression') return undefined;\n const prop = callee.property;\n if (!callee.computed && prop?.type === 'Identifier') return prop.name;\n if (callee.computed && prop?.type === 'Literal' && typeof prop.value === 'string') return prop.value;\n return undefined;\n}\n\n/** The CallExpression this call is chained onto (`<this>.method()`), or null if the base isn't itself a call. */\nexport function chainObjectCall(node: any): any | null {\n const obj = node?.callee?.object;\n return obj?.type === 'CallExpression' ? obj : null;\n}\n\n/** Every CallExpression link in a member chain, starting at `node` and walking down to the base call. */\nexport function chainLinks(node: any): any[] {\n const links: any[] = [];\n let current: any = node;\n while (current?.type === 'CallExpression') {\n links.push(current);\n current = chainObjectCall(current);\n }\n return links;\n}\n\n/** True for `<chain>.sessions.<name>(...)`, e.g. `bb.sessions.create(...)`, `client.sessions.debug(...)`. */\nexport function isSessionsCall(node: any, name: string): boolean {\n if (memberPropName(node) !== name) return false;\n const obj = node.callee.object;\n return obj?.type === 'MemberExpression' && !obj.computed && obj.property?.type === 'Identifier' && obj.property.name === 'sessions';\n}\n\n/** True for `<chain>.sessions.recording.<name>(...)`. */\nexport function isSessionsRecordingCall(node: any, name: string): boolean {\n if (memberPropName(node) !== name) return false;\n const recordingObj = node.callee.object;\n if (recordingObj?.type !== 'MemberExpression' || recordingObj.computed) return false;\n if (recordingObj.property?.type !== 'Identifier' || recordingObj.property.name !== 'recording') return false;\n const sessionsObj = recordingObj.object;\n return (\n sessionsObj?.type === 'MemberExpression' &&\n !sessionsObj.computed &&\n sessionsObj.property?.type === 'Identifier' &&\n sessionsObj.property.name === 'sessions'\n );\n}\n\n/** Returns the Property node named `name` on an ObjectExpression, else undefined. */\nexport function findProperty(objectExpression: any, name: string): any | undefined {\n if (objectExpression?.type !== 'ObjectExpression') return undefined;\n return objectExpression.properties?.find(\n (p: any) =>\n p?.type === 'Property' &&\n ((p.key?.type === 'Identifier' && p.key.name === name) || (p.key?.type === 'Literal' && p.key.value === name)),\n );\n}\n\n/** Best-effort absolute start offset of a node (range -> start -> loc fallback). */\nexport function startOffset(n: any): number {\n if (typeof n?.range?.[0] === 'number') return n.range[0];\n if (typeof n?.start === 'number') return n.start;\n return (n?.loc?.start?.line ?? 0) * 1_000_000 + (n?.loc?.start?.column ?? 0);\n}\n\n/** Best-effort absolute end offset of a node (range -> end -> loc fallback). */\nexport function endOffset(n: any): number {\n if (typeof n?.range?.[1] === 'number') return n.range[1];\n if (typeof n?.end === 'number') return n.end;\n return (n?.loc?.end?.line ?? n?.loc?.start?.line ?? 0) * 1_000_000 + (n?.loc?.end?.column ?? 0);\n}\n\n/** True when `outer`'s range fully contains `inner`'s start position. */\nexport function contains(outer: any, inner: any): boolean {\n const s = startOffset(inner);\n return s >= startOffset(outer) && s <= endOffset(outer);\n}\n\n/** Depth-first search over the AST rooted at `node` for any descendant matching `predicate`. */\nexport function someDescendant(node: any, predicate: (n: any) => boolean): boolean {\n let found = false;\n function visit(n: any) {\n if (found || !n || typeof n !== 'object') return;\n if (Array.isArray(n)) {\n for (const item of n) visit(item);\n return;\n }\n if (typeof n.type !== 'string') return;\n if (predicate(n)) {\n found = true;\n return;\n }\n for (const key of Object.keys(n)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n visit(n[key]);\n }\n }\n visit(node);\n return found;\n}\n\n/** True for a call to a response-sending method: res.json/.send, Response.json, NextResponse.json. */\nexport function isResponseSendCall(node: any): boolean {\n const name = memberPropName(node);\n if (name !== 'json' && name !== 'send') return false;\n const obj = node.callee.object;\n if (obj?.type === 'Identifier') {\n return /^(res|response)$/i.test(obj.name) || obj.name === 'Response' || obj.name === 'NextResponse';\n }\n return false;\n}\n\n/** True when the file path looks like a test file. */\nexport function isInsideTestFile(filename: string): boolean {\n return /(^|[\\\\/])__tests__[\\\\/]|\\.(test|spec)\\.[cm]?[jt]sx?$/.test(filename);\n}\n","/**\n * browserbase-no-conditional-authz-on-anonymous-user (security)\n *\n * A route handler that returns a Browserbase live-debugger URL or session\n * recording must reject unauthenticated/unauthorized callers unconditionally.\n * Gating the ownership check behind `if (user) { ...check... }` with no\n * unconditional `if (!user) return` guard means an anonymous request simply\n * skips the whole block and falls through to the sensitive call.\n */\nimport { contains, endOffset, isSessionsCall, isSessionsRecordingCall, startOffset } from '../utils.js';\n\nfunction isUserLikeExpr(node: any): boolean {\n if (node?.type === 'Identifier') return /user/i.test(node.name);\n if (node?.type === 'MemberExpression' && !node.computed && node.property?.type === 'Identifier') {\n return /user/i.test(node.property.name);\n }\n return false;\n}\n\nfunction isFalsyGuardTest(test: any): boolean {\n if (test?.type === 'UnaryExpression' && test.operator === '!') return isUserLikeExpr(test.argument);\n if (test?.type === 'BinaryExpression' && (test.operator === '===' || test.operator === '==')) {\n const sides = [test.left, test.right];\n const isNullish = (n: any) => (n?.type === 'Literal' && n.value === null) || (n?.type === 'Identifier' && n.name === 'undefined');\n const nullSide = sides.find(isNullish);\n const otherSide = sides.find((s: any) => s !== nullSide);\n return !!nullSide && isUserLikeExpr(otherSide);\n }\n return false;\n}\n\nfunction hasReturnOrThrow(stmt: any): boolean {\n if (!stmt) return false;\n if (stmt.type === 'ReturnStatement' || stmt.type === 'ThrowStatement') return true;\n if (stmt.type === 'BlockStatement') {\n return (stmt.body ?? []).some((s: any) => s.type === 'ReturnStatement' || s.type === 'ThrowStatement');\n }\n return false;\n}\n\nfunction isTruthyGateTest(test: any): boolean {\n if (isUserLikeExpr(test)) return true;\n if (test?.type === 'LogicalExpression' && test.operator === '&&') {\n return isTruthyGateTest(test.left) || isTruthyGateTest(test.right);\n }\n return false;\n}\n\ntype Scope = { node: any; start: number; end: number; guardPos?: number };\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Sensitive Browserbase resources must be guarded by unconditional authorization',\n category: 'security',\n cwe: 'CWE-862',\n owasp: 'A01:2021 Broken Access Control',\n rationale:\n 'bb.sessions.debug() and bb.sessions.recording.retrieve() return a live CDP debugger URL or a full rrweb session replay — high-value resources. Gating the ownership check behind `if (user) { ...check... }` with no unconditional `if (!user) return` guard means an anonymous caller (no credentials at all) simply skips the whole block and falls through to the sensitive call. Authorization must reject the unauthenticated case explicitly, not rely on a conditional that happens to be true for legitimate callers.',\n docsUrl: 'https://docs.browserbase.com/reference/api/session-live-urls',\n recommended: true,\n },\n messages: {\n conditionalAuthz:\n 'This route returns a Browserbase live-view/recording resource gated only by `if (user) {...}` with no unconditional rejection for anonymous callers. Add an `if (!user) return ...` guard before this.',\n },\n schema: [],\n },\n create(context: any) {\n const scopes: Scope[] = [];\n const gates: Array<{ start: number; end: number }> = [];\n const sensitiveCalls: any[] = [];\n\n function registerScope(node: any) {\n scopes.push({ node, start: startOffset(node), end: endOffset(node) });\n }\n\n function innermostScope(pos: number): Scope | undefined {\n let best: Scope | undefined;\n for (const scope of scopes) {\n if (pos < scope.start || pos > scope.end) continue;\n if (!best || scope.end - scope.start < best.end - best.start) best = scope;\n }\n return best;\n }\n\n return {\n FunctionDeclaration(node: any) {\n registerScope(node);\n },\n FunctionExpression(node: any) {\n registerScope(node);\n },\n ArrowFunctionExpression(node: any) {\n registerScope(node);\n },\n IfStatement(node: any) {\n if (isFalsyGuardTest(node.test) && hasReturnOrThrow(node.consequent)) {\n const pos = startOffset(node);\n const scope = innermostScope(pos);\n if (scope && (scope.guardPos === undefined || pos < scope.guardPos)) scope.guardPos = pos;\n return;\n }\n if (isTruthyGateTest(node.test) && !node.alternate) {\n gates.push({ start: startOffset(node), end: endOffset(node) });\n }\n },\n CallExpression(node: any) {\n if (isSessionsCall(node, 'debug') || isSessionsRecordingCall(node, 'retrieve')) {\n sensitiveCalls.push(node);\n }\n },\n 'Program:exit'() {\n for (const call of sensitiveCalls) {\n const gate = gates.find((g) => contains(g, call));\n if (!gate) continue;\n const scope = innermostScope(startOffset(call));\n const hasGuardBeforeGate = scope?.guardPos !== undefined && scope.guardPos < gate.start;\n if (!hasGuardBeforeGate) {\n context.report({ node: call, messageId: 'conditionalAuthz' });\n }\n }\n },\n };\n },\n};\n\nexport const browserbaseNoConditionalAuthzOnAnonymousUserRule = rule;\nexport default rule;\n","/**\n * browserbase-no-connect-url-in-api-response (security)\n *\n * `connectUrl` (the WebSocket CDP URL on SessionCreateResponse) is\n * self-authenticating — connecting to it grants full read/write control of\n * the live browser. It must stay server-side; the sharable artifact is\n * `debuggerFullscreenUrl` from `sessions.debug()`, not `connectUrl`.\n */\nimport { findProperty, isResponseSendCall } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'connectUrl must never be placed in an HTTP response body',\n category: 'security',\n cwe: 'CWE-200',\n owasp: 'A04:2021 Insecure Design',\n rationale:\n \"session.connectUrl is the WebSocket CDP URL returned by sessions.create() — it is self-authenticating; connecting to it grants full read/write control of the live browser (arbitrary JS execution, cookie/localStorage read, simulated input), equivalent to a bearer token. Putting it in a response body widens its exposure (network tab, browser extensions, error trackers, logs) for callers that almost never need it client-side — the intended sharable artifact is debuggerFullscreenUrl from sessions.debug().\",\n docsUrl: 'https://docs.browserbase.com/reference/api/create-a-session',\n recommended: true,\n },\n messages: {\n connectUrlInResponse:\n 'connectUrl is included in an HTTP response body. Keep it server-side only — it is a bearer credential for the live browser, not a sharable URL.',\n },\n schema: [],\n },\n create(context: any) {\n return {\n CallExpression(node: any) {\n if (!isResponseSendCall(node)) return;\n const arg = node.arguments?.[0];\n if (arg?.type !== 'ObjectExpression') return;\n if (findProperty(arg, 'connectUrl')) {\n context.report({ node, messageId: 'connectUrlInResponse' });\n }\n },\n };\n },\n};\n\nexport const browserbaseNoConnectUrlInApiResponseRule = rule;\nexport default rule;\n","/**\n * browserbase-session-id-requires-ownership-check (security)\n *\n * A handler that takes a sessionId (route param, query, or body) and passes\n * it straight into a Browserbase live-view/recording call with no ownership\n * check first is an IDOR: any authenticated user who learns or guesses a\n * session id can view someone else's live session.\n */\nimport { endOffset, isSessionsCall, isSessionsRecordingCall, startOffset } from '../utils.js';\n\nfunction isOwnershipCheckCall(node: any): boolean {\n if (node?.type !== 'CallExpression') return false;\n const callee = node.callee;\n const name =\n callee?.type === 'Identifier'\n ? callee.name\n : callee?.type === 'MemberExpression' && !callee.computed && callee.property?.type === 'Identifier'\n ? callee.property.name\n : undefined;\n if (!name) return false;\n return /owner|belongsto|hasaccess|authorize|verifyaccess|checkaccess|findproject|getproject/i.test(name);\n}\n\nfunction isSessionIdLikeArg(node: any): boolean {\n if (node?.type === 'Identifier') return /sessionid/i.test(node.name);\n if (node?.type === 'MemberExpression' && !node.computed && node.property?.type === 'Identifier') {\n return /sessionid/i.test(node.property.name);\n }\n return false;\n}\n\ntype Scope = { node: any; start: number; end: number; sawOwnershipCheck: boolean };\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Session id lookups must verify ownership before returning live-view data',\n category: 'security',\n cwe: 'CWE-862',\n rationale:\n 'A session id alone is not an authorization token — it is an opaque identifier that can leak via links, logs, screenshots, or support tickets. A handler that resolves a sessionId straight into sessions.debug()/sessions.recording.retrieve() with no ownership/org-membership check lets any authenticated caller view or replay a session that belongs to someone else.',\n docsUrl: 'https://docs.browserbase.com/features/session-live-view',\n recommended: true,\n },\n messages: {\n missingOwnershipCheck:\n 'sessionId is passed directly into a Browserbase live-view/recording call with no ownership check beforehand.',\n },\n schema: [],\n },\n create(context: any) {\n const scopes: Scope[] = [];\n const sensitiveCalls: any[] = [];\n\n function registerScope(node: any) {\n scopes.push({ node, start: startOffset(node), end: endOffset(node), sawOwnershipCheck: false });\n }\n\n function innermostScope(pos: number): Scope | undefined {\n let best: Scope | undefined;\n for (const scope of scopes) {\n if (pos < scope.start || pos > scope.end) continue;\n if (!best || scope.end - scope.start < best.end - best.start) best = scope;\n }\n return best;\n }\n\n return {\n FunctionDeclaration(node: any) {\n registerScope(node);\n },\n FunctionExpression(node: any) {\n registerScope(node);\n },\n ArrowFunctionExpression(node: any) {\n registerScope(node);\n },\n CallExpression(node: any) {\n const pos = startOffset(node);\n const scope = innermostScope(pos);\n\n if (isOwnershipCheckCall(node)) {\n for (const s of scopes) {\n if (pos >= s.start && pos <= s.end) s.sawOwnershipCheck = true;\n }\n return;\n }\n\n if (isSessionsCall(node, 'debug') || isSessionsRecordingCall(node, 'retrieve')) {\n const sessionIdArg = (node.arguments ?? []).some(isSessionIdLikeArg);\n if (sessionIdArg) sensitiveCalls.push({ node, scope });\n }\n },\n 'Program:exit'() {\n for (const { node, scope } of sensitiveCalls) {\n if (!scope || !scope.sawOwnershipCheck) {\n context.report({ node, messageId: 'missingOwnershipCheck' });\n }\n }\n },\n };\n },\n};\n\nexport const browserbaseSessionIdRequiresOwnershipCheckRule = rule;\nexport default rule;\n","/**\n * browserbase-no-concurrent-shared-context (correctness)\n *\n * Browserbase's docs are explicit: \"Avoid having multiple sessions using the\n * same Context at once. Sites may force a log out.\" Passing the same\n * browserSettings.context.id into every iteration of a concurrent\n * Promise.all batch creates 2+ sessions simultaneously attached to one\n * Context.\n */\nimport { findProperty, isSessionsCall, memberPropName } from '../utils.js';\n\nfunction isPromiseAllCall(node: any): boolean {\n return (\n node?.type === 'CallExpression' &&\n node.callee?.type === 'MemberExpression' &&\n !node.callee.computed &&\n node.callee.object?.type === 'Identifier' &&\n node.callee.object.name === 'Promise' &&\n node.callee.property?.type === 'Identifier' &&\n node.callee.property.name === 'all'\n );\n}\n\nfunction isMapCall(node: any): boolean {\n return memberPropName(node) === 'map';\n}\n\nfunction callbackParamNames(callback: any): Set<string> {\n const names = new Set<string>();\n const param = callback?.params?.[0];\n if (param?.type === 'Identifier') {\n names.add(param.name);\n } else if (param?.type === 'ObjectPattern') {\n for (const p of param.properties ?? []) {\n if (p?.type === 'Property' && p.value?.type === 'Identifier') names.add(p.value.name);\n else if (p?.type === 'RestElement' && p.argument?.type === 'Identifier') names.add(p.argument.name);\n }\n }\n return names;\n}\n\nfunction contextIdValueIsShared(callback: any, contextIdNode: any): boolean {\n if (contextIdNode?.type !== 'Identifier') return false;\n const params = callbackParamNames(callback);\n if (params.has(contextIdNode.name)) return false;\n\n // `(combo) => ... combo.contextId ...` style — not flaggable as an Identifier\n // check; the bare-identifier case below is the pattern this rule targets.\n return true;\n}\n\nfunction findSharedContextCreateCall(callback: any): any | null {\n const body = callback?.body;\n if (!body) return null;\n\n let found: any = null;\n function visit(n: any) {\n if (found || !n || typeof n !== 'object') return;\n if (Array.isArray(n)) {\n for (const item of n) visit(item);\n return;\n }\n if (typeof n.type !== 'string') return;\n\n if (isSessionsCall(n, 'create')) {\n const optsArg = n.arguments?.[0];\n const browserSettings = findProperty(optsArg, 'browserSettings')?.value;\n const ctxProp = findProperty(browserSettings, 'context')?.value;\n const idProp = findProperty(ctxProp, 'id');\n if (idProp && contextIdValueIsShared(callback, idProp.value)) {\n found = n;\n return;\n }\n }\n for (const key of Object.keys(n)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n visit(n[key]);\n }\n }\n visit(body);\n return found;\n}\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'A Browserbase Context must not be attached to concurrent sessions',\n category: 'correctness',\n rationale:\n 'Browserbase\\'s docs state explicitly: \"Avoid having multiple sessions using the same Context at once. Sites may force a log out.\" Passing the same browserSettings.context.id into every iteration of a Promise.all(items.map(...)) batch creates 2+ Browserbase sessions simultaneously attached to one Context, producing non-deterministic, flaky failures when a site force-logs-out one session because another concurrently authenticated against the same context.',\n docsUrl: 'https://docs.browserbase.com/features/contexts',\n recommended: true,\n },\n messages: {\n concurrentSharedContext:\n 'The same browserSettings.context.id is passed into every concurrent sessions.create() call in this Promise.all batch. Sites may force a log out when 2+ sessions share a Context at once.',\n },\n schema: [],\n },\n create(context: any) {\n const mapCallsByVarName = new Map<string, any>();\n\n function checkMapCall(mapCallNode: any) {\n if (!isMapCall(mapCallNode)) return;\n const callback = mapCallNode.arguments?.[mapCallNode.arguments.length - 1];\n if (!callback) return;\n const sharedCall = findSharedContextCreateCall(callback);\n if (sharedCall) {\n context.report({ node: sharedCall, messageId: 'concurrentSharedContext' });\n }\n }\n\n return {\n VariableDeclarator(node: any) {\n if (node.id?.type === 'Identifier' && isMapCall(node.init)) {\n mapCallsByVarName.set(node.id.name, node.init);\n }\n },\n CallExpression(node: any) {\n if (!isPromiseAllCall(node)) return;\n const arg = node.arguments?.[0];\n\n if (isMapCall(arg)) {\n checkMapCall(arg);\n return;\n }\n if (arg?.type === 'Identifier') {\n const mapCall = mapCallsByVarName.get(arg.name);\n if (mapCall) checkMapCall(mapCall);\n }\n },\n };\n },\n};\n\nexport const browserbaseNoConcurrentSharedContextRule = rule;\nexport default rule;\n","/**\n * browserbase-mobile-device-requires-os-setting (correctness)\n *\n * The Node SDK has no `fingerprint.devices`/`operatingSystems` API (that is\n * a Python-SDK-only shape) — device/OS emulation in Node is\n * `browserSettings.os: 'mobile' | 'tablet'`. A \"mobile\" combo that only\n * resizes the Playwright viewport, without setting `browserSettings.os`, is\n * still a desktop Chrome browser with a desktop user-agent in a small\n * window — sites that branch on UA/touch capability never see real mobile\n * behavior.\n */\nimport { someDescendant } from '../utils.js';\n\nfunction isMobileLiteral(node: any): boolean {\n return node?.type === 'Literal' && (node.value === 'mobile' || node.value === 'tablet');\n}\n\nfunction testComparesToMobile(test: any): boolean {\n if (test?.type !== 'BinaryExpression') return false;\n if (test.operator !== '===' && test.operator !== '==') return false;\n return isMobileLiteral(test.left) || isMobileLiteral(test.right);\n}\n\nfunction isViewportReference(node: any): boolean {\n if (node?.type === 'Identifier') return /viewport/i.test(node.name);\n if (node?.type === 'MemberExpression' && !node.computed && node.property?.type === 'Identifier') {\n return /viewport|width|height/i.test(node.property.name);\n }\n if (node?.type === 'Property') {\n return node.key?.type === 'Identifier' && /viewport|width|height/i.test(node.key.name);\n }\n return false;\n}\n\nfunction setsViewport(node: any): boolean {\n return someDescendant(node, isViewportReference);\n}\n\nfunction isOsMobileSetting(node: any): boolean {\n // `os: 'mobile'` / `os: 'tablet'` object property\n if (node?.type === 'Property' && node.key?.type === 'Identifier' && node.key.name === 'os' && isMobileLiteral(node.value)) {\n return true;\n }\n // `<x>.os = 'mobile'` assignment\n if (\n node?.type === 'AssignmentExpression' &&\n node.left?.type === 'MemberExpression' &&\n !node.left.computed &&\n node.left.property?.type === 'Identifier' &&\n node.left.property.name === 'os' &&\n isMobileLiteral(node.right)\n ) {\n return true;\n }\n return false;\n}\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Mobile device combos must set browserSettings.os, not just resize the viewport',\n category: 'correctness',\n rationale:\n \"The Node SDK's device emulation lever is browserSettings.os: 'mobile' | 'tablet' — there is no fingerprint API in this SDK. A \\\"mobile\\\" session that only resizes the Playwright viewport is still a desktop Chrome browser with a desktop user-agent string in a small window. Sites that branch behavior on UA/touch capability (the majority of responsive sites) never actually exercise their mobile code path, silently undermining \\\"test on mobile\\\" results.\",\n docsUrl: 'https://docs.browserbase.com/features/stealth-mode',\n recommended: true,\n },\n messages: {\n missingOsSetting:\n 'A \"mobile\" branch resizes the viewport but never sets browserSettings.os to \"mobile\"/\"tablet\". Without it this is still a desktop browser in a small window.',\n },\n schema: [],\n },\n create(context: any) {\n const mobileViewportBranches: any[] = [];\n let sawOsMobileSetting = false;\n\n return {\n IfStatement(node: any) {\n if (testComparesToMobile(node.test) && setsViewport(node.consequent)) {\n mobileViewportBranches.push(node);\n }\n },\n Property(node: any) {\n if (isOsMobileSetting(node)) sawOsMobileSetting = true;\n },\n AssignmentExpression(node: any) {\n if (isOsMobileSetting(node)) sawOsMobileSetting = true;\n },\n 'Program:exit'() {\n if (sawOsMobileSetting) return;\n for (const branch of mobileViewportBranches) {\n context.report({ node: branch, messageId: 'missingOsSetting' });\n }\n },\n };\n },\n};\n\nexport const browserbaseMobileDeviceRequiresOsSettingRule = rule;\nexport default rule;\n","/**\n * browserbase-use-typed-exception-status-not-substring (correctness)\n *\n * The SDK raises typed `Browserbase.APIError` (and subclasses) carrying a\n * real `.status: number`. Matching `err.message`/`String(err)` against\n * substrings like \"410\" or \"Gone\" is fragile — the API provider can change\n * an unversioned, human-readable error message at any time without notice.\n */\nimport { someDescendant } from '../utils.js';\n\nfunction isStringifiedErrorSource(node: any, errName: string): boolean {\n // String(err)\n if (node?.type === 'CallExpression' && node.callee?.type === 'Identifier' && node.callee.name === 'String') {\n const arg = node.arguments?.[0];\n return arg?.type === 'Identifier' && arg.name === errName;\n }\n // err.message / err.toString()\n if (node?.type === 'CallExpression' && node.callee?.type === 'MemberExpression') {\n const obj = node.callee.object;\n const prop = node.callee.property;\n if (obj?.type === 'Identifier' && obj.name === errName && prop?.type === 'Identifier' && prop.name === 'toString') {\n return true;\n }\n }\n if (node?.type === 'MemberExpression' && !node.computed) {\n const obj = node.object;\n const prop = node.property;\n if (obj?.type === 'Identifier' && obj.name === errName && prop?.type === 'Identifier' && prop.name === 'message') {\n return true;\n }\n }\n return false;\n}\n\nfunction unwrapToLowerCase(node: any): any {\n if (\n node?.type === 'CallExpression' &&\n node.callee?.type === 'MemberExpression' &&\n node.callee.property?.type === 'Identifier' &&\n node.callee.property.name === 'toLowerCase'\n ) {\n return node.callee.object;\n }\n return node;\n}\n\nfunction usesTypedStatus(body: any, errName: string): boolean {\n return someDescendant(body, (n) => {\n if (n.type === 'MemberExpression' && !n.computed && n.object?.type === 'Identifier' && n.object.name === errName) {\n return n.property?.type === 'Identifier' && n.property.name === 'status';\n }\n if (n.type === 'BinaryExpression' && n.operator === 'instanceof' && n.left?.type === 'Identifier' && n.left.name === errName) {\n return true;\n }\n return false;\n });\n}\n\nfunction usesSubstringMatch(body: any, errName: string, stringifiedVars: Set<string>): boolean {\n return someDescendant(body, (n) => {\n if (n.type !== 'CallExpression') return false;\n if (n.callee?.type !== 'MemberExpression' || n.callee.computed) return false;\n if (n.callee.property?.type !== 'Identifier' || n.callee.property.name !== 'includes') return false;\n const source = unwrapToLowerCase(n.callee.object);\n if (isStringifiedErrorSource(source, errName)) return true;\n return source?.type === 'Identifier' && stringifiedVars.has(source.name);\n });\n}\n\nfunction collectStringifiedVars(body: any, errName: string): Set<string> {\n const names = new Set<string>();\n someDescendant(body, (n) => {\n if (n.type === 'VariableDeclarator' && n.id?.type === 'Identifier' && n.init) {\n const source = unwrapToLowerCase(n.init);\n if (isStringifiedErrorSource(source, errName)) names.add(n.id.name);\n }\n return false;\n });\n return names;\n}\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Branch on err.status, not a substring match of the stringified error',\n category: 'correctness',\n rationale:\n \"The SDK raises typed Browserbase.APIError (and subclasses like NotFoundError) carrying a real .status: number and .headers. Matching err.message or String(err) against substrings like \\\"410\\\" or \\\"Session stopped\\\" is fragile — that human-readable text is an unversioned implementation detail the provider can change at any time without notice. Check err.status (or `instanceof`) instead.\",\n docsUrl: 'https://docs.browserbase.com/reference/api/session-live-urls',\n recommended: true,\n },\n messages: {\n substringStatusMatch:\n 'This catch block matches a substring of the stringified error instead of checking err.status or `instanceof Browserbase.APIError`.',\n },\n schema: [],\n },\n create(context: any) {\n return {\n CatchClause(node: any) {\n const param = node.param;\n const errName = param?.type === 'Identifier' ? param.name : undefined;\n if (!errName || !node.body) return;\n\n if (usesTypedStatus(node.body, errName)) return;\n\n const stringifiedVars = collectStringifiedVars(node.body, errName);\n if (usesSubstringMatch(node.body, errName, stringifiedVars)) {\n context.report({ node, messageId: 'substringStatusMatch' });\n }\n },\n };\n },\n};\n\nexport const browserbaseUseTypedExceptionStatusNotSubstringRule = rule;\nexport default rule;\n","/**\n * browserbase-release-session-on-connect-failure (reliability)\n *\n * If a CDP connect call (e.g. Playwright's `connectOverCDP`) raises after\n * `sessions.create()` already succeeded, the session stays RUNNING on\n * Browserbase's side unless something explicitly releases it. The SDK's own\n * docstring warns: \"Use REQUEST_RELEASE before session's timeout to avoid\n * additional charges.\"\n */\nimport { contains, findProperty, isSessionsCall, memberPropName, someDescendant } from '../utils.js';\n\nfunction isSessionsCreateAwait(node: any): boolean {\n return node?.type === 'AwaitExpression' && isSessionsCall(node.argument, 'create');\n}\n\nfunction isConnectCall(node: any): boolean {\n if (node?.type !== 'CallExpression') return false;\n const callee = node.callee;\n const name = callee?.type === 'Identifier' ? callee.name : memberPropName(node);\n return !!name && /connect/i.test(name);\n}\n\nfunction isReleaseCall(node: any): boolean {\n if (node?.type !== 'CallExpression') return false;\n if (isSessionsCall(node, 'update')) {\n const optsArg = node.arguments?.[1];\n const statusProp = findProperty(optsArg, 'status');\n if (statusProp?.value?.type === 'Literal' && statusProp.value.value === 'REQUEST_RELEASE') return true;\n }\n const callee = node.callee;\n const name = callee?.type === 'Identifier' ? callee.name : memberPropName(node);\n return !!name && /requeststop|releasesession|release_session/i.test(name);\n}\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'A failed connect after session creation must release the session',\n category: 'reliability',\n rationale:\n \"If the CDP connect call raises after sessions.create() already succeeded on Browserbase's side, the session stays RUNNING and only terminates once its timeout elapses (up to 6h) unless something explicitly calls sessions.update(id, { status: 'REQUEST_RELEASE' }). The SDK's own docs warn to do this before the timeout \\\"to avoid additional charges.\\\" A connect call with no try/catch (or a catch that doesn't release) leaks the session on every connect failure.\",\n docsUrl: 'https://docs.browserbase.com/reference/api/update-a-session',\n recommended: true,\n },\n messages: {\n sessionNotReleasedOnFailure:\n 'A session was created but this connect call has no catch that releases it (sessions.update with status: \"REQUEST_RELEASE\") on failure. A failed connect will leak the session until its timeout.',\n },\n schema: [],\n },\n create(context: any) {\n let sawSessionCreate = false;\n const connectCalls: any[] = [];\n const tryStatements: any[] = [];\n\n return {\n AwaitExpression(node: any) {\n if (isSessionsCreateAwait(node)) sawSessionCreate = true;\n },\n TryStatement(node: any) {\n tryStatements.push(node);\n },\n CallExpression(node: any) {\n if (isConnectCall(node)) connectCalls.push(node);\n },\n 'Program:exit'() {\n if (!sawSessionCreate) return;\n for (const call of connectCalls) {\n const enclosingTry = tryStatements.find((t) => t.block && contains(t.block, call));\n const handled = !!enclosingTry?.handler && someDescendant(enclosingTry.handler, isReleaseCall);\n if (!handled) {\n context.report({ node: call, messageId: 'sessionNotReleasedOnFailure' });\n }\n }\n },\n };\n },\n};\n\nexport const browserbaseReleaseSessionOnConnectFailureRule = rule;\nexport default rule;\n","/**\n * browserbase-dont-stack-custom-retry-on-sdk-retry (reliability)\n *\n * The client already retries internally (default maxRetries: 2, retrying\n * 408/409/429/5xx with Retry-After-aware backoff) before ever raising an\n * exception. A hand-rolled retry loop around sessions.create() that doesn't\n * pass `{ maxRetries: 0 }` stacks two uncoordinated backoff schedules,\n * multiplying worst-case attempts and latency.\n */\nimport { findProperty, isSessionsCall } from '../utils.js';\n\nfunction isLoopNode(node: any): boolean {\n return node?.type === 'ForStatement' || node?.type === 'WhileStatement' || node?.type === 'DoWhileStatement';\n}\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'A custom retry loop around sessions.create must disable the SDK\\'s own retry',\n category: 'reliability',\n rationale:\n 'The Browserbase client already retries internally (default maxRetries: 2, retrying 408/409/429/5xx with Retry-After-aware exponential backoff) before ever raising an exception back to the caller. A hand-rolled retry loop around sessions.create() that does not pass { maxRetries: 0 } stacks two independent, uncoordinated backoff schedules — a sustained 429 can trigger N outer attempts x (1 + 2 SDK-internal retries), multiplying worst-case latency well beyond what either layer alone would produce.',\n docsUrl: 'https://docs.browserbase.com/optimizations/concurrency/overview',\n recommended: true,\n },\n messages: {\n stackedRetry:\n 'sessions.create() is called inside a custom retry loop with no { maxRetries: 0 } override — the SDK retries this call internally too, stacking two backoff schedules.',\n },\n schema: [],\n },\n create(context: any) {\n const loopRanges: any[] = [];\n\n return {\n ForStatement(node: any) {\n loopRanges.push(node);\n },\n WhileStatement(node: any) {\n loopRanges.push(node);\n },\n DoWhileStatement(node: any) {\n loopRanges.push(node);\n },\n CallExpression(node: any) {\n if (!isSessionsCall(node, 'create')) return;\n const insideLoop = loopRanges.some((loop) => {\n const start = loop.range?.[0] ?? loop.start;\n const end = loop.range?.[1] ?? loop.end;\n const pos = node.range?.[0] ?? node.start;\n return pos >= start && pos <= end;\n });\n if (!insideLoop) return;\n\n const optsArg = node.arguments?.[1];\n const hasMaxRetries = optsArg?.type === 'ObjectExpression' && !!findProperty(optsArg, 'maxRetries');\n if (!hasMaxRetries) {\n context.report({ node, messageId: 'stackedRetry' });\n }\n },\n };\n },\n};\n\nexport const browserbaseDontStackCustomRetryOnSdkRetryRule = rule;\nexport default rule;\n","/**\n * browserbase-no-overbroad-error-substring-match (reliability)\n *\n * Matching a caught error's message against a single generic word like\n * \"session\" — the name of the resource being polled — is nearly guaranteed\n * to match on any unrelated transient error (connection reset, SSL error,\n * timeout) too. A single coincidental match shouldn't be treated the same\n * as a confirmed 404/410, especially when the action taken is destructive\n * (tearing down a healthy session).\n */\nimport { memberPropName, someDescendant } from '../utils.js';\n\nconst OVERBROAD_TERMS = new Set(['session', 'context', 'browser', 'browserbase']);\n\nfunction collectIncludesLiterals(test: any, literals: string[]): void {\n if (!test) return;\n if (test.type === 'LogicalExpression' && test.operator === '||') {\n collectIncludesLiterals(test.left, literals);\n collectIncludesLiterals(test.right, literals);\n return;\n }\n if (test.type === 'CallExpression' && memberPropName(test) === 'includes') {\n const arg = test.arguments?.[0];\n if (arg?.type === 'Literal' && typeof arg.value === 'string') literals.push(arg.value.toLowerCase());\n }\n}\n\nfunction isCleanupCall(node: any): boolean {\n if (node?.type !== 'CallExpression') return false;\n const callee = node.callee;\n const name = callee?.type === 'Identifier' ? callee.name : memberPropName(node);\n return !!name && /release|remove|cleanup|stop|teardown/i.test(name);\n}\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Error-message checks must not OR in a single generic resource-name substring',\n category: 'reliability',\n rationale:\n 'A condition like `err.includes(\"not found\") || err.includes(\"404\") || err.includes(\"session\")` looks like it is narrowing to a confirmed session-ended error, but the last clause matches a single generic word — the name of the resource being polled. Virtually any exception raised from a sessions.* call (a connection reset, an SSL error, a generic timeout that echoes the request URL) is likely to contain that substring too. A coincidental match then triggers the same destructive cleanup as a real 404/410, tearing down a healthy session on a transient blip.',\n docsUrl: 'https://docs.browserbase.com/reference/api/session-live-urls',\n recommended: true,\n },\n messages: {\n overbroadMatch:\n 'This OR-chain includes a generic substring check (\"{{term}}\") that matches almost any error from a sessions.* call, not just a confirmed session-ended response.',\n },\n schema: [],\n },\n create(context: any) {\n return {\n IfStatement(node: any) {\n const literals: string[] = [];\n collectIncludesLiterals(node.test, literals);\n if (literals.length < 2) return;\n\n const overbroad = literals.find((l) => OVERBROAD_TERMS.has(l));\n if (!overbroad) return;\n\n if (someDescendant(node.consequent, isCleanupCall)) {\n context.report({ node, messageId: 'overbroadMatch', data: { term: overbroad } });\n }\n },\n };\n },\n};\n\nexport const browserbaseNoOverbroadErrorSubstringMatchRule = rule;\nexport default rule;\n","/**\n * browserbase-use-sdk-not-raw-requests (integration)\n *\n * A raw fetch/axios/http call to an api.browserbase.com endpoint bypasses\n * the installed SDK's typed exceptions, retry/backoff, and consistent error\n * handling that every other call site in the same codebase gets for free.\n */\nconst BROWSERBASE_HOST = 'api.browserbase.com';\n\nfunction templateLiteralContainsHost(node: any): boolean {\n return (node.quasis ?? []).some((q: any) => {\n const text = q?.value?.cooked ?? q?.value?.raw ?? '';\n return typeof text === 'string' && text.includes(BROWSERBASE_HOST);\n });\n}\n\nfunction urlArgContainsHost(node: any): boolean {\n if (node?.type === 'Literal' && typeof node.value === 'string') return node.value.includes(BROWSERBASE_HOST);\n if (node?.type === 'TemplateLiteral') return templateLiteralContainsHost(node);\n return false;\n}\n\nfunction isRawHttpCall(node: any): { isCall: boolean; urlArg: any } {\n if (node?.type !== 'CallExpression') return { isCall: false, urlArg: undefined };\n const callee = node.callee;\n\n // fetch(url, ...)\n if (callee?.type === 'Identifier' && callee.name === 'fetch') {\n return { isCall: true, urlArg: node.arguments?.[0] };\n }\n\n if (callee?.type === 'MemberExpression' && !callee.computed && callee.property?.type === 'Identifier') {\n const objName = callee.object?.type === 'Identifier' ? callee.object.name : undefined;\n const methodName = callee.property.name;\n // axios.get(url, ...) / axios.post(url, ...) / http.get(url, ...) / https.get(url, ...)\n if (objName && /^(axios|http|https)$/i.test(objName) && /^(get|post|put|patch|delete|request)$/i.test(methodName)) {\n return { isCall: true, urlArg: node.arguments?.[0] };\n }\n }\n\n // axios(url, ...) or axios({ url, ... })\n if (callee?.type === 'Identifier' && callee.name === 'axios') {\n const arg = node.arguments?.[0];\n if (arg?.type === 'ObjectExpression') {\n const urlProp = arg.properties?.find(\n (p: any) => p?.type === 'Property' && p.key?.type === 'Identifier' && p.key.name === 'url',\n );\n return { isCall: true, urlArg: urlProp?.value };\n }\n return { isCall: true, urlArg: arg };\n }\n\n return { isCall: false, urlArg: undefined };\n}\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Use the installed Browserbase SDK instead of hand-rolled HTTP requests',\n category: 'integration',\n rationale:\n 'A raw fetch/axios/http call to an api.browserbase.com endpoint duplicates a method the installed SDK already exposes (e.g. sessions.recording.retrieve()), forfeiting its typed exceptions, built-in retry/backoff, and consistent error handling — and risks drifting on auth header naming or response shape as the API evolves.',\n docsUrl: 'https://docs.browserbase.com/reference/sdk/nodejs',\n recommended: true,\n },\n messages: {\n rawRequestToBrowserbase:\n 'This makes a raw HTTP request to a Browserbase API endpoint instead of using the installed SDK.',\n },\n schema: [],\n },\n create(context: any) {\n const urlVars = new Map<string, any>();\n\n return {\n VariableDeclarator(node: any) {\n if (node.id?.type === 'Identifier' && urlArgContainsHost(node.init)) {\n urlVars.set(node.id.name, node.init);\n }\n },\n CallExpression(node: any) {\n const { isCall, urlArg } = isRawHttpCall(node);\n if (!isCall || !urlArg) return;\n\n const resolved = urlArg.type === 'Identifier' ? urlVars.get(urlArg.name) ?? urlArg : urlArg;\n if (urlArgContainsHost(resolved)) {\n context.report({ node, messageId: 'rawRequestToBrowserbase' });\n }\n },\n };\n },\n};\n\nexport const browserbaseUseSdkNotRawRequestsRule = rule;\nexport default rule;\n","/**\n * browserbase-centralize-request-release (integration)\n *\n * `sessions.update(id, { status: \"REQUEST_RELEASE\" })` hand-rolled inline at\n * multiple call sites, each with slightly different error handling, drifts\n * over time and means an API change requires fixing N places instead of\n * one. Route it through a single designated provider/abstraction module.\n */\nimport { findProperty, isInsideTestFile, isSessionsCall } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Route REQUEST_RELEASE through a single shared abstraction',\n category: 'integration',\n rationale:\n 'sessions.update(id, { status: \"REQUEST_RELEASE\" }) hand-rolled inline at each call site, with each one carrying slightly different error handling, means an API change (a new required field, a renamed status value) requires fixing every call site instead of one — and the duplicated copies already drift in error-handling quality. Centralize behind one designated provider method (e.g. requestStop()/releaseSession()) and call that everywhere instead.',\n docsUrl: 'https://docs.browserbase.com/reference/api/update-a-session',\n recommended: true,\n },\n messages: {\n inlineRequestRelease:\n 'sessions.update(..., { status: \"REQUEST_RELEASE\" }) is hand-rolled inline here. Route this through a single shared release/provider abstraction instead.',\n },\n schema: [],\n },\n create(context: any) {\n const filename = String(context.filename ?? '');\n if (isInsideTestFile(filename) || /provider|browserbaseclient/i.test(filename)) {\n return {};\n }\n\n return {\n CallExpression(node: any) {\n if (!isSessionsCall(node, 'update')) return;\n const optsArg = node.arguments?.[1];\n const statusProp = findProperty(optsArg, 'status');\n const val = statusProp?.value;\n if (val?.type === 'Literal' && val.value === 'REQUEST_RELEASE') {\n context.report({ node, messageId: 'inlineRequestRelease' });\n }\n },\n };\n },\n};\n\nexport const browserbaseCentralizeRequestReleaseRule = rule;\nexport default rule;\n","/**\n * Flags a function that executes computer-use actions (click/type/goto/fill)\n * against the current page with no origin/domain allowlist check anywhere\n * in that function.\n */\nconst ACTION_METHOD_NAMES = new Set(['click', 'type', 'press', 'move', 'goto', 'fill', 'dblclick', 'dragAndDrop']);\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Computer-use action execution must check the page origin against an allowlist',\n category: 'security',\n cwe: 'CWE-284',\n owasp: 'A01:2021 – Broken Access Control',\n rationale:\n \"OpenAI's Computer Use guide instructs integrators to \\\"keep an allow list of domains and actions your agent should use, and block everything else.\\\" Without an origin check before executing actions, a click that follows an off-domain redirect (phishing link, ad, malicious iframe) is executed exactly like any in-domain click — and a field-fill action has no origin awareness either, so credentials could be typed into a page the agent was never meant to reach.\",\n docsUrl: 'https://developers.openai.com/api/docs/guides/tools-computer-use',\n recommended: true,\n },\n messages: {\n noOriginCheck:\n 'This function executes computer-use actions on the current page with no origin/domain allowlist check anywhere in it.',\n },\n },\n create(context: any) {\n type FnState = { sawAction: boolean; actionNode: any; sawOriginCheck: boolean };\n const stack: any[] = [];\n const states = new Map<any, FnState>();\n\n function ensureState(fn: any): FnState {\n let s = states.get(fn);\n if (!s) {\n s = { sawAction: false, actionNode: null, sawOriginCheck: false };\n states.set(fn, s);\n }\n return s;\n }\n\n function top(): any {\n return stack[stack.length - 1];\n }\n\n function pushScope(node: any) {\n stack.push(node);\n ensureState(node);\n }\n\n function popScope() {\n stack.pop();\n }\n\n function propName(node: any): string | undefined {\n if (!node) return undefined;\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'Literal' && typeof node.value === 'string') return node.value;\n return undefined;\n }\n\n function memberChainNames(node: any, names: string[] = []): string[] {\n if (node?.type === 'MemberExpression') {\n memberChainNames(node.object, names);\n const n = propName(node.property);\n if (n) names.push(n);\n } else if (node?.type === 'Identifier') {\n names.push(node.name);\n }\n return names;\n }\n\n function isPageActionCall(node: any): boolean {\n if (node?.type !== 'CallExpression') return false;\n if (node.callee?.type !== 'MemberExpression') return false;\n const chain = memberChainNames(node.callee);\n if (chain.length === 0) return false;\n const last = chain[chain.length - 1];\n if (!ACTION_METHOD_NAMES.has(last)) return false;\n return chain.some((n) => /^page$/i.test(n) || /page$/i.test(n));\n }\n\n function markOriginCheckSeen() {\n const fn = top();\n if (fn) ensureState(fn).sawOriginCheck = true;\n }\n\n return {\n Program(node: any) {\n pushScope(node);\n },\n 'Program:exit'() {\n for (const state of states.values()) {\n if (state.sawAction && !state.sawOriginCheck) {\n context.report({ node: state.actionNode, messageId: 'noOriginCheck' });\n }\n }\n },\n\n FunctionDeclaration(node: any) {\n pushScope(node);\n },\n 'FunctionDeclaration:exit'() {\n popScope();\n },\n FunctionExpression(node: any) {\n pushScope(node);\n },\n 'FunctionExpression:exit'() {\n popScope();\n },\n ArrowFunctionExpression(node: any) {\n pushScope(node);\n },\n 'ArrowFunctionExpression:exit'() {\n popScope();\n },\n\n CallExpression(node: any) {\n if (isPageActionCall(node)) {\n const fn = top();\n if (fn) {\n const state = ensureState(fn);\n if (!state.sawAction) {\n state.sawAction = true;\n state.actionNode = node;\n }\n }\n }\n },\n\n NewExpression(node: any) {\n if (node.callee?.type === 'Identifier' && node.callee.name === 'URL') {\n markOriginCheckSeen();\n }\n },\n\n MemberExpression(node: any) {\n const name = propName(node.property);\n if (name === 'hostname' || name === 'origin') {\n markOriginCheckSeen();\n }\n },\n\n Identifier(node: any) {\n if (/allow.?list/i.test(node.name) || /allowed.?domain/i.test(node.name)) {\n markOriginCheckSeen();\n }\n },\n };\n },\n};\n\nexport const openaiCuaNoDomainAllowlistRule = rule;\n","/**\n * Flags a missing vertical scroll delta (dy/deltaY/scrollY) being defaulted\n * to a non-zero literal instead of 0 — OpenAI's own reference scroll\n * handler defaults both axes to 0 when the model omits one.\n */\nconst VERTICAL_DELTA_NAME_PATTERN = /^(dy|delta_?y|scroll_?y)$/i;\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'A missing vertical scroll delta must default to 0, not an arbitrary non-zero value',\n category: 'correctness',\n rationale:\n \"The reference scroll handler in OpenAI's Computer Use guide defaults a missing scroll delta to 0 on both axes. Defaulting the vertical delta to any other value injects an unintended scroll the model never asked for whenever it omits that field, desyncing the model's mental model of the page from the page's actual state on the next turn.\",\n docsUrl: 'https://developers.openai.com/api/docs/guides/tools-computer-use',\n recommended: true,\n },\n messages: {\n nonZeroDefault:\n 'A missing vertical scroll delta defaults to {{value}} here instead of 0, injecting an unintended scroll the model never requested.',\n },\n },\n create(context: any) {\n function propName(node: any): string | undefined {\n if (!node) return undefined;\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'Literal' && typeof node.value === 'string') return node.value;\n return undefined;\n }\n\n function targetName(node: any): string | undefined {\n if (node?.type === 'Identifier') return node.name;\n if (node?.type === 'MemberExpression') return propName(node.property);\n return undefined;\n }\n\n function isNonZeroNumberLiteral(node: any): boolean {\n return node?.type === 'Literal' && typeof node.value === 'number' && node.value !== 0;\n }\n\n function reportIfBadDefault(targetNode: any, valueNode: any, reportNode: any) {\n const name = targetName(targetNode);\n if (!name || !VERTICAL_DELTA_NAME_PATTERN.test(name)) return;\n if (!isNonZeroNumberLiteral(valueNode)) return;\n context.report({ node: reportNode, messageId: 'nonZeroDefault', data: { value: String(valueNode.value) } });\n }\n\n function findDirectAssignment(stmt: any): { target: any; value: any } | undefined {\n let inner = stmt;\n if (inner?.type === 'BlockStatement') {\n const exprStmts = (inner.body ?? []).filter((s: any) => s.type === 'ExpressionStatement');\n if (exprStmts.length !== 1) return undefined;\n inner = exprStmts[0];\n }\n if (inner?.type !== 'ExpressionStatement') return undefined;\n const expr = inner.expression;\n if (expr?.type !== 'AssignmentExpression' || expr.operator !== '=') return undefined;\n return { target: expr.left, value: expr.right };\n }\n\n function undefinedCheckTargetName(test: any): string | undefined {\n if (test?.type !== 'BinaryExpression') return undefined;\n if (test.operator !== '===' && test.operator !== '==') return undefined;\n const sides = [test.left, test.right];\n const undefinedSide = sides.find(\n (s) =>\n (s?.type === 'Identifier' && s.name === 'undefined') ||\n (s?.type === 'Literal' && s.value === null) ||\n (s?.type === 'UnaryExpression' && s.operator === 'typeof'),\n );\n const otherSide = sides.find((s) => s !== undefinedSide);\n if (!undefinedSide || !otherSide) return undefined;\n if (undefinedSide.type === 'UnaryExpression') {\n return targetName(undefinedSide.argument);\n }\n return targetName(otherSide);\n }\n\n return {\n LogicalExpression(node: any) {\n if (node.operator !== '??') return;\n reportIfBadDefault(node.left, node.right, node);\n },\n\n IfStatement(node: any) {\n const name = undefinedCheckTargetName(node.test);\n if (!name) return;\n const assignment = findDirectAssignment(node.consequent);\n if (!assignment) return;\n reportIfBadDefault(assignment.target, assignment.value, node);\n },\n };\n },\n};\n\nexport const openaiCuaScrollDeltaDefaultZeroRule = rule;\n","/**\n * Flags a function that both (a) searches free text for a brace via\n * indexOf/lastIndexOf, and (b) calls JSON.parse on a slice/substring of\n * that text — manual brace-hunting JSON extraction instead of the\n * Responses API's structured tool/function output.\n */\nconst BRACE_SEARCH_METHODS = new Set(['indexOf', 'lastIndexOf']);\nconst SLICE_METHODS = new Set(['slice', 'substring', 'substr']);\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Step metadata must come from structured tool output, not brace-hunting in free text',\n category: 'correctness',\n rationale:\n 'Manually locating a JSON object inside a free-text model message (via indexOf/lastIndexOf plus a slice) is fragile by construction: it breaks if the model adds trailing commentary, wraps the JSON in a markdown fence, or reorders fields. The Responses API supports function tools and structured output specifically so required metadata is schema-validated by the API instead of regex/brace-scraped out of arbitrary text.',\n docsUrl: 'https://developers.openai.com/api/docs/guides/tools-computer-use',\n recommended: true,\n },\n messages: {\n textJsonExtraction:\n 'This function locates a JSON object in free text via indexOf/lastIndexOf and parses a slice of it — use a function tool or structured output instead of brace-hunting in the model\\'s text message.',\n },\n },\n create(context: any) {\n type FnState = { sawBraceSearch: boolean; sawJsonParseOnSlice: boolean; reportNode: any };\n const stack: any[] = [];\n const states = new Map<any, FnState>();\n\n function ensureState(fn: any): FnState {\n let s = states.get(fn);\n if (!s) {\n s = { sawBraceSearch: false, sawJsonParseOnSlice: false, reportNode: null };\n states.set(fn, s);\n }\n return s;\n }\n\n function top(): any {\n return stack[stack.length - 1];\n }\n\n function pushScope(node: any) {\n stack.push(node);\n ensureState(node);\n }\n\n function popScope() {\n stack.pop();\n }\n\n function isBraceSearchCall(node: any): boolean {\n if (node?.type !== 'CallExpression') return false;\n const callee = node.callee;\n if (callee?.type !== 'MemberExpression') return false;\n if (!BRACE_SEARCH_METHODS.has(callee.property?.name)) return false;\n const arg = node.arguments?.[0];\n return arg?.type === 'Literal' && typeof arg.value === 'string' && arg.value.includes('{');\n }\n\n function isJsonParseOnSliceCall(node: any): boolean {\n if (node?.type !== 'CallExpression') return false;\n const callee = node.callee;\n if (callee?.type !== 'MemberExpression') return false;\n if (callee.object?.type !== 'Identifier' || callee.object.name !== 'JSON') return false;\n if (callee.property?.name !== 'parse') return false;\n const arg = node.arguments?.[0];\n if (arg?.type !== 'CallExpression') return false;\n const argCallee = arg.callee;\n return argCallee?.type === 'MemberExpression' && SLICE_METHODS.has(argCallee.property?.name);\n }\n\n return {\n Program(node: any) {\n pushScope(node);\n },\n 'Program:exit'() {\n for (const state of states.values()) {\n if (state.sawBraceSearch && state.sawJsonParseOnSlice) {\n context.report({ node: state.reportNode, messageId: 'textJsonExtraction' });\n }\n }\n },\n\n FunctionDeclaration(node: any) {\n pushScope(node);\n },\n 'FunctionDeclaration:exit'() {\n popScope();\n },\n FunctionExpression(node: any) {\n pushScope(node);\n },\n 'FunctionExpression:exit'() {\n popScope();\n },\n ArrowFunctionExpression(node: any) {\n pushScope(node);\n },\n 'ArrowFunctionExpression:exit'() {\n popScope();\n },\n\n CallExpression(node: any) {\n const fn = top();\n if (!fn) return;\n const state = ensureState(fn);\n\n if (isBraceSearchCall(node)) {\n state.sawBraceSearch = true;\n if (!state.reportNode) state.reportNode = node;\n }\n if (isJsonParseOnSliceCall(node)) {\n state.sawJsonParseOnSlice = true;\n if (!state.reportNode) state.reportNode = node;\n }\n },\n };\n },\n};\n\nexport const openaiCuaStructuredStepMetadataNotTextJsonRule = rule;\n","/**\n * Flags a `.filter()` over a safety-checks array whose callback never\n * references `.code` or `.message` — i.e. it acknowledges every check\n * present instead of evaluating each one against a policy.\n */\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Acknowledging pending safety checks must evaluate each check, not blanket-pass them',\n category: 'correctness',\n rationale:\n '`acknowledged_safety_checks` exists specifically so a developer can selectively confirm checks they have actually reviewed — each entry carries an id/code/message. A filter that only checks the row\\'s shape (e.g. that it is an object) and never inspects `.code` or `.message` acknowledges every check present, defeating the purpose of the field entirely.',\n docsUrl: 'https://developers.openai.com/api/docs/guides/tools-computer-use',\n recommended: true,\n },\n messages: {\n blindAck:\n 'This filter never inspects .code or .message on each safety check — it acknowledges every check present instead of evaluating it against a policy.',\n },\n },\n create(context: any) {\n function propName(node: any): string | undefined {\n if (!node) return undefined;\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'Literal' && typeof node.value === 'string') return node.value;\n return undefined;\n }\n\n function sourceLooksLikeSafetyChecks(node: any): boolean {\n if (!node) return false;\n const name = propName(node) ?? (node.type === 'MemberExpression' ? propName(node.property) : undefined);\n if (name && /safety.?check/i.test(name)) return true;\n if (node.type === 'LogicalExpression') {\n return sourceLooksLikeSafetyChecks(node.left) || sourceLooksLikeSafetyChecks(node.right);\n }\n if (node.type === 'MemberExpression') {\n return sourceLooksLikeSafetyChecks(node.object) || sourceLooksLikeSafetyChecks(node.property);\n }\n return false;\n }\n\n function referencesCodeOrMessage(node: any, depth = 0): boolean {\n if (!node || typeof node !== 'object' || depth > 10) return false;\n if (Array.isArray(node)) return node.some((n) => referencesCodeOrMessage(n, depth + 1));\n if (node.type === 'MemberExpression') {\n const name = propName(node.property);\n if (name === 'code' || name === 'message') return true;\n }\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = (node as any)[key];\n if (val && typeof val === 'object') {\n if (referencesCodeOrMessage(val, depth + 1)) return true;\n }\n }\n return false;\n }\n\n return {\n CallExpression(node: any) {\n const callee = node.callee;\n if (callee?.type !== 'MemberExpression' || callee.property?.name !== 'filter') return;\n if (!sourceLooksLikeSafetyChecks(callee.object)) return;\n\n const fn = node.arguments?.[0];\n if (fn?.type !== 'ArrowFunctionExpression' && fn?.type !== 'FunctionExpression') return;\n\n if (!referencesCodeOrMessage(fn.body)) {\n context.report({ node, messageId: 'blindAck' });\n }\n },\n };\n },\n};\n\nexport const openaiCuaNoBlindSafetyCheckAckRule = rule;\n","/** Shared AST helpers for OpenAI Computer Use rules. */\n\nfunction propName(node: any): string | undefined {\n if (!node) return undefined;\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'Literal' && typeof node.value === 'string') return node.value;\n return undefined;\n}\n\nfunction memberChainNames(node: any, names: string[] = []): string[] {\n if (node?.type === 'MemberExpression') {\n memberChainNames(node.object, names);\n const n = propName(node.property);\n if (n) names.push(n);\n } else if (node?.type === 'Identifier') {\n names.push(node.name);\n }\n return names;\n}\n\n/** True for a CallExpression like `client.responses.create(...)` / `openai.responses.create(...)`. */\nexport function isResponsesCreateCall(node: any): boolean {\n if (node?.type !== 'CallExpression' || node.callee?.type !== 'MemberExpression') return false;\n const chain = memberChainNames(node.callee);\n return chain.length >= 2 && chain[chain.length - 1] === 'create' && chain[chain.length - 2] === 'responses';\n}\n\n/** Bounded recursive search for the first `responses.create(...)` call within a subtree. */\nexport function findResponsesCreateCall(node: any, depth = 0): any {\n if (!node || typeof node !== 'object' || depth > 12) return null;\n if (Array.isArray(node)) {\n for (const n of node) {\n const found = findResponsesCreateCall(n, depth + 1);\n if (found) return found;\n }\n return null;\n }\n if (isResponsesCreateCall(node)) return node;\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = (node as any)[key];\n if (val && typeof val === 'object') {\n const found = findResponsesCreateCall(val, depth + 1);\n if (found) return found;\n }\n }\n return null;\n}\n","/**\n * Flags a `responses.create()` call inside a try/catch with no retry —\n * neither a surrounding loop nor a retry call in the catch block — so any\n * exception that survives the SDK's own internal retries ends the entire run.\n */\nimport { findResponsesCreateCall } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'A responses.create() call must be retried at the turn level on transient errors',\n category: 'reliability',\n rationale:\n \"The SDK's own internal retry budget (DEFAULT_MAX_RETRIES) is finite. Treating any exception that survives it as fatal for the whole run — instead of retrying that one turn with backoff — means a single transient RateLimitError/APIConnectionError/InternalServerError can discard a long-running, multi-turn, expensive agent loop that may have already executed dozens of prior turns.\",\n docsUrl: 'https://developers.openai.com/api/docs/guides/tools-computer-use',\n recommended: true,\n },\n messages: {\n noTurnRetry:\n 'This responses.create() call has no turn-level retry — neither a surrounding loop nor a retry call in the catch block — so any error beyond the SDK\\'s own retry budget ends the entire run.',\n },\n },\n create(context: any) {\n let loopDepth = 0;\n\n function propName(node: any): string | undefined {\n if (!node) return undefined;\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'Literal' && typeof node.value === 'string') return node.value;\n return undefined;\n }\n\n function catchHasRetryCall(node: any, depth = 0): boolean {\n if (!node || typeof node !== 'object' || depth > 12) return false;\n if (Array.isArray(node)) return node.some((n) => catchHasRetryCall(n, depth + 1));\n if (node.type === 'CallExpression') {\n const callee = node.callee;\n const name =\n callee?.type === 'Identifier'\n ? callee.name\n : callee?.type === 'MemberExpression'\n ? propName(callee.property)\n : undefined;\n if (name && /retry/i.test(name)) return true;\n }\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = (node as any)[key];\n if (val && typeof val === 'object') {\n if (catchHasRetryCall(val, depth + 1)) return true;\n }\n }\n return false;\n }\n\n return {\n ForStatement() {\n loopDepth += 1;\n },\n 'ForStatement:exit'() {\n loopDepth -= 1;\n },\n WhileStatement() {\n loopDepth += 1;\n },\n 'WhileStatement:exit'() {\n loopDepth -= 1;\n },\n DoWhileStatement() {\n loopDepth += 1;\n },\n 'DoWhileStatement:exit'() {\n loopDepth -= 1;\n },\n ForOfStatement() {\n loopDepth += 1;\n },\n 'ForOfStatement:exit'() {\n loopDepth -= 1;\n },\n ForInStatement() {\n loopDepth += 1;\n },\n 'ForInStatement:exit'() {\n loopDepth -= 1;\n },\n\n TryStatement(node: any) {\n const createCall = findResponsesCreateCall(node.block);\n if (!createCall) return;\n if (loopDepth > 0) return;\n\n const handler = node.handler;\n if (!handler) return;\n if (catchHasRetryCall(handler.body)) return;\n\n context.report({ node: handler, messageId: 'noTurnRetry' });\n },\n };\n },\n};\n\nexport const openaiCuaRetryTransientTurnErrorsRule = rule;\n","/**\n * Flags a function that calls responses.create() and treats \"no tool calls\n * in the output\" as a successful completion, without ever checking\n * response.status === 'incomplete' anywhere in that function — a\n * token-budget truncation can produce the same shape and be silently\n * misreported as a voluntary, successful finish.\n */\nimport { findResponsesCreateCall } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'A completion check must rule out response.status === \"incomplete\" before reporting success',\n category: 'reliability',\n rationale:\n 'The Responses API can return status \"incomplete\" with zero visible message output when generation is cut off by the token budget — the same shape (\"no computer_call, no message\") a purely structural completion check treats as \"the model voluntarily finished.\" Without checking response.status, a token-budget truncation can be silently reported as a successful task completion.',\n docsUrl: 'https://developers.openai.com/api/docs/guides/tools-computer-use',\n recommended: true,\n },\n messages: {\n missingIncompleteCheck:\n 'This treats the absence of tool calls as a successful completion, but never checks response.status === \"incomplete\" — a token-budget truncation can be misreported as success.',\n },\n },\n create(context: any) {\n type FnState = { sawCreateCall: boolean; sawSuccessReturn: boolean; successNode: any; sawStatusCheck: boolean };\n const stack: any[] = [];\n const states = new Map<any, FnState>();\n\n function ensureState(fn: any): FnState {\n let s = states.get(fn);\n if (!s) {\n s = { sawCreateCall: false, sawSuccessReturn: false, successNode: null, sawStatusCheck: false };\n states.set(fn, s);\n }\n return s;\n }\n\n function top(): any {\n return stack[stack.length - 1];\n }\n\n function pushScope(node: any) {\n stack.push(node);\n ensureState(node);\n }\n\n function popScope() {\n stack.pop();\n }\n\n function propName(node: any): string | undefined {\n if (!node) return undefined;\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'Literal' && typeof node.value === 'string') return node.value;\n return undefined;\n }\n\n function isSuccessObjectLiteral(node: any): boolean {\n if (node?.type !== 'ObjectExpression') return false;\n return (node.properties ?? []).some((p: any) => {\n if (p?.type !== 'Property') return false;\n const keyName = propName(p.key);\n return (\n (keyName === 'success' || keyName === 'completed') &&\n p.value?.type === 'Literal' &&\n p.value.value === true\n );\n });\n }\n\n return {\n Program(node: any) {\n pushScope(node);\n },\n 'Program:exit'() {\n for (const state of states.values()) {\n if (state.sawCreateCall && state.sawSuccessReturn && !state.sawStatusCheck) {\n context.report({ node: state.successNode, messageId: 'missingIncompleteCheck' });\n }\n }\n },\n\n FunctionDeclaration(node: any) {\n pushScope(node);\n },\n 'FunctionDeclaration:exit'() {\n popScope();\n },\n FunctionExpression(node: any) {\n pushScope(node);\n },\n 'FunctionExpression:exit'() {\n popScope();\n },\n ArrowFunctionExpression(node: any) {\n pushScope(node);\n },\n 'ArrowFunctionExpression:exit'() {\n popScope();\n },\n\n CallExpression(node: any) {\n if (findResponsesCreateCall(node)) {\n const fn = top();\n if (fn) ensureState(fn).sawCreateCall = true;\n }\n },\n\n ObjectExpression(node: any) {\n if (isSuccessObjectLiteral(node)) {\n const fn = top();\n if (fn) {\n const state = ensureState(fn);\n if (!state.sawSuccessReturn) {\n state.sawSuccessReturn = true;\n state.successNode = node;\n }\n }\n }\n },\n\n BinaryExpression(node: any) {\n if (node.operator !== '===' && node.operator !== '==') return;\n const sides = [node.left, node.right];\n const statusSide = sides.find((s) => s?.type === 'MemberExpression' && propName(s.property) === 'status');\n const valueSide = sides.find((s) => s !== statusSide);\n if (statusSide && valueSide?.type === 'Literal' && valueSide.value === 'incomplete') {\n const fn = top();\n if (fn) ensureState(fn).sawStatusCheck = true;\n }\n },\n };\n },\n};\n\nexport const openaiCuaCheckResponseStatusIncompleteRule = rule;\n","/**\n * Flags a `responses.create()` call with no `safety_identifier` (or the\n * older `user`) parameter — without one, OpenAI attributes policy\n * violations to the whole shared API key rather than a single end user.\n */\nimport { isResponsesCreateCall } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'responses.create() must set safety_identifier for per-end-user policy attribution',\n category: 'integration',\n rationale:\n 'OpenAI documents that a stable per-end-user safety_identifier lets policy violations be attributed and acted on per end user. Without one on a multi-tenant integration routing many customers through a single shared API key, a single customer triggering a high-confidence policy-violation heuristic can result in access being temporarily revoked for the entire organization, not just the offending identifier.',\n docsUrl: 'https://help.openai.com/en/articles/5428082-how-to-incorporate-a-safety-identifier',\n recommended: true,\n },\n messages: {\n missingSafetyIdentifier:\n 'This responses.create() call sets no safety_identifier (or user) — a policy violation here could be attributed to the entire shared API key instead of one end user.',\n },\n },\n create(context: any) {\n function propName(node: any): string | undefined {\n if (!node) return undefined;\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'Literal' && typeof node.value === 'string') return node.value;\n return undefined;\n }\n\n return {\n CallExpression(node: any) {\n if (!isResponsesCreateCall(node)) return;\n\n const optionsArg = node.arguments?.[0];\n if (optionsArg?.type !== 'ObjectExpression') return;\n\n const hasIdentifier = (optionsArg.properties ?? []).some((p: any) => {\n if (p?.type !== 'Property') return false;\n const keyName = propName(p.key);\n return keyName === 'safety_identifier' || keyName === 'user';\n });\n\n if (!hasIdentifier) {\n context.report({ node, messageId: 'missingSafetyIdentifier' });\n }\n },\n };\n },\n};\n\nexport const openaiCuaSetSafetyIdentifierRule = rule;\n","/**\n * Oxlint JS plugin entrypoint. Rules are AST-based; no string matching.\n */\nimport { PLUGIN_NAME } from '../constants.js';\nimport { resendWebhookSignatureRule } from '../providers/resend/rules/webhook-signature.js';\nimport { resendApiKeyHardcodedRule } from '../providers/resend/rules/api-key-hardcoded.js';\nimport { resendApiKeyInClientBundleRule } from '../providers/resend/rules/api-key-in-client-bundle.js';\nimport { resendMarketingViaBatchSendRule } from '../providers/resend/rules/marketing-via-batch-send.js';\nimport { resendMarketingMissingUnsubscribeRule } from '../providers/resend/rules/marketing-missing-unsubscribe.js';\nimport { resendTestDomainInProductionPathRule } from '../providers/resend/rules/test-domain-in-production-path.js';\nimport { resendFromAddressNotFriendlyFormatRule } from '../providers/resend/rules/from-address-not-friendly-format.js';\nimport { resendBatchSizeNotEnforcedRule } from '../providers/resend/rules/batch-size-not-enforced.js';\nimport { resendMissingIdempotencyKeyRule } from '../providers/resend/rules/missing-idempotency-key.js';\nimport { resendNoErrorCodeMappingRule } from '../providers/resend/rules/no-error-code-mapping.js';\nimport { resendWebhookNoIdempotencyRule } from '../providers/resend/rules/webhook-no-idempotency.js';\nimport { resendMissingTagsRule } from '../providers/resend/rules/missing-tags.js';\nimport { resendRequestIdNotLoggedRule } from '../providers/resend/rules/request-id-not-logged.js';\nimport { supabaseScopeQueriesByTenantColumnRule } from '../providers/supabase/rules/scope-queries-by-tenant-column.js';\nimport { supabaseValidateUuidColumnsRule } from '../providers/supabase/rules/validate-uuid-columns.js';\nimport { supabaseOrderByTimestampNotIdentityRule } from '../providers/supabase/rules/order-by-timestamp-not-identity.js';\nimport { supabaseConsistentInputLengthLimitsRule } from '../providers/supabase/rules/consistent-input-length-limits.js';\nimport { supabaseIdempotentMutationsRule } from '../providers/supabase/rules/idempotent-mutations.js';\nimport { supabaseFailFastEnvValidationRule } from '../providers/supabase/rules/fail-fast-env-validation.js';\nimport { supabaseNoUserMetadataAuthzRule } from '../providers/supabase/rules/no-user-metadata-authz.js';\nimport { supabaseSingleWithoutErrorCheckRule } from '../providers/supabase/rules/single-without-error-check.js';\nimport { supabaseNonAtomicReplacePatternRule } from '../providers/supabase/rules/non-atomic-replace-pattern.js';\nimport { supabaseUncheckedMutationErrorRule } from '../providers/supabase/rules/unchecked-mutation-error.js';\nimport { supabaseRealtimeMissingFilterRule } from '../providers/supabase/rules/realtime-missing-filter.js';\nimport { supabaseStorageErrorNotSurfacedRule } from '../providers/supabase/rules/storage-error-not-surfaced.js';\nimport { auth0RequiredAudienceValidationRule } from '../providers/auth0/rules/required-audience-validation.js';\nimport { auth0NoAccountLinkWithoutVerifiedEmailRule } from '../providers/auth0/rules/no-account-link-without-verified-email.js';\nimport { auth0DeadClaimVerificationCheckRule } from '../providers/auth0/rules/dead-claim-verification-check.js';\nimport { auth0JwksRefreshOnUnknownKidRule } from '../providers/auth0/rules/jwks-refresh-on-unknown-kid.js';\nimport { firebaseMissingAppCheckRule } from '../providers/firebase/rules/missing-app-check.js';\nimport { firebaseUnhandledAuthPopupRejectionRule } from '../providers/firebase/rules/unhandled-auth-popup-rejection.js';\nimport { firebaseRtdbListReadForSingleItemRule } from '../providers/firebase/rules/rtdb-list-read-for-single-item.js';\nimport { firebaseUnvalidatedExternalDataToRtdbRule } from '../providers/firebase/rules/unvalidated-external-data-to-rtdb.js';\nimport { firebaseRtdbBatchWriteNotAtomicRule } from '../providers/firebase/rules/rtdb-batch-write-not-atomic.js';\nimport { firebaseRtdbListenerErrorNotHandledRule } from '../providers/firebase/rules/rtdb-listener-error-not-handled.js';\nimport { firebaseEffectDepsWholeUserObjectRule } from '../providers/firebase/rules/effect-deps-whole-user-object.js';\nimport { firebaseRtdbWritePromiseNotHandledRule } from '../providers/firebase/rules/rtdb-write-promise-not-handled.js';\nimport { lovableNoClientSideSecretFetchRule } from '../providers/lovable/rules/no-client-side-secret-fetch.js';\nimport { lovablePaidFlagWithoutEdgeFunctionRule } from '../providers/lovable/rules/paid-flag-without-edge-function.js';\nimport { lovableExpiryColumnNeverCheckedRule } from '../providers/lovable/rules/expiry-column-never-checked.js';\nimport { lovableSilentCatchOnProviderCallRule } from '../providers/lovable/rules/silent-catch-on-provider-call.js';\nimport { browserbaseNoConditionalAuthzOnAnonymousUserRule } from '../providers/browserbase/rules/no-conditional-authz-on-anonymous-user.js';\nimport { browserbaseNoConnectUrlInApiResponseRule } from '../providers/browserbase/rules/no-connect-url-in-api-response.js';\nimport { browserbaseSessionIdRequiresOwnershipCheckRule } from '../providers/browserbase/rules/session-id-requires-ownership-check.js';\nimport { browserbaseNoConcurrentSharedContextRule } from '../providers/browserbase/rules/no-concurrent-shared-context.js';\nimport { browserbaseMobileDeviceRequiresOsSettingRule } from '../providers/browserbase/rules/mobile-device-requires-os-setting.js';\nimport { browserbaseUseTypedExceptionStatusNotSubstringRule } from '../providers/browserbase/rules/use-typed-exception-status-not-substring.js';\nimport { browserbaseReleaseSessionOnConnectFailureRule } from '../providers/browserbase/rules/release-session-on-connect-failure.js';\nimport { browserbaseDontStackCustomRetryOnSdkRetryRule } from '../providers/browserbase/rules/dont-stack-custom-retry-on-sdk-retry.js';\nimport { browserbaseNoOverbroadErrorSubstringMatchRule } from '../providers/browserbase/rules/no-overbroad-error-substring-match.js';\nimport { browserbaseUseSdkNotRawRequestsRule } from '../providers/browserbase/rules/use-sdk-not-raw-requests.js';\nimport { browserbaseCentralizeRequestReleaseRule } from '../providers/browserbase/rules/centralize-request-release.js';\nimport { openaiCuaNoDomainAllowlistRule } from '../providers/openai-cua/rules/no-domain-allowlist.js';\nimport { openaiCuaScrollDeltaDefaultZeroRule } from '../providers/openai-cua/rules/scroll-delta-default-zero.js';\nimport { openaiCuaStructuredStepMetadataNotTextJsonRule } from '../providers/openai-cua/rules/structured-step-metadata-not-text-json.js';\nimport { openaiCuaNoBlindSafetyCheckAckRule } from '../providers/openai-cua/rules/no-blind-safety-check-ack.js';\nimport { openaiCuaRetryTransientTurnErrorsRule } from '../providers/openai-cua/rules/retry-transient-turn-errors.js';\nimport { openaiCuaCheckResponseStatusIncompleteRule } from '../providers/openai-cua/rules/check-response-status-incomplete.js';\nimport { openaiCuaSetSafetyIdentifierRule } from '../providers/openai-cua/rules/set-safety-identifier.js';\n\nconst plugin = {\n meta: { name: PLUGIN_NAME, version: '0.0.1' },\n rules: {\n 'resend-webhook-signature': resendWebhookSignatureRule,\n 'resend-api-key-hardcoded': resendApiKeyHardcodedRule,\n 'resend-api-key-in-client-bundle': resendApiKeyInClientBundleRule,\n 'resend-marketing-via-batch-send': resendMarketingViaBatchSendRule,\n 'resend-marketing-missing-unsubscribe': resendMarketingMissingUnsubscribeRule,\n 'resend-test-domain-in-production-path': resendTestDomainInProductionPathRule,\n 'resend-from-address-not-friendly-format': resendFromAddressNotFriendlyFormatRule,\n 'resend-batch-size-not-enforced': resendBatchSizeNotEnforcedRule,\n 'resend-missing-idempotency-key': resendMissingIdempotencyKeyRule,\n 'resend-no-error-code-mapping': resendNoErrorCodeMappingRule,\n 'resend-webhook-no-idempotency': resendWebhookNoIdempotencyRule,\n 'resend-missing-tags': resendMissingTagsRule,\n 'resend-request-id-not-logged': resendRequestIdNotLoggedRule,\n 'supabase-scope-queries-by-tenant-column': supabaseScopeQueriesByTenantColumnRule,\n 'supabase-validate-uuid-columns': supabaseValidateUuidColumnsRule,\n 'supabase-order-by-timestamp-not-identity': supabaseOrderByTimestampNotIdentityRule,\n 'supabase-consistent-input-length-limits': supabaseConsistentInputLengthLimitsRule,\n 'supabase-idempotent-mutations': supabaseIdempotentMutationsRule,\n 'supabase-fail-fast-env-validation': supabaseFailFastEnvValidationRule,\n 'supabase-no-user-metadata-authz': supabaseNoUserMetadataAuthzRule,\n 'supabase-single-without-error-check': supabaseSingleWithoutErrorCheckRule,\n 'supabase-non-atomic-replace-pattern': supabaseNonAtomicReplacePatternRule,\n 'supabase-unchecked-mutation-error': supabaseUncheckedMutationErrorRule,\n 'supabase-realtime-missing-filter': supabaseRealtimeMissingFilterRule,\n 'supabase-storage-error-not-surfaced': supabaseStorageErrorNotSurfacedRule,\n 'auth0-required-audience-validation': auth0RequiredAudienceValidationRule,\n 'auth0-no-account-link-without-verified-email': auth0NoAccountLinkWithoutVerifiedEmailRule,\n 'auth0-dead-claim-verification-check': auth0DeadClaimVerificationCheckRule,\n 'auth0-jwks-refresh-on-unknown-kid': auth0JwksRefreshOnUnknownKidRule,\n 'firebase-missing-app-check': firebaseMissingAppCheckRule,\n 'firebase-unhandled-auth-popup-rejection': firebaseUnhandledAuthPopupRejectionRule,\n 'firebase-rtdb-list-read-for-single-item': firebaseRtdbListReadForSingleItemRule,\n 'firebase-unvalidated-external-data-to-rtdb': firebaseUnvalidatedExternalDataToRtdbRule,\n 'firebase-rtdb-batch-write-not-atomic': firebaseRtdbBatchWriteNotAtomicRule,\n 'firebase-rtdb-listener-error-not-handled': firebaseRtdbListenerErrorNotHandledRule,\n 'firebase-effect-deps-whole-user-object': firebaseEffectDepsWholeUserObjectRule,\n 'firebase-rtdb-write-promise-not-handled': firebaseRtdbWritePromiseNotHandledRule,\n 'lovable-no-client-side-secret-fetch': lovableNoClientSideSecretFetchRule,\n 'lovable-paid-flag-without-edge-function': lovablePaidFlagWithoutEdgeFunctionRule,\n 'lovable-expiry-column-never-checked': lovableExpiryColumnNeverCheckedRule,\n 'lovable-silent-catch-on-provider-call': lovableSilentCatchOnProviderCallRule,\n 'browserbase-no-conditional-authz-on-anonymous-user': browserbaseNoConditionalAuthzOnAnonymousUserRule,\n 'browserbase-no-connect-url-in-api-response': browserbaseNoConnectUrlInApiResponseRule,\n 'browserbase-session-id-requires-ownership-check': browserbaseSessionIdRequiresOwnershipCheckRule,\n 'browserbase-no-concurrent-shared-context': browserbaseNoConcurrentSharedContextRule,\n 'browserbase-mobile-device-requires-os-setting': browserbaseMobileDeviceRequiresOsSettingRule,\n 'browserbase-use-typed-exception-status-not-substring': browserbaseUseTypedExceptionStatusNotSubstringRule,\n 'browserbase-release-session-on-connect-failure': browserbaseReleaseSessionOnConnectFailureRule,\n 'browserbase-dont-stack-custom-retry-on-sdk-retry': browserbaseDontStackCustomRetryOnSdkRetryRule,\n 'browserbase-no-overbroad-error-substring-match': browserbaseNoOverbroadErrorSubstringMatchRule,\n 'browserbase-use-sdk-not-raw-requests': browserbaseUseSdkNotRawRequestsRule,\n 'browserbase-centralize-request-release': browserbaseCentralizeRequestReleaseRule,\n 'openai-cua-no-domain-allowlist': openaiCuaNoDomainAllowlistRule,\n 'openai-cua-scroll-delta-default-zero': openaiCuaScrollDeltaDefaultZeroRule,\n 'openai-cua-structured-step-metadata-not-text-json': openaiCuaStructuredStepMetadataNotTextJsonRule,\n 'openai-cua-no-blind-safety-check-ack': openaiCuaNoBlindSafetyCheckAckRule,\n 'openai-cua-retry-transient-turn-errors': openaiCuaRetryTransientTurnErrorsRule,\n 'openai-cua-check-response-status-incomplete': openaiCuaCheckResponseStatusIncompleteRule,\n 'openai-cua-set-safety-identifier': openaiCuaSetSafetyIdentifierRule,\n },\n} as const;\n\nexport { plugin };\nexport default plugin;\n","/**\n * Lookup of per-rule documentation metadata (category, rationale, CWE/OWASP),\n * keyed by the plugin rule key. The manifest owns user-facing message/fix/\n * severity; this registry owns the longer-form docs surfaced in reports.\n */\nimport type { FindingCategory } from '../types.js';\nimport { plugin } from './index.js';\n\nexport interface RuleDocsMeta {\n category: FindingCategory;\n description: string;\n rationale: string;\n docsUrl?: string;\n cwe?: string;\n owasp?: string;\n}\n\nfunction buildRegistry(): Map<string, RuleDocsMeta> {\n const registry = new Map<string, RuleDocsMeta>();\n for (const [key, rule] of Object.entries(plugin.rules)) {\n const docs = (rule as any)?.meta?.docs ?? {};\n registry.set(key, {\n category: docs.category,\n description: docs.description ?? '',\n rationale: docs.rationale ?? '',\n docsUrl: docs.docsUrl,\n cwe: docs.cwe,\n owasp: docs.owasp,\n });\n }\n return registry;\n}\n\nconst registry = buildRegistry();\n\nexport function getRuleDocsMeta(ruleKey: string): RuleDocsMeta | undefined {\n return registry.get(ruleKey);\n}\n","/**\n * Extracts a small window of source lines around an issue, preserving original\n * indentation. Shared by every output format that embeds code context.\n */\nimport type { CodeSnippet } from '../types.js';\n\n/**\n * Returns up to `2 * contextLines + 1` lines centered on `line` (1-indexed).\n * Clamps to file bounds, so a short file returns only what's available.\n */\nexport function extractCodeSnippet(\n content: string,\n line: number,\n contextLines = 2,\n): CodeSnippet {\n const allLines = content.split(/\\r?\\n/);\n // Clamp the highlighted line into the file's range.\n const highlighted = Math.min(Math.max(line, 1), allLines.length || 1);\n\n const start = Math.max(1, highlighted - contextLines);\n const end = Math.min(allLines.length, highlighted + contextLines);\n\n const lines: Array<{ number: number; text: string }> = [];\n for (let n = start; n <= end; n++) {\n lines.push({ number: n, text: allLines[n - 1] ?? '' });\n }\n\n return { lines, highlightedLine: highlighted };\n}\n","/**\n * Shared contracts for provider detection, oxlint rule mapping, and scan output.\n */\n\nexport type Severity = 'error' | 'warning' | 'info';\n\nexport type FindingCategory = 'security' | 'correctness' | 'reliability' | 'integration';\n\nexport type ReportSeverityLabel = 'excellent' | 'good' | 'needs-work' | 'critical';\n\nexport interface ScanResult {\n file: string;\n line: number;\n column: number;\n endLine?: number;\n endColumn?: number;\n snippet: string;\n /** Plugin rule key (e.g. `resend-missing-idempotency-key`) — used for stable finding ids. */\n ruleKey: string;\n rule: string;\n severity: Severity;\n message: string;\n fix: string;\n docsUrl?: string;\n}\n\n/** Maps a provider to the oxlint rules that should run when it is detected. */\nexport interface OxlintRuleMeta {\n /** Rule key registered in the plugin (e.g. `resend-webhook-signature`). */\n key: string;\n /** Human-readable rule id shown in reports (e.g. `resend/webhook-signature-missing`). */\n resultRule: string;\n message: string;\n fix: string;\n docsUrl?: string;\n severity?: Severity;\n}\n\nexport interface ProviderManifest {\n name: string;\n displayName: string;\n detect: {\n packages?: string[];\n imports?: string[];\n urlPatterns?: string[];\n };\n oxlintRules: OxlintRuleMeta[];\n}\n\nexport interface DetectedProvider {\n name: string;\n source: 'package.json' | 'imports' | 'url-patterns';\n /** True when api-doctor ran oxlint rules for this provider. */\n checked: boolean;\n}\n\n/**\n * Structured report written to disk and emitted via `--format`. Schema is\n * versioned independently of the package so downstream consumers can pin to it.\n */\nexport interface Report {\n schemaVersion: '1.0.0';\n tool: { name: 'api-doctor'; version: string };\n scanMeta: ScanMeta;\n summary: ReportSummary;\n findings: Finding[];\n}\n\nexport interface ScanMeta {\n /** Absolute path scanned. */\n directory: string;\n /** ISO 8601 timestamp. */\n scannedAt: string;\n durationMs: number;\n filesScanned: number;\n providersDetected: Array<{\n name: string;\n detectedVia: DetectedProvider['source'];\n rulesRun: number;\n }>;\n}\n\nexport interface ReportSummary {\n score: number;\n severity: ReportSeverityLabel;\n errors: number;\n warnings: number;\n info: number;\n totalIssues: number;\n}\n\nexport interface Finding {\n /** `<rule-key>-<sequential-number>`; stable across runs as long as code is unchanged. */\n id: string;\n rule: string;\n category: FindingCategory;\n severity: Severity;\n message: string;\n fix: string;\n docsUrl?: string;\n cwe?: string;\n owasp?: string;\n location: {\n file: string;\n line: number;\n column: number;\n endLine?: number;\n endColumn?: number;\n };\n codeSnippet: CodeSnippet;\n}\n\nexport interface CodeSnippet {\n lines: Array<{ number: number; text: string }>;\n highlightedLine: number;\n}\n\n/** Order used when sorting findings (errors first). */\nexport const SEVERITY_ORDER: Record<Severity, number> = {\n error: 0,\n warning: 1,\n info: 2,\n};\n\n/** Maps a 0–100 score to the structured report's severity label. */\nexport function scoreToSeverityLabel(score: number): ReportSeverityLabel {\n if (score >= 80) return 'excellent';\n if (score >= 60) return 'good';\n if (score >= 40) return 'needs-work';\n return 'critical';\n}\n","/**\n * Turns raw scan output into the versioned Report consumed by the JSON and\n * markdown writers. Owns score computation, finding sort order, and stable finding ids.\n */\nimport { getRuleDocsMeta } from '../plugin/rule-registry.js';\nimport { providers } from '../providers/index.js';\nimport { extractCodeSnippet } from './snippet.js';\nimport {\n SEVERITY_ORDER,\n scoreToSeverityLabel,\n type DetectedProvider,\n type Finding,\n type Report,\n type ReportSummary,\n type ScanResult,\n} from '../types.js';\n\nexport interface BuildReportInput {\n results: ScanResult[];\n detected: DetectedProvider[];\n directory: string;\n filesScanned: number;\n filesContent: Map<string, string>;\n durationMs: number;\n version: string;\n scannedAt?: Date;\n}\n\n/** Same scoring as the terminal report: info findings do not affect the score. */\nfunction computeScore(errors: number, warnings: number): number {\n return Math.max(0, 100 - errors * 15 - warnings * 5);\n}\n\nfunction buildSummary(results: ScanResult[]): ReportSummary {\n const errors = results.filter((r) => r.severity === 'error').length;\n const warnings = results.filter((r) => r.severity === 'warning').length;\n const info = results.filter((r) => r.severity === 'info').length;\n const score = computeScore(errors, warnings);\n return {\n score,\n severity: scoreToSeverityLabel(score),\n errors,\n warnings,\n info,\n totalIssues: results.length,\n };\n}\n\n/** Errors first, then by file path, then by line — determines fix order. */\nfunction sortResults(results: ScanResult[]): ScanResult[] {\n return [...results].sort((a, b) => {\n const bySeverity = SEVERITY_ORDER[a.severity] - SEVERITY_ORDER[b.severity];\n if (bySeverity !== 0) return bySeverity;\n const byFile = a.file.localeCompare(b.file);\n if (byFile !== 0) return byFile;\n return a.line - b.line;\n });\n}\n\nfunction toFinding(result: ScanResult, sequence: number, content: string): Finding {\n const docs = getRuleDocsMeta(result.ruleKey);\n return {\n id: `${result.ruleKey}-${sequence}`,\n rule: result.rule,\n category: docs?.category ?? 'correctness',\n severity: result.severity,\n message: result.message,\n fix: result.fix,\n docsUrl: result.docsUrl ?? docs?.docsUrl,\n cwe: docs?.cwe,\n owasp: docs?.owasp,\n location: {\n file: result.file,\n line: result.line,\n column: result.column,\n endLine: result.endLine,\n endColumn: result.endColumn,\n },\n codeSnippet: extractCodeSnippet(content, result.line),\n };\n}\n\nexport function buildReport(input: BuildReportInput): Report {\n const sorted = sortResults(input.results);\n const summary = buildSummary(input.results);\n\n // Per-rule sequential numbering, assigned in the global sort order.\n const counters = new Map<string, number>();\n const findings: Finding[] = sorted.map((result) => {\n const next = (counters.get(result.ruleKey) ?? 0) + 1;\n counters.set(result.ruleKey, next);\n const content = input.filesContent.get(result.file) ?? '';\n return toFinding(result, next, content);\n });\n\n const providersDetected = input.detected.map((d) => {\n const manifest = providers.find((p) => p.name === d.name);\n return {\n name: d.name,\n detectedVia: d.source,\n rulesRun: d.checked ? (manifest?.oxlintRules.length ?? 0) : 0,\n };\n });\n\n return {\n schemaVersion: '1.0.0',\n tool: { name: 'api-doctor', version: input.version },\n scanMeta: {\n directory: input.directory,\n scannedAt: (input.scannedAt ?? new Date()).toISOString(),\n durationMs: Math.round(input.durationMs),\n filesScanned: input.filesScanned,\n providersDetected,\n },\n summary,\n findings,\n };\n}\n","/**\n * Orchestrates a full project scan:\n * 1) walks source files and detects API providers/SDKs,\n * 2) enables matching oxlint rules from the bundled plugin,\n * 3) shells out to oxlint and parses JSON diagnostics,\n * 4) maps diagnostics into ScanResult objects for the reporter.\n */\nimport { spawn } from 'node:child_process';\nimport { mkdtempSync, rmSync, writeFileSync } from 'node:fs';\nimport { readdir, readFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport os from 'node:os';\nimport { join, relative, resolve } from 'node:path';\nimport { PLUGIN_NAME } from './constants.js';\nimport { detectProviders, type DetectResult } from './detector.js';\nimport { providers } from './providers/index.js';\nimport type { DetectedProvider, OxlintRuleMeta, ScanResult } from './types.js';\n\nconst SKIP_DIRS = new Set(['node_modules', 'dist', 'build', '.next']);\nconst SOURCE_EXT = /\\.(tsx?|jsx?)$/;\n\n/**\n * Runs oxlint asynchronously (rather than spawnSync) so the event loop stays\n * free — this is what lets the CLI's spinner actually animate while it waits.\n */\nfunction runOxlint(\n args: string[],\n cwd: string,\n): Promise<{ stdout: string; stderr: string; error?: Error }> {\n return new Promise((resolveRun) => {\n const child = spawn('npx', args, { cwd });\n let stdout = '';\n let stderr = '';\n child.stdout?.on('data', (chunk) => {\n stdout += chunk;\n });\n child.stderr?.on('data', (chunk) => {\n stderr += chunk;\n });\n child.on('error', (error) => resolveRun({ stdout, stderr, error }));\n child.on('close', () => resolveRun({ stdout, stderr }));\n });\n}\n\n/**\n * Recursively walks a directory tree and collects relative paths to source files.\n * Skips hidden files/dirs (names starting with `.`) and dirs in SKIP_DIRS.\n * Mutates the `files` array in place — callers pass an empty array to fill.\n */\nasync function walk(dir: string, root: string, files: string[]): Promise<void> {\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.name.startsWith('.')) continue;\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n if (SKIP_DIRS.has(entry.name)) continue;\n await walk(full, root, files);\n } else if (SOURCE_EXT.test(entry.name)) {\n files.push(relative(root, full));\n }\n }\n}\n\n/** Options passed from the CLI into `scan()`. */\nexport interface ScanOptions {\n /** When set, only run checks for these provider names (from `--provider`). */\n onlyProviders?: string[];\n}\n\n/** Return value of `scan()` — findings plus which SDKs were detected. */\nexport interface ScanOutput {\n results: ScanResult[];\n detected: DetectedProvider[];\n /** All package names from the project's package.json — used for unsupported-package hints. */\n rawPackages: string[];\n /** Absolute path that was scanned. */\n directory: string;\n /** Number of source files walked. */\n filesScanned: number;\n /** Relative file path -> file contents, for snippet extraction downstream. */\n filesContent: Map<string, string>;\n}\n\n/** Thrown on tool-level failures (unreadable directory, oxlint crash). Maps to exit 2. */\nexport class ScanError extends Error {\n constructor(message: string, readonly cause?: unknown) {\n super(message);\n this.name = 'ScanError';\n }\n}\n\n/**\n * Builds the oxlint config for a scan based on which providers were detected.\n * Returns two things:\n * - oxlintRules: rule ids → severity, written into the temp .oxlintrc.json\n * - ruleMetaByKey: rule key → message/fix/docs, used when mapping diagnostics back\n */\nfunction buildOxlintConfig(detectedNames: Set<string>): {\n oxlintRules: Record<string, 'error' | 'warn' | 'off'>;\n ruleMetaByKey: Map<string, OxlintRuleMeta>;\n} {\n const oxlintRules: Record<string, 'error' | 'warn' | 'off'> = {};\n const ruleMetaByKey = new Map<string, OxlintRuleMeta>();\n\n for (const provider of providers) {\n if (!detectedNames.has(provider.name)) continue;\n for (const rule of provider.oxlintRules) {\n // oxlint has no `info` level; warnings and info both map to `warn`.\n // The declared severity is preserved in ruleMetaByKey for reporting.\n oxlintRules[`${PLUGIN_NAME}/${rule.key}`] =\n rule.severity === 'error' || rule.severity === undefined ? 'error' : 'warn';\n ruleMetaByKey.set(rule.key, rule);\n }\n }\n\n return { oxlintRules, ruleMetaByKey };\n}\n\nexport async function scan(directory: string, options: ScanOptions = {}): Promise<ScanOutput> {\n // Resolve the target directory to an absolute path.\n const absRoot = resolve(directory);\n\n // Collect every .ts/.tsx/.js/.jsx file under absRoot (skipping node_modules, etc.).\n const paths: string[] = [];\n try {\n await walk(absRoot, absRoot, paths);\n } catch (err) {\n throw new ScanError(`Could not read directory: ${absRoot}`, err);\n }\n\n // Read each file's contents into memory — used for provider detection and line snippets.\n const filesContent = new Map<string, string>();\n for (const rel of paths) {\n const content = await readFile(join(absRoot, rel), 'utf-8');\n filesContent.set(rel, content);\n }\n\n // Detect which API SDKs are present (package.json deps, imports, URL patterns).\n let { detected, rawPackages } = await detectProviders(absRoot, filesContent);\n\n // If --provider was passed, narrow detection to only those providers.\n if (options.onlyProviders?.length) {\n const allowed = new Set(options.onlyProviders.map((p) => p.toLowerCase()));\n detected = detected.filter((d) => allowed.has(d.name));\n }\n\n // Look up which oxlint rules to enable based on detected providers.\n const detectedNames = new Set(detected.map((d) => d.name));\n const { oxlintRules, ruleMetaByKey } = buildOxlintConfig(detectedNames);\n\n // Nothing to lint — e.g. no supported SDK found, or provider has no rules yet.\n if (Object.keys(oxlintRules).length === 0) {\n return {\n results: [],\n detected,\n rawPackages,\n directory: absRoot,\n filesScanned: paths.length,\n filesContent,\n };\n }\n\n // Resolve the bundled oxlint plugin on disk (dist/plugin.js).\n const require = createRequire(import.meta.url);\n const pluginEntry = require.resolve('@api-doctor/cli/plugin');\n\n // Write a temporary oxlint config — we don't require users to have one in their project.\n const tmpDir = mkdtempSync(join(os.tmpdir(), 'api-doctor-oxlint-'));\n const configPath = join(tmpDir, 'oxlintrc.json');\n\n const config = {\n jsPlugins: [pluginEntry],\n rules: oxlintRules,\n ignorePatterns: Array.from(SKIP_DIRS),\n };\n\n writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');\n\n // Run oxlint against the target project; diagnostics come back as JSON on stdout.\n const res = await runOxlint(\n ['oxlint', '--config', configPath, '--format', 'json', '.'],\n absRoot,\n );\n\n try {\n // `error` is set when the process couldn't start at all.\n if (res.error) {\n throw new ScanError('Failed to run oxlint', res.error);\n }\n let parsed: any;\n try {\n parsed = JSON.parse(res.stdout);\n } catch (err) {\n const stderr = (res.stderr ?? '').toString().trim();\n throw new ScanError(\n `oxlint produced no parseable output${stderr ? `: ${stderr}` : ''}`,\n err,\n );\n }\n const diagnostics: any[] = parsed.diagnostics ?? [];\n\n // Convert oxlint diagnostics into ScanResult objects for the reporter.\n const results: ScanResult[] = [];\n for (const d of diagnostics) {\n const code = String(d.code ?? '');\n // Skip built-in oxlint rules (e.g. no-unused-vars) — only keep our plugin rules.\n const matched = [...ruleMetaByKey.entries()].find(([key]) => code.includes(key));\n if (!matched) continue;\n const [ruleKey, meta] = matched;\n\n // Normalize the file path to be relative to the scanned directory.\n const relFile = (() => {\n const filename = String(d.filename ?? '');\n if (!filename) return '';\n if (filename.startsWith(absRoot)) return relative(absRoot, filename);\n return filename.replace(/^[.\\\\/]+/, '');\n })();\n\n const span = d.labels?.[0]?.span;\n const line = typeof span?.line === 'number' ? span.line : 1;\n const column = typeof span?.column === 'number' ? span.column : 1;\n const endLine = typeof span?.endLine === 'number' ? span.endLine : undefined;\n const endColumn = typeof span?.endColumn === 'number' ? span.endColumn : undefined;\n\n // Pull the offending source line for --verbose output.\n const content = filesContent.get(relFile) ?? '';\n const snippet = content.split(/\\r?\\n/)[line - 1]?.trim() ?? '';\n\n results.push({\n file: relFile,\n line,\n column,\n endLine,\n endColumn,\n snippet,\n ruleKey,\n rule: meta.resultRule,\n // The manifest declares the intended severity (including `info`, which\n // oxlint reports as a warning). Fall back to oxlint's severity.\n severity: meta.severity ?? (d.severity === 'warning' ? 'warning' : 'error'),\n message: meta.message,\n fix: meta.fix,\n docsUrl: meta.docsUrl,\n });\n }\n\n return {\n results,\n detected,\n rawPackages,\n directory: absRoot,\n filesScanned: paths.length,\n filesContent,\n };\n } finally {\n // Clean up the temp config directory regardless of success or failure.\n rmSync(tmpDir, { recursive: true, force: true });\n }\n}\n","/**\n * Detects which API providers are present in a project using package.json\n * dependencies, import patterns in source files, and URL substrings.\n * This is the only non-oxlint step — it decides which rules to enable.\n */\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { DetectedProvider } from './types.js';\nimport { providers } from './providers/index.js';\n\nfunction hasImportPattern(source: string, pkg: string): boolean {\n return (\n source.includes(`from '${pkg}'`) ||\n source.includes(`from \"${pkg}\"`) ||\n source.includes(`require('${pkg}')`) ||\n source.includes(`require(\"${pkg}\")`)\n );\n}\n\nexport interface DetectResult {\n detected: DetectedProvider[];\n /** All package names from package.json (deps + devDeps). Empty if no package.json. */\n rawPackages: string[];\n}\n\nexport async function detectProviders(\n directory: string,\n filesContent: Map<string, string>,\n): Promise<DetectResult> {\n // Dedupe by provider name — each SDK is only reported once.\n const detected = new Map<string, DetectedProvider>();\n\n // Single string of all source files, used for URL pattern matching below.\n const allSources = [...filesContent.values()].join('\\n');\n\n // Load dependencies from package.json (if it exists).\n let deps: Record<string, string> = {};\n try {\n const raw = await readFile(join(directory, 'package.json'), 'utf-8');\n const pkg = JSON.parse(raw) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n deps = { ...pkg.dependencies, ...pkg.devDependencies };\n } catch {\n // missing or invalid package.json — skip package-based detection\n }\n\n // Check each registered provider (Resend, Stripe, Supabase, …).\n for (const provider of providers) {\n if (detected.has(provider.name)) continue;\n\n // Stage 1: match npm package names in dependencies / devDependencies.\n const packages = provider.detect.packages ?? [];\n if (packages.some((p) => p in deps)) {\n detected.set(provider.name, {\n name: provider.name,\n source: 'package.json',\n checked: provider.oxlintRules.length > 0,\n });\n continue;\n }\n\n // Stage 2: match import/require statements in source files.\n const imports = provider.detect.imports ?? [];\n if (imports.some((p) => [...filesContent.values()].some((s) => hasImportPattern(s, p)))) {\n detected.set(provider.name, {\n name: provider.name,\n source: 'imports',\n checked: provider.oxlintRules.length > 0,\n });\n continue;\n }\n\n // Stage 3: match API URL substrings anywhere in source (e.g. api.resend.com).\n const urls = provider.detect.urlPatterns ?? [];\n if (urls.some((u) => allSources.includes(u))) {\n detected.set(provider.name, {\n name: provider.name,\n source: 'url-patterns',\n checked: provider.oxlintRules.length > 0,\n });\n }\n }\n\n return { detected: [...detected.values()], rawPackages: Object.keys(deps) };\n}\n","/**\n * Markdown export. Produces a self-contained document a user can paste into a\n * coding agent: every finding with code context, rationale, and fix, plus an\n * embedded handoff prompt at the end.\n */\nimport { basename } from 'node:path';\nimport { getRuleDocsMeta } from '../plugin/rule-registry.js';\nimport { providers } from '../providers/index.js';\nimport type { Finding, Report } from '../types.js';\n\n/** Maps a finding's result rule id to the rule's longer-form rationale. */\nfunction rationaleByRule(): Map<string, string> {\n const map = new Map<string, string>();\n for (const provider of providers) {\n for (const rule of provider.oxlintRules) {\n const docs = getRuleDocsMeta(rule.key);\n if (docs?.rationale) map.set(rule.resultRule, docs.rationale);\n }\n }\n return map;\n}\n\nfunction codeBlock(finding: Finding): string {\n const { lines, highlightedLine } = finding.codeSnippet;\n const body = lines\n .map((line) => (line.number === highlightedLine ? `${line.text} // ← issue` : line.text))\n .join('\\n');\n return ['```typescript', body, '```'].join('\\n');\n}\n\nfunction references(finding: Finding): string | undefined {\n const parts: string[] = [];\n if (finding.cwe) parts.push(finding.cwe);\n if (finding.owasp) parts.push(`OWASP ${finding.owasp}`);\n return parts.length > 0 ? parts.join(', ') : undefined;\n}\n\nconst HANDOFF_PROMPT =\n 'Please review these api-doctor findings and fix each one. Reference the docs ' +\n \"links if you're uncertain about any fix. Process them in order — earlier issues \" +\n 'may affect later ones.';\n\nexport function renderMarkdown(report: Report): string {\n const { summary, scanMeta, tool, findings } = report;\n const rationales = rationaleByRule();\n const out: string[] = [];\n\n out.push('# api-doctor report');\n out.push('');\n out.push(`**Score:** ${summary.score}/100 (${summary.severity})`);\n out.push(`**Generated:** ${new Date(scanMeta.scannedAt).toUTCString()}`);\n out.push(`**Project:** ${basename(scanMeta.directory)}`);\n out.push(`**Tool:** api-doctor v${tool.version}`);\n out.push('');\n\n out.push('## Summary');\n out.push('');\n out.push(`- ${summary.errors} errors`);\n out.push(`- ${summary.warnings} warnings`);\n out.push(`- ${summary.info} info notices`);\n out.push(\n `- ${summary.totalIssues} total issues across ${scanMeta.filesScanned} files`,\n );\n out.push('');\n\n out.push('## Issues to fix');\n out.push('');\n\n if (findings.length === 0) {\n out.push('No issues found. Nothing to fix.');\n out.push('');\n return `${out.join('\\n')}\\n`;\n }\n\n findings.forEach((finding, index) => {\n out.push(`### ${index + 1}. ${finding.message} [${finding.severity}]`);\n out.push(`**File:** \\`${finding.location.file}:${finding.location.line}\\``);\n out.push(`**Rule:** \\`${finding.rule}\\``);\n const refs = references(finding);\n if (refs) out.push(`**References:** ${refs}`);\n out.push('');\n out.push(codeBlock(finding));\n out.push('');\n const rationale = rationales.get(finding.rule);\n if (rationale) {\n out.push(`**Why this matters:** ${rationale}`);\n out.push('');\n }\n out.push(`**Fix:** ${finding.fix}`);\n out.push('');\n if (finding.docsUrl) {\n out.push(`**Docs:** ${finding.docsUrl}`);\n out.push('');\n }\n out.push('---');\n out.push('');\n });\n\n out.push('## How to fix these with a coding agent');\n out.push('');\n out.push(\n 'Copy this entire file and paste it into Cursor, Claude Code, or any AI coding ' +\n 'agent with a prompt like:',\n );\n out.push('');\n out.push(`> \"${HANDOFF_PROMPT}\"`);\n out.push('');\n\n return `${out.join('\\n')}\\n`;\n}\n","/**\n * Formats and prints scan results: detected providers, 0–100 score,\n * terminal header (icon, progress bar), and grouped issue list.\n *\n * This is the default human terminal output and is intentionally kept stable.\n */\nimport pc from 'picocolors';\nimport { INSTALL_COMMAND } from '../install.js';\nimport { providers } from '../providers/index.js';\nimport type { DetectedProvider, ScanResult } from '../types.js';\nimport { lineDelay, revealDelay } from './animate.js';\n\nconst ISSUES_URL = 'https://github.com/qualtyco/api-doctor/issues';\nconst BAR_WIDTH = 24;\n\nexport interface ReportOptions {\n verbose?: boolean;\n elapsedMs?: number;\n}\n\ninterface IssueGroup {\n rule: string;\n message: string;\n fix: string;\n docsUrl?: string;\n items: ScanResult[];\n}\n\nfunction displayNames(detected: DetectedProvider[]): string {\n return detected\n .map((d) => providers.find((p) => p.name === d.name)?.displayName ?? d.name)\n .join(', ');\n}\n\nfunction detectionSourceLabel(source: DetectedProvider['source']): string {\n switch (source) {\n case 'package.json':\n return 'package.json';\n case 'imports':\n return 'imports';\n case 'url-patterns':\n return 'URL patterns';\n }\n}\n\nasync function printDetectedProviders(detected: DetectedProvider[]): Promise<void> {\n console.log(pc.bold('Detected APIs & SDKs'));\n for (const d of detected) {\n const manifest = providers.find((p) => p.name === d.name);\n const label = manifest?.displayName ?? d.name;\n const via = pc.dim(`via ${detectionSourceLabel(d.source)}`);\n\n if (d.checked) {\n const ruleCount = manifest?.oxlintRules.length ?? 0;\n const checks = pc.dim(`— ${ruleCount} check${ruleCount === 1 ? '' : 's'}`);\n console.log(` ${pc.green('✓')} ${label} ${via} ${checks}`);\n } else {\n console.log(` ${pc.dim('○')} ${label} ${via} ${pc.dim('— no checks yet')}`);\n }\n await revealDelay();\n }\n console.log('');\n}\n\nfunction scoreColor(score: number): (s: string) => string {\n if (score >= 75) return pc.green;\n if (score >= 50) return pc.yellow;\n return pc.red;\n}\n\nfunction statusLabel(score: number): string {\n if (score >= 75) return 'Good';\n if (score >= 50) return 'Needs work';\n return 'Critical';\n}\n\nfunction headerIcon(score: number, color: (s: string) => string): string[] {\n const box = (face: string[]) => [\n color('┌────┐'),\n color(`│${face[0]}│`),\n color(`│${face[1]}│`),\n color('└────┘'),\n ];\n if (score >= 75) return box([' ^^ ', ' ‿‿ ']);\n if (score >= 50) return box([' o o', ' __ ']);\n return box([' >< ', ' == ']);\n}\n\nfunction progressBar(score: number, color: (s: string) => string): string {\n const filled = Math.round((score / 100) * BAR_WIDTH);\n const empty = BAR_WIDTH - filled;\n return color('█'.repeat(Math.max(0, filled))) + pc.dim('░'.repeat(Math.max(0, empty)));\n}\n\nfunction padVisible(text: string, width: number): string {\n const plain = text.replace(/\\u001b\\[[0-9;]*m/g, '');\n const spaces = Math.max(0, width - plain.length);\n return text + ' '.repeat(spaces);\n}\n\nasync function printHeader(score: number): Promise<void> {\n const color = scoreColor(score);\n const scoreText = `${color(String(score))}${pc.dim(' / 100')} ${color(statusLabel(score))}`;\n const bar = progressBar(score, color);\n const icon = headerIcon(score, color);\n const iconColWidth = 8;\n const lines = [\n `${padVisible(icon[0], iconColWidth)}${scoreText}`,\n `${padVisible(icon[1], iconColWidth)}${bar}`,\n padVisible(icon[2], iconColWidth),\n padVisible(icon[3], iconColWidth),\n ];\n for (const line of lines) {\n console.log(line);\n await lineDelay();\n }\n}\n\nfunction formatDuration(ms?: number): string {\n if (ms === undefined) return '';\n const sec = ms / 1000;\n return sec < 10 ? `${sec.toFixed(1)}s` : `${Math.round(sec)}s`;\n}\n\nfunction groupResults(results: ScanResult[]): IssueGroup[] {\n const groups = new Map<string, IssueGroup>();\n for (const r of results) {\n let group = groups.get(r.rule);\n if (!group) {\n group = { rule: r.rule, message: r.message, fix: r.fix, docsUrl: r.docsUrl, items: [] };\n groups.set(r.rule, group);\n }\n group.items.push(r);\n }\n return [...groups.values()];\n}\n\nfunction printSummary(\n errors: number,\n warnings: number,\n infos: number,\n fileCount: number,\n elapsedMs?: number,\n): void {\n const parts: string[] = [];\n if (errors > 0) parts.push(pc.red(`${errors} error${errors === 1 ? '' : 's'}`));\n if (warnings > 0) parts.push(pc.yellow(`${warnings} warning${warnings === 1 ? '' : 's'}`));\n if (infos > 0) parts.push(pc.cyan(`${infos} info`));\n if (parts.length === 0) {\n console.log(pc.green('No issues found'));\n return;\n }\n\n const duration = formatDuration(elapsedMs);\n const tail = [\n fileCount > 0 ? `across ${fileCount} file${fileCount === 1 ? '' : 's'}` : '',\n duration ? `in ${duration}` : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n console.log(`${parts.join(pc.dim(', '))}${tail ? pc.dim(` ${tail}`) : ''}`);\n}\n\nasync function printIssueGroups(groups: IssueGroup[], verbose: boolean): Promise<void> {\n for (const group of groups) {\n const count = group.items.length;\n const severity = group.items[0]?.severity;\n const countColor = severity === 'warning' ? pc.yellow : severity === 'info' ? pc.cyan : pc.red;\n const countLabel = count > 1 ? countColor(` (${count})`) : '';\n const prefix =\n severity === 'warning' ? pc.yellow('×') : severity === 'info' ? pc.cyan('ℹ') : pc.red('×');\n console.log(`${prefix} ${group.message}${countLabel}`);\n await lineDelay();\n\n for (const [index, item] of group.items.entries()) {\n console.log(pc.dim(` ${index + 1}. ${item.file}:${item.line}`));\n if (verbose) {\n console.log(pc.dim(` ${item.snippet}`));\n console.log(pc.cyan(` Fix: ${group.fix}`));\n if (group.docsUrl) console.log(pc.dim(` Docs: ${group.docsUrl}`));\n }\n if (group.items.length > 1) await lineDelay();\n }\n\n if (!verbose && (group.fix || group.docsUrl)) {\n console.log(pc.cyan(` → ${group.fix}`));\n }\n console.log('');\n await revealDelay();\n }\n}\n\nexport async function renderTerminalReport(\n results: ScanResult[],\n detected: DetectedProvider[],\n options: ReportOptions = {},\n): Promise<void> {\n if (detected.length === 0) {\n const names = providers.map((p) => p.displayName).join(', ');\n console.log(pc.dim('No supported Node.js API providers detected in this project.'));\n console.log(`Supported Node.js providers: ${names}`);\n console.log(`Request a provider: ${ISSUES_URL}`);\n return;\n }\n\n const errors = results.filter((r) => r.severity === 'error').length;\n const warnings = results.filter((r) => r.severity === 'warning').length;\n const infos = results.filter((r) => r.severity === 'info').length;\n // Info findings are advisory and do not affect the score.\n const score = Math.max(0, 100 - errors * 15 - warnings * 5);\n const fileCount = new Set(results.map((r) => r.file)).size;\n const checked = detected.filter((d) => d.checked);\n\n console.log('');\n await printDetectedProviders(detected);\n await printHeader(score);\n console.log('');\n await revealDelay();\n\n if (results.length === 0) {\n const duration = formatDuration(options.elapsedMs);\n const scannedLabel =\n checked.length > 0\n ? `Checked ${checked.map((d) => providers.find((p) => p.name === d.name)?.displayName ?? d.name).join(', ')}`\n : `Found ${displayNames(detected)}`;\n console.log(pc.dim(`${scannedLabel}${duration ? ` in ${duration}` : ''}`));\n console.log('');\n console.log(pc.green(`${pc.bold('✓')} No issues found`));\n return;\n }\n\n printSummary(errors, warnings, infos, fileCount, options.elapsedMs);\n console.log('');\n await printIssueGroups(groupResults(results), options.verbose ?? false);\n}\n\nexport function countErrors(results: ScanResult[]): number {\n return results.filter((r) => r.severity === 'error').length;\n}\n\nconst FOOTER_WIDTH = 54;\n\nexport function renderUnsupportedPackagesHint(): void {\n const innerWidth = FOOTER_WIDTH - 2;\n const border = (s: string) => pc.yellow(s);\n const top = border('╭' + '─'.repeat(innerWidth) + '╮');\n const bot = border('╰' + '─'.repeat(innerWidth) + '╯');\n const row = (s: string) => border('│') + ' ' + padVisible(s, innerWidth - 1) + border('│');\n\n console.log('');\n console.log(top);\n console.log(row(pc.yellow(\"This scan saw packages we don't support yet.\")));\n console.log(row(pc.yellow('Submit an issue to request support:')));\n console.log(row(pc.bold(pc.yellow(ISSUES_URL))));\n console.log(bot);\n}\n\nexport function renderFooter(opts: { reportPath?: string; showInstallHint: boolean }): void {\n console.log(pc.dim('─'.repeat(FOOTER_WIDTH)));\n\n if (opts.reportPath) {\n console.log('');\n console.log(pc.dim(` Saved → ${opts.reportPath}`));\n }\n\n if (opts.showInstallHint) {\n const innerWidth = FOOTER_WIDTH - 2; // exclude the two border chars\n const label = 'Connect to your coding agent to fix now';\n const cmd = ` ${INSTALL_COMMAND}`;\n const top = pc.cyan('╭' + '─'.repeat(innerWidth) + '╮');\n const bot = pc.cyan('╰' + '─'.repeat(innerWidth) + '╯');\n const row = (s: string) =>\n pc.cyan('│') + ' ' + padVisible(s, innerWidth - 1) + pc.cyan('│');\n console.log('');\n console.log(top);\n console.log(row(pc.cyan(label)));\n console.log(row(pc.bold(cmd)));\n console.log(bot);\n }\n\n console.log('');\n}\n","/**\n * Unaggregated terminal output: every finding printed inline with a code\n * snippet, in the report's sort order. Used by `--verbose`.\n */\nimport pc from 'picocolors';\nimport type { Report, Severity } from '../types.js';\nimport { revealDelay } from './animate.js';\n\nfunction severityTag(severity: Severity): string {\n if (severity === 'error') return pc.red('error');\n if (severity === 'warning') return pc.yellow('warning');\n return pc.cyan('info');\n}\n\nfunction printSnippet(report: Report, index: number): void {\n const finding = report.findings[index];\n const { lines, highlightedLine } = finding.codeSnippet;\n const gutterWidth = String(lines.at(-1)?.number ?? highlightedLine).length;\n for (const line of lines) {\n const num = String(line.number).padStart(gutterWidth, ' ');\n const isIssue = line.number === highlightedLine;\n const marker = isIssue ? pc.red('>') : ' ';\n const body = `${marker} ${pc.dim(`${num} |`)} ${line.text}`;\n console.log(isIssue ? body : pc.dim(body));\n }\n}\n\nexport async function renderVerboseReport(report: Report): Promise<void> {\n const { summary, findings } = report;\n console.log('');\n console.log(\n pc.bold(`api-doctor — ${summary.score}/100 (${summary.severity})`),\n );\n console.log(\n pc.dim(\n `${summary.errors} errors, ${summary.warnings} warnings, ${summary.info} info across ${report.scanMeta.filesScanned} files`,\n ),\n );\n console.log('');\n\n if (findings.length === 0) {\n console.log(pc.green(`${pc.bold('✓')} No issues found`));\n return;\n }\n\n for (let index = 0; index < findings.length; index++) {\n const finding = findings[index];\n const loc = `${finding.location.file}:${finding.location.line}:${finding.location.column}`;\n console.log(\n `${severityTag(finding.severity)} ${pc.bold(finding.message)} ${pc.dim(`[${finding.rule}]`)}`,\n );\n console.log(pc.dim(` ${loc}`));\n console.log('');\n printSnippet(report, index);\n console.log('');\n console.log(` ${pc.cyan('Fix:')} ${finding.fix}`);\n if (finding.docsUrl) console.log(` ${pc.dim('Docs:')} ${finding.docsUrl}`);\n console.log('');\n await revealDelay();\n }\n}\n","import { providers } from './providers/index.js';\n\n/** Common packages that are not useful for provider discovery prompts. */\nexport const EXCLUDED_PACKAGES = new Set([\n // React ecosystem\n 'react',\n 'react-dom',\n 'react-bootstrap',\n 'react-day-picker',\n 'react-hook-form',\n 'react-resizable-panels',\n 'react-router',\n 'react-router-dom',\n // Build tools\n 'vite',\n 'vitest',\n 'typescript',\n 'typescript-eslint',\n '@vitejs/plugin-react',\n '@vitejs/plugin-react-swc',\n // Linting\n 'eslint',\n '@eslint/js',\n 'eslint-plugin-react-hooks',\n 'eslint-plugin-react-refresh',\n 'globals',\n // CSS & styling\n 'bootstrap',\n 'tailwindcss',\n 'tailwindcss-animate',\n 'tailwind-merge',\n '@tailwindcss/typography',\n 'postcss',\n 'autoprefixer',\n 'class-variance-authority',\n 'clsx',\n 'next-themes',\n // UI libraries\n '@radix-ui/react-accordion',\n '@radix-ui/react-alert-dialog',\n '@radix-ui/react-aspect-ratio',\n '@radix-ui/react-avatar',\n '@radix-ui/react-checkbox',\n '@radix-ui/react-collapsible',\n '@radix-ui/react-context-menu',\n '@radix-ui/react-dialog',\n '@radix-ui/react-dropdown-menu',\n '@radix-ui/react-hover-card',\n '@radix-ui/react-label',\n '@radix-ui/react-menubar',\n '@radix-ui/react-navigation-menu',\n '@radix-ui/react-popover',\n '@radix-ui/react-progress',\n '@radix-ui/react-radio-group',\n '@radix-ui/react-scroll-area',\n '@radix-ui/react-select',\n '@radix-ui/react-separator',\n '@radix-ui/react-slider',\n '@radix-ui/react-slot',\n '@radix-ui/react-switch',\n '@radix-ui/react-tabs',\n '@radix-ui/react-toast',\n '@radix-ui/react-toggle',\n '@radix-ui/react-toggle-group',\n '@radix-ui/react-tooltip',\n 'cmdk',\n 'embla-carousel-react',\n 'input-otp',\n 'lucide-react',\n 'recharts',\n 'sonner',\n 'vaul',\n // Data fetching & forms\n '@hookform/resolvers',\n '@tanstack/react-query',\n 'zod',\n 'date-fns',\n // Testing\n '@testing-library/jest-dom',\n '@testing-library/react',\n 'jsdom',\n // Supported providers (common enough to skip the request-support prompt)\n 'firebase',\n '@supabase/supabase-js',\n // Misc dev tools\n 'pdfjs-dist',\n 'lovable-tagger',\n '@anthropic-ai/claude-code',\n '@api-doctor/cli',\n]);\n\nconst EXCLUDED_PREFIXES = ['@types/', '@radix-ui/', '@testing-library/'];\n\nconst SUPPORTED_PACKAGES = new Set(\n providers.flatMap((p) => [...(p.detect.packages ?? []), p.name]),\n);\n\n/** package.json deps that are not a supported provider and not excluded noise. */\nexport function getUnsupportedPackages(rawPackages: string[]): string[] {\n return rawPackages.filter(\n (p) =>\n !EXCLUDED_PACKAGES.has(p) &&\n !SUPPORTED_PACKAGES.has(p) &&\n !EXCLUDED_PREFIXES.some((prefix) => p.startsWith(prefix)),\n );\n}\n","/**\n * Output orchestration. Picks the renderer based on CLI flags and writes the\n * structured report file. The default (no-flag) path renders the stable human\n * terminal output unchanged.\n */\nimport type { DetectedProvider, Report, ScanResult } from '../types.js';\nimport { ScanError } from '../scanner.js';\nimport { INSTALL_COMMAND, isAgentSkillInstalled } from '../install.js';\nimport { writeReport } from './json-writer.js';\nimport { renderMarkdown } from './markdown.js';\nimport { countErrors, renderFooter, renderTerminalReport, renderUnsupportedPackagesHint } from './terminal.js';\nimport { renderVerboseReport } from './verbose.js';\nimport { getUnsupportedPackages } from '../unsupported-packages.js';\n\nexport type OutputFormat = 'json' | 'markdown';\n\nexport interface EmitOptions {\n quiet?: boolean;\n verbose?: boolean;\n format?: OutputFormat;\n noReport?: boolean;\n /** Absolute path the report file is written to. */\n outputPath: string;\n /** Path shown to the user (relative when possible). */\n reportDisplayPath: string;\n elapsedMs?: number;\n}\n\nexport { countErrors };\n\nexport async function emitReport(\n results: ScanResult[],\n detected: DetectedProvider[],\n report: Report,\n options: EmitOptions & { rawPackages?: string[] },\n): Promise<void> {\n const writeFileReport = (): void => {\n if (!options.noReport) writeReport(report, options.outputPath);\n };\n\n // Structured stdout formats suppress all human output so the stream can be piped.\n if (options.format) {\n if (options.format === 'json') {\n process.stdout.write(`${JSON.stringify(report, null, 2)}\\n`);\n } else if (options.format === 'markdown') {\n process.stdout.write(renderMarkdown(report));\n } else {\n throw new ScanError(`Unsupported format: ${options.format}`);\n }\n writeFileReport();\n return;\n }\n\n if (options.quiet) {\n writeFileReport();\n const parts = [`Score: ${report.summary.score}/100`];\n if (!options.noReport) parts.push(`→ ${options.reportDisplayPath}`);\n console.log(parts.join(' '));\n return;\n }\n\n if (options.verbose) {\n await renderVerboseReport(report);\n } else {\n await renderTerminalReport(results, detected, { elapsedMs: options.elapsedMs });\n }\n\n writeFileReport();\n\n if (!options.format && !options.quiet && getUnsupportedPackages(options.rawPackages ?? []).length > 0) {\n renderUnsupportedPackagesHint();\n }\n\n if (detected.length > 0) {\n renderFooter({\n reportPath: options.noReport ? undefined : options.reportDisplayPath,\n showInstallHint: !isAgentSkillInstalled(report.scanMeta.directory),\n });\n } else if (!options.noReport) {\n console.log(`→ Report written to ${options.reportDisplayPath}`);\n }\n}\n","import { createHash, randomUUID } from 'node:crypto';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join, resolve } from 'node:path';\nimport type { DetectedProvider, ScanResult } from './types.js';\nimport { readProjectHistory, writeProjectHistory } from './run-history.js';\n\n// Public project API key — safe to embed (same as a browser-side PostHog key).\nconst POSTHOG_API_KEY = 'phc_odgcBBsio9P5XJ3zT3Hyd6pgawQXW6YvwgJUejUTWhxz';\nconst POSTHOG_CAPTURE_URL = 'https://us.i.posthog.com/capture/';\n\n// install-id stays global (per-user); run history moves to each project dir.\nconst INSTALL_ID_PATH = join(homedir(), '.api-doctor', 'install-id');\n\n/** Privacy-safe stable identifier for a scanned project directory. */\nexport function hashProjectDir(projectDir: string): string {\n return createHash('sha256').update(resolve(projectDir)).digest('hex');\n}\n\nfunction isTelemetryDisabled(noTelemetry: boolean): boolean {\n if (noTelemetry) return true;\n if (process.env['DO_NOT_TRACK'] === '1') return true;\n if (process.env['API_DOCTOR_TELEMETRY'] === '0') return true;\n return false;\n}\n\nfunction getOrCreateInstallId(): string {\n try {\n mkdirSync(join(homedir(), '.api-doctor'), { recursive: true });\n if (existsSync(INSTALL_ID_PATH)) {\n return readFileSync(INSTALL_ID_PATH, 'utf-8').trim();\n }\n const id = randomUUID();\n writeFileSync(INSTALL_ID_PATH, id, 'utf-8');\n return id;\n } catch {\n return 'anonymous';\n }\n}\n\nfunction detectRunContext(): string {\n if (process.env['CI']) return 'ci';\n if (\n process.env['CLAUDE_CODE'] ||\n process.env['CURSOR_TRACE_ID'] ||\n process.env['CODEX_ENV'] ||\n process.env['WINDSURF_SESSION_ID']\n )\n return 'agent';\n return 'local';\n}\n\nasync function capture(event: string, distinctId: string, properties: Record<string, unknown>): Promise<void> {\n await fetch(POSTHOG_CAPTURE_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ api_key: POSTHOG_API_KEY, event, distinct_id: distinctId, properties }),\n });\n}\n\nfunction sanitizeErrorText(text: string | undefined): string | undefined {\n if (!text) return undefined;\n const home = homedir();\n let sanitized = text;\n if (home) sanitized = sanitized.split(home).join('[home]');\n sanitized = sanitized.replace(/\\/[\\w.@+~-]+(?:\\/[\\w.@+~-]+)+/g, '[path]');\n sanitized = sanitized.replace(/[A-Za-z]:\\\\(?:[^\\\\\\n]+\\\\)*[^\\\\\\n]*/g, '[path]');\n return sanitized;\n}\n\nexport interface TrackRunOptions {\n version: string;\n results: ScanResult[];\n detected: DetectedProvider[];\n score: number;\n durationMs: number;\n noTelemetry: boolean;\n projectDir: string;\n}\n\nexport async function trackRun(opts: TrackRunOptions): Promise<void> {\n if (isTelemetryDisabled(opts.noTelemetry)) return;\n\n try {\n const distinctId = getOrCreateInstallId();\n const prev = readProjectHistory(opts.projectDir);\n const scoreDelta = prev !== null ? opts.score - prev.last_score : null;\n\n const sharedProps = {\n cli_version: opts.version,\n node_version: process.version,\n platform: process.platform,\n run_context: detectRunContext(),\n };\n\n // 1. Summary event.\n await capture('cli_run', distinctId, {\n ...sharedProps,\n project_hash: hashProjectDir(opts.projectDir),\n score: opts.score,\n score_delta: scoreDelta,\n errors: opts.results.filter((r) => r.severity === 'error').length,\n warnings: opts.results.filter((r) => r.severity === 'warning').length,\n duration_ms: Math.round(opts.durationMs),\n run_count: (prev?.run_count ?? 0) + 1,\n });\n\n // 2. One event per detected provider.\n await Promise.all(\n opts.detected.map((d) => {\n const rules_triggered = [\n ...new Set(\n opts.results\n .filter((r) => r.ruleKey.startsWith(d.name) && (r.severity === 'error' || r.severity === 'warning'))\n .map((r) => r.ruleKey),\n ),\n ];\n return capture('provider_scanned', distinctId, {\n ...sharedProps,\n provider: d.name,\n score: opts.score,\n rules_triggered,\n });\n }),\n );\n\n writeProjectHistory(opts.projectDir, {\n last_score: opts.score,\n last_run: new Date().toISOString(),\n run_count: (prev?.run_count ?? 0) + 1,\n });\n } catch {\n // Never surface telemetry errors to the user.\n }\n}\n\nexport interface TrackInstallOptions {\n version: string;\n filesCreated: number;\n filesUpdated: number;\n filesSkipped: number;\n force: boolean;\n noTelemetry: boolean;\n}\n\nexport async function trackInstall(opts: TrackInstallOptions): Promise<void> {\n if (isTelemetryDisabled(opts.noTelemetry)) return;\n\n try {\n const distinctId = getOrCreateInstallId();\n await capture('install_command_run', distinctId, {\n cli_version: opts.version,\n node_version: process.version,\n platform: process.platform,\n files_created: opts.filesCreated,\n files_updated: opts.filesUpdated,\n files_skipped: opts.filesSkipped,\n force: opts.force,\n });\n } catch {\n // Never surface telemetry errors to the user.\n }\n}\n\nexport async function trackError(err: unknown, noTelemetry: boolean, version: string): Promise<void> {\n if (isTelemetryDisabled(noTelemetry)) return;\n\n try {\n const distinctId = getOrCreateInstallId();\n await capture('cli_error', distinctId, {\n cli_version: version,\n node_version: process.version,\n platform: process.platform,\n error_message: sanitizeErrorText(err instanceof Error ? err.message : String(err)),\n stack_trace: sanitizeErrorText(err instanceof Error ? err.stack : undefined),\n });\n } catch {\n // Never surface telemetry errors to the user.\n }\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nconst REPORT_DIR = '.api-doctor';\nconst RUN_HISTORY_FILE = 'run-history.json';\n\nexport interface ProjectRunHistory {\n last_score: number;\n last_run: string;\n run_count: number;\n}\n\nfunction historyPath(projectDir: string): string {\n return join(projectDir, REPORT_DIR, RUN_HISTORY_FILE);\n}\n\nexport function readProjectHistory(projectDir: string): ProjectRunHistory | null {\n try {\n const path = historyPath(projectDir);\n if (!existsSync(path)) return null;\n return JSON.parse(readFileSync(path, 'utf-8')) as ProjectRunHistory;\n } catch {\n return null;\n }\n}\n\nexport function writeProjectHistory(projectDir: string, history: ProjectRunHistory): void {\n try {\n mkdirSync(join(projectDir, REPORT_DIR), { recursive: true });\n writeFileSync(historyPath(projectDir), JSON.stringify(history, null, 2), 'utf-8');\n } catch {\n // Never throw — disk errors must not surface to the user.\n }\n}\n"],"mappings":"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","names":["readFileSync","dirname","join","relative","resolve","fileURLToPath","resolve","existsSync","mkdirSync","writeFileSync","dirname","rule","rule","rule","rule","rule","rule","rule","rule","rule","rule","rule","rule","rule","state","rule","arg","rule","rule","rule","rule","rule","rule","rule","rule","rule","rule","rule","rule","propName","rule","propName","rule","propName","memberPropName","chainObjectCall","startOffset","endOffset","contains","isInsideTestFile","rule","isInsideTestFile","rule","memberPropName","contains","rule","rule","startOffset","endOffset","scope","rule","rule","rule","rule","memberPropName","contains","rule","propName","rule","propName","memberChainNames","rule","propName","rule","memberPropName","memberPropName","findProperty","startOffset","endOffset","contains","someDescendant","isInsideTestFile","rule","startOffset","endOffset","contains","rule","findProperty","rule","startOffset","endOffset","isPromiseAllCall","isMapCall","memberPropName","findProperty","rule","someDescendant","rule","someDescendant","rule","memberPropName","findProperty","rule","contains","someDescendant","rule","findProperty","memberPropName","rule","someDescendant","rule","rule","isInsideTestFile","findProperty","rule","propName","memberChainNames","rule","propName","rule","rule","propName","rule","propName","rule","propName","rule","propName","registry","rule","writeFileSync","readFile","join","relative","join","pkg","join","join","relative","rule","readFile","require","writeFileSync","basename","rule","basename","pc","pc","existsSync","mkdirSync","readFileSync","writeFileSync","join","resolve","existsSync","mkdirSync","readFileSync","writeFileSync","join","join","resolve","mkdirSync","existsSync","readFileSync","writeFileSync","__dirname","dirname","fileURLToPath","readFileSync","join","resolve","relative"]}