@api-doctor/cli 0.0.3 → 0.0.5
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.
- package/README.md +39 -46
- package/dist/cli.cjs +5373 -1490
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +5373 -1490
- package/dist/cli.mjs.map +1 -1
- package/dist/plugin.d.ts +1013 -0
- package/dist/plugin.js +4887 -1476
- package/dist/plugin.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.15_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","../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":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","/**\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":["import_node_fs","import_node_path","import_node_url","resolve","import_node_fs","import_node_path","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","import_node_fs","import_promises","import_node_path","import_node_path","pkg","rule","require","os","import_node_path","rule","pc","import_picocolors","pc","import_node_fs","import_node_os","import_node_path","import_node_fs","import_node_path"]}
|
|
1
|
+
{"version":3,"sources":["../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.15_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","../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/tiptap/manifest.ts","../src/providers/elevenlabs/manifest.ts","../src/providers/twilio/manifest.ts","../src/providers/openai-realtime/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/firebase/rules/firestore-rules-expired.ts","../src/providers/firebase/rules/id-token-cookie-flags.ts","../src/providers/firebase/rules/middleware-token-not-verified.ts","../src/providers/firebase/rules/hardcoded-user-id.ts","../src/providers/firebase/rules/auth-user-not-found-disclosure.ts","../src/providers/firebase/rules/signup-password-confirm.ts","../src/providers/firebase/rules/use-array-union-remove.ts","../src/providers/firebase/rules/duplicate-initialize-app.ts","../src/providers/firebase/rules/onSnapshot-async-throw.ts","../src/providers/firebase/rules/onSnapshot-missing-error-callback.ts","../src/providers/firebase/rules/firestore-document-size-guard.ts","../src/providers/firebase/rules/use-timestamp-now.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/providers/tiptap/rules/upload-validate-fn-void.ts","../src/providers/tiptap/rules/script-src-hardcoded-api-key.ts","../src/providers/tiptap/rules/dynamic-script-no-sri.ts","../src/providers/tiptap/utils.ts","../src/providers/tiptap/rules/addAttributes-missing-renderHTML.ts","../src/providers/tiptap/rules/appendTransaction-add-to-history.ts","../src/providers/tiptap/rules/appendTransaction-full-scan.ts","../src/providers/tiptap/rules/atom-node-wrap-in.ts","../src/providers/tiptap/rules/twitter-url-regex.ts","../src/providers/tiptap/rules/drop-handler-pos-precedence.ts","../src/providers/tiptap/rules/prefer-table-kit.ts","../src/providers/tiptap/rules/tiptap-markdown-missing-node-spec.ts","../src/providers/elevenlabs/utils.ts","../src/providers/elevenlabs/rules/validate-signed-url-response.ts","../src/providers/elevenlabs/rules/no-error-object-logging.ts","../src/providers/elevenlabs/rules/fetch-timeout-required.ts","../src/providers/elevenlabs/rules/validate-agent-id-format.ts","../src/providers/elevenlabs/rules/secure-session-id-generation.ts","../src/providers/elevenlabs/rules/conversation-error-recovery.ts","../src/providers/elevenlabs/rules/api-version-pinning.ts","../src/providers/elevenlabs/rules/check-http-status-before-json.ts","../src/providers/elevenlabs/rules/conversation-cleanup-on-error.ts","../src/providers/elevenlabs/rules/env-var-validation.ts","../src/providers/twilio/utils.ts","../src/providers/twilio/rules/validate-webhook-signature.ts","../src/providers/twilio/rules/taskrouter-attributes-match-consumer.ts","../src/providers/twilio/rules/enqueue-task-json-stringify.ts","../src/providers/twilio/rules/media-streams-key-by-call-sid.ts","../src/providers/twilio/rules/await-or-catch-rest-calls-in-event-handlers.ts","../src/providers/twilio/rules/use-twiml-builder-not-string-templates.ts","../src/providers/twilio/rules/media-streams-mark-pacing.ts","../src/providers/twilio/rules/validate-all-request-inputs.ts","../src/providers/twilio/rules/media-streams-mark-name-string.ts","../src/providers/openai-realtime/utils.ts","../src/providers/openai-realtime/rules/migrate-beta-to-ga.ts","../src/providers/openai-realtime/rules/no-log-raw-message-payloads.ts","../src/providers/openai-realtime/rules/handle-error-server-event.ts","../src/providers/openai-realtime/rules/reconnect-on-drop.ts","../src/providers/openai-realtime/rules/avoid-dated-preview-snapshots.ts","../src/providers/openai-realtime/rules/verify-deprecated-session-fields.ts","../src/providers/openai-realtime/rules/buffer-audio-until-session-ready.ts","../src/providers/openai-realtime/rules/send-safety-identifier.ts","../src/providers/openai-realtime/rules/transcription-model-choice.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":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","/**\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 key: 'firebase-firestore-rules-expired',\n resultRule: 'firebase/security/firestore-rules-expired',\n message: 'Firestore security rules contain a hard-coded expiry date that has already passed. All client reads and writes are permanently denied.',\n fix: 'Replace the timestamp.date() expiry with proper auth-based rules: allow read, write: if request.auth != null && request.auth.uid == userId;',\n docsUrl: 'https://firebase.google.com/docs/firestore/security/insecure-rules',\n severity: 'error',\n },\n {\n key: 'firebase-id-token-cookie-flags',\n resultRule: 'firebase/security/id-token-cookie-flags',\n message: 'Firebase ID token stored in a cookie without httpOnly: true.',\n fix: 'Use the Firebase Admin SDK createSessionCookie flow to issue an httpOnly, secure session cookie instead of storing raw ID tokens client-side.',\n docsUrl: 'https://firebase.google.com/docs/auth/admin/manage-cookies',\n severity: 'error',\n },\n {\n key: 'firebase-middleware-token-not-verified',\n resultRule: 'firebase/security/middleware-token-not-verified',\n message: 'Middleware reads the auth cookie but never verifies it. Any non-empty cookie value bypasses the guard.',\n fix: 'Call adminAuth.verifySessionCookie(cookie, true) in the middleware and redirect on failure.',\n docsUrl: 'https://firebase.google.com/docs/auth/admin/manage-cookies#verify_session_cookies_and_check_permissions',\n severity: 'error',\n },\n {\n key: 'firebase-hardcoded-user-id',\n resultRule: 'firebase/security/hardcoded-user-id',\n message: 'Hardcoded userId found. All users share this Firestore document.',\n fix: 'Read the userId from the authenticated user: const { user } = useAuth(); user?.uid',\n docsUrl: 'https://firebase.google.com/docs/auth/web/manage-users',\n severity: 'error',\n },\n {\n key: 'firebase-auth-user-not-found-disclosure',\n resultRule: 'firebase/security/auth-user-not-found-disclosure',\n message: 'Checking for auth/user-not-found exposes whether an email is registered (user enumeration).',\n fix: 'Show the same generic message for all auth errors regardless of the error code.',\n docsUrl: 'https://firebase.google.com/docs/auth/web/password-auth#enumeration-protection',\n severity: 'warning',\n },\n {\n key: 'firebase-signup-password-confirm',\n resultRule: 'firebase/correctness/signup-password-confirm',\n message: 'createUserWithEmailAndPassword is called without verifying password === confirmPassword.',\n fix: 'Add: if (password !== confirmPassword) { setError(\"Passwords do not match\"); return; } before the Firebase call.',\n docsUrl: 'https://firebase.google.com/docs/auth/web/password-auth',\n severity: 'warning',\n },\n {\n key: 'firebase-use-array-union-remove',\n resultRule: 'firebase/correctness/use-array-union-remove',\n message: 'Firestore array updated with read-modify-write spread/filter instead of atomic arrayUnion/arrayRemove.',\n fix: 'Use arrayUnion(item) or arrayRemove(item) from firebase/firestore for atomic array operations.',\n docsUrl: 'https://firebase.google.com/docs/firestore/manage-data/add-data#update_elements_in_an_array',\n severity: 'warning',\n },\n {\n key: 'firebase-duplicate-initialize-app',\n resultRule: 'firebase/correctness/duplicate-initialize-app',\n message: 'initializeApp() called without checking getApps() first — risk of duplicate-app crash.',\n fix: 'Use: const app = getApps().length ? getApp() : initializeApp(config);',\n docsUrl: 'https://firebase.google.com/docs/projects/multiprojects',\n severity: 'warning',\n },\n {\n key: 'firebase-onSnapshot-async-throw',\n resultRule: 'firebase/reliability/onSnapshot-async-throw',\n message: 'throw inside an async onSnapshot callback creates an unhandled promise rejection.',\n fix: 'Return with error logging instead of throwing, or provide an error callback as the third argument to onSnapshot.',\n docsUrl: 'https://firebase.google.com/docs/firestore/query-data/listen#handle_listen_errors',\n severity: 'warning',\n },\n {\n key: 'firebase-onSnapshot-missing-error-callback',\n resultRule: 'firebase/reliability/onSnapshot-missing-error-callback',\n message: 'onSnapshot called without an error callback. Firestore permission errors silently stop the listener.',\n fix: 'Add an error callback: onSnapshot(ref, successFn, (error) => { console.error(error); })',\n docsUrl: 'https://firebase.google.com/docs/firestore/query-data/listen#handle_listen_errors',\n severity: 'warning',\n },\n {\n key: 'firebase-firestore-document-size-guard',\n resultRule: 'firebase/reliability/firestore-document-size-guard',\n message: 'Firestore write includes editor.getJSON() without a document size check.',\n fix: 'Check document size before writing: if (new Blob([payload]).size > 900_000) { setSaveStatus(\"Document too large\"); return; }',\n docsUrl: 'https://firebase.google.com/docs/firestore/quotas#limits',\n severity: 'warning',\n },\n {\n key: 'firebase-use-timestamp-now',\n resultRule: 'firebase/correctness/use-timestamp-now',\n message: 'new Date() used for a Firestore timestamp field instead of Timestamp.now() or serverTimestamp().',\n fix: 'Import { Timestamp } from \"firebase/firestore\" and use Timestamp.now() for consistency with Firestore security rules.',\n docsUrl: 'https://firebase.google.com/docs/reference/js/firestore_.timestamp',\n severity: 'info',\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","import type { ProviderManifest } from '../../types.js';\n\nexport const tiptapManifest: ProviderManifest = {\n name: 'tiptap',\n displayName: 'TipTap',\n detect: {\n packages: ['@tiptap/core', '@tiptap/react', '@tiptap/pm'],\n imports: ['@tiptap/core', '@tiptap/react', '@tiptap/pm'],\n urlPatterns: ['tiptap.dev'],\n },\n oxlintRules: [\n {\n key: 'tiptap-upload-validate-fn-void',\n resultRule: 'tiptap/security/upload-validate-fn-void',\n message: 'validateFn return value discarded — file validation never blocks uploads.',\n fix: 'Change validateFn return type to boolean and guard: if (validateFn && !validateFn(file)) return;',\n docsUrl: 'https://tiptap.dev/docs/editor/extensions/custom-extensions/node-views',\n severity: 'error',\n },\n {\n key: 'tiptap-script-src-hardcoded-api-key',\n resultRule: 'tiptap/security/script-src-hardcoded-api-key',\n message: 'script.src contains a hardcoded API key.',\n fix: 'Read the key from process.env and assemble the URL at runtime.',\n docsUrl: 'https://tiptap.dev/docs/editor/extensions/custom-extensions/node-views',\n severity: 'error',\n },\n {\n key: 'tiptap-dynamic-script-no-sri',\n resultRule: 'tiptap/security/dynamic-script-no-sri',\n message: 'Dynamically injected script appended without SRI integrity attribute.',\n fix: 'Add script.setAttribute(\"integrity\", \"sha384-...\") before appending the script.',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity',\n severity: 'warning',\n },\n {\n key: 'tiptap-addAttributes-missing-renderHTML',\n resultRule: 'tiptap/correctness/addAttributes-missing-renderHTML',\n message: 'TipTap attribute defines parseHTML but no renderHTML — attribute lost on HTML round-trip.',\n fix: 'Add renderHTML: (attrs) => ({ \"data-<name>\": attrs.<name> }) to the attribute descriptor.',\n docsUrl: 'https://tiptap.dev/docs/editor/extensions/custom-extensions/create-new/node#attributes',\n severity: 'error',\n },\n {\n key: 'tiptap-appendTransaction-add-to-history',\n resultRule: 'tiptap/correctness/appendTransaction-add-to-history',\n message: 'appendTransaction mutates without setMeta(\"addToHistory\", false) — pollutes undo stack.',\n fix: 'Chain .setMeta(\"addToHistory\", false) onto the transaction before dispatching.',\n docsUrl: 'https://prosemirror.net/docs/ref/#state.Transaction.setMeta',\n severity: 'warning',\n },\n {\n key: 'tiptap-appendTransaction-full-scan',\n resultRule: 'tiptap/reliability/appendTransaction-full-scan',\n message: 'appendTransaction calls doc.descendants() on every transaction — O(n) per keystroke.',\n fix: 'Guard with: const docChanged = transactions.some(tr => tr.docChanged); if (!docChanged) return;',\n docsUrl: 'https://prosemirror.net/docs/ref/#state.PluginSpec.appendTransaction',\n severity: 'warning',\n },\n {\n key: 'tiptap-atom-node-wrap-in',\n resultRule: 'tiptap/correctness/atom-node-wrap-in',\n message: 'wrapIn() called with an atom node type — always silently returns false.',\n fix: 'Use replaceSelectionWith(nodeType.create()) instead of wrapIn().',\n docsUrl: 'https://tiptap.dev/docs/editor/extensions/custom-extensions/create-new/node',\n severity: 'warning',\n },\n {\n key: 'tiptap-twitter-url-regex',\n resultRule: 'tiptap/integration/twitter-url-regex',\n message: 'Twitter/X regex matches x.com but not twitter.com — legacy URLs silently rejected.',\n fix: 'Update pattern to (x\\\\.com|twitter\\\\.com) to support both domains.',\n docsUrl: 'https://tiptap.dev/docs/editor/extensions/nodes',\n severity: 'warning',\n },\n {\n key: 'tiptap-drop-handler-pos-precedence',\n resultRule: 'tiptap/correctness/drop-handler-pos-precedence',\n message: 'Operator precedence bug: x ?? 0 - 1 evaluates to x ?? -1, not (x ?? 0) - 1.',\n fix: 'Add parentheses: (coordinates?.pos ?? 0) - 1',\n docsUrl: 'https://prosemirror.net/docs/ref/#view.EditorView.posAtCoords',\n severity: 'warning',\n },\n {\n key: 'tiptap-prefer-table-kit',\n resultRule: 'tiptap/integration/prefer-table-kit',\n message: 'Individual TipTap table extension imported — use TableKit instead.',\n fix: 'Import TableKit from @tiptap/extension-table and configure all table elements together.',\n docsUrl: 'https://tiptap.dev/docs/editor/extensions/functionality/table-kit',\n severity: 'info',\n },\n {\n key: 'tiptap-tiptap-markdown-missing-node-spec',\n resultRule: 'tiptap/integration/tiptap-markdown-missing-node-spec',\n message: 'TipTap node used with tiptap-markdown has no markdown serialization spec — content lost on export.',\n fix: 'Add a markdown serializer to addStorage or addOptions using MarkdownNodeSpec.',\n docsUrl: 'https://github.com/ueberdosis/tiptap-markdown',\n severity: 'warning',\n },\n ],\n};\n","import type { ProviderManifest } from '../../types.js';\n\nexport const elevenlabsManifest: ProviderManifest = {\n name: 'elevenlabs',\n displayName: 'ElevenLabs',\n detect: {\n packages: ['@11labs/client', 'elevenlabs', '@elevenlabs/elevenlabs-js'],\n imports: ['@11labs/client', 'elevenlabs', '@elevenlabs/elevenlabs-js'],\n urlPatterns: ['api.elevenlabs.io'],\n },\n oxlintRules: [\n {\n key: 'elevenlabs-validate-signed-url-response',\n resultRule: 'elevenlabs/correctness/validate-signed-url-response',\n message: 'The signed URL response is used without validating that signed_url is present.',\n fix: 'Check that data.signed_url exists before using it, and throw/return an error response if it is missing.',\n docsUrl: 'https://elevenlabs.io/docs/eleven-agents/api-reference/conversations/get-signed-url',\n severity: 'error',\n },\n {\n key: 'elevenlabs-no-error-object-logging',\n resultRule: 'elevenlabs/security/no-error-object-logging',\n message: 'A catch block around an ElevenLabs API call logs the raw error object.',\n fix: 'Log a sanitized message (e.g. error instanceof Error ? error.message : \"Unknown error\") instead of the raw error object.',\n docsUrl: 'https://elevenlabs.io/docs/api-reference/authentication',\n severity: 'error',\n },\n {\n key: 'elevenlabs-fetch-timeout-required',\n resultRule: 'elevenlabs/reliability/fetch-timeout-required',\n message: 'A fetch call to the ElevenLabs API has no abort signal/timeout.',\n fix: 'Pass an AbortController signal (e.g. via setTimeout(() => controller.abort(), 5000)) so a slow or unresponsive API does not hang the request indefinitely.',\n docsUrl: 'https://elevenlabs.io/docs/eleven-agents/api-reference/conversations/get-signed-url',\n severity: 'warning',\n },\n {\n key: 'elevenlabs-validate-agent-id-format',\n resultRule: 'elevenlabs/correctness/validate-agent-id-format',\n message: 'agentId is checked for existence but not validated against an expected format.',\n fix: 'Validate agentId against an allowed pattern (e.g. /^[a-zA-Z0-9\\\\-]{1,64}$/) before using it in an ElevenLabs API request.',\n docsUrl: 'https://elevenlabs.io/docs/eleven-agents/customization/authentication',\n severity: 'error',\n },\n {\n key: 'elevenlabs-secure-session-id-generation',\n resultRule: 'elevenlabs/security/secure-session-id-generation',\n message: 'A session id is generated with Math.random(), which is not cryptographically secure.',\n fix: 'Use crypto.getRandomValues() to generate session ids instead of Math.random().',\n docsUrl: 'https://elevenlabs.io/docs/eleven-api/guides/how-to/best-practices/security',\n severity: 'error',\n },\n {\n key: 'elevenlabs-conversation-error-recovery',\n resultRule: 'elevenlabs/reliability/conversation-error-recovery',\n message: 'A loading flag set before starting a conversation is never reset on failure.',\n fix: 'Reset the loading flag in the catch block (or a finally block) so a failed attempt does not leave the UI stuck loading.',\n docsUrl: 'https://elevenlabs.io/docs/eleven-agents/libraries/java-script',\n severity: 'warning',\n },\n {\n key: 'elevenlabs-api-version-pinning',\n resultRule: 'elevenlabs/reliability/api-version-pinning',\n message: 'A fetch call to the ElevenLabs API has no explicit API version header.',\n fix: 'Add an explicit version header (e.g. elevenlabs-version) to the request instead of relying on the URL path alone.',\n docsUrl: 'https://elevenlabs.io/docs/eleven-api/resources/breaking-changes-policy',\n severity: 'warning',\n },\n {\n key: 'elevenlabs-check-http-status-before-json',\n resultRule: 'elevenlabs/correctness/check-http-status-before-json',\n message: 'response.json() is called on an ElevenLabs API response without checking response.ok/status first.',\n fix: 'Check response.ok (or response.status) before calling response.json(), so an error body is not parsed as valid data.',\n docsUrl: 'https://elevenlabs.io/docs/eleven-api/resources/errors',\n severity: 'error',\n },\n {\n key: 'elevenlabs-conversation-cleanup-on-error',\n resultRule: 'elevenlabs/reliability/conversation-cleanup-on-error',\n message: 'A call to end the conversation has no surrounding try/catch.',\n fix: 'Wrap conversation.endSession()/endConversation() in try/catch so a rejection does not leave the conversation state in memory.',\n docsUrl: 'https://elevenlabs.io/docs/eleven-agents/libraries/java-script',\n severity: 'warning',\n },\n {\n key: 'elevenlabs-env-var-validation',\n resultRule: 'elevenlabs/correctness/env-var-validation',\n message: 'An ElevenLabs API key is only validated inside a request handler, not at module load.',\n fix: 'Read and validate the env var at module scope (and throw if missing) so a misconfigured deployment fails at startup.',\n docsUrl: 'https://elevenlabs.io/docs/api-reference/authentication',\n severity: 'warning',\n },\n ],\n};\n","import type { ProviderManifest } from '../../types.js';\n\nexport const twilioManifest: ProviderManifest = {\n name: 'twilio',\n displayName: 'Twilio',\n detect: {\n packages: ['twilio'],\n imports: ['twilio'],\n urlPatterns: ['api.twilio.com'],\n },\n oxlintRules: [\n {\n key: 'twilio-validate-webhook-signature',\n resultRule: 'twilio/security/validate-webhook-signature',\n message: 'A POST webhook route reads req.body but never validates the X-Twilio-Signature header.',\n fix: 'Validate the X-Twilio-Signature header with twilio.validateRequest()/RequestValidator before trusting the body.',\n docsUrl: 'https://www.twilio.com/docs/usage/webhooks/webhooks-security',\n severity: 'error',\n },\n {\n key: 'twilio-taskrouter-attributes-match-consumer',\n resultRule: 'twilio/correctness/taskrouter-attributes-match-consumer',\n message: 'A .task() attributes object is missing a field that a reservation handler reads back out of TaskAttributes.',\n fix: 'Add the missing field to the Task attributes object so the consumer\\'s JSON.parse(TaskAttributes) destructure actually finds it.',\n docsUrl: 'https://www.twilio.com/docs/taskrouter/twiml-queue-calls',\n severity: 'error',\n },\n {\n key: 'twilio-enqueue-task-json-stringify',\n resultRule: 'twilio/security/enqueue-task-json-stringify',\n message: 'A .task() call builds JSON attributes via raw string interpolation instead of JSON.stringify().',\n fix: 'Build the Task attributes as an object and serialize with JSON.stringify() instead of interpolating values into a JSON string/template literal.',\n docsUrl: 'https://www.twilio.com/docs/api/errors/14221',\n severity: 'error',\n },\n {\n key: 'twilio-media-streams-key-by-call-sid',\n resultRule: 'twilio/reliability/media-streams-key-by-call-sid',\n message: 'A Media Streams session map is keyed by a phone-number-like field instead of callSid.',\n fix: 'Key the map by start.callSid instead of the caller phone number, and propagate callSid (not the number) downstream as the lookup key.',\n docsUrl: 'https://www.twilio.com/docs/voice/media-streams/websocket-messages',\n severity: 'error',\n },\n {\n key: 'twilio-await-or-catch-rest-calls-in-event-handlers',\n resultRule: 'twilio/reliability/await-or-catch-rest-calls-in-event-handlers',\n message: 'A Twilio REST call inside an event-handler callback has no surrounding try/catch.',\n fix: 'Wrap the REST call in try/catch inside the handler so a rejected promise does not become an unhandled rejection.',\n docsUrl: 'https://www.twilio.com/docs/usage/webhooks/webhooks-faq',\n severity: 'error',\n },\n {\n key: 'twilio-use-twiml-builder-not-string-templates',\n resultRule: 'twilio/security/use-twiml-builder-not-string-templates',\n message: 'TwiML is built as a raw template literal instead of the VoiceResponse builder.',\n fix: 'Build TwiML with new VoiceResponse() and its builder methods (say, connect, stream, parameter) instead of interpolating values into an XML template literal.',\n docsUrl: 'https://www.twilio.com/docs/voice/twiml/stream',\n severity: 'warning',\n },\n {\n key: 'twilio-media-streams-mark-pacing',\n resultRule: 'twilio/reliability/media-streams-mark-pacing',\n message: 'Media is forwarded to a Stream with no mark-based pacing (isLast) anywhere in the file.',\n fix: 'Pace sends with mark events (pass isLast: true periodically) and wait for the inbound mark acknowledgment before queuing more audio.',\n docsUrl: 'https://www.twilio.com/docs/api/errors/31931',\n severity: 'warning',\n },\n {\n key: 'twilio-validate-all-request-inputs',\n resultRule: 'twilio/correctness/validate-all-request-inputs',\n message: 'A webhook route reads a request field that is not covered by its schema (or has no schema at all).',\n fix: 'Add a querystring/body schema covering every field the handler reads, and reject the request with a 400 if a required field is missing.',\n docsUrl: 'https://www.twilio.com/docs/voice/twiml/stream',\n severity: 'warning',\n },\n {\n key: 'twilio-media-streams-mark-name-string',\n resultRule: 'twilio/correctness/media-streams-mark-name-string',\n message: 'mark.name is set to a non-string value (Twilio requires a string).',\n fix: 'Wrap the value in String(...) (e.g. String(Date.now())) so mark.name matches Twilio\\'s documented string schema.',\n docsUrl: 'https://www.twilio.com/docs/voice/media-streams/websocket-messages',\n severity: 'warning',\n },\n ],\n};\n","import type { ProviderManifest } from '../../types.js';\n\nexport const openaiRealtimeManifest: ProviderManifest = {\n name: 'openai-realtime',\n displayName: 'OpenAI Realtime API',\n detect: {\n urlPatterns: ['api.openai.com/v1/realtime'],\n },\n oxlintRules: [\n {\n key: 'openai-realtime-migrate-beta-to-ga',\n resultRule: 'openai-realtime/correctness/migrate-beta-to-ga',\n message: 'This Realtime connection sends the deprecated OpenAI-Beta: realtime=v1 header.',\n fix: 'Remove the OpenAI-Beta header and migrate the session/event shapes to the GA interface (session.type, audio.output nesting, response.output_audio.delta event names).',\n docsUrl: 'https://developers.openai.com/api/docs/guides/realtime',\n severity: 'error',\n },\n {\n key: 'openai-realtime-no-log-raw-message-payloads',\n resultRule: 'openai-realtime/security/no-log-raw-message-payloads',\n message: 'A raw OpenAI Realtime message is logged verbatim, which can include live call audio or transcript content.',\n fix: 'Log only derived fields (e.g. { type: message.type }) at info level; log full payloads only at trace level behind an explicit opt-in.',\n docsUrl: 'https://developers.openai.com/api/docs/guides/realtime',\n severity: 'error',\n },\n {\n key: 'openai-realtime-handle-error-server-event',\n resultRule: 'openai-realtime/reliability/handle-error-server-event',\n message: 'This Realtime message handler branches on event types but never checks for the API-level \"error\" event.',\n fix: \"Add an explicit branch for message.type === 'error' that logs the error and surfaces/fails over, instead of letting it fall through silently.\",\n docsUrl: 'https://developers.openai.com/api/docs/api-reference/realtime_server_events',\n severity: 'error',\n },\n {\n key: 'openai-realtime-reconnect-on-drop',\n resultRule: 'openai-realtime/reliability/reconnect-on-drop',\n message: 'This Realtime socket\\'s close handler only logs and never attempts to reconnect.',\n fix: 'On close, attempt a bounded number of reconnects with a fresh session.update, and proactively end/flag the call if reconnection ultimately fails.',\n docsUrl: 'https://developers.openai.com/api/docs/guides/realtime',\n severity: 'error',\n },\n {\n key: 'openai-realtime-avoid-dated-preview-snapshots',\n resultRule: 'openai-realtime/correctness/avoid-dated-preview-snapshots',\n message: 'The Realtime connection is pinned to a dated preview model snapshot instead of the GA alias.',\n fix: \"Use the GA model id (e.g. 'gpt-realtime') or a current dated snapshot tracked against OpenAI's deprecation notices.\",\n docsUrl: 'https://developers.openai.com/api/docs/api-reference/realtime-sessions',\n severity: 'warning',\n },\n {\n key: 'openai-realtime-verify-deprecated-session-fields',\n resultRule: 'openai-realtime/correctness/verify-deprecated-session-fields',\n message: \"The session config sets 'temperature', a field not documented in the current GA Realtime sessions schema.\",\n fix: 'Re-verify this field against the current sessions reference before relying on it, or drop it and control determinism via turn_detection/instructions instead.',\n docsUrl: 'https://developers.openai.com/api/docs/api-reference/realtime-sessions',\n severity: 'warning',\n },\n {\n key: 'openai-realtime-buffer-audio-until-session-ready',\n resultRule: 'openai-realtime/reliability/buffer-audio-until-session-ready',\n message: 'Audio sent before the Realtime socket reaches the open state is dropped instead of buffered.',\n fix: 'Queue outbound input_audio_buffer.append messages until the open event fires, then flush them in order.',\n docsUrl: 'https://developers.openai.com/api/docs/voice/media-streams/websocket-messages',\n severity: 'warning',\n },\n {\n key: 'openai-realtime-send-safety-identifier',\n resultRule: 'openai-realtime/security/send-safety-identifier',\n message: 'This Realtime WebSocket connection does not send an OpenAI-Safety-Identifier header.',\n fix: 'Add an OpenAI-Safety-Identifier header with a stable, privacy-preserving value (e.g. a hashed account/call id) to support abuse/safety monitoring.',\n docsUrl: 'https://developers.openai.com/api/docs/guides/realtime',\n severity: 'info',\n },\n {\n key: 'openai-realtime-transcription-model-choice',\n resultRule: 'openai-realtime/correctness/transcription-model-choice',\n message: \"input_audio_transcription is configured with 'whisper-1', which is not natively streaming and not optimized for realtime sessions.\",\n fix: \"Switch to 'gpt-realtime-whisper' if transcription output is consumed, or drop input_audio_transcription entirely if it isn't.\",\n docsUrl: 'https://developers.openai.com/api/docs/guides/realtime-transcription',\n severity: 'info',\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';\nimport { tiptapManifest } from './tiptap/manifest.js';\nimport { elevenlabsManifest } from './elevenlabs/manifest.js';\nimport { twilioManifest } from './twilio/manifest.js';\nimport { openaiRealtimeManifest } from './openai-realtime/manifest.js';\n\nexport const providers: ProviderManifest[] = [\n resendManifest,\n supabaseManifest,\n auth0Manifest,\n firebaseManifest,\n lovableManifest,\n browserbaseManifest,\n openaiCuaManifest,\n tiptapManifest,\n elevenlabsManifest,\n twilioManifest,\n openaiRealtimeManifest,\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","import { someDescendant } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Firestore security rules contain a hard-coded expiry date that has already passed',\n category: 'security',\n cwe: 'CWE-284',\n owasp: 'A01:2021 Broken Access Control',\n rationale:\n 'The Firebase \"get started\" rules template includes a timestamp.date() expiry. Once that date passes the condition permanently evaluates to false, denying every client read and write. Replace with proper auth-based rules scoped to the authenticated user.',\n docsUrl: 'https://firebase.google.com/docs/firestore/security/insecure-rules',\n recommended: true,\n },\n messages: {\n firestoreRulesExpired:\n 'Firestore security rules contain a hard-coded expiry date that has already passed. All client reads and writes are permanently denied. Replace with proper auth-based rules.',\n },\n schema: [],\n },\n create(context: any) {\n const EXPIRED_YEAR = 2025;\n\n function checkStringForExpiredDate(value: string, reportNode: any) {\n const re = /timestamp\\.date\\(\\s*(\\d{4})\\s*,/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(value)) !== null) {\n const year = parseInt(match[1], 10);\n if (year <= EXPIRED_YEAR) {\n context.report({ node: reportNode, messageId: 'firestoreRulesExpired' });\n return;\n }\n }\n }\n\n return {\n Literal(node: any) {\n if (typeof node.value !== 'string') return;\n checkStringForExpiredDate(node.value, node);\n },\n TemplateLiteral(node: any) {\n for (const quasi of node.quasis ?? []) {\n const cooked = quasi?.value?.cooked ?? quasi?.value?.raw ?? '';\n if (typeof cooked === 'string' && cooked.includes('timestamp.date(')) {\n checkStringForExpiredDate(cooked, node);\n return;\n }\n }\n },\n };\n },\n};\n\nexport const firebaseFirestoreRulesExpiredRule = rule;\nexport default rule;\n","function findProp(obj: any, name: string): any {\n if (obj?.type !== 'ObjectExpression') return undefined;\n return (obj.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\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Firebase ID token stored in a cookie without httpOnly flag',\n category: 'security',\n cwe: 'CWE-1004',\n owasp: 'A02:2021 Cryptographic Failures',\n rationale:\n 'Storing a Firebase ID token in a non-httpOnly cookie makes it readable by any JavaScript on the page. An XSS vulnerability can steal the token and impersonate the user. Use the Firebase Admin SDK createSessionCookie flow to issue a proper httpOnly session cookie instead.',\n docsUrl: 'https://firebase.google.com/docs/auth/admin/manage-cookies',\n recommended: true,\n },\n messages: {\n idTokenCookieMissingHttpOnly:\n 'Firebase ID token stored in cookie without httpOnly: true. Any XSS vulnerability can steal the token. Use the Firebase Admin SDK createSessionCookie flow instead.',\n },\n schema: [],\n },\n create(context: any) {\n function isTokenName(val: string): boolean {\n return /token/i.test(val);\n }\n\n function hasHttpOnlyTrue(optsNode: any): boolean {\n if (optsNode?.type !== 'ObjectExpression') return false;\n const prop = findProp(optsNode, 'httpOnly');\n if (!prop) return false;\n return prop.value?.type === 'Literal' && prop.value.value === true;\n }\n\n return {\n CallExpression(node: any) {\n const callee = node.callee;\n const isCookieSet =\n callee?.type === 'Identifier' && callee.name === 'setCookie';\n\n if (!isCookieSet) return;\n\n const args = node.arguments ?? [];\n const nameArg = args[0];\n if (nameArg?.type !== 'Literal' || typeof nameArg.value !== 'string') return;\n if (!isTokenName(nameArg.value)) return;\n\n // Options is the 3rd arg for setCookie(name, value, opts)\n const optsArg = args.length >= 3 ? args[2] : null;\n\n if (!optsArg || optsArg.type !== 'ObjectExpression') {\n context.report({ node, messageId: 'idTokenCookieMissingHttpOnly' });\n return;\n }\n\n if (!hasHttpOnlyTrue(optsArg)) {\n context.report({ node, messageId: 'idTokenCookieMissingHttpOnly' });\n }\n },\n };\n },\n};\n\nexport const firebaseIdTokenCookieFlagsRule = rule;\nexport default rule;\n","const rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Next.js middleware reads auth cookie but never verifies it',\n category: 'security',\n cwe: 'CWE-345',\n owasp: 'A07:2021 Identification and Authentication Failures',\n rationale:\n 'Checking only that an auth cookie is non-empty does not verify the token. An attacker who sets any non-empty cookie value will bypass the guard entirely. The middleware must call verifySessionCookie or verifyIdToken to confirm the token is valid and unexpired.',\n docsUrl: 'https://firebase.google.com/docs/auth/admin/manage-cookies#verify_session_cookies_and_check_permissions',\n recommended: true,\n },\n messages: {\n tokenNotVerified:\n 'Middleware reads the auth cookie but never verifies it. Any non-empty cookie value bypasses the guard. Call adminAuth.verifySessionCookie() or verifyIdToken() before allowing access.',\n },\n schema: [],\n },\n create(context: any) {\n const AUTH_COOKIE_NAMES = /token|session/i;\n const VERIFY_METHOD_NAMES = new Set(['verifySessionCookie', 'verifyIdToken', 'verify']);\n\n let readsCookieWithAuthName = false;\n let hasVerifyCall = false;\n const cookieReadNodes: any[] = [];\n\n function isAuthCookieGet(node: any): boolean {\n // request.cookies.get(\"token\") or similar\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 !== 'get') return false;\n // First arg must be a string literal with a token-like name\n const arg = node.arguments?.[0];\n if (arg?.type !== 'Literal' || typeof arg.value !== 'string') return false;\n return AUTH_COOKIE_NAMES.test(arg.value);\n }\n\n return {\n CallExpression(node: any) {\n if (isAuthCookieGet(node)) {\n readsCookieWithAuthName = true;\n cookieReadNodes.push(node);\n }\n\n // Check for verify calls\n const callee = node.callee;\n if (callee?.type === 'Identifier' && VERIFY_METHOD_NAMES.has(callee.name)) {\n hasVerifyCall = true;\n }\n if (\n callee?.type === 'MemberExpression' &&\n callee.property?.type === 'Identifier' &&\n VERIFY_METHOD_NAMES.has(callee.property.name)\n ) {\n hasVerifyCall = true;\n }\n },\n\n 'Program:exit'() {\n if (readsCookieWithAuthName && !hasVerifyCall) {\n for (const node of cookieReadNodes) {\n context.report({ node, messageId: 'tokenNotVerified' });\n }\n }\n },\n };\n },\n};\n\nexport const firebaseMiddlewareTokenNotVerifiedRule = rule;\nexport default rule;\n","const rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Hardcoded string used as userId in Firestore operations',\n category: 'security',\n cwe: 'CWE-284',\n owasp: 'A01:2021 Broken Access Control',\n rationale:\n 'A hardcoded userId causes all users to share a single Firestore document. The last writer overwrites everyone else\\'s data, and when security rules are tightened the writes are rejected. The userId must always come from the authenticated user object.',\n docsUrl: 'https://firebase.google.com/docs/auth/web/manage-users',\n recommended: true,\n },\n messages: {\n hardcodedUserId:\n 'Hardcoded userId found. All users share this document. Read the userId from the authenticated user: const { user } = useAuth(); user?.uid',\n },\n schema: [],\n },\n create(context: any) {\n const USER_ID_NAMES = new Set(['userId', 'uid', 'userID', 'user_id']);\n\n return {\n VariableDeclarator(node: any) {\n if (node.id?.type !== 'Identifier') return;\n if (!USER_ID_NAMES.has(node.id.name)) return;\n const init = node.init;\n if (!init) return;\n // Flag when init is a plain string literal (not env access, not member expression)\n if (init.type === 'Literal' && typeof init.value === 'string' && init.value.length > 0) {\n context.report({ node, messageId: 'hardcodedUserId' });\n }\n },\n };\n },\n};\n\nexport const firebaseHardcodedUserIdRule = rule;\nexport default rule;\n","const rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'auth/user-not-found error code surfaced to the user enables email enumeration',\n category: 'security',\n cwe: 'CWE-204',\n owasp: 'A07:2021 Identification and Authentication Failures',\n rationale:\n 'Displaying a distinct message for the auth/user-not-found error code reveals whether an email address is registered. Firebase email enumeration protection (default on since September 2023) stops returning this code — making this branch dead code while still being a security risk on older projects.',\n docsUrl: 'https://firebase.google.com/docs/auth/web/password-auth#enumeration-protection',\n recommended: true,\n },\n messages: {\n userNotFoundDisclosure:\n 'Checking for auth/user-not-found exposes whether an email is registered (user enumeration). Show the same generic message for all auth errors.',\n },\n schema: [],\n },\n create(context: any) {\n function isErrorCode(n: any): boolean {\n return (\n n?.type === 'MemberExpression' &&\n !n.computed &&\n n.property?.type === 'Identifier' &&\n n.property.name === 'code'\n );\n }\n\n function isUserNotFoundLiteral(n: any): boolean {\n return n?.type === 'Literal' && n.value === 'auth/user-not-found';\n }\n\n return {\n BinaryExpression(node: any) {\n if (node.operator !== '===' && node.operator !== '==' && node.operator !== '!==' && node.operator !== '!=') return;\n if (\n (isErrorCode(node.left) && isUserNotFoundLiteral(node.right)) ||\n (isErrorCode(node.right) && isUserNotFoundLiteral(node.left))\n ) {\n context.report({ node, messageId: 'userNotFoundDisclosure' });\n }\n },\n\n SwitchCase(node: any) {\n if (isUserNotFoundLiteral(node.test)) {\n context.report({ node, messageId: 'userNotFoundDisclosure' });\n }\n },\n };\n },\n};\n\nexport const firebaseAuthUserNotFoundDisclosureRule = rule;\nexport default rule;\n","import { namedImportsFrom } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'createUserWithEmailAndPassword called without verifying password matches confirmPassword',\n category: 'correctness',\n rationale:\n 'If confirmPassword is collected but never compared to password before account creation, users who mistype their password will successfully create an account they cannot log in to. Always compare password === confirmPassword and bail early on mismatch.',\n docsUrl: 'https://firebase.google.com/docs/auth/web/password-auth',\n recommended: true,\n },\n messages: {\n passwordConfirmNotChecked:\n 'createUserWithEmailAndPassword is called without verifying password === confirmPassword. Users who mistype their password will create an account they cannot log in to.',\n },\n schema: [],\n },\n create(context: any) {\n let createUserLocalName: string | undefined;\n let hasConfirmPasswordIdentifier = false;\n let hasPasswordComparison = false;\n const createUserCalls: any[] = [];\n\n return {\n ImportDeclaration(node: any) {\n const imports = namedImportsFrom(node, 'firebase/auth');\n if (imports.has('createUserWithEmailAndPassword')) {\n createUserLocalName = imports.get('createUserWithEmailAndPassword');\n }\n },\n\n Identifier(node: any) {\n if (node.name === 'confirmPassword') {\n hasConfirmPasswordIdentifier = true;\n }\n },\n\n BinaryExpression(node: any) {\n if (node.operator !== '===' && node.operator !== '==' && node.operator !== '!==' && node.operator !== '!=') return;\n const mentionsConfirm = (n: any) =>\n n?.type === 'Identifier' && n.name === 'confirmPassword';\n if (mentionsConfirm(node.left) || mentionsConfirm(node.right)) {\n hasPasswordComparison = true;\n }\n },\n\n CallExpression(node: any) {\n if (!createUserLocalName) return;\n if (node.callee?.type === 'Identifier' && node.callee.name === createUserLocalName) {\n createUserCalls.push(node);\n }\n },\n\n 'Program:exit'() {\n if (!createUserLocalName) return;\n if (createUserCalls.length === 0) return;\n if (!hasConfirmPasswordIdentifier) return;\n if (hasPasswordComparison) return;\n for (const call of createUserCalls) {\n context.report({ node: call, messageId: 'passwordConfirmNotChecked' });\n }\n },\n };\n },\n};\n\nexport const firebaseSignupPasswordConfirmRule = rule;\nexport default rule;\n","const rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Firestore array field updated with read-modify-write spread/filter instead of arrayUnion/arrayRemove',\n category: 'correctness',\n rationale:\n 'Spreading an array or using filter() inside updateDoc() performs a non-atomic read-modify-write that loses concurrent updates. Firestore provides arrayUnion() and arrayRemove() specifically for atomic array updates that do not require reading the document first.',\n docsUrl: 'https://firebase.google.com/docs/firestore/manage-data/add-data#update_elements_in_an_array',\n recommended: true,\n },\n messages: {\n useArrayUnionRemove:\n 'Firestore array updated with read-modify-write spread/filter. Use arrayUnion() or arrayRemove() for atomic updates that do not require reading the document first.',\n },\n schema: [],\n },\n create(context: any) {\n function hasSpreadOrFilterValue(obj: any): boolean {\n if (obj?.type !== 'ObjectExpression') return false;\n for (const prop of obj.properties ?? []) {\n if (prop?.type !== 'Property') continue;\n const val = prop.value;\n // [...existing, newItem]\n if (val?.type === 'ArrayExpression') {\n if ((val.elements ?? []).some((el: any) => el?.type === 'SpreadElement')) {\n return true;\n }\n }\n // existingArray.filter(...)\n if (\n val?.type === 'CallExpression' &&\n val.callee?.type === 'MemberExpression' &&\n val.callee.property?.type === 'Identifier' &&\n val.callee.property.name === 'filter'\n ) {\n return true;\n }\n }\n return false;\n }\n\n return {\n CallExpression(node: any) {\n const callee = node.callee;\n if (callee?.type !== 'Identifier' || callee.name !== 'updateDoc') return;\n const args = node.arguments ?? [];\n if (args.length < 2) return;\n const payload = args[1];\n if (hasSpreadOrFilterValue(payload)) {\n context.report({ node, messageId: 'useArrayUnionRemove' });\n }\n },\n };\n },\n};\n\nexport const firebaseUseArrayUnionRemoveRule = rule;\nexport default rule;\n","import { namedImportsFrom } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'initializeApp called without checking getApps() first — risk of duplicate-app crash',\n category: 'correctness',\n rationale:\n 'Calling initializeApp() when the default app already exists throws \"Firebase App named [DEFAULT] already exists\". Always guard with getApps().length to make initialization idempotent across hot reloads and server-side rendering.',\n docsUrl: 'https://firebase.google.com/docs/projects/multiprojects',\n recommended: true,\n },\n messages: {\n duplicateInitializeApp:\n 'initializeApp() called without checking getApps() first. Calling it twice throws \"Firebase App already exists\". Use: getApps().length ? getApp() : initializeApp(config)',\n },\n schema: [],\n },\n create(context: any) {\n let initializeAppLocalName: string | undefined;\n let hasGetAppsCall = false;\n const initializeAppCalls: any[] = [];\n\n const FIREBASE_APP_SOURCES = new Set(['firebase/app', 'firebase-admin/app', 'firebase-admin']);\n\n return {\n ImportDeclaration(node: any) {\n for (const src of FIREBASE_APP_SOURCES) {\n const imports = namedImportsFrom(node, src);\n if (imports.has('initializeApp')) {\n initializeAppLocalName = imports.get('initializeApp');\n }\n }\n },\n\n CallExpression(node: any) {\n const callee = node.callee;\n if (callee?.type !== 'Identifier') return;\n\n if (initializeAppLocalName && callee.name === initializeAppLocalName) {\n initializeAppCalls.push(node);\n }\n\n if (callee.name === 'getApps') {\n hasGetAppsCall = true;\n }\n },\n\n 'Program:exit'() {\n if (hasGetAppsCall) return;\n for (const call of initializeAppCalls) {\n context.report({ node: call, messageId: 'duplicateInitializeApp' });\n }\n },\n };\n },\n};\n\nexport const firebaseDuplicateInitializeAppRule = rule;\nexport default rule;\n","import { someDescendant } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'throw inside async onSnapshot callback creates an unhandled promise rejection',\n category: 'reliability',\n rationale:\n 'onSnapshot does not handle Promise rejections from its callback. A throw inside an async callback becomes an unhandled rejection, silently terminating the listener and leaving the UI in a broken state with no error feedback.',\n docsUrl: 'https://firebase.google.com/docs/firestore/query-data/listen#handle_listen_errors',\n recommended: true,\n },\n messages: {\n asyncThrowInSnapshot:\n 'throw inside an async onSnapshot callback creates an unhandled promise rejection. The listener silently stops. Use return with error logging or the onSnapshot error callback instead.',\n },\n schema: [],\n },\n create(context: any) {\n function isAsyncFn(node: any): boolean {\n return (\n (node?.type === 'ArrowFunctionExpression' || node?.type === 'FunctionExpression') &&\n node.async === true\n );\n }\n\n function hasDirectThrow(fnNode: any): boolean {\n if (!fnNode?.body) return false;\n // Walk body but don't enter nested function boundaries\n function visit(n: any, depth: number): boolean {\n if (!n || typeof n !== 'object') return false;\n if (Array.isArray(n)) return n.some((item) => visit(item, depth));\n if (typeof n.type !== 'string') return false;\n // Don't descend into nested function definitions\n if (\n depth > 0 &&\n (n.type === 'FunctionDeclaration' ||\n n.type === 'FunctionExpression' ||\n n.type === 'ArrowFunctionExpression')\n ) {\n return false;\n }\n if (n.type === 'ThrowStatement') return true;\n for (const key of Object.keys(n)) {\n if (key === 'parent' || key === 'loc' || key === 'range' || key === 'type') continue;\n if (visit(n[key], depth + 1)) return true;\n }\n return false;\n }\n return visit(fnNode.body, 0);\n }\n\n return {\n CallExpression(node: any) {\n const callee = node.callee;\n if (callee?.type !== 'Identifier' || callee.name !== 'onSnapshot') return;\n\n for (const arg of node.arguments ?? []) {\n if (!isAsyncFn(arg)) continue;\n if (hasDirectThrow(arg)) {\n context.report({ node: arg, messageId: 'asyncThrowInSnapshot' });\n }\n }\n },\n };\n },\n};\n\nexport const firebaseOnSnapshotAsyncThrowRule = rule;\nexport default rule;\n","const rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'onSnapshot called without an error callback — Firestore permission errors silently stop the listener',\n category: 'reliability',\n rationale:\n 'When Firestore denies a read, the listener silently stops emitting snapshots with no error state set or user feedback. Always provide a third argument error callback to onSnapshot so permission denials and connection drops are surfaced.',\n docsUrl: 'https://firebase.google.com/docs/firestore/query-data/listen#handle_listen_errors',\n recommended: true,\n },\n messages: {\n missingErrorCallback:\n 'onSnapshot called without an error callback. Firestore permission errors will silently stop the listener with no user feedback. Add an error callback: onSnapshot(ref, successFn, errorFn).',\n },\n schema: [],\n },\n create(context: any) {\n function isFunctionNode(n: any): boolean {\n return n?.type === 'ArrowFunctionExpression' || n?.type === 'FunctionExpression';\n }\n\n function isOptionsObject(n: any): boolean {\n return n?.type === 'ObjectExpression';\n }\n\n return {\n CallExpression(node: any) {\n const callee = node.callee;\n if (callee?.type !== 'Identifier' || callee.name !== 'onSnapshot') return;\n\n const args = node.arguments ?? [];\n\n // onSnapshot(ref, callback) — exactly 2 args, second is a function\n if (args.length === 2 && isFunctionNode(args[1])) {\n context.report({ node, messageId: 'missingErrorCallback' });\n return;\n }\n\n // onSnapshot(ref, options, callback) — 3 args, 2nd is options object, 3rd is a function but no 4th error cb\n if (args.length === 3 && isOptionsObject(args[1]) && isFunctionNode(args[2])) {\n context.report({ node, messageId: 'missingErrorCallback' });\n }\n },\n };\n },\n};\n\nexport const firebaseOnSnapshotMissingErrorCallbackRule = rule;\nexport default rule;\n","import { someDescendant } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Firestore write includes editor.getJSON() without a document size guard',\n category: 'reliability',\n rationale:\n 'Firestore documents have a 1 MiB limit. When a rich-text editor stores base64 images inline, a single paste can push the document over the limit. The write silently fails with INVALID_ARGUMENT. Always check document size before calling updateDoc/setDoc when the payload includes editor JSON.',\n docsUrl: 'https://firebase.google.com/docs/firestore/quotas#limits',\n recommended: true,\n },\n messages: {\n missingDocumentSizeGuard:\n 'Firestore write includes editor.getJSON() without a document size check. Base64 images can exceed the 1 MiB Firestore limit, silently failing the write. Add a Blob size guard before calling updateDoc/setDoc.',\n },\n schema: [],\n },\n create(context: any) {\n const WRITE_FNS = new Set(['updateDoc', 'setDoc']);\n\n const flagCandidates: any[] = [];\n let hasBlobCheck = false;\n\n function containsGetJson(args: any[]): boolean {\n return args.some((arg) =>\n someDescendant(arg, (n) => {\n if (n?.type !== 'CallExpression') return false;\n const callee = n.callee;\n return (\n callee?.type === 'MemberExpression' &&\n callee.property?.type === 'Identifier' &&\n callee.property.name === 'getJSON'\n );\n }),\n );\n }\n\n return {\n CallExpression(node: any) {\n const callee = node.callee;\n if (callee?.type === 'Identifier' && WRITE_FNS.has(callee.name)) {\n if (containsGetJson(node.arguments ?? [])) {\n flagCandidates.push(node);\n }\n }\n },\n\n NewExpression(node: any) {\n if (node.callee?.type === 'Identifier' && node.callee.name === 'Blob') {\n hasBlobCheck = true;\n }\n },\n\n 'Program:exit'() {\n if (hasBlobCheck) return;\n for (const node of flagCandidates) {\n context.report({ node, messageId: 'missingDocumentSizeGuard' });\n }\n },\n };\n },\n};\n\nexport const firebaseFirestoreDocumentSizeGuardRule = rule;\nexport default rule;\n","const rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'new Date() used for Firestore timestamp instead of Timestamp.now() or serverTimestamp()',\n category: 'correctness',\n rationale:\n 'While Firestore auto-converts Date objects on write, mixing new Date() with Timestamp.now() creates type inconsistencies. Firestore security rules that compare request.resource.data.createdAt against request.time expect a Timestamp on both sides; a bare Date object can cause silent rule evaluation failures.',\n docsUrl: 'https://firebase.google.com/docs/reference/js/firestore_.timestamp',\n recommended: true,\n },\n messages: {\n useTimestampNow:\n 'Use Timestamp.now() or serverTimestamp() instead of new Date() for Firestore timestamp fields. new Date() creates type inconsistencies with security rules that compare against request.time.',\n },\n schema: [],\n },\n create(context: any) {\n let importsFromFirestore = false;\n\n return {\n ImportDeclaration(node: any) {\n const src = node.source?.value;\n if (typeof src === 'string' && (src.startsWith('firebase/') || src === 'firebase-admin/firestore')) {\n importsFromFirestore = true;\n }\n },\n\n NewExpression(node: any) {\n if (!importsFromFirestore) return;\n if (node.callee?.type !== 'Identifier' || node.callee.name !== 'Date') return;\n // Only flag new Date() with no arguments — new Date(value) is a conversion, not a \"now\" timestamp\n if ((node.arguments ?? []).length !== 0) return;\n context.report({ node, messageId: 'useTimestampNow' });\n },\n };\n },\n};\n\nexport const firebaseUseTimestampNowRule = 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 * tiptap-upload-validate-fn-void (security)\n *\n * Flags two patterns:\n * (a) An interface/type with a property `validateFn` typed as returning `void`\n * when it also has an `onUpload` property — the void return type means the\n * caller can never act on the validation result.\n * (b) A bare ExpressionStatement that calls `validateFn(...)` or `validateFn?.(...)`,\n * discarding the return value silently.\n */\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'validateFn must return boolean so callers can act on the result',\n category: 'security',\n cwe: 'CWE-20',\n owasp: 'API3:2023 Broken Object Property Level Authorization',\n rationale:\n 'When validateFn is typed as (file: File) => void, the return value is always discarded. A consumer that returns false to reject an oversized or wrong-type file will have that rejection silently ignored — the upload proceeds regardless. Changing the return type to boolean and guarding with if (validateFn && !validateFn(file)) return; ensures validation actually blocks uploads.',\n docsUrl: 'https://tiptap.dev/docs/editor/extensions/custom-extensions/node-views',\n recommended: true,\n },\n messages: {\n validateFnVoid:\n 'validateFn return value is discarded. Change the return type to boolean and guard the call: if (validateFn && !validateFn(file)) return;',\n },\n schema: [],\n },\n create(context: any) {\n let importsTiptap = false;\n\n function isVoidReturnType(typeAnnotation: any): boolean {\n if (!typeAnnotation) return false;\n // TSTypeAnnotation wraps the actual type\n const t = typeAnnotation.typeAnnotation ?? typeAnnotation;\n // (file: File) => void → TSFunctionType with returnType TSVoidKeyword\n if (t?.type === 'TSFunctionType') {\n const ret = t.returnType?.typeAnnotation ?? t.returnType;\n return ret?.type === 'TSVoidKeyword';\n }\n // TSTypeReference or similar wrapping\n return false;\n }\n\n function hasProperty(members: any[], name: string): boolean {\n return members?.some(\n (m: any) =>\n (m?.key?.type === 'Identifier' && m.key.name === name) ||\n (m?.key?.type === 'Literal' && m.key.value === name),\n ) ?? false;\n }\n\n return {\n ImportDeclaration(node: any) {\n const src: string = node?.source?.value ?? '';\n if (src.startsWith('@tiptap/')) importsTiptap = true;\n },\n\n // Pattern (a): interface / type with validateFn: (...) => void + onUpload\n TSInterfaceDeclaration(node: any) {\n const members = node?.body?.body ?? [];\n if (!hasProperty(members, 'onUpload')) return;\n for (const member of members) {\n const name =\n member?.key?.type === 'Identifier'\n ? member.key.name\n : member?.key?.type === 'Literal'\n ? member.key.value\n : null;\n if (name !== 'validateFn') continue;\n const typeAnno = member.typeAnnotation;\n if (isVoidReturnType(typeAnno)) {\n context.report({ node: member, messageId: 'validateFnVoid' });\n }\n }\n },\n\n // Pattern (b): validateFn?.() or validateFn() used as a bare statement\n ExpressionStatement(node: any) {\n const expr = node.expression;\n // Unwrap optional chain: validateFn?.(file) → ChainExpression → CallExpression\n const call =\n expr?.type === 'CallExpression'\n ? expr\n : expr?.type === 'ChainExpression' && expr.expression?.type === 'CallExpression'\n ? expr.expression\n : null;\n if (!call) return;\n\n const callee = call.callee;\n // callee may be Identifier(validateFn) or MemberExpression(...).validateFn\n const calleeName =\n callee?.type === 'Identifier'\n ? callee.name\n : callee?.type === 'MemberExpression' && callee.property?.type === 'Identifier'\n ? callee.property.name\n : null;\n if (calleeName !== 'validateFn') return;\n\n context.report({ node, messageId: 'validateFnVoid' });\n },\n };\n },\n};\n\nexport const tiptapUploadValidateFnVoidRule = rule;\nexport default rule;\n","/**\n * tiptap-script-src-hardcoded-api-key (security)\n *\n * Detects when script.src is assigned a string literal (plain or template)\n * that contains `apiKey=` with a hardcoded value instead of an env variable.\n *\n * Flags:\n * script.src = \"https://cdn.example.com/calc.js?apiKey=abc123\";\n * script.src = `https://cdn.example.com/calc.js?apiKey=${LITERAL}`;\n *\n * Does NOT flag:\n * script.src = `https://cdn.example.com/calc.js?apiKey=${process.env.KEY}`;\n */\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'script.src must not contain a hardcoded API key',\n category: 'security',\n cwe: 'CWE-798',\n owasp: 'API8:2023 Security Misconfiguration',\n rationale:\n 'Hardcoding an API key directly in a script URL string commits the credential to version control and ships it in the client bundle. The key is trivially visible to anyone who views the page source. Read the key from an environment variable at runtime so it can be rotated without a code change and kept out of the repository.',\n docsUrl: 'https://tiptap.dev/docs/editor/extensions/custom-extensions/node-views',\n recommended: true,\n },\n messages: {\n hardcodedApiKey:\n 'script.src contains a hardcoded API key. Read the key from an environment variable instead.',\n },\n schema: [],\n },\n create(context: any) {\n function isSrcAssignment(node: any): boolean {\n return (\n node?.type === 'AssignmentExpression' &&\n node.left?.type === 'MemberExpression' &&\n node.left.property?.type === 'Identifier' &&\n node.left.property.name === 'src'\n );\n }\n\n function isEnvAccess(node: any): boolean {\n // process.env.SOMETHING or process.env['SOMETHING']\n if (node?.type !== 'MemberExpression') return false;\n const obj = node.object;\n return (\n obj?.type === 'MemberExpression' &&\n obj.object?.type === 'Identifier' &&\n obj.object.name === 'process' &&\n obj.property?.type === 'Identifier' &&\n obj.property.name === 'env'\n );\n }\n\n return {\n AssignmentExpression(node: any) {\n if (!isSrcAssignment(node)) return;\n const right = node.right;\n\n // Plain string literal with apiKey= in it\n if (right?.type === 'Literal' && typeof right.value === 'string') {\n if (right.value.includes('apiKey=')) {\n context.report({ node, messageId: 'hardcodedApiKey' });\n }\n return;\n }\n\n // Template literal: `...apiKey=...` where the value after apiKey= is a literal expression\n if (right?.type === 'TemplateLiteral') {\n const quasis: any[] = right.quasis ?? [];\n const expressions: any[] = right.expressions ?? [];\n\n for (let i = 0; i < quasis.length; i++) {\n const cooked: string = quasis[i]?.value?.cooked ?? '';\n if (cooked.includes('apiKey=')) {\n // The key follows this quasi — check if the next expression is env access\n const nextExpr = expressions[i];\n if (!nextExpr) {\n // apiKey= is in a tail quasi with no following expression → hardcoded\n context.report({ node, messageId: 'hardcodedApiKey' });\n return;\n }\n if (!isEnvAccess(nextExpr)) {\n // Expression after apiKey= is not process.env.* → hardcoded\n context.report({ node, messageId: 'hardcodedApiKey' });\n return;\n }\n }\n }\n }\n },\n };\n },\n};\n\nexport const tiptapScriptSrcHardcodedApiKeyRule = rule;\nexport default rule;\n","/**\n * tiptap-dynamic-script-no-sri (security)\n *\n * Detects when a script element created with document.createElement('script')\n * is appended to the DOM without setting an integrity (SRI) attribute.\n *\n * Flags:\n * const script = document.createElement('script');\n * document.body.appendChild(script); // no integrity set\n *\n * Does NOT flag:\n * script.setAttribute('integrity', 'sha384-...');\n * document.body.appendChild(script); // integrity was set\n */\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Dynamically injected script elements must include an SRI integrity attribute',\n category: 'security',\n cwe: 'CWE-829',\n owasp: 'API8:2023 Security Misconfiguration',\n rationale:\n 'A script element injected without an integrity attribute will execute whatever the CDN returns, including malicious content if the CDN is compromised. Adding a Subresource Integrity hash (script.setAttribute(\"integrity\", \"sha384-...\")) lets the browser verify the fetched script matches the expected bytes before executing it.',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity',\n recommended: true,\n },\n messages: {\n missingIntegrity:\n 'Dynamically created script element is appended without an integrity (SRI) attribute. Add script.setAttribute(\"integrity\", \"sha384-...\") before appending.',\n },\n schema: [],\n },\n create(context: any) {\n // Map from variable name → { createNode, appendNode, hasIntegrity }\n const scriptVars = new Map<string, { createNode: any; appendNode: any | null; hasIntegrity: boolean }>();\n\n function isCreateScriptCall(node: any): string | null {\n // document.createElement('script') stored in a variable\n if (node?.type !== 'CallExpression') return null;\n const callee = node.callee;\n if (callee?.type !== 'MemberExpression') return null;\n if (callee.property?.name !== 'createElement') return null;\n const arg = node.arguments?.[0];\n if (arg?.type !== 'Literal' || arg.value !== 'script') return null;\n return 'script';\n }\n\n function getVarNameFromDeclarator(node: any): string | null {\n if (node?.type === 'VariableDeclarator' && node.id?.type === 'Identifier') {\n return node.id.name;\n }\n return null;\n }\n\n function isIntegritySet(node: any, varName: string): boolean {\n // script.setAttribute('integrity', ...) or script['setAttribute']('integrity', ...)\n if (node?.type === 'CallExpression') {\n const callee = node.callee;\n if (\n callee?.type === 'MemberExpression' &&\n callee.object?.type === 'Identifier' &&\n callee.object.name === varName &&\n (callee.property?.name === 'setAttribute' || callee.property?.value === 'setAttribute')\n ) {\n const firstArg = node.arguments?.[0];\n if (firstArg?.type === 'Literal' && firstArg.value === 'integrity') return true;\n }\n }\n // script.integrity = '...'\n if (\n node?.type === 'AssignmentExpression' &&\n node.left?.type === 'MemberExpression' &&\n node.left.object?.type === 'Identifier' &&\n node.left.object.name === varName &&\n node.left.property?.name === 'integrity'\n ) {\n return true;\n }\n return false;\n }\n\n function isAppendCall(node: any, varName: string): boolean {\n // *.appendChild(varName) or *.append(varName) or *.insertBefore(varName, ...)\n if (node?.type !== 'CallExpression') return false;\n const callee = node.callee;\n if (callee?.type !== 'MemberExpression') return false;\n const methodName = callee.property?.name;\n if (!['appendChild', 'append', 'insertBefore', 'prepend'].includes(methodName)) return false;\n const firstArg = node.arguments?.[0];\n return firstArg?.type === 'Identifier' && firstArg.name === varName;\n }\n\n return {\n VariableDeclarator(node: any) {\n if (node.init && isCreateScriptCall(node.init)) {\n const name = getVarNameFromDeclarator(node);\n if (name) {\n scriptVars.set(name, { createNode: node, appendNode: null, hasIntegrity: false });\n }\n }\n },\n\n ExpressionStatement(node: any) {\n const expr = node.expression;\n if (!expr) return;\n\n for (const [varName, info] of scriptVars) {\n if (isIntegritySet(expr, varName)) {\n info.hasIntegrity = true;\n }\n if (isAppendCall(expr, varName) && !info.appendNode) {\n info.appendNode = node;\n }\n }\n },\n\n // Also catch assignments: e.g. document.body.innerHTML won't appear here,\n // but handle AssignmentExpression for integrity\n AssignmentExpression(node: any) {\n for (const [varName, info] of scriptVars) {\n if (isIntegritySet(node, varName)) {\n info.hasIntegrity = true;\n }\n }\n },\n\n 'Program:exit'() {\n for (const [, info] of scriptVars) {\n if (info.appendNode && !info.hasIntegrity) {\n context.report({ node: info.appendNode, messageId: 'missingIntegrity' });\n }\n }\n },\n };\n },\n};\n\nexport const tiptapDynamicScriptNoSriRule = rule;\nexport default rule;\n","/**\n * Shared AST helpers for TipTap rules.\n */\n\n/** True if ImportDeclaration source is from @tiptap/* or tiptap-markdown. */\nexport function isTiptapImport(node: any): boolean {\n const src: string = node?.source?.value ?? '';\n return src.startsWith('@tiptap/') || src === 'tiptap-markdown';\n}\n\n/**\n * True for CallExpression matching `Node.create(...)` or `Mark.create(...)`.\n * Handles both `Node.create` and renamed imports like `TiptapNode.create`.\n */\nexport function isNodeOrMarkCreate(node: any): boolean {\n if (node?.type !== 'CallExpression') return false;\n const callee = node.callee;\n if (callee?.type !== 'MemberExpression') return false;\n const prop = callee.property;\n return prop?.type === 'Identifier' && prop.name === 'create';\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 start offset of a node. */\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 end offset of a node. */\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` fully contains `inner`'s start. */\nexport function contains(outer: any, inner: any): boolean {\n const s = startOffset(inner);\n return s >= startOffset(outer) && s <= endOffset(outer);\n}\n\n/**\n * Walks an AST node depth-first, calling `visit` for each node.\n * Stops descending into a child if `visit` returns false.\n */\nexport function walk(node: any, visit: (n: any) => boolean | void): void {\n if (!node || typeof node !== 'object') return;\n const result = visit(node);\n if (result === false) return;\n for (const key of Object.keys(node)) {\n if (key === 'parent') continue;\n const child = node[key];\n if (Array.isArray(child)) {\n for (const item of child) walk(item, visit);\n } else if (child && typeof child === 'object' && child.type) {\n walk(child, visit);\n }\n }\n}\n\n/** Returns the string value of a Literal or TemplateLiteral with no expressions. */\nexport function getLiteralString(node: any): string | null {\n if (node?.type === 'Literal' && typeof node.value === 'string') return node.value;\n if (node?.type === 'TemplateLiteral' && node.expressions?.length === 0) {\n return node.quasis?.[0]?.value?.cooked ?? null;\n }\n return null;\n}\n","/**\n * tiptap-addAttributes-missing-renderHTML (correctness)\n *\n * Detects TipTap node/mark attribute descriptors that define `parseHTML` but\n * not `renderHTML`. Without `renderHTML`, TipTap serializes the attribute\n * using the plain attribute name, while `parseHTML` reads from `data-*`.\n * The mismatch silently drops attribute values on HTML round-trips.\n */\nimport { findProperty, walk } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'TipTap addAttributes descriptors with parseHTML must also define renderHTML',\n category: 'correctness',\n rationale:\n 'When an attribute defines parseHTML: (el) => el.getAttribute(\"data-label\") but no renderHTML, TipTap emits the attribute as a plain HTML attribute (label=\"...\") instead of data-label=\"...\". On re-parse, getAttribute(\"data-label\") returns null and the value falls back to the default, silently discarding any customization across HTML export/import cycles.',\n docsUrl: 'https://tiptap.dev/docs/editor/extensions/custom-extensions/create-new/node#attributes',\n recommended: true,\n },\n messages: {\n missingRenderHTML:\n 'Attribute defines parseHTML but no renderHTML. TipTap will serialize this attribute with the default name, breaking the HTML round-trip. Add renderHTML: (attrs) => ({ \"data-<name>\": attrs.<name> }).',\n },\n schema: [],\n },\n create(context: any) {\n function checkAddAttributesReturn(returnObj: any): void {\n if (returnObj?.type !== 'ObjectExpression') return;\n for (const prop of returnObj.properties ?? []) {\n if (prop?.type !== 'Property') continue;\n const val = prop.value;\n if (val?.type !== 'ObjectExpression') continue;\n // Check if descriptor has parseHTML but not renderHTML\n if (findProperty(val, 'parseHTML') && !findProperty(val, 'renderHTML')) {\n context.report({ node: val, messageId: 'missingRenderHTML' });\n }\n }\n }\n\n function checkAddAttributesFunction(fn: any): void {\n // Find ReturnStatement(s) and check the returned object\n walk(fn, (node: any) => {\n if (node?.type === 'ReturnStatement' && node.argument) {\n checkAddAttributesReturn(node.argument);\n }\n });\n }\n\n return {\n // Handles: addAttributes() { return { ... } } as method shorthand\n // and addAttributes: function() { } / addAttributes: () => { }\n Property(node: any) {\n const keyName =\n node.key?.type === 'Identifier'\n ? node.key.name\n : node.key?.type === 'Literal'\n ? node.key.value\n : null;\n if (keyName !== 'addAttributes') return;\n\n const val = node.value;\n if (!val) return;\n\n if (\n val.type === 'FunctionExpression' ||\n val.type === 'ArrowFunctionExpression'\n ) {\n // Arrow with expression body: addAttributes: () => ({ ... })\n if (val.body?.type === 'ObjectExpression') {\n checkAddAttributesReturn(val.body);\n } else {\n checkAddAttributesFunction(val.body);\n }\n }\n },\n };\n },\n};\n\nexport const tiptapAddAttributesMissingRenderHTMLRule = rule;\nexport default rule;\n","/**\n * tiptap-appendTransaction-add-to-history (correctness)\n *\n * Detects `appendTransaction` callbacks that mutate the transaction without\n * calling `tr.setMeta(\"addToHistory\", false)`. Without this annotation,\n * auto-corrections end up in the undo history and fight user undo.\n */\nimport { walk } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'appendTransaction mutations must include tr.setMeta(\"addToHistory\", false)',\n category: 'correctness',\n rationale:\n 'ProseMirror records every transaction dispatched by appendTransaction into the undo history unless it is annotated with setMeta(\"addToHistory\", false). When an auto-correction (e.g. inserting a space into an empty node) is recorded, pressing Ctrl-Z undoes the correction and re-enters the broken state, which the plugin immediately re-corrects — the undo and redo keys fight each other.',\n docsUrl: 'https://prosemirror.net/docs/ref/#state.Transaction.setMeta',\n recommended: true,\n },\n messages: {\n missingAddToHistory:\n 'appendTransaction mutates the transaction without setMeta(\"addToHistory\", false). This pollutes the undo stack. Add tr.setMeta(\"addToHistory\", false) to the transaction.',\n },\n schema: [],\n },\n create(context: any) {\n function hasAddToHistoryMeta(fnBody: any): boolean {\n let found = false;\n walk(fnBody, (node: any) => {\n if (found) return false;\n if (node?.type !== 'CallExpression') return;\n const callee = node.callee;\n if (callee?.type !== 'MemberExpression') return;\n if (callee.property?.name !== 'setMeta') return;\n const firstArg = node.arguments?.[0];\n if (firstArg?.type === 'Literal' && firstArg.value === 'addToHistory') {\n found = true;\n }\n });\n return found;\n }\n\n function hasMutation(fnBody: any): boolean {\n const mutatingMethods = new Set([\n 'insert', 'insertText', 'replace', 'replaceWith', 'replaceRange',\n 'replaceRangeWith', 'delete', 'deleteRange', 'addMark', 'removeMark',\n 'setNodeMarkup', 'setNodeAttribute', 'setDocAttribute',\n ]);\n let found = false;\n walk(fnBody, (node: any) => {\n if (found) return false;\n if (node?.type !== 'CallExpression') return;\n const callee = node.callee;\n if (callee?.type !== 'MemberExpression') return;\n const methodName = callee.property?.name;\n if (methodName && mutatingMethods.has(methodName)) {\n found = true;\n }\n });\n return found;\n }\n\n function checkAppendTransactionFn(fn: any, reportNode: any): void {\n const body = fn?.body;\n if (!body) return;\n if (hasMutation(body) && !hasAddToHistoryMeta(body)) {\n context.report({ node: reportNode, messageId: 'missingAddToHistory' });\n }\n }\n\n return {\n Property(node: any) {\n const keyName =\n node.key?.type === 'Identifier'\n ? node.key.name\n : node.key?.type === 'Literal'\n ? node.key.value\n : null;\n if (keyName !== 'appendTransaction') return;\n\n const val = node.value;\n if (\n val?.type === 'FunctionExpression' ||\n val?.type === 'ArrowFunctionExpression'\n ) {\n checkAppendTransactionFn(val, node);\n }\n },\n };\n },\n};\n\nexport const tiptapAppendTransactionAddToHistoryRule = rule;\nexport default rule;\n","/**\n * tiptap-appendTransaction-full-scan (reliability)\n *\n * Detects `appendTransaction` callbacks that call `doc.descendants(...)` on\n * every transaction without first checking whether the document changed.\n * O(n) per keystroke is avoidable with a simple docChanged guard.\n */\nimport { walk } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'appendTransaction must guard doc.descendants() with a docChanged check',\n category: 'reliability',\n rationale:\n 'doc.descendants() visits every node in the document on every transaction — every keystroke, selection change, and formatting toggle. For documents with many nodes this is O(n) per transaction and causes visible input latency. ProseMirror provides the docChanged flag precisely to avoid this work when the document structure has not changed.',\n docsUrl: 'https://prosemirror.net/docs/ref/#state.PluginSpec.appendTransaction',\n recommended: true,\n },\n messages: {\n fullScanOnEveryTransaction:\n 'appendTransaction calls doc.descendants() on every transaction. Check docChanged first: const docChanged = transactions.some(tr => tr.docChanged); if (!docChanged) return;',\n },\n schema: [],\n },\n create(context: any) {\n function hasDocChangedGuard(fnBody: any): boolean {\n let found = false;\n walk(fnBody, (node: any) => {\n if (found) return false;\n // Look for tr.docChanged or transactions.some(tr => tr.docChanged) or docChanged identifier used as condition\n if (\n node?.type === 'MemberExpression' &&\n node.property?.name === 'docChanged'\n ) {\n found = true;\n return false;\n }\n // Also look for if (!docChanged) return; pattern\n if (\n node?.type === 'Identifier' &&\n node.name === 'docChanged'\n ) {\n found = true;\n return false;\n }\n });\n return found;\n }\n\n function hasDescendantsCall(fnBody: any): boolean {\n let found = false;\n walk(fnBody, (node: any) => {\n if (found) return false;\n if (\n node?.type === 'CallExpression' &&\n node.callee?.type === 'MemberExpression' &&\n node.callee.property?.name === 'descendants'\n ) {\n found = true;\n }\n });\n return found;\n }\n\n function checkAppendTransactionFn(fn: any, reportNode: any): void {\n const body = fn?.body;\n if (!body) return;\n if (hasDescendantsCall(body) && !hasDocChangedGuard(body)) {\n context.report({ node: reportNode, messageId: 'fullScanOnEveryTransaction' });\n }\n }\n\n return {\n Property(node: any) {\n const keyName =\n node.key?.type === 'Identifier'\n ? node.key.name\n : node.key?.type === 'Literal'\n ? node.key.value\n : null;\n if (keyName !== 'appendTransaction') return;\n\n const val = node.value;\n if (\n val?.type === 'FunctionExpression' ||\n val?.type === 'ArrowFunctionExpression'\n ) {\n checkAppendTransactionFn(val, node);\n }\n },\n };\n },\n};\n\nexport const tiptapAppendTransactionFullScanRule = rule;\nexport default rule;\n","/**\n * tiptap-atom-node-wrap-in (correctness)\n *\n * Detects when `wrapIn(nodeName)` is called with the name of a node type that\n * is defined as `atom: true` in the same file. Atom nodes cannot contain\n * content, so wrapIn() always silently returns false — the command appears\n * broken with no error or user feedback.\n */\nimport { walk } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'wrapIn() must not be called with an atom node type',\n category: 'correctness',\n rationale:\n 'Atom nodes have no content model — ProseMirror cannot wrap other nodes inside them. Calling wrapIn(\"atomNode\") always returns false silently, making the command appear broken when triggered on selected text. Use replaceSelectionWith(node.create()) or insertContent() instead.',\n docsUrl: 'https://tiptap.dev/docs/editor/extensions/custom-extensions/create-new/node',\n recommended: true,\n },\n messages: {\n wrapInAtomNode:\n 'wrapIn() is called with an atom node type. Atom nodes cannot contain content, so wrapIn() always silently returns false. Replace the selection instead of wrapping it.',\n },\n schema: [],\n },\n create(context: any) {\n // Collect atom node names defined in this file\n const atomNodeNames = new Set<string>();\n // Collect wrapIn calls with string literal arguments\n const wrapInCalls: Array<{ node: any; name: string }> = [];\n\n function extractNodeName(configObj: any): string | null {\n if (configObj?.type !== 'ObjectExpression') return null;\n const nameProp = configObj.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 const nameVal = nameProp?.value;\n if (nameVal?.type === 'Literal' && typeof nameVal.value === 'string') {\n return nameVal.value;\n }\n return null;\n }\n\n function hasAtomTrue(configObj: any): boolean {\n if (configObj?.type !== 'ObjectExpression') return false;\n return configObj.properties?.some(\n (p: any) =>\n p?.type === 'Property' &&\n ((p.key?.type === 'Identifier' && p.key.name === 'atom') ||\n (p.key?.type === 'Literal' && p.key.value === 'atom')) &&\n p.value?.type === 'Literal' &&\n p.value.value === true,\n ) ?? false;\n }\n\n return {\n CallExpression(node: any) {\n // Detect Node.create({...}) / Mark.create({...}) with atom: true\n if (\n node.callee?.type === 'MemberExpression' &&\n node.callee.property?.name === 'create'\n ) {\n const configArg = node.arguments?.[0];\n if (configArg?.type === 'ObjectExpression' && hasAtomTrue(configArg)) {\n const name = extractNodeName(configArg);\n if (name) atomNodeNames.add(name);\n }\n }\n\n // Detect wrapIn('nodeName') or commands.wrapIn('nodeName')\n const callee = node.callee;\n const isWrapIn =\n (callee?.type === 'Identifier' && callee.name === 'wrapIn') ||\n (callee?.type === 'MemberExpression' && callee.property?.name === 'wrapIn');\n if (isWrapIn) {\n const firstArg = node.arguments?.[0];\n if (firstArg?.type === 'Literal' && typeof firstArg.value === 'string') {\n wrapInCalls.push({ node, name: firstArg.value });\n }\n }\n },\n\n 'Program:exit'() {\n for (const { node, name } of wrapInCalls) {\n if (atomNodeNames.has(name)) {\n context.report({ node, messageId: 'wrapInAtomNode' });\n }\n }\n },\n };\n },\n};\n\nexport const tiptapAtomNodeWrapInRule = rule;\nexport default rule;\n","/**\n * tiptap-twitter-url-regex (integration)\n *\n * Detects regex literals that match `x.com` tweet URLs but omit `twitter.com`.\n * Legacy twitter.com URLs are still valid and resolve correctly.\n */\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Twitter/X URL regex must match both x.com and twitter.com',\n category: 'integration',\n rationale:\n 'Twitter rebranded to X but twitter.com URLs still resolve and embed correctly. A regex that only matches x.com silently rejects all legacy twitter.com links pasted by users. Update the pattern to (x\\\\.com|twitter\\\\.com) so both domains are handled.',\n docsUrl: 'https://tiptap.dev/docs/editor/extensions/nodes',\n recommended: true,\n },\n messages: {\n twitterRegexMissingLegacyDomain:\n 'This regex matches x.com but not twitter.com. Legacy twitter.com URLs are still valid and should be supported. Add (x\\\\.com|twitter\\\\.com) to the pattern.',\n },\n schema: [],\n },\n create(context: any) {\n function checkPattern(pattern: string, node: any): void {\n if (!pattern.includes('x\\\\.com') && !pattern.includes('x.com')) return;\n if (pattern.includes('twitter\\\\.com') || pattern.includes('twitter.com')) return;\n context.report({ node, messageId: 'twitterRegexMissingLegacyDomain' });\n }\n\n return {\n Literal(node: any) {\n // Regex literal\n if (node.regex?.pattern) {\n checkPattern(node.regex.pattern, node);\n }\n },\n\n NewExpression(node: any) {\n // new RegExp('pattern')\n if (\n node.callee?.type === 'Identifier' &&\n node.callee.name === 'RegExp'\n ) {\n const firstArg = node.arguments?.[0];\n if (firstArg?.type === 'Literal' && typeof firstArg.value === 'string') {\n checkPattern(firstArg.value, node);\n }\n }\n },\n };\n },\n};\n\nexport const tiptapTwitterUrlRegexRule = rule;\nexport default rule;\n","/**\n * tiptap-drop-handler-pos-precedence (correctness)\n *\n * Detects the operator-precedence bug `x ?? 0 - 1` which parses as\n * `x ?? (0 - 1)` = `x ?? -1` because `-` has higher precedence than `??`.\n *\n * The intended expression is `(x ?? 0) - 1`.\n *\n * AST shape of `x ?? 0 - 1`:\n * LogicalExpression(??)\n * left: x\n * right: BinaryExpression(-)\n * left: Literal(0)\n * right: Literal(1)\n */\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'x ?? 0 - 1 is parsed as x ?? (0 - 1) = x ?? -1 due to operator precedence',\n category: 'correctness',\n rationale:\n 'The nullish coalescing operator (??) has lower precedence than arithmetic operators. Writing `pos ?? 0 - 1` evaluates as `pos ?? -1`, not `(pos ?? 0) - 1`. When pos is null or undefined, the fallback is -1 instead of the intended -1 offset from 0. In ProseMirror drop handlers this produces a decoration at position -1, which corrupts the placeholder position map and can insert content at the document start.',\n docsUrl: 'https://prosemirror.net/docs/ref/#view.EditorView.posAtCoords',\n recommended: true,\n },\n messages: {\n posNullCoalescePrecedence:\n 'Operator precedence bug: \"x ?? 0 - 1\" is parsed as \"x ?? (0 - 1)\" = \"x ?? -1\". Wrap the intended expression: \"(x ?? 0) - 1\".',\n },\n schema: [],\n },\n create(context: any) {\n return {\n LogicalExpression(node: any) {\n if (node.operator !== '??') return;\n const right = node.right;\n if (\n right?.type === 'BinaryExpression' &&\n right.operator === '-' &&\n right.left?.type === 'Literal' &&\n right.left.value === 0 &&\n right.right?.type === 'Literal' &&\n right.right.value === 1\n ) {\n context.report({ node, messageId: 'posNullCoalescePrecedence' });\n }\n },\n };\n },\n};\n\nexport const tiptapDropHandlerPosPrecedenceRule = rule;\nexport default rule;\n","/**\n * tiptap-prefer-table-kit (integration)\n *\n * Detects when individual TipTap table sub-packages are imported instead of\n * using TableKit from @tiptap/extension-table. Individual imports miss the\n * coordinated configuration and the mergeOrSplit command.\n */\n\nconst INDIVIDUAL_TABLE_PACKAGES = new Set([\n '@tiptap/extension-table-row',\n '@tiptap/extension-table-cell',\n '@tiptap/extension-table-header',\n]);\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Use TableKit from @tiptap/extension-table instead of individual table packages',\n category: 'integration',\n rationale:\n 'Importing table extensions individually from their separate packages bypasses the coordinated wiring that TableKit provides: shared configuration, the mergeOrSplit command, and consistent HTMLAttributes across all table elements. Individual imports also leave TableCell and TableHeader unconfigured by default.',\n docsUrl: 'https://tiptap.dev/docs/editor/extensions/functionality/table-kit',\n recommended: true,\n },\n messages: {\n preferTableKit:\n 'Individual TipTap table extension imported. Use TableKit from @tiptap/extension-table for coordinated configuration and the mergeOrSplit command.',\n },\n schema: [],\n },\n create(context: any) {\n const individualImports: any[] = [];\n\n return {\n ImportDeclaration(node: any) {\n const src: string = node?.source?.value ?? '';\n if (INDIVIDUAL_TABLE_PACKAGES.has(src)) {\n individualImports.push(node);\n }\n },\n\n 'Program:exit'() {\n if (individualImports.length >= 2) {\n for (const node of individualImports) {\n context.report({ node, messageId: 'preferTableKit' });\n }\n }\n },\n };\n },\n};\n\nexport const tiptapPreferTableKitRule = rule;\nexport default rule;\n","/**\n * tiptap-tiptap-markdown-missing-node-spec (integration)\n *\n * Detects when a file imports both @tiptap/core and tiptap-markdown but\n * contains a Node.create() / Mark.create() call with no markdown serialization\n * spec (no MarkdownNodeSpec reference and no \"markdown\" property key).\n */\nimport { walk } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'TipTap nodes used with tiptap-markdown must define a markdown serialization spec',\n category: 'integration',\n rationale:\n 'When tiptap-markdown serializes a document, nodes without a markdown spec are silently dropped or emitted as empty strings. Custom node types must register a serialize/parse pair via MarkdownNodeSpec (in addStorage or addOptions) so content survives markdown export/import cycles.',\n docsUrl: 'https://github.com/ueberdosis/tiptap-markdown',\n recommended: true,\n },\n messages: {\n missingMarkdownNodeSpec:\n 'This TipTap node is used alongside tiptap-markdown but defines no markdown serialization. Nodes without a markdown spec are silently dropped on export. Add a MarkdownNodeSpec to addStorage or addOptions.',\n },\n schema: [],\n },\n create(context: any) {\n let importsTiptapCore = false;\n let importsTiptapMarkdown = false;\n const nodeCreateCalls: any[] = [];\n\n function hasMarkdownSpec(configObj: any): boolean {\n if (configObj?.type !== 'ObjectExpression') return false;\n // Check for any property key named \"markdown\" anywhere in the config\n let found = false;\n walk(configObj, (node: any) => {\n if (found) return false;\n if (node?.type === 'Property') {\n const keyName =\n node.key?.type === 'Identifier'\n ? node.key.name\n : node.key?.type === 'Literal'\n ? String(node.key.value)\n : null;\n if (keyName === 'markdown') {\n found = true;\n return false;\n }\n }\n // Also look for MarkdownNodeSpec identifier reference\n if (node?.type === 'Identifier' && node.name === 'MarkdownNodeSpec') {\n found = true;\n return false;\n }\n });\n return found;\n }\n\n return {\n ImportDeclaration(node: any) {\n const src: string = node?.source?.value ?? '';\n if (src.startsWith('@tiptap/core')) importsTiptapCore = true;\n if (src === 'tiptap-markdown' || src === '@tiptap/extension-markdown') {\n importsTiptapMarkdown = true;\n }\n },\n\n CallExpression(node: any) {\n if (\n node.callee?.type === 'MemberExpression' &&\n node.callee.property?.name === 'create'\n ) {\n const configArg = node.arguments?.[0];\n if (configArg?.type === 'ObjectExpression') {\n nodeCreateCalls.push({ callNode: node, configObj: configArg });\n }\n }\n },\n\n // Also check for MarkdownNodeSpec at program level\n 'Program:exit'() {\n if (!importsTiptapCore || !importsTiptapMarkdown) return;\n\n for (const { callNode, configObj } of nodeCreateCalls) {\n if (!hasMarkdownSpec(configObj)) {\n context.report({ node: callNode, messageId: 'missingMarkdownNodeSpec' });\n }\n }\n },\n };\n },\n};\n\nexport const tiptapTiptapMarkdownMissingNodeSpecRule = rule;\nexport default rule;\n","/** Shared AST helpers for ElevenLabs provider rules. */\n\n/** True when a fetch URL argument (string or template literal) targets the ElevenLabs API. */\nexport function isElevenLabsUrlArg(node: any): boolean {\n if (!node) return false;\n if (node.type === 'Literal' && typeof node.value === 'string') {\n return node.value.includes('elevenlabs.io');\n }\n if (node.type === 'TemplateLiteral') {\n return (node.quasis ?? []).some(\n (q: any) => typeof q?.value?.raw === 'string' && q.value.raw.includes('elevenlabs.io'),\n );\n }\n return false;\n}\n\n/** Recursively searches a subtree for a `fetch(<elevenlabs url>, ...)` call. */\nexport function findElevenLabsFetchCall(node: any, depth = 0): any {\n if (!node || typeof node !== 'object' || depth > 20) return null;\n if (Array.isArray(node)) {\n for (const n of node) {\n const found = findElevenLabsFetchCall(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 if (isElevenLabsUrlArg(node.arguments?.[0])) return node;\n }\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = node[key];\n if (val && typeof val === 'object') {\n const found = findElevenLabsFetchCall(val, depth + 1);\n if (found) return found;\n }\n }\n return null;\n}\n\n/** Unwraps `await <expr>` to `<expr>`; passes through anything else unchanged. */\nexport function unwrapAwait(node: any): any {\n return node?.type === 'AwaitExpression' ? node.argument : node;\n}\n\n/** Recursively collects every VariableDeclarator in a subtree. */\nexport function collectVarDeclarators(node: any, out: any[], depth = 0): void {\n if (!node || typeof node !== 'object' || depth > 24) return;\n if (Array.isArray(node)) {\n for (const n of node) collectVarDeclarators(n, out, depth + 1);\n return;\n }\n if (node.type === 'VariableDeclarator') out.push(node);\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = node[key];\n if (val && typeof val === 'object') collectVarDeclarators(val, out, depth + 1);\n }\n}\n\n/** A source-order sortable position for a node, used to compare \"happens before\". */\nexport function posOf(n: any): number {\n if (typeof n?.range?.[0] === 'number') return n.range[0];\n const line = n?.loc?.start?.line ?? 0;\n const column = n?.loc?.start?.column ?? 0;\n return line * 1_000_000 + column;\n}\n","/**\n * Flags code that reads `signed_url` off a parsed ElevenLabs API response\n * without first checking the field is present (CWE-252, Finding A).\n */\nimport { isElevenLabsUrlArg, unwrapAwait, collectVarDeclarators, posOf } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'ElevenLabs signed URL responses must be validated before the signed_url field is used',\n category: 'correctness',\n cwe: 'CWE-252',\n rationale:\n 'The signed-url endpoint assumes the ElevenLabs API always returns a well-formed body. If the API ever returns an unexpected shape (error payload, empty body, schema change), `data.signed_url` is silently `undefined` and the failure only surfaces downstream when the client tries to connect with an invalid URL.',\n docsUrl: 'https://elevenlabs.io/docs/eleven-agents/api-reference/conversations/get-signed-url',\n recommended: true,\n },\n messages: {\n missingValidation:\n 'This code reads signed_url from the ElevenLabs API response without checking that the field exists. A malformed or unexpected response will silently produce an undefined signed URL.',\n },\n },\n create(context: any) {\n function analyzeFunction(fnNode: any): void {\n const declarators: any[] = [];\n collectVarDeclarators(fnNode.body, declarators);\n\n const responseVarNames: string[] = [];\n for (const d of declarators) {\n const init = unwrapAwait(d.init);\n if (\n init?.type === 'CallExpression' &&\n init.callee?.type === 'Identifier' &&\n init.callee.name === 'fetch' &&\n isElevenLabsUrlArg(init.arguments?.[0]) &&\n d.id?.type === 'Identifier'\n ) {\n responseVarNames.push(d.id.name);\n }\n }\n if (responseVarNames.length === 0) return;\n\n for (const responseVarName of responseVarNames) {\n for (const d of declarators) {\n const init = unwrapAwait(d.init);\n if (\n init?.type === 'CallExpression' &&\n init.callee?.type === 'MemberExpression' &&\n init.callee.property?.type === 'Identifier' &&\n init.callee.property.name === 'json' &&\n init.callee.object?.type === 'Identifier' &&\n init.callee.object.name === responseVarName &&\n d.id?.type === 'Identifier'\n ) {\n analyzeDataVar(fnNode, d.id.name, d);\n }\n }\n }\n }\n\n function analyzeDataVar(fnNode: any, dataVarName: string, dataDeclaratorNode: any): void {\n function isSignedUrlMember(n: any): boolean {\n if (n?.type !== 'MemberExpression') return false;\n if (n.object?.type !== 'Identifier' || n.object.name !== dataVarName) return false;\n if (!n.computed) return n.property?.type === 'Identifier' && n.property.name === 'signed_url';\n return n.property?.type === 'Literal' && n.property.value === 'signed_url';\n }\n\n function isNullishLiteral(n: any): boolean {\n return (n?.type === 'Identifier' && n.name === 'undefined') || (n?.type === 'Literal' && n.value === null);\n }\n\n function isFalsyGuardOnSignedUrl(test: any): boolean {\n if (!test) return false;\n if (test.type === 'UnaryExpression' && test.operator === '!') {\n return isSignedUrlMember(test.argument);\n }\n if (test.type === 'BinaryExpression' && (test.operator === '==' || test.operator === '===')) {\n return (\n (isSignedUrlMember(test.left) && isNullishLiteral(test.right)) ||\n (isSignedUrlMember(test.right) && isNullishLiteral(test.left))\n );\n }\n if (test.type === 'LogicalExpression') {\n return isFalsyGuardOnSignedUrl(test.left) || isFalsyGuardOnSignedUrl(test.right);\n }\n return false;\n }\n\n let guardPos: number | null = null;\n let usagePos: number | null = null;\n\n function walk(n: any, depth = 0): void {\n if (!n || typeof n !== 'object' || depth > 40) return;\n if (Array.isArray(n)) {\n for (const item of n) walk(item, depth + 1);\n return;\n }\n if (n.type === 'IfStatement' && isFalsyGuardOnSignedUrl(n.test)) {\n const p = posOf(n);\n if (guardPos === null || p < guardPos) guardPos = p;\n }\n if (isSignedUrlMember(n) && n !== dataDeclaratorNode) {\n const p = posOf(n);\n if (usagePos === null || p < usagePos) usagePos = p;\n }\n for (const key of Object.keys(n)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = n[key];\n if (val && typeof val === 'object') walk(val, depth + 1);\n }\n }\n walk(fnNode.body);\n\n if (usagePos === null) return;\n if (guardPos !== null && guardPos < usagePos) return;\n\n context.report({ node: dataDeclaratorNode, messageId: 'missingValidation' });\n }\n\n return {\n FunctionDeclaration(node: any) {\n analyzeFunction(node);\n },\n FunctionExpression(node: any) {\n analyzeFunction(node);\n },\n ArrowFunctionExpression(node: any) {\n analyzeFunction(node);\n },\n };\n },\n};\n\nexport const elevenlabsValidateSignedUrlResponseRule = rule;\n","/**\n * Flags console.error/warn/log calls in a catch block that pass the raw\n * caught error object instead of a sanitized message (CWE-532, Finding B).\n */\nimport { findElevenLabsFetchCall } from '../utils.js';\n\nconst LOGGING_METHODS = new Set(['error', 'warn', 'log']);\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Catch blocks must not log the raw caught error object',\n category: 'security',\n cwe: 'CWE-532',\n rationale:\n 'Error objects thrown by fetch/SDK calls can carry response bodies, headers, or internal state. Logging them directly with console.error(error) writes that data verbatim into server logs, which may be shipped to third-party log aggregators or be readable by anyone with log access.',\n docsUrl: 'https://elevenlabs.io/docs/api-reference/authentication',\n recommended: true,\n },\n messages: {\n rawErrorLogged:\n 'This catch block logs the raw error object instead of a sanitized message — error responses, headers, or internal state may leak into server logs.',\n },\n },\n create(context: any) {\n function isConsoleLogCall(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 !== 'console') return false;\n return callee.property?.type === 'Identifier' && LOGGING_METHODS.has(callee.property.name);\n }\n\n function referencesRawIdentifier(node: any, paramName: string, depth = 0): boolean {\n if (!node || typeof node !== 'object' || depth > 10) return false;\n if (Array.isArray(node)) return node.some((n) => referencesRawIdentifier(n, paramName, depth + 1));\n\n // The bare identifier itself: console.error('msg', error)\n if (node.type === 'Identifier' && node.name === paramName) return true;\n\n // A property whose value is the bare identifier: console.error({ error })\n if (node.type === 'ObjectExpression') {\n return (node.properties ?? []).some((p: any) => {\n if (p.type !== 'Property') return false;\n return referencesRawIdentifier(p.value, paramName, depth + 1);\n });\n }\n\n if (node.type === 'ArrayExpression') {\n return (node.elements ?? []).some((el: any) => referencesRawIdentifier(el, paramName, depth + 1));\n }\n\n return false;\n }\n\n return {\n TryStatement(node: any) {\n if (!findElevenLabsFetchCall(node.block)) return;\n\n const handler = node.handler;\n const paramName = handler?.param?.type === 'Identifier' ? handler.param.name : null;\n if (!paramName) return;\n\n function walk(n: any, depth = 0): void {\n if (!n || typeof n !== 'object' || depth > 30) return;\n if (Array.isArray(n)) {\n for (const item of n) walk(item, depth + 1);\n return;\n }\n if (isConsoleLogCall(n)) {\n const args = n.arguments ?? [];\n const loggedRaw = args.some((a: any) => referencesRawIdentifier(a, paramName));\n if (loggedRaw) {\n context.report({ node: n, messageId: 'rawErrorLogged' });\n }\n }\n for (const key of Object.keys(n)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = n[key];\n if (val && typeof val === 'object') walk(val, depth + 1);\n }\n }\n\n walk(handler.body);\n },\n };\n },\n};\n\nexport const elevenlabsNoErrorObjectLoggingRule = rule;\n","/**\n * Flags fetch() calls to the ElevenLabs API that have no abort signal /\n * timeout configured, so a slow or unresponsive API hangs the request\n * indefinitely (Finding C).\n */\nimport { isElevenLabsUrlArg } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Fetch calls to the ElevenLabs API must set an abort timeout',\n category: 'reliability',\n rationale:\n 'Native fetch has no default timeout. If the ElevenLabs API becomes slow or hangs, a request with no AbortController/signal will wait indefinitely, tying up the request handler and starving the server of available connections.',\n docsUrl: 'https://elevenlabs.io/docs/eleven-agents/api-reference/conversations/get-signed-url',\n recommended: true,\n },\n messages: {\n missingTimeout:\n 'This fetch call to the ElevenLabs API has no abort signal/timeout — a slow or unresponsive API will hang the request indefinitely.',\n },\n },\n create(context: any) {\n function hasSignalOption(optionsArg: any): boolean {\n if (optionsArg?.type !== 'ObjectExpression') return false;\n return (optionsArg.properties ?? []).some((p: any) => {\n if (p.type === 'SpreadElement') return true; // be conservative: spread could carry a signal\n return p.type === 'Property' && p.key?.type === 'Identifier' && p.key.name === 'signal';\n });\n }\n\n return {\n CallExpression(node: any) {\n if (node.callee?.type !== 'Identifier' || node.callee.name !== 'fetch') return;\n if (!isElevenLabsUrlArg(node.arguments?.[0])) return;\n\n const optionsArg = node.arguments?.[1];\n if (hasSignalOption(optionsArg)) return;\n\n context.report({ node, messageId: 'missingTimeout' });\n },\n };\n },\n};\n\nexport const elevenlabsFetchTimeoutRequiredRule = rule;\n","/**\n * Flags an `agentId` query-param value that is checked for existence but\n * never validated against an expected format before being used in an\n * ElevenLabs API URL (CWE-20, Finding D).\n */\nimport { isElevenLabsUrlArg, unwrapAwait, collectVarDeclarators, posOf } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'agentId must be format-validated, not just checked for existence, before use',\n category: 'correctness',\n cwe: 'CWE-20',\n rationale:\n 'A query-param agentId that is only checked with `if (!agentId)` accepts any non-empty string. An attacker can pass arbitrary values — oversized strings, path-traversal-like sequences, or characters the ElevenLabs API was never designed to receive — directly into the request URL, producing undefined behavior instead of a clean 400.',\n docsUrl: 'https://elevenlabs.io/docs/eleven-agents/customization/authentication',\n recommended: true,\n },\n messages: {\n missingFormatValidation:\n 'agentId is checked for existence but never validated against an expected format before being used in an ElevenLabs API request.',\n },\n },\n create(context: any) {\n function isSearchParamsGetAgentId(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 !== 'get') return false;\n const arg = node.arguments?.[0];\n return arg?.type === 'Literal' && arg.value === 'agentId';\n }\n\n function analyzeFunction(fnNode: any): void {\n const declarators: any[] = [];\n collectVarDeclarators(fnNode.body, declarators);\n\n let agentIdVarName: string | null = null;\n let agentIdDeclaratorNode: any = null;\n for (const d of declarators) {\n const init = unwrapAwait(d.init);\n if (isSearchParamsGetAgentId(init) && d.id?.type === 'Identifier') {\n agentIdVarName = d.id.name;\n agentIdDeclaratorNode = d;\n }\n }\n\n // A parameter literally named `agentId` is treated the same way —\n // callers may have sourced it from a query param a level up.\n if (!agentIdVarName) {\n for (const param of fnNode.params ?? []) {\n if (param?.type === 'Identifier' && param.name === 'agentId') {\n agentIdVarName = param.name;\n agentIdDeclaratorNode = param;\n }\n }\n }\n if (!agentIdVarName) return;\n\n function isAgentIdMember(n: any): boolean {\n return n?.type === 'Identifier' && n.name === agentIdVarName;\n }\n\n // A regex-based format check: agentId.match(/.../) or /.../.test(agentId)\n function isFormatCheck(n: any, depth = 0): boolean {\n if (!n || typeof n !== 'object' || depth > 10) return false;\n if (Array.isArray(n)) return n.some((x) => isFormatCheck(x, depth + 1));\n if (n.type === 'CallExpression' && n.callee?.type === 'MemberExpression') {\n const propName = n.callee.property?.type === 'Identifier' ? n.callee.property.name : null;\n if (propName === 'test' && isAgentIdMember(n.arguments?.[0])) return true;\n if ((propName === 'match' || propName === 'matchAll') && isAgentIdMember(n.callee.object)) return true;\n }\n if (n.type === 'LogicalExpression') {\n return isFormatCheck(n.left, depth + 1) || isFormatCheck(n.right, depth + 1);\n }\n if (n.type === 'UnaryExpression') return isFormatCheck(n.argument, depth + 1);\n return false;\n }\n\n let formatGuardPos: number | null = null;\n let usagePos: number | null = null;\n\n function walk(n: any, depth = 0): void {\n if (!n || typeof n !== 'object' || depth > 40) return;\n if (Array.isArray(n)) {\n for (const item of n) walk(item, depth + 1);\n return;\n }\n if (n.type === 'IfStatement' && isFormatCheck(n.test)) {\n const p = posOf(n);\n if (formatGuardPos === null || p < formatGuardPos) formatGuardPos = p;\n }\n // Usage: agentId used inside a fetch() URL targeting the ElevenLabs API.\n if (\n n.type === 'CallExpression' &&\n n.callee?.type === 'Identifier' &&\n n.callee.name === 'fetch' &&\n isElevenLabsUrlArg(n.arguments?.[0])\n ) {\n const urlArg = n.arguments[0];\n const containsAgentId =\n urlArg.type === 'TemplateLiteral' &&\n (urlArg.expressions ?? []).some((e: any) => isAgentIdMember(e));\n if (containsAgentId) {\n const p = posOf(n);\n if (usagePos === null || p < usagePos) usagePos = p;\n }\n }\n for (const key of Object.keys(n)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = n[key];\n if (val && typeof val === 'object') walk(val, depth + 1);\n }\n }\n walk(fnNode.body);\n\n if (usagePos === null) return;\n if (formatGuardPos !== null && formatGuardPos < usagePos) return;\n\n context.report({ node: agentIdDeclaratorNode, messageId: 'missingFormatValidation' });\n }\n\n return {\n FunctionDeclaration(node: any) {\n analyzeFunction(node);\n },\n FunctionExpression(node: any) {\n analyzeFunction(node);\n },\n ArrowFunctionExpression(node: any) {\n analyzeFunction(node);\n },\n };\n },\n};\n\nexport const elevenlabsValidateAgentIdFormatRule = rule;\n","/**\n * Flags `Math.random()` used to build a session-id-like value (CWE-338,\n * Finding E). Math.random() is not cryptographically secure and predictable\n * session ids can allow unauthorized access if used for access control.\n */\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Session ids must be generated with a cryptographically secure RNG',\n category: 'security',\n cwe: 'CWE-338',\n rationale:\n 'Math.random() is a non-cryptographic PRNG — its output can be predicted by an attacker who observes enough samples or knows the engine implementation. If a \"session_*\" value derived from it is later trusted for routing, deduplication, or any access-control-adjacent decision, that predictability can be exploited.',\n docsUrl: 'https://elevenlabs.io/docs/eleven-api/guides/how-to/best-practices/security',\n recommended: true,\n },\n messages: {\n insecureSessionId:\n 'This session id is generated with Math.random(), which is not cryptographically secure and can be predicted. Use crypto.getRandomValues() instead.',\n },\n },\n create(context: any) {\n function containsMathRandomCall(node: any, depth = 0): boolean {\n if (!node || typeof node !== 'object' || depth > 20) return false;\n if (Array.isArray(node)) return node.some((n) => containsMathRandomCall(n, depth + 1));\n if (\n node.type === 'CallExpression' &&\n node.callee?.type === 'MemberExpression' &&\n node.callee.object?.type === 'Identifier' &&\n node.callee.object.name === 'Math' &&\n node.callee.property?.type === 'Identifier' &&\n node.callee.property.name === 'random'\n ) {\n return true;\n }\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = node[key];\n if (val && typeof val === 'object' && containsMathRandomCall(val, depth + 1)) return true;\n }\n return false;\n }\n\n function looksLikeSessionId(name: string | undefined): boolean {\n return typeof name === 'string' && /session/i.test(name);\n }\n\n function isSessionIdValue(init: any): boolean {\n // `session_${...Math.random()...}` or `'session_' + ... Math.random() ...`\n if (init?.type === 'TemplateLiteral') {\n const firstQuasi = init.quasis?.[0]?.value?.raw ?? '';\n if (/session[-_]?/i.test(firstQuasi) && containsMathRandomCall(init)) return true;\n }\n if (init?.type === 'BinaryExpression' && init.operator === '+') {\n const leftLiteral = init.left?.type === 'Literal' && typeof init.left.value === 'string';\n if (leftLiteral && /session[-_]?/i.test(init.left.value) && containsMathRandomCall(init)) return true;\n }\n return false;\n }\n\n return {\n VariableDeclarator(node: any) {\n const init = node.init;\n if (!init) return;\n\n const declaredName =\n node.id?.type === 'Identifier'\n ? node.id.name\n : node.id?.type === 'ArrayPattern' && node.id.elements?.[0]?.type === 'Identifier'\n ? node.id.elements[0].name\n : undefined;\n\n // `useState(() => ...)` form: the random expression lives in the callback's return.\n let valueNode = init;\n if (\n init.type === 'CallExpression' &&\n init.callee?.type === 'Identifier' &&\n init.callee.name === 'useState' &&\n init.arguments?.[0]?.type === 'ArrowFunctionExpression'\n ) {\n const body = init.arguments[0].body;\n valueNode = body?.type === 'BlockStatement' ? null : body;\n if (body?.type === 'BlockStatement') {\n const returnStmt = (body.body ?? []).find((s: any) => s.type === 'ReturnStatement');\n valueNode = returnStmt?.argument ?? null;\n }\n }\n\n if (!valueNode) return;\n if (!looksLikeSessionId(declaredName) && !isSessionIdValue(valueNode)) return;\n if (!containsMathRandomCall(valueNode)) return;\n\n context.report({ node, messageId: 'insecureSessionId' });\n },\n };\n },\n};\n\nexport const elevenlabsSecureSessionIdGenerationRule = rule;\n","/**\n * Flags an async conversation-start function that sets a loading flag true\n * before a try block, but whose catch/finally never resets it to false —\n * leaving the UI stuck in a loading state after a failed attempt and\n * allowing rapid repeated clicks to spawn overlapping attempts (Finding F).\n */\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'A loading flag set before starting a conversation must be reset on failure',\n category: 'reliability',\n rationale:\n 'If startConversation() sets isLoading true and getSignedUrl()/Conversation.startSession() throws, the loading flag must be reset in the catch or finally block. Otherwise the UI is stuck \"loading\" forever and the user can trigger overlapping conversation attempts by clicking again.',\n docsUrl: 'https://elevenlabs.io/docs/eleven-agents/libraries/java-script',\n recommended: true,\n },\n messages: {\n missingLoadingReset:\n 'This function sets a loading flag true before a try block, but neither the catch nor a finally block resets it to false on failure.',\n },\n },\n create(context: any) {\n function isSetterCallWithBoolean(n: any, setterName: string, expected: boolean): boolean {\n if (n?.type !== 'CallExpression') return false;\n if (n.callee?.type !== 'Identifier' || n.callee.name !== setterName) return false;\n const arg = n.arguments?.[0];\n return arg?.type === 'Literal' && arg.value === expected;\n }\n\n function containsCall(node: any, predicate: (n: any) => boolean, depth = 0): boolean {\n if (!node || typeof node !== 'object' || depth > 20) return false;\n if (Array.isArray(node)) return node.some((n) => containsCall(n, predicate, depth + 1));\n if (predicate(node)) return true;\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = node[key];\n if (val && typeof val === 'object' && containsCall(val, predicate, depth + 1)) return true;\n }\n return false;\n }\n\n function findLoadingSetterFromUseState(fnNode: any): string | null {\n let setterName: string | null = null;\n\n function collect(n: any, depth = 0): void {\n if (setterName || !n || typeof n !== 'object' || depth > 20) return;\n if (Array.isArray(n)) {\n for (const item of n) collect(item, depth + 1);\n return;\n }\n if (\n n.type === 'VariableDeclarator' &&\n n.id?.type === 'ArrayPattern' &&\n n.id.elements?.length === 2 &&\n n.id.elements[0]?.type === 'Identifier' &&\n /loading/i.test(n.id.elements[0].name) &&\n n.id.elements[1]?.type === 'Identifier' &&\n n.init?.type === 'CallExpression' &&\n n.init.callee?.type === 'Identifier' &&\n n.init.callee.name === 'useState'\n ) {\n setterName = n.id.elements[1].name;\n return;\n }\n for (const key of Object.keys(n)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = n[key];\n if (val && typeof val === 'object') collect(val, depth + 1);\n }\n }\n collect(fnNode);\n return setterName;\n }\n\n function isLoadingTrueStatement(stmt: any, setterName: string): boolean {\n return stmt?.type === 'ExpressionStatement' && isSetterCallWithBoolean(stmt.expression, setterName, true);\n }\n\n function analyzeFunction(fnNode: any): void {\n const setterName = findLoadingSetterFromUseState(fnNode);\n if (!setterName) return;\n\n // Only the try block immediately following a `setLoading(true)` sibling\n // statement is in scope — a stray setLoading(true) elsewhere in the\n // function must not implicate every unrelated try block.\n function walk(n: any, depth = 0): void {\n if (!n || typeof n !== 'object' || depth > 30) return;\n if (Array.isArray(n)) {\n for (const item of n) walk(item, depth + 1);\n return;\n }\n if (n.type === 'BlockStatement' && Array.isArray(n.body)) {\n for (let i = 0; i < n.body.length - 1; i++) {\n if (!isLoadingTrueStatement(n.body[i], setterName)) continue;\n const tryNode = n.body[i + 1];\n if (tryNode?.type !== 'TryStatement') continue;\n\n const handler = tryNode.handler;\n const finalizer = tryNode.finalizer;\n const finallyResets =\n finalizer && containsCall(finalizer, (x) => isSetterCallWithBoolean(x, setterName, false));\n const catchResets =\n handler && containsCall(handler.body, (x) => isSetterCallWithBoolean(x, setterName, false));\n\n if (!finallyResets && !catchResets) {\n context.report({ node: tryNode, messageId: 'missingLoadingReset' });\n }\n }\n }\n for (const key of Object.keys(n)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = n[key];\n if (val && typeof val === 'object') walk(val, depth + 1);\n }\n }\n walk(fnNode.body);\n }\n\n return {\n FunctionDeclaration(node: any) {\n analyzeFunction(node);\n },\n FunctionExpression(node: any) {\n analyzeFunction(node);\n },\n ArrowFunctionExpression(node: any) {\n analyzeFunction(node);\n },\n };\n },\n};\n\nexport const elevenlabsConversationErrorRecoveryRule = rule;\n","/**\n * Flags fetch() calls to the ElevenLabs API that have no explicit API\n * version header, so a future breaking API change silently changes\n * behavior under the request (Finding G).\n */\nimport { isElevenLabsUrlArg } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'ElevenLabs API requests should pin an explicit API version header',\n category: 'reliability',\n rationale:\n 'The endpoint is hardcoded to /v1 in the URL path with no explicit version header. If ElevenLabs ships a v2 API and changes default response behavior for unversioned clients, requests with no version header silently pick up the new behavior instead of failing loudly or staying pinned.',\n docsUrl: 'https://elevenlabs.io/docs/eleven-api/resources/breaking-changes-policy',\n recommended: true,\n },\n messages: {\n missingVersionHeader:\n 'This fetch call to the ElevenLabs API has no explicit API version header — a future API change could silently alter behavior.',\n },\n },\n create(context: any) {\n function hasVersionHeader(optionsArg: any): boolean {\n if (optionsArg?.type !== 'ObjectExpression') return false;\n const headersProp = (optionsArg.properties ?? []).find(\n (p: any) => p.type === 'Property' && p.key?.type === 'Identifier' && p.key.name === 'headers',\n );\n if (!headersProp) return false;\n if (headersProp.value?.type !== 'ObjectExpression') return true; // spread/computed headers — be conservative\n return (headersProp.value.properties ?? []).some((p: any) => {\n if (p.type === 'SpreadElement') return true;\n if (p.type !== 'Property') return false;\n const keyName = p.key?.type === 'Identifier' ? p.key.name : p.key?.type === 'Literal' ? p.key.value : null;\n return typeof keyName === 'string' && /version/i.test(keyName);\n });\n }\n\n return {\n CallExpression(node: any) {\n if (node.callee?.type !== 'Identifier' || node.callee.name !== 'fetch') return;\n if (!isElevenLabsUrlArg(node.arguments?.[0])) return;\n\n const optionsArg = node.arguments?.[1];\n if (hasVersionHeader(optionsArg)) return;\n\n context.report({ node, messageId: 'missingVersionHeader' });\n },\n };\n },\n};\n\nexport const elevenlabsApiVersionPinningRule = rule;\n","/**\n * Flags `response.json()` called on an ElevenLabs API fetch response with no\n * preceding response.ok / status check, which parses error bodies as if\n * they were successful data (Finding H).\n */\nimport { isElevenLabsUrlArg, unwrapAwait, collectVarDeclarators, posOf } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'response.json() must not be called before checking the HTTP status of an ElevenLabs response',\n category: 'correctness',\n rationale:\n 'Calling response.json() unconditionally parses whatever body the server returned, including error payloads, as if it were a successful response. Without checking response.ok (or response.status) first, a 4xx/5xx error from the ElevenLabs API is silently treated as valid data.',\n docsUrl: 'https://elevenlabs.io/docs/eleven-api/resources/errors',\n recommended: true,\n },\n messages: {\n missingStatusCheck:\n 'response.json() is called on this ElevenLabs API response without first checking response.ok/status — an error response will be parsed as if it were valid data.',\n },\n },\n create(context: any) {\n function analyzeFunction(fnNode: any): void {\n const declarators: any[] = [];\n collectVarDeclarators(fnNode.body, declarators);\n\n const responseVarNames: string[] = [];\n for (const d of declarators) {\n const init = unwrapAwait(d.init);\n if (\n init?.type === 'CallExpression' &&\n init.callee?.type === 'Identifier' &&\n init.callee.name === 'fetch' &&\n isElevenLabsUrlArg(init.arguments?.[0]) &&\n d.id?.type === 'Identifier'\n ) {\n responseVarNames.push(d.id.name);\n }\n }\n for (const responseVarName of responseVarNames) {\n analyzeResponseVar(fnNode, responseVarName);\n }\n }\n\n function analyzeResponseVar(fnNode: any, responseVarName: string): void {\n function isResponseStatusCheck(test: any): boolean {\n if (!test) return false;\n // response.ok / !response.ok\n if (test.type === 'UnaryExpression' && test.operator === '!') return isResponseStatusCheck(test.argument);\n if (\n test.type === 'MemberExpression' &&\n test.object?.type === 'Identifier' &&\n test.object.name === responseVarName &&\n test.property?.type === 'Identifier' &&\n test.property.name === 'ok'\n ) {\n return true;\n }\n // response.status compared to something\n if (test.type === 'BinaryExpression') {\n const sideIsStatus = (n: any) =>\n n?.type === 'MemberExpression' &&\n n.object?.type === 'Identifier' &&\n n.object.name === responseVarName &&\n n.property?.type === 'Identifier' &&\n n.property.name === 'status';\n if (sideIsStatus(test.left) || sideIsStatus(test.right)) return true;\n }\n if (test.type === 'LogicalExpression') {\n return isResponseStatusCheck(test.left) || isResponseStatusCheck(test.right);\n }\n return false;\n }\n\n function isResponseJsonCall(n: any): boolean {\n if (n?.type !== 'CallExpression') return false;\n const callee = n.callee;\n if (callee?.type !== 'MemberExpression') return false;\n if (callee.property?.type !== 'Identifier' || callee.property.name !== 'json') return false;\n return callee.object?.type === 'Identifier' && callee.object.name === responseVarName;\n }\n\n let guardPos: number | null = null;\n let jsonCallNode: any = null;\n let jsonCallPos: number | null = null;\n\n function walk(n: any, depth = 0): void {\n if (!n || typeof n !== 'object' || depth > 40) return;\n if (Array.isArray(n)) {\n for (const item of n) walk(item, depth + 1);\n return;\n }\n if (n.type === 'IfStatement' && isResponseStatusCheck(n.test)) {\n const p = posOf(n);\n if (guardPos === null || p < guardPos) guardPos = p;\n }\n if (isResponseJsonCall(n)) {\n const p = posOf(n);\n if (jsonCallPos === null || p < jsonCallPos) {\n jsonCallPos = p;\n jsonCallNode = n;\n }\n }\n for (const key of Object.keys(n)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = n[key];\n if (val && typeof val === 'object') walk(val, depth + 1);\n }\n }\n walk(fnNode.body);\n\n if (jsonCallPos === null) return;\n if (guardPos !== null && guardPos < jsonCallPos) return;\n\n context.report({ node: jsonCallNode, messageId: 'missingStatusCheck' });\n }\n\n return {\n FunctionDeclaration(node: any) {\n analyzeFunction(node);\n },\n FunctionExpression(node: any) {\n analyzeFunction(node);\n },\n ArrowFunctionExpression(node: any) {\n analyzeFunction(node);\n },\n };\n },\n};\n\nexport const elevenlabsCheckHttpStatusBeforeJsonRule = rule;\n","/**\n * Flags `conversation.endSession()` / `conversation.endConversation()` calls\n * with no surrounding try/catch, which can leave the conversation in memory\n * if the call rejects (Finding I).\n */\nimport { posOf } from '../utils.js';\n\nconst END_METHODS = new Set(['endSession', 'endConversation']);\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Ending a conversation must be wrapped in try/catch so a rejected call is handled',\n category: 'reliability',\n rationale:\n 'If conversation.endSession()/endConversation() rejects (e.g. during a GL-mode transition) and the call site has no try/catch, the rejection becomes an unhandled promise rejection and the conversation state is never cleaned up, leaving stale connections in memory.',\n docsUrl: 'https://elevenlabs.io/docs/eleven-agents/libraries/java-script',\n recommended: true,\n },\n messages: {\n missingTryCatch:\n 'This call to end the conversation has no surrounding try/catch — a rejection will go unhandled and the conversation state may never be cleaned up.',\n },\n },\n create(context: any) {\n function posEnd(n: any): number {\n if (typeof n?.range?.[1] === 'number') return n.range[1];\n const line = n?.loc?.end?.line ?? n?.loc?.start?.line ?? 0;\n const column = n?.loc?.end?.column ?? n?.loc?.start?.column ?? 0;\n return line * 1_000_000 + column;\n }\n\n function isConversationEndCall(node: any): boolean {\n if (node?.type !== 'CallExpression') return false;\n const callee = node.callee;\n // `conversation.endSession()` / `conversation.endConversation()`\n if (callee?.type === 'MemberExpression') {\n return callee.property?.type === 'Identifier' && END_METHODS.has(callee.property.name);\n }\n // A bare `endConversation()` call (e.g. a destructured handler prop).\n return callee?.type === 'Identifier' && END_METHODS.has(callee.name);\n }\n\n return {\n 'Program:exit'(program: any) {\n const tryRanges: Array<[number, number]> = [];\n const endCalls: any[] = [];\n\n function walk(n: any, depth = 0): void {\n if (!n || typeof n !== 'object' || depth > 60) return;\n if (Array.isArray(n)) {\n for (const item of n) walk(item, depth + 1);\n return;\n }\n if (n.type === 'TryStatement' && n.block) {\n tryRanges.push([posOf(n.block), posEnd(n.block)]);\n }\n if (isConversationEndCall(n)) endCalls.push(n);\n for (const key of Object.keys(n)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = n[key];\n if (val && typeof val === 'object') walk(val, depth + 1);\n }\n }\n walk(program);\n\n for (const call of endCalls) {\n const p = posOf(call);\n const covered = tryRanges.some(([start, end]) => p >= start && p <= end);\n if (!covered) {\n context.report({ node: call, messageId: 'missingTryCatch' });\n }\n }\n },\n };\n },\n};\n\nexport const elevenlabsConversationCleanupOnErrorRule = rule;\n","/**\n * Flags a module that reads process.env.XI_API_KEY (or similar ElevenLabs\n * env vars) only inside a request handler, with no module-scope assertion\n * that the variable exists — so a missing key only surfaces when a user\n * first hits the feature instead of at startup (Finding J).\n */\nconst ELEVENLABS_ENV_VAR_PATTERN = /^(XI_API_KEY|ELEVENLABS_API_KEY)$/;\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'ElevenLabs API key environment variables should be validated at module load, not only at request time',\n category: 'correctness',\n rationale:\n 'Checking `if (!apiKey)` inside a request handler means a misconfigured deployment only fails the first time a user exercises the feature, instead of failing fast at startup where it would show up in deploy logs or a health check.',\n docsUrl: 'https://elevenlabs.io/docs/api-reference/authentication',\n recommended: true,\n },\n messages: {\n missingStartupValidation:\n 'This module reads an ElevenLabs API key from process.env but only validates it inside a request handler — validate it at module scope so a missing key fails at startup, not at first use.',\n },\n },\n create(context: any) {\n function isElevenLabsEnvAccess(node: any): boolean {\n if (node?.type !== 'MemberExpression') return false;\n if (node.object?.type !== 'MemberExpression') return false;\n const inner = node.object;\n if (inner.object?.type !== 'Identifier' || inner.object.name !== 'process') return false;\n if (inner.property?.type !== 'Identifier' || inner.property.name !== 'env') return false;\n const propName = node.property?.type === 'Identifier' ? node.property.name : node.property?.value;\n return typeof propName === 'string' && ELEVENLABS_ENV_VAR_PATTERN.test(propName);\n }\n\n function isInsideFunction(node: any, ancestors: any[]): boolean {\n return ancestors.some(\n (a: any) =>\n a?.type === 'FunctionDeclaration' || a?.type === 'FunctionExpression' || a?.type === 'ArrowFunctionExpression',\n );\n }\n\n return {\n 'Program:exit'(program: any) {\n let moduleScopeAccess = false;\n let handlerScopeAccess = false;\n\n function walk(n: any, ancestors: any[], depth = 0): void {\n if (!n || typeof n !== 'object' || depth > 60) return;\n if (Array.isArray(n)) {\n for (const item of n) walk(item, ancestors, depth + 1);\n return;\n }\n if (isElevenLabsEnvAccess(n)) {\n if (isInsideFunction(n, ancestors)) {\n handlerScopeAccess = true;\n } else {\n moduleScopeAccess = true;\n }\n }\n const nextAncestors =\n n.type === 'FunctionDeclaration' || n.type === 'FunctionExpression' || n.type === 'ArrowFunctionExpression'\n ? [...ancestors, n]\n : ancestors;\n for (const key of Object.keys(n)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = n[key];\n if (val && typeof val === 'object') walk(val, nextAncestors, depth + 1);\n }\n }\n walk(program, []);\n\n if (handlerScopeAccess && !moduleScopeAccess) {\n context.report({ node: program, messageId: 'missingStartupValidation' });\n }\n },\n };\n },\n};\n\nexport const elevenlabsEnvVarValidationRule = rule;\n","/** Shared AST helpers for Twilio provider rules. */\n\nconst POST_METHOD_NAMES = new Set(['post']);\nconst ROUTER_OBJECT_NAMES = new Set(['server', 'app', 'router', 'fastify']);\n\n/** True for `server.post('/path', ...)` / `app.post('/path', ...)` style route registrations. */\nexport function isPostRouteRegistration(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' || !POST_METHOD_NAMES.has(callee.property.name)) return false;\n return callee.object?.type === 'Identifier' && ROUTER_OBJECT_NAMES.has(callee.object.name);\n}\n\n/** Recursively searches a subtree for any node matching the predicate. */\nexport function findInSubtree(node: any, predicate: (n: any) => boolean, depth = 0): any {\n if (!node || typeof node !== 'object' || depth > 40) return null;\n if (Array.isArray(node)) {\n for (const n of node) {\n const found = findInSubtree(n, predicate, depth + 1);\n if (found) return found;\n }\n return null;\n }\n if (predicate(node)) return node;\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = node[key];\n if (val && typeof val === 'object') {\n const found = findInSubtree(val, predicate, depth + 1);\n if (found) return found;\n }\n }\n return null;\n}\n\n/** True when a subtree references `req.body`/`request.body` anywhere. */\nexport function referencesRequestBody(node: any): boolean {\n return !!findInSubtree(node, (n) => {\n if (n?.type !== 'MemberExpression') return false;\n if (n.property?.type !== 'Identifier' || n.property.name !== 'body') return false;\n return n.object?.type === 'Identifier' && (n.object.name === 'req' || n.object.name === 'request');\n });\n}\n\n/** Recursively collects every VariableDeclarator in a subtree. */\nexport function collectVarDeclarators(node: any, out: any[], depth = 0): void {\n if (!node || typeof node !== 'object' || depth > 24) return;\n if (Array.isArray(node)) {\n for (const n of node) collectVarDeclarators(n, out, depth + 1);\n return;\n }\n if (node.type === 'VariableDeclarator') out.push(node);\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = node[key];\n if (val && typeof val === 'object') collectVarDeclarators(val, out, depth + 1);\n }\n}\n\n/** A source-order sortable position for a node, used to compare \"happens before\". */\nexport function posOf(n: any): number {\n if (typeof n?.range?.[0] === 'number') return n.range[0];\n const line = n?.loc?.start?.line ?? 0;\n const column = n?.loc?.start?.column ?? 0;\n return line * 1_000_000 + column;\n}\n","/**\n * Flags POST webhook routes that read req.body but never validate the\n * X-Twilio-Signature header via twilio.validateRequest()/RequestValidator\n * anywhere in the file (CWE-345, Finding A).\n */\nimport { isPostRouteRegistration, referencesRequestBody, findInSubtree } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Twilio webhook routes must validate the X-Twilio-Signature header before trusting the body',\n category: 'security',\n cwe: 'CWE-345',\n owasp: 'A07:2021 Identification and Authentication Failures',\n rationale:\n 'Webhook URLs are public. Anyone who learns or guesses the path can POST a forged body — fake CallSid/From/TaskAttributes values — and the handler has no way to tell it apart from a real Twilio request. Without validating the signature first, an attacker can trigger outbound calls (toll/billing impact) or falsely invoke reservation/task callbacks to manipulate call state for an arbitrary caller.',\n docsUrl: 'https://www.twilio.com/docs/usage/webhooks/webhooks-security',\n recommended: true,\n },\n messages: {\n missingSignatureValidation:\n 'This POST webhook route reads req.body but the file never validates the X-Twilio-Signature header via twilio.validateRequest()/RequestValidator — a forged request body is indistinguishable from a real Twilio callback.',\n },\n },\n create(context: any) {\n function isValidateRequestCall(n: any): boolean {\n if (n?.type !== 'CallExpression') return false;\n const callee = n.callee;\n if (callee?.type !== 'MemberExpression') return false;\n return callee.property?.type === 'Identifier' && callee.property.name === 'validateRequest';\n }\n\n function isRequestValidatorConstruction(n: any): boolean {\n return n?.type === 'NewExpression' && n.callee?.type === 'Identifier' && n.callee.name === 'RequestValidator';\n }\n\n return {\n 'Program:exit'(program: any) {\n const hasValidation =\n !!findInSubtree(program, isValidateRequestCall) || !!findInSubtree(program, isRequestValidatorConstruction);\n if (hasValidation) return;\n\n const postRoutes: any[] = [];\n findInSubtree(program, (n) => {\n if (isPostRouteRegistration(n) && referencesRequestBody(n)) postRoutes.push(n);\n return false;\n });\n\n for (const route of postRoutes) {\n context.report({ node: route, messageId: 'missingSignatureValidation' });\n }\n },\n };\n },\n};\n\nexport const twilioValidateWebhookSignatureRule = rule;\n","/**\n * Flags a TaskRouter `.task(...)` attributes payload that omits a field\n * which the same file later destructures from `JSON.parse(req.body.TaskAttributes)`\n * (Finding E). The producer and consumer of Task attributes silently drift\n * apart, so the consumer's lookup is always undefined.\n */\nimport { findInSubtree, collectVarDeclarators } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'TaskRouter Task attributes must include every field the reservation handler reads back out',\n category: 'correctness',\n rationale:\n 'A Task is created with attributes like `{ name, type }`, and later a reservation-accepted handler does `const { from } = JSON.parse(req.body.TaskAttributes)` to look up state by `from`. If the producer never set `from` on the Task attributes, that destructure is always `undefined`, the lookup always misses, and the handler returns 404 — even though every other part of the flow worked correctly.',\n docsUrl: 'https://www.twilio.com/docs/taskrouter/twiml-queue-calls',\n recommended: true,\n },\n messages: {\n attributeMismatch:\n 'This .task() attributes object does not set \"{{field}}\", but a reservation handler in this codebase destructures \"{{field}}\" from JSON.parse(TaskAttributes) — that lookup will always be undefined.',\n },\n },\n create(context: any) {\n function isTaskCall(n: any): boolean {\n if (n?.type !== 'CallExpression') return false;\n const callee = n.callee;\n if (callee?.type !== 'MemberExpression') return false;\n return callee.property?.type === 'Identifier' && callee.property.name === 'task';\n }\n\n function extractAttributeKeys(taskCallNode: any): Set<string> | null {\n const arg = taskCallNode.arguments?.[0];\n if (!arg) return null;\n\n // JSON.stringify({ name: ..., from: ... }) form\n if (\n arg.type === 'CallExpression' &&\n arg.callee?.type === 'MemberExpression' &&\n arg.callee.object?.type === 'Identifier' &&\n arg.callee.object.name === 'JSON' &&\n arg.callee.property?.type === 'Identifier' &&\n arg.callee.property.name === 'stringify' &&\n arg.arguments?.[0]?.type === 'ObjectExpression'\n ) {\n return objectKeys(arg.arguments[0]);\n }\n\n // Raw template-literal/string JSON form: `{ \"name\": \"${...}\", \"type\": \"inbound\" }`.\n // JSON keys are always literal text in the quasis, never inside the\n // interpolated expressions, so concatenating quasis text is sufficient.\n if (arg.type === 'TemplateLiteral') {\n const raw = arg.quasis.map((q: any) => q.value?.raw ?? '').join('');\n const keys = new Set<string>();\n for (const m of raw.matchAll(/\"([a-zA-Z0-9_]+)\"\\s*:/g)) keys.add(m[1]);\n return keys;\n }\n if (arg.type === 'Literal' && typeof arg.value === 'string') {\n const keys = new Set<string>();\n for (const m of arg.value.matchAll(/\"([a-zA-Z0-9_]+)\"\\s*:/g)) keys.add(m[1]);\n return keys;\n }\n\n return null;\n }\n\n function objectKeys(objExpr: any): Set<string> {\n const keys = new Set<string>();\n for (const p of objExpr.properties ?? []) {\n if (p.type !== 'Property') continue;\n const name = p.key?.type === 'Identifier' ? p.key.name : p.key?.type === 'Literal' ? p.key.value : null;\n if (typeof name === 'string') keys.add(name);\n }\n return keys;\n }\n\n function isTaskAttributesJsonParse(n: any): boolean {\n if (n?.type !== 'CallExpression') return false;\n const callee = n.callee;\n if (callee?.type !== 'MemberExpression') return false;\n if (callee.object?.type !== 'Identifier' || callee.object.name !== 'JSON') return false;\n if (callee.property?.type !== 'Identifier' || callee.property.name !== 'parse') return false;\n const arg = n.arguments?.[0];\n if (arg?.type !== 'MemberExpression') return false;\n return arg.property?.type === 'Identifier' && arg.property.name === 'TaskAttributes';\n }\n\n function findConsumedFields(program: any): Set<string> {\n const fields = new Set<string>();\n const declarators: any[] = [];\n collectVarDeclarators(program, declarators);\n for (const d of declarators) {\n if (!isTaskAttributesJsonParse(d.init)) continue;\n if (d.id?.type === 'ObjectPattern') {\n for (const p of d.id.properties ?? []) {\n if (p.type !== 'Property') continue;\n const name = p.key?.type === 'Identifier' ? p.key.name : null;\n if (name) fields.add(name);\n }\n }\n }\n return fields;\n }\n\n return {\n 'Program:exit'(program: any) {\n const consumedFields = findConsumedFields(program);\n if (consumedFields.size === 0) return;\n\n const taskCalls: any[] = [];\n findInSubtree(program, (n) => {\n if (isTaskCall(n)) taskCalls.push(n);\n return false;\n });\n\n for (const taskCall of taskCalls) {\n const producedKeys = extractAttributeKeys(taskCall);\n if (!producedKeys) continue;\n\n for (const field of consumedFields) {\n if (!producedKeys.has(field)) {\n context.report({ node: taskCall, messageId: 'attributeMismatch', data: { field } });\n }\n }\n }\n },\n };\n },\n};\n\nexport const twilioTaskrouterAttributesMatchConsumerRule = rule;\n","/**\n * Flags `.task(...)` (TaskRouter Enqueue attributes) built by hand-interpolating\n * a request field into a template-literal/string JSON instead of using\n * JSON.stringify() (CWE-116/CWE-91, Finding B).\n */\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'TaskRouter .task() attributes must be built with JSON.stringify(), not raw string interpolation',\n category: 'security',\n cwe: 'CWE-116',\n owasp: 'CWE-91 XML/JSON Injection',\n rationale:\n 'Hand-building the Task attributes JSON by interpolating an unvalidated request field directly into a string literal breaks the moment that field contains a `\"` or `\\\\`. The resulting body is invalid JSON, and Twilio rejects the Enqueue with error 14221 (\"Provided Attributes JSON was not valid\") — turning a single unexpected character in a caller-controlled field (like a name with a quote in it) into a hard failure of the call flow.',\n docsUrl: 'https://www.twilio.com/docs/api/errors/14221',\n recommended: true,\n },\n messages: {\n rawJsonInterpolation:\n 'This .task() call builds JSON attributes via raw string interpolation instead of JSON.stringify() — a \"/\\\\\\\\ character in the interpolated value produces invalid JSON and Twilio error 14221.',\n },\n },\n create(context: any) {\n function isTaskCall(n: any): boolean {\n if (n?.type !== 'CallExpression') return false;\n const callee = n.callee;\n if (callee?.type !== 'MemberExpression') return false;\n return callee.property?.type === 'Identifier' && callee.property.name === 'task';\n }\n\n function hasInterpolatedExpression(templateLiteral: any): boolean {\n return (templateLiteral.expressions ?? []).length > 0;\n }\n\n return {\n CallExpression(node: any) {\n if (!isTaskCall(node)) return;\n const arg = node.arguments?.[0];\n if (!arg) return;\n\n if (arg.type === 'TemplateLiteral' && hasInterpolatedExpression(arg)) {\n context.report({ node, messageId: 'rawJsonInterpolation' });\n return;\n }\n\n // `'{ \"name\": \"' + req.body.Caller + '\", ... }'` concatenation form.\n if (arg.type === 'BinaryExpression' && arg.operator === '+') {\n context.report({ node, messageId: 'rawJsonInterpolation' });\n }\n },\n };\n },\n};\n\nexport const twilioEnqueueTaskJsonStringifyRule = rule;\n","/**\n * Flags a Media Streams interceptor/session map keyed by a phone-number-like\n * field (`from`/`customParameters.from`) instead of the unique `callSid`\n * Twilio provides on every `start` message (Finding F).\n */\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Media Streams session maps must be keyed by callSid, not phone number',\n category: 'reliability',\n rationale:\n 'A Map keyed on the caller\\'s phone number breaks the moment the same number places two concurrent calls — a retry after a dropped call, two family members sharing a line, a misdial-and-redial. The second map.set() silently overwrites the first call\\'s entry, and that first call\\'s downstream events (reservation-accepted, outbound-leg wiring) end up pointed at the wrong session, crossing audio streams between two unrelated calls. Twilio provides a unique callSid on every start message specifically to avoid this collision.',\n docsUrl: 'https://www.twilio.com/docs/voice/media-streams/websocket-messages',\n recommended: true,\n },\n messages: {\n keyedByPhoneNumber:\n 'This Map is keyed by \"{{key}}\" (a phone-number-like field) instead of callSid — two concurrent calls from the same number will silently overwrite each other\\'s entry.',\n },\n },\n create(context: any) {\n function isFromLikeIdentifier(n: any): string | null {\n if (n?.type === 'Identifier' && n.name === 'from') return 'from';\n if (\n n?.type === 'MemberExpression' &&\n n.property?.type === 'Identifier' &&\n n.property.name === 'from' &&\n !n.computed\n ) {\n return 'from';\n }\n return null;\n }\n\n function isMapMutationCall(n: any, methodNames: Set<string>): boolean {\n if (n?.type !== 'CallExpression') return false;\n const callee = n.callee;\n if (callee?.type !== 'MemberExpression') return false;\n return callee.property?.type === 'Identifier' && methodNames.has(callee.property.name);\n }\n\n const SET_OR_GET = new Set(['set', 'get']);\n\n return {\n 'Program:exit'(program: any) {\n // Only flag when callSid is available elsewhere in the file (e.g. on\n // the Media Streams `start` message) — i.e. the correct key existed\n // and was passed over, not just any unrelated Map<string, T>.\n let callSidAvailable = false;\n function scanForCallSid(n: any, depth = 0): void {\n if (callSidAvailable || !n || typeof n !== 'object' || depth > 60) return;\n if (Array.isArray(n)) {\n for (const item of n) scanForCallSid(item, depth + 1);\n return;\n }\n if (n.type === 'Identifier' && n.name === 'callSid') {\n callSidAvailable = true;\n return;\n }\n if (n.type === 'MemberExpression' && !n.computed && n.property?.type === 'Identifier' && n.property.name === 'callSid') {\n callSidAvailable = true;\n return;\n }\n for (const key of Object.keys(n)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = n[key];\n if (val && typeof val === 'object') scanForCallSid(val, depth + 1);\n }\n }\n scanForCallSid(program);\n if (!callSidAvailable) return;\n\n function walk(n: any, depth = 0): void {\n if (!n || typeof n !== 'object' || depth > 60) return;\n if (Array.isArray(n)) {\n for (const item of n) walk(item, depth + 1);\n return;\n }\n if (isMapMutationCall(n, SET_OR_GET)) {\n const firstArg = n.arguments?.[0];\n const key = isFromLikeIdentifier(firstArg);\n if (key) context.report({ node: n, messageId: 'keyedByPhoneNumber', data: { key } });\n }\n for (const k of Object.keys(n)) {\n if (k === 'parent' || k === 'loc' || k === 'range') continue;\n const val = n[k];\n if (val && typeof val === 'object') walk(val, depth + 1);\n }\n }\n walk(program);\n },\n };\n },\n};\n\nexport const twilioMediaStreamsKeyByCallSidRule = rule;\n","/**\n * Flags `await twilio.calls.create(...)` (or other Twilio REST calls) made\n * inside an async event-handler callback with no surrounding try/catch\n * (Finding G). An unhandled rejection there can crash the whole process.\n */\nconst REST_RESOURCE_METHODS = new Set(['create', 'update', 'remove', 'fetch']);\nconst EVENT_REGISTRATION_METHODS = new Set(['onStart', 'onStop', 'onMedia', 'onConnected', 'on']);\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Twilio REST calls inside event-handler callbacks must be wrapped in try/catch',\n category: 'reliability',\n rationale:\n 'Event-emitter style callbacks (onStart, onMessage, on(\"message\", ...)) are typically invoked via something like `callbacks.map((cb) => cb(event))`, which discards the returned promise. If the callback is `async` and calls `await twilio.calls.create(...)` with no try/catch, any Twilio REST error (invalid number, suspended account, rate limit) becomes an unhandled promise rejection. If the process has a global `unhandledRejection` handler that calls `process.exit()` (a common pattern), one failed outbound call takes down the entire server and every other in-progress call, not just the failing one.',\n docsUrl: 'https://www.twilio.com/docs/usage/webhooks/webhooks-faq',\n recommended: true,\n },\n messages: {\n missingTryCatch:\n 'This await twilio.{{resource}}.{{method}}() call is inside an event-handler callback with no surrounding try/catch — a REST API error here becomes an unhandled promise rejection that can crash the whole process.',\n },\n },\n create(context: any) {\n function isAwaitedTwilioRestCall(n: any): { resource: string; method: string } | null {\n if (n?.type !== 'AwaitExpression') return null;\n const call = n.argument;\n if (call?.type !== 'CallExpression') return null;\n const callee = call.callee;\n if (callee?.type !== 'MemberExpression') return null;\n const method = callee.property?.type === 'Identifier' ? callee.property.name : null;\n if (!method || !REST_RESOURCE_METHODS.has(method)) return null;\n\n const obj = callee.object;\n if (obj?.type !== 'MemberExpression') return null;\n const resource = obj.property?.type === 'Identifier' ? obj.property.name : null;\n if (!resource) return null;\n\n // The base object should ultimately be a Twilio client identifier\n // (commonly named `twilio`/`twilioClient`/bare `client`), not an\n // unrelated SDK whose identifier merely contains the word \"client\"\n // (e.g. `openaiClient`, `dbClient`).\n const base = obj.object;\n const baseName = base?.type === 'Identifier' ? base.name : null;\n if (!baseName || !/^(twilio\\w*|client)$/i.test(baseName)) return null;\n\n return { resource, method };\n }\n\n function isEventHandlerRegistration(n: any): boolean {\n if (n?.type !== 'CallExpression') return false;\n const callee = n.callee;\n if (callee?.type !== 'MemberExpression') return false;\n return callee.property?.type === 'Identifier' && EVENT_REGISTRATION_METHODS.has(callee.property.name);\n }\n\n function isAsyncCallback(n: any): boolean {\n return (n?.type === 'ArrowFunctionExpression' || n?.type === 'FunctionExpression') && n.async === true;\n }\n\n function posOf(n: any): number {\n if (typeof n?.range?.[0] === 'number') return n.range[0];\n const line = n?.loc?.start?.line ?? 0;\n const column = n?.loc?.start?.column ?? 0;\n return line * 1_000_000 + column;\n }\n function posEnd(n: any): number {\n if (typeof n?.range?.[1] === 'number') return n.range[1];\n const line = n?.loc?.end?.line ?? n?.loc?.start?.line ?? 0;\n const column = n?.loc?.end?.column ?? n?.loc?.start?.column ?? 0;\n return line * 1_000_000 + column;\n }\n\n function isWithinTryBlock(node: any, root: any): boolean {\n const tryRanges: Array<[number, number]> = [];\n function collectTryRanges(n: any, depth = 0): void {\n if (!n || typeof n !== 'object' || depth > 60) return;\n if (Array.isArray(n)) {\n for (const item of n) collectTryRanges(item, depth + 1);\n return;\n }\n if (n.type === 'TryStatement' && n.block) {\n tryRanges.push([posOf(n.block), posEnd(n.block)]);\n }\n for (const key of Object.keys(n)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = n[key];\n if (val && typeof val === 'object') collectTryRanges(val, depth + 1);\n }\n }\n collectTryRanges(root);\n\n const p = posOf(node);\n return tryRanges.some(([start, end]) => p >= start && p <= end);\n }\n\n return {\n CallExpression(node: any) {\n if (!isEventHandlerRegistration(node)) return;\n const callback = node.arguments?.find((a: any) => isAsyncCallback(a));\n if (!callback) return;\n\n const restCalls: Array<{ node: any; resource: string; method: string }> = [];\n function collect(n: any, depth = 0): void {\n if (!n || typeof n !== 'object' || depth > 40) return;\n if (Array.isArray(n)) {\n for (const item of n) collect(item, depth + 1);\n return;\n }\n const info = isAwaitedTwilioRestCall(n);\n if (info) restCalls.push({ node: n, ...info });\n for (const key of Object.keys(n)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = n[key];\n if (val && typeof val === 'object') collect(val, depth + 1);\n }\n }\n collect(callback.body);\n\n for (const call of restCalls) {\n if (!isWithinTryBlock(call.node, callback.body)) {\n context.report({\n node: call.node,\n messageId: 'missingTryCatch',\n data: { resource: call.resource, method: call.method },\n });\n }\n }\n },\n };\n },\n};\n\nexport const twilioAwaitOrCatchRestCallsInEventHandlersRule = rule;\n","/**\n * Flags TwiML built as a raw template literal containing `<Response>`/XML\n * tags, instead of the twilio SDK's VoiceResponse builder, which XML-escapes\n * interpolated values automatically (CWE-91, Finding C).\n */\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'TwiML responses must be built with the VoiceResponse builder, not raw XML template strings',\n category: 'security',\n cwe: 'CWE-91',\n rationale:\n 'The VoiceResponse builder XML-escapes every interpolated value automatically. A raw template literal that interpolates values directly into XML attribute or text positions has no such protection — if either value\\'s source ever changes to something attacker-influenced (e.g. a SIP header instead of a Twilio-controlled CallSid), unescaped `<`/`\"`/`&` characters can break out of the intended XML structure.',\n docsUrl: 'https://www.twilio.com/docs/voice/twiml/stream',\n recommended: true,\n },\n messages: {\n rawTwimlTemplate:\n 'TwiML is built here as a raw template literal with interpolated values instead of the VoiceResponse builder — interpolated values are not XML-escaped, unlike new VoiceResponse().',\n },\n },\n create(context: any) {\n function looksLikeTwimlXml(raw: string): boolean {\n return /<Response>|<Connect>|<Say>|<Stream\\b|<Enqueue\\b|<Dial\\b/.test(raw);\n }\n\n return {\n TemplateLiteral(node: any) {\n if ((node.expressions ?? []).length === 0) return;\n const raw = (node.quasis ?? []).map((q: any) => q.value?.raw ?? '').join('');\n if (!looksLikeTwimlXml(raw)) return;\n\n context.report({ node, messageId: 'rawTwimlTemplate' });\n },\n };\n },\n};\n\nexport const twilioUseTwimlBuilderNotStringTemplatesRule = rule;\n","/**\n * Best-effort heuristic: flags a Media Streams `.send()`/socket.send() call\n * site that forwards `media` payloads but never passes `isLast`/a mark\n * argument anywhere in the same file (Finding H). Conservative by design —\n * the audit notes this is \"mostly non-rule\" and prone to false positives,\n * so this only fires when there is unambiguously zero mark-pacing signal\n * in the whole file.\n */\nimport { findInSubtree } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Media Streams audio forwarding should use mark-based pacing to avoid buffer overflow',\n category: 'reliability',\n rationale:\n 'Twilio buffers at most 10 minutes of audio per bidirectional Stream. If audio chunks are forwarded with no mark events and no pacing, and the sender produces media faster than real-time (or playback stalls), Twilio stops accepting further audio for that Stream and emits warning 31931 (\"Media Discarded\") — silently dropping audio rather than erroring loudly.',\n docsUrl: 'https://www.twilio.com/docs/api/errors/31931',\n recommended: true,\n },\n messages: {\n noMarkPacing:\n 'This file forwards media payloads via send() but never passes isLast/a mark argument anywhere — sustained high-throughput forwarding risks Twilio silently discarding buffered audio (warning 31931).',\n },\n },\n create(context: any) {\n function isMediaSendCall(n: any): boolean {\n if (n?.type !== 'CallExpression') return false;\n const callee = n.callee;\n if (callee?.type !== 'MemberExpression') return false;\n if (callee.property?.type !== 'Identifier' || callee.property.name !== 'send') return false;\n // Must be sending something that looks like media/delta payloads.\n const arg = n.arguments?.[0];\n const argText =\n (arg?.type === 'ArrayExpression' &&\n (arg.elements ?? []).some(\n (el: any) => el?.type === 'MemberExpression' && el.property?.type === 'Identifier' && el.property.name === 'delta',\n )) ||\n (arg?.type === 'Identifier' && /delta|payload|media/i.test(arg.name));\n return !!argText;\n }\n\n function hasIsLastOrMarkSignal(program: any): boolean {\n let found = false;\n function walk(n: any, depth = 0): void {\n if (found || !n || typeof n !== 'object' || depth > 60) return;\n if (Array.isArray(n)) {\n for (const item of n) walk(item, depth + 1);\n return;\n }\n // Skip TS type-only constructs (e.g. `isLast?: boolean` in a type\n // signature is not an actual pacing call site).\n if (typeof n.type === 'string' && n.type.startsWith('TS')) return;\n\n if (n.type === 'CallExpression') {\n const callee = n.callee;\n if (callee?.type === 'MemberExpression' && callee.property?.type === 'Identifier' && callee.property.name === 'send') {\n const second = n.arguments?.[1];\n if (second?.type === 'Literal' && second.value === true) {\n found = true;\n return;\n }\n if (second?.type === 'Identifier' && /isLast/i.test(second.name)) {\n found = true;\n return;\n }\n }\n }\n // explicit `isLast` value-position identifier (param default, destructure, variable)\n if (n.type === 'Identifier' && n.name === 'isLast') {\n found = true;\n return;\n }\n\n for (const key of Object.keys(n)) {\n if (key === 'parent' || key === 'loc' || key === 'range' || key === 'typeAnnotation' || key === 'returnType') continue;\n const val = n[key];\n if (val && typeof val === 'object') walk(val, depth + 1);\n }\n }\n walk(program);\n return found;\n }\n\n return {\n 'Program:exit'(program: any) {\n const sendCalls: any[] = [];\n findInSubtree(program, (n) => {\n if (isMediaSendCall(n)) sendCalls.push(n);\n return false;\n });\n if (sendCalls.length === 0) return;\n if (hasIsLastOrMarkSignal(program)) return;\n\n // Report once per file at the first offending call site to keep\n // this conservative, per the audit's \"mostly non-rule\" guidance.\n context.report({ node: sendCalls[0], messageId: 'noMarkPacing' });\n },\n };\n },\n};\n\nexport const twilioMediaStreamsMarkPacingRule = rule;\n","/**\n * Flags two related gaps in Fastify Twilio webhook routes (Findings J, L):\n * - a route with a `body` schema but no `querystring` schema, while the\n * handler still reads `req.query.<field>`\n * - a route with no `schema` object at all, while the handler reads\n * `req.body.<field>`\n */\nimport { isPostRouteRegistration, findInSubtree } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Fastify Twilio webhook routes must declare a schema for every request input they read',\n category: 'correctness',\n rationale:\n 'A route that validates `body` but not `querystring` (or declares no schema at all) lets unvalidated, possibly-undefined fields flow downstream. If a later call does `value.toString()` or similar on a field that never arrived, that throws instead of failing the request cleanly with a 400 — the failure surfaces far from the actual missing-validation root cause.',\n docsUrl: 'https://www.twilio.com/docs/voice/twiml/stream',\n recommended: true,\n },\n messages: {\n missingQuerystringSchema:\n 'This route reads req.query.{{field}} but the route schema validates body without a matching querystring schema — a missing query param flows downstream as undefined instead of failing with a 400.',\n missingSchemaEntirely:\n 'This route reads req.body.{{field}} but declares no request schema at all — req.body is untyped and unvalidated before use.',\n },\n },\n create(context: any) {\n function getOptionsArg(routeCall: any): any {\n // server.post('/path', { ... }, handler) — options is arg[1] when 3 args.\n return routeCall.arguments?.length === 3 ? routeCall.arguments[1] : null;\n }\n\n function getHandlerArg(routeCall: any): any {\n const args = routeCall.arguments ?? [];\n return args[args.length - 1];\n }\n\n function hasSchemaProperty(optionsArg: any, propName: string): boolean {\n if (optionsArg?.type !== 'ObjectExpression') return false;\n const schemaProp = (optionsArg.properties ?? []).find(\n (p: any) => p.type === 'Property' && p.key?.type === 'Identifier' && p.key.name === 'schema',\n );\n if (!schemaProp || schemaProp.value?.type !== 'ObjectExpression') return false;\n return (schemaProp.value.properties ?? []).some(\n (p: any) => p.type === 'Property' && p.key?.type === 'Identifier' && p.key.name === propName,\n );\n }\n\n function hasAnySchema(optionsArg: any): boolean {\n if (optionsArg?.type !== 'ObjectExpression') return false;\n return (optionsArg.properties ?? []).some(\n (p: any) => p.type === 'Property' && p.key?.type === 'Identifier' && p.key.name === 'schema',\n );\n }\n\n function findReadFields(handlerBody: any, objectNames: Set<string>): Set<string> {\n const fields = new Set<string>();\n findInSubtree(handlerBody, (n) => {\n if (n?.type !== 'MemberExpression') return false;\n const obj = n.object;\n if (obj?.type !== 'MemberExpression') return false;\n if (obj.object?.type !== 'Identifier' || (obj.object.name !== 'req' && obj.object.name !== 'request')) return false;\n if (obj.property?.type !== 'Identifier' || !objectNames.has(obj.property.name)) return false;\n const field = n.property?.type === 'Identifier' ? n.property.name : null;\n if (field) fields.add(field);\n return false;\n });\n return fields;\n }\n\n return {\n CallExpression(node: any) {\n if (!isPostRouteRegistration(node)) return;\n\n const optionsArg = getOptionsArg(node);\n const handler = getHandlerArg(node);\n if (!handler || (handler.type !== 'ArrowFunctionExpression' && handler.type !== 'FunctionExpression')) return;\n\n const queryFields = findReadFields(handler.body, new Set(['query']));\n const bodyFields = findReadFields(handler.body, new Set(['body']));\n\n const hasBodySchema = hasSchemaProperty(optionsArg, 'body');\n const hasQuerystringSchema = hasSchemaProperty(optionsArg, 'querystring');\n\n if (queryFields.size > 0 && hasBodySchema && !hasQuerystringSchema) {\n const field = [...queryFields][0];\n context.report({ node, messageId: 'missingQuerystringSchema', data: { field } });\n }\n\n if (bodyFields.size > 0 && !hasAnySchema(optionsArg)) {\n const field = [...bodyFields][0];\n context.report({ node, messageId: 'missingSchemaEntirely', data: { field } });\n }\n },\n };\n },\n};\n\nexport const twilioValidateAllRequestInputsRule = rule;\n","/**\n * Flags a Media Streams `mark.name` field set to a number instead of a\n * string (Finding K). Twilio's documented mark schema requires a string.\n */\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Media Streams mark.name must be a string, not a number',\n category: 'correctness',\n rationale:\n 'Twilio\\'s documented Media Streams `mark` message schema and every example show `mark.name` as a string (e.g. \"my label\"). Setting it to a bare number — `Date.now()` is a common culprit — means JSON.stringify() serializes it as a numeric literal, not the documented string type, a latent type mismatch that surfaces once mark-based pacing actually depends on matching mark names.',\n docsUrl: 'https://www.twilio.com/docs/voice/media-streams/websocket-messages',\n recommended: true,\n },\n messages: {\n markNameNotString:\n 'mark.name is set to a non-string value here — Twilio\\'s documented schema requires mark.name to be a string (e.g. String(Date.now())).',\n },\n },\n create(context: any) {\n // Calls known to return a number — the common culprits for a bare,\n // unwrapped mark.name. Any other call (including string-returning\n // helpers like `someId.toString()` or a custom label generator) is left\n // alone since its return type can't be determined statically.\n const NUMERIC_CALLS = new Set(['Date.now', 'performance.now', 'Math.random', 'Math.floor', 'Math.round']);\n\n function isNumericLooking(n: any): boolean {\n if (!n) return false;\n if (n.type === 'Literal' && typeof n.value === 'number') return true;\n if (n.type === 'CallExpression') {\n const callee = n.callee;\n if (callee?.type === 'Identifier') return false;\n if (\n callee?.type === 'MemberExpression' &&\n callee.object?.type === 'Identifier' &&\n callee.property?.type === 'Identifier'\n ) {\n return NUMERIC_CALLS.has(`${callee.object.name}.${callee.property.name}`);\n }\n return false;\n }\n return false;\n }\n\n function findMarkNameProperty(markObjExpr: any): any {\n for (const p of markObjExpr.properties ?? []) {\n if (p.type !== 'Property') continue;\n const keyName = p.key?.type === 'Identifier' ? p.key.name : p.key?.type === 'Literal' ? p.key.value : null;\n if (keyName === 'name') return p;\n }\n return null;\n }\n\n return {\n Property(node: any) {\n const keyName = node.key?.type === 'Identifier' ? node.key.name : node.key?.type === 'Literal' ? node.key.value : null;\n if (keyName !== 'mark') return;\n if (node.value?.type !== 'ObjectExpression') return;\n\n const nameProp = findMarkNameProperty(node.value);\n if (!nameProp) return;\n if (!isNumericLooking(nameProp.value)) return;\n\n context.report({ node: nameProp, messageId: 'markNameNotString' });\n },\n };\n },\n};\n\nexport const twilioMediaStreamsMarkNameStringRule = rule;\n","/** Shared AST helpers for OpenAI Realtime provider rules. */\n\n/** True when a URL argument (string or template literal) targets the OpenAI Realtime endpoint. */\nexport function isOpenAIRealtimeUrlArg(node: any): boolean {\n if (!node) return false;\n if (node.type === 'Literal' && typeof node.value === 'string') {\n return node.value.includes('api.openai.com/v1/realtime');\n }\n if (node.type === 'TemplateLiteral') {\n return (node.quasis ?? []).some(\n (q: any) => typeof q?.value?.raw === 'string' && q.value.raw.includes('api.openai.com/v1/realtime'),\n );\n }\n return false;\n}\n\n/**\n * Collects every local variable name whose initializer is a string/template\n * literal containing the OpenAI Realtime URL, e.g. `const url = 'wss://api.openai.com/v1/realtime'`.\n */\nexport function collectOpenAIRealtimeUrlVarNames(program: any): Set<string> {\n const names = new Set<string>();\n visit(program);\n return names;\n\n function visit(node: any, depth = 0): void {\n if (!node || typeof node !== 'object' || depth > 40) return;\n if (Array.isArray(node)) {\n for (const n of node) visit(n, depth + 1);\n return;\n }\n if (node.type === 'VariableDeclarator' && node.id?.type === 'Identifier' && isOpenAIRealtimeUrlArg(node.init)) {\n names.add(node.id.name);\n }\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = node[key];\n if (val && typeof val === 'object') visit(val, depth + 1);\n }\n }\n}\n\n/**\n * True when `urlArgNode` resolves to the OpenAI Realtime URL — either directly\n * (string/template literal) or via a local variable in `urlVarNames`.\n */\nexport function isOpenAIRealtimeUrlNode(urlArgNode: any, urlVarNames: Set<string>): boolean {\n if (isOpenAIRealtimeUrlArg(urlArgNode)) return true;\n return urlArgNode?.type === 'Identifier' && urlVarNames.has(urlArgNode.name);\n}\n\n/** True for `new WebSocket(<openai realtime url>, ...)`, resolving simple url variables. */\nexport function isOpenAIRealtimeNewWebSocket(node: any, urlVarNames: Set<string> = new Set()): boolean {\n if (node?.type !== 'NewExpression') return false;\n if (node.callee?.type !== 'Identifier' || node.callee.name !== 'WebSocket') return false;\n return isOpenAIRealtimeUrlNode(node.arguments?.[0], urlVarNames);\n}\n\n/** Finds a Property node in an ObjectExpression by its key name (Identifier or string Literal). */\nexport function findProperty(objectExpression: any, propertyName: string): any {\n if (objectExpression?.type !== 'ObjectExpression') return null;\n for (const prop of objectExpression.properties ?? []) {\n if (prop?.type !== 'Property') continue;\n const key = prop.key;\n const name = key?.type === 'Identifier' ? key.name : key?.type === 'Literal' ? key.value : null;\n if (name === propertyName) return prop;\n }\n return null;\n}\n\n/**\n * Walks a VariableDeclarator's `init` (unwrapping `new WebSocket(...)` directly assigned to a\n * variable, e.g. `const callerSocket = new WebSocket(url, opts)`) and collects every local\n * variable name initialized to an OpenAI Realtime WebSocket.\n */\nexport function collectOpenAIRealtimeSocketVarNames(program: any): Set<string> {\n const urlVarNames = collectOpenAIRealtimeUrlVarNames(program);\n const names = new Set<string>();\n visit(program);\n return names;\n\n function visit(node: any, depth = 0): void {\n if (!node || typeof node !== 'object' || depth > 40) return;\n if (Array.isArray(node)) {\n for (const n of node) visit(n, depth + 1);\n return;\n }\n if (\n node.type === 'VariableDeclarator' &&\n node.id?.type === 'Identifier' &&\n isOpenAIRealtimeNewWebSocket(node.init, urlVarNames)\n ) {\n names.add(node.id.name);\n }\n // Also handle `this.#socket = new WebSocket(...)` / `this.socket = new WebSocket(...)`.\n if (\n node.type === 'AssignmentExpression' &&\n node.operator === '=' &&\n isOpenAIRealtimeNewWebSocket(node.right, urlVarNames)\n ) {\n const left = node.left;\n if (left?.type === 'Identifier') {\n names.add(left.name);\n } else if (left?.type === 'MemberExpression' && left.property) {\n const propName = left.property.name;\n if (typeof propName === 'string') names.add(propName);\n }\n }\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = node[key];\n if (val && typeof val === 'object') visit(val, depth + 1);\n }\n }\n}\n\n/** True when `objNode` refers to a tracked socket variable, either `socket` or `this.#socket`/`this.socket`. */\nexport function isTrackedSocketRef(objNode: any, socketVarNames: Set<string>): boolean {\n if (objNode?.type === 'Identifier') return socketVarNames.has(objNode.name);\n if (objNode?.type === 'MemberExpression' && objNode.property) {\n const propName = objNode.property.name;\n return typeof propName === 'string' && socketVarNames.has(propName);\n }\n return false;\n}\n\n/** True for `<socketVar>.on(<eventName>, <handler>)` where socketVar is one of `socketVarNames`. */\nexport function isSocketOnCall(node: any, socketVarNames: Set<string>, eventName: string): boolean {\n if (node?.type !== 'CallExpression') return false;\n const callee = node.callee;\n if (callee?.type !== 'MemberExpression') return false;\n const prop = callee.property;\n if (prop?.type !== 'Identifier' || prop.name !== 'on') return false;\n if (!isTrackedSocketRef(callee.object, socketVarNames)) return false;\n const firstArg = node.arguments?.[0];\n return firstArg?.type === 'Literal' && firstArg.value === eventName;\n}\n\n/** Collects `const name = '<string literal>'` / `const name = \\`<plain template>\\`` values. */\nexport function collectStringVarValues(program: any): Map<string, string> {\n const values = new Map<string, string>();\n visit(program);\n return values;\n\n function visit(node: any, depth = 0): void {\n if (!node || typeof node !== 'object' || depth > 40) return;\n if (Array.isArray(node)) {\n for (const n of node) visit(n, depth + 1);\n return;\n }\n if (node.type === 'VariableDeclarator' && node.id?.type === 'Identifier') {\n const init = node.init;\n if (init?.type === 'Literal' && typeof init.value === 'string') {\n values.set(node.id.name, init.value);\n } else if (init?.type === 'TemplateLiteral' && (init.expressions ?? []).length === 0) {\n values.set(node.id.name, (init.quasis ?? []).map((q: any) => q.value?.raw ?? '').join(''));\n }\n }\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = node[key];\n if (val && typeof val === 'object') visit(val, depth + 1);\n }\n }\n}\n\n/** Resolves a node to its string value: literal, plain template literal, or a tracked variable. */\nexport function resolveStringValue(node: any, stringVarValues: Map<string, string>): string | null {\n if (!node) return null;\n if (node.type === 'Literal' && typeof node.value === 'string') return node.value;\n if (node.type === 'TemplateLiteral' && (node.expressions ?? []).length === 0) {\n return (node.quasis ?? []).map((q: any) => q.value?.raw ?? '').join('');\n }\n if (node.type === 'Identifier' && stringVarValues.has(node.name)) {\n return stringVarValues.get(node.name) ?? null;\n }\n return null;\n}\n\n/** A source-order sortable position for a node. */\nexport function posOf(n: any): number {\n if (typeof n?.range?.[0] === 'number') return n.range[0];\n const line = n?.loc?.start?.line ?? 0;\n const column = n?.loc?.start?.column ?? 0;\n return line * 1_000_000 + column;\n}\n","import { collectOpenAIRealtimeUrlVarNames, findProperty, isOpenAIRealtimeNewWebSocket } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'OpenAI Realtime connections must not pin to the deprecated beta interface',\n category: 'correctness',\n docsUrl: 'https://developers.openai.com/api/docs/guides/realtime',\n rationale:\n \"OpenAI's current Realtime guide states that beta integrations must migrate to the GA interface before new work proceeds, and explicitly calls out removing the OpenAI-Beta: realtime=v1 header as a required step. Staying on the beta header keeps a connection locked to the legacy session shape and event names with no confirmed sunset date — a ticking liability rather than an active failure.\",\n recommended: true,\n },\n messages: {\n betaHeaderPresent:\n \"This OpenAI Realtime connection sends the deprecated 'OpenAI-Beta: realtime=v1' header instead of using the GA interface.\",\n },\n schema: [],\n },\n create(context: any) {\n let urlVarNames = new Set<string>();\n\n return {\n Program(node: any) {\n urlVarNames = collectOpenAIRealtimeUrlVarNames(node);\n },\n\n NewExpression(node: any) {\n if (!isOpenAIRealtimeNewWebSocket(node, urlVarNames)) return;\n\n const optionsArg = node.arguments?.[1];\n if (optionsArg?.type !== 'ObjectExpression') return;\n\n const headersProp = findProperty(optionsArg, 'headers');\n if (headersProp?.value?.type !== 'ObjectExpression') return;\n\n const betaProp = findProperty(headersProp.value, 'OpenAI-Beta');\n if (!betaProp) return;\n\n const value = betaProp.value;\n const isRealtimeV1 =\n value?.type === 'Literal' &&\n typeof value.value === 'string' &&\n value.value.includes('realtime=v1');\n if (!isRealtimeV1) return;\n\n context.report({ node: betaProp, messageId: 'betaHeaderPresent' });\n },\n };\n },\n};\n\nexport const openaiRealtimeMigrateBetaToGaRule = rule;\n","import { collectOpenAIRealtimeSocketVarNames, isSocketOnCall } from '../utils.js';\n\nconst LOG_METHOD_NAMES = new Set(['info', 'warn', 'error', 'log']);\n\nfunction isLogCall(node: any): { matches: boolean; calleeProp?: any } {\n if (node?.type !== 'CallExpression') return { matches: false };\n const callee = node.callee;\n if (callee?.type !== 'MemberExpression') return { matches: false };\n const prop = callee.property;\n if (prop?.type !== 'Identifier' || !LOG_METHOD_NAMES.has(prop.name)) return { matches: false };\n return { matches: true, calleeProp: prop };\n}\n\n/** True if `argNode` references `paramName` as a whole value (not a narrowed property access). */\nfunction referencesRawParam(argNode: any, paramName: string): boolean {\n if (!argNode) return false;\n\n // Direct identifier: logger.info(msg)\n if (argNode.type === 'Identifier' && argNode.name === paramName) return true;\n\n // msg.toString()\n if (\n argNode.type === 'CallExpression' &&\n argNode.callee?.type === 'MemberExpression' &&\n argNode.callee.object?.type === 'Identifier' &&\n argNode.callee.object.name === paramName &&\n argNode.callee.property?.type === 'Identifier' &&\n argNode.callee.property.name === 'toString'\n ) {\n return true;\n }\n\n // Template literal: `... ${msg} ...` or `... ${msg.toString()} ...`\n if (argNode.type === 'TemplateLiteral') {\n return (argNode.expressions ?? []).some((expr: any) => referencesRawParam(expr, paramName));\n }\n\n return false;\n}\n\nfunction findCallExpressions(node: any, out: any[], depth = 0): void {\n if (!node || typeof node !== 'object' || depth > 40) return;\n if (Array.isArray(node)) {\n for (const n of node) findCallExpressions(n, out, depth + 1);\n return;\n }\n if (node.type === 'CallExpression') out.push(node);\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = node[key];\n if (val && typeof val === 'object') findCallExpressions(val, out, depth + 1);\n }\n}\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Raw OpenAI Realtime message payloads must not be logged verbatim',\n category: 'security',\n cwe: 'CWE-532',\n docsUrl: 'https://developers.openai.com/api/docs/guides/realtime',\n rationale:\n 'Every inbound Realtime WebSocket message can include response.audio.delta payloads (base64-encoded live call audio) and, once transcription is wired up, transcript text. Logging the raw message object or string verbatim writes a durable, unredacted record of live conversation content into whatever log sink the application ships to.',\n recommended: true,\n },\n messages: {\n rawPayloadLogged:\n 'A raw OpenAI Realtime message is logged verbatim here, which can include live call audio or transcript content.',\n },\n schema: [],\n },\n create(context: any) {\n let socketVarNames = new Set<string>();\n\n return {\n Program(node: any) {\n socketVarNames = collectOpenAIRealtimeSocketVarNames(node);\n },\n\n CallExpression(node: any) {\n if (socketVarNames.size === 0) return;\n if (!isSocketOnCall(node, socketVarNames, 'message')) return;\n\n const handler = node.arguments?.[1];\n if (handler?.type !== 'ArrowFunctionExpression' && handler?.type !== 'FunctionExpression') return;\n\n const param = handler.params?.[0];\n if (param?.type !== 'Identifier') return;\n const paramName = param.name;\n\n const calls: any[] = [];\n findCallExpressions(handler.body, calls);\n\n for (const call of calls) {\n const { matches } = isLogCall(call);\n if (!matches) continue;\n const hasRawArg = (call.arguments ?? []).some((arg: any) => referencesRawParam(arg, paramName));\n if (hasRawArg) {\n context.report({ node: call, messageId: 'rawPayloadLogged' });\n }\n }\n },\n };\n },\n};\n\nexport const openaiRealtimeNoLogRawMessagePayloadsRule = rule;\n","import { collectOpenAIRealtimeSocketVarNames, isSocketOnCall } from '../utils.js';\n\nfunction isTypeMemberExpression(node: any): boolean {\n return node?.type === 'MemberExpression' && node.property?.type === 'Identifier' && node.property.name === 'type';\n}\n\n/**\n * Recursively collects every string literal compared against a `.type`\n * member expression — covers `if (x.type === 'foo')` and `switch (x.type) { case 'foo': }`.\n */\nfunction collectTypeComparisonLiterals(node: any, out: Set<string>, depth = 0): void {\n if (!node || typeof node !== 'object' || depth > 60) return;\n if (Array.isArray(node)) {\n for (const n of node) collectTypeComparisonLiterals(n, out, depth + 1);\n return;\n }\n\n if (node.type === 'BinaryExpression' && (node.operator === '===' || node.operator === '==')) {\n if (isTypeMemberExpression(node.left) && node.right?.type === 'Literal' && typeof node.right.value === 'string') {\n out.add(node.right.value);\n }\n if (isTypeMemberExpression(node.right) && node.left?.type === 'Literal' && typeof node.left.value === 'string') {\n out.add(node.left.value);\n }\n }\n\n if (node.type === 'SwitchStatement' && isTypeMemberExpression(node.discriminant)) {\n for (const c of node.cases ?? []) {\n if (c?.test?.type === 'Literal' && typeof c.test.value === 'string') out.add(c.test.value);\n }\n }\n\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = node[key];\n if (val && typeof val === 'object') collectTypeComparisonLiterals(val, out, depth + 1);\n }\n}\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'OpenAI Realtime message handlers must check for the API-level \"error\" server event',\n category: 'reliability',\n docsUrl: 'https://developers.openai.com/api/docs/api-reference/realtime_server_events',\n rationale:\n \"The Realtime API's own error server event — distinct from the WebSocket transport-level error event — covers rate limits, invalid session.update payloads, content-moderation blocks, and retired/invalid model ids. A message handler that branches on event types but never checks for 'error' lets the call continue silently with translation/processing permanently dead for that leg, with no operator-visible signal of why.\",\n recommended: true,\n },\n messages: {\n missingErrorBranch:\n \"This Realtime message handler branches on event types but never checks for message.type === 'error'.\",\n },\n schema: [],\n },\n create(context: any) {\n let socketVarNames = new Set<string>();\n\n return {\n Program(node: any) {\n socketVarNames = collectOpenAIRealtimeSocketVarNames(node);\n },\n\n CallExpression(node: any) {\n if (socketVarNames.size === 0) return;\n if (!isSocketOnCall(node, socketVarNames, 'message')) return;\n\n const handler = node.arguments?.[1];\n if (handler?.type !== 'ArrowFunctionExpression' && handler?.type !== 'FunctionExpression') return;\n\n const literals = new Set<string>();\n collectTypeComparisonLiterals(handler.body, literals);\n\n // No type-dispatch pattern at all — not the shape this rule targets.\n if (literals.size === 0) return;\n\n if (!literals.has('error')) {\n context.report({ node, messageId: 'missingErrorBranch' });\n }\n },\n };\n },\n};\n\nexport const openaiRealtimeHandleErrorServerEventRule = rule;\n","import { collectOpenAIRealtimeSocketVarNames, isSocketOnCall } from '../utils.js';\n\nconst RECONNECT_NAME_PATTERN = /reconnect/i;\n\n/** True when `subtree` contains a `new WebSocket(...)` or a call to something named like \"reconnect\". */\nfunction hasReconnectAttempt(node: any, depth = 0): boolean {\n if (!node || typeof node !== 'object' || depth > 60) return false;\n if (Array.isArray(node)) {\n return node.some((n) => hasReconnectAttempt(n, depth + 1));\n }\n\n if (node.type === 'NewExpression' && node.callee?.type === 'Identifier' && node.callee.name === 'WebSocket') {\n return true;\n }\n\n if (node.type === 'CallExpression') {\n const callee = node.callee;\n const calleeName =\n callee?.type === 'Identifier'\n ? callee.name\n : callee?.type === 'MemberExpression' && callee.property?.type === 'Identifier'\n ? callee.property.name\n : null;\n if (typeof calleeName === 'string' && RECONNECT_NAME_PATTERN.test(calleeName)) return true;\n }\n\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = node[key];\n if (val && typeof val === 'object' && hasReconnectAttempt(val, depth + 1)) return true;\n }\n return false;\n}\n\nconst rule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'A dropped OpenAI Realtime connection must be retried, not just logged',\n category: 'reliability',\n docsUrl: 'https://developers.openai.com/api/docs/guides/realtime',\n rationale:\n \"For a multi-minute phone call, a single transient OpenAI-side disconnect that is only logged on 'close' permanently kills translation/processing for the remainder of the call in that direction — the call itself stays connected and silently degraded, with neither party getting a signal that something stopped working.\",\n recommended: true,\n },\n messages: {\n noReconnectAttempt:\n \"This Realtime socket's close handler only logs and never attempts to reconnect.\",\n },\n schema: [],\n },\n create(context: any) {\n let socketVarNames = new Set<string>();\n\n return {\n Program(node: any) {\n socketVarNames = collectOpenAIRealtimeSocketVarNames(node);\n },\n\n CallExpression(node: any) {\n if (socketVarNames.size === 0) return;\n if (!isSocketOnCall(node, socketVarNames, 'close')) return;\n\n const handler = node.arguments?.[1];\n if (handler?.type !== 'ArrowFunctionExpression' && handler?.type !== 'FunctionExpression') return;\n\n if (!hasReconnectAttempt(handler.body)) {\n context.report({ node, messageId: 'noReconnectAttempt' });\n }\n },\n };\n },\n};\n\nexport const openaiRealtimeReconnectOnDropRule = rule;\n","import {\n collectOpenAIRealtimeUrlVarNames,\n collectStringVarValues,\n isOpenAIRealtimeNewWebSocket,\n resolveStringValue,\n} from '../utils.js';\n\nconst DATED_PREVIEW_MODEL_PATTERN = /model=[^&'\"`]*-preview-\\d{4}-\\d{2}-\\d{2}/;\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'OpenAI Realtime connections should not pin to a dated preview model snapshot',\n category: 'correctness',\n docsUrl: 'https://developers.openai.com/api/docs/api-reference/realtime-sessions',\n rationale:\n \"Dated preview snapshots are the category of model id OpenAI has historically retired with advance-notice sunset windows. Pinning to a dated preview snapshot rather than the floating GA alias (or a current dated GA snapshot) maximizes exposure to an eventual retirement, with no code path to detect or gracefully react to a model_not_found-style error if/when that happens.\",\n recommended: true,\n },\n messages: {\n datedPreviewSnapshot:\n 'This Realtime connection is pinned to a dated preview model snapshot instead of the GA alias.',\n },\n schema: [],\n },\n create(context: any) {\n let stringVarValues = new Map<string, string>();\n let urlVarNames = new Set<string>();\n\n return {\n Program(node: any) {\n stringVarValues = collectStringVarValues(node);\n urlVarNames = collectOpenAIRealtimeUrlVarNames(node);\n },\n\n NewExpression(node: any) {\n if (!isOpenAIRealtimeNewWebSocket(node, urlVarNames)) return;\n\n const urlArg = node.arguments?.[0];\n const urlString = resolveStringValue(urlArg, stringVarValues);\n if (!urlString) return;\n\n if (DATED_PREVIEW_MODEL_PATTERN.test(urlString)) {\n context.report({ node: urlArg, messageId: 'datedPreviewSnapshot' });\n }\n },\n };\n },\n};\n\nexport const openaiRealtimeAvoidDatedPreviewSnapshotsRule = rule;\n","import { findProperty } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: \"OpenAI Realtime session.update payloads should not rely on an unverified 'temperature' field\",\n category: 'correctness',\n docsUrl: 'https://developers.openai.com/api/docs/api-reference/realtime-sessions',\n rationale:\n \"Two independent fetches of the current Realtime sessions API reference did not surface 'temperature' as a documented session field. Sending an undocumented field is typically harmless (silently ignored), but code that depends on an assumed constraint (e.g. 'a hard floor of 0.6') for behavior like deterministic output is relying on a claim that is no longer traceable to any current, citable source.\",\n recommended: true,\n },\n messages: {\n unverifiedTemperatureField:\n \"This session.update payload sets 'temperature', a field not documented in the current GA Realtime sessions schema.\",\n },\n schema: [],\n },\n create(context: any) {\n return {\n ObjectExpression(node: any) {\n const typeProp = findProperty(node, 'type');\n const typeValue = typeProp?.value;\n const isSessionUpdate =\n typeValue?.type === 'Literal' && typeof typeValue.value === 'string' && typeValue.value === 'session.update';\n if (!isSessionUpdate) return;\n\n const sessionProp = findProperty(node, 'session');\n if (sessionProp?.value?.type !== 'ObjectExpression') return;\n\n const temperatureProp = findProperty(sessionProp.value, 'temperature');\n if (!temperatureProp) return;\n\n context.report({ node: temperatureProp, messageId: 'unverifiedTemperatureField' });\n },\n };\n },\n};\n\nexport const openaiRealtimeVerifyDeprecatedSessionFieldsRule = rule;\n","const QUEUE_CALL_NAME_PATTERN = /^(push|unshift|enqueue|queue)$/i;\n\nfunction isReadyStateOpenCheck(test: any): boolean {\n if (test?.type !== 'BinaryExpression' || (test.operator !== '===' && test.operator !== '==')) return false;\n\n const isReadyStateMember = (n: any) =>\n n?.type === 'MemberExpression' && n.property?.type === 'Identifier' && n.property.name === 'readyState';\n\n const isOpenValue = (n: any) =>\n (n?.type === 'MemberExpression' && n.property?.type === 'Identifier' && n.property.name === 'OPEN') ||\n (n?.type === 'Literal' && n.value === 1);\n\n return (isReadyStateMember(test.left) && isOpenValue(test.right)) ||\n (isReadyStateMember(test.right) && isOpenValue(test.left));\n}\n\n/** True if `node` contains a call that looks like enqueueing onto a buffer (push/unshift/enqueue/queue). */\nfunction hasQueueCall(node: any, depth = 0): boolean {\n if (!node || typeof node !== 'object' || depth > 40) return false;\n if (Array.isArray(node)) return node.some((n) => hasQueueCall(n, depth + 1));\n\n if (node.type === 'CallExpression') {\n const callee = node.callee;\n const calleeName =\n callee?.type === 'MemberExpression' && callee.property?.type === 'Identifier'\n ? callee.property.name\n : callee?.type === 'Identifier'\n ? callee.name\n : null;\n if (typeof calleeName === 'string' && QUEUE_CALL_NAME_PATTERN.test(calleeName)) return true;\n }\n\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue;\n const val = node[key];\n if (val && typeof val === 'object' && hasQueueCall(val, depth + 1)) return true;\n }\n return false;\n}\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Audio sent before an OpenAI Realtime socket is open must be buffered, not dropped',\n category: 'reliability',\n docsUrl: 'https://developers.openai.com/api/docs/voice/media-streams/websocket-messages',\n rationale:\n 'Caller audio can arrive before the Realtime WebSocket finishes its connect + session.update round-trip. A readyState !== OPEN branch that only logs and returns silently drops every audio chunk that arrives in that window, meaning the first fragment of speech is lost to translation/processing on every call.',\n recommended: true,\n },\n messages: {\n audioDroppedNotBuffered:\n 'Audio sent while this Realtime socket is not yet open is dropped here instead of being buffered and flushed once open.',\n },\n schema: [],\n },\n create(context: any) {\n return {\n IfStatement(node: any) {\n if (!isReadyStateOpenCheck(node.test)) return;\n if (!node.alternate) return;\n if (hasQueueCall(node.alternate)) return;\n\n context.report({ node: node.alternate, messageId: 'audioDroppedNotBuffered' });\n },\n };\n },\n};\n\nexport const openaiRealtimeBufferAudioUntilSessionReadyRule = rule;\n","import { collectOpenAIRealtimeUrlVarNames, findProperty, isOpenAIRealtimeNewWebSocket } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'OpenAI Realtime connections should send an OpenAI-Safety-Identifier header',\n category: 'security',\n docsUrl: 'https://developers.openai.com/api/docs/guides/realtime',\n rationale:\n \"OpenAI's Realtime guidance recommends including an OpenAI-Safety-Identifier header with a stable, privacy-preserving value (e.g. a hashed user/account id) on Realtime connections, to support OpenAI's abuse/safety monitoring for voice content. A connection that omits it gives OpenAI no way to correlate abusive sessions back to an account without per-connection metadata.\",\n recommended: true,\n },\n messages: {\n missingSafetyIdentifier:\n 'This OpenAI Realtime WebSocket connection does not send an OpenAI-Safety-Identifier header.',\n },\n schema: [],\n },\n create(context: any) {\n let urlVarNames = new Set<string>();\n\n return {\n Program(node: any) {\n urlVarNames = collectOpenAIRealtimeUrlVarNames(node);\n },\n\n NewExpression(node: any) {\n if (!isOpenAIRealtimeNewWebSocket(node, urlVarNames)) return;\n\n const optionsArg = node.arguments?.[1];\n const headersProp = optionsArg?.type === 'ObjectExpression' ? findProperty(optionsArg, 'headers') : null;\n const headersObj = headersProp?.value?.type === 'ObjectExpression' ? headersProp.value : null;\n\n const safetyIdProp = headersObj ? findProperty(headersObj, 'OpenAI-Safety-Identifier') : null;\n if (safetyIdProp) return;\n\n context.report({ node: headersObj ?? optionsArg ?? node, messageId: 'missingSafetyIdentifier' });\n },\n };\n },\n};\n\nexport const openaiRealtimeSendSafetyIdentifierRule = rule;\n","import { findProperty } from '../utils.js';\n\nconst rule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: \"OpenAI Realtime sessions should not configure 'whisper-1' for input transcription\",\n category: 'correctness',\n docsUrl: 'https://developers.openai.com/api/docs/guides/realtime-transcription',\n rationale:\n \"OpenAI's transcription guidance describes 'whisper-1' as for existing Whisper integrations that are not natively streaming, while 'gpt-realtime-whisper' is the natively-streaming option designed for realtime sessions. Configuring input_audio_transcription with 'whisper-1' is the wrong tool for a realtime session, adding latency/cost to a streaming pipeline.\",\n recommended: true,\n },\n messages: {\n nonStreamingTranscriptionModel:\n \"input_audio_transcription is configured with 'whisper-1', which is not natively streaming and not optimized for realtime sessions.\",\n },\n schema: [],\n },\n create(context: any) {\n return {\n ObjectExpression(node: any) {\n const typeProp = findProperty(node, 'type');\n const typeValue = typeProp?.value;\n const isSessionUpdate =\n typeValue?.type === 'Literal' && typeof typeValue.value === 'string' && typeValue.value === 'session.update';\n if (!isSessionUpdate) return;\n\n const sessionProp = findProperty(node, 'session');\n if (sessionProp?.value?.type !== 'ObjectExpression') return;\n\n const transcriptionProp = findProperty(sessionProp.value, 'input_audio_transcription');\n if (transcriptionProp?.value?.type !== 'ObjectExpression') return;\n\n const modelProp = findProperty(transcriptionProp.value, 'model');\n const modelValue = modelProp?.value;\n const isWhisper1 =\n modelValue?.type === 'Literal' && typeof modelValue.value === 'string' && modelValue.value === 'whisper-1';\n if (!isWhisper1) return;\n\n context.report({ node: modelProp, messageId: 'nonStreamingTranscriptionModel' });\n },\n };\n },\n};\n\nexport const openaiRealtimeTranscriptionModelChoiceRule = 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 { firebaseFirestoreRulesExpiredRule } from '../providers/firebase/rules/firestore-rules-expired.js';\nimport { firebaseIdTokenCookieFlagsRule } from '../providers/firebase/rules/id-token-cookie-flags.js';\nimport { firebaseMiddlewareTokenNotVerifiedRule } from '../providers/firebase/rules/middleware-token-not-verified.js';\nimport { firebaseHardcodedUserIdRule } from '../providers/firebase/rules/hardcoded-user-id.js';\nimport { firebaseAuthUserNotFoundDisclosureRule } from '../providers/firebase/rules/auth-user-not-found-disclosure.js';\nimport { firebaseSignupPasswordConfirmRule } from '../providers/firebase/rules/signup-password-confirm.js';\nimport { firebaseUseArrayUnionRemoveRule } from '../providers/firebase/rules/use-array-union-remove.js';\nimport { firebaseDuplicateInitializeAppRule } from '../providers/firebase/rules/duplicate-initialize-app.js';\nimport { firebaseOnSnapshotAsyncThrowRule } from '../providers/firebase/rules/onSnapshot-async-throw.js';\nimport { firebaseOnSnapshotMissingErrorCallbackRule } from '../providers/firebase/rules/onSnapshot-missing-error-callback.js';\nimport { firebaseFirestoreDocumentSizeGuardRule } from '../providers/firebase/rules/firestore-document-size-guard.js';\nimport { firebaseUseTimestampNowRule } from '../providers/firebase/rules/use-timestamp-now.js';\n\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';\nimport { tiptapUploadValidateFnVoidRule } from '../providers/tiptap/rules/upload-validate-fn-void.js';\nimport { tiptapScriptSrcHardcodedApiKeyRule } from '../providers/tiptap/rules/script-src-hardcoded-api-key.js';\nimport { tiptapDynamicScriptNoSriRule } from '../providers/tiptap/rules/dynamic-script-no-sri.js';\nimport { tiptapAddAttributesMissingRenderHTMLRule } from '../providers/tiptap/rules/addAttributes-missing-renderHTML.js';\nimport { tiptapAppendTransactionAddToHistoryRule } from '../providers/tiptap/rules/appendTransaction-add-to-history.js';\nimport { tiptapAppendTransactionFullScanRule } from '../providers/tiptap/rules/appendTransaction-full-scan.js';\nimport { tiptapAtomNodeWrapInRule } from '../providers/tiptap/rules/atom-node-wrap-in.js';\nimport { tiptapTwitterUrlRegexRule } from '../providers/tiptap/rules/twitter-url-regex.js';\nimport { tiptapDropHandlerPosPrecedenceRule } from '../providers/tiptap/rules/drop-handler-pos-precedence.js';\nimport { tiptapPreferTableKitRule } from '../providers/tiptap/rules/prefer-table-kit.js';\nimport { tiptapTiptapMarkdownMissingNodeSpecRule } from '../providers/tiptap/rules/tiptap-markdown-missing-node-spec.js';\nimport { elevenlabsValidateSignedUrlResponseRule } from '../providers/elevenlabs/rules/validate-signed-url-response.js';\nimport { elevenlabsNoErrorObjectLoggingRule } from '../providers/elevenlabs/rules/no-error-object-logging.js';\nimport { elevenlabsFetchTimeoutRequiredRule } from '../providers/elevenlabs/rules/fetch-timeout-required.js';\nimport { elevenlabsValidateAgentIdFormatRule } from '../providers/elevenlabs/rules/validate-agent-id-format.js';\nimport { elevenlabsSecureSessionIdGenerationRule } from '../providers/elevenlabs/rules/secure-session-id-generation.js';\nimport { elevenlabsConversationErrorRecoveryRule } from '../providers/elevenlabs/rules/conversation-error-recovery.js';\nimport { elevenlabsApiVersionPinningRule } from '../providers/elevenlabs/rules/api-version-pinning.js';\nimport { elevenlabsCheckHttpStatusBeforeJsonRule } from '../providers/elevenlabs/rules/check-http-status-before-json.js';\nimport { elevenlabsConversationCleanupOnErrorRule } from '../providers/elevenlabs/rules/conversation-cleanup-on-error.js';\nimport { elevenlabsEnvVarValidationRule } from '../providers/elevenlabs/rules/env-var-validation.js';\nimport { twilioValidateWebhookSignatureRule } from '../providers/twilio/rules/validate-webhook-signature.js';\nimport { twilioTaskrouterAttributesMatchConsumerRule } from '../providers/twilio/rules/taskrouter-attributes-match-consumer.js';\nimport { twilioEnqueueTaskJsonStringifyRule } from '../providers/twilio/rules/enqueue-task-json-stringify.js';\nimport { twilioMediaStreamsKeyByCallSidRule } from '../providers/twilio/rules/media-streams-key-by-call-sid.js';\nimport { twilioAwaitOrCatchRestCallsInEventHandlersRule } from '../providers/twilio/rules/await-or-catch-rest-calls-in-event-handlers.js';\nimport { twilioUseTwimlBuilderNotStringTemplatesRule } from '../providers/twilio/rules/use-twiml-builder-not-string-templates.js';\nimport { twilioMediaStreamsMarkPacingRule } from '../providers/twilio/rules/media-streams-mark-pacing.js';\nimport { twilioValidateAllRequestInputsRule } from '../providers/twilio/rules/validate-all-request-inputs.js';\nimport { twilioMediaStreamsMarkNameStringRule } from '../providers/twilio/rules/media-streams-mark-name-string.js';\nimport { openaiRealtimeMigrateBetaToGaRule } from '../providers/openai-realtime/rules/migrate-beta-to-ga.js';\nimport { openaiRealtimeNoLogRawMessagePayloadsRule } from '../providers/openai-realtime/rules/no-log-raw-message-payloads.js';\nimport { openaiRealtimeHandleErrorServerEventRule } from '../providers/openai-realtime/rules/handle-error-server-event.js';\nimport { openaiRealtimeReconnectOnDropRule } from '../providers/openai-realtime/rules/reconnect-on-drop.js';\nimport { openaiRealtimeAvoidDatedPreviewSnapshotsRule } from '../providers/openai-realtime/rules/avoid-dated-preview-snapshots.js';\nimport { openaiRealtimeVerifyDeprecatedSessionFieldsRule } from '../providers/openai-realtime/rules/verify-deprecated-session-fields.js';\nimport { openaiRealtimeBufferAudioUntilSessionReadyRule } from '../providers/openai-realtime/rules/buffer-audio-until-session-ready.js';\nimport { openaiRealtimeSendSafetyIdentifierRule } from '../providers/openai-realtime/rules/send-safety-identifier.js';\nimport { openaiRealtimeTranscriptionModelChoiceRule } from '../providers/openai-realtime/rules/transcription-model-choice.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 'firebase-firestore-rules-expired': firebaseFirestoreRulesExpiredRule,\n 'firebase-id-token-cookie-flags': firebaseIdTokenCookieFlagsRule,\n 'firebase-middleware-token-not-verified': firebaseMiddlewareTokenNotVerifiedRule,\n 'firebase-hardcoded-user-id': firebaseHardcodedUserIdRule,\n 'firebase-auth-user-not-found-disclosure': firebaseAuthUserNotFoundDisclosureRule,\n 'firebase-signup-password-confirm': firebaseSignupPasswordConfirmRule,\n 'firebase-use-array-union-remove': firebaseUseArrayUnionRemoveRule,\n 'firebase-duplicate-initialize-app': firebaseDuplicateInitializeAppRule,\n 'firebase-onSnapshot-async-throw': firebaseOnSnapshotAsyncThrowRule,\n 'firebase-onSnapshot-missing-error-callback': firebaseOnSnapshotMissingErrorCallbackRule,\n 'firebase-firestore-document-size-guard': firebaseFirestoreDocumentSizeGuardRule,\n 'firebase-use-timestamp-now': firebaseUseTimestampNowRule,\n\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 'tiptap-upload-validate-fn-void': tiptapUploadValidateFnVoidRule,\n 'tiptap-script-src-hardcoded-api-key': tiptapScriptSrcHardcodedApiKeyRule,\n 'tiptap-dynamic-script-no-sri': tiptapDynamicScriptNoSriRule,\n 'tiptap-addAttributes-missing-renderHTML': tiptapAddAttributesMissingRenderHTMLRule,\n 'tiptap-appendTransaction-add-to-history': tiptapAppendTransactionAddToHistoryRule,\n 'tiptap-appendTransaction-full-scan': tiptapAppendTransactionFullScanRule,\n 'tiptap-atom-node-wrap-in': tiptapAtomNodeWrapInRule,\n 'tiptap-twitter-url-regex': tiptapTwitterUrlRegexRule,\n 'tiptap-drop-handler-pos-precedence': tiptapDropHandlerPosPrecedenceRule,\n 'tiptap-prefer-table-kit': tiptapPreferTableKitRule,\n 'tiptap-tiptap-markdown-missing-node-spec': tiptapTiptapMarkdownMissingNodeSpecRule,\n\n 'elevenlabs-validate-signed-url-response': elevenlabsValidateSignedUrlResponseRule,\n 'elevenlabs-no-error-object-logging': elevenlabsNoErrorObjectLoggingRule,\n 'elevenlabs-fetch-timeout-required': elevenlabsFetchTimeoutRequiredRule,\n 'elevenlabs-validate-agent-id-format': elevenlabsValidateAgentIdFormatRule,\n 'elevenlabs-secure-session-id-generation': elevenlabsSecureSessionIdGenerationRule,\n 'elevenlabs-conversation-error-recovery': elevenlabsConversationErrorRecoveryRule,\n 'elevenlabs-api-version-pinning': elevenlabsApiVersionPinningRule,\n 'elevenlabs-check-http-status-before-json': elevenlabsCheckHttpStatusBeforeJsonRule,\n 'elevenlabs-conversation-cleanup-on-error': elevenlabsConversationCleanupOnErrorRule,\n 'elevenlabs-env-var-validation': elevenlabsEnvVarValidationRule,\n\n 'twilio-validate-webhook-signature': twilioValidateWebhookSignatureRule,\n 'twilio-taskrouter-attributes-match-consumer': twilioTaskrouterAttributesMatchConsumerRule,\n 'twilio-enqueue-task-json-stringify': twilioEnqueueTaskJsonStringifyRule,\n 'twilio-media-streams-key-by-call-sid': twilioMediaStreamsKeyByCallSidRule,\n 'twilio-await-or-catch-rest-calls-in-event-handlers': twilioAwaitOrCatchRestCallsInEventHandlersRule,\n 'twilio-use-twiml-builder-not-string-templates': twilioUseTwimlBuilderNotStringTemplatesRule,\n 'twilio-media-streams-mark-pacing': twilioMediaStreamsMarkPacingRule,\n 'twilio-validate-all-request-inputs': twilioValidateAllRequestInputsRule,\n 'twilio-media-streams-mark-name-string': twilioMediaStreamsMarkNameStringRule,\n\n 'openai-realtime-migrate-beta-to-ga': openaiRealtimeMigrateBetaToGaRule,\n 'openai-realtime-no-log-raw-message-payloads': openaiRealtimeNoLogRawMessagePayloadsRule,\n 'openai-realtime-handle-error-server-event': openaiRealtimeHandleErrorServerEventRule,\n 'openai-realtime-reconnect-on-drop': openaiRealtimeReconnectOnDropRule,\n 'openai-realtime-avoid-dated-preview-snapshots': openaiRealtimeAvoidDatedPreviewSnapshotsRule,\n 'openai-realtime-verify-deprecated-session-fields': openaiRealtimeVerifyDeprecatedSessionFieldsRule,\n 'openai-realtime-buffer-audio-until-session-ready': openaiRealtimeBufferAudioUntilSessionReadyRule,\n 'openai-realtime-send-safety-identifier': openaiRealtimeSendSafetyIdentifierRule,\n 'openai-realtime-transcription-model-choice': openaiRealtimeTranscriptionModelChoiceRule,\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 // A pattern only counts if no OTHER registered provider has a strictly\n // more specific pattern (one that contains this one as a substring) that\n // also matches — otherwise a broad host-only pattern (e.g. api.openai.com)\n // would falsely claim sources that actually match a more specific sibling\n // provider's path-qualified pattern (e.g. api.openai.com/v1/realtime).\n const urls = provider.detect.urlPatterns ?? [];\n const matchedUrl = urls.find((u) => {\n if (!allSources.includes(u)) return false;\n const isShadowedByMoreSpecificProvider = providers.some((other) => {\n if (other === provider) return false;\n return (other.detect.urlPatterns ?? []).some(\n (otherUrl) => otherUrl !== u && otherUrl.includes(u) && allSources.includes(otherUrl),\n );\n });\n return !isShadowedByMoreSpecificProvider;\n });\n if (matchedUrl) {\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":["import_node_fs","import_node_path","import_node_url","resolve","import_node_fs","import_node_path","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","rule","rule","rule","rule","rule","rule","rule","rule","rule","rule","rule","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","rule","rule","rule","findProperty","rule","findProperty","rule","rule","rule","rule","rule","rule","rule","rule","walk","rule","walk","rule","rule","propName","walk","rule","rule","walk","rule","rule","isResponseJsonCall","walk","rule","program","walk","rule","propName","program","walk","collectVarDeclarators","rule","program","rule","program","collectVarDeclarators","rule","rule","program","walk","rule","posOf","rule","rule","program","walk","rule","propName","rule","program","findProperty","propName","rule","findProperty","rule","rule","rule","rule","rule","findProperty","rule","rule","findProperty","rule","findProperty","registry","rule","import_node_fs","import_promises","import_node_path","import_node_path","pkg","walk","rule","require","os","import_node_path","rule","pc","import_picocolors","pc","import_node_fs","import_node_os","import_node_path","import_node_fs","import_node_path"]}
|