blackveil-dns 2.1.0 → 2.2.2
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 +51 -564
- package/dist/index.d.ts +44 -2
- package/dist/index.js +840 -3969
- package/dist/index.js.map +1 -1
- package/dist/stdio.js +904 -4127
- package/dist/stdio.js.map +1 -1
- package/package.json +6 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/dns-types.ts","../src/lib/config.ts","../src/schemas/dns.ts","../src/lib/dns-transport.ts","../src/lib/dns-records.ts","../packages/dns-checks/src/types.ts","../packages/dns-checks/src/scoring/model.ts","../packages/dns-checks/src/scoring/profiles.ts","../packages/dns-checks/src/scoring/config.ts","../packages/dns-checks/src/scoring/generic.ts","../packages/dns-checks/src/scoring/engine.ts","../src/lib/adaptive-weights.ts","../src/lib/sanitize.ts","../src/lib/server-version.ts","../packages/dns-checks/src/check-utils.ts","../packages/dns-checks/src/checks/dmarc-utils.ts","../packages/dns-checks/src/checks/spf-analysis.ts","../packages/dns-checks/src/checks/spf-trust-surface.ts","../packages/dns-checks/src/checks/check-spf.ts","../packages/dns-checks/src/checks/check-dmarc.ts","../packages/dns-checks/src/checks/dkim-analysis.ts","../packages/dns-checks/src/checks/check-dkim.ts","../packages/dns-checks/src/checks/dnssec-analysis.ts","../packages/dns-checks/src/checks/check-dnssec.ts","../packages/dns-checks/src/checks/ssl-analysis.ts","../packages/dns-checks/src/checks/check-ssl.ts","../packages/dns-checks/src/checks/mta-sts-analysis.ts","../packages/dns-checks/src/checks/check-mta-sts.ts","../packages/dns-checks/src/checks/mx-analysis.ts","../packages/dns-checks/src/checks/check-mx.ts","../packages/dns-checks/src/checks/caa-analysis.ts","../packages/dns-checks/src/checks/check-caa.ts","../packages/dns-checks/src/checks/check-bimi.ts","../packages/dns-checks/src/checks/ns-analysis.ts","../packages/dns-checks/src/checks/check-ns.ts","../packages/dns-checks/src/checks/check-tlsrpt.ts","../packages/dns-checks/src/checks/dane-analysis.ts","../packages/dns-checks/src/checks/check-dane.ts","../packages/dns-checks/src/checks/check-dane-https.ts","../packages/dns-checks/src/checks/check-svcb-https.ts","../packages/dns-checks/src/checks/subdomain-takeover-analysis.ts","../packages/dns-checks/src/checks/check-subdomain-takeover.ts","../packages/dns-checks/src/checks/http-security-analysis.ts","../packages/dns-checks/src/checks/check-http-security.ts","../packages/dns-checks/src/schemas/scoring.ts","../src/tools/check-bimi.ts","../src/tools/check-caa.ts","../src/tools/check-dkim.ts","../src/tools/check-dmarc.ts","../src/tools/check-dnssec.ts","../src/tools/lookalike-analysis.ts","../src/tools/check-lookalikes.ts","../src/tools/check-mta-sts.ts","../src/lib/provider-signature-source.ts","../src/lib/provider-signatures.ts","../src/tools/check-mx.ts","../src/tools/check-ns.ts","../src/tools/check-spf.ts","../src/tools/check-ssl.ts","../src/tools/check-subdomain-takeover.ts","../src/tools/check-tlsrpt.ts","../src/lib/output-sanitize.ts","../src/tools/explain-finding-data.ts","../src/tools/explain-finding.ts","../src/lib/category-interactions.ts","../src/lib/log.ts","../src/lib/cache.ts","../src/tools/check-http-security.ts","../src/tools/check-dane.ts","../src/tools/check-dane-https.ts","../src/tools/check-svcb-https.ts","../src/tools/scan/post-processing.ts","../src/tools/scan/maturity-staging.ts","../src/tools/scan/format-report.ts","../src/tools/scan-domain.ts"],"names":["topCat","topDelta","SEVERITY_PENALTIES","isExplicitConfidence","inferFindingConfidence","withConfidenceMetadata","computeCategoryScore","MISSING_CONTROL_REGEX","scoreIndicatesMissingControl","buildCheckResult","createFinding","HTTPS_TIMEOUT_MS","findings","parseCaaRecord","parseTlsaRecord","parts","usage","selector","matchingType","certData","parseMxFromRaw","z","makeQueryDNS","checkDnssec","normalizeDomain","checkSubdomainTakeover","lines","extractSpfSignalDomains","evidence","getParentDomain","hasDnssec"],"mappings":"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","file":"index.js","sourcesContent":["// SPDX-License-Identifier: BUSL-1.1\n\n/** Standard DNS record type codes */\nexport const RecordType = {\n\tA: 1,\n\tAAAA: 28,\n\tCNAME: 5,\n\tMX: 15,\n\tTXT: 16,\n\tNS: 2,\n\tSOA: 6,\n\tCAA: 257,\n\tTLSA: 52,\n\tDNSKEY: 48,\n\tDS: 43,\n\tRRSIG: 46,\n\tPTR: 12,\n\tSRV: 33,\n\tHTTPS: 65,\n} as const;\n\nexport type RecordTypeName = keyof typeof RecordType;\n\n/** A single DNS answer record from the DoH JSON response */\nexport interface DnsAnswer {\n\tname: string;\n\ttype: number;\n\tTTL: number;\n\tdata: string;\n}\n\n/** A single DNS authority record */\nexport interface DnsAuthority {\n\tname: string;\n\ttype: number;\n\tTTL: number;\n\tdata: string;\n}\n\n/** Cloudflare DoH JSON wire-format response */\nexport interface DohResponse {\n\tStatus: number;\n\tTC: boolean;\n\tRD: boolean;\n\tRA: boolean;\n\tAD: boolean;\n\tCD: boolean;\n\tQuestion: Array<{ name: string; type: number }>;\n\tAnswer?: DnsAnswer[];\n\tAuthority?: DnsAuthority[];\n}\n\n/** Configuration for a custom secondary DoH resolver (e.g., bv-dns on Oracle Cloud). */\nexport interface SecondaryDohConfig {\n\t/** DoH endpoint URL (e.g. https://doh.example.com/dns-query) */\n\tendpoint: string;\n\t/** Optional auth token sent as X-BV-Token header */\n\ttoken?: string;\n}\n\nexport interface QueryDnsOptions {\n\ttimeoutMs?: number;\n\tretries?: number;\n\tconfirmWithSecondaryOnEmpty?: boolean;\n\t/** When true, skip secondary resolver confirmation on empty results. Used in scan context for speed. */\n\tskipSecondaryConfirmation?: boolean;\n\t/** Scan-scoped DNS query cache. Stores Promises keyed by `domain:type:dnssecCheck` to deduplicate concurrent and sequential identical queries within a single scan. */\n\tqueryCache?: Map<string, Promise<DohResponse>>;\n\t/** Custom secondary DoH resolver. When set, used instead of Google DoH for empty-result confirmation. Falls back to Google if this resolver fails. */\n\tsecondaryDoh?: SecondaryDohConfig;\n}","// SPDX-License-Identifier: BUSL-1.1\n\nimport type { Tier } from '../schemas/primitives';\n\n/**\n * Centralized configuration for domain normalization and validation.\n */\nexport const BLOCKED_SUFFIXES = [\n\t'.local',\n\t'.localhost',\n\t'.internal',\n\t'.example',\n\t'.invalid',\n\t'.test',\n\t'.onion',\n\t'.lan',\n\t'.home',\n\t'.corp',\n\t'.intranet',\n];\nexport const BLOCKED_HOSTS = ['localhost', 'localhost.localdomain'];\nexport const BLOCKED_IP_PATTERNS = [\n\t/^127\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$/,\n\t/^10\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$/,\n\t/^172\\.(1[6-9]|2[0-9]|3[01])\\.[0-9]{1,3}\\.[0-9]{1,3}$/,\n\t/^192\\.168\\.[0-9]{1,3}\\.[0-9]{1,3}$/,\n\t/^169\\.254\\.[0-9]{1,3}\\.[0-9]{1,3}$/,\n\t/^0\\.0\\.0\\.0$/,\n\t/^::1$/,\n\t/^fc00:/i,\n\t/^fd[0-9a-f]{2}:/i,\n\t/^fe[89ab][0-9a-f]:/i,\n];\nexport const BLOCKED_DNS_REBINDING = ['.nip.io', '.sslip.io', '.xip.io', '.nip.direct'];\nexport const MAX_DOMAIN_LENGTH = 253;\nexport const MAX_LABEL_LENGTH = 63;\nexport const LABEL_REGEX = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/i;\n\n/** Hard limit on incoming JSON-RPC request body size (bytes). */\nexport const MAX_REQUEST_BODY_BYTES = 10_240;\n\n/** Timeout for outbound HTTPS fetches (SSL, MTA-STS policy, etc.). */\nexport const HTTPS_TIMEOUT_MS = 4_000;\n\n/** Default timeout for DNS-over-HTTPS queries. CF DoH p99 is <500ms. */\nexport const DNS_TIMEOUT_MS = 3_000;\n\n/** Default number of retry attempts for DNS-over-HTTPS queries. */\nexport const DNS_RETRIES = 1;\n\n/** Edge cache TTL (seconds) for outbound DoH fetch requests via Cloudflare's cf API. */\nexport const DOH_EDGE_CACHE_TTL = 300;\n\n/** Timeout (ms) after which a stuck INFLIGHT promise is evicted from the dedup map. */\nexport const INFLIGHT_CLEANUP_MS = 30_000;\n\n/** Base delay (ms) between DNS retry attempts. Actual delay = base * (attempt+1) + jitter. */\nexport const DNS_RETRY_BASE_DELAY_MS = 75;\n\n/**\n * When true, empty DoH answers from the primary resolver are optionally\n * confirmed with a secondary resolver to reduce false negatives.\n */\nexport const DNS_CONFIRM_WITH_SECONDARY_ON_EMPTY = true;\n\n/** Default cache TTL in seconds. Override via CACHE_TTL_SECONDS env var. */\nexport const DEFAULT_CACHE_TTL_SECONDS = 300;\n\n/**\n * Parse CACHE_TTL_SECONDS env var, clamping to [60, 3600].\n * Returns DEFAULT_CACHE_TTL_SECONDS when absent or invalid.\n */\nexport function parseCacheTtl(envValue?: string): number {\n\tif (!envValue) return DEFAULT_CACHE_TTL_SECONDS;\n\tconst parsed = Number(envValue);\n\tif (!Number.isFinite(parsed) || parsed < 60) return DEFAULT_CACHE_TTL_SECONDS;\n\treturn Math.min(parsed, 3600);\n}\n\n/**\n * Global daily free-tier request ceiling across all unauthenticated IPs.\n * Protects from abuse by capping free usage at a service-wide level.\n * Authenticated requests are exempt.\n */\nexport const GLOBAL_DAILY_TOOL_LIMIT = 500_000;\n\n/**\n * Free-tier daily tool quotas for unauthenticated callers.\n * Tools omitted from this map are governed only by baseline per-IP rate limits.\n */\n/** MCP API key tiers with daily scan quotas. Derived from the Zod TierSchema in schemas/primitives. */\nexport type McpApiKeyTier = Tier;\n\n/** Daily scan limits per API key tier (applies per tool unless overridden by TIER_TOOL_DAILY_LIMITS). */\nexport const TIER_DAILY_LIMITS: Record<McpApiKeyTier, number> = {\n\tfree: 50,\n\tagent: 200,\n\tdeveloper: 500,\n\tenterprise: 10_000,\n\tpartner: 100_000,\n};\n\n/**\n * Per-tool daily limit overrides for specific tiers.\n * When a tier+tool combo exists here, it takes precedence over the flat TIER_DAILY_LIMITS value.\n */\nexport const TIER_TOOL_DAILY_LIMITS: Partial<Record<McpApiKeyTier, Record<string, number>>> = {\n\tpartner: {\n\t\tscan_domain: 100_000,\n\t\tscan: 100_000,\n\t\tcompare_baseline: 100_000,\n\t\tcheck_spf: 500_000,\n\t\tcheck_dmarc: 500_000,\n\t\tcheck_dkim: 500_000,\n\t\tcheck_mx: 500_000,\n\t\tcheck_ns: 500_000,\n\t\tcheck_ssl: 500_000,\n\t\tcheck_dnssec: 500_000,\n\t\tcheck_mta_sts: 500_000,\n\t\tcheck_caa: 500_000,\n\t\tcheck_bimi: 500_000,\n\t\tcheck_tlsrpt: 500_000,\n\t\tcheck_lookalikes: 50_000,\n\t\tcheck_shadow_domains: 50_000,\n\t\tcheck_txt_hygiene: 500_000,\n\t\tcheck_http_security: 500_000,\n\t\tcheck_dane: 500_000,\n\t\tcheck_mx_reputation: 50_000,\n\t\tcheck_srv: 500_000,\n\t\tcheck_zone_hygiene: 500_000,\n\t\texplain_finding: 500_000,\n\t},\n};\n\nexport const FREE_TOOL_DAILY_LIMITS: Record<string, number> = {\n\tscan_domain: 75,\n\tscan: 75,\n\tcheck_spf: 200,\n\tcheck_dmarc: 200,\n\tcheck_dkim: 200,\n\tcheck_mx: 200,\n\tcheck_ns: 200,\n\tcheck_ssl: 200,\n\tcheck_dnssec: 200,\n\tcheck_mta_sts: 200,\n\tcheck_caa: 200,\n\tcheck_bimi: 200,\n\tcheck_tlsrpt: 200,\n\tcheck_lookalikes: 20,\n\texplain_finding: 200,\n\tcompare_baseline: 150,\n\tcheck_shadow_domains: 20,\n\tcheck_txt_hygiene: 200,\n\tcheck_http_security: 200,\n\tcheck_dane: 200,\n\tcheck_mx_reputation: 20,\n\tcheck_srv: 200,\n\tcheck_zone_hygiene: 200,\n\tgenerate_fix_plan: 75,\n\tgenerate_spf_record: 200,\n\tgenerate_dmarc_record: 200,\n\tgenerate_dkim_config: 200,\n\tgenerate_mta_sts_policy: 200,\n\tget_benchmark: 100,\n\tget_provider_insights: 50,\n\tassess_spoofability: 150,\n\tcheck_resolver_consistency: 50,\n\tmap_supply_chain: 75,\n\tanalyze_drift: 75,\n\tvalidate_fix: 200,\n\tgenerate_rollout_plan: 150,\n\tresolve_spf_chain: 100,\n\tdiscover_subdomains: 50,\n\tmap_compliance: 75,\n\tsimulate_attack_paths: 75,\n};\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { z } from 'zod';\n\n/** DNS answer record from DoH response. */\nexport const DnsAnswerSchema = z.object({\n\tname: z.string(),\n\ttype: z.number(),\n\tTTL: z.number().optional(),\n\tdata: z.string(),\n});\n\n/** DNS authority record from DoH response. */\nexport const DnsAuthoritySchema = z.object({\n\tname: z.string(),\n\ttype: z.number(),\n\tTTL: z.number().optional(),\n\tdata: z.string(),\n});\n\n/** Complete DoH JSON response. Validates shape before casting. */\nexport const DohResponseSchema = z\n\t.object({\n\t\tStatus: z.number().finite(),\n\t\tTC: z.boolean().optional(),\n\t\tRD: z.boolean().optional(),\n\t\tRA: z.boolean().optional(),\n\t\tAD: z.boolean().optional(),\n\t\tCD: z.boolean().optional(),\n\t\tQuestion: z.array(z.object({ name: z.string(), type: z.unknown() })).optional(),\n\t\tAnswer: z.array(DnsAnswerSchema).optional(),\n\t\tAuthority: z.array(DnsAuthoritySchema).optional(),\n\t})\n\t.passthrough();\n\n/** Parsed CAA record. */\nexport const CaaRecordSchema = z.object({\n\tflags: z.number(),\n\ttag: z.string(),\n\tvalue: z.string(),\n});\n\n/** Parsed TLSA record. */\nexport const TlsaRecordSchema = z.object({\n\tusage: z.number(),\n\tselector: z.number(),\n\tmatchingType: z.number(),\n\tcertData: z.string(),\n});\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { DNS_TIMEOUT_MS, DNS_RETRIES, DNS_CONFIRM_WITH_SECONDARY_ON_EMPTY, DOH_EDGE_CACHE_TTL, DNS_RETRY_BASE_DELAY_MS } from './config';\nimport { type DohResponse, type QueryDnsOptions, RecordType, type RecordTypeName } from './dns-types';\nimport { DohResponseSchema } from '../schemas/dns';\n\nconst DOH_ENDPOINT = 'https://cloudflare-dns.com/dns-query';\nconst GOOGLE_DOH_ENDPOINT = 'https://dns.google/resolve';\n\nfunction buildDohUrl(endpoint: string, domain: string, type: RecordTypeName, dnssecCheck: boolean): string {\n\tconst params = new URLSearchParams({\n\t\tname: domain,\n\t\ttype,\n\t\t...(dnssecCheck ? { cd: '0' } : {}),\n\t});\n\n\treturn `${endpoint}?${params.toString()}`;\n}\n\nfunction hasTypedAnswers(response: DohResponse, type: RecordTypeName): boolean {\n\treturn (response.Answer ?? []).some((answer) => answer.type === RecordType[type]);\n}\n\nasync function fetchDohResponse(url: string, timeoutMs: number): Promise<DohResponse | null> {\n\tconst controller = new AbortController();\n\tconst timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n\ttry {\n\t\tconst response = await fetch(url, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: { Accept: 'application/dns-json' },\n\t\t\tsignal: controller.signal,\n\t\t\tcf: { cacheTtl: DOH_EDGE_CACHE_TTL, cacheEverything: true },\n\t\t});\n\t\tif (!response.ok) return null;\n\t\tconst data = await response.json();\n\t\tconst parsed = DohResponseSchema.safeParse(data);\n\t\tif (!parsed.success) return null;\n\t\treturn parsed.data as DohResponse;\n\t} catch {\n\t\treturn null;\n\t} finally {\n\t\tclearTimeout(timeout);\n\t}\n}\n\nasync function queryDnsFromEndpoint(\n\tendpoint: string,\n\tdomain: string,\n\ttype: RecordTypeName,\n\tdnssecCheck: boolean,\n\ttimeoutMs: number,\n): Promise<DohResponse | null> {\n\treturn fetchDohResponse(buildDohUrl(endpoint, domain, type, dnssecCheck), timeoutMs);\n}\n\n/**\n * Fetch a DoH response from an endpoint with optional auth header.\n * Used for custom secondary resolvers (e.g., bv-dns) that may require authentication.\n * Does NOT use Cloudflare edge cache (`cf` directive) since the target is an external origin.\n */\nasync function fetchDohWithAuth(url: string, timeoutMs: number, token?: string): Promise<DohResponse | null> {\n\tconst controller = new AbortController();\n\tconst timeout = setTimeout(() => controller.abort(), timeoutMs);\n\ttry {\n\t\tconst headers: Record<string, string> = { Accept: 'application/dns-json' };\n\t\tif (token) headers['X-BV-Token'] = token;\n\t\tconst response = await fetch(url, {\n\t\t\tmethod: 'GET',\n\t\t\theaders,\n\t\t\tsignal: controller.signal,\n\t\t});\n\t\tif (!response.ok) return null;\n\t\tconst data = await response.json();\n\t\tconst parsed = DohResponseSchema.safeParse(data);\n\t\tif (!parsed.success) return null;\n\t\treturn parsed.data as DohResponse;\n\t} catch {\n\t\treturn null;\n\t} finally {\n\t\tclearTimeout(timeout);\n\t}\n}\n\n/** Error thrown when a DNS query fails */\nexport class DnsQueryError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly domain: string,\n\t\tpublic readonly recordType: string,\n\t\tpublic readonly status?: number,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'DnsQueryError';\n\t}\n}\n\n/**\n * Query Cloudflare DoH for DNS records.\n *\n * When `opts.queryCache` is provided, deduplicates concurrent and sequential\n * identical queries within a single scan by caching the Promise keyed by\n * `domain:type:dnssecCheck`. Failed queries are evicted so retries can re-attempt.\n *\n * @param domain - The domain name to query\n * @param type - DNS record type name (e.g. \"TXT\", \"MX\", \"A\")\n * @param dnssecCheck - If true, sets the CD=0 flag to request DNSSEC validation\n * @returns The full DoH JSON response\n */\nexport async function queryDns(domain: string, type: RecordTypeName, dnssecCheck = false, opts?: QueryDnsOptions): Promise<DohResponse> {\n\tconst cache = opts?.queryCache;\n\tif (!cache) {\n\t\treturn queryDnsUncached(domain, type, dnssecCheck, opts);\n\t}\n\n\tconst cacheKey = `${domain}:${type}:${dnssecCheck}`;\n\tconst existing = cache.get(cacheKey);\n\tif (existing) {\n\t\treturn existing;\n\t}\n\n\tconst promise = queryDnsUncached(domain, type, dnssecCheck, opts);\n\tcache.set(cacheKey, promise);\n\tpromise.catch(() => cache.delete(cacheKey));\n\treturn promise;\n}\n\nasync function queryDnsUncached(domain: string, type: RecordTypeName, dnssecCheck = false, opts?: QueryDnsOptions): Promise<DohResponse> {\n\tconst timeoutMs = opts?.timeoutMs ?? DNS_TIMEOUT_MS;\n\tconst retries = opts?.retries ?? DNS_RETRIES;\n\tconst confirmWithSecondaryOnEmpty = opts?.confirmWithSecondaryOnEmpty ?? DNS_CONFIRM_WITH_SECONDARY_ON_EMPTY;\n\tconst url = buildDohUrl(DOH_ENDPOINT, domain, type, dnssecCheck);\n\n\tfor (let attempt = 0; attempt <= retries; attempt++) {\n\t\tconst controller = new AbortController();\n\t\tconst timeout = setTimeout(() => controller.abort(), timeoutMs);\n\t\tlet response: Response;\n\n\t\ttry {\n\t\t\tresponse = await fetch(url, {\n\t\t\t\tmethod: 'GET',\n\t\t\t\theaders: { Accept: 'application/dns-json' },\n\t\t\t\tsignal: controller.signal,\n\t\t\t\tcf: { cacheTtl: DOH_EDGE_CACHE_TTL, cacheEverything: true },\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tclearTimeout(timeout);\n\t\t\tif (err instanceof DOMException && err.name === 'AbortError') {\n\t\t\t\tif (attempt < retries) {\n\t\t\t\t\tawait new Promise((r) => setTimeout(r, DNS_RETRY_BASE_DELAY_MS * (attempt + 1) + Math.random() * 50));\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthrow new DnsQueryError(`DNS query timed out after ${timeoutMs}ms`, domain, type);\n\t\t\t}\n\t\t\tif (attempt < retries) {\n\t\t\t\tawait new Promise((r) => setTimeout(r, DNS_RETRY_BASE_DELAY_MS * (attempt + 1) + Math.random() * 50));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow new DnsQueryError(`DNS query failed: ${err instanceof Error ? err.message : String(err)}`, domain, type);\n\t\t}\n\n\t\tclearTimeout(timeout);\n\n\t\tif (!response.ok) {\n\t\t\tif (attempt < retries && response.status >= 500) {\n\t\t\t\tawait new Promise((r) => setTimeout(r, DNS_RETRY_BASE_DELAY_MS * (attempt + 1) + Math.random() * 50));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow new DnsQueryError(`DoH returned HTTP ${response.status}`, domain, type, response.status);\n\t\t}\n\n\t\tconst raw = await response.json();\n\t\tconst validated = DohResponseSchema.safeParse(raw);\n\t\tif (!validated.success) {\n\t\t\tthrow new DnsQueryError('Invalid DoH response format', domain, type);\n\t\t}\n\t\tconst data = validated.data as DohResponse;\n\n\t\tif (confirmWithSecondaryOnEmpty && !opts?.skipSecondaryConfirmation && !hasTypedAnswers(data, type)) {\n\t\t\t// Try custom secondary (bv-dns) first if configured\n\t\t\tif (opts?.secondaryDoh?.endpoint) {\n\t\t\t\tconst bvDns = await fetchDohWithAuth(\n\t\t\t\t\tbuildDohUrl(opts.secondaryDoh.endpoint, domain, type, dnssecCheck),\n\t\t\t\t\ttimeoutMs,\n\t\t\t\t\topts.secondaryDoh.token,\n\t\t\t\t);\n\t\t\t\tif (bvDns && hasTypedAnswers(bvDns, type)) {\n\t\t\t\t\treturn bvDns;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Google DoH as final fallback\n\t\t\tconst google = await queryDnsFromEndpoint(GOOGLE_DOH_ENDPOINT, domain, type, dnssecCheck, timeoutMs);\n\t\t\tif (google && hasTypedAnswers(google, type)) {\n\t\t\t\treturn google;\n\t\t\t}\n\t\t}\n\n\t\treturn data;\n\t}\n\n\tthrow new DnsQueryError('DNS query failed after retries', domain, type);\n}","// SPDX-License-Identifier: BUSL-1.1\n\nimport { queryDns } from './dns-transport';\nimport { RecordType, type QueryDnsOptions, type RecordTypeName } from './dns-types';\nimport { CaaRecordSchema, TlsaRecordSchema } from '../schemas/dns';\n\n/** Parsed CAA record with flags, tag, and value */\nexport interface CaaRecord {\n\tflags: number;\n\ttag: string;\n\tvalue: string;\n}\n\n/** Parsed PTR record hostname */\nexport interface PtrRecord {\n\thostname: string;\n}\n\n/** Parsed SRV record with priority, weight, port, and target */\nexport interface SrvRecord {\n\tpriority: number;\n\tweight: number;\n\tport: number;\n\ttarget: string;\n}\n\n/** Parsed TLSA record with usage, selector, matching type, and certificate data */\nexport interface TlsaRecord {\n\tusage: number;\n\tselector: number;\n\tmatchingType: number;\n\tcertData: string;\n}\n\n/**\n * Query DNS and return just the answer data strings.\n * Returns an empty array if no answers are found.\n */\nexport async function queryDnsRecords(domain: string, type: RecordTypeName, opts?: QueryDnsOptions): Promise<string[]> {\n\tconst resp = await queryDns(domain, type, false, opts);\n\treturn (resp.Answer ?? []).filter((answer) => answer.type === RecordType[type]).map((answer) => answer.data);\n}\n\n/**\n * Query TXT records, concatenate multi-string values, and unescape DNS\n * presentation-format backslash sequences.\n *\n * Cloudflare DoH returns TXT data with surrounding quotes and multiple\n * strings separated by `\" \"`. Per RFC 7208 §3.3, multi-string TXT records\n * MUST be concatenated without adding spaces. Some nameservers also emit\n * RFC 1035 §5.1 backslash escapes (e.g. `\\;` for a literal semicolon);\n * we unescape both `\\X` (single-char) and `\\DDD` (decimal octet) forms.\n */\nexport async function queryTxtRecords(domain: string, opts?: QueryDnsOptions): Promise<string[]> {\n\tconst records = await queryDnsRecords(domain, 'TXT', opts);\n\treturn records.map((record) =>\n\t\tunescapeDnsTxt(\n\t\t\trecord\n\t\t\t\t.replace(/\" \"/g, '')\n\t\t\t\t.replace(/^\"|\"$/g, ''),\n\t\t),\n\t);\n}\n\n/**\n * Unescape DNS presentation-format backslash sequences in TXT record data.\n * Handles `\\DDD` (decimal octet 000–255) and `\\X` (literal character).\n *\n * Some DoH providers double-escape (e.g. `\\\\;` in the JS string for what\n * should be a plain `;`), so we loop until the string stabilises.\n */\nexport function unescapeDnsTxt(text: string): string {\n\tconst unescape = (s: string) =>\n\t\ts.replace(/\\\\(\\d{3})|\\\\(.)/g, (_, decimal, ch) => {\n\t\t\tif (decimal !== undefined) {\n\t\t\t\tconst code = parseInt(decimal, 10);\n\t\t\t\treturn code <= 255 ? String.fromCharCode(code) : `\\\\${decimal}`;\n\t\t\t}\n\t\t\treturn ch;\n\t\t});\n\n\tlet result = text;\n\tfor (let i = 0; i < 2; i++) {\n\t\tconst next = unescape(result);\n\t\tif (next === result) break;\n\t\tresult = next;\n\t}\n\treturn result;\n}\n\n/**\n * Check if a domain has valid DNSSEC by examining the AD (Authenticated Data) flag.\n * Returns true if the response was DNSSEC-validated.\n */\nexport async function checkDnssec(domain: string, opts?: QueryDnsOptions): Promise<boolean> {\n\tconst resp = await queryDns(domain, 'A', true, opts);\n\treturn resp.AD === true;\n}\n\n/**\n * Parse a single CAA record data string.\n * Handles both human-readable format (e.g. `0 issue \"letsencrypt.org\"`)\n * and Cloudflare DoH hex wire format (e.g. `\\# 19 00 05 69 73 73 75 65...`).\n *\n * Wire format bytes: flags(1) + tag_length(1) + tag(tag_length) + value(rest)\n */\nexport function parseCaaRecord(data: string): CaaRecord | null {\n\tif (data.startsWith('\\\\#') || data.startsWith('#')) {\n\t\tconst parts = data.trim().split(/\\s+/);\n\t\tconst hexStart = parts[0] === '\\\\#' || parts[0] === '#' ? 2 : 1;\n\t\tconst hexBytes = parts.slice(hexStart);\n\t\tif (hexBytes.length < 3) return null;\n\n\t\tconst flags = parseInt(hexBytes[0], 16);\n\t\tconst tagLen = parseInt(hexBytes[1], 16);\n\t\tif (isNaN(flags) || isNaN(tagLen) || hexBytes.length < 2 + tagLen) return null;\n\n\t\tconst tag = hexBytes\n\t\t\t.slice(2, 2 + tagLen)\n\t\t\t.map((hexByte) => String.fromCharCode(parseInt(hexByte, 16)))\n\t\t\t.join('');\n\t\tconst value = hexBytes\n\t\t\t.slice(2 + tagLen)\n\t\t\t.map((hexByte) => String.fromCharCode(parseInt(hexByte, 16)))\n\t\t\t.join('');\n\n\t\tconst record = { flags, tag: tag.toLowerCase(), value };\n\t\treturn CaaRecordSchema.safeParse(record).success ? record : null;\n\t}\n\n\tconst match = data.match(/^(\\d+)\\s+(\\S+)\\s+\"?([^\"]*)\"?\\s*$/);\n\tif (match) {\n\t\tconst record = {\n\t\t\tflags: parseInt(match[1], 10),\n\t\t\ttag: match[2].toLowerCase(),\n\t\t\tvalue: match[3],\n\t\t};\n\t\treturn CaaRecordSchema.safeParse(record).success ? record : null;\n\t}\n\n\treturn null;\n}\n\n/**\n * Query CAA records and parse them into structured objects.\n * Handles both human-readable and hex wire format from DoH.\n */\nexport async function queryCaaRecords(domain: string, opts?: QueryDnsOptions): Promise<CaaRecord[]> {\n\tconst records = await queryDnsRecords(domain, 'CAA', opts);\n\treturn records.map(parseCaaRecord).filter((record): record is CaaRecord => record !== null);\n}\n\n/**\n * Query MX records and parse them into priority + exchange pairs.\n */\nexport async function queryMxRecords(domain: string, opts?: QueryDnsOptions): Promise<Array<{ priority: number; exchange: string }>> {\n\tconst records = await queryDnsRecords(domain, 'MX', opts);\n\treturn records.map((record) => {\n\t\tconst parts = record.split(' ');\n\t\treturn {\n\t\t\tpriority: parseInt(parts[0], 10),\n\t\t\texchange: parts.slice(1).join(' ').replace(/\\.$/, ''),\n\t\t};\n\t});\n}\n\n/**\n * Query PTR records for an IP address by constructing the reverse DNS name.\n * For IPv4 address `192.0.2.1`, queries `1.2.0.192.in-addr.arpa`.\n * Returns an array of PTR hostnames with trailing dots stripped.\n */\nexport async function queryPtrRecords(ip: string, opts?: QueryDnsOptions): Promise<string[]> {\n\tconst reverseName = ip.split('.').reverse().join('.') + '.in-addr.arpa';\n\tconst records = await queryDnsRecords(reverseName, 'PTR', opts);\n\treturn records.map((record) => record.replace(/\\.$/, ''));\n}\n\n/**\n * Query SRV records and parse them into structured objects.\n * SRV data format: `priority weight port target`\n */\nexport async function querySrvRecords(\n\tname: string,\n\topts?: QueryDnsOptions,\n): Promise<Array<{ priority: number; weight: number; port: number; target: string }>> {\n\tconst records = await queryDnsRecords(name, 'SRV', opts);\n\treturn records.map((record) => {\n\t\tconst parts = record.split(' ');\n\t\treturn {\n\t\t\tpriority: parseInt(parts[0], 10),\n\t\t\tweight: parseInt(parts[1], 10),\n\t\t\tport: parseInt(parts[2], 10),\n\t\t\ttarget: parts.slice(3).join(' ').replace(/\\.$/, ''),\n\t\t};\n\t});\n}\n\n/**\n * Parse a TLSA record data string into structured fields.\n * Handles both human-readable format (`usage selector matchingType certData`)\n * and hex wire format (data starting with `\\#`).\n *\n * Returns null if the data cannot be parsed.\n */\nexport function parseTlsaRecord(data: string): TlsaRecord | null {\n\tif (data.startsWith('\\\\#') || data.startsWith('#')) {\n\t\tconst parts = data.trim().split(/\\s+/);\n\t\tconst hexStart = parts[0] === '\\\\#' || parts[0] === '#' ? 2 : 1;\n\t\tconst hexBytes = parts.slice(hexStart);\n\t\tif (hexBytes.length < 4) return null;\n\n\t\tconst usage = parseInt(hexBytes[0], 16);\n\t\tconst selector = parseInt(hexBytes[1], 16);\n\t\tconst matchingType = parseInt(hexBytes[2], 16);\n\t\tif (isNaN(usage) || isNaN(selector) || isNaN(matchingType)) return null;\n\n\t\tconst certData = hexBytes.slice(3).join('');\n\t\tconst record = { usage, selector, matchingType, certData };\n\t\treturn TlsaRecordSchema.safeParse(record).success ? record : null;\n\t}\n\n\tconst parts = data.trim().split(/\\s+/);\n\tif (parts.length < 4) return null;\n\n\tconst usage = parseInt(parts[0], 10);\n\tconst selector = parseInt(parts[1], 10);\n\tconst matchingType = parseInt(parts[2], 10);\n\tif (isNaN(usage) || isNaN(selector) || isNaN(matchingType)) return null;\n\n\tconst certData = parts.slice(3).join('');\n\tconst record = { usage, selector, matchingType, certData };\n\treturn TlsaRecordSchema.safeParse(record).success ? record : null;\n}","/**\n * Shared types for @blackveil/dns-checks\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\n// SPDX-License-Identifier: BUSL-1.1\n\n// DNS query function — dependency injection interface\nexport type DNSQueryFunction = (\n\tdomain: string,\n\trecordType: string,\n\toptions?: { timeout?: number }\n) => Promise<string[]>;\n\n/**\n * Raw DoH-style DNS response for checks that need the AD flag or full Answer array.\n * Mirrors the subset of DoH JSON response used by DNSSEC and NS checks.\n */\nexport interface RawDNSResponse {\n\tAD?: boolean;\n\tAnswer?: Array<{ type: number; data: string }>;\n}\n\n/**\n * Extended DNS query function that returns the full DoH-style response.\n * Used by DNSSEC and NS checks that need the AD flag or answer type filtering.\n */\nexport type RawDNSQueryFunction = (\n\tdomain: string,\n\trecordType: string,\n\tdnssecFlag?: boolean,\n\toptions?: { timeout?: number }\n) => Promise<RawDNSResponse>;\n\n/**\n * Fetch function — dependency injection interface for HTTP-based checks.\n * Matches the standard fetch() API signature.\n */\nexport type FetchFunction = (\n\turl: string,\n\tinit?: RequestInit\n) => Promise<Response>;\n\nexport type Severity = 'critical' | 'high' | 'medium' | 'low' | 'info';\nexport type FindingConfidence = 'deterministic' | 'heuristic' | 'verified';\n\nexport type CheckCategory =\n\t| 'spf'\n\t| 'dmarc'\n\t| 'dkim'\n\t| 'dnssec'\n\t| 'ssl'\n\t| 'mta_sts'\n\t| 'ns'\n\t| 'caa'\n\t| 'subdomain_takeover'\n\t| 'mx'\n\t| 'bimi'\n\t| 'tlsrpt'\n\t| 'lookalikes'\n\t| 'shadow_domains'\n\t| 'txt_hygiene'\n\t| 'http_security'\n\t| 'dane'\n\t| 'mx_reputation'\n\t| 'srv'\n\t| 'zone_hygiene'\n\t| 'dane_https'\n\t| 'svcb_https';\n\n/** Three-tier classification for check categories: core (critical baseline), protective (active risk mitigation), hardening (advanced posture). */\nexport type CategoryTier = 'core' | 'protective' | 'hardening';\n\n/** Maps every check category to its tier classification. */\nexport const CATEGORY_TIERS: Record<CheckCategory, CategoryTier> = {\n\tspf: 'core',\n\tdmarc: 'core',\n\tdkim: 'core',\n\tdnssec: 'core',\n\tssl: 'core',\n\tsubdomain_takeover: 'protective',\n\thttp_security: 'protective',\n\tmta_sts: 'protective',\n\tmx: 'protective',\n\tcaa: 'protective',\n\tns: 'protective',\n\tlookalikes: 'protective',\n\tshadow_domains: 'protective',\n\tdane: 'hardening',\n\tbimi: 'hardening',\n\ttlsrpt: 'hardening',\n\ttxt_hygiene: 'hardening',\n\tmx_reputation: 'hardening',\n\tsrv: 'hardening',\n\tzone_hygiene: 'hardening',\n\tdane_https: 'protective',\n\tsvcb_https: 'protective',\n};\n\nexport interface Finding {\n\tcategory: CheckCategory;\n\ttitle: string;\n\tseverity: Severity;\n\tdetail: string;\n\tmetadata?: Record<string, unknown>;\n}\n\nexport interface CheckResult {\n\tcategory: CheckCategory;\n\tpassed: boolean;\n\tscore: number;\n\tfindings: Finding[];\n}\n\nexport interface ScanScore {\n\toverall: number;\n\tgrade: string;\n\tcategoryScores: Record<CheckCategory, number>;\n\tfindings: Finding[];\n\tsummary: string;\n}\n\n/** Display/UI weight distribution for categories. NOT used in scoring — see IMPORTANCE_WEIGHTS for actual scoring weights. Exists for category registry and display purposes only. */\nexport const CATEGORY_DISPLAY_WEIGHTS: Record<CheckCategory, number> = {\n\tspf: 0.15,\n\tdmarc: 0.15,\n\tdkim: 0.15,\n\tdnssec: 0.15,\n\tssl: 0.15,\n\tmta_sts: 0.05,\n\tns: 0.05,\n\tcaa: 0.05,\n\tsubdomain_takeover: 0.1,\n\tmx: 0,\n\tbimi: 0,\n\ttlsrpt: 0.02,\n\tlookalikes: 0,\n\tshadow_domains: 0,\n\ttxt_hygiene: 0,\n\thttp_security: 0.05,\n\tdane: 0,\n\tmx_reputation: 0,\n\tsrv: 0,\n\tzone_hygiene: 0,\n\tdane_https: 0,\n\tsvcb_https: 0,\n};\n\n/** Severity penalty multipliers applied to the category score */\nexport const SEVERITY_PENALTIES: Record<Severity, number> = {\n\tcritical: 40,\n\thigh: 25,\n\tmedium: 15,\n\tlow: 5,\n\tinfo: 0,\n};\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport type { CheckCategory, CheckResult, Finding, Severity } from '../types';\nimport { CATEGORY_DISPLAY_WEIGHTS, SEVERITY_PENALTIES } from '../types';\n\nexport type { CheckCategory, CheckResult, Finding, Severity };\nexport { CATEGORY_DISPLAY_WEIGHTS, SEVERITY_PENALTIES };\n\nexport type { CategoryTier } from '../types';\nexport { CATEGORY_TIERS } from '../types';\nexport type { ScanScore } from '../types';\n\n/** Display/UI weight distribution for categories — re-exported from types for convenience. */\n\n/** Severity penalty multipliers — re-exported from types for convenience. */\n\nexport type FindingConfidence = 'deterministic' | 'heuristic' | 'verified';\n\nfunction isExplicitConfidence(value: unknown): value is FindingConfidence {\n\treturn value === 'deterministic' || value === 'heuristic' || value === 'verified';\n}\n\n/**\n * Infer how strongly a finding can be trusted based on available evidence.\n * - verified: explicit proof (currently only supported on takeover checks)\n * - heuristic: signal-based or partial-evidence checks\n * - deterministic: direct record/protocol validation\n */\nexport function inferFindingConfidence(finding: Finding): FindingConfidence {\n\tconst declared = finding.metadata?.confidence;\n\tif (isExplicitConfidence(declared)) return declared;\n\n\tif (finding.category === 'subdomain_takeover') {\n\t\tconst status = finding.metadata?.verificationStatus;\n\t\tif (status === 'verified') return 'verified';\n\t\treturn 'heuristic';\n\t}\n\n\tconst text = `${finding.title} ${finding.detail}`.toLowerCase();\n\tif (\n\t\ttext.includes('common selectors') ||\n\t\ttext.includes('among tested selectors') ||\n\t\ttext.includes('inferred') ||\n\t\ttext.includes('manual review') ||\n\t\ttext.includes('possible') ||\n\t\ttext.includes('potential') ||\n\t\ttext.includes('could indicate')\n\t) {\n\t\treturn 'heuristic';\n\t}\n\n\treturn 'deterministic';\n}\n\nfunction withConfidenceMetadata(finding: Finding): Finding {\n\tconst confidence = inferFindingConfidence(finding);\n\treturn {\n\t\t...finding,\n\t\tmetadata: {\n\t\t\t...(finding.metadata ?? {}),\n\t\t\tconfidence,\n\t\t},\n\t};\n}\n\n/**\n * Compute the score for a single check category based on its findings.\n * Starts at 100 and deducts points based on finding severities.\n */\nexport function computeCategoryScore(findings: Finding[]): number {\n\tlet score = 100;\n\tfor (const finding of findings) {\n\t\tscore -= SEVERITY_PENALTIES[finding.severity];\n\t}\n\treturn Math.max(0, Math.min(100, score));\n}\n\n/** Regex for detecting missing control patterns in finding text. */\nconst MISSING_CONTROL_REGEX = /(no\\s+.+\\s+record|missing|required|not\\s+found)/i;\n\n/**\n * Determine whether findings for a category indicate a fundamentally missing control.\n * Requires both a missing-control text pattern AND deterministic/verified confidence\n * to avoid false zeroing from heuristic checks (e.g., DKIM selector probing).\n */\nexport function scoreIndicatesMissingControl(findings: Finding[]): boolean {\n\treturn findings.some((f) => {\n\t\tconst isMissingPattern = MISSING_CONTROL_REGEX.test(f.detail) || MISSING_CONTROL_REGEX.test(f.title);\n\t\tconst confidence = (f.metadata?.confidence as string) ?? inferFindingConfidence(f);\n\t\treturn isMissingPattern\n\t\t\t&& (f.severity === 'critical' || f.severity === 'high')\n\t\t\t&& (confidence === 'deterministic' || confidence === 'verified');\n\t});\n}\n\n/**\n * Build a CheckResult from a category and its findings.\n * A check fails (passed=false) if the score is below 50, if findings indicate\n * a fundamentally missing security control (e.g., no SPF/DMARC record), or if\n * any finding carries explicit `missingControl: true` metadata.\n */\nexport function buildCheckResult(category: CheckCategory, findings: Finding[]): CheckResult {\n\tconst normalizedFindings = findings.map(withConfidenceMetadata);\n\tconst score = computeCategoryScore(normalizedFindings);\n\tconst hasMissingControl = scoreIndicatesMissingControl(normalizedFindings)\n\t\t|| normalizedFindings.some((f) => f.metadata?.missingControl === true);\n\tconst passed = score >= 50 && !hasMissingControl;\n\treturn {\n\t\tcategory,\n\t\tpassed,\n\t\tscore: hasMissingControl ? 0 : score,\n\t\tfindings: normalizedFindings,\n\t};\n}\n\n/**\n * Create a finding object with the given parameters.\n */\nexport function createFinding(\n\tcategory: CheckCategory,\n\ttitle: string,\n\tseverity: Severity,\n\tdetail: string,\n\tmetadata?: Record<string, unknown>,\n): Finding {\n\t// Sanitize detail to strip control characters and unsafe markdown/HTML chars\n\tconst sanitized = detail\n\t\t.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]/g, '')\n\t\t.replace(/[`[\\]<>]/g, ' ')\n\t\t.replace(/\\s+/g, ' ')\n\t\t.trim();\n\treturn { category, title, severity, detail: sanitized, ...(metadata ? { metadata } : {}) };\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Context-aware scoring profiles for scan_domain.\n *\n * Adapts importance weights based on detected domain purpose (mail-enabled,\n * enterprise mail, non-mail, web-only, minimal infrastructure).\n *\n * Phase 1: Auto-detection runs and reports the detected profile in the\n * structured result, but `auto` uses `mail_enabled` weights (identical to\n * today). Only explicit profile selection activates different weights.\n */\n\nimport type { CheckCategory, CheckResult } from '../types';\n\nexport type DomainProfile = 'mail_enabled' | 'enterprise_mail' | 'non_mail' | 'web_only' | 'minimal';\n\nexport interface DomainContext {\n\tprofile: DomainProfile;\n\tsignals: string[];\n\tweights: Record<CheckCategory, ImportanceProfile>;\n\tdetectedProvider: string | null;\n}\n\ninterface ImportanceProfile {\n\timportance: number;\n}\n\n/** Per-profile importance weights. */\nexport const PROFILE_WEIGHTS: Record<DomainProfile, Record<CheckCategory, ImportanceProfile>> = {\n\tmail_enabled: {\n\t\t// Core (sum=54)\n\t\tspf: { importance: 10 },\n\t\tdmarc: { importance: 16 },\n\t\tdkim: { importance: 10 },\n\t\tdnssec: { importance: 10 },\n\t\tssl: { importance: 8 },\n\t\t// Protective (sum=20)\n\t\tsubdomain_takeover: { importance: 4 },\n\t\thttp_security: { importance: 3 },\n\t\tmta_sts: { importance: 3 },\n\t\tmx: { importance: 2 },\n\t\tcaa: { importance: 2 },\n\t\tns: { importance: 2 },\n\t\tlookalikes: { importance: 2 },\n\t\tshadow_domains: { importance: 2 },\n\t\tdane_https: { importance: 2 },\n\t\tsvcb_https: { importance: 1 },\n\t\t// Hardening (all 0)\n\t\tdane: { importance: 0 },\n\t\tbimi: { importance: 0 },\n\t\ttlsrpt: { importance: 0 },\n\t\ttxt_hygiene: { importance: 0 },\n\t\tmx_reputation: { importance: 0 },\n\t\tsrv: { importance: 0 },\n\t\tzone_hygiene: { importance: 0 },\n\t},\n\tenterprise_mail: {\n\t\t// Core (sum=63)\n\t\tspf: { importance: 10 },\n\t\tdmarc: { importance: 20 },\n\t\tdkim: { importance: 12 },\n\t\tdnssec: { importance: 13 },\n\t\tssl: { importance: 8 },\n\t\t// Protective (sum=22)\n\t\tsubdomain_takeover: { importance: 5 },\n\t\thttp_security: { importance: 3 },\n\t\tmta_sts: { importance: 4 },\n\t\tmx: { importance: 2 },\n\t\tcaa: { importance: 2 },\n\t\tns: { importance: 2 },\n\t\tlookalikes: { importance: 2 },\n\t\tshadow_domains: { importance: 2 },\n\t\tdane_https: { importance: 2 },\n\t\tsvcb_https: { importance: 1 },\n\t\t// Hardening (all 0)\n\t\tdane: { importance: 0 },\n\t\tbimi: { importance: 0 },\n\t\ttlsrpt: { importance: 0 },\n\t\ttxt_hygiene: { importance: 0 },\n\t\tmx_reputation: { importance: 0 },\n\t\tsrv: { importance: 0 },\n\t\tzone_hygiene: { importance: 0 },\n\t},\n\tnon_mail: {\n\t\t// Core (sum=29)\n\t\tspf: { importance: 2 },\n\t\tdmarc: { importance: 3 },\n\t\tdkim: { importance: 2 },\n\t\tdnssec: { importance: 12 },\n\t\tssl: { importance: 10 },\n\t\t// Protective (sum=24)\n\t\tsubdomain_takeover: { importance: 6 },\n\t\thttp_security: { importance: 6 },\n\t\tmta_sts: { importance: 1 },\n\t\tmx: { importance: 1 },\n\t\tcaa: { importance: 3 },\n\t\tns: { importance: 3 },\n\t\tlookalikes: { importance: 2 },\n\t\tshadow_domains: { importance: 2 },\n\t\tdane_https: { importance: 2 },\n\t\tsvcb_https: { importance: 1 },\n\t\t// Hardening (all 0)\n\t\tdane: { importance: 0 },\n\t\tbimi: { importance: 0 },\n\t\ttlsrpt: { importance: 0 },\n\t\ttxt_hygiene: { importance: 0 },\n\t\tmx_reputation: { importance: 0 },\n\t\tsrv: { importance: 0 },\n\t\tzone_hygiene: { importance: 0 },\n\t},\n\tweb_only: {\n\t\t// Core (sum=28)\n\t\tspf: { importance: 0 },\n\t\tdmarc: { importance: 0 },\n\t\tdkim: { importance: 0 },\n\t\tdnssec: { importance: 14 },\n\t\tssl: { importance: 14 },\n\t\t// Protective (sum=24)\n\t\tsubdomain_takeover: { importance: 6 },\n\t\thttp_security: { importance: 8 },\n\t\tmta_sts: { importance: 0 },\n\t\tmx: { importance: 0 },\n\t\tcaa: { importance: 3 },\n\t\tns: { importance: 3 },\n\t\tlookalikes: { importance: 2 },\n\t\tshadow_domains: { importance: 2 },\n\t\tdane_https: { importance: 2 },\n\t\tsvcb_https: { importance: 1 },\n\t\t// Hardening (all 0)\n\t\tdane: { importance: 0 },\n\t\tbimi: { importance: 0 },\n\t\ttlsrpt: { importance: 0 },\n\t\ttxt_hygiene: { importance: 0 },\n\t\tmx_reputation: { importance: 0 },\n\t\tsrv: { importance: 0 },\n\t\tzone_hygiene: { importance: 0 },\n\t},\n\tminimal: {\n\t\t// Core (sum=15)\n\t\tspf: { importance: 1 },\n\t\tdmarc: { importance: 1 },\n\t\tdkim: { importance: 1 },\n\t\tdnssec: { importance: 5 },\n\t\tssl: { importance: 7 },\n\t\t// Protective (sum=10)\n\t\tsubdomain_takeover: { importance: 2 },\n\t\thttp_security: { importance: 2 },\n\t\tmta_sts: { importance: 1 },\n\t\tmx: { importance: 1 },\n\t\tcaa: { importance: 1 },\n\t\tns: { importance: 1 },\n\t\tlookalikes: { importance: 1 },\n\t\tshadow_domains: { importance: 1 },\n\t\tdane_https: { importance: 0 },\n\t\tsvcb_https: { importance: 0 },\n\t\t// Hardening (all 0)\n\t\tdane: { importance: 0 },\n\t\tbimi: { importance: 0 },\n\t\ttlsrpt: { importance: 0 },\n\t\ttxt_hygiene: { importance: 0 },\n\t\tmx_reputation: { importance: 0 },\n\t\tsrv: { importance: 0 },\n\t\tzone_hygiene: { importance: 0 },\n\t},\n};\n\n/** Which categories trigger the critical gap ceiling per profile. */\n// DNSSEC added to all profiles per NIST SP 800-81r3 (mandatory control)\n// DANE_HTTPS added to web/non-mail profiles (certificate integrity)\nexport const PROFILE_CRITICAL_CATEGORIES: Record<DomainProfile, CheckCategory[]> = {\n\tmail_enabled: ['spf', 'dmarc', 'dkim', 'ssl', 'dnssec', 'subdomain_takeover'],\n\tenterprise_mail: ['spf', 'dmarc', 'dkim', 'ssl', 'dnssec', 'subdomain_takeover'],\n\tnon_mail: ['ssl', 'dnssec', 'http_security', 'subdomain_takeover', 'dane_https'],\n\tweb_only: ['ssl', 'dnssec', 'http_security', 'subdomain_takeover', 'dane_https'],\n\tminimal: ['ssl', 'dnssec', 'subdomain_takeover'],\n};\n\n/** Whether a profile is eligible for the email bonus. */\nexport const PROFILE_EMAIL_BONUS_ELIGIBLE: Record<DomainProfile, boolean> = {\n\tmail_enabled: true,\n\tenterprise_mail: true,\n\tnon_mail: false,\n\tweb_only: false,\n\tminimal: false,\n};\n\n/** Known enterprise mail providers detected via MX record patterns. */\nconst ENTERPRISE_PROVIDERS = [\n\t'google workspace',\n\t'microsoft 365',\n\t'proofpoint',\n\t'mimecast',\n\t'barracuda',\n];\n\n/**\n * Detect domain context from completed check results.\n * Pure function — reads findings metadata only, no DNS queries.\n */\nexport function detectDomainContext(results: CheckResult[]): DomainContext {\n\tconst signals: string[] = [];\n\n\tconst mxResult = results.find((r) => r.category === 'mx');\n\tconst sslResult = results.find((r) => r.category === 'ssl');\n\tconst caaResult = results.find((r) => r.category === 'caa');\n\tconst dkimResult = results.find((r) => r.category === 'dkim');\n\tconst mtaStsResult = results.find((r) => r.category === 'mta_sts');\n\tconst bimiResult = results.find((r) => r.category === 'bimi');\n\n\t// Detect MX presence\n\tconst hasNoMx = mxResult\n\t\t? mxResult.findings.some((f) => {\n\t\t\t\tconst title = f.title.toLowerCase();\n\t\t\t\treturn title.includes('no mx records') || title.includes('null mx');\n\t\t\t})\n\t\t: false;\n\tconst hasMxUnknown = mxResult\n\t\t? mxResult.findings.some((f) => f.title.toLowerCase().includes('dns query failed'))\n\t\t: false;\n\tconst hasMx = mxResult && !hasNoMx && !hasMxUnknown;\n\n\tif (hasMx) signals.push('MX present');\n\tif (hasNoMx) signals.push('No MX records');\n\tif (hasMxUnknown) signals.push('MX status unknown');\n\n\t// Detect enterprise provider from MX findings\n\tlet hasEnterpriseProvider = false;\n\tlet detectedProviderName: string | null = null;\n\tif (mxResult) {\n\t\tfor (const finding of mxResult.findings) {\n\t\t\tconst text = `${finding.title} ${finding.detail}`.toLowerCase();\n\t\t\tconst providerName = finding.metadata?.provider;\n\t\t\tconst providerStr = typeof providerName === 'string' ? providerName.toLowerCase() : '';\n\t\t\tfor (const provider of ENTERPRISE_PROVIDERS) {\n\t\t\t\tif (text.includes(provider) || providerStr.includes(provider)) {\n\t\t\t\t\thasEnterpriseProvider = true;\n\t\t\t\t\tdetectedProviderName = provider;\n\t\t\t\t\tsignals.push(`${provider} provider`);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (hasEnterpriseProvider) break;\n\t\t}\n\t}\n\n\t// Detect hardening signals (DKIM present, MTA-STS present, BIMI present)\n\tconst dkimPresent = dkimResult\n\t\t? !dkimResult.findings.some((f) => {\n\t\t\t\tconst text = `${f.title} ${f.detail}`.toLowerCase();\n\t\t\t\treturn /(no\\s+dkim|not\\s+found|missing)/.test(text) && f.severity !== 'info';\n\t\t\t})\n\t\t: false;\n\tif (dkimPresent && hasMx) signals.push('DKIM present');\n\n\tconst mtaStsPresent = mtaStsResult ? mtaStsResult.passed : false;\n\tif (mtaStsPresent) signals.push('MTA-STS present');\n\n\tconst bimiPresent = bimiResult ? bimiResult.passed : false;\n\tif (bimiPresent) signals.push('BIMI present');\n\n\tconst hasHardeningSignal = dkimPresent || mtaStsPresent || bimiPresent;\n\n\t// Detect web indicators\n\tconst sslPass = sslResult ? sslResult.passed : false;\n\tconst caaPass = caaResult ? caaResult.passed : false;\n\tif (sslPass) signals.push('SSL valid');\n\tif (caaPass) signals.push('CAA present');\n\n\t// Count failed/timed-out checks\n\tconst totalChecks = results.length;\n\tconst failedChecks = results.filter((r) => !r.passed).length;\n\tconst failureRatio = totalChecks > 0 ? failedChecks / totalChecks : 0;\n\tif (failureRatio > 0.5) signals.push(`>${Math.round(failureRatio * 100)}% checks failed`);\n\n\t// Detection priority\n\tlet profile: DomainProfile;\n\n\tif (hasNoMx) {\n\t\t// Explicitly no MX (no records or null MX) → non-mail profiles\n\t\tif (caaPass || sslPass) {\n\t\t\tprofile = 'web_only';\n\t\t} else {\n\t\t\tprofile = 'non_mail';\n\t\t}\n\t} else if (hasMxUnknown || !hasMx) {\n\t\t// MX lookup failed or no MX result at all → default to mail_enabled (safe fallback)\n\t\tprofile = 'mail_enabled';\n\t} else if (hasMx && hasEnterpriseProvider && hasHardeningSignal) {\n\t\tprofile = 'enterprise_mail';\n\t} else {\n\t\tprofile = 'mail_enabled';\n\t}\n\n\t// Override to minimal if most checks failed\n\tif (failureRatio > 0.5) {\n\t\tprofile = 'minimal';\n\t}\n\n\treturn {\n\t\tprofile,\n\t\tsignals,\n\t\tweights: PROFILE_WEIGHTS[profile],\n\t\tdetectedProvider: detectedProviderName,\n\t};\n}\n\n/** Look up the weight table for a given profile, optionally from runtime config. */\nexport function getProfileWeights(\n\tprofile: DomainProfile,\n\tconfig?: import('./config').ScoringConfig,\n): Record<CheckCategory, ImportanceProfile> {\n\tif (config) {\n\t\tconst flat = config.profileWeights[profile];\n\t\tconst result = {} as Record<CheckCategory, ImportanceProfile>;\n\t\tfor (const key of Object.keys(flat) as CheckCategory[]) {\n\t\t\tresult[key] = { importance: flat[key] };\n\t\t}\n\t\treturn result;\n\t}\n\treturn PROFILE_WEIGHTS[profile];\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Runtime scoring configuration.\n *\n * All scoring weights, thresholds, and tuning constants are configurable\n * via the `SCORING_CONFIG` environment variable (JSON string). The open-source\n * codebase ships with reasonable defaults; production deployments can override\n * any subset of values.\n *\n * Parse once at request entry and thread through the call chain — never\n * re-parse per tool call.\n */\n\nimport type { CheckCategory } from '../types';\nimport { CATEGORY_TIERS } from '../types';\nimport type { DomainProfile } from './profiles';\n\n/** All tunable scoring parameters. */\nexport interface ScoringConfig {\n\t/** @deprecated Use coreWeights and protectiveWeights */\n\tweights: Record<CheckCategory, number>;\n\n\t/** Per-profile importance weights. */\n\tprofileWeights: Record<DomainProfile, Record<CheckCategory, number>>;\n\n\t/** Tier budget split — percentage of the total score allocated to each tier. Must sum to 100. */\n\ttierSplit: { core: number; protective: number; hardening: number };\n\n\t/** Importance weights for core-tier categories (SPF, DMARC, DKIM, DNSSEC, SSL). */\n\tcoreWeights: Record<string, number>;\n\n\t/** Importance weights for protective-tier categories. */\n\tprotectiveWeights: Record<string, number>;\n\n\t/** Per-provider DKIM confidence factors (0–1). */\n\tproviderDkimConfidence: Record<string, number>;\n\n\t/** Scoring thresholds and constants. */\n\tthresholds: {\n\t\t/** @deprecated Use emailBonusFull, emailBonusMid, emailBonusPartial */\n\t\temailBonusImportance: number;\n\t\temailBonusFull: number;\n\t\temailBonusMid: number;\n\t\temailBonusPartial: number;\n\t\tspfStrongThreshold: number;\n\t\tcriticalOverallPenalty: number;\n\t\tcriticalGapCeiling: number;\n\t};\n\n\t/** Grade boundaries (minimum score for each grade). */\n\tgrades: {\n\t\taPlus: number;\n\t\ta: number;\n\t\tbPlus: number;\n\t\tb: number;\n\t\tcPlus: number;\n\t\tc: number;\n\t\tdPlus: number;\n\t\td: number;\n\t};\n\n\t/** Baseline failure rates for adaptive weight computation. */\n\tbaselineFailureRates: Record<string, number>;\n}\n\n/** Built-in defaults — used when `SCORING_CONFIG` env var is absent or partial. */\nexport const DEFAULT_SCORING_CONFIG: ScoringConfig = {\n\tweights: {\n\t\tspf: 10,\n\t\tdmarc: 16,\n\t\tdkim: 10,\n\t\tdnssec: 8,\n\t\tssl: 8,\n\t\tmta_sts: 2,\n\t\tns: 0,\n\t\tcaa: 0,\n\t\tsubdomain_takeover: 3,\n\t\tmx: 2,\n\t\tbimi: 0,\n\t\ttlsrpt: 1,\n\t\tlookalikes: 0,\n\t\tshadow_domains: 0,\n\t\ttxt_hygiene: 0,\n\t\thttp_security: 3,\n\t\tdane: 1,\n\t\tmx_reputation: 0,\n\t\tsrv: 0,\n\t\tzone_hygiene: 0,\n\t\tdane_https: 2,\n\t\tsvcb_https: 1,\n\t},\n\tprofileWeights: {\n\t\tmail_enabled: { dmarc: 16, dkim: 10, spf: 10, ssl: 8, subdomain_takeover: 4, dnssec: 10, mta_sts: 3, mx: 2, tlsrpt: 0, caa: 2, ns: 2, bimi: 0, lookalikes: 2, shadow_domains: 2, txt_hygiene: 0, http_security: 3, dane: 0, mx_reputation: 0, srv: 0, zone_hygiene: 0, dane_https: 2, svcb_https: 1 },\n\t\tenterprise_mail: { dmarc: 20, dkim: 12, spf: 10, ssl: 8, subdomain_takeover: 5, dnssec: 13, mta_sts: 4, mx: 2, tlsrpt: 0, caa: 2, ns: 2, bimi: 0, lookalikes: 2, shadow_domains: 2, txt_hygiene: 0, http_security: 3, dane: 0, mx_reputation: 0, srv: 0, zone_hygiene: 0, dane_https: 2, svcb_https: 1 },\n\t\tnon_mail: { ssl: 10, subdomain_takeover: 6, dnssec: 12, caa: 3, dmarc: 3, ns: 3, dkim: 2, spf: 2, mx: 1, mta_sts: 1, tlsrpt: 0, bimi: 0, lookalikes: 2, shadow_domains: 2, txt_hygiene: 0, http_security: 6, dane: 0, mx_reputation: 0, srv: 0, zone_hygiene: 0, dane_https: 2, svcb_https: 1 },\n\t\tweb_only: { ssl: 14, subdomain_takeover: 6, dnssec: 14, caa: 3, dmarc: 0, ns: 3, dkim: 0, spf: 0, mx: 0, mta_sts: 0, tlsrpt: 0, bimi: 0, lookalikes: 2, shadow_domains: 2, txt_hygiene: 0, http_security: 8, dane: 0, mx_reputation: 0, srv: 0, zone_hygiene: 0, dane_https: 2, svcb_https: 1 },\n\t\tminimal: { dmarc: 1, ssl: 7, dnssec: 5, dkim: 1, spf: 1, subdomain_takeover: 2, ns: 1, mx: 1, caa: 1, mta_sts: 1, tlsrpt: 0, bimi: 0, lookalikes: 1, shadow_domains: 1, txt_hygiene: 0, http_security: 2, dane: 0, mx_reputation: 0, srv: 0, zone_hygiene: 0, dane_https: 0, svcb_https: 0 },\n\t},\n\ttierSplit: { core: 70, protective: 20, hardening: 10 },\n\tcoreWeights: { dmarc: 16, dkim: 10, spf: 10, dnssec: 10, ssl: 8 },\n\tprotectiveWeights: {\n\t\tsubdomain_takeover: 4, http_security: 3, mta_sts: 3, mx: 2,\n\t\tcaa: 2, ns: 2, lookalikes: 2, shadow_domains: 2,\n\t},\n\tproviderDkimConfidence: {\n\t\tamazonses: 0.8, sendgrid: 0.8, mailgun: 0.8, postmark: 0.8,\n\t\tgoogle: 0.9, microsoft365: 0.9, proofpoint: 0.6, mimecast: 0.6,\n\t},\n\tthresholds: {\n\t\temailBonusImportance: 8,\n\t\temailBonusFull: 5,\n\t\temailBonusMid: 3,\n\t\temailBonusPartial: 2,\n\t\tspfStrongThreshold: 57,\n\t\tcriticalOverallPenalty: 15,\n\t\tcriticalGapCeiling: 64,\n\t},\n\tgrades: {\n\t\taPlus: 92,\n\t\ta: 87,\n\t\tbPlus: 82,\n\t\tb: 76,\n\t\tcPlus: 70,\n\t\tc: 63,\n\t\tdPlus: 56,\n\t\td: 50,\n\t},\n\tbaselineFailureRates: {\n\t\tdmarc: 0.40,\n\t\tspf: 0.25,\n\t\tdkim: 0.35,\n\t\tssl: 0.08,\n\t\tmta_sts: 0.85,\n\t\tdnssec: 0.80,\n\t\tmx: 0.05,\n\t\tcaa: 0.70,\n\t\tns: 0.03,\n\t\tbimi: 0.95,\n\t\ttlsrpt: 0.90,\n\t\tsubdomain_takeover: 0.10,\n\t\tlookalikes: 0.00,\n\t\tshadow_domains: 0.00,\n\t\ttxt_hygiene: 0.00,\n\t\thttp_security: 0.35,\n\t\tdane: 0.90,\n\t\tmx_reputation: 0.00,\n\t\tsrv: 0.00,\n\t\tzone_hygiene: 0.00,\n\t\tdane_https: 0.95,\n\t\tsvcb_https: 0.85,\n\t},\n};\n\n/**\n * Convert flat weight numbers to the `{ importance: number }` shape\n * used by the scoring engine and profile system.\n */\nexport function toImportanceRecord<K extends string>(\n\tweights: Record<K, number>,\n): Record<K, { importance: number }> {\n\tconst result = {} as Record<K, { importance: number }>;\n\tfor (const key of Object.keys(weights) as K[]) {\n\t\tresult[key] = { importance: weights[key] };\n\t}\n\treturn result;\n}\n\n/** Safely merge a partial weight record into defaults. */\nfunction mergeWeights(\n\tdefaults: Record<string, number>,\n\toverrides: Record<string, unknown> | undefined,\n): Record<string, number> {\n\tif (!overrides || typeof overrides !== 'object') return { ...defaults };\n\tconst result = { ...defaults };\n\tfor (const [key, value] of Object.entries(overrides)) {\n\t\tif (key in defaults && typeof value === 'number' && Number.isFinite(value)) {\n\t\t\tresult[key] = Math.max(0, value);\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Parse a `SCORING_CONFIG` env var string into a fully-populated `ScoringConfig`.\n *\n * Gracefully handles undefined, empty, invalid JSON, partial overrides,\n * and invalid value types. Always returns a complete config by merging\n * overrides into defaults.\n *\n * Provides legacy migration:\n * - `weights` without `coreWeights` → partitions into core/protective via CATEGORY_TIERS\n * - `thresholds.emailBonusImportance` without `emailBonusFull` → derives three-tier bonus fields\n * - `tierSplit` not summing to 100 → falls back to default tierSplit\n * - `grades.e` → silently ignored (E grade removed in scoring v2)\n */\nexport function parseScoringConfig(raw: string | undefined): ScoringConfig {\n\tif (!raw || raw.trim().length === 0) return DEFAULT_SCORING_CONFIG;\n\n\tlet parsed: Record<string, unknown>;\n\ttry {\n\t\tparsed = JSON.parse(raw) as Record<string, unknown>;\n\t} catch {\n\t\treturn DEFAULT_SCORING_CONFIG;\n\t}\n\n\tif (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n\t\treturn DEFAULT_SCORING_CONFIG;\n\t}\n\n\t// Merge weights\n\tconst rawWeightsObj = parsed.weights as Record<string, unknown> | undefined;\n\tconst weights = mergeWeights(\n\t\tDEFAULT_SCORING_CONFIG.weights,\n\t\trawWeightsObj,\n\t) as Record<CheckCategory, number>;\n\n\t// Merge profile weights\n\tconst profileWeights = { ...DEFAULT_SCORING_CONFIG.profileWeights } as Record<DomainProfile, Record<CheckCategory, number>>;\n\tconst rawProfileWeights = parsed.profileWeights as Record<string, Record<string, unknown>> | undefined;\n\tif (rawProfileWeights && typeof rawProfileWeights === 'object') {\n\t\tfor (const profile of Object.keys(DEFAULT_SCORING_CONFIG.profileWeights) as DomainProfile[]) {\n\t\t\tif (profile in rawProfileWeights) {\n\t\t\t\tprofileWeights[profile] = mergeWeights(\n\t\t\t\t\tDEFAULT_SCORING_CONFIG.profileWeights[profile],\n\t\t\t\t\trawProfileWeights[profile],\n\t\t\t\t) as Record<CheckCategory, number>;\n\t\t\t}\n\t\t}\n\t}\n\n\t// --- Tier split ---\n\tlet tierSplit = { ...DEFAULT_SCORING_CONFIG.tierSplit };\n\tconst rawTierSplit = parsed.tierSplit as Record<string, unknown> | undefined;\n\tif (rawTierSplit && typeof rawTierSplit === 'object') {\n\t\tconst c = rawTierSplit.core;\n\t\tconst p = rawTierSplit.protective;\n\t\tconst h = rawTierSplit.hardening;\n\t\tif (typeof c === 'number' && typeof p === 'number' && typeof h === 'number' && Number.isFinite(c + p + h)) {\n\t\t\tif (c + p + h === 100) {\n\t\t\t\ttierSplit = { core: c, protective: p, hardening: h };\n\t\t\t}\n\t\t\t// Sum != 100 → fall back to default (validation rejection)\n\t\t}\n\t}\n\n\t// --- Core/Protective weights with legacy migration ---\n\tlet coreWeights: Record<string, number>;\n\tlet protectiveWeights: Record<string, number>;\n\n\tif (parsed.coreWeights && typeof parsed.coreWeights === 'object') {\n\t\tcoreWeights = mergeWeights(DEFAULT_SCORING_CONFIG.coreWeights, parsed.coreWeights as Record<string, unknown>);\n\t} else if (rawWeightsObj && typeof rawWeightsObj === 'object') {\n\t\t// Legacy migration: partition weights into core/protective via CATEGORY_TIERS\n\t\tconst migrated = { ...DEFAULT_SCORING_CONFIG.coreWeights };\n\t\tfor (const [key, value] of Object.entries(rawWeightsObj)) {\n\t\t\tif (typeof value === 'number' && Number.isFinite(value) && key in CATEGORY_TIERS) {\n\t\t\t\tconst tier = CATEGORY_TIERS[key as CheckCategory];\n\t\t\t\tif (tier === 'core') {\n\t\t\t\t\tmigrated[key] = Math.max(0, value);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcoreWeights = migrated;\n\t} else {\n\t\tcoreWeights = { ...DEFAULT_SCORING_CONFIG.coreWeights };\n\t}\n\n\tif (parsed.protectiveWeights && typeof parsed.protectiveWeights === 'object') {\n\t\tprotectiveWeights = mergeWeights(DEFAULT_SCORING_CONFIG.protectiveWeights, parsed.protectiveWeights as Record<string, unknown>);\n\t} else if (rawWeightsObj && typeof rawWeightsObj === 'object') {\n\t\t// Legacy migration: partition weights into core/protective via CATEGORY_TIERS\n\t\tconst migrated = { ...DEFAULT_SCORING_CONFIG.protectiveWeights };\n\t\tfor (const [key, value] of Object.entries(rawWeightsObj)) {\n\t\t\tif (typeof value === 'number' && Number.isFinite(value) && key in CATEGORY_TIERS) {\n\t\t\t\tconst tier = CATEGORY_TIERS[key as CheckCategory];\n\t\t\t\tif (tier === 'protective') {\n\t\t\t\t\tmigrated[key] = Math.max(0, value);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tprotectiveWeights = migrated;\n\t} else {\n\t\tprotectiveWeights = { ...DEFAULT_SCORING_CONFIG.protectiveWeights };\n\t}\n\n\t// --- Provider DKIM confidence ---\n\tconst providerDkimConfidence = { ...DEFAULT_SCORING_CONFIG.providerDkimConfidence };\n\tconst rawProviderDkim = parsed.providerDkimConfidence as Record<string, unknown> | undefined;\n\tif (rawProviderDkim && typeof rawProviderDkim === 'object') {\n\t\tfor (const [key, value] of Object.entries(rawProviderDkim)) {\n\t\t\tif (typeof value === 'number' && Number.isFinite(value)) {\n\t\t\t\tproviderDkimConfidence[key] = Math.max(0, Math.min(1, value));\n\t\t\t}\n\t\t}\n\t}\n\n\t// Merge thresholds\n\tconst rawThresholds = parsed.thresholds as Record<string, unknown> | undefined;\n\tconst thresholds = { ...DEFAULT_SCORING_CONFIG.thresholds };\n\tif (rawThresholds && typeof rawThresholds === 'object') {\n\t\tfor (const key of Object.keys(thresholds) as Array<keyof typeof thresholds>) {\n\t\t\tif (key in rawThresholds && typeof rawThresholds[key] === 'number' && Number.isFinite(rawThresholds[key])) {\n\t\t\t\tthresholds[key] = rawThresholds[key] as number;\n\t\t\t}\n\t\t}\n\n\t\t// Legacy migration: emailBonusImportance → three-tier bonus fields\n\t\tif (\n\t\t\t'emailBonusImportance' in rawThresholds &&\n\t\t\ttypeof rawThresholds.emailBonusImportance === 'number' &&\n\t\t\t!('emailBonusFull' in rawThresholds)\n\t\t) {\n\t\t\tconst v = rawThresholds.emailBonusImportance;\n\t\t\tthresholds.emailBonusFull = v;\n\t\t\tthresholds.emailBonusMid = Math.ceil(v * 0.6);\n\t\t\tthresholds.emailBonusPartial = Math.ceil(v * 0.4);\n\t\t}\n\t}\n\n\t// Merge grades — silently ignore legacy 'e' grade\n\tconst rawGrades = parsed.grades as Record<string, unknown> | undefined;\n\tconst grades = { ...DEFAULT_SCORING_CONFIG.grades };\n\tif (rawGrades && typeof rawGrades === 'object') {\n\t\tfor (const key of Object.keys(grades) as Array<keyof typeof grades>) {\n\t\t\tif (key in rawGrades && typeof rawGrades[key] === 'number' && Number.isFinite(rawGrades[key])) {\n\t\t\t\tgrades[key] = rawGrades[key] as number;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Merge baseline failure rates\n\tconst baselineFailureRates = mergeWeights(\n\t\tDEFAULT_SCORING_CONFIG.baselineFailureRates,\n\t\tparsed.baselineFailureRates as Record<string, unknown> | undefined,\n\t);\n\n\treturn {\n\t\tweights, profileWeights, tierSplit, coreWeights, protectiveWeights,\n\t\tproviderDkimConfidence, thresholds, grades, baselineFailureRates,\n\t};\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Generic scoring engine for @blackveil/dns-checks\n *\n * Accepts string keys (not concrete `CheckCategory`) so any consumer can plug in\n * their own check vocabulary. The existing `computeScanScore` (which uses `CheckResult[]`\n * and `CheckCategory`) will later become a wrapper around this function.\n *\n * Three-tier formula:\n * - **Core** (default 70 pts): Weighted accumulation. `missingControls[key]=true` zeros the contribution.\n * - **Protective** (default 20 pts): Weighted accumulation. No missing control zeroing.\n * - **Hardening** (default 10 pts): Binary pass/fail from `hardeningPassed` map. Only submitted keys count.\n * - **Email bonus**: +5/+3/+2 based on DMARC quality (configurable keys).\n * - **Provider modifier**: Average of providerConfidence values, centered at 0.5, scaled to -5..+5.\n * - **Critical penalty**: -15 if findingSeverityCounts.critical > 0.\n * - **Critical gap ceiling**: If any criticalCategories key has missingControls=true, cap at 64.\n */\n\nimport type { CategoryTier } from '../types';\nimport type { ScoringConfig } from './config';\nimport { DEFAULT_SCORING_CONFIG } from './config';\nimport { scoreToGrade } from './engine';\n\n/** Finding severity counts for summary generation and critical penalty. */\nexport interface FindingSeverityCounts {\n\tcritical: number;\n\thigh: number;\n\tmedium: number;\n\tlow: number;\n\tinfo: number;\n}\n\n/** Mapping of the three email-related keys to arbitrary category key names. */\nexport interface EmailBonusKeyMap {\n\tspf: string;\n\tdkim: string;\n\tdmarc: string;\n}\n\n/**\n * Generic scoring context — all inputs needed to compute a score.\n * Keys are arbitrary strings, not tied to `CheckCategory`.\n */\nexport interface GenericScoringContext {\n\t/** Category key → score (0–100). Absent keys default to 100. */\n\tcategoryScores: Record<string, number>;\n\n\t/** Category key → tier classification. Only keys present here participate in scoring. */\n\ttierMap: Record<string, CategoryTier>;\n\n\t/** Category key → importance weight. Must cover all keys in tierMap. */\n\tweights: Record<string, number>;\n\n\t/** Category keys that trigger the critical gap ceiling when missing. */\n\tcriticalCategories: string[];\n\n\t/** Whether this context is eligible for the email bonus. */\n\temailBonusEligible: boolean;\n\n\t/** Category key → true if the control is fundamentally missing (deterministic/verified). */\n\tmissingControls: Record<string, boolean>;\n\n\t/** Hardening category key → true if passed. Only submitted keys count. */\n\thardeningPassed: Record<string, boolean>;\n\n\t/** Category key → true if the check suffered a transient failure (excluded from scoring). */\n\ttransientFailures?: Record<string, boolean>;\n\n\t/** Override default email bonus keys (spf/dkim/dmarc) with custom category key names. */\n\temailBonusKeys?: EmailBonusKeyMap;\n\n\t/** Category key → provider confidence (0–1). Averaged, centered at 0.5, scaled to -5..+5. */\n\tproviderConfidence?: Record<string, number>;\n\n\t/** Severity counts for summary generation and critical penalty. */\n\tfindingSeverityCounts?: FindingSeverityCounts;\n}\n\n/** Tier breakdown showing earned points per tier. */\nexport interface TierBreakdown {\n\tcore: number;\n\tprotective: number;\n\thardening: number;\n}\n\n/** Result of the generic scoring computation. */\nexport interface GenericScanScore {\n\t/** Overall score (0–100). */\n\toverall: number;\n\n\t/** Letter grade (A+ through F). */\n\tgrade: string;\n\n\t/** Input category scores echoed back (with absent defaults filled to 100). */\n\tcategoryScores: Record<string, number>;\n\n\t/** Human-readable summary. */\n\tsummary: string;\n\n\t/** Points earned per tier. */\n\ttierBreakdown: TierBreakdown;\n\n\t/** Email bonus points added (0, 2, 3, or 5). */\n\temailBonus: number;\n\n\t/** Category keys that triggered the critical gap ceiling. */\n\tcriticalGaps: string[];\n\n\t/** Provider confidence modifier applied (-5 to +5). */\n\tproviderModifier: number;\n\n\t/** Critical penalty applied (0 or criticalOverallPenalty from config). */\n\tcriticalPenalty: number;\n}\n\nconst DEFAULT_EMAIL_BONUS_KEYS: EmailBonusKeyMap = {\n\tspf: 'spf',\n\tdkim: 'dkim',\n\tdmarc: 'dmarc',\n};\n\nfunction clampPercent(score: number): number {\n\treturn Math.max(0, Math.min(100, score));\n}\n\nfunction computeProviderModifier(providerConfidence: Record<string, number> | undefined): number {\n\tif (!providerConfidence) return 0;\n\n\tconst values = Object.values(providerConfidence).filter(\n\t\t(v) => typeof v === 'number' && Number.isFinite(v),\n\t);\n\tif (values.length === 0) return 0;\n\n\tconst clamped = values.map((v) => Math.max(0, Math.min(1, v)));\n\tconst avg = clamped.reduce((sum, v) => sum + v, 0) / clamped.length;\n\tconst centered = avg - 0.5;\n\treturn Math.round(centered * 10);\n}\n\n/**\n * Compute a score using the three-tier formula with arbitrary string keys.\n *\n * @param input - Scoring context with category scores, tier map, weights, etc.\n * @param config - Optional scoring config override (defaults to DEFAULT_SCORING_CONFIG).\n * @returns A GenericScanScore with overall score, grade, breakdown, and metadata.\n */\nexport function computeGenericScore(input: GenericScoringContext, config?: ScoringConfig): GenericScanScore {\n\tconst cfg = config ?? DEFAULT_SCORING_CONFIG;\n\tconst tierSplit = cfg.tierSplit;\n\tconst thresholds = cfg.thresholds;\n\n\tconst transient = input.transientFailures ?? {};\n\tconst emailKeys = input.emailBonusKeys ?? DEFAULT_EMAIL_BONUS_KEYS;\n\n\t// --- Partition weights by tier, excluding transient failures ---\n\tconst coreWeights: Record<string, number> = {};\n\tconst protectiveWeights: Record<string, number> = {};\n\tconst hardeningKeys: string[] = [];\n\n\tfor (const [key, tier] of Object.entries(input.tierMap)) {\n\t\tif (transient[key]) continue;\n\t\tconst weight = input.weights[key] ?? 0;\n\t\tif (tier === 'core') {\n\t\t\tcoreWeights[key] = weight;\n\t\t} else if (tier === 'protective') {\n\t\t\tprotectiveWeights[key] = weight;\n\t\t} else if (tier === 'hardening') {\n\t\t\thardeningKeys.push(key);\n\t\t}\n\t}\n\n\t// --- Core tier accumulation ---\n\tconst coreMax = Object.values(coreWeights).reduce((sum, w) => sum + w, 0);\n\tlet coreEarned = 0;\n\n\tfor (const [key, weight] of Object.entries(coreWeights)) {\n\t\tif (weight === 0) continue;\n\t\tconst rawScore = clampPercent(input.categoryScores[key] ?? 100);\n\t\tconst effectiveScore = input.missingControls[key] ? 0 : rawScore;\n\t\tcoreEarned += (effectiveScore / 100) * weight;\n\t}\n\n\tconst corePct = coreMax > 0 ? coreEarned / coreMax : 1;\n\tconst corePoints = corePct * tierSplit.core;\n\n\t// --- Protective tier accumulation ---\n\tconst protectiveMax = Object.values(protectiveWeights).reduce((sum, w) => sum + w, 0);\n\tlet protectiveEarned = 0;\n\n\tfor (const [key, weight] of Object.entries(protectiveWeights)) {\n\t\tif (weight === 0) continue;\n\t\tconst rawScore = clampPercent(input.categoryScores[key] ?? 100);\n\t\t// Protective: NO missingControls zeroing\n\t\tprotectiveEarned += (rawScore / 100) * weight;\n\t}\n\n\tconst protectivePct = protectiveMax > 0 ? protectiveEarned / protectiveMax : 1;\n\tconst protectivePoints = protectivePct * tierSplit.protective;\n\n\t// --- Hardening tier (binary pass/fail) ---\n\t// Only keys present in hardeningPassed count — absent hardening categories are ignored.\n\tconst submittedHardeningKeys = hardeningKeys.filter((key) => key in input.hardeningPassed);\n\tconst passedCount = submittedHardeningKeys.filter((key) => input.hardeningPassed[key]).length;\n\tconst hardeningPoints = submittedHardeningKeys.length > 0\n\t\t? (passedCount / submittedHardeningKeys.length) * tierSplit.hardening\n\t\t: 0;\n\n\t// --- Base score ---\n\tconst base = corePoints + protectivePoints + hardeningPoints;\n\n\t// --- Email bonus ---\n\tlet emailBonus = 0;\n\tif (input.emailBonusEligible) {\n\t\tconst spfKey = emailKeys.spf;\n\t\tconst dkimKey = emailKeys.dkim;\n\t\tconst dmarcKey = emailKeys.dmarc;\n\n\t\tconst spfScore = input.categoryScores[spfKey] ?? 0;\n\t\tconst spfStrong = !input.missingControls[spfKey] && spfScore >= thresholds.spfStrongThreshold;\n\n\t\tconst dkimNotMissing = !input.missingControls[dkimKey];\n\n\t\tconst dmarcScore = input.categoryScores[dmarcKey];\n\t\tconst dmarcPresent = dmarcScore !== undefined && !input.missingControls[dmarcKey];\n\n\t\tif (spfStrong && dkimNotMissing && dmarcPresent) {\n\t\t\tif (dmarcScore >= 90) {\n\t\t\t\temailBonus = thresholds.emailBonusFull;\n\t\t\t} else if (dmarcScore >= 70) {\n\t\t\t\temailBonus = thresholds.emailBonusMid;\n\t\t\t} else {\n\t\t\t\temailBonus = thresholds.emailBonusPartial;\n\t\t\t}\n\t\t}\n\t}\n\n\t// --- Provider confidence modifier ---\n\tconst providerModifier = computeProviderModifier(input.providerConfidence);\n\n\t// --- Critical penalty ---\n\tconst counts = input.findingSeverityCounts;\n\tconst criticalPenalty = counts && counts.critical > 0 ? thresholds.criticalOverallPenalty : 0;\n\n\t// --- Assemble pre-ceiling score ---\n\tconst preCeiling = clampPercent(Math.round(base) + emailBonus + providerModifier - criticalPenalty);\n\n\t// --- Critical gap ceiling ---\n\tconst criticalGaps: string[] = [];\n\tfor (const key of input.criticalCategories) {\n\t\tif (input.missingControls[key]) {\n\t\t\tcriticalGaps.push(key);\n\t\t}\n\t}\n\tconst overall = criticalGaps.length > 0\n\t\t? Math.min(preCeiling, thresholds.criticalGapCeiling)\n\t\t: preCeiling;\n\n\t// --- Grade ---\n\tconst grade = scoreToGrade(overall, config);\n\n\t// --- Summary ---\n\tconst summary = buildSummary(counts, grade);\n\n\t// --- Populate category scores with absent defaults ---\n\tconst filledScores: Record<string, number> = {};\n\tfor (const key of Object.keys(input.tierMap)) {\n\t\tfilledScores[key] = input.categoryScores[key] ?? 100;\n\t}\n\t// Also include any explicitly-provided scores not in tierMap\n\tfor (const key of Object.keys(input.categoryScores)) {\n\t\tif (!(key in filledScores)) {\n\t\t\tfilledScores[key] = input.categoryScores[key];\n\t\t}\n\t}\n\n\treturn {\n\t\toverall,\n\t\tgrade,\n\t\tcategoryScores: filledScores,\n\t\tsummary,\n\t\ttierBreakdown: {\n\t\t\tcore: corePoints,\n\t\t\tprotective: protectivePoints,\n\t\t\thardening: hardeningPoints,\n\t\t},\n\t\temailBonus,\n\t\tcriticalGaps,\n\t\tproviderModifier,\n\t\tcriticalPenalty,\n\t};\n}\n\nfunction buildSummary(counts: FindingSeverityCounts | undefined, grade: string): string {\n\tif (!counts) {\n\t\treturn `Excellent! No security issues found. Grade: ${grade}`;\n\t}\n\n\tconst { critical, high, medium, low } = counts;\n\tconst totalNonInfo = critical + high + medium + low;\n\n\tif (totalNonInfo === 0) {\n\t\treturn `Excellent! No security issues found. Grade: ${grade}`;\n\t}\n\tif (critical > 0) {\n\t\treturn `${critical} critical issue(s) found requiring immediate attention. Grade: ${grade}`;\n\t}\n\tif (high > 0) {\n\t\treturn `${high} high-severity issue(s) found. Grade: ${grade}`;\n\t}\n\treturn `${totalNonInfo} issue(s) found. Grade: ${grade}`;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport {\n\tCATEGORY_DISPLAY_WEIGHTS,\n\tCATEGORY_TIERS,\n\ttype CheckCategory,\n\ttype CheckResult,\n\ttype Finding,\n\tinferFindingConfidence,\n\tscoreIndicatesMissingControl,\n\ttype ScanScore,\n} from './model';\nimport type { DomainContext } from './profiles';\nimport { PROFILE_CRITICAL_CATEGORIES, PROFILE_EMAIL_BONUS_ELIGIBLE } from './profiles';\nimport type { ScoringConfig } from './config';\nimport { DEFAULT_SCORING_CONFIG } from './config';\nimport { computeGenericScore } from './generic';\nimport type { GenericScoringContext, FindingSeverityCounts } from './generic';\n\ninterface ImportanceProfile {\n\timportance: number;\n}\n\n/**\n * Scanner-aligned importance weighting for the checks currently supported by this MCP server.\n * @deprecated Use CORE_WEIGHTS and PROTECTIVE_WEIGHTS for three-tier scoring. Retained for backward compatibility.\n */\nexport const IMPORTANCE_WEIGHTS: Record<CheckCategory, ImportanceProfile> = {\n\tspf: { importance: 10 },\n\tdmarc: { importance: 16 },\n\tdkim: { importance: 10 },\n\tdnssec: { importance: 8 },\n\tssl: { importance: 8 },\n\tmta_sts: { importance: 2 },\n\tns: { importance: 0 },\n\tcaa: { importance: 0 },\n\tsubdomain_takeover: { importance: 3 },\n\tmx: { importance: 2 },\n\tbimi: { importance: 0 },\n\ttlsrpt: { importance: 1 },\n\tlookalikes: { importance: 0 },\n\tshadow_domains: { importance: 0 },\n\ttxt_hygiene: { importance: 0 },\n\thttp_security: { importance: 3 },\n\tdane: { importance: 1 },\n\tmx_reputation: { importance: 0 },\n\tsrv: { importance: 0 },\n\tzone_hygiene: { importance: 0 },\n\tdane_https: { importance: 2 },\n\tsvcb_https: { importance: 1 },\n};\n\n/** Core-tier importance weights (SPF, DMARC, DKIM, DNSSEC, SSL). Used by the three-tier scoring formula. */\nexport const CORE_WEIGHTS: Record<string, number> = {\n\tdmarc: 16, dkim: 10, spf: 10, dnssec: 8, ssl: 8,\n};\n\n/** Protective-tier importance weights. Used by the three-tier scoring formula. */\nexport const PROTECTIVE_WEIGHTS: Record<string, number> = {\n\tsubdomain_takeover: 4, http_security: 3, mta_sts: 3, mx: 2,\n\tcaa: 2, ns: 2, lookalikes: 2, shadow_domains: 2,\n};\n\n\n/** Map numeric score to letter grade */\nexport function scoreToGrade(score: number, config?: ScoringConfig): string {\n\tconst g = config?.grades ?? DEFAULT_SCORING_CONFIG.grades;\n\tif (score >= g.aPlus) return 'A+';\n\tif (score >= g.a) return 'A';\n\tif (score >= g.bPlus) return 'B+';\n\tif (score >= g.b) return 'B';\n\tif (score >= g.cPlus) return 'C+';\n\tif (score >= g.c) return 'C';\n\tif (score >= g.dPlus) return 'D+';\n\tif (score >= g.d) return 'D';\n\treturn 'F';\n}\n\n/** Default critical categories used when no context is provided. */\nconst DEFAULT_CRITICAL_CATEGORIES: CheckCategory[] = ['spf', 'dmarc', 'dkim', 'ssl'];\n\n/**\n * Build a GenericScoringContext from CheckResult[] + DomainContext.\n *\n * This bridges the concrete bv-mcp types (CheckResult, CheckCategory, Finding)\n * to the generic scoring engine's string-keyed inputs.\n */\nfunction buildGenericContext(\n\tresults: CheckResult[],\n\tcategoryScores: Record<CheckCategory, number>,\n\tallFindings: Finding[],\n\tcontext: DomainContext | undefined,\n\tconfig: ScoringConfig,\n): GenericScoringContext {\n\t// --- Build weights map (flat importance values) ---\n\tconst weights: Record<string, number> = {};\n\n\tif (context) {\n\t\tfor (const category of Object.keys(context.weights) as CheckCategory[]) {\n\t\t\tweights[category] = context.weights[category].importance;\n\t\t}\n\t} else {\n\t\t// Merge core + protective from config; hardening categories get 0\n\t\tfor (const [key, value] of Object.entries(config.coreWeights)) {\n\t\t\tweights[key] = value;\n\t\t}\n\t\tfor (const [key, value] of Object.entries(config.protectiveWeights)) {\n\t\t\tweights[key] = value;\n\t\t}\n\t\t// Ensure hardening categories are in weights (with 0 from config defaults)\n\t\tfor (const cat of Object.keys(CATEGORY_TIERS) as CheckCategory[]) {\n\t\t\tif (CATEGORY_TIERS[cat] === 'hardening' && !(cat in weights)) {\n\t\t\t\tweights[cat] = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\t// --- Build missingControls map ---\n\t// Only mark a category as missing when an actual result exists and\n\t// scoreIndicatesMissingControl returns true. Absent categories must NOT\n\t// be marked missing — the original engine's critical gap ceiling check\n\t// requires an actual result (`result && scoreIndicatesMissingControl(...)`),\n\t// and absent categories default to 100 with no zeroing.\n\tconst missingControls: Record<string, boolean> = {};\n\tconst resultMap = new Map<CheckCategory, CheckResult>();\n\tfor (const result of results) {\n\t\tresultMap.set(result.category, result);\n\t\tif (scoreIndicatesMissingControl(result.findings)) {\n\t\t\tmissingControls[result.category] = true;\n\t\t}\n\t}\n\n\t// --- Build hardeningPassed map ---\n\t// The original engine iterates ALL hardening categories from CATEGORY_TIERS (not just\n\t// those with results). It uses hardeningCount = total hardening categories.\n\t// A category counts as \"passed\" only if result exists AND result.passed is true.\n\t// Categories without results don't count as passed but DO count toward the denominator.\n\t//\n\t// The generic engine only counts *submitted* keys in hardeningPassed toward the denominator.\n\t// To match: submit ALL hardening categories, marking passed=true only for those with passing results.\n\tconst hardeningPassed: Record<string, boolean> = {};\n\tfor (const cat of Object.keys(CATEGORY_TIERS) as CheckCategory[]) {\n\t\tif (CATEGORY_TIERS[cat] === 'hardening') {\n\t\t\tconst result = resultMap.get(cat);\n\t\t\t// Submit all hardening categories so denominator = total hardening count.\n\t\t\t// Only mark as passed if an actual result was provided AND it passed.\n\t\t\thardeningPassed[cat] = !!(result && result.passed);\n\t\t}\n\t}\n\n\t// --- Extract provider confidence from findings metadata ---\n\tconst providerConfidence: Record<string, number> = {};\n\tfor (const finding of allFindings) {\n\t\tconst confidence = finding.metadata?.providerConfidence;\n\t\tif (typeof confidence === 'number' && Number.isFinite(confidence)) {\n\t\t\t// Use a synthetic key per finding to preserve the original per-finding averaging behavior.\n\t\t\t// The original engine averages ALL providerConfidence values across all findings.\n\t\t\t// The generic engine averages all values in the providerConfidence map.\n\t\t\tconst key = `_finding_${Object.keys(providerConfidence).length}`;\n\t\t\tproviderConfidence[key] = confidence;\n\t\t}\n\t}\n\n\t// --- Build finding severity counts ---\n\t// Critical penalty: original only counts findings with severity=critical AND confidence=verified.\n\t// Generic applies penalty when findingSeverityCounts.critical > 0.\n\t// To match: pass only verified critical findings as the critical count.\n\tconst verifiedCriticalCount = allFindings.filter(\n\t\t(f) => f.severity === 'critical' && inferFindingConfidence(f) === 'verified',\n\t).length;\n\n\t// For critical penalty equivalence, use verified-only count as the \"critical\" count.\n\t// The original engine only applies the penalty for verified critical findings.\n\tconst findingSeverityCounts: FindingSeverityCounts = {\n\t\tcritical: verifiedCriticalCount,\n\t\thigh: allFindings.filter((f) => f.severity === 'high').length,\n\t\tmedium: allFindings.filter((f) => f.severity === 'medium').length,\n\t\tlow: allFindings.filter((f) => f.severity === 'low').length,\n\t\tinfo: allFindings.filter((f) => f.severity === 'info').length,\n\t};\n\n\t// --- Critical categories ---\n\tconst criticalCategories = context\n\t\t? PROFILE_CRITICAL_CATEGORIES[context.profile]\n\t\t: DEFAULT_CRITICAL_CATEGORIES;\n\n\t// --- Email bonus eligibility ---\n\t// Original engine requires actual SPF and DMARC results to exist for the bonus\n\t// (!!spfResult && !!dmarcResult). Absent DKIM qualifies (dkimNotDeterministicallyMissing = !dkimResult || ...).\n\t// Disable email bonus entirely when SPF or DMARC has no result to match original behavior.\n\tlet emailBonusEligible = context ? PROFILE_EMAIL_BONUS_ELIGIBLE[context.profile] : true;\n\tif (!resultMap.has('spf') || !resultMap.has('dmarc')) {\n\t\temailBonusEligible = false;\n\t}\n\n\t// --- Build the summary-compatible severity counts ---\n\t// The original summary uses ALL critical findings (not just verified) for the summary text.\n\t// We store the \"display\" counts separately and use them to override the summary after scoring.\n\t// (The findingSeverityCounts above has verifiedCriticalCount for the penalty calculation.)\n\n\treturn {\n\t\tcategoryScores: { ...categoryScores },\n\t\ttierMap: { ...CATEGORY_TIERS },\n\t\tweights,\n\t\tmissingControls,\n\t\thardeningPassed,\n\t\tcriticalCategories: [...criticalCategories],\n\t\temailBonusEligible,\n\t\tproviderConfidence: Object.keys(providerConfidence).length > 0 ? providerConfidence : undefined,\n\t\tfindingSeverityCounts,\n\t};\n}\n\n/**\n * Compute the overall scan score from individual check results using the three-tier formula.\n *\n * Delegates to `computeGenericScore` internally, building a `GenericScoringContext` from\n * the concrete `CheckResult[]` and optional `DomainContext`.\n *\n * Three tiers:\n * - **Core** (default 70 points): Weighted accumulation of foundational categories (SPF, DMARC, DKIM, DNSSEC, SSL).\n * `scoreIndicatesMissingControl()` can zero a category's contribution when confidence is deterministic/verified.\n * - **Protective** (default 20 points): Weighted accumulation of active defense categories.\n * No `scoreIndicatesMissingControl()` override.\n * - **Hardening** (default 10 points): Binary pass/fail — each category with score >= 50 contributes\n * `tierSplit.hardening / hardeningCount` points. Never subtracts.\n *\n * When a `DomainContext` is provided, uses profile-specific weights partitioned by CATEGORY_TIERS,\n * critical gap categories, and email bonus eligibility instead of defaults.\n */\nexport function computeScanScore(results: CheckResult[], context?: DomainContext, config?: ScoringConfig): ScanScore {\n\tconst partialScores: Partial<Record<CheckCategory, number>> = {};\n\tconst allFindings: Finding[] = [];\n\n\t// Seed all categories to 100 (default for absent results)\n\tfor (const category of Object.keys(CATEGORY_DISPLAY_WEIGHTS) as CheckCategory[]) {\n\t\tpartialScores[category] = 100;\n\t}\n\n\t// All CheckCategory keys are populated above — safe to widen from Partial\n\tconst categoryScores = partialScores as Record<CheckCategory, number>;\n\n\tconst cfg = config ?? DEFAULT_SCORING_CONFIG;\n\n\tif (results.length === 0) {\n\t\treturn {\n\t\t\toverall: 100,\n\t\t\tgrade: scoreToGrade(100, config),\n\t\t\tcategoryScores,\n\t\t\tfindings: [],\n\t\t\tsummary: `Excellent! No security issues found. Grade: ${scoreToGrade(100, config)}`,\n\t\t};\n\t}\n\n\t// Populate category scores from actual results\n\tfor (const result of results) {\n\t\tcategoryScores[result.category] = result.score;\n\t\tallFindings.push(...result.findings);\n\t}\n\n\t// Build the generic context and delegate to the generic engine\n\tconst genericContext = buildGenericContext(results, categoryScores, allFindings, context, cfg);\n\tconst genericResult = computeGenericScore(genericContext, config);\n\n\t// --- Build summary using original logic ---\n\t// The original summary uses ALL critical findings (not just verified ones used for penalty).\n\tconst criticalCount = allFindings.filter((f) => f.severity === 'critical').length;\n\tconst highCount = allFindings.filter((f) => f.severity === 'high').length;\n\tconst totalIssues = allFindings.filter((f) => f.severity !== 'info').length;\n\n\tlet summary: string;\n\tif (totalIssues === 0) {\n\t\tsummary = `Excellent! No security issues found. Grade: ${genericResult.grade}`;\n\t} else if (criticalCount > 0) {\n\t\tsummary = `${criticalCount} critical issue(s) found requiring immediate attention. Grade: ${genericResult.grade}`;\n\t} else if (highCount > 0) {\n\t\tsummary = `${highCount} high-severity issue(s) found. Grade: ${genericResult.grade}`;\n\t} else {\n\t\tsummary = `${totalIssues} issue(s) found. Grade: ${genericResult.grade}`;\n\t}\n\n\treturn {\n\t\toverall: genericResult.overall,\n\t\tgrade: genericResult.grade,\n\t\tcategoryScores,\n\t\tfindings: allFindings,\n\t\tsummary,\n\t};\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Adaptive weight computation for context-aware scoring.\n *\n * Uses exponential moving averages (EMA) of per-category failure rates,\n * collected by the ProfileAccumulator Durable Object, to adjust static\n * importance weights at scoring time. A maturity-gated blend ensures\n * weights stay close to static until enough telemetry has accumulated.\n */\n\nimport type { CheckCategory } from './scoring-model';\nimport type { DomainProfile } from './context-profiles';\nimport { PROFILE_WEIGHTS } from './context-profiles';\n\n// ─── Telemetry interfaces ──────────────────────────────────────────────\n\n/** A single scan's telemetry payload sent to the ProfileAccumulator DO. */\nexport interface ScanTelemetry {\n\tprofile: string;\n\tprovider: string | null;\n\tcategoryFindings: Array<{ category: string; score: number; passed: boolean }>;\n\ttimestamp: number;\n\t/** Overall scan score (0–100). Used for intelligence layer aggregation (histogram, cohort, trends). */\n\toverallScore?: number;\n}\n\n/** Response from the adaptive weights endpoint. */\nexport interface AdaptiveWeightsResponse {\n\tprofile: string;\n\tprovider: string | null;\n\tsampleCount: number;\n\tblendFactor: number;\n\tweights: Record<string, number>;\n\tboundHits: string[];\n}\n\n/** Min/max bounds for an adaptive weight value. */\nexport interface WeightBound {\n\tmin: number;\n\tmax: number;\n}\n\n// ─── Constants ─────────────────────────────────────────────────────────\n\n/** How aggressively deviation from baseline adjusts the weight (0–1). */\nexport const SENSITIVITY = 0.5;\n\n/** Sample count at which blending reaches 100% adaptive. */\nexport const MATURITY_THRESHOLD = 200;\n\n/** EMA span (number of recent observations the average reflects). */\nexport const EMA_SPAN = 200;\n\n/** EMA smoothing factor derived from span. */\nexport const EMA_ALPHA = 2 / (EMA_SPAN + 1);\n\n/** Minimum |scoreDelta| before a scoring note is generated. */\nexport const SCORING_NOTE_DELTA_THRESHOLD = 3;\n\n/** Expected failure rate per category across all domains (prior). */\nexport const BASELINE_FAILURE_RATES: Record<string, number> = {\n\tdmarc: 0.40,\n\tspf: 0.25,\n\tdkim: 0.35,\n\tssl: 0.08,\n\tmta_sts: 0.85,\n\tdnssec: 0.80,\n\tmx: 0.05,\n\tcaa: 0.70,\n\tns: 0.03,\n\tbimi: 0.95,\n\ttlsrpt: 0.90,\n\tsubdomain_takeover: 0.10,\n\tlookalikes: 0.00,\n};\n\n// ─── Weight bounds ─────────────────────────────────────────────────────\n\n/** Categories treated as \"critical mail\" for bound computation in mail-centric profiles. */\nconst CRITICAL_MAIL_CATEGORIES = new Set<string>(['dmarc', 'spf', 'dkim', 'ssl']);\n\n/** Profiles where critical-mail floor applies. */\nconst CRITICAL_MAIL_PROFILES = new Set<string>(['mail_enabled', 'enterprise_mail']);\n\n/**\n * Compute default min/max bounds for an adaptive weight.\n *\n * Critical-mail categories get a higher floor (min 5) to prevent\n * important email-auth checks from being zeroed out.\n */\nexport function defaultBounds(staticWeight: number, isCriticalMail: boolean): WeightBound {\n\tconst minFloor = isCriticalMail ? 5 : 0;\n\treturn {\n\t\tmin: Math.max(minFloor, Math.floor(staticWeight * 0.5)),\n\t\tmax: Math.ceil(staticWeight * 2) + 3,\n\t};\n}\n\n/** Pre-computed bounds for every profile × category combination. */\nexport const WEIGHT_BOUNDS: Record<DomainProfile, Record<CheckCategory, WeightBound>> = (() => {\n\tconst profiles = Object.keys(PROFILE_WEIGHTS) as DomainProfile[];\n\tconst result = {} as Record<DomainProfile, Record<CheckCategory, WeightBound>>;\n\n\tfor (const profile of profiles) {\n\t\tconst weights = PROFILE_WEIGHTS[profile];\n\t\tconst categories = Object.keys(weights) as CheckCategory[];\n\t\tconst profileBounds = {} as Record<CheckCategory, WeightBound>;\n\n\t\tfor (const cat of categories) {\n\t\t\tconst isCritical = CRITICAL_MAIL_PROFILES.has(profile) && CRITICAL_MAIL_CATEGORIES.has(cat);\n\t\t\tprofileBounds[cat] = defaultBounds(weights[cat].importance, isCritical);\n\t\t}\n\n\t\tresult[profile] = profileBounds;\n\t}\n\n\treturn result;\n})();\n\n// ─── Computation functions ─────────────────────────────────────────────\n\n/**\n * Compute a single adaptive weight from EMA failure rate and baseline.\n *\n * @returns The clamped weight and whether a bound was hit ('min' | 'max' | null).\n */\nexport function computeAdaptiveWeight(params: {\n\tstaticWeight: number;\n\temaFailureRate: number;\n\tbaselineFailureRate: number;\n\tbounds: WeightBound;\n}): { weight: number; boundHit: 'min' | 'max' | null } {\n\tconst { staticWeight, emaFailureRate, baselineFailureRate, bounds } = params;\n\n\tconst deviation = emaFailureRate - baselineFailureRate;\n\tconst rawAdjustment = deviation * SENSITIVITY * staticWeight;\n\tconst adaptive = staticWeight + rawAdjustment;\n\tconst clamped = Math.max(bounds.min, Math.min(bounds.max, adaptive));\n\n\tlet boundHit: 'min' | 'max' | null = null;\n\tif (clamped <= bounds.min && adaptive < bounds.min) {\n\t\tboundHit = 'min';\n\t} else if (clamped >= bounds.max && adaptive > bounds.max) {\n\t\tboundHit = 'max';\n\t}\n\n\treturn { weight: clamped, boundHit };\n}\n\n/**\n * Blend static and adaptive weights based on sample maturity.\n *\n * Returns `(1 - blendFactor) * staticWeight + blendFactor * adaptiveWeight`\n * where `blendFactor = min(1.0, sampleCount / MATURITY_THRESHOLD)`.\n */\nexport function blendWeights(staticWeight: number, adaptiveWeight: number, sampleCount: number): number {\n\tconst blendFactor = Math.min(1.0, sampleCount / MATURITY_THRESHOLD);\n\treturn (1 - blendFactor) * staticWeight + blendFactor * adaptiveWeight;\n}\n\n// ─── Type adapter ──────────────────────────────────────────────────────\n\n/**\n * Convert a DO-returned weight map to a CheckCategory-keyed importance record.\n *\n * Falls back to the static profile weight for any category not present in the\n * DO response. Returns `null` if any value is non-finite or negative.\n */\nexport function adaptiveWeightsToContext(\n\tdoWeights: Record<string, number>,\n\tprofile: DomainProfile,\n): Record<CheckCategory, { importance: number }> | null {\n\tconst staticWeights = PROFILE_WEIGHTS[profile];\n\tconst categories = Object.keys(staticWeights) as CheckCategory[];\n\tconst result = {} as Record<CheckCategory, { importance: number }>;\n\n\tfor (const cat of categories) {\n\t\tconst value = cat in doWeights ? doWeights[cat] : staticWeights[cat].importance;\n\t\tif (!isFinite(value) || value < 0) {\n\t\t\treturn null;\n\t\t}\n\t\tresult[cat] = { importance: value };\n\t}\n\n\treturn result;\n}\n\n// ─── Scoring note generation ───────────────────────────────────────────\n\n/**\n * Generate a human-readable note explaining adaptive weight shifts.\n *\n * Returns `null` if the absolute score delta is below the threshold.\n */\nexport function generateScoringNote(\n\tweightDeltas: Record<string, number>,\n\tscoreDelta: number,\n\tprovider: string | null,\n): string | null {\n\tif (Math.abs(scoreDelta) < SCORING_NOTE_DELTA_THRESHOLD) {\n\t\treturn null;\n\t}\n\n\t// Collect significant deltas (|delta| >= 2) sorted by magnitude descending\n\tconst significant = Object.entries(weightDeltas)\n\t\t.filter(([, d]) => Math.abs(d) >= 2)\n\t\t.sort((a, b) => Math.abs(b[1]) - Math.abs(a[1]));\n\n\tif (significant.length === 0) {\n\t\t// No individually significant deltas but overall threshold met — use the largest anyway\n\t\tconst all = Object.entries(weightDeltas).sort((a, b) => Math.abs(b[1]) - Math.abs(a[1]));\n\t\tif (all.length === 0) return null;\n\t\tconst [topCat, topDelta] = all[0];\n\t\treturn formatNote(topCat, topDelta, provider);\n\t}\n\n\tif (significant.length >= 3) {\n\t\tconst [topCat] = significant[0];\n\t\treturn `Several checks were weighted differently based on patterns seen across similar domains. The biggest shift was in ${topCat.toUpperCase()}.`;\n\t}\n\n\tconst [topCat, topDelta] = significant[0];\n\treturn formatNote(topCat, topDelta, provider);\n}\n\n/** Format a single-category scoring note. */\nfunction formatNote(category: string, delta: number, provider: string | null): string {\n\tconst cat = category.toUpperCase();\n\n\tif (delta > 0 && provider) {\n\t\tconst providerDisplay = capitalizeWords(provider);\n\t\treturn `${cat} carried more weight because domains using ${providerDisplay} frequently have issues in this area.`;\n\t}\n\n\tif (delta > 0) {\n\t\treturn `${cat} carried more weight in this scan because it is a common issue across similar domains.`;\n\t}\n\n\treturn `${cat} carried less weight because similar domains rarely have issues there.`;\n}\n\n/** Capitalize the first letter of each word. */\nfunction capitalizeWords(s: string): string {\n\treturn s.replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n// For IDN/Unicode normalization\nimport * as punycode from 'punycode/';\n// Centralized normalization config\nimport {\n\tBLOCKED_SUFFIXES,\n\tBLOCKED_HOSTS,\n\tBLOCKED_IP_PATTERNS,\n\tBLOCKED_DNS_REBINDING,\n\tMAX_DOMAIN_LENGTH,\n\tMAX_LABEL_LENGTH,\n\tLABEL_REGEX,\n} from './config';\n/**\n * Input sanitization and validation utilities for the DNS Security MCP Server.\n * Handles domain validation, input cleaning, and MCP error response helpers.\n * Compatible with Cloudflare Workers runtime (no Node.js APIs).\n */\n\nexport interface ValidationResult {\n\tvalid: boolean;\n\terror?: string;\n}\n\n/**\n * Parse a numeric IPv4 segment using decimal, octal, or hex notation.\n * Returns null when the token is not a numeric IP segment.\n */\nfunction parseIpv4NumberToken(token: string): number | null {\n\tif (!token) return null;\n\n\tlet radix = 10;\n\tlet digits = token;\n\tif (/^0x[0-9a-f]+$/i.test(token)) {\n\t\tradix = 16;\n\t\tdigits = token.slice(2);\n\t} else if (/^0[0-7]+$/.test(token) && token.length > 1) {\n\t\tradix = 8;\n\t}\n\n\tif (digits.length === 0) return null;\n\tconst value = Number.parseInt(digits, radix);\n\tif (!Number.isFinite(value) || value < 0) return null;\n\treturn value;\n}\n\n/**\n * Canonicalize IPv4 literals that may use short/octal/hex forms.\n * Returns null when input is not an IPv4 host literal candidate.\n */\nfunction canonicalizeIpv4Literal(input: string): string | null {\n\tif (!/^[0-9a-fx.]+$/i.test(input)) return null;\n\n\tconst parts = input.split('.');\n\tif (parts.length < 1 || parts.length > 4) return null;\n\tif (parts.some((part) => part.length === 0)) return null;\n\n\tconst values: number[] = [];\n\tfor (const part of parts) {\n\t\tconst parsed = parseIpv4NumberToken(part);\n\t\tif (parsed === null) return null;\n\t\tvalues.push(parsed);\n\t}\n\n\tlet ipAsUint32 = 0;\n\tif (values.length === 1) {\n\t\tif (values[0] > 0xffffffff) return null;\n\t\tipAsUint32 = values[0] >>> 0;\n\t} else if (values.length === 2) {\n\t\tif (values[0] > 0xff || values[1] > 0xffffff) return null;\n\t\tipAsUint32 = ((values[0] << 24) | values[1]) >>> 0;\n\t} else if (values.length === 3) {\n\t\tif (values[0] > 0xff || values[1] > 0xff || values[2] > 0xffff) return null;\n\t\tipAsUint32 = ((values[0] << 24) | (values[1] << 16) | values[2]) >>> 0;\n\t} else {\n\t\tif (values.some((value) => value > 0xff)) return null;\n\t\tipAsUint32 = ((values[0] << 24) | (values[1] << 16) | (values[2] << 8) | values[3]) >>> 0;\n\t}\n\n\tconst oct1 = (ipAsUint32 >>> 24) & 0xff;\n\tconst oct2 = (ipAsUint32 >>> 16) & 0xff;\n\tconst oct3 = (ipAsUint32 >>> 8) & 0xff;\n\tconst oct4 = ipAsUint32 & 0xff;\n\treturn `${oct1}.${oct2}.${oct3}.${oct4}`;\n}\n\n/**\n * Validate and sanitize a domain name for DNS queries.\n * Rejects localhost, private/reserved TLDs, IP addresses, and malformed domains.\n */\n\nexport function validateDomain(input: string): ValidationResult {\n\tif (!input || typeof input !== 'string') {\n\t\treturn { valid: false, error: 'Domain name is required' };\n\t}\n\n\t// Check for invisible/non-printable Unicode (except space, dot, hyphen)\n\tconst invisiblePattern = /[\\p{C}\\p{Zl}\\p{Zp}\\u200B-\\u200D\\uFEFF]/gu;\n\tif (invisiblePattern.test(input)) {\n\t\treturn { valid: false, error: 'Domain contains invalid Unicode or cannot be converted to ASCII' };\n\t}\n\tconst cleaned = input.replace(invisiblePattern, '').trim();\n\tif (cleaned.length === 0) {\n\t\treturn { valid: false, error: 'Domain name is required' };\n\t}\n\n\t// Normalize Unicode to NFC, lowercase, remove trailing dot\n\tlet domain = cleaned.normalize('NFC').toLowerCase();\n\tif (domain.endsWith('.')) domain = domain.slice(0, -1);\n\n\t// Convert Unicode/emoji/IDN to punycode for validation\n\tlet asciiDomain: string;\n\ttry {\n\t\tasciiDomain = punycode.toASCII(domain);\n\t} catch {\n\t\treturn { valid: false, error: 'Domain contains invalid Unicode or cannot be converted to ASCII' };\n\t}\n\n\tif (asciiDomain.length > MAX_DOMAIN_LENGTH) {\n\t\treturn { valid: false, error: `Domain exceeds maximum length of ${MAX_DOMAIN_LENGTH} characters` };\n\t}\n\n\t// Check blocked exact hostnames\n\tif (BLOCKED_HOSTS.includes(asciiDomain)) {\n\t\treturn { valid: false, error: `Domain \"${asciiDomain}\" is not allowed: reserved hostname` };\n\t}\n\n\t// Check blocked suffixes\n\tfor (const suffix of BLOCKED_SUFFIXES) {\n\t\tif (asciiDomain === suffix.slice(1) || asciiDomain.endsWith(suffix)) {\n\t\t\treturn { valid: false, error: `Domain \"${asciiDomain}\" is not allowed: reserved TLD \"${suffix}\"` };\n\t\t}\n\t}\n\n\t// Canonicalize non-standard IPv4 literals (e.g. 127.1, 0177.0.0.1)\n\t// and reject all IP literal forms (public, private, and special).\n\tconst canonicalIpv4 = canonicalizeIpv4Literal(asciiDomain);\n\tif (canonicalIpv4) {\n\t\treturn { valid: false, error: `IP addresses are not allowed: \"${asciiDomain}\"` };\n\t}\n\n\t// Reject dotted numeric host literals that are IPv4-like but malformed/out-of-range.\n\tif (/^\\d+(?:\\.\\d+){1,3}$/.test(asciiDomain)) {\n\t\treturn { valid: false, error: `IP addresses are not allowed: \"${asciiDomain}\"` };\n\t}\n\n\t// Check if it looks like an IP address (blocked)\n\tfor (const pattern of BLOCKED_IP_PATTERNS) {\n\t\tif (pattern.test(asciiDomain)) {\n\t\t\treturn { valid: false, error: `IP addresses are not allowed: \"${asciiDomain}\"` };\n\t\t}\n\t}\n\n\t// Check for DNS rebinding services\n\tfor (const suffix of BLOCKED_DNS_REBINDING) {\n\t\tif (asciiDomain === suffix.slice(1) || asciiDomain.endsWith(suffix)) {\n\t\t\treturn { valid: false, error: 'Domain uses a DNS rebinding service and is not allowed' };\n\t\t}\n\t}\n\n\t// Validate domain label structure (punycode labels)\n\tconst labels = asciiDomain.split('.');\n\tif (labels.length < 2) {\n\t\treturn { valid: false, error: 'Domain must have at least two labels (e.g., example.com)' };\n\t}\n\tfor (const label of labels) {\n\t\tif (label.length === 0) {\n\t\t\treturn { valid: false, error: 'Domain contains empty label (consecutive dots)' };\n\t\t}\n\t\tif (label.length > MAX_LABEL_LENGTH) {\n\t\t\treturn { valid: false, error: `Label \"${label}\" exceeds maximum length of ${MAX_LABEL_LENGTH} characters` };\n\t\t}\n\t\tif (!LABEL_REGEX.test(label)) {\n\t\t\treturn { valid: false, error: `Label \"${label}\" contains invalid characters` };\n\t\t}\n\t}\n\n\treturn { valid: true };\n}\n\n/**\n * Sanitize a domain string: trim, lowercase, remove trailing dot.\n * Call validateDomain first to ensure the domain is valid.\n */\nexport function sanitizeDomain(input: string): string {\n\t// Remove invisible/non-printable Unicode (except space, dot, hyphen)\n\tconst cleaned = input.replace(/[\\p{C}\\p{Zl}\\p{Zp}\\u200B-\\u200D\\uFEFF]/gu, '').trim();\n\tif (cleaned.length === 0) return '';\n\tlet domain = cleaned.normalize('NFC').toLowerCase();\n\tif (domain.endsWith('.')) domain = domain.slice(0, -1);\n\t// Convert Unicode/emoji/IDN to punycode for DNS queries\n\ttry {\n\t\treturn punycode.toASCII(domain);\n\t} catch {\n\t\treturn '';\n\t}\n}\n\n/**\n * Sanitize arbitrary text input for safe logging/display.\n * Removes control characters except newlines and tabs, and truncates length.\n */\nexport function sanitizeInput(input: string, maxLength = 500): string {\n\tif (typeof input !== 'string') return '';\n\tconst sanitized = input.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]/g, '');\n\treturn sanitized.slice(0, maxLength);\n}\n\n\n","// SPDX-License-Identifier: BUSL-1.1\n\n/** Server version — keep in sync with package.json */\nexport const SERVER_VERSION = '2.1.0';","// SPDX-License-Identifier: BUSL-1.1\n\nimport type { CheckCategory, Finding, Severity } from './types';\n\n// Re-export scoring functions from the single source of truth (scoring/model.ts).\n// check-utils keeps createFinding + sanitizeDnsData locally because they apply\n// DNS-specific sanitization that differs from the generic scoring model version.\nexport { buildCheckResult, computeCategoryScore, inferFindingConfidence } from './scoring/model';\n\n// ── Output sanitization (inlined from src/lib/output-sanitize.ts) ──────────\n\n/**\n * Characters that can inject HTML or dangerous markdown constructs.\n * Excludes `_` (common in DNS names like `_dmarc`, `_mta-sts`) and\n * `()` (used in natural-language detail text) which are safe in finding details.\n */\nconst DNS_DATA_UNSAFE = /[`*#[\\]>|<]/g;\n\n/**\n * Sanitize DNS-sourced data before it enters finding detail strings.\n * Strips C0 control characters (preserving tab/newline), replaces HTML/markdown\n * injection characters, but does NOT truncate — DNS data in findings can be\n * longer than display output.\n */\nexport function sanitizeDnsData(input: string): string {\n\treturn input\n\t\t.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]/g, '')\n\t\t.replace(DNS_DATA_UNSAFE, ' ')\n\t\t.replace(/\\s+/g, ' ')\n\t\t.trim();\n}\n\n/**\n * Create a finding object with the given parameters.\n */\nexport function createFinding(\n\tcategory: CheckCategory,\n\ttitle: string,\n\tseverity: Severity,\n\tdetail: string,\n\tmetadata?: Record<string, unknown>,\n): Finding {\n\treturn { category, title, severity, detail: sanitizeDnsData(detail), ...(metadata ? { metadata } : {}) };\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DMARC utility functions.\n * Pure functions for parsing DMARC tags, validating URIs,\n * detecting aggregators, and checking RUA authorization.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { DNSQueryFunction, Finding } from '../types';\nimport { createFinding } from '../check-utils';\n\n/** Parse DMARC tag-value pairs from a DMARC record string. */\nexport function parseDmarcTags(record: string): Map<string, string> {\n\tconst tags = new Map<string, string>();\n\tconst parts = record.split(';');\n\tfor (const part of parts) {\n\t\tconst trimmed = part.trim();\n\t\tconst eqIndex = trimmed.indexOf('=');\n\t\tif (eqIndex > 0) {\n\t\t\tconst key = trimmed.substring(0, eqIndex).trim().toLowerCase();\n\t\t\tconst value = trimmed.substring(eqIndex + 1).trim().toLowerCase();\n\t\t\ttags.set(key, value);\n\t\t}\n\t}\n\treturn tags;\n}\n\n/** Extract the domain part from a mailto: URI, stripping optional size suffix. */\nexport function extractDomainFromMailto(uri: string): string | null {\n\tconst trimmed = uri.trim().toLowerCase();\n\tif (!trimmed.startsWith('mailto:')) return null;\n\tlet email = trimmed.substring(7).trim();\n\temail = email.replace(/![0-9]+[kmgt]?$/i, '');\n\tconst atIndex = email.lastIndexOf('@');\n\tif (atIndex < 0) return null;\n\treturn email.substring(atIndex + 1);\n}\n\n/**\n * Validate DMARC URI format (must be mailto: scheme).\n * Strips the optional RFC 7489 §6.2 size limit suffix before checking.\n */\nexport function isValidDmarcUri(uri: string): boolean {\n\tconst trimmed = uri.trim().toLowerCase();\n\tif (!trimmed.startsWith('mailto:')) {\n\t\treturn false;\n\t}\n\tlet email = trimmed.substring(7).trim();\n\temail = email.replace(/![0-9]+[kmgt]?$/i, '');\n\treturn /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email);\n}\n\n/** Detect known third-party DMARC aggregator services. */\nexport function detectThirdPartyAggregators(uris: string[]): string[] {\n\tconst knownAggregators = [\n\t\t'dmarcian.com',\n\t\t'agari.com',\n\t\t'valimail.com',\n\t\t'returnpath.com',\n\t\t'postmarkapp.com',\n\t\t'dmarcanalyzer.com',\n\t\t'mimecast.com',\n\t\t'proofpoint.com',\n\t\t'250ok.com',\n\t\t'easydmarc.com',\n\t\t'sendmarc.com',\n\t\t'ondmarc.com',\n\t\t'dmarcdigest.com',\n\t\t'dmarcly.com',\n\t\t'powerdmarc.com',\n\t\t'redsift.com',\n\t];\n\n\tconst detected: string[] = [];\n\tfor (const uri of uris) {\n\t\tconst lower = uri.toLowerCase();\n\t\tfor (const aggregator of knownAggregators) {\n\t\t\tif (lower.includes(aggregator) && !detected.includes(aggregator)) {\n\t\t\t\tdetected.push(aggregator);\n\t\t\t}\n\t\t}\n\t}\n\treturn detected;\n}\n\n/**\n * Check cross-domain RUA authorization per RFC 7489 §7.1.\n * When rua= points to a third-party domain, verify authorization TXT records.\n */\nexport async function checkRuaAuthorization(\n\tdomain: string,\n\truaUris: string[],\n\tqueryDNS: DNSQueryFunction,\n\ttimeout?: number,\n): Promise<Finding[]> {\n\tconst findings: Finding[] = [];\n\tconst checkedDomains = new Set<string>();\n\n\tfor (const uri of ruaUris) {\n\t\tconst targetDomain = extractDomainFromMailto(uri);\n\t\tif (!targetDomain || targetDomain === domain || checkedDomains.has(targetDomain)) continue;\n\t\tcheckedDomains.add(targetDomain);\n\n\t\ttry {\n\t\t\tconst authRecords = await queryDNS(`${domain}._report._dmarc.${targetDomain}`, 'TXT', { timeout });\n\t\t\tconst hasAuth = authRecords.some((record) => record.toLowerCase().startsWith('v=dmarc1'));\n\t\t\tif (!hasAuth) {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'dmarc',\n\t\t\t\t\t\t'Third-party aggregate reporting not authorized',\n\t\t\t\t\t\t'medium',\n\t\t\t\t\t\t`Aggregate reports sent to ${targetDomain} will be silently discarded. The authorization record ${domain}._report._dmarc.${targetDomain} must contain a TXT record with \"v=DMARC1\" (RFC 7489 §7.1).`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\t// DNS query failed — don't produce a finding for transient errors.\n\t\t}\n\t}\n\n\treturn findings;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * SPF record analysis helpers.\n * Pure functions for analyzing SPF lookup budgets, extracting signal domains,\n * and checking broad IP ranges.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { DNSQueryFunction, Finding } from '../types';\nimport { createFinding } from '../check-utils';\n\n/** Known risky SPF mechanisms that allow broad sending. */\nexport const RISKY_MECHANISMS = ['+all', '?all'];\n\n/** Maximum recursion depth for SPF include expansion. */\nexport const MAX_RECURSION_DEPTH = 10;\n\n/** Maximum total DNS queries during recursive expansion. */\nexport const MAX_RECURSIVE_QUERIES = 10;\n\nexport type SpfLookupAnalysis = {\n\tcount: number;\n\tmechanisms: string[];\n};\n\nexport type RecursiveState = {\n\ttotalQueries: number;\n\tvisited: Set<string>;\n\tcache: Map<string, SpfLookupAnalysis>;\n\tfindings: Finding[];\n\tcircularDetected: boolean;\n};\n\n/**\n * Count SPF mechanisms that consume DNS lookups in a single record (non-recursive).\n * RFC 7208 limits evaluation to 10 DNS-mechanism lookups.\n */\nexport function analyzeSpfLookupBudget(spfRecord: string): SpfLookupAnalysis {\n\tconst mechanisms: string[] = [];\n\tfor (const token of spfRecord.split(/\\s+/)) {\n\t\tif (!token) continue;\n\t\tconst normalized = token.replace(/^[+\\-~?]/, '').toLowerCase();\n\t\tif (normalized.startsWith('include:')) mechanisms.push('include');\n\t\telse if (normalized === 'a' || normalized.startsWith('a:') || normalized.startsWith('a/')) mechanisms.push('a');\n\t\telse if (normalized === 'mx' || normalized.startsWith('mx:') || normalized.startsWith('mx/')) mechanisms.push('mx');\n\t\telse if (normalized === 'ptr' || normalized.startsWith('ptr:')) mechanisms.push('ptr');\n\t\telse if (normalized.startsWith('exists:')) mechanisms.push('exists');\n\t\t// Note: redirect= is a modifier (RFC 7208 §6.1), not a mechanism.\n\t\t// It does not consume a DNS lookup slot itself — the target record's\n\t\t// mechanisms are counted when countRecursiveLookups recurses into it.\n\t}\n\n\treturn { count: mechanisms.length, mechanisms };\n}\n\n/**\n * Extract include domains and redirect domain from an SPF record.\n * Used by scan-domain provider inference — do not change the return shape.\n */\nexport function extractSpfSignalDomains(spfRecord: string): { includeDomains: string[]; redirectDomain?: string } {\n\tconst includeDomains = Array.from(spfRecord.matchAll(/\\binclude:([^\\s]+)/gi))\n\t\t.map((match) => match[1].trim().toLowerCase())\n\t\t.filter((domain) => domain.length > 0);\n\n\tconst redirectMatch = spfRecord.match(/\\bredirect=([^\\s]+)/i);\n\tconst redirectDomain = redirectMatch?.[1]?.trim().toLowerCase();\n\n\treturn {\n\t\tincludeDomains,\n\t\t...(redirectDomain ? { redirectDomain } : {}),\n\t};\n}\n\n/** Extract domains referenced by include: and redirect= mechanisms. */\nexport function extractLookupDomains(spfRecord: string): { includes: string[]; redirect?: string } {\n\tconst includes: string[] = [];\n\tlet redirect: string | undefined;\n\n\tfor (const token of spfRecord.split(/\\s+/)) {\n\t\tif (!token) continue;\n\t\tconst normalized = token.replace(/^[+\\-~?]/, '').toLowerCase();\n\t\tif (normalized.startsWith('include:')) {\n\t\t\tconst domain = normalized.slice('include:'.length);\n\t\t\tif (domain) includes.push(domain);\n\t\t} else if (normalized.startsWith('redirect=')) {\n\t\t\tconst domain = normalized.slice('redirect='.length);\n\t\t\tif (domain) redirect = domain;\n\t\t}\n\t}\n\n\treturn { includes, redirect };\n}\n\n/**\n * Recursively count all DNS-lookup-generating mechanisms across SPF include chains.\n * Tracks visited domains to detect circular includes.\n */\nexport async function countRecursiveLookups(\n\tspfRecord: string,\n\tdepth: number,\n\tstate: RecursiveState,\n\tqueryDNS: DNSQueryFunction,\n\ttimeout?: number,\n): Promise<number> {\n\tconst local = analyzeSpfLookupBudget(spfRecord);\n\tlet totalCount = local.count;\n\n\tif (depth >= MAX_RECURSION_DEPTH) {\n\t\treturn totalCount;\n\t}\n\n\tconst { includes, redirect } = extractLookupDomains(spfRecord);\n\tconst domainsToResolve = [...includes];\n\tif (redirect) domainsToResolve.push(redirect);\n\n\tfor (const targetDomain of domainsToResolve) {\n\t\tif (state.visited.has(targetDomain)) {\n\t\t\tif (!state.circularDetected) {\n\t\t\t\tstate.circularDetected = true;\n\t\t\t\tstate.findings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'spf',\n\t\t\t\t\t\t'Circular SPF include detected',\n\t\t\t\t\t\t'high',\n\t\t\t\t\t\t`SPF include chain contains a circular reference involving ${targetDomain}. This will cause SPF evaluation to fail.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (state.cache.has(targetDomain)) {\n\t\t\ttotalCount += state.cache.get(targetDomain)!.count;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (state.totalQueries >= MAX_RECURSIVE_QUERIES) {\n\t\t\tbreak;\n\t\t}\n\n\t\tstate.visited.add(targetDomain);\n\t\tstate.totalQueries++;\n\n\t\ttry {\n\t\t\tconst txtRecords = await queryDNS(targetDomain, 'TXT', { timeout });\n\t\t\tconst nestedSpf = txtRecords.find((record) => record.toLowerCase().startsWith('v=spf1'));\n\n\t\t\tif (nestedSpf) {\n\t\t\t\tconst nestedCount = await countRecursiveLookups(nestedSpf, depth + 1, state, queryDNS, timeout);\n\t\t\t\tstate.cache.set(targetDomain, { count: nestedCount, mechanisms: [] });\n\t\t\t\ttotalCount += nestedCount;\n\t\t\t}\n\t\t} catch {\n\t\t\t// DNS query failed for nested domain — local mechanism count already includes the lookup.\n\t\t}\n\n\t\tstate.visited.delete(targetDomain);\n\t}\n\n\treturn totalCount;\n}\n\n/**\n * Check for overly broad IP ranges in SPF record.\n * Returns findings for ip4 prefixes <= /8 and ip6 prefixes <= /16.\n */\nexport function checkBroadIpRanges(spfRecord: string, metadata: Record<string, unknown>): Finding[] {\n\tconst findings: Finding[] = [];\n\n\tfor (const token of spfRecord.split(/\\s+/)) {\n\t\tif (!token) continue;\n\t\tconst normalized = token.replace(/^[+\\-~?]/, '').toLowerCase();\n\n\t\tconst ip4Match = normalized.match(/^ip4:([^/]+)(?:\\/(\\d+))?$/);\n\t\tif (ip4Match) {\n\t\t\tconst prefix = ip4Match[2] ? parseInt(ip4Match[2], 10) : 32;\n\t\t\tif (prefix <= 8) {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'spf',\n\t\t\t\t\t\t'Overly broad IP range',\n\t\t\t\t\t\t'high',\n\t\t\t\t\t\t`SPF record contains \"${token}\" which authorizes an extremely large IP range (/${prefix}). This undermines SPF protection by allowing too many servers to send mail.`,\n\t\t\t\t\t\tmetadata,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst ip6Match = normalized.match(/^ip6:([^/]+)(?:\\/(\\d+))?$/);\n\t\tif (ip6Match) {\n\t\t\tconst prefix = ip6Match[2] ? parseInt(ip6Match[2], 10) : 128;\n\t\t\tif (prefix <= 16) {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'spf',\n\t\t\t\t\t\t'Overly broad IPv6 range',\n\t\t\t\t\t\t'high',\n\t\t\t\t\t\t`SPF record contains \"${token}\" which authorizes an extremely large IPv6 range (/${prefix}). This undermines SPF protection by allowing too many servers to send mail.`,\n\t\t\t\t\t\tmetadata,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn findings;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * SPF Trust Surface Analysis.\n * Identifies when SPF include: or redirect= directives delegate sending\n * authority to multi-tenant SaaS platforms, expanding the domain's trust surface.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { Finding } from '../types';\nimport { createFinding } from '../check-utils';\n\ninterface PlatformInfo {\n\tname: string;\n\trisk: string;\n}\n\nexport interface TrustSurfaceContext {\n\tcorroboratedByWeakDmarc?: boolean;\n\tdmarcPolicy?: string;\n\tdmarcAlignmentMode?: string;\n}\n\n/** Known multi-tenant SaaS platforms whose shared SPF includes widen the trust surface. */\nconst MULTI_TENANT_PLATFORMS: ReadonlyMap<string, PlatformInfo> = new Map([\n\t['_spf.salesforce.com', { name: 'Salesforce', risk: 'Any Salesforce customer can send as your domain' }],\n\t[\n\t\t'spf.protection.outlook.com',\n\t\t{ name: 'Microsoft 365', risk: 'Any M365 tenant can send as your domain without DKIM/DMARC enforcement' },\n\t],\n\t['_spf.google.com', { name: 'Google Workspace', risk: 'Any Google Workspace customer can send as your domain' }],\n\t['sendgrid.net', { name: 'SendGrid', risk: 'Any SendGrid customer can send as your domain' }],\n\t['spf.mandrillapp.com', { name: 'Mailchimp/Mandrill', risk: 'Any Mailchimp customer can send as your domain' }],\n\t['mail.zendesk.com', { name: 'Zendesk', risk: 'Any Zendesk customer can send as your domain' }],\n\t['stspg-customer.com', { name: 'Postmark', risk: 'Any Postmark customer can send as your domain' }],\n\t['spf.brevo.com', { name: 'Brevo (Sendinblue)', risk: 'Any Brevo customer can send as your domain' }],\n\t['amazonses.com', { name: 'Amazon SES', risk: 'Any SES customer can send as your domain' }],\n\t['servers.mcsv.net', { name: 'Mailchimp', risk: 'Any Mailchimp customer can send as your domain' }],\n\t['hubspotemail.net', { name: 'HubSpot', risk: 'Any HubSpot customer can send as your domain' }],\n\t['mktomail.com', { name: 'Marketo', risk: 'Any Marketo customer can send as your domain' }],\n\t['pphosted.com', { name: 'Proofpoint', risk: 'Any Proofpoint customer can send as your domain' }],\n\t['firebasemail.com', { name: 'Firebase', risk: 'Any Firebase project can send as your domain' }],\n\t['freshdesk.com', { name: 'Freshdesk', risk: 'Any Freshdesk customer can send as your domain' }],\n\t['spf.messagelabs.com', { name: 'Symantec/Broadcom', risk: 'Shared sending infrastructure' }],\n\t['_spf.atlassian.net', { name: 'Atlassian', risk: 'Any Atlassian customer can send as your domain' }],\n\t['xero.com', { name: 'Xero', risk: 'Any Xero customer can send as your domain' }],\n]);\n\n/**\n * Check whether a domain matches or is a subdomain of a known multi-tenant platform.\n */\nfunction matchPlatform(domain: string): { key: string; info: PlatformInfo } | undefined {\n\tconst lower = domain.toLowerCase();\n\tfor (const [key, info] of MULTI_TENANT_PLATFORMS) {\n\t\tif (lower === key || lower.endsWith(`.${key}`)) {\n\t\t\treturn { key, info };\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/**\n * Extract include: and redirect= domains from an SPF record string.\n */\nfunction extractIncludeAndRedirectDomains(spfRecord: string): string[] {\n\tconst domains: string[] = [];\n\tconst includeRegex = /\\binclude:([^\\s]+)/gi;\n\tconst redirectRegex = /\\bredirect=([^\\s]+)/gi;\n\n\tlet match: RegExpExecArray | null;\n\twhile ((match = includeRegex.exec(spfRecord)) !== null) {\n\t\tdomains.push(match[1]);\n\t}\n\twhile ((match = redirectRegex.exec(spfRecord)) !== null) {\n\t\tdomains.push(match[1]);\n\t}\n\treturn domains;\n}\n\n/**\n * Analyze an SPF record for trust surface exposure from multi-tenant SaaS platform includes.\n * Returns findings for each shared platform detected, plus a summary finding when multiple are found.\n */\nexport function analyzeTrustSurface(spfRecord: string, context: TrustSurfaceContext = {}): Finding[] {\n\tconst findings: Finding[] = [];\n\tconst domains = extractIncludeAndRedirectDomains(spfRecord);\n\tconst matchedPlatforms: { name: string; includeDomain: string }[] = [];\n\tconst corroboratedByWeakDmarc = context.corroboratedByWeakDmarc === true;\n\tconst findingSeverity = corroboratedByWeakDmarc ? 'medium' : 'info';\n\tconst summarySeverity = corroboratedByWeakDmarc ? 'high' : 'info';\n\tconst detailSuffix = corroboratedByWeakDmarc\n\t\t? 'Weak DMARC enforcement and relaxed alignment corroborate this exposure, so a provider misconfiguration or abuse case would be more likely to pass policy checks.'\n\t\t: 'This is common and not inherently a misconfiguration, but it expands the sending infrastructure you rely on. The risk becomes more material when DMARC enforcement and alignment are weak.';\n\n\tfor (const domain of domains) {\n\t\tconst result = matchPlatform(domain);\n\t\tif (result) {\n\t\t\tmatchedPlatforms.push({ name: result.info.name, includeDomain: domain });\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'spf',\n\t\t\t\t\t`SPF delegates to shared platform: ${result.info.name}`,\n\t\t\t\t\tfindingSeverity,\n\t\t\t\t\t`SPF include:${domain} authorizes ${result.info.name}. ${result.info.risk}. ${detailSuffix}`,\n\t\t\t\t\t{\n\t\t\t\t\t\ttrustSurface: true,\n\t\t\t\t\t\tplatform: result.info.name,\n\t\t\t\t\t\tincludeDomain: domain,\n\t\t\t\t\t\tdmarcCorroborated: corroboratedByWeakDmarc,\n\t\t\t\t\t\t...(context.dmarcPolicy ? { dmarcPolicy: context.dmarcPolicy } : {}),\n\t\t\t\t\t\t...(context.dmarcAlignmentMode ? { dmarcAlignmentMode: context.dmarcAlignmentMode } : {}),\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\tif (matchedPlatforms.length > 1) {\n\t\tconst platformNames = matchedPlatforms.map((p) => p.name).join(', ');\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'spf',\n\t\t\t\t`SPF trust surface: ${matchedPlatforms.length} shared platforms`,\n\t\t\t\tsummarySeverity,\n\t\t\t\t`SPF record delegates sending authority to ${matchedPlatforms.length} multi-tenant platforms (${platformNames}). Audit each include to confirm it is still needed, configure provider-specific DKIM, and keep DMARC enforcement and alignment strong across every authorized sender.`,\n\t\t\t\t{\n\t\t\t\t\ttrustSurface: true,\n\t\t\t\t\tplatformCount: matchedPlatforms.length,\n\t\t\t\t\tplatforms: platformNames,\n\t\t\t\t\tdmarcCorroborated: corroboratedByWeakDmarc,\n\t\t\t\t\t...(context.dmarcPolicy ? { dmarcPolicy: context.dmarcPolicy } : {}),\n\t\t\t\t\t...(context.dmarcAlignmentMode ? { dmarcAlignmentMode: context.dmarcAlignmentMode } : {}),\n\t\t\t\t},\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * SPF (Sender Policy Framework) check.\n * Queries TXT records for SPF and validates the policy.\n * Implements recursive include expansion per RFC 7208 §4.6.4.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { CheckResult, DNSQueryFunction, Finding } from '../types';\nimport { buildCheckResult, createFinding } from '../check-utils';\nimport { parseDmarcTags } from './dmarc-utils';\nimport {\n\tRISKY_MECHANISMS,\n\tcheckBroadIpRanges,\n\tcountRecursiveLookups,\n\textractSpfSignalDomains,\n\ttype RecursiveState,\n} from './spf-analysis';\nimport { analyzeTrustSurface } from './spf-trust-surface';\n\n/** Detect no-send SPF policy: -all or ~all with zero authorizing mechanisms */\nfunction isNoSendPolicy(spf: string): boolean {\n\tconst allMatch = spf.match(/[+?~-]all/i);\n\tif (!allMatch) return false;\n\tconst qualifier = allMatch[0][0];\n\tif (qualifier !== '-' && qualifier !== '~') return false;\n\tconst hasAuthorizing = /\\b(include:|a[:/\\s]|a$|mx[:/\\s]|mx$|ip4:|ip6:|redirect=|exists:)/i.test(spf);\n\treturn !hasAuthorizing;\n}\n\ninterface TrustSurfaceDmarcContext {\n\tcorroboratedByWeakDmarc: boolean;\n\tdmarcPolicy?: string;\n\tdmarcAlignmentMode?: string;\n}\n\nasync function getTrustSurfaceDmarcContext(\n\tdomain: string,\n\tqueryDNS: DNSQueryFunction,\n\ttimeout?: number,\n): Promise<TrustSurfaceDmarcContext> {\n\ttry {\n\t\tconst dmarcRecords = await queryDNS(`_dmarc.${domain}`, 'TXT', { timeout });\n\t\tconst dmarcRecord = dmarcRecords.find((record) => record.toLowerCase().startsWith('v=dmarc1'));\n\n\t\tif (!dmarcRecord) {\n\t\t\treturn {\n\t\t\t\tcorroboratedByWeakDmarc: true,\n\t\t\t\tdmarcPolicy: 'missing',\n\t\t\t\tdmarcAlignmentMode: 'missing',\n\t\t\t};\n\t\t}\n\n\t\tconst tags = parseDmarcTags(dmarcRecord);\n\t\tconst policy = tags.get('p') ?? 'none';\n\t\tconst pct = tags.get('pct') ?? '100';\n\t\tconst aspf = tags.get('aspf') ?? 'r';\n\t\tconst adkim = tags.get('adkim') ?? 'r';\n\t\tconst enforcementWeak = policy !== 'reject' || pct !== '100';\n\t\tconst alignmentWeak = aspf !== 's' || adkim !== 's';\n\t\tconst alignmentMode = aspf === 's' && adkim === 's' ? 'strict' : 'relaxed';\n\n\t\treturn {\n\t\t\tcorroboratedByWeakDmarc: enforcementWeak && alignmentWeak,\n\t\t\tdmarcPolicy: pct === '100' ? policy : `${policy}; pct=${pct}`,\n\t\t\tdmarcAlignmentMode: alignmentMode,\n\t\t};\n\t} catch {\n\t\treturn {\n\t\t\tcorroboratedByWeakDmarc: false,\n\t\t\tdmarcPolicy: 'unknown',\n\t\t\tdmarcAlignmentMode: 'unknown',\n\t\t};\n\t}\n}\n\n/**\n * Check SPF records for a domain.\n * Looks for v=spf1 TXT records and validates their configuration.\n * Recursively expands include chains to compute true DNS lookup count.\n */\nexport async function checkSPF(\n\tdomain: string,\n\tqueryDNS: DNSQueryFunction,\n\toptions?: { timeout?: number },\n): Promise<CheckResult> {\n\tconst timeout = options?.timeout ?? 5000;\n\tconst findings: Finding[] = [];\n\tconst txtRecords = await queryDNS(domain, 'TXT', { timeout });\n\n\t// Filter for SPF records\n\tconst spfRecords = txtRecords.filter((r) => r.toLowerCase().startsWith('v=spf1'));\n\n\tif (spfRecords.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'spf',\n\t\t\t\t'No SPF record found',\n\t\t\t\t'critical',\n\t\t\t\t`No SPF (v=spf1) TXT record found for ${domain}. Without SPF, any server can send email claiming to be from your domain.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('spf', findings);\n\t}\n\n\tif (spfRecords.length > 1) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'spf',\n\t\t\t\t'Multiple SPF records',\n\t\t\t\t'high',\n\t\t\t\t`Found ${spfRecords.length} SPF records. RFC 7208 requires exactly one SPF record per domain. Multiple records cause unpredictable behavior.`,\n\t\t\t),\n\t\t);\n\t}\n\n\tconst spf = spfRecords[0];\n\tconst spfSignals = extractSpfSignalDomains(spf);\n\tconst spfMetadata: Record<string, unknown> = {\n\t\tsignalType: 'spf',\n\t\tincludeDomains: spfSignals.includeDomains,\n\t\t...(spfSignals.redirectDomain ? { redirectDomain: spfSignals.redirectDomain } : {}),\n\t};\n\n\t// Detect no-send policy (e.g., v=spf1 -all with no authorizing mechanisms)\n\tif (isNoSendPolicy(spf)) {\n\t\tspfMetadata.noSendPolicy = true;\n\t}\n\n\t// Check for redirect= — determines whether missing 'all' is an issue\n\tconst hasRedirect = /\\bredirect=/i.test(spf);\n\n\t// Check for overly permissive +all or ?all\n\tconst allMechanism = spf.match(/[+?~-]all/i);\n\tif (allMechanism) {\n\t\tconst qualifier = allMechanism[0];\n\t\tif (RISKY_MECHANISMS.includes(qualifier.toLowerCase())) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'spf',\n\t\t\t\t\t`Permissive SPF: ${qualifier}`,\n\t\t\t\t\t'critical',\n\t\t\t\t\t`SPF record uses \"${qualifier}\" which allows any server to send email as ${domain}. Use \"-all\" (hard fail) or \"~all\" (soft fail) instead.`,\n\t\t\t\t\tspfMetadata,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (qualifier.toLowerCase() === '~all') {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'spf',\n\t\t\t\t\t'SPF soft fail (~all)',\n\t\t\t\t\t'low',\n\t\t\t\t\t`SPF record uses \"~all\" (soft fail). Consider upgrading to \"-all\" (hard fail) for stricter enforcement once you've verified all legitimate senders are included.`,\n\t\t\t\t\tspfMetadata,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\t// -all is the recommended setting, no finding needed\n\t} else if (!hasRedirect) {\n\t\t// RFC 7208 §6.1: redirect= replaces the entire record, making 'all' irrelevant\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'spf',\n\t\t\t\t\"No 'all' mechanism\",\n\t\t\t\t'medium',\n\t\t\t\t`SPF record does not end with an \"all\" mechanism. Without it, the default behavior is neutral, which provides weak protection.`,\n\t\t\t\tspfMetadata,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Check for overly broad IP ranges\n\tfindings.push(...checkBroadIpRanges(spf, spfMetadata));\n\n\t// Recursive DNS lookup budget (RFC 7208 §4.6.4)\n\tconst state: RecursiveState = {\n\t\ttotalQueries: 0,\n\t\tvisited: new Set([domain]),\n\t\tcache: new Map(),\n\t\tfindings: [],\n\t\tcircularDetected: false,\n\t};\n\tconst recursiveLookupCount = await countRecursiveLookups(spf, 0, state, queryDNS, timeout);\n\n\t// Add any circular-include findings from recursive expansion\n\tfindings.push(...state.findings);\n\n\tif (recursiveLookupCount > 10) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'spf',\n\t\t\t\t'Too many DNS lookups',\n\t\t\t\t'critical',\n\t\t\t\t`SPF record requires ${recursiveLookupCount} DNS lookups (limit: 10). Receivers may return PermError and reject legitimate mail.`,\n\t\t\t\t{ ...spfMetadata, lookupCount: recursiveLookupCount },\n\t\t\t),\n\t\t);\n\t} else if (recursiveLookupCount >= 9) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'spf',\n\t\t\t\t'SPF lookup budget near limit',\n\t\t\t\t'high',\n\t\t\t\t`SPF record requires ${recursiveLookupCount}/10 DNS lookups. Any future sender additions may push this domain into permanent SPF failures.`,\n\t\t\t\t{ ...spfMetadata, lookupCount: recursiveLookupCount },\n\t\t\t),\n\t\t);\n\t}\n\n\t// Check for deprecated ptr mechanism\n\tif (/\\bptr\\b/i.test(spf)) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'spf',\n\t\t\t\t'Deprecated ptr mechanism',\n\t\t\t\t'medium',\n\t\t\t\t`SPF record uses the \"ptr\" mechanism which is deprecated in RFC 7208 due to performance and reliability issues.`,\n\t\t\t\tspfMetadata,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Trust surface analysis — flag multi-tenant SaaS platform includes\n\tconst trustSurfaceContext = await getTrustSurfaceDmarcContext(domain, queryDNS, timeout);\n\tconst trustSurfaceFindings = analyzeTrustSurface(spf, trustSurfaceContext);\n\tfindings.push(...trustSurfaceFindings);\n\n\t// Informational trust-surface findings should not suppress the clean SPF status.\n\tconst issueFindings = findings.filter((f) => !(f.metadata?.trustSurface && f.severity === 'info'));\n\tif (issueFindings.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'spf',\n\t\t\t\t'SPF record configured',\n\t\t\t\t'info',\n\t\t\t\t`SPF record found and properly configured: ${spf.substring(0, 100)}${spf.length > 100 ? '...' : ''}`,\n\t\t\t\tspfMetadata,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('spf', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DMARC (Domain-based Message Authentication, Reporting & Conformance) check.\n * Queries _dmarc TXT records and validates the policy.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { CheckResult, DNSQueryFunction, Finding } from '../types';\nimport { buildCheckResult, createFinding } from '../check-utils';\nimport { checkRuaAuthorization, detectThirdPartyAggregators, isValidDmarcUri, parseDmarcTags } from './dmarc-utils';\n\nexport { parseDmarcTags } from './dmarc-utils';\n\n/**\n * Check DMARC records for a domain.\n * Queries _dmarc.<domain> TXT records and validates policy configuration.\n */\nexport async function checkDMARC(\n\tdomain: string,\n\tqueryDNS: DNSQueryFunction,\n\toptions?: { timeout?: number },\n): Promise<CheckResult> {\n\tconst timeout = options?.timeout ?? 5000;\n\tconst findings: Finding[] = [];\n\tconst txtRecords = await queryDNS(`_dmarc.${domain}`, 'TXT', { timeout });\n\n\t// Filter for DMARC records\n\tconst dmarcRecords = txtRecords.filter((r) => r.toLowerCase().startsWith('v=dmarc1'));\n\n\tif (dmarcRecords.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'No DMARC record found',\n\t\t\t\t'critical',\n\t\t\t\t`No DMARC record found at _dmarc.${domain}. Without DMARC, receivers cannot verify email authentication and spoofing is easier.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('dmarc', findings);\n\t}\n\n\tif (dmarcRecords.length > 1) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'Multiple DMARC records',\n\t\t\t\t'high',\n\t\t\t\t`Found ${dmarcRecords.length} DMARC records. Only one DMARC record should exist per domain.`,\n\t\t\t),\n\t\t);\n\t}\n\n\tconst dmarc = dmarcRecords[0];\n\tconst tags = parseDmarcTags(dmarc);\n\tconst validPolicies = new Set(['none', 'quarantine', 'reject']);\n\n\t// Check policy (p= tag)\n\tconst policy = tags.get('p');\n\tif (!policy) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'Missing DMARC policy',\n\t\t\t\t'critical',\n\t\t\t\t`DMARC record is missing the required \"p=\" tag. Without a policy, DMARC provides no protection.`,\n\t\t\t),\n\t\t);\n\t} else if (!validPolicies.has(policy)) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'Invalid DMARC policy value',\n\t\t\t\t'high',\n\t\t\t\t`DMARC policy value \"${policy}\" is invalid. Allowed values are none, quarantine, or reject.`,\n\t\t\t),\n\t\t);\n\t} else if (policy === 'none') {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'DMARC policy set to none',\n\t\t\t\t'high',\n\t\t\t\t`DMARC policy is \"none\" which only monitors but does not reject or quarantine spoofed emails. Consider upgrading to \"quarantine\" or \"reject\".`,\n\t\t\t),\n\t\t);\n\t} else if (policy === 'quarantine') {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'DMARC policy set to quarantine',\n\t\t\t\t'low',\n\t\t\t\t`DMARC policy is \"quarantine\". Consider upgrading to \"reject\" for maximum protection once you've verified legitimate email flows.`,\n\t\t\t),\n\t\t);\n\t}\n\t// \"reject\" is the strongest setting - no finding needed\n\n\t// Check subdomain policy (sp= tag)\n\tconst sp = tags.get('sp');\n\tif (!sp && policy === 'reject') {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'No subdomain policy',\n\t\t\t\t'low',\n\t\t\t\t`No subdomain policy (sp=) specified. Subdomains inherit the main policy (\"${policy}\"), but explicitly setting sp= is recommended.`,\n\t\t\t),\n\t\t);\n\t} else if (!sp && policy === 'none') {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'Subdomains inherit p=none policy',\n\t\t\t\t'info',\n\t\t\t\t'No subdomain policy (sp=) specified. Subdomains inherit the \"none\" policy, which provides no protection against spoofing.',\n\t\t\t),\n\t\t);\n\t} else if (sp) {\n\t\tif (!validPolicies.has(sp)) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Invalid subdomain policy value',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`DMARC subdomain policy value \"${sp}\" is invalid. Allowed values are none, quarantine, or reject.`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (policy === 'reject' && sp === 'none') {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Subdomain policy weaker than parent policy',\n\t\t\t\t\t'high',\n\t\t\t\t\t'Subdomain policy is set to \"none\" while parent policy is \"reject\". This leaves subdomains vulnerable to spoofing.',\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (policy === 'reject' && sp === 'quarantine') {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Subdomain policy weaker than parent policy',\n\t\t\t\t\t'low',\n\t\t\t\t\t'Subdomain policy is \"quarantine\" while parent policy is \"reject\". Consider using sp=reject for consistent enforcement.',\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (policy === 'quarantine' && sp === 'none') {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Subdomain policy weaker than domain policy',\n\t\t\t\t\t'medium',\n\t\t\t\t\t'Subdomain policy is set to \"none\" while domain policy is \"quarantine\". Subdomains are unprotected against spoofing.',\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Check percentage (pct= tag)\n\tconst pct = tags.get('pct');\n\tif (pct) {\n\t\tconst pctValue = Number.parseInt(pct, 10);\n\t\tif (!Number.isFinite(pctValue) || Number.isNaN(pctValue) || pctValue < 0 || pctValue > 100) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Invalid DMARC percentage value',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`DMARC pct value \"${pct}\" is invalid. Allowed range is 0-100.`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (pctValue < 100) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'DMARC not applied to all emails',\n\t\t\t\t'medium',\n\t\t\t\t`DMARC pct=${pctValue} means the policy only applies to ${pctValue}% of emails. Set pct=100 for full coverage.`,\n\t\t\t),\n\t\t);\n\t\t}\n\t}\n\n\t// Check forensic failure reporting options (fo=)\n\tconst fo = tags.get('fo');\n\tif (fo) {\n\t\tconst allowedFoValues = new Set(['0', '1', 'd', 's']);\n\t\tconst foValues = fo\n\t\t\t.split(':')\n\t\t\t.map((v) => v.trim())\n\t\t\t.filter((v) => v.length > 0);\n\n\t\tconst invalidFo = foValues.filter((v) => !allowedFoValues.has(v));\n\t\tif (foValues.length === 0 || invalidFo.length > 0) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Invalid DMARC failure reporting options',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`DMARC fo value \"${fo}\" contains unsupported option(s): ${invalidFo.join(', ') || 'none'}. Allowed values: 0, 1, d, s.`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (foValues.length === 1 && foValues[0] === '0') {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Limited DMARC failure reporting coverage',\n\t\t\t\t\t'low',\n\t\t\t\t\t'DMARC fo=0 only generates forensic reports when both SPF and DKIM fail. Consider fo=1 for broader failure visibility.',\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Check for reporting (rua= tag)\n\tconst rua = tags.get('rua');\n\tif (!rua) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'No aggregate reporting',\n\t\t\t\t'medium',\n\t\t\t\t`No aggregate report URI (rua=) specified. Without reporting, you cannot monitor DMARC authentication results.`,\n\t\t\t),\n\t\t);\n\t} else {\n\t\t// Validate rua= URI format\n\t\tconst ruaUris = rua.split(',').map((u) => u.trim());\n\t\tconst invalidRuaUris = ruaUris.filter((uri) => !isValidDmarcUri(uri));\n\t\tif (invalidRuaUris.length > 0) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Invalid aggregate report URI format',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`DMARC aggregate report URI(s) invalid: ${invalidRuaUris.join(', ')}. Must use mailto: scheme.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\t// Check for third-party aggregator services\n\t\tconst aggregators = detectThirdPartyAggregators(ruaUris);\n\t\tif (aggregators.length > 0) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Third-party DMARC aggregator detected',\n\t\t\t\t\t'info',\n\t\t\t\t\t`Using third-party aggregator(s): ${aggregators.join(', ')}. Ensure these services are authorized to receive your DMARC reports.`,\n\t\t\t\t\t{ aggregators },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\t// Cross-domain RUA authorization check (RFC 7489 §7.1)\n\t\tconst ruaAuthFindings = await checkRuaAuthorization(domain, ruaUris, queryDNS, timeout);\n\t\tfindings.push(...ruaAuthFindings);\n\t}\n\n\t// Check forensic reporting (ruf= tag)\n\tconst ruf = tags.get('ruf');\n\tif (ruf) {\n\t\tconst rufUris = ruf.split(',').map((u) => u.trim());\n\t\tconst invalidRufUris = rufUris.filter((uri) => !isValidDmarcUri(uri));\n\t\tif (invalidRufUris.length > 0) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Invalid forensic report URI format',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`DMARC forensic report URI(s) invalid: ${invalidRufUris.join(', ')}. Must use mailto: scheme.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t} else if (rua) {\n\t\t// rua= is present but ruf= is not\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'No forensic reporting configured (ruf= absent)',\n\t\t\t\t'low',\n\t\t\t\t'Aggregate reporting (rua=) is configured but forensic reporting (ruf=) is not. Forensic reports provide detailed failure information useful for troubleshooting.',\n\t\t\t),\n\t\t);\n\t}\n\n\t// Check DKIM alignment mode (adkim= tag)\n\tconst adkim = tags.get('adkim');\n\tif (adkim && adkim !== 'r' && adkim !== 's') {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'Invalid DKIM alignment mode',\n\t\t\t\t'medium',\n\t\t\t\t`DMARC adkim value \"${adkim}\" is invalid. Allowed values are \"r\" (relaxed) or \"s\" (strict).`,\n\t\t\t),\n\t\t);\n\t} else if (!adkim || adkim === 'r') {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'Relaxed DKIM alignment',\n\t\t\t\t'low',\n\t\t\t\t`DKIM alignment mode is relaxed (adkim=r or unset). Consider adkim=s (strict) for stronger authentication.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Check SPF alignment mode (aspf= tag)\n\tconst aspf = tags.get('aspf');\n\tif (aspf && aspf !== 'r' && aspf !== 's') {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'Invalid SPF alignment mode',\n\t\t\t\t'medium',\n\t\t\t\t`DMARC aspf value \"${aspf}\" is invalid. Allowed values are \"r\" (relaxed) or \"s\" (strict).`,\n\t\t\t),\n\t\t);\n\t} else if (!aspf || aspf === 'r') {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'Relaxed SPF alignment',\n\t\t\t\t'low',\n\t\t\t\t`SPF alignment mode is relaxed (aspf=r or unset). Consider aspf=s (strict) for stronger authentication.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// If no critical, high, or medium issues found, add info\n\tconst hasSignificantIssues = findings.some((f) => f.severity === 'critical' || f.severity === 'high' || f.severity === 'medium');\n\tif (!hasSignificantIssues) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'DMARC properly configured',\n\t\t\t\t'info',\n\t\t\t\t`DMARC record found with policy \"${policy}\" and valid core tags.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('dmarc', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DKIM key analysis helpers.\n * Pure functions for analyzing DKIM key strength and consolidating findings.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { Finding } from '../types';\nimport { createFinding } from '../check-utils';\n\nexport type DkimKeyStrength = 'critical' | 'high' | 'medium' | 'info';\n\nexport type DkimKeyAnalysis = {\n\tbits: number | null;\n\tstrength: DkimKeyStrength;\n\tkeyType: 'rsa' | 'ed25519' | 'unknown';\n};\n\nexport function getDkimTagValue(record: string, tag: string): string | undefined {\n\tif (!/^[a-zA-Z0-9]+$/.test(tag)) return undefined;\n\tconst match = record.match(new RegExp(`(?:^|;)\\\\s*${tag}=([^;]*)`, 'i'));\n\treturn match?.[1]?.trim();\n}\n\n/**\n * Analyze key strength based on key type and base64 character count.\n * For RSA keys, estimates bit-length from base64 character count.\n * For Ed25519 keys, always returns info (strong by design).\n */\nexport function analyzeKeyStrength(publicKeyBase64: string | undefined, declaredKeyType: string): DkimKeyAnalysis {\n\tif (!publicKeyBase64) {\n\t\treturn { bits: null, strength: 'info', keyType: 'unknown' };\n\t}\n\n\tif (declaredKeyType === 'ed25519') {\n\t\treturn { bits: 256, strength: 'info', keyType: 'ed25519' };\n\t}\n\n\tconst cleanKey = publicKeyBase64.replace(/\\s/g, '');\n\tconst charCount = cleanKey.length;\n\n\tif (declaredKeyType === 'rsa-default' && charCount < 50) {\n\t\treturn { bits: null, strength: 'medium', keyType: 'unknown' };\n\t}\n\n\tif (charCount < 150) {\n\t\treturn { bits: 512, strength: 'critical', keyType: 'rsa' };\n\t}\n\n\tif (charCount < 230) {\n\t\treturn { bits: 1024, strength: 'high', keyType: 'rsa' };\n\t}\n\n\tif (charCount < 550) {\n\t\treturn { bits: 2048, strength: 'medium', keyType: 'rsa' };\n\t}\n\n\treturn { bits: 4096, strength: 'info', keyType: 'rsa' };\n}\n\nexport function consolidateSelectorProbeKeyStrengthFindings(findings: Finding[]): void {\n\tconst seen = new Set<string>();\n\tlet removed = 0;\n\n\tfor (let index = findings.length - 1; index >= 0; index--) {\n\t\tconst finding = findings[index];\n\t\tif (!/rsa key:/i.test(finding.title)) continue;\n\t\tif (!['critical', 'high', 'medium'].includes(finding.severity)) continue;\n\t\tconst estimatedBits = finding.metadata?.estimatedBits;\n\t\tconst keyType = finding.metadata?.keyType;\n\t\tif (typeof estimatedBits !== 'number' || keyType !== 'rsa') continue;\n\n\t\tconst key = `${finding.severity}:${estimatedBits}:${keyType}`;\n\t\tif (seen.has(key)) {\n\t\t\tfindings.splice(index, 1);\n\t\t\tremoved += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tseen.add(key);\n\t}\n\n\tif (removed > 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dkim',\n\t\t\t\t'Similar DKIM key-strength findings consolidated',\n\t\t\t\t'info',\n\t\t\t\t`Consolidated ${removed} duplicate selector-probe key-strength finding(s) to reduce repeated penalty for identical key profiles across selectors.`,\n\t\t\t),\n\t\t);\n\t}\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DKIM (DomainKeys Identified Mail) check.\n * Queries common DKIM selector TXT records and validates configuration.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { CheckResult, DNSQueryFunction, Finding } from '../types';\nimport { buildCheckResult, createFinding } from '../check-utils';\nimport { analyzeKeyStrength, consolidateSelectorProbeKeyStrengthFindings, getDkimTagValue } from './dkim-analysis';\n\n/** Common DKIM selectors used by major email providers */\nconst COMMON_SELECTORS = [\n\t'default',\n\t'google',\n\t'20230601', // Google Workspace\n\t'selector1', // Microsoft 365\n\t'selector2', // Microsoft 365\n\t'k1', // Mailchimp\n\t's1',\n\t's2',\n\t'mail',\n\t'dkim',\n\t'amazonses', // Amazon SES\n\t'zoho', // Zoho Mail\n];\n\n/**\n * Check DKIM records for a domain.\n * Probes common selectors at <selector>._domainkey.<domain>.\n * Optionally accepts a specific selector to check.\n */\nexport async function checkDKIM(\n\tdomain: string,\n\tqueryDNS: DNSQueryFunction,\n\toptions?: { timeout?: number; selector?: string },\n): Promise<CheckResult> {\n\tconst timeout = options?.timeout ?? 5000;\n\tconst selector = options?.selector;\n\tconst findings: Finding[] = [];\n\tconst selectorsToCheck = selector ? [selector] : COMMON_SELECTORS;\n\tconst foundSelectors: string[] = [];\n\tlet hasValidKey = false;\n\n\t// Check each selector in parallel\n\tconst results = await Promise.all(\n\t\tselectorsToCheck.map(async (sel) => {\n\t\t\ttry {\n\t\t\t\tconst records = await queryDNS(`${sel}._domainkey.${domain}`, 'TXT', { timeout });\n\t\t\t\tconst dkimRecords = records.filter((r) => r.toLowerCase().includes('v=dkim1') || r.includes('p='));\n\t\t\t\treturn { selector: sel, records: dkimRecords };\n\t\t\t} catch {\n\t\t\t\treturn { selector: sel, records: [] };\n\t\t\t}\n\t\t}),\n\t);\n\n\tfor (const result of results) {\n\t\tif (result.records.length > 0) {\n\t\t\tfoundSelectors.push(result.selector);\n\n\t\t\t// Validate each DKIM record\n\t\t\tfor (const record of result.records) {\n\t\t\t\tconst isRevoked = /p=\\s*;/i.test(record) || /p=\\s*$/i.test(record);\n\t\t\t\tconst publicKey = getDkimTagValue(record, 'p');\n\n\t\t\t\t// Check for empty public key (revoked)\n\t\t\t\tif (isRevoked) {\n\t\t\t\t\tfindings.push(\n\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t'dkim',\n\t\t\t\t\t\t\t`Revoked DKIM key: ${result.selector}`,\n\t\t\t\t\t\t\t'medium',\n\t\t\t\t\t\t\t`DKIM selector \"${result.selector}\" has an empty public key (p=), indicating the key has been revoked.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\thasValidKey = true;\n\t\t\t\t}\n\n\t\t\t\t// Check key type (should be rsa or ed25519)\n\t\t\t\tconst keyTypeMatch = record.match(/k=([^;\\s]+)/i);\n\t\t\t\tconst parsedKeyType = keyTypeMatch ? keyTypeMatch[1].toLowerCase() : null;\n\t\t\t\tif (keyTypeMatch && !['rsa', 'ed25519'].includes(parsedKeyType!)) {\n\t\t\t\t\tfindings.push(\n\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t'dkim',\n\t\t\t\t\t\t\t`Unknown DKIM key type: ${keyTypeMatch[1]}`,\n\t\t\t\t\t\t\t'medium',\n\t\t\t\t\t\t\t`DKIM selector \"${result.selector}\" uses unknown key type \"${keyTypeMatch[1]}\". Expected \"rsa\" or \"ed25519\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Check for testing mode\n\t\t\t\tif (/t=y/i.test(record)) {\n\t\t\t\t\tfindings.push(\n\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t'dkim',\n\t\t\t\t\t\t\t`DKIM in testing mode: ${result.selector}`,\n\t\t\t\t\t\t\t'low',\n\t\t\t\t\t\t\t`DKIM selector \"${result.selector}\" is in testing mode (t=y). Verifiers may treat failures as non-fatal.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Analyze key strength (only if key is valid/not revoked)\n\t\t\t\tif (!isRevoked && publicKey) {\n\t\t\t\t\tconst declaredKeyType = parsedKeyType ?? 'rsa-default';\n\t\t\t\t\tconst keyAnalysis = analyzeKeyStrength(publicKey, declaredKeyType);\n\n\t\t\t\t\tif (keyAnalysis.keyType === 'ed25519') {\n\t\t\t\t\t\tfindings.push(\n\t\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t\t'dkim',\n\t\t\t\t\t\t\t\t`Ed25519 key detected: ${result.selector}`,\n\t\t\t\t\t\t\t\t'info',\n\t\t\t\t\t\t\t\t`DKIM selector \"${result.selector}\" uses Ed25519, a strong elliptic-curve key type.`,\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tkeyType: 'ed25519',\n\t\t\t\t\t\t\t\t\tselector: result.selector,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (keyAnalysis.keyType === 'unknown') {\n\t\t\t\t\t\tfindings.push(\n\t\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t\t'dkim',\n\t\t\t\t\t\t\t\t`Short key material: ${result.selector}`,\n\t\t\t\t\t\t\t\t'medium',\n\t\t\t\t\t\t\t\t`DKIM selector \"${result.selector}\" has very short key material without a k= tag. Consider adding \"k=ed25519\" or \"k=rsa\" for clarity.`,\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tselector: result.selector,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (keyAnalysis.keyType === 'rsa') {\n\t\t\t\t\t\tconst severityMsg =\n\t\t\t\t\t\t\tkeyAnalysis.strength === 'critical'\n\t\t\t\t\t\t\t\t? 'weak'\n\t\t\t\t\t\t\t\t: keyAnalysis.strength === 'high'\n\t\t\t\t\t\t\t\t\t? 'legacy'\n\t\t\t\t\t\t\t\t\t: keyAnalysis.strength === 'medium'\n\t\t\t\t\t\t\t\t\t\t? 'below recommended'\n\t\t\t\t\t\t\t\t\t\t: 'strong';\n\t\t\t\t\t\tconst descriptions: Record<string, string> = {\n\t\t\t\t\t\t\tcritical:\n\t\t\t\t\t\t\t\t`DKIM RSA key for \"${result.selector}\" is ${severityMsg} (~${keyAnalysis.bits} bits). Upgrade to 2048-bit RSA or use Ed25519 for better security.`,\n\t\t\t\t\t\t\thigh: `DKIM RSA key for \"${result.selector}\" is ${severityMsg} (${keyAnalysis.bits} bits). Consider upgrading to 2048-bit RSA or Ed25519.`,\n\t\t\t\t\t\t\tmedium: `DKIM RSA key for \"${result.selector}\" is ${severityMsg} (${keyAnalysis.bits} bits). Major providers recommend 4096-bit RSA or Ed25519.`,\n\t\t\t\t\t\t\tinfo: `DKIM RSA key for \"${result.selector}\" is strong (${keyAnalysis.bits} bits).`,\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tif (keyAnalysis.strength !== 'info') {\n\t\t\t\t\t\t\tfindings.push(\n\t\t\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t\t\t'dkim',\n\t\t\t\t\t\t\t\t\t`${severityMsg.charAt(0).toUpperCase() + severityMsg.slice(1)} RSA key: ${result.selector}`,\n\t\t\t\t\t\t\t\t\tkeyAnalysis.strength,\n\t\t\t\t\t\t\t\t\tdescriptions[keyAnalysis.strength],\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\testimatedBits: keyAnalysis.bits,\n\t\t\t\t\t\t\t\t\t\tkeyType: keyAnalysis.keyType,\n\t\t\t\t\t\t\t\t\t\tselector: result.selector,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Check for missing v= tag (should be v=DKIM1)\n\t\t\t\tconst versionTag = getDkimTagValue(record, 'v');\n\t\t\t\tif (!versionTag) {\n\t\t\t\t\tfindings.push(\n\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t'dkim',\n\t\t\t\t\t\t\t`Missing DKIM version tag: ${result.selector}`,\n\t\t\t\t\t\t\t'medium',\n\t\t\t\t\t\t\t`DKIM selector \"${result.selector}\" is missing the v= tag. Should be set to v=DKIM1.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// If multiple found selectors are ALL revoked and none have valid keys,\n\t// this is a non-sending domain posture — downgrade to info\n\tif (foundSelectors.length > 1 && !hasValidKey) {\n\t\tconst revokedCount = findings.filter((f) => f.title.startsWith('Revoked DKIM key:')).length;\n\t\t// Remove individual revoked findings\n\t\tfor (let i = findings.length - 1; i >= 0; i--) {\n\t\t\tif (findings[i].title.startsWith('Revoked DKIM key:')) {\n\t\t\t\tfindings.splice(i, 1);\n\t\t\t}\n\t\t}\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dkim',\n\t\t\t\t'DKIM keys revoked (non-sending)',\n\t\t\t\t'info',\n\t\t\t\t`All ${revokedCount} DKIM selector(s) have revoked keys (empty p= tag). This is expected for domains that do not send email.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// In selector-probing mode, multiple selectors can expose identical key profiles.\n\tif (!selector && foundSelectors.length > 1) {\n\t\tconsolidateSelectorProbeKeyStrengthFindings(findings);\n\t}\n\n\tif (foundSelectors.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dkim',\n\t\t\t\t'No DKIM records found among tested selectors',\n\t\t\t\t'high',\n\t\t\t\t`No DKIM records were found for ${domain} among the tested selector set (${selectorsToCheck.join(', ')}). This result is based on selector probing and may miss custom selector names. DKIM helps verify email authenticity and integrity.`,\n\t\t\t\t{\n\t\t\t\t\tsignalType: 'dkim',\n\t\t\t\t\tconfidence: 'heuristic',\n\t\t\t\t\tdetectionMethod: 'selector-probing',\n\t\t\t\t\tselectorsChecked: selectorsToCheck,\n\t\t\t\t\tselectorsFound: [],\n\t\t\t\t},\n\t\t\t),\n\t\t);\n\t} else if (foundSelectors.length > 0 && hasValidKey && findings.every((f) => f.severity === 'info')) {\n\t\tfindings.push(\n\t\t\tcreateFinding('dkim', 'DKIM configured', 'info', `DKIM records found for selectors: ${foundSelectors.join(', ')}`, {\n\t\t\t\tsignalType: 'dkim',\n\t\t\t\tselectorsChecked: selectorsToCheck,\n\t\t\t\tselectorsFound: foundSelectors,\n\t\t\t}),\n\t\t);\n\t}\n\n\treturn buildCheckResult('dkim', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DNSSEC analysis helpers.\n * Pure functions for auditing DNSKEY algorithms and DS digest types.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { Finding } from '../types';\nimport { createFinding } from '../check-utils';\n\n/** DNSKEY algorithm number to human-readable name and security status */\nconst DNSKEY_ALGORITHMS: Record<number, { name: string; deprecated: boolean }> = {\n\t5: { name: 'RSA/SHA-1', deprecated: true },\n\t7: { name: 'RSASHA1-NSEC3', deprecated: true },\n\t8: { name: 'RSA/SHA-256', deprecated: false },\n\t10: { name: 'RSA/SHA-512', deprecated: false },\n\t13: { name: 'ECDSA P-256', deprecated: false },\n\t14: { name: 'ECDSA P-384', deprecated: false },\n\t15: { name: 'Ed25519', deprecated: false },\n};\n\n/** Modern algorithm numbers that warrant a positive info finding */\nconst MODERN_ALGORITHMS = new Set([13, 14, 15]);\n\n/** DS digest types considered deprecated */\nconst DEPRECATED_DS_DIGESTS: Record<number, string> = {\n\t1: 'SHA-1',\n};\n\n/**\n * Parse the algorithm number from a DNSKEY record data string.\n * Format: \"flags protocol algorithm <base64key>\" e.g. \"257 3 13 mdsswUyr3DPW...\"\n */\nexport function parseDnskeyAlgorithm(data: string): number | null {\n\tconst parts = data.trim().split(/\\s+/);\n\tif (parts.length < 3) return null;\n\tconst algorithm = parseInt(parts[2], 10);\n\treturn isNaN(algorithm) ? null : algorithm;\n}\n\n/**\n * Parse algorithm and digest type from a DS record data string.\n * Format: \"keytag algorithm digesttype <hex-digest>\" e.g. \"12345 13 2 abc123...\"\n */\nexport function parseDsRecord(data: string): { algorithm: number; digestType: number } | null {\n\tconst parts = data.trim().split(/\\s+/);\n\tif (parts.length < 3) return null;\n\tconst algorithm = parseInt(parts[1], 10);\n\tconst digestType = parseInt(parts[2], 10);\n\tif (isNaN(algorithm) || isNaN(digestType)) return null;\n\treturn { algorithm, digestType };\n}\n\n/**\n * Audit DNSKEY algorithm numbers and produce findings for deprecated or modern algorithms.\n */\nexport function auditDnskeyAlgorithms(domain: string, dnskeyRecords: string[]): Finding[] {\n\tconst findings: Finding[] = [];\n\tconst seenAlgorithms = new Set<number>();\n\n\tfor (const record of dnskeyRecords) {\n\t\tconst algorithm = parseDnskeyAlgorithm(record);\n\t\tif (algorithm === null || seenAlgorithms.has(algorithm)) continue;\n\t\tseenAlgorithms.add(algorithm);\n\n\t\tconst known = DNSKEY_ALGORITHMS[algorithm];\n\t\tif (known?.deprecated) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dnssec',\n\t\t\t\t\t`Deprecated DNSKEY algorithm (${known.name})`,\n\t\t\t\t\t'high',\n\t\t\t\t\t`${domain} uses DNSKEY algorithm ${algorithm} (${known.name}), which is deprecated and may be vulnerable to collision attacks. Upgrade to ECDSA (algorithm 13/14) or Ed25519 (algorithm 15).`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (MODERN_ALGORITHMS.has(algorithm)) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dnssec',\n\t\t\t\t\t`Modern DNSSEC algorithm (${known!.name})`,\n\t\t\t\t\t'info',\n\t\t\t\t\t`${domain} uses DNSKEY algorithm ${algorithm} (${known!.name}), which is a modern and secure choice.`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (!known) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dnssec',\n\t\t\t\t\t`Unknown DNSKEY algorithm (${algorithm})`,\n\t\t\t\t\t'medium',\n\t\t\t\t\t`${domain} uses DNSKEY algorithm ${algorithm}, which is not a commonly recognized DNSSEC algorithm. Verify this is intentional.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\treturn findings;\n}\n\n/**\n * Audit DS digest types and produce findings for deprecated digests.\n */\nexport function auditDsDigestTypes(domain: string, dsRecords: string[]): Finding[] {\n\tconst findings: Finding[] = [];\n\tconst seenDigestTypes = new Set<number>();\n\n\tfor (const record of dsRecords) {\n\t\tconst parsed = parseDsRecord(record);\n\t\tif (parsed === null) continue;\n\n\t\tconst { digestType } = parsed;\n\t\tif (seenDigestTypes.has(digestType)) continue;\n\t\tseenDigestTypes.add(digestType);\n\n\t\tconst deprecatedName = DEPRECATED_DS_DIGESTS[digestType];\n\t\tif (deprecatedName) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dnssec',\n\t\t\t\t\t`Deprecated DS digest type (${deprecatedName})`,\n\t\t\t\t\t'medium',\n\t\t\t\t\t`${domain} uses DS digest type ${digestType} (${deprecatedName}), which is deprecated. Use SHA-256 (type 2) or SHA-384 (type 4) instead.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\treturn findings;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DNSSEC (DNS Security Extensions) check.\n * Validates DNSSEC by checking the AD flag, querying for DNSKEY/DS records,\n * and auditing algorithm and digest type security.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { CheckResult, DNSQueryFunction, Finding, RawDNSQueryFunction } from '../types';\nimport { buildCheckResult, createFinding } from '../check-utils';\nimport { auditDnskeyAlgorithms, auditDsDigestTypes } from './dnssec-analysis';\n\nexport { parseDnskeyAlgorithm, parseDsRecord } from './dnssec-analysis';\n\n/**\n * Check DNSSEC configuration for a domain.\n * Verifies the AD (Authenticated Data) flag, checks for DNSKEY/DS records,\n * and audits algorithm and digest type security.\n *\n * Requires a rawQueryDNS function that returns the full DoH response (including AD flag).\n * Falls back to queryDNS for DNSKEY/DS record queries.\n */\nexport async function checkDNSSEC(\n\tdomain: string,\n\tqueryDNS: DNSQueryFunction,\n\toptions?: { timeout?: number; rawQueryDNS?: RawDNSQueryFunction },\n): Promise<CheckResult> {\n\tconst timeout = options?.timeout ?? 5000;\n\tconst rawQueryDNS = options?.rawQueryDNS;\n\tconst findings: Finding[] = [];\n\n\t// Check AD flag via raw DoH query\n\tlet adFlag = false;\n\ttry {\n\t\tif (rawQueryDNS) {\n\t\t\tconst resp = await rawQueryDNS(domain, 'A', true, { timeout });\n\t\t\tadFlag = resp.AD === true;\n\t\t}\n\t\t// If no rawQueryDNS provided, we can't check AD flag — continue without it\n\t} catch {\n\t\tfindings.push(\n\t\t\tcreateFinding('dnssec', 'DNSSEC check failed', 'medium', `Could not verify DNSSEC status for ${domain}. The DNS query failed.`),\n\t\t);\n\t\treturn buildCheckResult('dnssec', findings);\n\t}\n\n\t// Query DNSKEY and DS records independently; default to empty on failure\n\tlet dnskeyRecords: string[] = [];\n\tlet dsRecords: string[] = [];\n\n\ttry {\n\t\tdnskeyRecords = await queryDNS(domain, 'DNSKEY', { timeout });\n\t} catch {\n\t\t// Non-critical: DNSKEY query failure — treat as absent\n\t}\n\n\ttry {\n\t\tdsRecords = await queryDNS(domain, 'DS', { timeout });\n\t} catch {\n\t\t// Non-critical: DS query failure — treat as absent\n\t}\n\n\t// Consolidated finding logic\n\tif (!adFlag && dnskeyRecords.length === 0 && dsRecords.length === 0) {\n\t\t// Fully absent — single MEDIUM\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dnssec',\n\t\t\t\t'DNSSEC not enabled',\n\t\t\t\t'high',\n\t\t\t\t`DNSSEC is not configured for ${domain}. Without DNSSEC, DNS responses are not cryptographically verified, leaving SPF, DMARC, and DKIM records vulnerable to DNS-level manipulation.`,\n\t\t\t\t{ missingControl: true },\n\t\t\t),\n\t\t);\n\t} else if (dnskeyRecords.length > 0 && dsRecords.length === 0) {\n\t\t// DNSKEY published but no DS in parent zone — broken chain\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dnssec',\n\t\t\t\t'DNSSEC chain of trust incomplete',\n\t\t\t\t'high',\n\t\t\t\t`DNSKEY records are published for ${domain} but no DS records exist in the parent zone. The chain of trust is broken — DNSSEC validation will fail.`,\n\t\t\t),\n\t\t);\n\t} else if (dnskeyRecords.length > 0 && dsRecords.length > 0 && !adFlag) {\n\t\t// Deployed but validation failing — worse than not having DNSSEC\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dnssec',\n\t\t\t\t'DNSSEC validation failing',\n\t\t\t\t'high',\n\t\t\t\t`DNSKEY and DS records are present for ${domain} but the AD flag is not set. DNSSEC is deployed but validation is failing — this is worse than not having DNSSEC.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Algorithm/digest audits (only when records exist)\n\tif (dnskeyRecords.length > 0) {\n\t\tfindings.push(...auditDnskeyAlgorithms(domain, dnskeyRecords));\n\t}\n\tif (dsRecords.length > 0) {\n\t\tfindings.push(...auditDsDigestTypes(domain, dsRecords));\n\t}\n\n\t// If DNSSEC is valid and no issues found (only info findings at most)\n\tif (findings.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dnssec',\n\t\t\t\t'DNSSEC enabled and validated',\n\t\t\t\t'info',\n\t\t\t\t`DNSSEC is properly configured for ${domain}. DNS responses are cryptographically verified.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('dnssec', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * SSL/TLS analysis helpers.\n * Pure functions for analyzing HTTPS connectivity and HSTS headers.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { Finding } from '../types';\nimport { createFinding } from '../check-utils';\n\nexport function getHttpsFindings(domain: string, responseUrl: string | undefined, hstsHeader: string | null): Finding[] {\n\tconst findings: Finding[] = [];\n\n\tif (responseUrl && responseUrl.startsWith('http://')) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'ssl',\n\t\t\t\t'HTTPS redirects to HTTP',\n\t\t\t\t'critical',\n\t\t\t\t`${domain} redirects HTTPS requests to HTTP, exposing traffic to interception.`,\n\t\t\t),\n\t\t);\n\t}\n\n\tif (!hstsHeader) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'ssl',\n\t\t\t\t'No HSTS header',\n\t\t\t\t'medium',\n\t\t\t\t`${domain} does not set a Strict-Transport-Security header. HSTS prevents browsers from connecting over plain HTTP.`,\n\t\t\t),\n\t\t);\n\t\treturn findings;\n\t}\n\n\tconst maxAgeMatch = hstsHeader.match(/max-age=(\\d+)/i);\n\tif (maxAgeMatch) {\n\t\tconst maxAge = parseInt(maxAgeMatch[1], 10);\n\t\tif (maxAge < 31536000) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'ssl',\n\t\t\t\t\t'HSTS max-age too short',\n\t\t\t\t\t'low',\n\t\t\t\t\t`HSTS max-age is ${maxAge} seconds (${Math.round(maxAge / 86400)} days). Recommended minimum is 31536000 (1 year).`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\tif (!/includeSubDomains/i.test(hstsHeader)) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'ssl',\n\t\t\t\t'HSTS missing includeSubDomains',\n\t\t\t\t'low',\n\t\t\t\t'HSTS header does not include the includeSubDomains directive. Subdomains are not protected by HSTS.',\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n\nexport function getHttpsErrorFinding(domain: string, message: string): Finding {\n\tif (message.includes('timeout') || message.includes('abort')) {\n\t\treturn createFinding(\n\t\t\t'ssl',\n\t\t\t'HTTPS connection timeout',\n\t\t\t'high',\n\t\t\t`Could not establish HTTPS connection to ${domain} within 10 seconds. The server may not support HTTPS.`,\n\t\t);\n\t}\n\n\treturn createFinding(\n\t\t'ssl',\n\t\t'HTTPS connection failed',\n\t\t'critical',\n\t\t`Failed to connect to ${domain} over HTTPS: ${message}. The domain may not have a valid SSL certificate.`,\n\t);\n}\n\nexport function getHttpRedirectFindings(domain: string, status: number, location: string | null): Finding[] {\n\tif (status >= 300 && status < 400 && location?.startsWith('https://')) {\n\t\treturn [];\n\t}\n\n\tif (status >= 300 && status < 400 && location && !location.startsWith('https://')) {\n\t\treturn [\n\t\t\tcreateFinding(\n\t\t\t\t'ssl',\n\t\t\t\t'HTTP does not redirect to HTTPS',\n\t\t\t\t'medium',\n\t\t\t\t`HTTP requests to ${domain} redirect to ${location} instead of HTTPS.`,\n\t\t\t),\n\t\t];\n\t}\n\n\treturn [\n\t\tcreateFinding(\n\t\t\t'ssl',\n\t\t\t'No HTTP to HTTPS redirect',\n\t\t\t'medium',\n\t\t\t`HTTP requests to ${domain} are not redirected to HTTPS (status ${status}).`,\n\t\t),\n\t];\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * SSL/TLS certificate check.\n * Validates SSL certificate by attempting HTTPS connection,\n * checks HSTS configuration, and verifies HTTP->HTTPS redirect.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { CheckResult, FetchFunction, Finding } from '../types';\nimport { buildCheckResult, createFinding } from '../check-utils';\nimport { getHttpRedirectFindings, getHttpsErrorFinding, getHttpsFindings } from './ssl-analysis';\n\n/** Default HTTPS timeout (ms) */\nconst HTTPS_TIMEOUT_MS = 4_000;\n\n/**\n * Check SSL/TLS configuration for a domain.\n * Validates HTTPS connectivity, HSTS headers, and HTTP->HTTPS redirect.\n *\n * Requires a fetch function for making HTTP requests.\n */\nexport async function checkSSL(\n\tdomain: string,\n\tfetchFn: FetchFunction,\n\toptions?: { timeout?: number },\n): Promise<CheckResult> {\n\tconst timeoutMs = options?.timeout ?? HTTPS_TIMEOUT_MS;\n\tconst findings: Finding[] = [];\n\n\tconst httpsResult = await checkHttps(domain, fetchFn, timeoutMs);\n\tfindings.push(...httpsResult);\n\n\t// Only check HTTP redirect if HTTPS is working (no critical findings)\n\tconst hasCritical = findings.some((f) => f.severity === 'critical');\n\tif (!hasCritical) {\n\t\tconst redirectResult = await checkHttpRedirect(domain, fetchFn, timeoutMs);\n\t\tfindings.push(...redirectResult);\n\t}\n\n\tif (findings.length === 0) {\n\t\tfindings.push(createFinding('ssl', 'HTTPS and HSTS properly configured', 'info', `HTTPS connection succeeded and HSTS header is properly configured for ${domain}. Note: This check verifies HTTPS reachability and HSTS policy. Certificate expiry, TLS version, and cipher suite analysis require a dedicated TLS scanner.`));\n\t}\n\n\treturn buildCheckResult('ssl', findings);\n}\n\n/** Check HTTPS connectivity by attempting a fetch */\nasync function checkHttps(domain: string, fetchFn: FetchFunction, timeoutMs: number): Promise<Finding[]> {\n\tconst findings: Finding[] = [];\n\n\ttry {\n\t\tconst response = await fetchFn(`https://${domain}`, {\n\t\t\tmethod: 'HEAD',\n\t\t\tredirect: 'manual',\n\t\t\tsignal: AbortSignal.timeout(timeoutMs),\n\t\t});\n\n\t\tconst isRedirect = response.status >= 300 && response.status < 400;\n\t\tconst location = isRedirect ? response.headers.get('location') : null;\n\t\tconst isDowngrade = location?.startsWith('http://') ?? false;\n\t\tconst isHttpsRedirect = isRedirect && !isDowngrade;\n\n\t\tif (!isHttpsRedirect) {\n\t\t\tconst redirectTarget = isDowngrade ? (location ?? undefined) : undefined;\n\t\t\tfindings.push(...getHttpsFindings(domain, redirectTarget, response.headers.get('strict-transport-security')));\n\t\t}\n\n\t} catch (err) {\n\t\tconst message = err instanceof Error && (err.message.includes('timeout') || err.message.includes('abort'))\n\t\t\t? 'Connection timeout'\n\t\t\t: 'Connection failed';\n\t\tfindings.push(getHttpsErrorFinding(domain, message));\n\t}\n\n\treturn findings;\n}\n\n/** Check if HTTP redirects to HTTPS */\nasync function checkHttpRedirect(domain: string, fetchFn: FetchFunction, timeoutMs: number): Promise<Finding[]> {\n\tconst findings: Finding[] = [];\n\ttry {\n\t\tconst response = await fetchFn(`http://${domain}`, {\n\t\t\tmethod: 'HEAD',\n\t\t\tredirect: 'manual',\n\t\t\tsignal: AbortSignal.timeout(timeoutMs),\n\t\t});\n\t\tfindings.push(...getHttpRedirectFindings(domain, response.status, response.headers.get('location')));\n\t} catch {\n\t\t// HTTP not available or blocked — not necessarily an issue, skip silently\n\t}\n\treturn findings;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * MTA-STS analysis helpers.\n * Pure functions for analyzing MTA-STS TXT records, policy files, and TLS-RPT records.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { Finding } from '../types';\nimport { createFinding } from '../check-utils';\n\nexport function getMtaStsTxtFindings(records: string[]): { findings: Finding[]; hasTxtRecord: boolean } {\n\tconst findings: Finding[] = [];\n\tconst mtaStsRecords = records.filter((record) => /^v=stsv1[;\\s]/i.test(record));\n\n\tif (mtaStsRecords.length === 0) {\n\t\treturn {\n\t\t\tfindings: [\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mta_sts',\n\t\t\t\t\t'No MTA-STS record found',\n\t\t\t\t\t'medium',\n\t\t\t\t\t'',\n\t\t\t\t\t{ missingControl: true },\n\t\t\t\t),\n\t\t\t],\n\t\t\thasTxtRecord: false,\n\t\t};\n\t}\n\n\tif (mtaStsRecords.length > 1) {\n\t\tfindings.push(\n\t\t\tcreateFinding('mta_sts', 'Multiple MTA-STS records', 'medium', `Found ${mtaStsRecords.length} MTA-STS records. Only one should exist.`),\n\t\t);\n\t}\n\n\tif (!mtaStsRecords[0].includes('id=')) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mta_sts',\n\t\t\t\t'MTA-STS missing id tag',\n\t\t\t\t'medium',\n\t\t\t\t'MTA-STS record is missing the \"id=\" tag. This tag is required for policy versioning.',\n\t\t\t),\n\t\t);\n\t}\n\n\treturn { findings, hasTxtRecord: true };\n}\n\nexport function finalizeMissingMtaStsRecordFinding(findings: Finding[], domain: string): Finding[] {\n\treturn findings.map((finding) =>\n\t\tfinding.title === 'No MTA-STS record found'\n\t\t\t? createFinding(\n\t\t\t\t\t'mta_sts',\n\t\t\t\t\t'No MTA-STS record found',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`No MTA-STS TXT record found at _mta-sts.${domain}. MTA-STS enforces TLS for incoming email, preventing downgrade attacks.`,\n\t\t\t\t\t{ missingControl: true },\n\t\t\t\t)\n\t\t\t: finding,\n\t);\n}\n\nexport function getMtaStsPolicyFindings(body: string, policyUrl: string): Finding[] {\n\tconst findings: Finding[] = [];\n\tconst versionMatch = body.match(/version:\\s*(\\S+)/i);\n\tif (!versionMatch || versionMatch[1] !== 'STSv1') {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mta_sts',\n\t\t\t\t'MTA-STS policy missing or invalid version',\n\t\t\t\t'high',\n\t\t\t\t'The MTA-STS policy must contain \"version: STSv1\" as required by RFC 8461.',\n\t\t\t),\n\t\t);\n\t}\n\n\tconst modeMatch = body.match(/mode:\\s*(enforce|testing|none)/i);\n\n\tif (!modeMatch) {\n\t\tfindings.push(\n\t\t\tcreateFinding('mta_sts', 'MTA-STS policy missing mode', 'high', 'MTA-STS policy file does not contain a valid \"mode:\" directive.'),\n\t\t);\n\t} else {\n\t\tconst mode = modeMatch[1].toLowerCase();\n\t\tif (mode === 'testing') {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding('mta_sts', 'MTA-STS in testing mode', 'low', 'MTA-STS policy is in \"testing\" mode. Consider switching to \"enforce\" once verified.'),\n\t\t\t);\n\t\t} else if (mode === 'none') {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding('mta_sts', 'MTA-STS policy disabled', 'medium', 'MTA-STS policy mode is \"none\", effectively disabling MTA-STS protection.'),\n\t\t\t);\n\t\t}\n\t}\n\n\tif (!body.includes('mx:')) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mta_sts',\n\t\t\t\t'MTA-STS policy missing MX entries',\n\t\t\t\t'high',\n\t\t\t\t'MTA-STS policy file does not contain any \"mx:\" entries. At least one MX pattern is required.',\n\t\t\t),\n\t\t);\n\t}\n\n\tconst maxAgeMatch = body.match(/max_age:\\s*(\\d+)/i);\n\tif (!maxAgeMatch) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mta_sts',\n\t\t\t\t'MTA-STS policy missing max_age',\n\t\t\t\t'high',\n\t\t\t\t'The max_age directive is required by RFC 8461. Without it, the policy is technically invalid.',\n\t\t\t),\n\t\t);\n\t} else {\n\t\tconst maxAge = parseInt(maxAgeMatch[1], 10);\n\t\tif (maxAge < 86400) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mta_sts',\n\t\t\t\t\t'MTA-STS max_age too short',\n\t\t\t\t\t'low',\n\t\t\t\t\t`MTA-STS max_age is ${maxAge} seconds (less than 1 day). A short max_age reduces the effectiveness of MTA-STS protection.`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (maxAge > 31557600) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mta_sts',\n\t\t\t\t\t'MTA-STS max_age exceeds one year',\n\t\t\t\t\t'info',\n\t\t\t\t\t`MTA-STS max_age is ${maxAge} seconds (more than 1 year). This is acceptable but noted.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\tif (findings.length === 0) {\n\t\treturn [];\n\t}\n\n\treturn findings.map((finding) =>\n\t\tfinding.title === 'MTA-STS policy missing mode' || finding.title === 'MTA-STS policy missing MX entries'\n\t\t\t? createFinding('mta_sts', finding.title, finding.severity, finding.detail.replace('MTA-STS policy file', `MTA-STS policy file at ${policyUrl}`))\n\t\t\t: finding,\n\t);\n}\n\nexport function extractPolicyMxPatterns(body: string): string[] {\n\treturn [...body.matchAll(/mx:\\s*(\\S+)/gi)].map((match) => match[1].toLowerCase());\n}\n\nexport function matchesMxPattern(hostname: string, pattern: string): boolean {\n\tif (pattern.startsWith('*.')) {\n\t\tconst suffix = pattern.slice(1);\n\t\treturn hostname.endsWith(suffix) || hostname === pattern.slice(2);\n\t}\n\n\treturn hostname === pattern;\n}\n\nexport function getUncoveredMxHostFindings(mxHosts: string[], policyMxPatterns: string[]): Finding[] {\n\treturn mxHosts.flatMap((mxHost) => {\n\t\tconst hostname = mxHost.toLowerCase();\n\t\tconst covered = policyMxPatterns.some((pattern) => matchesMxPattern(hostname, pattern));\n\t\tif (covered) {\n\t\t\treturn [];\n\t\t}\n\n\t\treturn [\n\t\t\tcreateFinding(\n\t\t\t\t'mta_sts',\n\t\t\t\t`MTA-STS policy does not cover MX host ${mxHost}`,\n\t\t\t\t'high',\n\t\t\t\t`The MX host ${mxHost} is not matched by any mx: entry in the MTA-STS policy. Mail delivered to this MX will fail MTA-STS validation.`,\n\t\t\t),\n\t\t];\n\t});\n}\n\nexport function hasValidTlsRptRecord(records: string[]): boolean {\n\treturn records.some((record) => record.toLowerCase().startsWith('v=tlsrptv1'));\n}\n\nexport function getTlsRptRecordFindings(records: string[]): { findings: Finding[]; hasTlsRptRecord: boolean } {\n\tconst validRecords = records.filter((record) => record.toLowerCase().startsWith('v=tlsrptv1'));\n\tif (validRecords.length === 0) {\n\t\treturn {\n\t\t\tfindings: [\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mta_sts',\n\t\t\t\t\t'TLS-RPT record missing',\n\t\t\t\t\t'low',\n\t\t\t\t\t'',\n\t\t\t\t),\n\t\t\t],\n\t\t\thasTlsRptRecord: false,\n\t\t};\n\t}\n\n\tconst tlsrptRecord = validRecords[0];\n\tconst ruaMatch = tlsrptRecord.match(/rua\\s*=\\s*([^;\\s]+)/i);\n\tif (!ruaMatch) {\n\t\treturn {\n\t\t\tfindings: [\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mta_sts',\n\t\t\t\t\t'TLS-RPT missing rua directive',\n\t\t\t\t\t'low',\n\t\t\t\t\t'TLS-RPT record does not contain a \"rua=\" directive. The rua URI is needed to receive TLS failure reports.',\n\t\t\t\t),\n\t\t\t],\n\t\t\thasTlsRptRecord: true,\n\t\t};\n\t}\n\n\tconst ruaValue = ruaMatch[1];\n\tconst isValidMailto = /^mailto:[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/.test(ruaValue);\n\tconst isValidHttps = /^https:\\/\\/.+/.test(ruaValue);\n\tif (!isValidMailto && !isValidHttps) {\n\t\treturn {\n\t\t\tfindings: [\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mta_sts',\n\t\t\t\t\t'TLS-RPT invalid rua format',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`TLS-RPT rua value \"${ruaValue}\" is not a valid mailto: or https: URI.`,\n\t\t\t\t),\n\t\t\t],\n\t\t\thasTlsRptRecord: true,\n\t\t};\n\t}\n\n\treturn { findings: [], hasTlsRptRecord: true };\n}\n\nexport function finalizeMissingTlsRptRecordFinding(findings: Finding[], domain: string): Finding[] {\n\treturn findings.map((finding) =>\n\t\tfinding.title === 'TLS-RPT record missing'\n\t\t\t? createFinding(\n\t\t\t\t\t'mta_sts',\n\t\t\t\t\t'TLS-RPT record missing',\n\t\t\t\t\t'low',\n\t\t\t\t\t`No TLS-RPT record found at _smtp._tls.${domain}. Consider adding a TLS-RPT record for reporting SMTP TLS issues.`,\n\t\t\t\t)\n\t\t\t: finding,\n\t);\n}\n\nexport function shouldSummarizeMissingMailProtections(findings: Finding[], hasTxtRecord: boolean, tlsRptChecked: boolean, hasTlsRptRecord: boolean): boolean {\n\tconst hasDnsErrorFindings = findings.some((finding) => finding.title.includes('DNS query failed'));\n\treturn !hasTxtRecord && tlsRptChecked && !hasTlsRptRecord && !hasDnsErrorFindings;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * MTA-STS (Mail Transfer Agent Strict Transport Security) check.\n * Queries _mta-sts TXT records and validates the MTA-STS policy.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { CheckResult, DNSQueryFunction, FetchFunction, Finding } from '../types';\nimport { buildCheckResult, createFinding } from '../check-utils';\nimport {\n\tfinalizeMissingMtaStsRecordFinding,\n\tfinalizeMissingTlsRptRecordFinding,\n\textractPolicyMxPatterns,\n\tgetMtaStsPolicyFindings,\n\tgetMtaStsTxtFindings,\n\tgetTlsRptRecordFindings,\n\tgetUncoveredMxHostFindings,\n\tshouldSummarizeMissingMailProtections,\n} from './mta-sts-analysis';\n\n/** Default HTTPS timeout (ms) */\nconst HTTPS_TIMEOUT_MS = 4_000;\n\n/**\n * Parse MX records from raw DNS response strings.\n * MX data format: \"priority exchange\"\n */\nfunction parseMxFromRaw(answers: string[]): Array<{ exchange: string }> {\n\treturn answers.map((answer) => {\n\t\tconst parts = answer.split(' ');\n\t\tconst exchange = (parts.slice(1).join(' ') || '').replace(/\\.$/, '').toLowerCase();\n\t\treturn { exchange };\n\t});\n}\n\n/**\n * Check MTA-STS configuration for a domain.\n * Queries _mta-sts.<domain> TXT records and optionally fetches the policy file.\n */\nexport async function checkMTASTS(\n\tdomain: string,\n\tqueryDNS: DNSQueryFunction,\n\toptions?: { timeout?: number; fetchFn?: FetchFunction },\n): Promise<CheckResult> {\n\tconst timeout = options?.timeout ?? 5000;\n\tconst fetchFn = options?.fetchFn;\n\tlet findings: Finding[] = [];\n\n\t// Check for _mta-sts TXT record\n\tlet hasTxtRecord = false;\n\ttry {\n\t\tconst txtRecords = await queryDNS(`_mta-sts.${domain}`, 'TXT', { timeout });\n\t\tconst txtAnalysis = getMtaStsTxtFindings(txtRecords);\n\t\thasTxtRecord = txtAnalysis.hasTxtRecord;\n\t\tfindings.push(...finalizeMissingMtaStsRecordFinding(txtAnalysis.findings, domain));\n\t} catch {\n\t\tfindings = [];\n\t\tfindings.push(createFinding('mta_sts', 'MTA-STS DNS query failed', 'low', `Could not query MTA-STS TXT record for ${domain}.`));\n\t}\n\n\t// Try to fetch the MTA-STS policy file (only if fetch function provided)\n\tif (hasTxtRecord && fetchFn) {\n\t\ttry {\n\t\t\tconst policyUrl = `https://mta-sts.${domain}/.well-known/mta-sts.txt`;\n\t\t\tconst response = await fetchFn(policyUrl, {\n\t\t\t\tmethod: 'GET',\n\t\t\t\tredirect: 'manual',\n\t\t\t\tsignal: AbortSignal.timeout(HTTPS_TIMEOUT_MS),\n\t\t\t});\n\n\t\t\tif ([301, 302, 303, 307, 308].includes(response.status)) {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'mta_sts',\n\t\t\t\t\t\t'MTA-STS policy redirects',\n\t\t\t\t\t\t'high',\n\t\t\t\t\t\t`MTA-STS policy file at ${policyUrl} returned HTTP ${response.status} redirect. The policy must be served directly at the well-known URL without redirects.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else if (!response.ok) {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'mta_sts',\n\t\t\t\t\t\t'MTA-STS policy file not accessible',\n\t\t\t\t\t\t'high',\n\t\t\t\t\t\t`MTA-STS policy file at ${policyUrl} returned HTTP ${response.status}. The policy file must be accessible over HTTPS.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconst MAX_BODY_BYTES = 65_536; // 64 KB — RFC 8461 max for MTA-STS\n\t\t\t\tconst contentLength = parseInt(response.headers?.get('content-length') ?? '0', 10);\n\t\t\t\tif (contentLength > MAX_BODY_BYTES) {\n\t\t\t\t\tfindings.push(\n\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t'mta_sts',\n\t\t\t\t\t\t\t'MTA-STS policy file oversized',\n\t\t\t\t\t\t\t'high',\n\t\t\t\t\t\t\t`MTA-STS policy file at ${policyUrl} exceeds 64 KB (Content-Length: ${contentLength}). This is abnormally large for an MTA-STS policy and was not fetched.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tconst body = await response.text();\n\t\t\t\t\tif (body.length > MAX_BODY_BYTES) {\n\t\t\t\t\t\tfindings.push(\n\t\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t\t'mta_sts',\n\t\t\t\t\t\t\t\t'MTA-STS policy file oversized',\n\t\t\t\t\t\t\t\t'high',\n\t\t\t\t\t\t\t\t`MTA-STS policy file at ${policyUrl} exceeds 64 KB. This is abnormally large for an MTA-STS policy and was not parsed.`,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfindings.push(...getMtaStsPolicyFindings(body, policyUrl));\n\n\t\t\t\t\t\tconst policyMxPatterns = extractPolicyMxPatterns(body);\n\t\t\t\t\t\tconst modeMatch = body.match(/mode:\\s*(enforce|testing|none)/i);\n\t\t\t\t\t\tconst policyMode = modeMatch ? modeMatch[1].toLowerCase() : '';\n\t\t\t\t\t\tif (policyMxPatterns.length > 0 && (policyMode === 'enforce' || policyMode === 'testing')) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst mxAnswers = await queryDNS(domain, 'MX', { timeout });\n\t\t\t\t\t\t\t\tconst mxRecords = parseMxFromRaw(mxAnswers);\n\t\t\t\t\t\t\t\tfindings.push(\n\t\t\t\t\t\t\t\t\t...getUncoveredMxHostFindings(mxRecords.map((mx) => mx.exchange), policyMxPatterns),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// MX query failed; skip coverage cross-check.\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mta_sts',\n\t\t\t\t\t'MTA-STS policy fetch failed',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`Could not fetch MTA-STS policy file from https://mta-sts.${domain}/.well-known/mta-sts.txt`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Check for TLSRPT record\n\tlet hasTlsRptRecord = false;\n\tlet tlsRptChecked = false;\n\ttry {\n\t\tconst tlsrptRecords = await queryDNS(`_smtp._tls.${domain}`, 'TXT', { timeout });\n\t\ttlsRptChecked = true;\n\t\tconst tlsRptAnalysis = getTlsRptRecordFindings(tlsrptRecords);\n\t\thasTlsRptRecord = tlsRptAnalysis.hasTlsRptRecord;\n\t\tfindings.push(...finalizeMissingTlsRptRecordFinding(tlsRptAnalysis.findings, domain));\n\t} catch {\n\t\ttlsRptChecked = true;\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mta_sts',\n\t\t\t\t'TLS-RPT DNS query failed',\n\t\t\t\t'low',\n\t\t\t\t`Could not query TLS-RPT TXT record for ${domain}.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// If no issues found\n\tif (findings.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mta_sts',\n\t\t\t\t'MTA-STS properly configured',\n\t\t\t\t'info',\n\t\t\t\t`MTA-STS is properly configured for ${domain} with an accessible policy file.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// If both records are missing, add a clear summary and suppress duplicate findings\n\tif (shouldSummarizeMissingMailProtections(findings, hasTxtRecord, tlsRptChecked, hasTlsRptRecord)) {\n\t\tfindings = [];\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mta_sts',\n\t\t\t\t'No MTA-STS or TLS-RPT records found',\n\t\t\t\t'medium',\n\t\t\t\t`Neither MTA-STS nor TLS-RPT records are present for ${domain}. This is normal for domains that do not accept inbound email, but consider adding these records if you operate a mail server.`,\n\t\t\t\t{ missingControl: true },\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('mta_sts', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * MX record analysis helpers.\n * Pure functions for parsing and analyzing MX records.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { Finding } from '../types';\nimport { createFinding } from '../check-utils';\n\nexport type ParsedMxRecord = {\n\tpriority: number;\n\texchange: string;\n\traw: string;\n};\n\nexport function parseMxRecords(answers: string[]): ParsedMxRecord[] {\n\treturn answers.map((answer) => {\n\t\tconst parts = answer.split(' ');\n\t\tconst priority = parseInt(parts[0], 10);\n\t\tconst exchange = (parts.slice(1).join(' ') || '').replace(/\\.$/, '').toLowerCase();\n\t\treturn { priority, exchange, raw: answer };\n\t});\n}\n\nexport function isNullMxRecord(record: ParsedMxRecord): boolean {\n\treturn record.exchange === '' || record.exchange === '.';\n}\n\nexport function getNullMxFinding(): Finding {\n\treturn createFinding('mx', 'Null MX record (RFC 7505)', 'info', 'Domain explicitly declares it does not accept email via null MX record.');\n}\n\nexport function getPresenceFinding(mxRecords: ParsedMxRecord[]): Finding {\n\treturn createFinding('mx', 'MX records found', 'info', `${mxRecords.length} mail exchange record(s) present.`);\n}\n\nexport function getIpTargetFindings(mxRecords: ParsedMxRecord[]): Finding[] {\n\tconst ipPattern = /^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/;\n\treturn mxRecords.flatMap((mxRecord) =>\n\t\tipPattern.test(mxRecord.exchange)\n\t\t\t? [\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'mx',\n\t\t\t\t\t\t'MX points to IP address',\n\t\t\t\t\t\t'medium',\n\t\t\t\t\t\t`MX record \"${mxRecord.raw}\" points to an IP address. MX targets must be hostnames per RFC 5321.`,\n\t\t\t\t\t),\n\t\t\t\t]\n\t\t\t: [],\n\t);\n}\n\nexport function getSingleMxFinding(mxRecords: ParsedMxRecord[]): Finding | null {\n\tif (mxRecords.length !== 1) {\n\t\treturn null;\n\t}\n\n\treturn createFinding('mx', 'Single MX record', 'low', 'Only one MX record found. Consider adding a backup MX for redundancy.');\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * MX record check.\n * Validates presence and quality of MX records for a domain.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { CheckResult, DNSQueryFunction, Finding } from '../types';\nimport { buildCheckResult, createFinding } from '../check-utils';\nimport { getIpTargetFindings, getNullMxFinding, getPresenceFinding, getSingleMxFinding, isNullMxRecord, parseMxRecords } from './mx-analysis';\n\n/**\n * Check MX record configuration for a domain.\n * Validates MX records exist, checks for null MX, IP targets, dangling records,\n * and single MX (no redundancy).\n *\n * Note: Provider detection from the original check is omitted here as it depends\n * on external provider signature files. Consumers can implement provider detection\n * as a post-processing step.\n */\nexport async function checkMX(\n\tdomain: string,\n\tqueryDNS: DNSQueryFunction,\n\toptions?: { timeout?: number },\n): Promise<CheckResult> {\n\tconst timeout = options?.timeout ?? 5000;\n\tlet answers: string[];\n\ttry {\n\t\tanswers = await queryDNS(domain, 'MX', { timeout });\n\t} catch {\n\t\treturn buildCheckResult('mx', [createFinding('mx', 'DNS query failed', 'medium', 'MX record lookup failed')]);\n\t}\n\n\tif (!answers || answers.length === 0) {\n\t\tconst findings: Finding[] = [\n\t\t\tcreateFinding(\n\t\t\t\t'mx',\n\t\t\t\t'No MX records found',\n\t\t\t\t'medium',\n\t\t\t\t'No mail exchange records present. If this domain does not handle email, consider publishing a null MX record (RFC 7505).',\n\t\t\t\t{ missingControl: true },\n\t\t\t),\n\t\t];\n\t\t// Non-mail domains should publish v=spf1 -all to explicitly reject all mail\n\t\ttry {\n\t\t\tconst txtRecords = await queryDNS(domain, 'TXT', { timeout });\n\t\t\tconst spfRecords = txtRecords.filter((r) => r.toLowerCase().startsWith('v=spf1'));\n\t\t\tif (spfRecords.length === 0) {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'mx',\n\t\t\t\t\t\t'Missing SPF reject-all for non-mail domain',\n\t\t\t\t\t\t'medium',\n\t\t\t\t\t\t`No SPF record found. Non-mail domains should publish \"v=spf1 -all\" to explicitly prevent email spoofing.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconst spf = spfRecords[0].toLowerCase();\n\t\t\t\tif (!spf.includes('-all')) {\n\t\t\t\t\tfindings.push(\n\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t'mx',\n\t\t\t\t\t\t\t'SPF not set to reject-all for non-mail domain',\n\t\t\t\t\t\t\t'low',\n\t\t\t\t\t\t\t`SPF record found but does not use \"-all\" (hard fail). Non-mail domains should publish \"v=spf1 -all\" to explicitly reject all email.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// DNS query failed — skip SPF check for non-mail domain\n\t\t}\n\t\treturn buildCheckResult('mx', findings);\n\t}\n\n\tconst findings: Finding[] = [];\n\n\tconst mxRecords = parseMxRecords(answers);\n\n\t// Check for null MX (RFC 7505: priority 0, exchange \".\")\n\tconst nullMx = mxRecords.find(isNullMxRecord);\n\tif (nullMx) {\n\t\tfindings.push(getNullMxFinding());\n\t\treturn buildCheckResult('mx', findings);\n\t}\n\n\tfindings.push(getPresenceFinding(mxRecords));\n\n\tfindings.push(...getIpTargetFindings(mxRecords));\n\n\t// Check for dangling MX records (hostnames that don't resolve)\n\tconst ipPattern = /^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/;\n\tconst hostnameRecords = mxRecords.filter((r) => !ipPattern.test(r.exchange));\n\tconst resolutions = await Promise.all(\n\t\thostnameRecords.map(async (r) => {\n\t\t\ttry {\n\t\t\t\tconst [a, aaaa] = await Promise.all([\n\t\t\t\t\tqueryDNS(r.exchange, 'A', { timeout }).catch(() => []),\n\t\t\t\t\tqueryDNS(r.exchange, 'AAAA', { timeout }).catch(() => []),\n\t\t\t\t]);\n\t\t\t\treturn { record: r, resolved: a.length > 0 || aaaa.length > 0 };\n\t\t\t} catch {\n\t\t\t\treturn { record: r, resolved: false };\n\t\t\t}\n\t\t}),\n\t);\n\tfor (const { record, resolved } of resolutions) {\n\t\tif (!resolved) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mx',\n\t\t\t\t\t'Dangling MX record',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`MX target \"${record.exchange}\" does not resolve to any A or AAAA record. Mail delivery to this host will fail.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Check for single MX (no redundancy)\n\tconst singleMxFinding = getSingleMxFinding(mxRecords);\n\tif (singleMxFinding) {\n\t\tfindings.push(singleMxFinding);\n\t}\n\n\treturn buildCheckResult('mx', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * CAA record analysis helpers.\n * Pure functions for summarizing and validating CAA records.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { Finding } from '../types';\nimport { createFinding } from '../check-utils';\n\n/** Parsed CAA record with flags, tag, and value */\nexport interface CaaRecord {\n\tflags: number;\n\ttag: string;\n\tvalue: string;\n}\n\n/**\n * Parse a single CAA record data string.\n * Handles both human-readable format (e.g. `0 issue \"letsencrypt.org\"`)\n * and Cloudflare DoH hex wire format (e.g. `\\# 19 00 05 69 73 73 75 65...`).\n */\nexport function parseCaaRecord(data: string): CaaRecord | null {\n\tif (data.startsWith('\\\\#') || data.startsWith('#')) {\n\t\tconst parts = data.trim().split(/\\s+/);\n\t\tconst hexStart = parts[0] === '\\\\#' || parts[0] === '#' ? 2 : 1;\n\t\tconst hexBytes = parts.slice(hexStart);\n\t\tif (hexBytes.length < 3) return null;\n\n\t\tconst flags = parseInt(hexBytes[0], 16);\n\t\tconst tagLen = parseInt(hexBytes[1], 16);\n\t\tif (isNaN(flags) || isNaN(tagLen) || hexBytes.length < 2 + tagLen) return null;\n\n\t\tconst tag = hexBytes\n\t\t\t.slice(2, 2 + tagLen)\n\t\t\t.map((hexByte) => String.fromCharCode(parseInt(hexByte, 16)))\n\t\t\t.join('');\n\t\tconst value = hexBytes\n\t\t\t.slice(2 + tagLen)\n\t\t\t.map((hexByte) => String.fromCharCode(parseInt(hexByte, 16)))\n\t\t\t.join('');\n\n\t\treturn { flags, tag: tag.toLowerCase(), value };\n\t}\n\n\tconst match = data.match(/^(\\d+)\\s+(\\S+)\\s+\"?([^\"]*)\"?\\s*$/);\n\tif (match) {\n\t\treturn {\n\t\t\tflags: parseInt(match[1], 10),\n\t\t\ttag: match[2].toLowerCase(),\n\t\t\tvalue: match[3],\n\t\t};\n\t}\n\n\treturn null;\n}\n\nexport function summarizeCaaTags(caaRecords: CaaRecord[]): {\n\thasIssue: boolean;\n\thasIssuewild: boolean;\n\thasIodef: boolean;\n} {\n\tlet hasIssue = false;\n\tlet hasIssuewild = false;\n\tlet hasIodef = false;\n\n\tfor (const record of caaRecords) {\n\t\tif (record.tag === 'issue') {\n\t\t\thasIssue = true;\n\t\t}\n\t\tif (record.tag === 'issuewild') {\n\t\t\thasIssuewild = true;\n\t\t}\n\t\tif (record.tag === 'iodef') {\n\t\t\thasIodef = true;\n\t\t}\n\t}\n\n\treturn { hasIssue, hasIssuewild, hasIodef };\n}\n\nexport function getCaaValidationFindings(tagSummary: { hasIssue: boolean; hasIssuewild: boolean; hasIodef: boolean }): Finding[] {\n\tconst findings: Finding[] = [];\n\n\tif (!tagSummary.hasIssue) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'caa',\n\t\t\t\t'No CAA issue tag',\n\t\t\t\t'medium',\n\t\t\t\t'CAA records exist but no \"issue\" tag found. The \"issue\" tag specifies which CAs are authorized to issue certificates.',\n\t\t\t),\n\t\t);\n\t}\n\n\tif (!tagSummary.hasIssuewild) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'caa',\n\t\t\t\t'No CAA issuewild tag',\n\t\t\t\t'low',\n\t\t\t\t'No \"issuewild\" CAA tag found. Consider adding one to control wildcard certificate issuance separately.',\n\t\t\t),\n\t\t);\n\t}\n\n\tif (!tagSummary.hasIodef) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'caa',\n\t\t\t\t'No CAA iodef tag',\n\t\t\t\t'low',\n\t\t\t\t'No \"iodef\" CAA tag found. The iodef tag specifies where CAs should report policy violations.',\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n\nexport function getCaaConfiguredFinding(): Finding {\n\treturn createFinding('caa', 'CAA properly configured', 'info', 'CAA records found with issue, issuewild, and iodef tags configured.');\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * CAA (Certificate Authority Authorization) check.\n * Validates CAA DNS records that restrict which CAs can issue certificates.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { CheckResult, DNSQueryFunction, Finding } from '../types';\nimport { buildCheckResult, createFinding } from '../check-utils';\nimport { type CaaRecord, parseCaaRecord, getCaaConfiguredFinding, getCaaValidationFindings, summarizeCaaTags } from './caa-analysis';\n\n/**\n * Check CAA records for a domain.\n * Validates that CAA records exist and are properly configured.\n *\n * Queries CAA record type and parses the raw DNS data into structured records.\n */\nexport async function checkCAA(\n\tdomain: string,\n\tqueryDNS: DNSQueryFunction,\n\toptions?: { timeout?: number },\n): Promise<CheckResult> {\n\tconst timeout = options?.timeout ?? 5000;\n\tconst findings: Finding[] = [];\n\n\tlet rawRecords: string[];\n\ttry {\n\t\trawRecords = await queryDNS(domain, 'CAA', { timeout });\n\t} catch {\n\t\tfindings.push(createFinding('caa', 'CAA query failed', 'medium', `Could not query CAA records for ${domain}.`));\n\t\treturn buildCheckResult('caa', findings);\n\t}\n\n\t// Parse raw CAA record data into structured records\n\tconst caaRecords: CaaRecord[] = rawRecords\n\t\t.map(parseCaaRecord)\n\t\t.filter((record): record is CaaRecord => record !== null);\n\n\tif (caaRecords.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'caa',\n\t\t\t\t'No CAA records',\n\t\t\t\t'medium',\n\t\t\t\t`No CAA records found for ${domain}. CAA records restrict which Certificate Authorities can issue certificates for your domain, preventing unauthorized issuance.`,\n\t\t\t\t{ missingControl: true },\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('caa', findings);\n\t}\n\n\tfindings.push(...getCaaValidationFindings(summarizeCaaTags(caaRecords)));\n\n\t// If no issues found\n\tif (findings.length === 0) {\n\t\tfindings.push(getCaaConfiguredFinding());\n\t}\n\n\treturn buildCheckResult('caa', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * BIMI (Brand Indicators for Message Identification) check.\n * Queries TXT records at default._bimi.<domain> and validates\n * logo URL and authority evidence configuration.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { CheckResult, DNSQueryFunction, Finding } from '../types';\nimport { buildCheckResult, createFinding } from '../check-utils';\n\n/**\n * Check BIMI records for a domain.\n * Validates the presence and configuration of BIMI TXT records,\n * including logo URL format and VMC authority evidence.\n */\nexport async function checkBIMI(\n\tdomain: string,\n\tqueryDNS: DNSQueryFunction,\n\toptions?: { timeout?: number },\n): Promise<CheckResult> {\n\tconst timeout = options?.timeout ?? 5000;\n\tconst findings: Finding[] = [];\n\tconst bimiDomain = `default._bimi.${domain}`;\n\tconst txtRecords = await queryDNS(bimiDomain, 'TXT', { timeout });\n\n\tconst bimiRecords = txtRecords.filter((r) => r.toLowerCase().startsWith('v=bimi1'));\n\n\t// Check DMARC enforcement status — BIMI requires p=quarantine or p=reject\n\tconst dmarcRecords = await queryDNS(`_dmarc.${domain}`, 'TXT', { timeout });\n\tconst dmarcRecord = dmarcRecords.find((r) => r.toLowerCase().startsWith('v=dmarc1'));\n\tconst isEnforcing =\n\t\tdmarcRecord && (/\\bp=reject\\b/i.test(dmarcRecord) || /\\bp=quarantine\\b/i.test(dmarcRecord));\n\n\tif (bimiRecords.length === 0) {\n\t\tif (!isEnforcing) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'bimi',\n\t\t\t\t\t'No BIMI record (DMARC not enforcing)',\n\t\t\t\t\t'low',\n\t\t\t\t\t`No BIMI record found at ${bimiDomain}. BIMI requires DMARC enforcement (p=quarantine or p=reject) before a BIMI record can be validated by mail clients. Set up DMARC enforcement first.`,\n\t\t\t\t\t{ missingControl: true },\n\t\t\t\t),\n\t\t\t);\n\t\t} else {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'bimi',\n\t\t\t\t\t'No BIMI record found',\n\t\t\t\t\t'low',\n\t\t\t\t\t`No BIMI record found at ${bimiDomain}. This domain has DMARC enforcement and is eligible for BIMI. Publishing a BIMI record allows email clients like Gmail and Apple Mail to display your brand logo next to your emails.`,\n\t\t\t\t\t{ missingControl: true },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\treturn buildCheckResult('bimi', findings);\n\t}\n\n\t// BIMI record exists but DMARC is not enforcing — record is non-functional\n\tif (!isEnforcing) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'bimi',\n\t\t\t\t'BIMI record ineffective (DMARC not enforcing)',\n\t\t\t\t'medium',\n\t\t\t\t`BIMI record found at ${bimiDomain} but DMARC policy is not set to quarantine or reject. Mail clients will not display the BIMI logo until DMARC enforcement is enabled.`,\n\t\t\t\t{ missingControl: true },\n\t\t\t),\n\t\t);\n\t}\n\n\tif (bimiRecords.length > 1) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'bimi',\n\t\t\t\t'Multiple BIMI records',\n\t\t\t\t'medium',\n\t\t\t\t`Found ${bimiRecords.length} BIMI records at ${bimiDomain}. There should be exactly one BIMI record.`,\n\t\t\t),\n\t\t);\n\t}\n\n\tconst bimi = bimiRecords[0];\n\n\t// Extract l= tag (logo URL)\n\tconst logoMatch = bimi.match(/\\bl=([^\\s;]+)/i);\n\tconst logoUrl = logoMatch?.[1];\n\n\tif (!logoUrl) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'bimi',\n\t\t\t\t'BIMI record missing logo URL',\n\t\t\t\t'medium',\n\t\t\t\t`BIMI record at ${bimiDomain} does not contain a logo URL (l= tag). The logo URL is required for email clients to display your brand indicator.`,\n\t\t\t),\n\t\t);\n\t} else {\n\t\t// Validate logo URL format\n\t\tconst isHttps = logoUrl.toLowerCase().startsWith('https://');\n\t\tconst isSvg = logoUrl.toLowerCase().endsWith('.svg');\n\n\t\tif (!isHttps || !isSvg) {\n\t\t\tconst issues: string[] = [];\n\t\t\tif (!isHttps) issues.push('must use HTTPS');\n\t\t\tif (!isSvg) issues.push('must be an SVG file (SVG Tiny PS format)');\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'bimi',\n\t\t\t\t\t'BIMI logo URL invalid format',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`BIMI logo URL \"${logoUrl}\" is invalid: ${issues.join(' and ')}. BIMI requires an HTTPS URL pointing to an SVG Tiny PS image.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Extract a= tag (VMC/authority evidence URL)\n\tconst authMatch = bimi.match(/\\ba=([^\\s;]+)/i);\n\tconst authUrl = authMatch?.[1];\n\n\tif (!authUrl) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'bimi',\n\t\t\t\t'No BIMI authority evidence (VMC)',\n\t\t\t\t'info',\n\t\t\t\t`BIMI record at ${bimiDomain} does not include an authority evidence URL (a= tag). A Verified Mark Certificate (VMC) is optional but required by Gmail to display your logo. Consider obtaining a VMC from a certificate authority like DigiCert or Entrust.`,\n\t\t\t),\n\t\t);\n\t} else {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'bimi',\n\t\t\t\t'BIMI authority evidence present',\n\t\t\t\t'info',\n\t\t\t\t`BIMI record includes a Verified Mark Certificate (VMC) reference: ${authUrl}`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// If logo URL is valid and present, add a positive finding\n\tif (logoUrl && logoUrl.toLowerCase().startsWith('https://') && logoUrl.toLowerCase().endsWith('.svg')) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'bimi',\n\t\t\t\t'BIMI record configured',\n\t\t\t\t'info',\n\t\t\t\t`BIMI record found and configured at ${bimiDomain} with a valid HTTPS SVG logo reference.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('bimi', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * NS record analysis helpers.\n * Pure functions for analyzing nameserver configuration.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { Finding } from '../types';\nimport { createFinding } from '../check-utils';\n\nconst RESILIENT_NS_PROVIDERS: Record<string, string> = {\n\t'cloudflare.com':\n\t\t\"Cloudflare's anycast network provides built-in geographic redundancy, so this is lower risk than single-provider setups on traditional DNS hosts.\",\n\t'awsdns.com': \"AWS Route 53's anycast network provides built-in geographic redundancy, so this is lower risk than single-provider setups on traditional DNS hosts.\",\n\t'google.com':\n\t\t'Google Cloud DNS uses globally distributed authoritative infrastructure, so this is lower risk than single-provider setups on traditional DNS hosts.',\n};\n\nexport type ParsedSoaValues = {\n\trefresh: number | null;\n\tretry: number | null;\n\texpire: number | null;\n\tminimum: number | null;\n};\n\nexport function normalizeNsRecords(nsRecords: string[]): string[] {\n\treturn nsRecords.map((record) => record.replace(/\\.$/, '').toLowerCase());\n}\n\nexport function getNsVisibilityFinding(domain: string, domainResolves: boolean): Finding {\n\tif (domainResolves) {\n\t\treturn createFinding(\n\t\t\t'ns',\n\t\t\t'NS records not directly visible',\n\t\t\t'low',\n\t\t\t`No NS records returned for ${domain} directly, but the domain resolves. NS records may be managed at a parent zone.`,\n\t\t);\n\t}\n\n\treturn createFinding(\n\t\t'ns',\n\t\t'No NS records found',\n\t\t'critical',\n\t\t`No nameserver records found for ${domain}. Without NS records, the domain cannot resolve.`,\n\t\t{ missingControl: true },\n\t);\n}\n\nexport function getSingleNsFinding(nsRecords: string[]): Finding | null {\n\tif (nsRecords.length !== 1) {\n\t\treturn null;\n\t}\n\n\treturn createFinding(\n\t\t'ns',\n\t\t'Single nameserver (violates RFC 1035 §2.2)',\n\t\t'high',\n\t\t`Only one nameserver found (${nsRecords[0]}). RFC 1035 §2.2 mandates at least two nameservers for every zone to ensure redundancy and availability.`,\n\t);\n}\n\nexport function getNameserverDiversityFinding(nsRecords: string[]): Finding | null {\n\tconst providerDomains = new Set(\n\t\tnsRecords.map((record) => {\n\t\t\tconst parts = record.split('.');\n\t\t\treturn parts.slice(-2).join('.');\n\t\t}),\n\t);\n\n\tif (providerDomains.size !== 1 || nsRecords.length <= 1) {\n\t\treturn null;\n\t}\n\n\tconst providerDomain = [...providerDomains][0];\n\tconst providerContext =\n\t\tRESILIENT_NS_PROVIDERS[providerDomain] ?? 'Consider using nameservers from different providers for better resilience.';\n\n\treturn createFinding(\n\t\t'ns',\n\t\t'Low nameserver diversity',\n\t\t'low',\n\t\t`All nameservers are under ${providerDomain}. ${providerContext} For maximum independence, a secondary DNS provider can be added.`,\n\t);\n}\n\nexport function parseSoaValues(soaData: string): ParsedSoaValues | null {\n\tconst soaParts = soaData.trim().split(/\\s+/);\n\tif (soaParts.length < 7) {\n\t\treturn null;\n\t}\n\n\tconst refresh = parseInt(soaParts[3], 10);\n\tconst retry = parseInt(soaParts[4], 10);\n\tconst expire = parseInt(soaParts[5], 10);\n\tconst minimum = parseInt(soaParts[6], 10);\n\n\treturn {\n\t\trefresh: Number.isNaN(refresh) ? null : refresh,\n\t\tretry: Number.isNaN(retry) ? null : retry,\n\t\texpire: Number.isNaN(expire) ? null : expire,\n\t\tminimum: Number.isNaN(minimum) ? null : minimum,\n\t};\n}\n\nexport function getSoaValidationFindings(soaValues: ParsedSoaValues): Finding[] {\n\tconst findings: Finding[] = [];\n\n\tif (soaValues.refresh !== null) {\n\t\tif (soaValues.refresh < 300) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'ns',\n\t\t\t\t\t'SOA refresh interval too short',\n\t\t\t\t\t'low',\n\t\t\t\t\t`SOA refresh interval is ${soaValues.refresh}s (< 300s / 5 min). Very short refresh intervals increase DNS traffic and load on nameservers.`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (soaValues.refresh > 86400) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'ns',\n\t\t\t\t\t'SOA refresh interval too long',\n\t\t\t\t\t'low',\n\t\t\t\t\t`SOA refresh interval is ${soaValues.refresh}s (> 86400s / 1 day). Long refresh intervals delay propagation of zone changes to secondary nameservers.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\tif (soaValues.retry !== null && soaValues.refresh !== null && soaValues.retry > soaValues.refresh) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'ns',\n\t\t\t\t'SOA retry exceeds refresh interval',\n\t\t\t\t'low',\n\t\t\t\t`SOA retry interval (${soaValues.retry}s) exceeds refresh interval (${soaValues.refresh}s). Retry should be shorter than refresh to allow timely recovery after failed zone transfers.`,\n\t\t\t),\n\t\t);\n\t}\n\n\tif (soaValues.expire !== null && soaValues.expire < 604800) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'ns',\n\t\t\t\t'SOA expire too short',\n\t\t\t\t'medium',\n\t\t\t\t`SOA expire value is ${soaValues.expire}s (< 604800s / 1 week). If secondary nameservers cannot reach the primary for this duration, they will stop serving the zone.`,\n\t\t\t),\n\t\t);\n\t}\n\n\tif (soaValues.minimum !== null && soaValues.minimum > 86400) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'ns',\n\t\t\t\t'SOA negative cache TTL too long',\n\t\t\t\t'low',\n\t\t\t\t`SOA minimum (negative cache TTL) is ${soaValues.minimum}s (> 86400s / 1 day). This means NXDOMAIN responses will be cached for extended periods, delaying visibility of new records.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n\nexport function getNsConfiguredFinding(nsRecords: string[]): Finding {\n\treturn createFinding('ns', 'Nameservers properly configured', 'info', `${nsRecords.length} nameservers found: ${nsRecords.join(', ')}`);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * NS (Name Server) check.\n * Validates nameserver configuration for a domain.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { CheckResult, DNSQueryFunction, Finding, RawDNSQueryFunction } from '../types';\nimport { buildCheckResult, createFinding } from '../check-utils';\nimport {\n\tgetNameserverDiversityFinding,\n\tgetNsConfiguredFinding,\n\tgetNsVisibilityFinding,\n\tgetSingleNsFinding,\n\tgetSoaValidationFindings,\n\tnormalizeNsRecords,\n\tparseSoaValues,\n} from './ns-analysis';\n\n/**\n * Check nameserver configuration for a domain.\n * Validates NS records exist, checks for diversity, and verifies SOA configuration.\n *\n * Requires rawQueryDNS for SOA record parsing (needs answer type filtering)\n * and for domain resolution check (A record check for delegation-only zones).\n */\nexport async function checkNS(\n\tdomain: string,\n\tqueryDNS: DNSQueryFunction,\n\toptions?: { timeout?: number; rawQueryDNS?: RawDNSQueryFunction },\n): Promise<CheckResult> {\n\tconst timeout = options?.timeout ?? 5000;\n\tconst rawQueryDNS = options?.rawQueryDNS;\n\tconst findings: Finding[] = [];\n\n\tlet nsRecords: string[] = [];\n\ttry {\n\t\tnsRecords = normalizeNsRecords(await queryDNS(domain, 'NS', { timeout }));\n\t} catch {\n\t\tfindings.push(createFinding('ns', 'NS query failed', 'critical', `Could not query nameserver records for ${domain}.`));\n\t\treturn buildCheckResult('ns', findings);\n\t}\n\n\tif (nsRecords.length === 0) {\n\t\t// Check if domain still resolves (e.g. delegation-only zones like govt.nz)\n\t\tlet domainResolves = false;\n\t\tif (rawQueryDNS) {\n\t\t\ttry {\n\t\t\t\tconst aResp = await rawQueryDNS(domain, 'A', false, { timeout });\n\t\t\t\tdomainResolves = (aResp.Answer ?? []).length > 0;\n\t\t\t} catch {\n\t\t\t\t/* ignore */\n\t\t\t}\n\t\t} else {\n\t\t\t// Fallback: try resolving A records via queryDNS\n\t\t\ttry {\n\t\t\t\tconst aRecords = await queryDNS(domain, 'A', { timeout });\n\t\t\t\tdomainResolves = aRecords.length > 0;\n\t\t\t} catch {\n\t\t\t\t/* ignore */\n\t\t\t}\n\t\t}\n\n\t\tfindings.push(getNsVisibilityFinding(domain, domainResolves));\n\t\treturn buildCheckResult('ns', findings);\n\t}\n\n\t// Check for single nameserver (no redundancy) — RFC 1035 §2.2 mandates at least two\n\tconst singleNsFinding = getSingleNsFinding(nsRecords);\n\tif (singleNsFinding) {\n\t\tfindings.push(singleNsFinding);\n\t}\n\n\tconst diversityFinding = getNameserverDiversityFinding(nsRecords);\n\tif (diversityFinding) {\n\t\tfindings.push(diversityFinding);\n\t}\n\n\t// Check SOA record exists and validate parameters\n\tif (rawQueryDNS) {\n\t\ttry {\n\t\t\tconst soaResp = await rawQueryDNS(domain, 'SOA', false, { timeout });\n\t\t\tconst soaRecords = (soaResp.Answer ?? []).filter((a) => a.type === 6);\n\t\t\tif (soaRecords.length === 0) {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'ns',\n\t\t\t\t\t\t'No SOA record',\n\t\t\t\t\t\t'medium',\n\t\t\t\t\t\t`No SOA (Start of Authority) record found for ${domain}. SOA records are required for proper DNS zone configuration.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconst soaValues = parseSoaValues(soaRecords[0].data);\n\t\t\t\tif (soaValues) {\n\t\t\t\t\tfindings.push(...getSoaValidationFindings(soaValues));\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Non-critical\n\t\t}\n\t}\n\n\t// Wildcard DNS detection — probe a random subdomain\n\ttry {\n\t\tconst probeId = Math.random().toString(36).substring(2, 10);\n\t\tconst probeFqdn = `_bv-probe-${probeId}.${domain}`;\n\t\tconst probeRecords = await queryDNS(probeFqdn, 'A', { timeout });\n\t\tif (probeRecords.length > 0) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'ns',\n\t\t\t\t\t'Wildcard DNS detected',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`Domain responds to arbitrary subdomains, indicating a wildcard DNS record (*.${domain}). Wildcard records can mask dangling CNAMEs, complicate subdomain enumeration defences, and make subdomain takeover detection unreliable.`,\n\t\t\t\t\t{ wildcardDetected: true, probeSubdomain: probeFqdn },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t} catch {\n\t\t// Non-critical — wildcard detection failure should not affect NS check\n\t}\n\n\t// If no issues found\n\tif (findings.length === 0) {\n\t\tfindings.push(getNsConfiguredFinding(nsRecords));\n\t}\n\n\treturn buildCheckResult('ns', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * TLS-RPT (SMTP TLS Reporting) check.\n * Queries TXT records at _smtp._tls.<domain> and validates\n * reporting configuration per RFC 8460.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { CheckResult, DNSQueryFunction, Finding } from '../types';\nimport { buildCheckResult, createFinding } from '../check-utils';\n\n/**\n * Check TLS-RPT records for a domain.\n * Validates the presence and configuration of SMTP TLS Reporting records.\n */\nexport async function checkTLSRPT(\n\tdomain: string,\n\tqueryDNS: DNSQueryFunction,\n\toptions?: { timeout?: number },\n): Promise<CheckResult> {\n\tconst timeout = options?.timeout ?? 5000;\n\tconst findings: Finding[] = [];\n\tconst tlsrptDomain = `_smtp._tls.${domain}`;\n\tconst txtRecords = await queryDNS(tlsrptDomain, 'TXT', { timeout });\n\n\tconst tlsrptRecords = txtRecords.filter((r) => r.toLowerCase().startsWith('v=tlsrptv1'));\n\n\tif (tlsrptRecords.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'tlsrpt',\n\t\t\t\t'No TLS-RPT record found',\n\t\t\t\t'low',\n\t\t\t\t`No TLS-RPT (v=TLSRPTv1) record found at ${tlsrptDomain}. TLS-RPT enables your domain to receive reports about SMTP TLS failures, complementing MTA-STS. Without it, you have no visibility into email delivery security issues.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('tlsrpt', findings);\n\t}\n\n\tif (tlsrptRecords.length > 1) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'tlsrpt',\n\t\t\t\t'Multiple TLS-RPT records',\n\t\t\t\t'medium',\n\t\t\t\t`Found ${tlsrptRecords.length} TLS-RPT records at ${tlsrptDomain}. There should be exactly one TLS-RPT record per domain.`,\n\t\t\t),\n\t\t);\n\t}\n\n\tconst record = tlsrptRecords[0];\n\n\t// Check for rua= tag\n\tconst ruaMatch = record.match(/\\brua=([^\\s;]+)/i);\n\tif (!ruaMatch) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'tlsrpt',\n\t\t\t\t'TLS-RPT record missing reporting URI',\n\t\t\t\t'medium',\n\t\t\t\t`TLS-RPT record at ${tlsrptDomain} does not contain a reporting URI (rua= tag). Without a reporting destination, TLS failure reports cannot be delivered.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('tlsrpt', findings);\n\t}\n\n\tconst ruaValue = ruaMatch[1];\n\t// Split comma-separated URIs and validate each\n\tconst uris = ruaValue.split(',').map((u) => u.trim());\n\tconst invalidUris: string[] = [];\n\n\tfor (const uri of uris) {\n\t\tif (!uri.toLowerCase().startsWith('mailto:') && !uri.toLowerCase().startsWith('https://')) {\n\t\t\tinvalidUris.push(uri);\n\t\t}\n\t}\n\n\tif (invalidUris.length > 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'tlsrpt',\n\t\t\t\t'TLS-RPT invalid reporting URI scheme',\n\t\t\t\t'medium',\n\t\t\t\t`TLS-RPT reporting URI(s) use invalid scheme: ${invalidUris.join(', ')}. Only mailto: and https:// schemes are supported per RFC 8460.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// If record is valid\n\tif (invalidUris.length === 0 && tlsrptRecords.length <= 1) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'tlsrpt',\n\t\t\t\t'TLS-RPT record configured',\n\t\t\t\t'info',\n\t\t\t\t`TLS-RPT record found and configured at ${tlsrptDomain}: ${record.substring(0, 120)}${record.length > 120 ? '...' : ''}`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('tlsrpt', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DANE (DNS-Based Authentication of Named Entities) analysis helpers.\n * Pure functions for analyzing TLSA records and classifying DANE presence.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { Finding } from '../types';\nimport { createFinding } from '../check-utils';\n\n/** Parsed TLSA record with usage, selector, matching type, and certificate data */\nexport interface TlsaRecord {\n\tusage: number;\n\tselector: number;\n\tmatchingType: number;\n\tcertData: string;\n}\n\n/**\n * Parse a TLSA record data string into structured fields.\n * Handles both human-readable format (`usage selector matchingType certData`)\n * and hex wire format (data starting with `\\#`).\n */\nexport function parseTlsaRecord(data: string): TlsaRecord | null {\n\tif (data.startsWith('\\\\#') || data.startsWith('#')) {\n\t\tconst parts = data.trim().split(/\\s+/);\n\t\tconst hexStart = parts[0] === '\\\\#' || parts[0] === '#' ? 2 : 1;\n\t\tconst hexBytes = parts.slice(hexStart);\n\t\tif (hexBytes.length < 4) return null;\n\n\t\tconst usage = parseInt(hexBytes[0], 16);\n\t\tconst selector = parseInt(hexBytes[1], 16);\n\t\tconst matchingType = parseInt(hexBytes[2], 16);\n\t\tif (isNaN(usage) || isNaN(selector) || isNaN(matchingType)) return null;\n\n\t\tconst certData = hexBytes.slice(3).join('');\n\t\treturn { usage, selector, matchingType, certData };\n\t}\n\n\tconst parts = data.trim().split(/\\s+/);\n\tif (parts.length < 4) return null;\n\n\tconst usage = parseInt(parts[0], 10);\n\tconst selector = parseInt(parts[1], 10);\n\tconst matchingType = parseInt(parts[2], 10);\n\tif (isNaN(usage) || isNaN(selector) || isNaN(matchingType)) return null;\n\n\tconst certData = parts.slice(3).join('');\n\treturn { usage, selector, matchingType, certData };\n}\n\n/** TLSA usage field labels for human-readable output. */\nconst USAGE_LABELS: Record<number, string> = {\n\t0: 'PKIX-TA (CA constraint)',\n\t1: 'PKIX-EE (service certificate constraint)',\n\t2: 'DANE-TA (trust anchor assertion)',\n\t3: 'DANE-EE (domain-issued certificate)',\n};\n\n/**\n * Analyze a set of TLSA records for a given DNS name.\n * Validates field ranges, checks DNSSEC dependency, and flags weak matching types.\n */\nexport function analyzeTlsaRecords(records: string[], name: string, hasDnssec: boolean): Finding[] {\n\tconst findings: Finding[] = [];\n\tconst seenDaneWithoutDnssec = new Set<string>();\n\tlet validRecordCount = 0;\n\n\tfor (const record of records) {\n\t\tconst parsed = parseTlsaRecord(record);\n\t\tif (!parsed) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dane',\n\t\t\t\t\t'Malformed TLSA record',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`Could not parse TLSA record for ${name}: ${record}`,\n\t\t\t\t),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Validate usage field (0-3)\n\t\tif (parsed.usage < 0 || parsed.usage > 3) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dane',\n\t\t\t\t\t'Invalid TLSA usage',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`TLSA record for ${name} has invalid usage value ${parsed.usage}. Valid range is 0-3.`,\n\t\t\t\t\t{ usage: parsed.usage },\n\t\t\t\t),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Validate selector field (0-1)\n\t\tif (parsed.selector < 0 || parsed.selector > 1) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dane',\n\t\t\t\t\t'Invalid TLSA selector',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`TLSA record for ${name} has invalid selector value ${parsed.selector}. Valid range is 0-1.`,\n\t\t\t\t\t{ selector: parsed.selector },\n\t\t\t\t),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Validate matching type field (0-2)\n\t\tif (parsed.matchingType < 0 || parsed.matchingType > 2) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dane',\n\t\t\t\t\t'Invalid TLSA matching type',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`TLSA record for ${name} has invalid matching type ${parsed.matchingType}. Valid range is 0-2.`,\n\t\t\t\t\t{ matchingType: parsed.matchingType },\n\t\t\t\t),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// DANE-EE (3) and DANE-TA (2) require DNSSEC for security — deduplicate per host\n\t\tif ((parsed.usage === 2 || parsed.usage === 3) && !hasDnssec && !seenDaneWithoutDnssec.has(name)) {\n\t\t\tseenDaneWithoutDnssec.add(name);\n\t\t\tconst usageLabel = USAGE_LABELS[parsed.usage] ?? `usage ${parsed.usage}`;\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dane',\n\t\t\t\t\t'DANE without DNSSEC',\n\t\t\t\t\t'high',\n\t\t\t\t\t`TLSA record for ${name} uses ${usageLabel} but DNSSEC is not validated. Without DNSSEC, DANE records can be spoofed, negating their security benefit.`,\n\t\t\t\t\t{ usage: parsed.usage, name },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\t// Matching type 0 = full certificate data (less secure than hash)\n\t\tif (parsed.matchingType === 0) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dane',\n\t\t\t\t\t'TLSA uses full certificate matching',\n\t\t\t\t\t'low',\n\t\t\t\t\t`TLSA record for ${name} uses matching type 0 (full certificate). SHA-256 (type 1) or SHA-512 (type 2) matching is recommended for better security and smaller records.`,\n\t\t\t\t\t{ matchingType: parsed.matchingType, name },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\t// Count valid DANE records for consolidated info finding\n\t\tvalidRecordCount++;\n\t}\n\n\t// Emit a single consolidated info finding for all valid TLSA records\n\tif (validRecordCount > 0) {\n\t\tconst detail =\n\t\t\tvalidRecordCount === 1\n\t\t\t\t? `Valid TLSA record configured for ${name}.`\n\t\t\t\t: `${validRecordCount} DANE TLSA records configured for ${name}.`;\n\t\tfindings.push(\n\t\t\tcreateFinding('dane', `DANE TLSA configured for ${name}`, 'info', detail, { name, validRecordCount }),\n\t\t);\n\t}\n\n\treturn findings;\n}\n\n/**\n * Generate findings when no TLSA records are found for MX and/or HTTPS endpoints.\n */\nexport function classifyDanePresence(hasMxTlsa: boolean, hasHttpsTlsa: boolean): Finding[] {\n\tconst findings: Finding[] = [];\n\n\tif (!hasMxTlsa) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dane',\n\t\t\t\t'No DANE TLSA for MX servers',\n\t\t\t\t'medium',\n\t\t\t\t'No TLSA records found for MX server SMTP ports (_25._tcp). DANE pins TLS certificates to DNS, preventing CA misissuance attacks on email delivery.',\n\t\t\t),\n\t\t);\n\t}\n\n\tif (!hasHttpsTlsa) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dane',\n\t\t\t\t'No DANE TLSA for HTTPS',\n\t\t\t\t'low',\n\t\t\t\t'No TLSA record found for HTTPS endpoint (_443._tcp). DANE can pin web server certificates to DNS, providing an additional layer of trust beyond the CA system.',\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DANE (DNS-Based Authentication of Named Entities) check — EMAIL ONLY.\n * Validates TLSA records for MX servers (_25._tcp.{mx-host}).\n * HTTPS DANE (_443._tcp) is handled by the dedicated check-dane-https.ts.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { CheckResult, DNSQueryFunction, Finding, RawDNSQueryFunction } from '../types';\nimport { buildCheckResult, createFinding } from '../check-utils';\nimport { analyzeTlsaRecords } from './dane-analysis';\n\n/**\n * Parse MX records from raw DNS response strings.\n */\nfunction parseMxFromRaw(answers: string[]): Array<{ exchange: string }> {\n\treturn answers.map((answer) => {\n\t\tconst parts = answer.split(' ');\n\t\tconst exchange = (parts.slice(1).join(' ') || '').replace(/\\.$/, '').toLowerCase();\n\t\treturn { exchange };\n\t});\n}\n\n/**\n * Check DANE TLSA records for a domain's MX servers (email DANE only).\n */\nexport async function checkDANE(\n\tdomain: string,\n\tqueryDNS: DNSQueryFunction,\n\toptions?: { timeout?: number; rawQueryDNS?: RawDNSQueryFunction },\n): Promise<CheckResult> {\n\tconst timeout = options?.timeout ?? 5000;\n\tconst rawQueryDNS = options?.rawQueryDNS;\n\tconst findings: Finding[] = [];\n\tlet hasDnssec = false;\n\tlet hasMxTlsa = false;\n\n\t// Step 1: Check DNSSEC status for the domain\n\tif (rawQueryDNS) {\n\t\ttry {\n\t\t\tconst resp = await rawQueryDNS(domain, 'A', true, { timeout });\n\t\t\thasDnssec = resp.AD === true;\n\t\t} catch {\n\t\t\t// DNSSEC check failed — continue without it\n\t\t}\n\t}\n\n\t// Step 2: Query MX records and check TLSA for each MX host\n\ttry {\n\t\tconst mxAnswers = await queryDNS(domain, 'MX', { timeout });\n\t\tconst mxRecords = parseMxFromRaw(mxAnswers);\n\n\t\tfor (const mx of mxRecords) {\n\t\t\tconst mxHost = mx.exchange;\n\t\t\tif (!mxHost || mxHost === '.') continue;\n\n\t\t\tconst tlsaName = `_25._tcp.${mxHost}`;\n\t\t\ttry {\n\t\t\t\tconst tlsaRecords = await queryDNS(tlsaName, 'TLSA', { timeout });\n\t\t\t\tif (tlsaRecords.length > 0) {\n\t\t\t\t\thasMxTlsa = true;\n\t\t\t\t\tfindings.push(...analyzeTlsaRecords(tlsaRecords, tlsaName, hasDnssec));\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Individual MX TLSA query failed — skip this host\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// MX query failed\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dane',\n\t\t\t\t'MX lookup failed for DANE check',\n\t\t\t\t'low',\n\t\t\t\t`Could not query MX records for ${domain} to check SMTP DANE.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Step 3: If no MX TLSA found, report absence\n\tif (!hasMxTlsa && findings.every((f) => f.severity !== 'medium' || !f.title.includes('Malformed'))) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dane',\n\t\t\t\t'No DANE TLSA for MX servers',\n\t\t\t\t'medium',\n\t\t\t\t'No TLSA records found for MX server SMTP ports (_25._tcp). DANE pins TLS certificates to DNS, preventing CA misissuance attacks on email delivery.',\n\t\t\t),\n\t\t);\n\t}\n\n\t// Step 5: Handle case where all DNS queries failed\n\tif (findings.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dane',\n\t\t\t\t'DANE check inconclusive',\n\t\t\t\t'medium',\n\t\t\t\t`DNS queries for DANE TLSA records failed for ${domain}. Unable to determine DANE status.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('dane', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DANE-HTTPS check.\n * Validates TLSA records specifically for the HTTPS endpoint (_443._tcp.{domain}).\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { CheckResult, DNSQueryFunction, Finding, RawDNSQueryFunction } from '../types';\nimport { buildCheckResult, createFinding } from '../check-utils';\nimport { analyzeTlsaRecords } from './dane-analysis';\n\n/**\n * Check DANE TLSA records for a domain's HTTPS endpoint (_443._tcp.{domain}).\n */\nexport async function checkDANEHTTPS(\n\tdomain: string,\n\tqueryDNS: DNSQueryFunction,\n\toptions?: { timeout?: number; rawQueryDNS?: RawDNSQueryFunction },\n): Promise<CheckResult> {\n\tconst timeout = options?.timeout ?? 5000;\n\tconst rawQueryDNS = options?.rawQueryDNS;\n\tconst findings: Finding[] = [];\n\tlet hasDnssec = false;\n\n\t// Step 1: Check DNSSEC status for the domain\n\tif (rawQueryDNS) {\n\t\ttry {\n\t\t\tconst resp = await rawQueryDNS(domain, 'A', true, { timeout });\n\t\t\thasDnssec = resp.AD === true;\n\t\t} catch {\n\t\t\t// DNSSEC check failed — continue without it\n\t\t}\n\t}\n\n\t// Step 2: Query TLSA records at _443._tcp.{domain}\n\tconst tlsaName = `_443._tcp.${domain}`;\n\tlet hasHttpsTlsa = false;\n\n\ttry {\n\t\tconst tlsaRecords = await queryDNS(tlsaName, 'TLSA', { timeout });\n\t\tif (tlsaRecords.length > 0) {\n\t\t\thasHttpsTlsa = true;\n\t\t\tfindings.push(...analyzeTlsaRecords(tlsaRecords, tlsaName, hasDnssec));\n\t\t}\n\t} catch {\n\t\t// TLSA query failed — report and continue\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dane_https',\n\t\t\t\t'DANE HTTPS query failed',\n\t\t\t\t'low',\n\t\t\t\t`DNS query for TLSA records at ${tlsaName} failed. Unable to determine DANE HTTPS status for ${domain}.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Step 3: If no TLSA records found, classify absence\n\tif (!hasHttpsTlsa && findings.every((f) => f.title !== 'DANE HTTPS query failed')) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dane_https',\n\t\t\t\t'No DANE TLSA for HTTPS',\n\t\t\t\t'low',\n\t\t\t\t`No TLSA record found at ${tlsaName}. DANE can pin web server certificates to DNS, providing an additional layer of trust beyond the CA system. Implement DANE-EE (usage 3) with DNSSEC enabled for maximum security.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Step 4: Handle case where all DNS queries failed and findings is empty\n\tif (findings.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dane_https',\n\t\t\t\t'DANE HTTPS check inconclusive',\n\t\t\t\t'medium',\n\t\t\t\t`DNS queries for DANE HTTPS TLSA records failed for ${domain}. Unable to determine DANE HTTPS status.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Remap any finding categories to 'dane_https' (analyzeTlsaRecords produces 'dane' category)\n\tconst remapped = findings.map((f) => ({ ...f, category: 'dane_https' as const }));\n\n\treturn buildCheckResult('dane_https', remapped);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * SVCB/HTTPS DNS record check (RFC 9460).\n * Queries HTTPS resource records at the apex domain and validates the\n * presence and content of modern transport capability advertisements.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { CheckResult, DNSQueryFunction, Finding } from '../types';\nimport { buildCheckResult, createFinding } from '../check-utils';\n\n/**\n * Parse ALPN protocols from an HTTPS record data string.\n */\nfunction parseAlpn(data: string): string[] {\n\tconst match = data.match(/\\balpn=(?:\"([^\"]+)\"|(\\S+))/i);\n\tif (!match) return [];\n\tconst raw = match[1] ?? match[2] ?? '';\n\treturn raw.split(',').map((p) => p.trim()).filter(Boolean);\n}\n\n/**\n * Check for ECH (Encrypted Client Hello) in the HTTPS record data.\n */\nfunction hasEch(data: string): boolean {\n\treturn /\\bech=/i.test(data);\n}\n\n/**\n * Parse the priority from HTTPS record data.\n */\nfunction parsePriority(data: string): number | null {\n\tconst match = data.match(/^(\\d+)\\s/);\n\tif (!match) return null;\n\treturn parseInt(match[1], 10);\n}\n\n/**\n * Check HTTPS/SVCB records (RFC 9460) for a domain.\n * Validates the presence of HTTPS records and analyzes their contents\n * for modern transport capability advertisements.\n */\nexport async function checkSVCBHTTPS(\n\tdomain: string,\n\tqueryDNS: DNSQueryFunction,\n\toptions?: { timeout?: number },\n): Promise<CheckResult> {\n\tconst timeout = options?.timeout ?? 5000;\n\tconst findings: Finding[] = [];\n\n\tlet httpsRecords: string[] = [];\n\ttry {\n\t\thttpsRecords = await queryDNS(domain, 'HTTPS', { timeout });\n\t} catch {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'svcb_https',\n\t\t\t\t'HTTPS record query failed',\n\t\t\t\t'low',\n\t\t\t\t`DNS query for HTTPS records at ${domain} failed. Unable to determine SVCB/HTTPS status.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('svcb_https', findings);\n\t}\n\n\tif (httpsRecords.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'svcb_https',\n\t\t\t\t'No HTTPS record found',\n\t\t\t\t'low',\n\t\t\t\t`No HTTPS (type 65) record found at ${domain}. HTTPS records (RFC 9460) advertise modern transport capabilities (ALPN, ECH) and enable clients to connect securely without an initial redirect round-trip. Consider publishing an HTTPS record with h2 and h3 ALPN support.`,\n\t\t\t\t{ missingControl: true },\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('svcb_https', findings);\n\t}\n\n\t// Analyze each HTTPS record\n\tlet hasH2 = false;\n\tlet hasH3 = false;\n\tlet hasEchParam = false;\n\tlet hasAliasMode = false;\n\tlet validServiceModeRecords = 0;\n\n\tfor (const record of httpsRecords) {\n\t\tconst priority = parsePriority(record);\n\n\t\tif (priority === 0) {\n\t\t\t// Alias mode — delegates to another name for parameters\n\t\t\thasAliasMode = true;\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'svcb_https',\n\t\t\t\t\t'HTTPS record in alias mode',\n\t\t\t\t\t'info',\n\t\t\t\t\t`HTTPS record at ${domain} uses alias mode (priority 0): ${record}. This delegates SVCB parameters to a canonical name. Ensure the target also has valid HTTPS records.`,\n\t\t\t\t\t{ record, mode: 'alias' },\n\t\t\t\t),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Service mode (priority >= 1)\n\t\tvalidServiceModeRecords++;\n\t\tconst alpnProtocols = parseAlpn(record);\n\t\tconst recordHasEch = hasEch(record);\n\n\t\tif (alpnProtocols.includes('h2')) hasH2 = true;\n\t\tif (alpnProtocols.includes('h3')) hasH3 = true;\n\t\tif (recordHasEch) hasEchParam = true;\n\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'svcb_https',\n\t\t\t\t'HTTPS record configured',\n\t\t\t\t'info',\n\t\t\t\t`HTTPS record found at ${domain} (priority ${priority}): ALPN=[${alpnProtocols.join(', ') || 'none'}]${recordHasEch ? ', ECH=present' : ''}.`,\n\t\t\t\t{ record, priority, alpn: alpnProtocols, ech: recordHasEch },\n\t\t\t),\n\t\t);\n\n\t\t// Flag missing ALPN\n\t\tif (alpnProtocols.length === 0 && !hasAliasMode) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'svcb_https',\n\t\t\t\t\t'HTTPS record missing ALPN parameter',\n\t\t\t\t\t'low',\n\t\t\t\t\t`HTTPS record at ${domain} does not specify an ALPN parameter. Without ALPN, clients cannot use the record to negotiate HTTP/2 or HTTP/3 without an additional round-trip. Add alpn=\"h2\" or alpn=\"h2,h3\" to enable protocol negotiation.`,\n\t\t\t\t\t{ record },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Summary findings for capabilities\n\tif (validServiceModeRecords > 0 || hasAliasMode) {\n\t\tif (!hasH2 && !hasAliasMode) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'svcb_https',\n\t\t\t\t\t'HTTPS record does not advertise HTTP/2',\n\t\t\t\t\t'low',\n\t\t\t\t\t`HTTPS records at ${domain} do not include h2 in the ALPN list. HTTP/2 support via SVCB allows faster TLS negotiation. Add alpn=\"h2,h3\" to enable HTTP/2 and HTTP/3 advertisement.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tif (hasH3) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'svcb_https',\n\t\t\t\t\t'HTTP/3 (QUIC) advertised via HTTPS record',\n\t\t\t\t\t'info',\n\t\t\t\t\t`HTTPS record at ${domain} advertises HTTP/3 (h3) ALPN, enabling QUIC-based transport. This provides improved performance and resilience, especially on lossy networks.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tif (hasEchParam) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'svcb_https',\n\t\t\t\t\t'Encrypted Client Hello (ECH) advertised',\n\t\t\t\t\t'info',\n\t\t\t\t\t`HTTPS record at ${domain} includes ECH parameters. ECH encrypts the TLS SNI field, preventing passive observers from identifying the target hostname during connection establishment.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\treturn buildCheckResult('svcb_https', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Subdomain takeover analysis helpers.\n * Scanning logic for detecting dangling CNAMEs and takeover vectors.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { DNSQueryFunction, FetchFunction, Finding } from '../types';\nimport { createFinding } from '../check-utils';\n\nexport type TakeoverVerificationStatus = 'potential' | 'verified' | 'not_exploitable';\n\n/** Default HTTPS timeout for fingerprint probing (ms) */\nconst HTTPS_TIMEOUT_MS = 4_000;\n\nexport const KNOWN_SUBDOMAINS = [\n\t'www',\n\t'app',\n\t'api',\n\t'staging',\n\t'dev',\n\t'admin',\n\t'cdn',\n\t'static',\n\t'mail',\n\t'blog',\n\t'docs',\n\t'status',\n\t'portal',\n\t'login',\n\t'support',\n];\n\nconst TAKEOVER_SERVICES = [\n\t'cloudfront.net',\n\t'herokuapp.com',\n\t'azurewebsites.net',\n\t'amazonaws.com',\n\t'github.io',\n\t'pages.dev',\n\t'fastly.net',\n\t'netlify.app',\n\t'fly.dev',\n\t'zeit.co',\n\t'webflow.io',\n\t'firebaseapp.com',\n\t'vercel.app',\n\t'vercel-dns.com',\n\t'now.sh',\n\t'myshopify.com',\n\t'zendesk.com',\n\t'pantheonsite.io',\n\t'squarespace.com',\n\t'sqsp.net',\n\t'ghost.io',\n\t'surge.sh',\n\t'wpengine.com',\n\t'wordpress.com',\n\t'tumblr.com',\n\t'readme.io',\n\t'hs-sites.com',\n\t'freshdesk.com',\n\t'bitbucket.io',\n];\n\nconst TAKEOVER_FINGERPRINTS: Record<string, string> = {\n\t'github.io': \"There isn't a GitHub Pages site here\",\n\t'herokuapp.com': 'no-such-app',\n\t'amazonaws.com': 'NoSuchBucket',\n\t'cloudfront.net': 'NoSuchBucket',\n\t'fastly.net': 'Fastly error: unknown domain',\n\t'netlify.app': 'Not Found - Request ID',\n\t'pantheonsite.io': 'The gods are displeased',\n\t'tumblr.com': \"There's nothing here\",\n\t'ghost.io': 'The thing you were looking for is no longer here',\n};\n\nconst SERVICE_DISPLAY_NAMES: Record<string, string> = {\n\t'github.io': 'GitHub Pages',\n\t'amazonaws.com': 'AWS S3',\n\t'cloudfront.net': 'AWS S3',\n\t'fastly.net': 'Fastly',\n\t'netlify.app': 'Netlify',\n\t'pantheonsite.io': 'Pantheon',\n\t'tumblr.com': 'Tumblr',\n\t'ghost.io': 'Ghost',\n};\n\nexport function createTakeoverFinding(\n\ttitle: string,\n\tseverity: 'critical' | 'high' | 'info',\n\tdetail: string,\n\tverificationStatus: TakeoverVerificationStatus,\n\tevidence: string[],\n): Finding {\n\treturn createFinding('subdomain_takeover', title, severity, detail, {\n\t\tverificationStatus,\n\t\tevidence,\n\t});\n}\n\nexport function isThirdPartyTakeoverService(cname: string): boolean {\n\treturn TAKEOVER_SERVICES.some((service) => cname.includes(service));\n}\n\n/**\n * Probe an HTTP endpoint for known takeover fingerprints.\n * Returns the matched service name or null if no fingerprint matched.\n */\nexport async function probeHttpFingerprint(fqdn: string, cname: string, fetchFn: FetchFunction): Promise<string | null> {\n\tconst matchingEntries = Object.entries(TAKEOVER_FINGERPRINTS).filter(([service]) => cname.includes(service));\n\tif (matchingEntries.length === 0) return null;\n\n\ttry {\n\t\tconst response = await fetchFn(`https://${fqdn}`, {\n\t\t\tredirect: 'manual',\n\t\t\tsignal: AbortSignal.timeout(HTTPS_TIMEOUT_MS),\n\t\t});\n\t\t// Skip fingerprint matching on redirects — redirecting services are not deprovisioned\n\t\tif (response.status >= 300 && response.status < 400) return null;\n\n\t\tconst MAX_BODY_BYTES = 65_536; // 64 KB — no legitimate takeover fingerprint page exceeds this\n\t\tconst contentLength = parseInt(response.headers?.get('content-length') ?? '0', 10);\n\t\tif (contentLength > MAX_BODY_BYTES) return null;\n\t\tconst body = await response.text();\n\t\tif (body.length > MAX_BODY_BYTES) return null;\n\n\t\tfor (const [service, fingerprint] of matchingEntries) {\n\t\t\tif (service === 'herokuapp.com') {\n\t\t\t\tif (body.includes('no-such-app') || body.includes('No such app')) {\n\t\t\t\t\treturn 'Heroku';\n\t\t\t\t}\n\t\t\t} else if (body.includes(fingerprint)) {\n\t\t\t\treturn SERVICE_DISPLAY_NAMES[service] ?? service;\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Timeout or network error — silently skip.\n\t}\n\n\treturn null;\n}\n\nexport async function scanSubdomainForTakeover(\n\tdomain: string,\n\tsubdomain: string,\n\tqueryDNS: DNSQueryFunction,\n\tfetchFn: FetchFunction,\n\ttimeout?: number,\n): Promise<Finding[]> {\n\tconst fqdn = `${subdomain}.${domain}`;\n\tconst findings: Finding[] = [];\n\n\ttry {\n\t\tconst cnameRecords = await queryDNS(fqdn, 'CNAME', { timeout });\n\t\tfor (const rawCname of cnameRecords) {\n\t\t\tconst cname = rawCname.replace(/\\.$/, '').replace(/[\\x00-\\x1F\\x7F]/g, '').toLowerCase();\n\t\t\tif (!isThirdPartyTakeoverService(cname)) continue;\n\n\t\t\ttry {\n\t\t\t\tconst targetAddresses = await queryDNS(cname, 'A', { timeout });\n\t\t\t\tif (targetAddresses.length === 0) {\n\t\t\t\t\tfindings.push(\n\t\t\t\t\t\tcreateTakeoverFinding(\n\t\t\t\t\t\t\t`Dangling CNAME: ${fqdn} → ${cname}`,\n\t\t\t\t\t\t\t'high',\n\t\t\t\t\t\t\t`Subdomain ${fqdn} points to ${cname}, which does not resolve. This is a potential subdomain takeover vector and should be manually validated with authorized claim testing.`,\n\t\t\t\t\t\t\t'potential',\n\t\t\t\t\t\t\t['cname_target_unresolved'],\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst vulnerableService = await probeHttpFingerprint(fqdn, cname, fetchFn);\n\t\t\t\tif (vulnerableService) {\n\t\t\t\t\tfindings.push(\n\t\t\t\t\t\tcreateTakeoverFinding(\n\t\t\t\t\t\t\t`Subdomain vulnerable to takeover (${vulnerableService})`,\n\t\t\t\t\t\t\t'critical',\n\t\t\t\t\t\t\t`Subdomain ${fqdn} points to ${cname}, which resolves but returns a ${vulnerableService} deprovisioned fingerprint. This is a verified takeover signal and should be confirmed with authorized proof-of-control testing.`,\n\t\t\t\t\t\t\t'verified',\n\t\t\t\t\t\t\t['cname_resolves', 'provider_deprovisioned_fingerprint'],\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateTakeoverFinding(\n\t\t\t\t\t\t`CNAME resolution failed: ${fqdn} → ${cname}`,\n\t\t\t\t\t\t'high',\n\t\t\t\t\t\t`Could not resolve CNAME target ${cname} for ${fqdn}. This is a potential takeover signal and requires manual verification.`,\n\t\t\t\t\t\t'potential',\n\t\t\t\t\t\t['cname_target_resolution_error'],\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// No CNAME or query failed; not critical.\n\t}\n\n\treturn findings;\n}\n\nexport function getNoTakeoverFinding(domain: string): Finding {\n\treturn createTakeoverFinding(\n\t\t'No dangling CNAME records found',\n\t\t'info',\n\t\t`No subdomain takeover vectors detected for ${domain} among known/active subdomains.`,\n\t\t'not_exploitable',\n\t\t['no_takeover_signals_detected'],\n\t);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Subdomain Takeover / Dangling CNAME Detection check.\n * Scans known/active subdomains for orphaned CNAME records pointing to\n * deleted/unresolved third-party services.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { CheckResult, DNSQueryFunction, FetchFunction, Finding } from '../types';\nimport { buildCheckResult } from '../check-utils';\nimport { KNOWN_SUBDOMAINS, getNoTakeoverFinding, scanSubdomainForTakeover } from './subdomain-takeover-analysis';\n\n/**\n * Check for dangling CNAME records on known/active subdomains.\n * Flags orphaned records and potential takeover vectors.\n *\n * Requires a fetch function for HTTP fingerprint probing.\n */\nexport async function checkSubdomainTakeover(\n\tdomain: string,\n\tqueryDNS: DNSQueryFunction,\n\toptions?: { timeout?: number; fetchFn?: FetchFunction },\n): Promise<CheckResult> {\n\tconst timeout = options?.timeout ?? 5000;\n\t// Default to a no-op fetch that never matches fingerprints if no fetchFn provided\n\tconst fetchFn: FetchFunction = options?.fetchFn ?? (async () => new Response('', { status: 200 }));\n\tconst findings: Finding[] = [];\n\n\tconst findingsPerSubdomain = await Promise.all(\n\t\tKNOWN_SUBDOMAINS.map((subdomain) => scanSubdomainForTakeover(domain, subdomain, queryDNS, fetchFn, timeout)),\n\t);\n\n\tfor (const subdomainFindings of findingsPerSubdomain) {\n\t\tfindings.push(...subdomainFindings);\n\t}\n\n\tif (findings.length === 0) {\n\t\tfindings.push(getNoTakeoverFinding(domain));\n\t}\n\n\treturn buildCheckResult('subdomain_takeover', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * HTTP security headers analysis helpers.\n * Pure functions for analyzing browser security headers from HTTP responses.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { Finding } from '../types';\nimport { createFinding } from '../check-utils';\n\n/** Headers checked by the HTTP security analysis. */\nconst SECURITY_HEADERS = [\n\t'content-security-policy',\n\t'x-frame-options',\n\t'x-content-type-options',\n\t'permissions-policy',\n\t'referrer-policy',\n\t'cross-origin-resource-policy',\n\t'cross-origin-opener-policy',\n] as const;\n\n/** CSP directive name for dynamic code execution. */\nconst CSP_UNSAFE_EVAL_DIRECTIVE = \"'unsafe-eval'\";\n\n/**\n * Analyze CSP for unsafe directives.\n * Returns findings for unsafe-inline, unsafe-eval, and wildcard sources in script-src.\n */\nfunction analyzeCspQuality(cspValue: string): Finding[] {\n\tconst findings: Finding[] = [];\n\tconst lower = cspValue.toLowerCase();\n\n\t// Check for unsafe-inline in script-src (or default-src if no script-src)\n\tconst scriptSrcMatch = lower.match(/script-src\\s+([^;]+)/);\n\tconst defaultSrcMatch = lower.match(/default-src\\s+([^;]+)/);\n\tconst effectiveScriptSrc = scriptSrcMatch?.[1] ?? defaultSrcMatch?.[1] ?? '';\n\n\tif (effectiveScriptSrc.includes(\"'unsafe-inline'\")) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'CSP allows unsafe-inline scripts',\n\t\t\t\t'medium',\n\t\t\t\t\"Content-Security-Policy contains 'unsafe-inline' in the script source, which undermines XSS protection. Use nonces or hashes instead.\",\n\t\t\t),\n\t\t);\n\t}\n\n\tif (effectiveScriptSrc.includes(CSP_UNSAFE_EVAL_DIRECTIVE)) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'CSP allows unsafe-eval',\n\t\t\t\t'medium',\n\t\t\t\t`Content-Security-Policy contains ${CSP_UNSAFE_EVAL_DIRECTIVE} in the script source, allowing dynamic code execution. This weakens XSS protection.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Check for wildcard source in script-src or default-src\n\t// Match standalone * but not *.example.com\n\tconst sources = effectiveScriptSrc.split(/\\s+/);\n\tif (sources.some((s) => s === '*')) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'CSP uses wildcard source',\n\t\t\t\t'medium',\n\t\t\t\t'Content-Security-Policy uses a wildcard (*) source, allowing scripts from any origin. This provides minimal XSS protection.',\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n\n/**\n * Analyze HTTP security headers from a response.\n * Returns findings for missing or misconfigured headers.\n *\n * @param headers - The response headers to analyze\n * @returns Array of findings describing missing or weak security headers\n */\nexport function analyzeSecurityHeaders(headers: Headers): Finding[] {\n\tconst findings: Finding[] = [];\n\n\tconst csp = headers.get('content-security-policy');\n\tconst xfo = headers.get('x-frame-options');\n\tconst xcto = headers.get('x-content-type-options');\n\tconst pp = headers.get('permissions-policy');\n\tconst rp = headers.get('referrer-policy');\n\tconst corp = headers.get('cross-origin-resource-policy');\n\tconst coop = headers.get('cross-origin-opener-policy');\n\n\t// Track whether we have CSP frame-ancestors (supersedes X-Frame-Options)\n\tconst cspHasFrameAncestors = csp ? /frame-ancestors/i.test(csp) : false;\n\n\t// Content-Security-Policy\n\tif (!csp) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'No Content-Security-Policy',\n\t\t\t\t'high',\n\t\t\t\t'No Content-Security-Policy header found. CSP is a critical defense against cross-site scripting (XSS) and data injection attacks.',\n\t\t\t),\n\t\t);\n\t} else {\n\t\tfindings.push(...analyzeCspQuality(csp));\n\t}\n\n\t// X-Frame-Options — only flag if CSP frame-ancestors is also missing\n\tif (!xfo && !cspHasFrameAncestors) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'No X-Frame-Options',\n\t\t\t\t'medium',\n\t\t\t\t'No X-Frame-Options header and no CSP frame-ancestors directive found. The page may be vulnerable to clickjacking attacks.',\n\t\t\t),\n\t\t);\n\t}\n\n\t// X-Content-Type-Options\n\tif (!xcto) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'No X-Content-Type-Options',\n\t\t\t\t'low',\n\t\t\t\t'No X-Content-Type-Options header found. Set to \"nosniff\" to prevent browsers from MIME-sniffing the content type.',\n\t\t\t),\n\t\t);\n\t}\n\n\t// Permissions-Policy\n\tif (!pp) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'No Permissions-Policy',\n\t\t\t\t'low',\n\t\t\t\t'No Permissions-Policy header found. This header restricts access to browser features like camera, microphone, and geolocation.',\n\t\t\t),\n\t\t);\n\t}\n\n\t// Referrer-Policy\n\tif (!rp) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'No Referrer-Policy',\n\t\t\t\t'low',\n\t\t\t\t'No Referrer-Policy header found. Without it, the full URL including query parameters may be leaked to third-party sites via the Referer header.',\n\t\t\t),\n\t\t);\n\t}\n\n\t// Cross-Origin-Resource-Policy\n\tif (!corp) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'No CORP header',\n\t\t\t\t'info',\n\t\t\t\t'No Cross-Origin-Resource-Policy header found. CORP prevents other origins from loading your resources, mitigating Spectre-class side-channel attacks.',\n\t\t\t),\n\t\t);\n\t}\n\n\t// Cross-Origin-Opener-Policy\n\tif (!coop) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'No COOP header',\n\t\t\t\t'info',\n\t\t\t\t'No Cross-Origin-Opener-Policy header found. COOP isolates the browsing context from cross-origin popups, mitigating cross-origin attacks.',\n\t\t\t),\n\t\t);\n\t}\n\n\t// All good case: all headers present and CSP has no unsafe directives\n\tif (findings.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'HTTP security headers well configured',\n\t\t\t\t'info',\n\t\t\t\t`All ${SECURITY_HEADERS.length} security headers are present and Content-Security-Policy has no unsafe directives.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * HTTP security headers check.\n * Fetches the HTTPS endpoint and analyzes browser security headers.\n *\n * Copyright (c) 2023-2026 BlackVeil Security Ltd.\n * Licensed under BSL 1.1\n */\n\nimport type { CheckResult, FetchFunction, Finding } from '../types';\nimport { buildCheckResult, createFinding } from '../check-utils';\nimport { analyzeSecurityHeaders } from './http-security-analysis';\n\n/** Default HTTPS timeout (ms) */\nconst HTTPS_TIMEOUT_MS = 4_000;\n\n/**\n * Check HTTP security headers for a domain.\n * Fetches the HTTPS endpoint and analyzes browser security headers.\n *\n * Requires a fetch function for making HTTP requests.\n */\nexport async function checkHTTPSecurity(\n\tdomain: string,\n\tfetchFn: FetchFunction,\n\toptions?: { timeout?: number },\n): Promise<CheckResult> {\n\tconst timeoutMs = options?.timeout ?? HTTPS_TIMEOUT_MS;\n\tconst findings: Finding[] = [];\n\n\ttry {\n\t\tconst response = await fetchFn(`https://${domain}`, {\n\t\t\tmethod: 'HEAD',\n\t\t\tredirect: 'manual', // SSRF protection — never follow redirects\n\t\t\tsignal: AbortSignal.timeout(timeoutMs),\n\t\t});\n\n\t\t// Only analyze headers on successful or redirect responses\n\t\tif (response.status < 500) {\n\t\t\tfindings.push(...analyzeSecurityHeaders(response.headers));\n\t\t} else {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'http_security',\n\t\t\t\t\t'Server error',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`HTTPS returned status ${response.status} for ${domain}. Cannot analyze security headers.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t} catch (err) {\n\t\tconst message =\n\t\t\terr instanceof Error && (err.message.includes('timeout') || err.message.includes('abort'))\n\t\t\t\t? 'Connection timed out'\n\t\t\t\t: 'Connection failed';\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t`HTTPS ${message.toLowerCase()}`,\n\t\t\t\t'medium',\n\t\t\t\t`Could not fetch https://${domain} to check security headers: ${message}.`,\n\t\t\t\t{ missingControl: true },\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('http_security', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { z } from 'zod';\n\n/** All valid check categories. */\nexport const CheckCategorySchema = z.enum([\n\t'spf', 'dmarc', 'dkim', 'dnssec', 'ssl', 'mta_sts', 'ns', 'caa',\n\t'subdomain_takeover', 'mx', 'bimi', 'tlsrpt', 'lookalikes', 'shadow_domains',\n\t'txt_hygiene', 'http_security', 'dane', 'mx_reputation', 'srv', 'zone_hygiene',\n\t'dane_https', 'svcb_https',\n]);\n\n/** Severity levels. */\nexport const SeveritySchema = z.enum(['critical', 'high', 'medium', 'low', 'info']);\n\n/** Finding confidence. */\nexport const FindingConfidenceSchema = z.enum(['deterministic', 'heuristic', 'verified']);\n\n/** Category tier. */\nexport const CategoryTierSchema = z.enum(['core', 'protective', 'hardening']);\n\n/** A single finding from a check. */\nexport const FindingSchema = z.object({\n\tcategory: CheckCategorySchema,\n\ttitle: z.string(),\n\tseverity: SeveritySchema,\n\tdetail: z.string(),\n\tmetadata: z.record(z.string(), z.unknown()).optional(),\n});\n\n/** Result of a single DNS check. */\nexport const CheckResultSchema = z.object({\n\tcategory: CheckCategorySchema,\n\tpassed: z.boolean(),\n\tscore: z.number(),\n\tfindings: z.array(FindingSchema),\n});\n\n/** Scan score result. */\nexport const ScanScoreSchema = z.object({\n\toverall: z.number(),\n\tgrade: z.string(),\n\tcategoryScores: z.record(z.string(), z.number()),\n\tfindings: z.array(FindingSchema),\n\tsummary: z.string(),\n});\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * BIMI (Brand Indicators for Message Identification) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkBIMI } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check BIMI records for a domain.\n * Validates the presence and configuration of BIMI TXT records,\n * including logo URL format and VMC authority evidence.\n */\nexport async function checkBimi(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkBIMI(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? 5000 },\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * CAA (Certificate Authority Authorization) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkCAA } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check CAA records for a domain.\n * Validates that CAA records exist and are properly configured.\n */\nexport async function checkCaa(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkCAA(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? 5000 },\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DKIM (DomainKeys Identified Mail) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n * Retains applyProviderDkimContext for scan_domain post-processing.\n */\n\nimport { checkDKIM, createFinding, buildCheckResult } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\n/**\n * Email providers with high confidence of default DKIM signing.\n */\nconst HIGH_CONFIDENCE_DKIM_PROVIDERS = new Set([\n\t'amazon ses',\n\t'sendgrid',\n\t'mailgun',\n\t'postmark',\n\t'google workspace',\n\t'microsoft 365',\n]);\n\n/**\n * Email providers that typically sign with DKIM but vary by configuration.\n */\nconst MEDIUM_CONFIDENCE_DKIM_PROVIDERS = new Set(['proofpoint', 'mimecast']);\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check DKIM records for a domain.\n * Probes common selectors at <selector>._domainkey.<domain>.\n * Optionally accepts a specific selector to check.\n */\nexport async function checkDkim(domain: string, selector?: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkDKIM(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? 5000, selector },\n\t) as Promise<CheckResult>;\n}\n\n/**\n * Apply provider-informed context to DKIM results.\n * Called as a post-processing step in scan_domain after MX-based provider detection completes.\n * When a known DKIM-signing provider is detected, downgrades the \"No DKIM records found\"\n * finding from HIGH to MEDIUM since the provider likely signs outbound mail by default.\n */\nexport function applyProviderDkimContext(dkimResult: CheckResult, provider: string): CheckResult {\n\tconst normalizedProvider = provider.toLowerCase();\n\tconst notFoundIdx = dkimResult.findings.findIndex(\n\t\t(f) => /No DKIM records found/i.test(f.title) && f.severity === 'high',\n\t);\n\tif (notFoundIdx === -1) return dkimResult;\n\n\tconst selectorsChecked = (dkimResult.findings[notFoundIdx].metadata?.selectorsChecked as string[]) ?? [];\n\tconst newFindings = [...dkimResult.findings];\n\n\tif (HIGH_CONFIDENCE_DKIM_PROVIDERS.has(normalizedProvider)) {\n\t\tnewFindings[notFoundIdx] = createFinding(\n\t\t\t'dkim',\n\t\t\t'DKIM selector not discovered',\n\t\t\t'medium',\n\t\t\t`No DKIM selectors were found among the tested set, but ${provider} is detected as the email provider and signs outbound mail by default. DKIM is likely present with a custom selector.`,\n\t\t\t{\n\t\t\t\tconfidence: 'heuristic',\n\t\t\t\tdetectionMethod: 'provider-implied',\n\t\t\t\tprovider: normalizedProvider,\n\t\t\t\tselectorsChecked,\n\t\t\t},\n\t\t);\n\t} else if (MEDIUM_CONFIDENCE_DKIM_PROVIDERS.has(normalizedProvider)) {\n\t\tnewFindings[notFoundIdx] = createFinding(\n\t\t\t'dkim',\n\t\t\t'DKIM selector not discovered',\n\t\t\t'medium',\n\t\t\t`No DKIM selectors were found among the tested set. ${provider} is detected as the email provider and typically signs outbound mail.`,\n\t\t\t{\n\t\t\t\tconfidence: 'heuristic',\n\t\t\t\tdetectionMethod: 'provider-implied',\n\t\t\t\tprovider: normalizedProvider,\n\t\t\t\tselectorsChecked,\n\t\t\t},\n\t\t);\n\t\tnewFindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dkim',\n\t\t\t\t'DKIM provider signing unverified',\n\t\t\t\t'low',\n\t\t\t\t`${provider} signing policy varies by configuration — DKIM presence cannot be confirmed without selector discovery.`,\n\t\t\t\t{ confidence: 'heuristic' },\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('dkim', newFindings) as CheckResult;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DMARC (Domain-based Message Authentication, Reporting & Conformance) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkDMARC } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\nexport { parseDmarcTags } from '@blackveil/dns-checks';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check DMARC records for a domain.\n * Queries _dmarc.<domain> TXT records and validates policy configuration.\n */\nexport async function checkDmarc(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkDMARC(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? 5000 },\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DNSSEC (DNS Security Extensions) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkDNSSEC } from '@blackveil/dns-checks';\nimport { queryDns, queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\nexport { parseDnskeyAlgorithm, parseDsRecord } from '@blackveil/dns-checks';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check DNSSEC configuration for a domain.\n * Verifies the AD (Authenticated Data) flag, checks for DNSKEY/DS records,\n * and audits algorithm and digest type security.\n */\nexport async function checkDnssec(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkDNSSEC(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{\n\t\t\ttimeout: dnsOptions?.timeoutMs ?? 5000,\n\t\t\trawQueryDNS: async (d, type, dnssecFlag) => {\n\t\t\t\tconst resp = await queryDns(d, type as Parameters<typeof queryDns>[1], dnssecFlag ?? false, dnsOptions);\n\t\t\t\treturn { AD: resp.AD, Answer: resp.Answer };\n\t\t\t},\n\t\t},\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Lookalike domain generation utilities.\n * Generates typosquat/lookalike domain permutations using multiple strategies:\n * adjacent key swaps, character omission, character duplication, dot insertion,\n * common TLD swaps, and homoglyph substitution.\n */\n\nimport { LABEL_REGEX, MAX_DOMAIN_LENGTH, MAX_LABEL_LENGTH } from '../lib/config';\n\n/** QWERTY keyboard adjacency map for typosquat detection */\nconst QWERTY_ADJACENT: Record<string, string[]> = {\n\tq: ['w', 'a'],\n\tw: ['q', 'e', 's', 'a'],\n\te: ['w', 'r', 'd', 's'],\n\tr: ['e', 't', 'f', 'd'],\n\tt: ['r', 'y', 'g', 'f'],\n\ty: ['t', 'u', 'h', 'g'],\n\tu: ['y', 'i', 'j', 'h'],\n\ti: ['u', 'o', 'k', 'j'],\n\to: ['i', 'p', 'l', 'k'],\n\tp: ['o', 'l'],\n\ta: ['q', 'w', 's', 'z'],\n\ts: ['a', 'w', 'e', 'd', 'z', 'x'],\n\td: ['s', 'e', 'r', 'f', 'x', 'c'],\n\tf: ['d', 'r', 't', 'g', 'c', 'v'],\n\tg: ['f', 't', 'y', 'h', 'v', 'b'],\n\th: ['g', 'y', 'u', 'j', 'b', 'n'],\n\tj: ['h', 'u', 'i', 'k', 'n', 'm'],\n\tk: ['j', 'i', 'o', 'l', 'm'],\n\tl: ['k', 'o', 'p'],\n\tz: ['a', 's', 'x'],\n\tx: ['z', 's', 'd', 'c'],\n\tc: ['x', 'd', 'f', 'v'],\n\tv: ['c', 'f', 'g', 'b'],\n\tb: ['v', 'g', 'h', 'n'],\n\tn: ['b', 'h', 'j', 'm'],\n\tm: ['n', 'j', 'k'],\n};\n\n/** Homoglyph substitution pairs (one substitution at a time) */\nconst HOMOGLYPHS: Array<[string, string]> = [\n\t['o', '0'],\n\t['0', 'o'],\n\t['l', '1'],\n\t['1', 'l'],\n\t['i', '1'],\n\t['1', 'i'],\n\t['l', 'i'],\n\t['i', 'l'],\n\t['rn', 'm'],\n\t['m', 'rn'],\n\t['vv', 'w'],\n\t['w', 'vv'],\n];\n\n/** Common TLD swap pairs */\nconst TLD_SWAPS: Array<[string, string]> = [\n\t['.com', '.co'],\n\t['.com', '.net'],\n\t['.com', '.org'],\n\t['.com', '.io'],\n\t['.co.nz', '.com'],\n\t['.com.au', '.com'],\n];\n\n/** Maximum number of permutations to return */\nconst MAX_PERMUTATIONS = 50;\n\n/**\n * Split a domain into base (before TLD) and TLD parts.\n * Handles multi-part TLDs like .co.nz and .com.au.\n */\nfunction splitDomainTld(domain: string): { base: string; tld: string } {\n\tconst multiPartTlds = ['.co.nz', '.com.au', '.co.uk', '.org.uk', '.net.au', '.org.au'];\n\tfor (const multiTld of multiPartTlds) {\n\t\tif (domain.endsWith(multiTld)) {\n\t\t\treturn { base: domain.slice(0, -multiTld.length), tld: multiTld };\n\t\t}\n\t}\n\tconst lastDot = domain.lastIndexOf('.');\n\tif (lastDot === -1) return { base: domain, tld: '' };\n\treturn { base: domain.slice(0, lastDot), tld: domain.slice(lastDot) };\n}\n\n/**\n * Check whether a domain string is structurally valid.\n * Labels must be 1-63 chars, alphanumeric + hyphens, total <= 253 chars.\n */\nfunction isDomainValid(domain: string): boolean {\n\tif (domain.length > MAX_DOMAIN_LENGTH) return false;\n\tconst labels = domain.split('.');\n\tif (labels.length < 2) return false;\n\tfor (const label of labels) {\n\t\tif (label.length === 0 || label.length > MAX_LABEL_LENGTH) return false;\n\t\tif (!LABEL_REGEX.test(label)) return false;\n\t}\n\treturn true;\n}\n\n/**\n * Generate lookalike/typosquat domain permutations for a given domain.\n * Applies six strategies: adjacent key swaps, character omission, character duplication,\n * dot insertion, common TLD swaps, and homoglyph substitution.\n *\n * Returns up to 50 unique, valid, alphabetically sorted permutations.\n */\nexport function generateLookalikes(domain: string): string[] {\n\tconst normalizedDomain = domain.toLowerCase();\n\tconst { base, tld } = splitDomainTld(normalizedDomain);\n\tconst candidates = new Set<string>();\n\n\t// 1. Adjacent key swaps — swap each char in base with QWERTY adjacent keys\n\tfor (let i = 0; i < base.length; i++) {\n\t\tconst ch = base[i];\n\t\tconst adjacent = QWERTY_ADJACENT[ch];\n\t\tif (adjacent) {\n\t\t\tfor (const adj of adjacent) {\n\t\t\t\tconst permuted = base.slice(0, i) + adj + base.slice(i + 1);\n\t\t\t\tcandidates.add(permuted + tld);\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. Character omission — remove one char at a time from base\n\tfor (let i = 0; i < base.length; i++) {\n\t\tconst permuted = base.slice(0, i) + base.slice(i + 1);\n\t\tif (permuted.length > 0) {\n\t\t\tcandidates.add(permuted + tld);\n\t\t}\n\t}\n\n\t// 3. Character duplication — double one char at a time in base\n\tfor (let i = 0; i < base.length; i++) {\n\t\tconst permuted = base.slice(0, i) + base[i] + base[i] + base.slice(i + 1);\n\t\tcandidates.add(permuted + tld);\n\t}\n\n\t// 4. Dot insertion — insert dots between chars in base (both parts must be >= 2 chars)\n\tfor (let i = 1; i < base.length; i++) {\n\t\tconst left = base.slice(0, i);\n\t\tconst right = base.slice(i);\n\t\tif (left.length >= 2 && right.length >= 2) {\n\t\t\tcandidates.add(left + '.' + right + tld);\n\t\t}\n\t}\n\n\t// 5. Common TLD swaps — swap to different TLD if original matches\n\tfor (const [fromTld, toTld] of TLD_SWAPS) {\n\t\tif (tld === fromTld) {\n\t\t\tcandidates.add(base + toTld);\n\t\t} else if (tld === toTld) {\n\t\t\tcandidates.add(base + fromTld);\n\t\t}\n\t}\n\n\t// 6. Homoglyph substitution — one substitution at a time in base\n\tfor (const [from, to] of HOMOGLYPHS) {\n\t\tlet searchIdx = 0;\n\t\twhile (searchIdx <= base.length - from.length) {\n\t\t\tconst idx = base.indexOf(from, searchIdx);\n\t\t\tif (idx === -1) break;\n\t\t\tconst permuted = base.slice(0, idx) + to + base.slice(idx + from.length);\n\t\t\tcandidates.add(permuted + tld);\n\t\t\tsearchIdx = idx + 1;\n\t\t}\n\t}\n\n\t// Filter, dedup, and cap\n\tconst results = Array.from(candidates)\n\t\t.filter((candidate) => candidate !== normalizedDomain && isDomainValid(candidate))\n\t\t.sort();\n\n\treturn results.slice(0, MAX_PERMUTATIONS);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Lookalike domain detection tool.\n * Generates typosquat/lookalike domain permutations and checks for\n * active DNS registrations and mail infrastructure.\n * Standalone check — not included in scan_domain due to query volume.\n */\n\nimport { queryDnsRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult, Finding } from '../lib/scoring';\nimport { buildCheckResult, createFinding } from '../lib/scoring';\nimport { generateLookalikes } from './lookalike-analysis';\n\n/** Default and minimum batch sizes for adaptive batching */\nexport const INITIAL_BATCH_SIZE = 10;\nexport const MIN_BATCH_SIZE = 3;\nexport const BACKOFF_DELAY_MS = 500;\nexport const FAILURE_THRESHOLD = 2;\n\n/** Maximum wall-clock time for the entire lookalike check (ms). */\nconst LOOKALIKE_TIMEOUT_MS = 20_000;\n\n/** Canary label used for wildcard detection on parent domains */\nexport const WILDCARD_CANARY_LABEL = '_bv-wc-probe';\n\n/** Lean DNS options for Phase 1 existence checks — fast, no retries, no secondary confirmation. */\nexport const PHASE1_DNS_OPTS: QueryDnsOptions = {\n\ttimeoutMs: 2000,\n\tretries: 0,\n\tskipSecondaryConfirmation: true,\n};\n\ninterface LookalikeResult {\n\tdomain: string;\n\thasA: boolean;\n\thasMX: boolean;\n}\n\n/** Minimum number of NS records that must overlap to consider domains as sharing nameservers. */\nconst SHARED_NS_THRESHOLD = 1;\n\n/**\n * Check whether an MX record represents real mail infrastructure.\n * RFC 7505 null MX (\"0 .\") explicitly means \"no mail accepted\" and must be excluded.\n */\nfunction isRealMxRecord(data: string): boolean {\n\t// Null MX: priority 0, exchange \".\" — RFC 7505\n\tconst trimmed = data.trim();\n\treturn trimmed !== '0 .' && trimmed !== '0\\t.';\n}\n\n/**\n * Check a single lookalike domain for DNS and MX records.\n * Filters out null MX records (RFC 7505) to avoid false positives.\n */\nasync function probeLookalike(domain: string): Promise<LookalikeResult> {\n\tconst [aRecords, mxRecords] = await Promise.allSettled([\n\t\tqueryDnsRecords(domain, 'A'),\n\t\tqueryDnsRecords(domain, 'MX'),\n\t]);\n\n\tconst realMxRecords =\n\t\tmxRecords.status === 'fulfilled' ? mxRecords.value.filter(isRealMxRecord) : [];\n\n\treturn {\n\t\tdomain,\n\t\thasA: aRecords.status === 'fulfilled' && aRecords.value.length > 0,\n\t\thasMX: realMxRecords.length > 0,\n\t};\n}\n\n/**\n * Count the number of labels (dot-separated segments) in a domain.\n */\nfunction labelCount(domain: string): number {\n\treturn domain.split('.').length;\n}\n\n/**\n * Extract the parent domain from a dot-insertion permutation.\n * E.g., \"blackve.ilsecurity.com\" → \"ilsecurity.com\"\n */\nfunction getParentDomain(domain: string): string {\n\tconst parts = domain.split('.');\n\treturn parts.slice(1).join('.');\n}\n\n/**\n * Detect wildcard DNS on a set of parent domains by probing a canary subdomain.\n * Returns a Set of parent domains that have wildcard A records.\n */\nasync function detectWildcardParents(parentDomains: string[]): Promise<Set<string>> {\n\tconst wildcardParents = new Set<string>();\n\tconst probes = parentDomains.map(async (parent) => {\n\t\ttry {\n\t\t\tconst canary = `${WILDCARD_CANARY_LABEL}.${parent}`;\n\t\t\tconst records = await queryDnsRecords(canary, 'A');\n\t\t\tif (records.length > 0) {\n\t\t\t\twildcardParents.add(parent);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Query failed — not a wildcard\n\t\t}\n\t});\n\tawait Promise.allSettled(probes);\n\treturn wildcardParents;\n}\n\n/**\n * Phase 1: Fast NS existence check for all domains in parallel.\n * Returns only domains that have NS records (i.e., are registered),\n * along with their normalized NS record data for ownership comparison.\n */\nasync function filterByNsExistence(domains: string[]): Promise<{ registered: string[]; nsMap: Map<string, Set<string>> }> {\n\tconst nsMap = new Map<string, Set<string>>();\n\tconst results = await Promise.allSettled(\n\t\tdomains.map(async (domain) => {\n\t\t\tconst ns = await queryDnsRecords(domain, 'NS', PHASE1_DNS_OPTS);\n\t\t\tif (ns.length > 0) {\n\t\t\t\tnsMap.set(domain, normalizeNsSet(ns));\n\t\t\t}\n\t\t\treturn { domain, hasNs: ns.length > 0 };\n\t\t}),\n\t);\n\tconst registered = results\n\t\t.filter(\n\t\t\t(r): r is PromiseFulfilledResult<{ domain: string; hasNs: boolean }> =>\n\t\t\t\tr.status === 'fulfilled' && r.value.hasNs,\n\t\t)\n\t\t.map((r) => r.value.domain);\n\treturn { registered, nsMap };\n}\n\n/**\n * Normalize a set of NS record values for comparison.\n * Strips trailing dots, lowercases, and returns a Set.\n */\nfunction normalizeNsSet(nsRecords: string[]): Set<string> {\n\treturn new Set(nsRecords.map((ns) => ns.replace(/\\.$/, '').toLowerCase()));\n}\n\n/**\n * Check whether two NS sets share at least SHARED_NS_THRESHOLD nameservers.\n * Shared nameservers are a strong signal that both domains are controlled by the same entity.\n */\nfunction sharesNameservers(primaryNs: Set<string>, lookalikeNs: Set<string>): boolean {\n\tlet overlap = 0;\n\tfor (const ns of lookalikeNs) {\n\t\tif (primaryNs.has(ns)) {\n\t\t\toverlap++;\n\t\t\tif (overlap >= SHARED_NS_THRESHOLD) return true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Query NS records for the primary domain to use for ownership comparison.\n * Returns an empty set if the query fails.\n */\nasync function queryPrimaryNs(domain: string): Promise<Set<string>> {\n\ttry {\n\t\tconst ns = await queryDnsRecords(domain, 'NS', PHASE1_DNS_OPTS);\n\t\treturn normalizeNsSet(ns);\n\t} catch {\n\t\treturn new Set<string>();\n\t}\n}\n\n/**\n * Run permutation probes with adaptive batch sizing and backoff.\n * Starts at INITIAL_BATCH_SIZE, halves on repeated failures (floor at MIN_BATCH_SIZE),\n * recovers on clean batches.\n */\nasync function probeWithAdaptiveBatching(\n\tpermutations: string[],\n): Promise<PromiseSettledResult<LookalikeResult>[]> {\n\tconst allResults: PromiseSettledResult<LookalikeResult>[] = [];\n\tlet batchSize = INITIAL_BATCH_SIZE;\n\tlet delayMs = 0;\n\n\tfor (let i = 0; i < permutations.length; i += batchSize) {\n\t\tif (delayMs > 0) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, delayMs));\n\t\t}\n\n\t\tconst batch = permutations.slice(i, i + batchSize);\n\t\tconst batchResults = await Promise.allSettled(batch.map((d) => probeLookalike(d)));\n\t\tallResults.push(...batchResults);\n\n\t\t// Count failures in this batch\n\t\tconst failures = batchResults.filter((r) => r.status === 'rejected').length;\n\t\tif (failures > FAILURE_THRESHOLD) {\n\t\t\t// Back off: halve batch size (floor to MIN_BATCH_SIZE) and add delay\n\t\t\tbatchSize = Math.max(MIN_BATCH_SIZE, Math.floor(batchSize / 2));\n\t\t\tdelayMs = BACKOFF_DELAY_MS;\n\t\t} else if (delayMs > 0 && failures === 0) {\n\t\t\t// Recover: if a clean batch after backoff, try increasing again\n\t\t\tbatchSize = Math.min(INITIAL_BATCH_SIZE, batchSize + 2);\n\t\t\tdelayMs = 0;\n\t\t}\n\t}\n\n\treturn allResults;\n}\n\n/**\n * Detect registered lookalike/typosquat domains with DNS or mail infrastructure.\n * Generates domain permutations and checks for active registrations using adaptive batching.\n * Filters out false positives from wildcard DNS on parent domains and null MX records.\n */\nexport async function checkLookalikes(domain: string): Promise<CheckResult> {\n\treturn Promise.race([\n\t\tcheckLookalikesCore(domain),\n\t\tnew Promise<never>((_, reject) => setTimeout(() => reject(new Error('Lookalike check timed out')), LOOKALIKE_TIMEOUT_MS)),\n\t]).catch(() => {\n\t\treturn buildCheckResult('lookalikes', [\n\t\t\tcreateFinding(\n\t\t\t\t'lookalikes',\n\t\t\t\t'Lookalike check incomplete',\n\t\t\t\t'info',\n\t\t\t\t'Lookalike check did not complete. This check generates many DNS queries — try again shortly, as partial results are cached.',\n\t\t\t),\n\t\t]);\n\t});\n}\n\nasync function checkLookalikesCore(domain: string): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\tconst permutations = generateLookalikes(domain);\n\n\tif (permutations.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'lookalikes',\n\t\t\t\t'No active lookalike domains detected',\n\t\t\t\t'info',\n\t\t\t\t`No lookalike domain permutations could be generated for ${domain}.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('lookalikes', findings);\n\t}\n\n\t// Identify dot-insertion permutations (they have more labels than the original domain)\n\tconst originalLabelCount = labelCount(domain);\n\tconst dotInsertionParents = new Map<string, string[]>(); // parent → [permutations]\n\tconst nonDotInsertionPerms: string[] = [];\n\n\tfor (const perm of permutations) {\n\t\tif (labelCount(perm) > originalLabelCount) {\n\t\t\tconst parent = getParentDomain(perm);\n\t\t\tconst existing = dotInsertionParents.get(parent);\n\t\t\tif (existing) {\n\t\t\t\texisting.push(perm);\n\t\t\t} else {\n\t\t\t\tdotInsertionParents.set(parent, [perm]);\n\t\t\t}\n\t\t} else {\n\t\t\tnonDotInsertionPerms.push(perm);\n\t\t}\n\t}\n\n\t// Detect wildcard DNS on parent domains of dot-insertion permutations\n\tconst wildcardParents = dotInsertionParents.size > 0\n\t\t? await detectWildcardParents([...dotInsertionParents.keys()])\n\t\t: new Set<string>();\n\n\t// Filter out permutations whose parent has wildcard DNS\n\tconst filteredDotInsertionPerms: string[] = [];\n\tfor (const [parent, perms] of dotInsertionParents) {\n\t\tif (!wildcardParents.has(parent)) {\n\t\t\tfilteredDotInsertionPerms.push(...perms);\n\t\t}\n\t}\n\n\tconst permsToProbe = [...nonDotInsertionPerms, ...filteredDotInsertionPerms];\n\n\t// Phase 1: Fast NS existence check — filter out unregistered domains\n\t// Also query the primary domain's NS for ownership comparison\n\tconst [nsResult, primaryNs] = await Promise.all([\n\t\tfilterByNsExistence(permsToProbe),\n\t\tqueryPrimaryNs(domain),\n\t]);\n\tconst { registered: registeredPerms, nsMap: lookalikeNsMap } = nsResult;\n\n\tif (registeredPerms.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'lookalikes',\n\t\t\t\t'No active lookalike domains detected',\n\t\t\t\t'info',\n\t\t\t\t`Checked ${permutations.length} domain permutations of ${domain}. No active registrations detected.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('lookalikes', findings);\n\t}\n\n\t// Phase 2: Detail probe only registered domains\n\tconst probeResults = await probeWithAdaptiveBatching(registeredPerms);\n\tconst results: LookalikeResult[] = [];\n\tfor (const result of probeResults) {\n\t\tif (result.status === 'fulfilled') {\n\t\t\tresults.push(result.value);\n\t\t}\n\t}\n\n\t// Classify results — check for shared nameservers with primary domain to detect defensive registrations\n\tlet highCount = 0;\n\tfor (const result of results) {\n\t\tconst lookalikeNs = lookalikeNsMap.get(result.domain);\n\t\tconst sameOwner = primaryNs.size > 0 && lookalikeNs !== undefined && sharesNameservers(primaryNs, lookalikeNs);\n\n\t\tif (sameOwner) {\n\t\t\t// Shared nameservers — likely a defensive registration by the same entity\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'lookalikes',\n\t\t\t\t\t`Lookalike domain likely owned by same entity: ${result.domain}`,\n\t\t\t\t\t'info',\n\t\t\t\t\t`The domain ${result.domain} shares nameservers with ${domain}, indicating it is likely a defensive registration by the same owner.${result.hasMX ? ' Has active mail infrastructure.' : ''}${result.hasA ? ' Has web presence.' : ''}`,\n\t\t\t\t\t{ lookalikeDomain: result.domain, hasA: result.hasA, hasMX: result.hasMX, sharedNs: true },\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (result.hasMX) {\n\t\t\thighCount++;\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'lookalikes',\n\t\t\t\t\t`Lookalike domain with mail infrastructure: ${result.domain}`,\n\t\t\t\t\t'high',\n\t\t\t\t\t`The domain ${result.domain} is registered with active mail servers (MX records), which could be used for phishing or email spoofing targeting ${domain}.`,\n\t\t\t\t\t{ lookalikeDomain: result.domain, hasA: result.hasA, hasMX: result.hasMX },\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (result.hasA) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'lookalikes',\n\t\t\t\t\t`Lookalike domain registered: ${result.domain}`,\n\t\t\t\t\t'medium',\n\t\t\t\t\t`The domain ${result.domain} is registered (has web presence) but no mail infrastructure detected. It could still be used for phishing websites targeting ${domain}.`,\n\t\t\t\t\t{ lookalikeDomain: result.domain, hasA: result.hasA, hasMX: result.hasMX },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Summary finding for high-severity lookalikes\n\tif (highCount > 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'lookalikes',\n\t\t\t\t`${highCount} lookalike domain${highCount > 1 ? 's' : ''} with mail capability detected`,\n\t\t\t\t'high',\n\t\t\t\t`${highCount} lookalike domain${highCount > 1 ? 's' : ''} of ${domain} ${highCount > 1 ? 'have' : 'has'} active mail infrastructure, presenting a phishing risk. Consider monitoring these domains and implementing DMARC with p=reject to protect your brand.`,\n\t\t\t\t{ lookalikeDomainCount: highCount },\n\t\t\t),\n\t\t);\n\t}\n\n\t// If no active lookalikes found\n\tif (findings.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'lookalikes',\n\t\t\t\t'No active lookalike domains detected',\n\t\t\t\t'info',\n\t\t\t\t`Checked ${permutations.length} domain permutations of ${domain}. No active registrations with DNS or mail infrastructure detected.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('lookalikes', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * MTA-STS (Mail Transfer Agent Strict Transport Security) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkMTASTS } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\nimport { HTTPS_TIMEOUT_MS } from '../lib/config';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check MTA-STS configuration for a domain.\n * Queries _mta-sts.<domain> TXT records and optionally fetches the policy file.\n */\nexport async function checkMtaSts(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkMTASTS(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? HTTPS_TIMEOUT_MS, fetchFn: fetch },\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nexport interface ProviderSignature {\n\tname: string;\n\tdomains: string[];\n\tselectorHints?: string[];\n}\n\nexport interface ProviderSignaturePayload {\n\tversion?: string;\n\tinbound?: ProviderSignature[];\n\toutbound?: ProviderSignature[];\n}\n\nexport interface ProviderSourceResult {\n\tversion: string;\n\tsource: 'runtime' | 'stale' | 'built-in';\n\tfetchedAt: string;\n\tdegraded: boolean;\n\tinbound: ProviderSignature[];\n\toutbound: ProviderSignature[];\n}\n\nexport interface LoadProviderSignaturesOptions {\n\tsourceUrl?: string;\n\tallowedHosts?: string[];\n\texpectedSha256?: string;\n\ttimeoutMs?: number;\n\tretries?: number;\n}\n\nexport const DEFAULT_TIMEOUT_MS = 2500;\nexport const DEFAULT_RETRIES = 1;\nexport const RUNTIME_SIGNATURE_CACHE_TTL_MS = 5 * 60 * 1000;\n\nexport const BUILT_IN_SIGNATURES: ProviderSignaturePayload = {\n\tversion: 'built-in-2026-03-04',\n\tinbound: [\n\t\t{ name: 'Google Workspace', domains: ['google.com', 'googlemail.com'], selectorHints: ['google'] },\n\t\t{ name: 'Microsoft 365', domains: ['outlook.com', 'protection.outlook.com'], selectorHints: ['selector1', 'selector2'] },\n\t\t{ name: 'Proofpoint', domains: ['pphosted.com'] },\n\t\t{ name: 'Mimecast', domains: ['mimecast.com'], selectorHints: ['mimecast'] },\n\t\t{ name: 'Mailgun', domains: ['mailgun.org'] },\n\t\t{ name: 'SendGrid', domains: ['sendgrid.net'] },\n\t\t{ name: 'Amazon SES', domains: ['amazonses.com'] },\n\t],\n\toutbound: [],\n};\n\nexport function normalizeSha256(value: string): string {\n\treturn value.trim().toLowerCase().replace(/^sha256:/, '');\n}\n\nexport function normalizeAllowedHosts(input: string[] | undefined): string[] {\n\tif (!Array.isArray(input)) return [];\n\treturn input.map((host) => host.trim().toLowerCase()).filter((host) => host.length > 0);\n}\n\nexport function validateRuntimeSourceUrl(sourceUrl: string, allowedHosts: string[]): URL {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(sourceUrl);\n\t} catch {\n\t\tthrow new Error('Invalid provider signature source URL');\n\t}\n\n\tif (url.protocol !== 'https:') {\n\t\tthrow new Error('Invalid provider signature source URL: HTTPS is required');\n\t}\n\n\tif (allowedHosts.length > 0 && !allowedHosts.includes(url.hostname.toLowerCase())) {\n\t\tthrow new Error('Invalid provider signature source URL: host is not allowlisted');\n\t}\n\n\treturn url;\n}\n\nasync function sha256Hex(input: string): Promise<string> {\n\tconst digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(input));\n\treturn Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\nfunction normalizeDomain(value: string): string {\n\treturn value.trim().toLowerCase().replace(/\\.$/, '');\n}\n\nfunction normalizeProviderSignatures(input: ProviderSignature[] | undefined): ProviderSignature[] {\n\tif (!Array.isArray(input)) return [];\n\n\treturn input\n\t\t.map((provider) => {\n\t\t\tconst name = typeof provider?.name === 'string' ? provider.name.trim() : '';\n\t\t\tconst domains = Array.isArray(provider?.domains)\n\t\t\t\t? provider.domains.map((domain) => normalizeDomain(String(domain))).filter((domain) => domain.length > 0)\n\t\t\t\t: [];\n\t\t\tconst selectorHints = Array.isArray(provider?.selectorHints)\n\t\t\t\t? provider.selectorHints.map((selector) => String(selector).trim().toLowerCase()).filter((selector) => selector.length > 0)\n\t\t\t\t: [];\n\t\t\treturn { name, domains, ...(selectorHints.length > 0 ? { selectorHints } : {}) };\n\t\t})\n\t\t.filter((provider) => provider.name.length > 0 && provider.domains.length > 0);\n}\n\nexport function buildResult(\n\tpayload: ProviderSignaturePayload,\n\tsource: ProviderSourceResult['source'],\n\tdegraded: boolean,\n): ProviderSourceResult {\n\tconst inbound = normalizeProviderSignatures(payload.inbound);\n\tconst outbound = normalizeProviderSignatures(payload.outbound);\n\n\treturn {\n\t\tversion: payload.version?.trim() || BUILT_IN_SIGNATURES.version || 'unknown',\n\t\tsource,\n\t\tfetchedAt: new Date().toISOString(),\n\t\tdegraded,\n\t\tinbound,\n\t\toutbound,\n\t};\n}\n\nexport function isValidSignaturePayload(payload: unknown): payload is ProviderSignaturePayload {\n\tif (!payload || typeof payload !== 'object') return false;\n\tconst record = payload as Record<string, unknown>; // typeof payload === 'object' is checked above\n\tif (record.version !== undefined && typeof record.version !== 'string') return false;\n\tif (record.inbound !== undefined && !Array.isArray(record.inbound)) return false;\n\tif (record.outbound !== undefined && !Array.isArray(record.outbound)) return false;\n\treturn true;\n}\n\nexport async function fetchProviderPayload(\n\turl: string,\n\ttimeoutMs: number,\n\tretries: number,\n\texpectedSha256?: string,\n): Promise<ProviderSignaturePayload | null> {\n\tfor (let attempt = 0; attempt <= retries; attempt++) {\n\t\tconst controller = new AbortController();\n\t\tconst timeout = setTimeout(() => controller.abort(), timeoutMs);\n\t\ttry {\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tmethod: 'GET',\n\t\t\t\theaders: { Accept: 'application/json' },\n\t\t\t\tsignal: controller.signal,\n\t\t\t\tredirect: 'manual',\n\t\t\t});\n\t\t\tif (response.status >= 300 && response.status < 400) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (!response.ok) {\n\t\t\t\tif (attempt < retries && response.status >= 500) continue;\n\t\t\t\tthrow new Error(`Provider signature source returned HTTP ${response.status}`);\n\t\t\t}\n\n\t\t\tconst MAX_BODY_BYTES = 1_048_576; // 1 MB — provider signature JSON from pinned source\n\t\t\tconst contentLength = parseInt(response.headers?.get('content-length') ?? '0', 10);\n\t\t\tif (contentLength > MAX_BODY_BYTES) {\n\t\t\t\tthrow new Error(`Provider signature source exceeds ${MAX_BODY_BYTES} bytes (Content-Length: ${contentLength})`);\n\t\t\t}\n\t\t\tconst rawPayload = await response.text();\n\t\t\tif (rawPayload.length > MAX_BODY_BYTES) {\n\t\t\t\tthrow new Error(`Provider signature source exceeds ${MAX_BODY_BYTES} bytes`);\n\t\t\t}\n\t\t\tif (!expectedSha256) {\n\t\t\t\tthrow new Error('Provider signature source requires a pinned SHA-256 digest');\n\t\t\t}\n\n\t\t\tconst digest = await sha256Hex(rawPayload);\n\t\t\tif (digest !== normalizeSha256(expectedSha256)) {\n\t\t\t\tthrow new Error('Provider signature source failed SHA-256 verification');\n\t\t\t}\n\n\t\t\tconst payload = JSON.parse(rawPayload) as unknown;\n\t\t\tif (!isValidSignaturePayload(payload)) {\n\t\t\t\tthrow new Error('Provider signature source returned an invalid payload shape');\n\t\t\t}\n\n\t\t\treturn payload;\n\t\t} catch (error) {\n\t\t\tif (attempt < retries) continue;\n\t\t\tif (error instanceof DOMException && error.name === 'AbortError') {\n\t\t\t\tthrow new Error(`Provider signature source timed out after ${timeoutMs}ms`);\n\t\t\t}\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tclearTimeout(timeout);\n\t\t}\n\t}\n\n\tthrow new Error('Failed to load provider signatures');\n}","// SPDX-License-Identifier: BUSL-1.1\n\nimport {\n\tBUILT_IN_SIGNATURES,\n\tbuildResult,\n\tDEFAULT_RETRIES,\n\tDEFAULT_TIMEOUT_MS,\n\tfetchProviderPayload,\n\ttype LoadProviderSignaturesOptions,\n\tnormalizeAllowedHosts,\n\ttype ProviderSignature,\n\ttype ProviderSourceResult,\n\tRUNTIME_SIGNATURE_CACHE_TTL_MS,\n\tvalidateRuntimeSourceUrl,\n} from './provider-signature-source';\n\ninterface ProviderMatchEvidence {\n\tprovider: string;\n\tmatches: string[];\n}\n\nlet lastKnownGood: ProviderSourceResult | null = null;\nlet runtimeSignatureCache: {\n\tsourceUrl: string;\n\tresult: ProviderSourceResult;\n\texpiresAt: number;\n} | null = null;\n\nfunction normalizeDomain(value: string): string {\n\treturn value.trim().toLowerCase().replace(/\\.$/, '');\n}\n\nfunction boundarySuffixMatch(hostname: string, suffix: string): boolean {\n\tconst host = normalizeDomain(hostname);\n\tconst normalizedSuffix = normalizeDomain(suffix);\n\tif (!host || !normalizedSuffix) return false;\n\treturn host === normalizedSuffix || host.endsWith(`.${normalizedSuffix}`);\n}\n\n\nexport async function loadProviderSignatures(options?: LoadProviderSignaturesOptions): Promise<ProviderSourceResult> {\n\tconst timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\tconst retries = options?.retries ?? DEFAULT_RETRIES;\n\tconst sourceUrl = options?.sourceUrl?.trim();\n\tconst allowedHosts = normalizeAllowedHosts(options?.allowedHosts);\n\tconst expectedSha256 = options?.expectedSha256?.trim();\n\n\tif (!sourceUrl) {\n\t\treturn buildResult(BUILT_IN_SIGNATURES, 'built-in', false);\n\t}\n\n\tconst now = Date.now();\n\tif (runtimeSignatureCache && runtimeSignatureCache.sourceUrl === sourceUrl && runtimeSignatureCache.expiresAt > now) {\n\t\treturn runtimeSignatureCache.result;\n\t}\n\n\ttry {\n\t\tconst validatedUrl = validateRuntimeSourceUrl(sourceUrl, allowedHosts);\n\t\tconst payload = await fetchProviderPayload(validatedUrl.toString(), timeoutMs, retries, expectedSha256);\n\t\tif (!payload) {\n\t\t\tthrow new Error('Provider signature source returned a redirect');\n\t\t}\n\t\tconst result = buildResult(payload, 'runtime', false);\n\t\tlastKnownGood = result;\n\t\truntimeSignatureCache = {\n\t\t\tsourceUrl,\n\t\t\tresult,\n\t\t\texpiresAt: now + RUNTIME_SIGNATURE_CACHE_TTL_MS,\n\t\t};\n\t\treturn result;\n\t} catch {\n\t\tif (lastKnownGood) {\n\t\t\tconst staleResult = { ...lastKnownGood, source: 'stale' as const, degraded: true, fetchedAt: new Date().toISOString() };\n\t\t\truntimeSignatureCache = {\n\t\t\t\tsourceUrl,\n\t\t\t\tresult: staleResult,\n\t\t\t\texpiresAt: now + RUNTIME_SIGNATURE_CACHE_TTL_MS,\n\t\t\t};\n\t\t\treturn staleResult;\n\t\t}\n\t\tconst fallbackResult = buildResult(BUILT_IN_SIGNATURES, 'built-in', true);\n\t\truntimeSignatureCache = {\n\t\t\tsourceUrl,\n\t\t\tresult: fallbackResult,\n\t\t\texpiresAt: now + RUNTIME_SIGNATURE_CACHE_TTL_MS,\n\t\t};\n\t\treturn fallbackResult;\n\t}\n}\n\n/**\n * Test helper to reset provider signature loader state between cases.\n * @internal Exported for test use only.\n */\nexport function resetProviderSignatureState(): void {\n\tlastKnownGood = null;\n\truntimeSignatureCache = null;\n}\n\nexport function detectProviderMatches(hosts: string[], signatures: ProviderSignature[]): ProviderMatchEvidence[] {\n\tconst normalizedHosts = hosts.map((host) => normalizeDomain(host)).filter((host) => host.length > 0);\n\tconst matches: ProviderMatchEvidence[] = [];\n\n\tfor (const provider of signatures) {\n\t\tconst providerMatches = new Set<string>();\n\t\tfor (const host of normalizedHosts) {\n\t\t\tif (provider.domains.some((domain) => boundarySuffixMatch(host, domain))) {\n\t\t\t\tproviderMatches.add(host);\n\t\t\t}\n\t\t}\n\t\tif (providerMatches.size > 0) {\n\t\t\tmatches.push({ provider: provider.name, matches: Array.from(providerMatches) });\n\t\t}\n\t}\n\n\treturn matches;\n}\n\nexport function detectProviderMatchesBySelectors(selectors: string[], signatures: ProviderSignature[]): ProviderMatchEvidence[] {\n\tconst normalizedSelectors = selectors.map((selector) => selector.trim().toLowerCase()).filter((selector) => selector.length > 0);\n\tconst matches: ProviderMatchEvidence[] = [];\n\n\tfor (const provider of signatures) {\n\t\tconst hints = provider.selectorHints ?? [];\n\t\tif (hints.length === 0) continue;\n\n\t\tconst providerMatches = normalizedSelectors.filter((selector) => hints.includes(selector));\n\t\tif (providerMatches.length > 0) {\n\t\t\tmatches.push({ provider: provider.name, matches: Array.from(new Set(providerMatches)) });\n\t\t}\n\t}\n\n\treturn matches;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * MX record check tool for MCP server.\n * Thin wrapper around @blackveil/dns-checks — delegates core logic to the shared package.\n * Adds provider detection post-processing on top of the package result.\n */\n\nimport { checkMX, createFinding } from '@blackveil/dns-checks';\nimport type { CheckResult } from '../lib/scoring';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { detectProviderMatches, loadProviderSignatures } from '../lib/provider-signatures';\n\nexport interface CheckMxOptions {\n\tproviderSignaturesUrl?: string;\n\tproviderSignaturesAllowedHosts?: string[];\n\tproviderSignaturesSha256?: string;\n}\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/** Check MX record configuration for a domain */\nexport async function checkMx(domain: string, options?: CheckMxOptions, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tconst timeout = dnsOptions?.timeoutMs ?? 5000;\n\n\t// Run core MX check from shared package\n\tconst baseResult = await checkMX(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout },\n\t) as CheckResult;\n\n\t// Early return if MX check already returned critical/error findings (no MX records, etc.)\n\t// Only add provider detection when we have meaningful MX records\n\tconst hasCritical = baseResult.findings.some((f) => f.severity === 'critical');\n\tconst hasMediumQueryFailed = baseResult.findings.some((f) => f.title === 'DNS query failed');\n\tif (hasCritical || hasMediumQueryFailed) {\n\t\treturn baseResult;\n\t}\n\n\t// Provider detection post-processing\n\tconst findings = [...baseResult.findings];\n\n\ttry {\n\t\t// Re-query MX records to get raw strings for provider matching\n\t\tconst mxAnswers = await queryDnsRecords(domain, 'MX', dnsOptions);\n\t\tconst mxTargets = mxAnswers.map((answer) => {\n\t\t\tconst parts = answer.split(' ');\n\t\t\treturn (parts.slice(1).join(' ') || '').replace(/\\.$/, '').toLowerCase();\n\t\t}).filter(Boolean);\n\n\t\tif (mxTargets.length > 0) {\n\t\t\tconst providerSignatures = await loadProviderSignatures({\n\t\t\t\tsourceUrl: options?.providerSignaturesUrl,\n\t\t\t\tallowedHosts: options?.providerSignaturesAllowedHosts,\n\t\t\t\texpectedSha256: options?.providerSignaturesSha256,\n\t\t\t});\n\t\t\tconst inboundMatches = detectProviderMatches(mxTargets, providerSignatures.inbound);\n\n\t\t\tif (inboundMatches.length > 0) {\n\t\t\t\tconst providerNames = inboundMatches.map((m) => m.provider).join(', ');\n\t\t\t\tconst evidence = inboundMatches.map((m) => `${m.provider}: ${m.matches.join(', ')}`).join('; ');\n\t\t\t\tconst providerConfidence = providerSignatures.source === 'runtime' ? 0.95 : providerSignatures.source === 'stale' ? 0.75 : 0.7;\n\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding('mx', 'Managed email provider detected', 'info', `Inbound provider(s): ${providerNames}. Evidence: ${evidence}.`, {\n\t\t\t\t\t\tdetectionType: 'inbound',\n\t\t\t\t\t\tproviders: inboundMatches.map((m) => ({ name: m.provider, matches: m.matches })),\n\t\t\t\t\t\tproviderConfidence,\n\t\t\t\t\t\tsignatureSource: providerSignatures.source,\n\t\t\t\t\t\tsignatureVersion: providerSignatures.version,\n\t\t\t\t\t\tsignatureFetchedAt: providerSignatures.fetchedAt,\n\t\t\t\t\t}) as (typeof findings)[0],\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (providerSignatures.degraded) {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'mx',\n\t\t\t\t\t\t'Provider signature source unavailable',\n\t\t\t\t\t\t'info',\n\t\t\t\t\t\t`Provider detection used ${providerSignatures.source === 'stale' ? 'stale cached' : 'built-in fallback'} signatures.`,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdetectionType: 'inbound',\n\t\t\t\t\t\t\tproviderConfidence: providerSignatures.source === 'stale' ? 0.55 : 0.45,\n\t\t\t\t\t\t\tsignatureSource: providerSignatures.source,\n\t\t\t\t\t\t\tsignatureVersion: providerSignatures.version,\n\t\t\t\t\t\t\tsignatureFetchedAt: providerSignatures.fetchedAt,\n\t\t\t\t\t\t},\n\t\t\t\t\t) as (typeof findings)[0],\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Provider detection failure is non-critical — return base result\n\t}\n\n\treturn { ...baseResult, findings };\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * NS (Name Server) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkNS } from '@blackveil/dns-checks';\nimport { queryDns, queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check nameserver configuration for a domain.\n * Validates NS records exist, checks for diversity, and verifies responsiveness.\n */\nexport async function checkNs(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkNS(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{\n\t\t\ttimeout: dnsOptions?.timeoutMs ?? 5000,\n\t\t\trawQueryDNS: async (d, type, dnssecFlag) => {\n\t\t\t\tconst resp = await queryDns(d, type as Parameters<typeof queryDns>[1], dnssecFlag ?? false, dnsOptions);\n\t\t\t\treturn { AD: resp.AD, Answer: resp.Answer };\n\t\t\t},\n\t\t},\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * SPF (Sender Policy Framework) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkSPF } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\n/**\n * Build a DNSQueryFunction adapter that routes TXT queries through queryTxtRecords\n * (which strips surrounding quotes from DoH TXT data) and all other record types\n * through queryDnsRecords.\n */\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check SPF records for a domain.\n * Looks for v=spf1 TXT records and validates their configuration.\n * Recursively expands include chains to compute true DNS lookup count.\n */\nexport async function checkSpf(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkSPF(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? 5000 },\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * SSL/TLS certificate check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkSSL } from '@blackveil/dns-checks';\nimport type { CheckResult } from '../lib/scoring';\nimport { HTTPS_TIMEOUT_MS } from '../lib/config';\n\n/**\n * Check SSL/TLS configuration for a domain.\n * Validates HTTPS connectivity, HSTS headers, and HTTP→HTTPS redirect.\n */\nexport async function checkSsl(domain: string): Promise<CheckResult> {\n\treturn checkSSL(domain, fetch, { timeout: HTTPS_TIMEOUT_MS }) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Subdomain Takeover / Dangling CNAME Detection Tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkSubdomainTakeover as checkSubdomainTakeoverPkg } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\nimport { HTTPS_TIMEOUT_MS } from '../lib/config';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check for dangling CNAME records on known/active subdomains.\n * Flags orphaned records and potential takeover vectors.\n */\nexport async function checkSubdomainTakeover(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkSubdomainTakeoverPkg(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? HTTPS_TIMEOUT_MS, fetchFn: fetch },\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * TLS-RPT (SMTP TLS Reporting) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkTLSRPT } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check TLS-RPT records for a domain.\n * Validates the presence and configuration of SMTP TLS Reporting records.\n */\nexport async function checkTlsrpt(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkTLSRPT(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? 5000 },\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { sanitizeInput } from './sanitize';\n\nconst MARKDOWN_SYNTAX = /[`*_#[\\]()>|<]/g;\n\n/**\n * Characters that can inject HTML or dangerous markdown constructs.\n * Excludes `_` (common in DNS names like `_dmarc`, `_mta-sts`) and\n * `()` (used in natural-language detail text) which are safe in finding details.\n */\nconst DNS_DATA_UNSAFE = /[`*#[\\]>|<]/g;\n\n/**\n * Sanitize DNS-sourced data before it enters finding detail strings.\n * Strips C0 control characters (preserving tab/newline), replaces HTML/markdown\n * injection characters, but does NOT truncate — DNS data in findings can be\n * longer than display output.\n */\nexport function sanitizeDnsData(input: string): string {\n\treturn input\n\t\t.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]/g, '')\n\t\t.replace(DNS_DATA_UNSAFE, ' ')\n\t\t.replace(/\\s+/g, ' ')\n\t\t.trim();\n}\n\nexport function sanitizeOutputText(input: string, maxLength = 240): string {\n\tconst trimmed = sanitizeInput(input, maxLength * 2)\n\t\t.replace(/\\x1b\\[[0-9;]*[a-zA-Z]/g, '')\n\t\t.replace(MARKDOWN_SYNTAX, ' ')\n\t\t.replace(/\\s+/g, ' ')\n\t\t.trim();\n\n\tif (trimmed.length <= maxLength) {\n\t\treturn trimmed;\n\t}\n\n\treturn `${trimmed.slice(0, maxLength - 3).trimEnd()}...`;\n}","export interface ExplanationTemplate {\n\ttitle: string;\n\tseverity: string;\n\texplanation: string;\n\timpact?: string;\n\tadverseConsequences?: string;\n\trecommendation: string;\n\treferences: string[];\n}\n\nexport interface ImpactNarrative {\n\timpact?: string;\n\tadverseConsequences?: string;\n}\n\nexport interface SpecificImpactRule extends ImpactNarrative {\n\tcheckType?: string;\n\ttitleIncludes?: string[];\n\tdetailIncludes?: string[];\n}\n\nexport const EXPLANATIONS: Record<string, ExplanationTemplate> = {\n\tSUBDOMAIN_TAKEOVER_CRITICAL: {\n\t\ttitle: 'Dangling CNAME — Subdomain Takeover Risk',\n\t\tseverity: 'critical',\n\t\texplanation:\n\t\t\t'A subdomain points to a third-party service (e.g., CloudFront, Heroku) that does not resolve. This is a potential subdomain takeover vector, allowing attackers to claim the orphaned resource and control the subdomain.',\n\t\timpact: 'Attackers may host malicious content or capture traffic on a trusted subdomain, enabling phishing and session abuse.',\n\t\tadverseConsequences:\n\t\t\t'Brand trust can be damaged, users can be redirected to attacker infrastructure, and incident response costs can increase.',\n\t\trecommendation: 'Remove or update the CNAME record to point to a valid, owned resource. Regularly audit DNS for orphaned records.',\n\t\treferences: [\n\t\t\t'https://github.com/EdOverflow/can-i-take-over-xyz',\n\t\t\t'https://www.hackerone.com/blog/Guide-Subdomain-Takeover',\n\t\t\t'https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html',\n\t\t],\n\t},\n\tSUBDOMAIN_TAKEOVER_HIGH: {\n\t\ttitle: 'CNAME Resolution Failed — Manual Review Needed',\n\t\tseverity: 'high',\n\t\texplanation:\n\t\t\t'A subdomain CNAME points to a third-party service but the target could not be resolved. This may indicate a takeover risk or DNS misconfiguration.',\n\t\timpact: 'If the target is orphaned, an attacker may be able to claim it and gain control of the affected subdomain.',\n\t\tadverseConsequences: 'Users may be exposed to fraudulent pages and the organization may face reputation damage until DNS is remediated.',\n\t\trecommendation: 'Manually review the CNAME target and remove or update if orphaned. Use DNS monitoring tools for ongoing checks.',\n\t\treferences: [\n\t\t\t'https://github.com/EdOverflow/can-i-take-over-xyz',\n\t\t\t'https://www.hackerone.com/blog/Guide-Subdomain-Takeover',\n\t\t],\n\t},\n\tSUBDOMAIN_TAKEOVER_INFO: {\n\t\ttitle: 'No Dangling CNAME Records Found',\n\t\tseverity: 'info',\n\t\texplanation: 'No subdomain takeover vectors detected among known/active subdomains. DNS configuration is secure for this check.',\n\t\trecommendation: 'Continue regular DNS audits and monitoring for new subdomains or changes.',\n\t\treferences: ['https://github.com/EdOverflow/can-i-take-over-xyz'],\n\t},\n\tSPF_PASS: {\n\t\ttitle: 'SPF Validated',\n\t\tseverity: 'pass',\n\t\texplanation:\n\t\t\t'SPF (Sender Policy Framework) is properly configured. The domain specifies which mail servers are authorized to send email on its behalf.',\n\t\trecommendation: 'Maintain your current SPF configuration. Ensure you update it when adding new email sending sources.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7208'],\n\t},\n\tSPF_FAIL: {\n\t\ttitle: 'SPF Validation Failed',\n\t\tseverity: 'fail',\n\t\texplanation: 'SPF validation failed - emails from this domain are being rejected because the sending server is not authorized.',\n\t\timpact: 'Email authentication becomes unreliable, and spoofed or misrouted messages may evade expected controls.',\n\t\tadverseConsequences:\n\t\t\t'Legitimate email delivery can degrade, while impersonation attempts can increase helpdesk and abuse handling load.',\n\t\trecommendation:\n\t\t\t'Review your SPF record and ensure all legitimate email sources are included. Common issue: using -all but missing include statements.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7208', 'https://www.cloudflare.com/learning/dns/dns-records/dns-spf-record/'],\n\t},\n\tSPF_WARNING: {\n\t\ttitle: 'SPF Soft Fail',\n\t\tseverity: 'warning',\n\t\texplanation: 'SPF uses a soft fail (~all) policy. Emails that fail SPF will be accepted but may be flagged as suspicious.',\n\t\timpact: 'Failing SPF messages are often still accepted, so spoofed mail may continue reaching recipients.',\n\t\tadverseConsequences: 'Phishing risk remains elevated and security teams may need to manually triage suspicious mail.',\n\t\trecommendation: 'Upgrade to hard fail (-all) after verifying all legitimate sources are in your SPF record.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7208#section-8.1'],\n\t},\n\tSPF_MISSING: {\n\t\ttitle: 'No SPF Record Found',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t'SPF (Sender Policy Framework) is a DNS TXT record that specifies which mail servers are authorized to send email on behalf of your domain. Without SPF, any server can send email pretending to be from your domain.',\n\t\timpact: 'Any internet host can attempt to send email as your domain, making sender impersonation significantly easier.',\n\t\tadverseConsequences: 'Spoofing and phishing campaigns can harm brand trust, increase abuse complaints, and impair deliverability.',\n\t\trecommendation: \"Add a TXT record to your domain's DNS with a valid SPF policy. Start with: v=spf1 include:<your-email-provider> -all\",\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7208', 'https://www.cloudflare.com/learning/dns/dns-records/dns-spf-record/'],\n\t},\n\tDMARC_PASS: {\n\t\ttitle: 'DMARC Policy Validated',\n\t\tseverity: 'pass',\n\t\texplanation:\n\t\t\t'DMARC (Domain-based Message Authentication, Reporting & Conformance) is properly configured with a policy that provides protection against email spoofing.',\n\t\trecommendation:\n\t\t\t'Monitor your DMARC reports to ensure legitimate email is not being blocked. Consider enabling reject policy for stronger protection.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7489'],\n\t},\n\tDMARC_FAIL: {\n\t\ttitle: 'No DMARC Record Found',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t'DMARC builds on SPF and DKIM to provide email authentication policy. Without DMARC, receivers have no policy guidance for handling authentication failures.',\n\t\timpact: 'Receiving systems cannot consistently quarantine or reject forged messages that fail authentication.',\n\t\tadverseConsequences: 'Domain spoofing can reach inboxes more often, increasing phishing exposure and reputational damage.',\n\t\trecommendation: 'Add a TXT record at _dmarc.<domain> with at minimum: v=DMARC1; p=quarantine; rua=mailto:dmarc@<domain>',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7489', 'https://www.cloudflare.com/learning/dns/dns-records/dns-dmarc-record/'],\n\t},\n\tDMARC_WARNING: {\n\t\ttitle: 'DMARC Policy Not Enforcing',\n\t\tseverity: 'warning',\n\t\texplanation: \"DMARC policy is set to 'none' (monitoring only) or 'quarantine'. This provides limited protection against spoofing.\",\n\t\timpact: 'Authentication failures may not be fully blocked, allowing some malicious mail to be delivered.',\n\t\tadverseConsequences: 'Attackers can still impersonate the domain in recipient inboxes, leading to fraud and support overhead.',\n\t\trecommendation: \"After reviewing DMARC reports, upgrade the policy to 'reject' to actively protect against email spoofing.\",\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7489#section-6.3'],\n\t},\n\tDKIM_PASS: {\n\t\ttitle: 'DKIM Validated',\n\t\tseverity: 'pass',\n\t\texplanation:\n\t\t\t'DKIM (DomainKeys Identified Mail) is properly configured. Outgoing emails are digitally signed and can be verified by receivers.',\n\t\trecommendation: 'Maintain your DKIM configuration. Rotate keys periodically as per your security policy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc6376'],\n\t},\n\tDKIM_FAIL: {\n\t\ttitle: 'No DKIM Records Found',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t\"DKIM adds a digital signature to outgoing emails, allowing receivers to verify the email was sent by an authorized server and wasn't modified in transit.\",\n\t\timpact: 'Receivers lose a key authenticity signal, which weakens anti-spoofing and anti-tampering protections.',\n\t\tadverseConsequences:\n\t\t\t'Legitimate email may be distrusted while fraudulent messages are harder to distinguish, hurting deliverability and trust.',\n\t\trecommendation: 'Configure DKIM signing with your email provider. They will provide the DKIM DNS records to publish.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc6376', 'https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/'],\n\t},\n\tDNSSEC_PASS: {\n\t\ttitle: 'DNSSEC Enabled',\n\t\tseverity: 'pass',\n\t\texplanation:\n\t\t\t'DNSSEC is properly configured with valid cryptographic signatures. This protects against DNS spoofing and cache poisoning attacks.',\n\t\trecommendation: 'Maintain your DNSSEC configuration. Monitor for any validation failures in your logs.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc4033'],\n\t},\n\tDNSSEC_FAIL: {\n\t\ttitle: 'DNSSEC Not Validated',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t\"DNSSEC adds cryptographic signatures to DNS records, preventing DNS spoofing and cache poisoning attacks. Without DNSSEC, attackers can redirect your domain's traffic.\",\n\t\timpact: 'DNS responses can be forged in transit, enabling redirection to attacker-controlled infrastructure.',\n\t\tadverseConsequences: 'Users may be sent to malicious destinations, causing credential theft, service disruption, and incident response costs.',\n\t\trecommendation: 'Enable DNSSEC through your domain registrar and DNS provider. Most providers offer one-click DNSSEC activation.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc4033', 'https://www.cloudflare.com/dns/dnssec/how-dnssec-works/'],\n\t},\n\tSSL_PASS: {\n\t\ttitle: 'SSL/TLS Validated',\n\t\tseverity: 'pass',\n\t\texplanation: 'The domain properly serves content over HTTPS with a valid certificate.',\n\t\trecommendation: 'Maintain your SSL certificate. Consider implementing HSTS for additional security.',\n\t\treferences: ['https://https.cio.gov/hsts/'],\n\t},\n\tSSL_FAIL: {\n\t\ttitle: 'HTTPS Not Available',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t'The domain does not have a valid SSL/TLS certificate or the HTTPS server is not responding. This means traffic to the domain is not encrypted.',\n\t\timpact: 'Network attackers can intercept or tamper with data exchanged between users and the site.',\n\t\tadverseConsequences: 'Credentials and sensitive data may be exposed, and browser trust warnings can reduce conversion and user confidence.',\n\t\trecommendation: \"Install a valid SSL/TLS certificate. Free certificates are available from Let's Encrypt or Cloudflare.\",\n\t\treferences: ['https://letsencrypt.org/', 'https://www.cloudflare.com/ssl/'],\n\t},\n\tSSL_WARNING: {\n\t\ttitle: 'Mixed Content or Redirect Issues',\n\t\tseverity: 'warning',\n\t\texplanation: 'HTTPS is available but there may be issues with redirects or mixed content.',\n\t\timpact: 'Some resources may still load insecurely, creating opportunities for content manipulation or privacy leakage.',\n\t\tadverseConsequences: 'User sessions and page integrity can be weakened, and security posture may fail audit expectations.',\n\t\trecommendation: 'Ensure all resources load over HTTPS and implement proper redirects from HTTP to HTTPS.',\n\t\treferences: ['https://www.cloudflare.com/ssl/'],\n\t},\n\tSSL_MEDIUM: {\n\t\ttitle: 'HSTS or Redirect Issues',\n\t\tseverity: 'medium',\n\t\texplanation:\n\t\t\t'HTTPS is available but the domain is missing HSTS (Strict-Transport-Security) headers or does not redirect HTTP to HTTPS. Without HSTS, browsers may still attempt insecure connections.',\n\t\timpact: 'Clients may be downgraded to insecure HTTP connections, especially on first visit or hostile networks.',\n\t\tadverseConsequences: 'Session data can be exposed in transit and users remain vulnerable to downgrade or interception attacks.',\n\t\trecommendation:\n\t\t\t'Add a Strict-Transport-Security header with max-age of at least 1 year (31536000). Configure your web server to redirect all HTTP requests to HTTPS.',\n\t\treferences: ['https://https.cio.gov/hsts/', 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security'],\n\t},\n\tSSL_LOW: {\n\t\ttitle: 'HSTS Configuration Suboptimal',\n\t\tseverity: 'low',\n\t\texplanation:\n\t\t\t'HSTS is configured but could be improved. Common issues include a short max-age value or missing includeSubDomains directive.',\n\t\timpact: 'Partial HSTS coverage leaves windows where transport security guarantees are weaker than expected.',\n\t\tadverseConsequences: 'Subdomains or returning sessions may still face avoidable downgrade exposure and policy non-compliance findings.',\n\t\trecommendation:\n\t\t\t'Set max-age to at least 31536000 (1 year) and include the includeSubDomains directive. Consider adding your domain to the HSTS preload list.',\n\t\treferences: [\n\t\t\t'https://hstspreload.org/',\n\t\t\t'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security',\n\t\t],\n\t},\n\tMTA_STS_PASS: {\n\t\ttitle: 'MTA-STS Enabled',\n\t\tseverity: 'pass',\n\t\texplanation: 'MTA-STS (Mail Transfer Agent Strict Transport Security) is properly configured and enforces TLS for incoming email.',\n\t\trecommendation: 'Monitor your MTA-STS reports to ensure legitimate mail servers can deliver successfully.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc8461'],\n\t},\n\tMTA_STS_FAIL: {\n\t\ttitle: 'No MTA-STS Record Found',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t'MTA-STS enforces TLS encryption for incoming email, preventing downgrade attacks where an attacker forces email to be sent unencrypted.',\n\t\timpact: 'Inbound SMTP sessions are more susceptible to TLS downgrade and interception attempts.',\n\t\tadverseConsequences: 'Sensitive email content can be exposed in transit, raising confidentiality and compliance risks.',\n\t\trecommendation:\n\t\t\t'Publish an MTA-STS TXT record at _mta-sts.<domain> and host a policy file at https://mta-sts.<domain>/.well-known/mta-sts.txt',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc8461'],\n\t},\n\tMTA_STS_WARNING: {\n\t\ttitle: 'MTA-STS in Testing Mode',\n\t\tseverity: 'warning',\n\t\texplanation: 'MTA-STS is configured but in testing mode (mode=testing) rather than enforcement mode.',\n\t\timpact: 'Delivery behavior is monitored but not enforced, so some insecure transport paths may still be accepted.',\n\t\tadverseConsequences: 'Security gaps can persist longer and confidentiality controls for inbound mail remain partially effective.',\n\t\trecommendation: 'After verifying all mail servers can successfully deliver over TLS, upgrade to mode=enforce.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc8461'],\n\t},\n\tNS_PASS: {\n\t\ttitle: 'Nameservers Validated',\n\t\tseverity: 'pass',\n\t\texplanation: 'The domain has properly configured nameservers that are responding to queries.',\n\t\trecommendation: 'Maintain your current nameserver configuration. Use at least two geographically distributed nameservers for redundancy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc1035'],\n\t},\n\tNS_FAIL: {\n\t\ttitle: 'Nameserver Issues Detected',\n\t\tseverity: 'fail',\n\t\texplanation: 'One or more nameservers for this domain are not responding or are misconfigured, which can cause DNS resolution failures.',\n\t\timpact: 'Resolvers may fail to resolve the domain, degrading access to web, API, and mail services.',\n\t\tadverseConsequences: 'Users can experience outages, failed transactions, and business continuity disruptions.',\n\t\trecommendation: 'Verify all listed nameservers are operational and properly configured. Ensure NS records match those at the registrar.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc1035', 'https://www.cloudflare.com/learning/dns/dns-records/dns-ns-record/'],\n\t},\n\tNS_WARNING: {\n\t\ttitle: 'Nameserver Configuration Suboptimal',\n\t\tseverity: 'warning',\n\t\texplanation: 'Nameservers are functional but the configuration could be improved for better reliability or security.',\n\t\timpact: 'Single points of failure or weak diversity can reduce DNS resilience during provider or network incidents.',\n\t\tadverseConsequences: 'Availability and latency can degrade under stress, increasing user-facing instability.',\n\t\trecommendation: 'Consider adding additional nameservers for redundancy and ensuring they are geographically distributed.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc1035'],\n\t},\n\tCAA_PASS: {\n\t\ttitle: 'CAA Records Configured',\n\t\tseverity: 'pass',\n\t\texplanation: 'CAA (Certificate Authority Authorization) records are properly configured, restricting which CAs can issue certificates for this domain.',\n\t\trecommendation: 'Maintain your CAA records. Review periodically to ensure they reflect your current certificate issuance needs.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc8659'],\n\t},\n\tCAA_FAIL: {\n\t\ttitle: 'No CAA Records Found',\n\t\tseverity: 'fail',\n\t\texplanation: 'No CAA records are present for this domain. Without CAA, any certificate authority can issue certificates for your domain.',\n\t\timpact: 'Certificate issuance controls are broad, increasing the chance of unauthorized or misissued certificates.',\n\t\tadverseConsequences: 'Attackers may abuse misissuance for impersonation and interception, with trust and compliance implications.',\n\t\trecommendation: 'Add CAA DNS records to restrict certificate issuance to your authorized CAs (e.g., \"0 issue letsencrypt.org\").',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc8659', 'https://www.cloudflare.com/learning/dns/dns-records/dns-caa-record/'],\n\t},\n\tCAA_WARNING: {\n\t\ttitle: 'CAA Configuration Incomplete',\n\t\tseverity: 'warning',\n\t\texplanation: 'CAA records exist but may not fully restrict certificate issuance. Consider adding iodef or wildcard policies.',\n\t\timpact: 'Incomplete CAA policy can leave gaps in issuance constraints for wildcard or incident-reporting scenarios.',\n\t\tadverseConsequences: 'Certificate governance may be weaker than intended, increasing operational and audit risk.',\n\t\trecommendation: 'Review your CAA records and add an iodef tag for incident reporting. Consider restricting wildcard certificate issuance separately.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc8659'],\n\t},\n\tMX_PASS: {\n\t\ttitle: 'MX Records Validated',\n\t\tseverity: 'pass',\n\t\texplanation: 'MX (Mail Exchange) records are properly configured, directing email to the correct mail servers.',\n\t\trecommendation: 'Maintain your MX records. Ensure backup MX entries exist for redundancy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321'],\n\t},\n\tMX_FAIL: {\n\t\ttitle: 'No MX Records Found',\n\t\tseverity: 'fail',\n\t\texplanation: 'No MX records are present for this domain. Without MX records, email delivery to this domain will fail or fall back to A record delivery.',\n\t\timpact: 'Mail routing is unreliable or unavailable for intended recipients on this domain.',\n\t\tadverseConsequences: 'Inbound communications may be lost, causing business disruption and missed security notifications.',\n\t\trecommendation: 'Add MX records pointing to your mail server. If this domain does not handle email, consider adding a null MX record (0 .).',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321', 'https://datatracker.ietf.org/doc/html/rfc7505'],\n\t},\n\tMX_WARNING: {\n\t\ttitle: 'MX Configuration Suboptimal',\n\t\tseverity: 'warning',\n\t\texplanation: 'MX records exist but the configuration could be improved, such as missing backup MX or unusual priority values.',\n\t\timpact: 'Mail delivery reliability is reduced during server failures or routing anomalies.',\n\t\tadverseConsequences: 'Message delays and intermittent delivery failures can affect operations and customer support.',\n\t\trecommendation: 'Review MX priorities and add at least one backup MX record for redundancy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321'],\n\t},\n\tMX_INFO: {\n\t\ttitle: 'MX Records Present',\n\t\tseverity: 'info',\n\t\texplanation: 'Mail exchange records are properly configured for this domain.',\n\t\trecommendation: 'No action required. Ensure backup MX records exist for redundancy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321'],\n\t},\n\tMX_LOW: {\n\t\ttitle: 'MX Configuration Could Be Improved',\n\t\tseverity: 'low',\n\t\texplanation: 'MX records are present but the configuration has minor issues such as missing backup MX records.',\n\t\timpact: 'Resilience to mail infrastructure outages is lower than recommended.',\n\t\tadverseConsequences: 'Short outages can become user-visible delivery delays and increase operational toil.',\n\t\trecommendation: 'Add at least one backup MX record with a different priority for redundancy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321'],\n\t},\n\tMX_HIGH: {\n\t\ttitle: 'MX Configuration Error',\n\t\tseverity: 'medium',\n\t\texplanation:\n\t\t\t'MX records have a configuration error such as pointing to an IP address instead of a hostname (violating RFC 5321) or referencing a hostname that does not resolve to any address record.',\n\t\timpact: 'Standards-incompatible or unresolvable MX targets can cause mail rejection or routing failures across sending systems.',\n\t\tadverseConsequences: 'Business-critical messages may bounce, delaying incident response and external communication.',\n\t\trecommendation:\n\t\t\t'Update MX records to point to valid hostnames, not IP addresses. Ensure all MX targets resolve to valid A/AAAA records.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321'],\n\t},\n\tMX_MEDIUM: {\n\t\ttitle: 'No MX Records Found',\n\t\tseverity: 'medium',\n\t\texplanation:\n\t\t\t'No MX records are present for this domain. Email delivery will fall back to A record delivery or fail entirely.',\n\t\timpact: 'Email reception may fail or behave inconsistently depending on sender fallback behavior.',\n\t\tadverseConsequences: 'Organizations may miss customer, partner, or security messages, creating operational and reputational risk.',\n\t\trecommendation:\n\t\t\t'If this domain should receive email, add MX records. If not, publish a null MX record per RFC 7505 to explicitly declare that.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321', 'https://datatracker.ietf.org/doc/html/rfc7505'],\n\t},\n\tDANE_HTTPS_PASS: {\n\t\ttitle: 'DANE TLSA Configured for HTTPS',\n\t\tseverity: 'pass',\n\t\texplanation:\n\t\t\t'TLSA records at _443._tcp.{domain} pin the web server certificate to DNS, providing an additional layer of TLS trust beyond the CA system. Combined with DNSSEC, this prevents unauthorized CAs from issuing fraudulent certificates for the domain.',\n\t\trecommendation: 'Maintain your DANE HTTPS configuration. Ensure TLSA records are updated whenever TLS certificates are renewed.',\n\t\treferences: [\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc6698',\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc7671',\n\t\t],\n\t},\n\tDANE_HTTPS_FAIL: {\n\t\ttitle: 'No DANE TLSA for HTTPS',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t'No TLSA records were found at _443._tcp.{domain}. DANE certificate pinning for HTTPS provides an additional trust anchor beyond the CA system, preventing unauthorized certificate issuance attacks.',\n\t\timpact: 'Certificate issuance for this domain relies solely on the CA trust hierarchy.',\n\t\tadverseConsequences:\n\t\t\t'A compromised or rogue CA can issue a valid certificate for the domain, enabling MITM attacks that bypass standard browser trust checks.',\n\t\trecommendation:\n\t\t\t'Implement DANE-EE (usage 3) TLSA records at _443._tcp.{domain} and ensure DNSSEC is enabled. Use SHA-256 (matching type 1) or SHA-512 (matching type 2) for the certificate data hash.',\n\t\treferences: [\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc6698',\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc7671',\n\t\t],\n\t},\n\tDANE_HTTPS_WARNING: {\n\t\ttitle: 'DANE HTTPS Configuration Warning',\n\t\tseverity: 'warning',\n\t\texplanation:\n\t\t\t'DANE TLSA records exist for the HTTPS endpoint but the configuration has issues that reduce their security value, such as DANE without DNSSEC or weak matching types.',\n\t\timpact: 'DANE protection is partially effective but can be bypassed or subverted.',\n\t\tadverseConsequences:\n\t\t\t'Attackers may be able to spoof or modify TLSA records if DNSSEC is absent, negating the security benefit of DANE.',\n\t\trecommendation:\n\t\t\t'Enable DNSSEC on the domain and use DANE-EE (usage 3) with SHA-256 matching (type 1) for best security.',\n\t\treferences: [\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc6698',\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc7671',\n\t\t],\n\t},\n\tDANE_HTTPS_INFO: {\n\t\ttitle: 'DANE HTTPS Record Present',\n\t\tseverity: 'info',\n\t\texplanation: 'A TLSA record is configured at _443._tcp.{domain}, enabling DANE certificate pinning for HTTPS.',\n\t\trecommendation: 'Keep TLSA records synchronized with your TLS certificate. Automate renewal if possible.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc6698'],\n\t},\n\tSVCB_HTTPS_PASS: {\n\t\ttitle: 'HTTPS Record Configured',\n\t\tseverity: 'pass',\n\t\texplanation:\n\t\t\t'HTTPS/SVCB records (RFC 9460) are present and advertise modern transport capabilities. This enables clients to negotiate HTTP/2 or HTTP/3 without an initial redirect and optionally distributes ECH parameters for privacy.',\n\t\trecommendation: 'Maintain your HTTPS records. Consider enabling ECH for enhanced connection privacy.',\n\t\treferences: [\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc9460',\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc8446',\n\t\t],\n\t},\n\tSVCB_HTTPS_FAIL: {\n\t\ttitle: 'No HTTPS Record Found',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t'No HTTPS record (type 65, RFC 9460) was found for this domain. HTTPS records advertise modern transport capabilities (ALPN, ECH) and allow clients to connect securely and efficiently without an initial redirect round-trip.',\n\t\timpact: 'Clients cannot discover HTTP/2 or HTTP/3 support via DNS, requiring an additional round-trip.',\n\t\tadverseConsequences:\n\t\t\t'Connection setup is slower, privacy from ECH is unavailable, and the domain misses opportunities for TLS optimization.',\n\t\trecommendation:\n\t\t\t'Publish an HTTPS record with at minimum alpn=\"h2,h3\" to enable HTTP/2 and HTTP/3 advertisement. If using Cloudflare or similar CDN, this may be automatically managed.',\n\t\treferences: [\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc9460',\n\t\t\t'https://blog.cloudflare.com/speeding-up-https-and-http-3-negotiation-with-dns/',\n\t\t],\n\t},\n\tSVCB_HTTPS_WARNING: {\n\t\ttitle: 'HTTPS Record Configuration Warning',\n\t\tseverity: 'warning',\n\t\texplanation:\n\t\t\t'HTTPS records are present but the configuration is suboptimal — for example, no ALPN parameters or missing HTTP/2 support.',\n\t\timpact: 'Clients cannot fully leverage the capabilities advertised in the HTTPS record.',\n\t\tadverseConsequences:\n\t\t\t'Performance benefits from SVCB are partially lost and ECH privacy may be unavailable.',\n\t\trecommendation:\n\t\t\t'Update HTTPS records to include alpn=\"h2,h3\" and consider adding ECH parameters. Ensure alias mode targets also have valid HTTPS records.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc9460'],\n\t},\n\tSVCB_HTTPS_INFO: {\n\t\ttitle: 'HTTPS Record Present',\n\t\tseverity: 'info',\n\t\texplanation: 'An HTTPS/SVCB record is configured, advertising modern connection capabilities for this domain.',\n\t\trecommendation: 'No action required. Consider adding ECH for enhanced privacy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc9460'],\n\t},\n};\n\nexport const DEFAULT_EXPLANATION: ExplanationTemplate = {\n\ttitle: 'Security Check Complete',\n\tseverity: 'info',\n\texplanation: \"This check has been completed. Review the findings above for details on your domain's security posture.\",\n\trecommendation: 'Refer to the specific check documentation for detailed remediation steps.',\n\treferences: ['https://www.cloudflare.com/learning/dns/what-is-dns/'],\n};\n\nexport const CATEGORY_TO_CHECKTYPE: Record<string, string> = {\n\tspf: 'SPF',\n\tdmarc: 'DMARC',\n\tdkim: 'DKIM',\n\tdnssec: 'DNSSEC',\n\tssl: 'SSL',\n\tmta_sts: 'MTA_STS',\n\tns: 'NS',\n\tcaa: 'CAA',\n\tmx: 'MX',\n\tsubdomain_takeover: 'SUBDOMAIN_TAKEOVER',\n\tdane_https: 'DANE_HTTPS',\n\tsvcb_https: 'SVCB_HTTPS',\n};\n\nexport const CATEGORY_FALLBACK_IMPACT: Record<string, ImpactNarrative> = {\n\tSPF: {\n\t\timpact: 'SPF coverage is weak, so unauthorized senders can spoof domain identity more easily.',\n\t\tadverseConsequences: 'Phishing attempts and deliverability disputes increase security and support workload.',\n\t},\n\tDMARC: {\n\t\timpact: 'DMARC enforcement is reduced or absent at receiving systems.',\n\t\tadverseConsequences: 'Forged messages are more likely to reach users and erode brand trust.',\n\t},\n\tDKIM: {\n\t\timpact: 'DKIM assurance is weak, reducing message integrity and sender-authenticity confidence.',\n\t\tadverseConsequences: 'Legitimate messages may be distrusted while impersonation attempts become harder to detect.',\n\t},\n\tDNSSEC: {\n\t\timpact: 'DNS answers are more exposed to spoofing and tampering in transit.',\n\t\tadverseConsequences: 'Users can be redirected to attacker infrastructure, causing security and availability incidents.',\n\t},\n\tSSL: {\n\t\timpact: 'Transport security guarantees are reduced, increasing interception and tampering risk.',\n\t\tadverseConsequences: 'Sensitive user data may be exposed and browser trust can decline.',\n\t},\n\tMTA_STS: {\n\t\timpact: 'Inbound SMTP delivery is not consistently protected from downgrade attacks.',\n\t\tadverseConsequences: 'Confidential email content may be exposed in transit, increasing compliance risk.',\n\t},\n\tNS: {\n\t\timpact: 'DNS resolution reliability is reduced, which weakens service reachability.',\n\t\tadverseConsequences: 'Users may experience outages and business transactions may fail.',\n\t},\n\tCAA: {\n\t\timpact: 'Certificate issuance controls are weak, raising unauthorized issuance risk.',\n\t\tadverseConsequences: 'Domain impersonation and TLS trust incidents become more likely.',\n\t},\n\tMX: {\n\t\timpact: 'Mail routing reliability is reduced by MX configuration gaps or errors.',\n\t\tadverseConsequences: 'Important communications can be delayed, bounced, or lost.',\n\t},\n\tSUBDOMAIN_TAKEOVER: {\n\t\timpact: 'An orphaned delegated subdomain may be claimable by an attacker.',\n\t\tadverseConsequences: 'Users can be redirected to malicious content hosted under a trusted hostname.',\n\t},\n\tDANE_HTTPS: {\n\t\timpact: 'HTTPS certificate pinning via DANE is absent or misconfigured, leaving TLS trust dependent solely on the CA system.',\n\t\tadverseConsequences: 'A rogue or compromised CA can issue a fraudulent certificate, enabling undetected MITM attacks.',\n\t},\n\tSVCB_HTTPS: {\n\t\timpact: 'Modern transport capabilities (ALPN, ECH) cannot be advertised via DNS, reducing connection efficiency and privacy.',\n\t\tadverseConsequences: 'Clients require additional round-trips to negotiate protocols, and ECH-based privacy is unavailable.',\n\t},\n};\n\nexport const SEVERITY_FALLBACK_IMPACT: Record<string, ImpactNarrative> = {\n\tcritical: {\n\t\timpact: 'This is a high-likelihood weakness with immediate exploitation potential.',\n\t\tadverseConsequences: 'Compromise, disruption, or abuse can occur without prompt remediation.',\n\t},\n\thigh: {\n\t\timpact: 'This weakness materially increases attack surface and failure risk.',\n\t\tadverseConsequences: 'Business operations, user trust, and response workload can be negatively affected.',\n\t},\n\tmedium: {\n\t\timpact: 'This issue weakens defenses and compounds risk when paired with other gaps.',\n\t\tadverseConsequences: 'Over time it can degrade reliability, security assurance, and compliance posture.',\n\t},\n\twarning: {\n\t\timpact: 'This configuration is partially protective but leaves avoidable exposure.',\n\t\tadverseConsequences: 'If unresolved, incidents become harder to prevent or contain.',\n\t},\n\tfail: {\n\t\timpact: 'A required control is missing or not functioning as intended.',\n\t\tadverseConsequences: 'Security and availability incidents become more likely until it is corrected.',\n\t},\n\tlow: {\n\t\timpact: 'This is a minor weakness that still reduces resilience.',\n\t\tadverseConsequences: 'Operational friction and audit findings can increase over time.',\n\t},\n};\n\nexport const SPECIFIC_IMPACT_RULES: SpecificImpactRule[] = [\n\t{\n\t\tcheckType: 'DKIM',\n\t\ttitleIncludes: ['weak rsa key'],\n\t\timpact: 'Weak DKIM keys are easier to forge, reducing message authenticity assurance.',\n\t\tadverseConsequences: 'Attackers can impersonate trusted senders more easily, increasing fraud and phishing risk.',\n\t},\n\t{\n\t\tcheckType: 'SSL',\n\t\ttitleIncludes: ['no hsts header', 'no http to https redirect', 'mixed content'],\n\t\timpact: 'Users are exposed to insecure transport paths that permit interception or downgrade attacks.',\n\t\tadverseConsequences: 'Sensitive sessions and data can leak on hostile networks, weakening trust and compliance posture.',\n\t},\n\t{\n\t\tcheckType: 'DMARC',\n\t\ttitleIncludes: ['no aggregate reporting'],\n\t\timpact: 'Authentication failures and spoofing activity become harder to observe at scale.',\n\t\tadverseConsequences: 'Threats can persist longer without detection, increasing response time and abuse volume.',\n\t},\n\t{\n\t\tcheckType: 'MX',\n\t\ttitleIncludes: ['no mx records found', 'mx configuration error'],\n\t\timpact: 'Inbound email delivery becomes unreliable or fails for recipients on this domain.',\n\t\tadverseConsequences: 'Critical business and security communications may be delayed, bounced, or silently lost.',\n\t},\n\t{\n\t\tcheckType: 'NS',\n\t\ttitleIncludes: ['no soa record', 'nameserver', 'low nameserver diversity'],\n\t\timpact: 'DNS resilience and consistency are reduced, increasing partial or full resolution outage risk.',\n\t\tadverseConsequences: 'Availability incidents can affect websites, APIs, and transactional workflows.',\n\t},\n\t{\n\t\tcheckType: 'CAA',\n\t\ttitleIncludes: ['no caa records', 'issuewild', 'iodef'],\n\t\timpact: 'Certificate governance controls are weakened, especially for unauthorized or wildcard issuance.',\n\t\tadverseConsequences: 'TLS trust incidents and audit findings become more likely if certificate misuse occurs.',\n\t},\n\t{\n\t\tcheckType: 'SPF',\n\t\ttitleIncludes: ['permissive spf: +all', 'multiple spf records'],\n\t\tdetailIncludes: ['+all', 'multiple records'],\n\t\timpact: 'SPF policy becomes ineffective or ambiguous, allowing unauthorized senders to appear legitimate.',\n\t\tadverseConsequences: 'Spoofing, phishing, and deliverability failures can increase simultaneously.',\n\t},\n\t{\n\t\tcheckType: 'MTA_STS',\n\t\ttitleIncludes: ['no mta-sts', 'testing mode', 'tls-rpt'],\n\t\timpact: 'SMTP transport protections are not consistently enforced for inbound mail delivery.',\n\t\tadverseConsequences: 'Confidential email may traverse weaker paths, increasing confidentiality and regulatory risk.',\n\t},\n];","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Explain Finding tool.\n * Provides static explanations for DNS security findings.\n * No AI binding required - uses a built-in knowledge base.\n */\n\nimport type { OutputFormat } from '../handlers/tool-args';\nimport { sanitizeOutputText } from '../lib/output-sanitize';\n\nimport {\n\tCATEGORY_FALLBACK_IMPACT,\n\tCATEGORY_TO_CHECKTYPE,\n\tDEFAULT_EXPLANATION,\n\tEXPLANATIONS,\n\ttype ExplanationTemplate,\n\ttype ImpactNarrative,\n\tSEVERITY_FALLBACK_IMPACT,\n\tSPECIFIC_IMPACT_RULES,\n} from './explain-finding-data';\n\nexport interface ExplanationResult {\n\tcheckType: string;\n\tstatus: string;\n\tdetails?: string;\n\ttitle: string;\n\tseverity: string;\n\texplanation: string;\n\timpact?: string;\n\tadverseConsequences?: string;\n\trecommendation: string;\n\treferences: string[];\n}\n\ntype ExplanationEntry = ExplanationTemplate;\n\nfunction matchesRule(ruleValues: string[] | undefined, source: string): boolean {\n\tif (!ruleValues || ruleValues.length === 0) return true;\n\treturn ruleValues.some((value) => source.includes(value));\n}\n\nfunction resolveSpecificNarrative(params: {\n\tcheckType?: string;\n\ttitle?: string;\n\tdetail?: string;\n}): ImpactNarrative | undefined {\n\tconst checkType = params.checkType?.toUpperCase();\n\tconst title = params.title?.toLowerCase() ?? '';\n\tconst detail = params.detail?.toLowerCase() ?? '';\n\n\tfor (const rule of SPECIFIC_IMPACT_RULES) {\n\t\tif (rule.checkType && checkType && rule.checkType !== checkType) continue;\n\t\tif (!matchesRule(rule.titleIncludes, title)) continue;\n\t\tif (!matchesRule(rule.detailIncludes, detail)) continue;\n\t\treturn {\n\t\t\timpact: rule.impact,\n\t\t\tadverseConsequences: rule.adverseConsequences,\n\t\t};\n\t}\n\n\treturn undefined;\n}\n\nfunction getNarrativeFromEntry(entry: ExplanationEntry | undefined): ImpactNarrative | undefined {\n\tif (!entry) return undefined;\n\tif (!entry.impact && !entry.adverseConsequences) return undefined;\n\treturn {\n\t\timpact: entry.impact,\n\t\tadverseConsequences: entry.adverseConsequences,\n\t};\n}\n\n/**\n * Resolve impact/adverse-consequence narrative for a finding context.\n * Uses explicit explanation entries first, then category, then severity fallback.\n */\nexport function resolveImpactNarrative(params: {\n\tcheckType?: string;\n\tcategory?: string;\n\tstatus?: string;\n\tseverity?: string;\n\ttitle?: string;\n\tdetail?: string;\n}): ImpactNarrative {\n\tconst normalizedCheckType = params.checkType?.toUpperCase();\n\tconst normalizedStatus = params.status?.toUpperCase();\n\tconst normalizedSeverity = params.severity?.toLowerCase();\n\tconst derivedCheckType = params.category ? CATEGORY_TO_CHECKTYPE[params.category.toLowerCase()] : undefined;\n\n\tif (normalizedCheckType && normalizedStatus) {\n\t\tconst narrative = getNarrativeFromEntry(EXPLANATIONS[`${normalizedCheckType}_${normalizedStatus}`]);\n\t\tif (narrative) return narrative;\n\t}\n\n\tif (normalizedCheckType && normalizedSeverity) {\n\t\tconst narrative = getNarrativeFromEntry(EXPLANATIONS[`${normalizedCheckType}_${normalizedSeverity.toUpperCase()}`]);\n\t\tif (narrative) return narrative;\n\t}\n\n\tif (derivedCheckType && normalizedStatus) {\n\t\tconst narrative = getNarrativeFromEntry(EXPLANATIONS[`${derivedCheckType}_${normalizedStatus}`]);\n\t\tif (narrative) return narrative;\n\t}\n\n\tif (derivedCheckType && normalizedSeverity) {\n\t\tconst narrative = getNarrativeFromEntry(EXPLANATIONS[`${derivedCheckType}_${normalizedSeverity.toUpperCase()}`]);\n\t\tif (narrative) return narrative;\n\t}\n\n\tconst specificNarrative = resolveSpecificNarrative({\n\t\tcheckType: normalizedCheckType ?? derivedCheckType,\n\t\ttitle: params.title,\n\t\tdetail: params.detail,\n\t});\n\tif (specificNarrative) return specificNarrative;\n\n\tif (normalizedCheckType && CATEGORY_FALLBACK_IMPACT[normalizedCheckType]) {\n\t\treturn CATEGORY_FALLBACK_IMPACT[normalizedCheckType];\n\t}\n\n\tif (derivedCheckType && CATEGORY_FALLBACK_IMPACT[derivedCheckType]) {\n\t\treturn CATEGORY_FALLBACK_IMPACT[derivedCheckType];\n\t}\n\n\tif (normalizedSeverity && SEVERITY_FALLBACK_IMPACT[normalizedSeverity]) {\n\t\treturn SEVERITY_FALLBACK_IMPACT[normalizedSeverity];\n\t}\n\n\treturn {};\n}\n\nexport function explainFinding(checkType: string, status: string, details?: string): ExplanationResult {\n\tconst normalizedType = checkType.toUpperCase();\n\tconst key = `${normalizedType}_${status.toUpperCase()}`;\n\n\t// 1. Try checkType_STATUS key\n\tlet entry: ExplanationTemplate | undefined = EXPLANATIONS[key];\n\n\t// 2. Fall back to default\n\tif (!entry) {\n\t\tentry = DEFAULT_EXPLANATION;\n\t}\n\n\tconst narrative = resolveImpactNarrative({ checkType: normalizedType, status, detail: details });\n\n\treturn {\n\t\tcheckType: normalizedType,\n\t\tstatus,\n\t\tdetails,\n\t\t...entry,\n\t\timpact: entry.impact ?? narrative.impact,\n\t\tadverseConsequences: entry.adverseConsequences ?? narrative.adverseConsequences,\n\t};\n}\n\nexport function formatExplanation(result: ExplanationResult, format: OutputFormat = 'full'): string {\n\tif (format === 'compact') {\n\t\tconst lines = [\n\t\t\t`${result.title} (${result.checkType} | ${result.status})`,\n\t\t\tsanitizeOutputText(result.explanation, 200),\n\t\t\t`Recommendation: ${sanitizeOutputText(result.recommendation, 200)}`,\n\t\t];\n\t\treturn lines.join('\\n');\n\t}\n\n\tconst lines = [`## ${result.title}`, `**Check Type:** ${result.checkType} | **Status:** ${result.status}`, ''];\n\n\tlines.push(`### What this means`, result.explanation, '');\n\n\tif (result.impact) {\n\t\tlines.push(`### Potential Impact`, result.impact, '');\n\t}\n\n\tif (result.adverseConsequences) {\n\t\tlines.push(`### Adverse Consequences`, result.adverseConsequences, '');\n\t}\n\n\tlines.push(`### Recommendation`, result.recommendation, '', `### References`, ...result.references.map((reference) => `- ${reference}`));\n\treturn lines.join('\\n');\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Category interaction scoring — post-scoring adjustments for correlated weaknesses.\n *\n * Applied after computeScanScore() as a separate penalty layer.\n * Does NOT modify categoryScores — only adjusts the overall score.\n * Existing compare_baseline CI/CD workflows continue to work identically.\n */\n\nimport type { CheckCategory, ScanScore } from './scoring-model';\nimport { scoreToGrade } from './scoring-engine';\nimport type { ScoringConfig } from './scoring-config';\n\n/** A condition that must be met for an interaction rule to fire. */\ninterface InteractionCondition {\n\tcategory: CheckCategory;\n\t/** Maximum category score for the condition to be true (score <= maxScore). */\n\tmaxScore?: number;\n\t/** Minimum category score for the condition to be true (score >= minScore). */\n\tminScore?: number;\n}\n\n/** An interaction rule that applies a penalty when all conditions are met. */\nexport interface InteractionRule {\n\t/** Unique identifier for the interaction. */\n\tid: string;\n\t/** All conditions must be satisfied for the penalty to apply. */\n\tconditions: InteractionCondition[];\n\t/** Additional points deducted from the overall score. */\n\toverallPenalty: number;\n\t/** Human-readable explanation of the interaction effect. */\n\tnarrative: string;\n}\n\n/** Result of applying interaction rules to a scan score. */\nexport interface InteractionEffect {\n\truleId: string;\n\tpenalty: number;\n\tnarrative: string;\n}\n\n/** Interaction rules — correlated weaknesses that amplify risk. */\nexport const INTERACTION_RULES: InteractionRule[] = [\n\t{\n\t\tid: 'weak_dkim_permissive_dmarc',\n\t\tconditions: [\n\t\t\t{ category: 'dkim', maxScore: 40 },\n\t\t\t{ category: 'dmarc', maxScore: 60 },\n\t\t],\n\t\toverallPenalty: 5,\n\t\tnarrative: 'Weak DKIM combined with permissive DMARC creates multiplicative spoofing risk — attackers can forge messages that pass relaxed alignment checks.',\n\t},\n\t{\n\t\tid: 'no_spf_no_dmarc',\n\t\tconditions: [\n\t\t\t{ category: 'spf', maxScore: 0 },\n\t\t\t{ category: 'dmarc', maxScore: 0 },\n\t\t],\n\t\toverallPenalty: 10,\n\t\tnarrative: 'Complete absence of both SPF and DMARC means any server can send as this domain with no detection mechanism.',\n\t},\n\t{\n\t\tid: 'weak_dnssec_enforcing_dmarc',\n\t\tconditions: [\n\t\t\t{ category: 'dmarc', minScore: 80 },\n\t\t\t{ category: 'dnssec', maxScore: 40 },\n\t\t],\n\t\toverallPenalty: 3,\n\t\tnarrative: 'Strong email authentication is in place but DNSSEC is weak or absent — DNS tampering could undermine authentication records.',\n\t},\n\t{\n\t\tid: 'no_spf_no_dkim',\n\t\tconditions: [\n\t\t\t{ category: 'spf', maxScore: 0 },\n\t\t\t{ category: 'dkim', maxScore: 0 },\n\t\t],\n\t\toverallPenalty: 5,\n\t\tnarrative: 'Neither SPF nor DKIM is configured — DMARC alignment cannot be satisfied through either mechanism, making enforcement ineffective even if DMARC is published.',\n\t},\n\t{\n\t\tid: 'weak_ssl_no_http_security',\n\t\tconditions: [\n\t\t\t{ category: 'ssl', maxScore: 40 },\n\t\t\t{ category: 'http_security', maxScore: 30 },\n\t\t],\n\t\toverallPenalty: 3,\n\t\tnarrative: 'Weak SSL/TLS combined with missing HTTP security headers exposes the domain to man-in-the-middle attacks and content injection.',\n\t},\n];\n\n/** Check if a single condition is satisfied by the category scores. */\nfunction conditionMet(condition: InteractionCondition, categoryScores: Record<string, number>): boolean {\n\tconst score = categoryScores[condition.category];\n\tif (score === undefined) return false;\n\n\tif (condition.maxScore !== undefined && score > condition.maxScore) return false;\n\tif (condition.minScore !== undefined && score < condition.minScore) return false;\n\n\treturn true;\n}\n\n/**\n * Apply interaction penalties to a scan score.\n *\n * This is a post-scoring adjustment — categoryScores remain unchanged,\n * only the overall score and grade are updated.\n *\n * @param score - The computed scan score from computeScanScore()\n * @param config - Optional scoring config for grade computation\n * @returns Updated score with interaction penalties applied, plus the list of triggered effects\n */\nexport function applyInteractionPenalties(\n\tscore: ScanScore,\n\tconfig?: ScoringConfig,\n): { adjustedScore: ScanScore; effects: InteractionEffect[] } {\n\tconst effects: InteractionEffect[] = [];\n\tlet totalPenalty = 0;\n\n\tfor (const rule of INTERACTION_RULES) {\n\t\tconst allMet = rule.conditions.every((c) => conditionMet(c, score.categoryScores));\n\t\tif (allMet) {\n\t\t\teffects.push({\n\t\t\t\truleId: rule.id,\n\t\t\t\tpenalty: rule.overallPenalty,\n\t\t\t\tnarrative: rule.narrative,\n\t\t\t});\n\t\t\ttotalPenalty += rule.overallPenalty;\n\t\t}\n\t}\n\n\tif (totalPenalty === 0) {\n\t\treturn { adjustedScore: score, effects };\n\t}\n\n\tconst adjustedOverall = Math.max(0, score.overall - totalPenalty);\n\tconst adjustedGrade = scoreToGrade(adjustedOverall, config);\n\n\t// Update summary if grade changed\n\tlet summary = score.summary;\n\tif (adjustedGrade !== score.grade) {\n\t\tsummary = summary.replace(`Grade: ${score.grade}`, `Grade: ${adjustedGrade}`);\n\t}\n\n\treturn {\n\t\tadjustedScore: {\n\t\t\t...score,\n\t\t\toverall: adjustedOverall,\n\t\t\tgrade: adjustedGrade,\n\t\t\tsummary,\n\t\t},\n\t\teffects,\n\t};\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Structured logging utility for Cloudflare Worker (MCP server)\n * Logs JSON objects with request, tool, result, and error metadata\n * Usage: logEvent({ ... })\n */\n\nexport type LogEvent = {\n\ttimestamp: string;\n\trequestId?: string;\n\tip?: string;\n\ttool?: string;\n\tdomain?: string;\n\tseverity?: 'info' | 'warn' | 'error';\n\tcategory?: string;\n\tresult?: string;\n\tdetails?: unknown;\n\terror?: string;\n\tdurationMs?: number;\n\tuserAgent?: string;\n};\n\nconst REDACTED = '[redacted]';\nconst MAX_LOG_STRING_LENGTH = 256;\nconst SENSITIVE_KEY_PATTERN = /(^ip$|authorization|mcp-session-id|session|token|api[-_]?key|secret|password|cookie|rawbody)/i;\n\nfunction isSensitiveKey(key: string): boolean {\n\treturn !/^has[A-Z]/.test(key) && SENSITIVE_KEY_PATTERN.test(key);\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction sanitizeString(value: string): string {\n\t// Strip control characters (except tab) to prevent log injection via newlines/ANSI sequences\n\tconst stripped = value.replace(/[\\x00-\\x08\\x0a-\\x1f\\x7f]/g, ' ');\n\treturn stripped.length > MAX_LOG_STRING_LENGTH ? `${stripped.slice(0, MAX_LOG_STRING_LENGTH)}...` : stripped;\n}\n\nexport function sanitizeLogValue(value: unknown, key?: string): unknown {\n\tif (key && isSensitiveKey(key)) {\n\t\treturn REDACTED;\n\t}\n\n\tif (typeof value === 'string') {\n\t\treturn sanitizeString(value);\n\t}\n\n\tif (Array.isArray(value)) {\n\t\treturn value.map((item) => sanitizeLogValue(item));\n\t}\n\n\tif (isPlainObject(value)) {\n\t\tconst sanitized: Record<string, unknown> = {};\n\t\tfor (const [entryKey, entryValue] of Object.entries(value)) {\n\t\t\tsanitized[entryKey] = sanitizeLogValue(entryValue, entryKey);\n\t\t}\n\t\treturn sanitized;\n\t}\n\n\treturn value;\n}\n\nexport function sanitizeHeadersForLog(headers: Headers | Record<string, string>): Record<string, string> {\n\tconst sanitized: Record<string, string> = {};\n\tif (headers instanceof Headers) {\n\t\theaders.forEach((value, rawKey) => {\n\t\t\tconst key = rawKey.toLowerCase();\n\t\t\tsanitized[key] = isSensitiveKey(key) ? REDACTED : sanitizeString(value);\n\t\t});\n\t\treturn sanitized;\n\t}\n\n\tfor (const [rawKey, value] of Object.entries(headers)) {\n\t\tconst key = rawKey.toLowerCase();\n\t\tsanitized[key] = isSensitiveKey(key) ? REDACTED : sanitizeString(value);\n\t}\n\treturn sanitized;\n}\n\n/**\n * Emit a structured log event (console.log as JSON)\n */\nexport function logEvent(event: LogEvent): void {\n\tconst log = {\n\t\t...event,\n\t\ttimestamp: event.timestamp || new Date().toISOString(),\n\t\tdetails: sanitizeLogValue(event.details),\n\t\terror: typeof event.error === 'string' ? sanitizeString(event.error) : event.error,\n\t};\n\tconsole.log(JSON.stringify(log));\n}\n\n/**\n * Helper for error logging\n */\nexport function logError(error: Error | string, context?: Partial<LogEvent>): void {\n\tlogEvent({\n\t\ttimestamp: new Date().toISOString(),\n\t\tseverity: 'error',\n\t\terror: typeof error === 'string' ? error : error.message,\n\t\t...context,\n\t});\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { INFLIGHT_CLEANUP_MS } from './config';\nimport { logError } from './log';\n\n/**\n * TTL cache for DNS scan results.\n *\n * Uses Cloudflare KV for persistent caching when available,\n * with in-memory fallback when KV is not configured.\n *\n * Cloudflare Workers compatible - no Node.js APIs.\n */\n\ninterface CacheEntry<T> {\n\tvalue: T;\n\texpiresAt: number;\n}\n\ninterface CacheOptions {\n\t/** Time-to-live in milliseconds. Default: 5 minutes (300_000ms) */\n\tttlMs?: number;\n\t/** Maximum number of entries. Default: 1000 */\n\tmaxEntries?: number;\n}\n\nconst DEFAULT_TTL_MS = 5 * 60 * 1000; // 5 minutes\nconst DEFAULT_TTL_SECONDS = 300; // 5 minutes in seconds (for KV expirationTtl)\nconst DEFAULT_MAX_ENTRIES = 1000;\n\nexport class TTLCache<T = unknown> {\n\tprivate readonly store = new Map<string, CacheEntry<T>>();\n\tprivate readonly ttlMs: number;\n\tprivate readonly maxEntries: number;\n\n\tconstructor(options: CacheOptions = {}) {\n\t\tthis.ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;\n\t\tthis.maxEntries = options.maxEntries ?? DEFAULT_MAX_ENTRIES;\n\t}\n\n\t/**\n\t * Get a cached value by key. Returns undefined if not found or expired.\n\t */\n\tget(key: string): T | undefined {\n\t\tconst entry = this.store.get(key);\n\t\tif (!entry) {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (Date.now() > entry.expiresAt) {\n\t\t\tthis.store.delete(key);\n\t\t\treturn undefined;\n\t\t}\n\t\treturn entry.value;\n\t}\n\n\t/**\n\t * Set a value in the cache with optional custom TTL.\n\t */\n\tset(key: string, value: T, ttlMs?: number): void {\n\t\t// Evict expired entries if at capacity\n\t\tif (this.store.size >= this.maxEntries && !this.store.has(key)) {\n\t\t\tthis.evictExpired();\n\t\t}\n\t\t// If still at capacity after eviction, remove oldest entry\n\t\tif (this.store.size >= this.maxEntries && !this.store.has(key)) {\n\t\t\tconst firstKey = this.store.keys().next().value;\n\t\t\tif (firstKey !== undefined) {\n\t\t\t\tthis.store.delete(firstKey);\n\t\t\t}\n\t\t}\n\t\tthis.store.set(key, {\n\t\t\tvalue,\n\t\t\texpiresAt: Date.now() + (ttlMs ?? this.ttlMs),\n\t\t});\n\t}\n\n\t/**\n\t * Check if a key exists and is not expired.\n\t */\n\thas(key: string): boolean {\n\t\treturn this.get(key) !== undefined;\n\t}\n\n\t/**\n\t * Delete a specific key from the cache.\n\t */\n\tdelete(key: string): boolean {\n\t\treturn this.store.delete(key);\n\t}\n\n\t/**\n\t * Remove all entries from the cache.\n\t */\n\tclear(): void {\n\t\tthis.store.clear();\n\t}\n\n\t/**\n\t * Get the number of entries (including potentially expired ones).\n\t */\n\tget size(): number {\n\t\treturn this.store.size;\n\t}\n\n\t/**\n\t * Remove all expired entries from the cache.\n\t */\n\tevictExpired(): number {\n\t\tconst now = Date.now();\n\t\tlet evicted = 0;\n\t\tfor (const [key, entry] of this.store) {\n\t\t\tif (now > entry.expiresAt) {\n\t\t\t\tthis.store.delete(key);\n\t\t\t\tevicted++;\n\t\t\t}\n\t\t}\n\t\treturn evicted;\n\t}\n}\n\n/** In-flight promise map for cache stampede (thundering herd) protection */\nconst INFLIGHT = new Map<string, Promise<unknown>>();\n\n/** In-memory cache instance used as fallback when KV is unavailable */\nexport const IN_MEMORY_CACHE = new TTLCache<unknown>({\n\tttlMs: DEFAULT_TTL_MS,\n\tmaxEntries: DEFAULT_MAX_ENTRIES,\n});\n\n// ---------------------------------------------------------------------------\n// KV-backed cache functions\n// ---------------------------------------------------------------------------\n\n/**\n * Get a cached value by key.\n * Uses KV when available, falls back to in-memory.\n *\n * @param key - Cache key\n * @param kv - Optional KV namespace for persistent caching\n */\nexport async function cacheGet<T>(key: string, kv?: KVNamespace): Promise<T | undefined> {\n if (kv) {\n\t try {\n\t\t const val = await kv.get(key, 'json');\n\t\t return (val ?? undefined) as T | undefined; // KV.get('json') returns unknown; generic T is caller-enforced\n\t } catch {\n\t\t // KV error — log warning and fall through to in-memory\n\t\t logError('[cache] KV get failed, falling back to in-memory');\n\t }\n }\n return IN_MEMORY_CACHE.get(key) as T | undefined;\n}\n\n/**\n * Set a cached value with configurable TTL.\n * Uses KV when available, falls back to in-memory.\n *\n * @param key - Cache key\n * @param value - Value to cache (must be JSON-serializable for KV)\n * @param kv - Optional KV namespace for persistent caching\n * @param ttlSeconds - Cache TTL in seconds (default: 300 = 5 minutes)\n */\n/**\n * Set a cached value, deferring the KV write via ctx.waitUntil() to avoid blocking the response.\n * Falls back to synchronous cacheSet when no ExecutionContext is provided.\n */\nexport function cacheSetDeferred(key: string, value: unknown, ctx: ExecutionContext, kv?: KVNamespace, ttlSeconds?: number): void {\n\tctx.waitUntil(cacheSet(key, value, kv, ttlSeconds));\n}\n\nexport async function cacheSet(key: string, value: unknown, kv?: KVNamespace, ttlSeconds?: number): Promise<void> {\n const ttl = ttlSeconds ?? DEFAULT_TTL_SECONDS;\n if (kv) {\n\t try {\n\t\t await kv.put(key, JSON.stringify(value), { expirationTtl: ttl });\n\t\t return;\n\t } catch {\n\t\t // KV error — log warning and fall through to in-memory\n\t\t logError('[cache] KV put failed, falling back to in-memory');\n\t }\n }\n IN_MEMORY_CACHE.set(key, value, ttl * 1000);\n}\n\n/**\n * Run a function with cache-aside logic: returns cached value if available,\n * otherwise executes the function and caches the result.\n * Includes in-flight deduplication to prevent cache stampedes.\n *\n * @param key - Cache key\n * @param run - Async function to execute on cache miss\n * @param kv - Optional KV namespace for persistent caching\n * @param ttlSeconds - Cache TTL in seconds (default: 300 = 5 minutes)\n * @param skipCache - When true, bypass cache lookup and always execute the function (result is still cached)\n * @returns The cached or freshly computed result\n */\nexport async function runWithCache<T>(key: string, run: () => Promise<T>, kv?: KVNamespace, ttlSeconds?: number, skipCache?: boolean): Promise<T> {\n\tif (!skipCache) {\n\t\tconst cached = await cacheGet<T>(key, kv);\n\t\tif (cached !== undefined) return cached;\n\t}\n\n\tconst existing = INFLIGHT.get(key);\n\tif (existing) return existing as Promise<T>; // INFLIGHT map stores Promise<unknown>; keyed by same cache key ensures type match\n\n\tconst cleanup = setTimeout(() => INFLIGHT.delete(key), INFLIGHT_CLEANUP_MS);\n\tconst promise = run()\n\t\t.then(async (result) => {\n\t\t\tawait cacheSet(key, result, kv, ttlSeconds);\n\t\t\treturn result;\n\t\t})\n\t\t.finally(() => {\n\t\t\tclearTimeout(cleanup);\n\t\t\tINFLIGHT.delete(key);\n\t\t});\n\n\tINFLIGHT.set(key, promise);\n\treturn promise;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * HTTP security headers check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkHTTPSecurity } from '@blackveil/dns-checks';\nimport type { CheckResult } from '../lib/scoring';\nimport { HTTPS_TIMEOUT_MS } from '../lib/config';\n\n/**\n * Check HTTP security headers for a domain.\n * Fetches the HTTPS endpoint and analyzes browser security headers.\n */\nexport async function checkHttpSecurity(domain: string): Promise<CheckResult> {\n\treturn checkHTTPSecurity(domain, fetch, { timeout: HTTPS_TIMEOUT_MS }) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DANE (DNS-Based Authentication of Named Entities) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkDANE } from '@blackveil/dns-checks';\nimport { queryDns, queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check DANE TLSA records for a domain's MX servers and HTTPS endpoint.\n */\nexport async function checkDane(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkDANE(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{\n\t\t\ttimeout: dnsOptions?.timeoutMs ?? 5000,\n\t\t\trawQueryDNS: async (d, type, dnssecFlag) => {\n\t\t\t\tconst resp = await queryDns(d, type as Parameters<typeof queryDns>[1], dnssecFlag ?? false, dnsOptions);\n\t\t\t\treturn { AD: resp.AD, Answer: resp.Answer };\n\t\t\t},\n\t\t},\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DANE-HTTPS check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkDANEHTTPS } from '@blackveil/dns-checks';\nimport { queryDns, queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check DANE TLSA records for a domain's HTTPS endpoint (_443._tcp.{domain}).\n */\nexport async function checkDaneHttps(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkDANEHTTPS(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{\n\t\t\ttimeout: dnsOptions?.timeoutMs ?? 5000,\n\t\t\trawQueryDNS: async (d, type, dnssecFlag) => {\n\t\t\t\tconst resp = await queryDns(d, type as Parameters<typeof queryDns>[1], dnssecFlag ?? false, dnsOptions);\n\t\t\t\treturn { AD: resp.AD, Answer: resp.Answer };\n\t\t\t},\n\t\t},\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * SVCB/HTTPS DNS record check tool (RFC 9460).\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkSVCBHTTPS } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check HTTPS/SVCB records (RFC 9460) for a domain.\n */\nexport async function checkSvcbHttps(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkSVCBHTTPS(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? 5000 },\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { type CheckCategory, type CheckResult, buildCheckResult, createFinding } from '../../lib/scoring';\nimport { queryTxtRecords } from '../../lib/dns';\nimport { detectProviderMatches, detectProviderMatchesBySelectors, loadProviderSignatures } from '../../lib/provider-signatures';\nimport { parseDmarcTags } from '../check-dmarc';\n\nexport interface ScanRuntimeOptions {\n\tproviderSignaturesUrl?: string;\n\tproviderSignaturesAllowedHosts?: string[];\n\tproviderSignaturesSha256?: string;\n\tprofile?: 'mail_enabled' | 'enterprise_mail' | 'non_mail' | 'web_only' | 'minimal' | 'auto';\n\tprofileAccumulator?: DurableObjectNamespace;\n\twaitUntil?: (promise: Promise<unknown>) => void;\n\tscoringConfig?: import('../../lib/scoring-config').ScoringConfig;\n\t/** Override cache TTL in seconds (default: 300). Clamped to [60, 3600]. */\n\tcacheTtlSeconds?: number;\n\t/** Custom secondary DoH resolver config (bv-dns). Threaded to scanDns but only active when skipSecondaryConfirmation is false. */\n\tsecondaryDoh?: import('../../lib/dns-types').SecondaryDohConfig;\n\t/** Bypass cache and run a fresh scan. Useful for troubleshooting after DNS changes. */\n\tforceRefresh?: boolean;\n}\n\nexport async function applyScanPostProcessing(\n\tdomain: string,\n\tcheckResults: CheckResult[],\n\truntimeOptions?: ScanRuntimeOptions,\n): Promise<CheckResult[]> {\n\tlet results = checkResults;\n\tconst mxResult = results.find((result) => result.category === 'mx');\n\tconst hasNoMx = mxResult ? mxResult.findings.some((finding) => finding.title === 'No MX records found') : false;\n\n\tif (hasNoMx) {\n\t\tconst apexCovers = await checkApexDmarcPolicy(domain);\n\t\tresults = adjustForNonMailDomain(results, apexCovers);\n\t\tresults = adjustBimiForNonMailDomain(results);\n\t} else if (mxResult) {\n\t\tresults = clarifyMtaStsForMailDomain(domain, results);\n\t}\n\n\t// Detect no-send SPF policy (v=spf1 -all with no authorizing mechanisms)\n\tconst spfResult = results.find((result) => result.category === 'spf');\n\tconst hasNoSendPolicy = spfResult?.findings.some((f) => f.metadata?.noSendPolicy === true) ?? false;\n\tif (hasNoSendPolicy && !hasNoMx) {\n\t\tresults = adjustForNoSendDomain(results);\n\t}\n\n\treturn addOutboundProviderInference(results, runtimeOptions);\n}\n\nfunction extractSpfSignalDomains(result: CheckResult | undefined): string[] {\n\tif (!result) return [];\n\n\tconst domains = new Set<string>();\n\tfor (const finding of result.findings) {\n\t\tconst metadata = finding.metadata;\n\t\tif (!metadata || typeof metadata !== 'object') continue;\n\n\t\tconst includeDomains = metadata.includeDomains;\n\t\tif (Array.isArray(includeDomains)) {\n\t\t\tfor (const domain of includeDomains) {\n\t\t\t\tif (typeof domain === 'string' && domain.trim().length > 0) {\n\t\t\t\t\tdomains.add(domain.trim().toLowerCase());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst redirectDomain = metadata.redirectDomain;\n\t\tif (typeof redirectDomain === 'string' && redirectDomain.trim().length > 0) {\n\t\t\tdomains.add(redirectDomain.trim().toLowerCase());\n\t\t}\n\t}\n\n\treturn Array.from(domains);\n}\n\nfunction extractDkimSignalSelectors(result: CheckResult | undefined): string[] {\n\tif (!result) return [];\n\n\tconst selectors = new Set<string>();\n\tfor (const finding of result.findings) {\n\t\tconst metadata = finding.metadata;\n\t\tif (!metadata || typeof metadata !== 'object') continue;\n\n\t\tconst selectorsFound = metadata.selectorsFound;\n\t\tif (!Array.isArray(selectorsFound)) continue;\n\n\t\tfor (const selector of selectorsFound) {\n\t\t\tif (typeof selector === 'string' && selector.trim().length > 0) {\n\t\t\t\tselectors.add(selector.trim().toLowerCase());\n\t\t\t}\n\t\t}\n\t}\n\n\treturn Array.from(selectors);\n}\n\nfunction upsertCheckResult(results: CheckResult[], updated: CheckResult): CheckResult[] {\n\treturn results.map((result) => (result.category === updated.category ? updated : result));\n}\n\nasync function addOutboundProviderInference(results: CheckResult[], runtimeOptions?: ScanRuntimeOptions): Promise<CheckResult[]> {\n\tconst spfResult = results.find((result) => result.category === 'spf');\n\tconst dkimResult = results.find((result) => result.category === 'dkim');\n\n\tconst signalDomains = extractSpfSignalDomains(spfResult);\n\tconst dkimSelectors = extractDkimSignalSelectors(dkimResult);\n\tif (signalDomains.length === 0 && dkimSelectors.length === 0) return results;\n\n\tconst signatures = await loadProviderSignatures({\n\t\tsourceUrl: runtimeOptions?.providerSignaturesUrl,\n\t\tallowedHosts: runtimeOptions?.providerSignaturesAllowedHosts,\n\t\texpectedSha256: runtimeOptions?.providerSignaturesSha256,\n\t});\n\tconst signatureSet = signatures.outbound.length > 0 ? signatures.outbound : signatures.inbound;\n\tconst hostMatches = detectProviderMatches(signalDomains, signatureSet);\n\tconst selectorMatches = detectProviderMatchesBySelectors(dkimSelectors, signatureSet);\n\n\tconst mergedMatches = new Map<string, Set<string>>();\n\tfor (const match of [...hostMatches, ...selectorMatches]) {\n\t\tif (!mergedMatches.has(match.provider)) {\n\t\t\tmergedMatches.set(match.provider, new Set<string>());\n\t\t}\n\t\tfor (const evidence of match.matches) {\n\t\t\tmergedMatches.get(match.provider)?.add(evidence);\n\t\t}\n\t}\n\n\tconst outboundMatches = Array.from(mergedMatches.entries()).map(([provider, matches]) => ({\n\t\tprovider,\n\t\tmatches: Array.from(matches),\n\t}));\n\tif (outboundMatches.length === 0) return results;\n\n\tconst providerNames = outboundMatches.map((match) => match.provider).join(', ');\n\tconst evidence = outboundMatches.map((match) => `${match.provider}: ${match.matches.join(', ')}`).join('; ');\n\tconst signalBoost = signalDomains.length > 0 && dkimSelectors.length > 0 ? 0.05 : 0;\n\tconst baseConfidence = signatures.source === 'runtime' ? 0.85 : signatures.source === 'stale' ? 0.7 : 0.65;\n\tconst providerConfidence = Math.min(0.95, baseConfidence + signalBoost);\n\n\tconst spfBaseline = spfResult ?? buildCheckResult('spf', []);\n\tconst updatedSpf = buildCheckResult('spf', [\n\t\t...spfBaseline.findings,\n\t\tcreateFinding('spf', 'Outbound email provider inferred', 'info', `Outbound provider(s): ${providerNames}. Evidence: ${evidence}.`, {\n\t\t\tdetectionType: 'outbound',\n\t\t\tproviders: outboundMatches.map((match) => ({ name: match.provider, matches: match.matches })),\n\t\t\tsignalsUsed: {\n\t\t\t\tspfDomains: signalDomains,\n\t\t\t\tdkimSelectors,\n\t\t\t},\n\t\t\tproviderConfidence,\n\t\t\tsignatureSource: signatures.source,\n\t\t\tsignatureVersion: signatures.version,\n\t\t\tsignatureFetchedAt: signatures.fetchedAt,\n\t\t}),\n\t]);\n\n\treturn upsertCheckResult(results, updatedSpf);\n}\n\nfunction getParentDomain(domain: string): string | null {\n\tconst parts = domain.split('.');\n\tif (parts.length <= 2) return null;\n\treturn parts.slice(1).join('.');\n}\n\nasync function checkApexDmarcPolicy(domain: string): Promise<boolean> {\n\tconst parent = getParentDomain(domain);\n\tif (!parent) return false;\n\n\ttry {\n\t\tconst records = await queryTxtRecords(`_dmarc.${parent}`);\n\t\tconst dmarcRecord = records.find((record) => record.toLowerCase().startsWith('v=dmarc1'));\n\t\tif (!dmarcRecord) return false;\n\n\t\tconst tags = parseDmarcTags(dmarcRecord);\n\t\tconst effectivePolicy = tags.get('sp') || tags.get('p') || '';\n\t\treturn effectivePolicy === 'quarantine' || effectivePolicy === 'reject';\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction isMissingRecordFinding(finding: { title: string; detail: string }): boolean {\n\t// Match against title only (controlled by check modules, not DNS data) to avoid ReDoS on attacker-controlled detail strings\n\tconst title = finding.title.toLowerCase();\n\treturn (\n\t\ttitle.includes('missing') ||\n\t\ttitle.includes('not found') ||\n\t\ttitle.includes('no mta-sts') ||\n\t\ttitle.includes('no dkim') ||\n\t\t/^no\\s+\\S+\\s+record/.test(title)\n\t);\n}\n\nfunction clarifyMtaStsForMailDomain(domain: string, results: CheckResult[]): CheckResult[] {\n\treturn results.map((result) => {\n\t\tif (result.category !== 'mta_sts') return result;\n\t\tconst adjusted = result.findings.map((finding) => {\n\t\t\tif (finding.title === 'No MTA-STS or TLS-RPT records found') {\n\t\t\t\treturn {\n\t\t\t\t\t...finding,\n\t\t\t\t\tdetail: `Neither MTA-STS nor TLS-RPT records are present for ${domain}. Since this domain has MX records and accepts email, adding MTA-STS and TLS-RPT is recommended to protect inbound email in transit.`,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn finding;\n\t\t});\n\t\treturn buildCheckResult(result.category, adjusted);\n\t});\n}\n\nfunction adjustForNonMailDomain(results: CheckResult[], apexDmarcCovers: boolean): CheckResult[] {\n\tconst emailCategories: CheckCategory[] = ['spf', 'dmarc', 'dkim', 'mta_sts'];\n\treturn results.map((result) => {\n\t\tif (!emailCategories.includes(result.category)) return result;\n\t\tconst adjusted = result.findings.map((finding) => {\n\t\t\tif ((finding.severity === 'critical' || finding.severity === 'high') && isMissingRecordFinding(finding)) {\n\t\t\t\tconst reason = apexDmarcCovers\n\t\t\t\t\t? 'expected — no MX records and parent domain DMARC policy covers subdomains'\n\t\t\t\t\t: 'expected — domain has no MX records';\n\t\t\t\treturn { ...finding, severity: 'info' as const, detail: `${finding.detail} (${reason})` };\n\t\t\t}\n\t\t\treturn finding;\n\t\t});\n\t\treturn buildCheckResult(result.category, adjusted);\n\t});\n}\n\nfunction adjustBimiForNonMailDomain(results: CheckResult[]): CheckResult[] {\n\treturn results.map((result) => {\n\t\tif (result.category !== 'bimi') return result;\n\t\tconst adjusted = result.findings.map((finding) => {\n\t\t\tif (finding.title === 'No BIMI record found' && finding.detail.includes('eligible for BIMI')) {\n\t\t\t\tconst bimiDomain = finding.detail.match(/at (default\\._bimi\\.\\S+)/)?.[1] ?? `default._bimi.unknown`;\n\t\t\t\treturn {\n\t\t\t\t\t...finding,\n\t\t\t\t\tdetail: `No BIMI record found at ${bimiDomain}. This domain does not appear to send email, so BIMI is not applicable.`,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn finding;\n\t\t});\n\t\treturn buildCheckResult(result.category, adjusted);\n\t});\n}\n\nfunction adjustForNoSendDomain(results: CheckResult[]): CheckResult[] {\n\tconst noSendCategories: CheckCategory[] = ['dkim', 'mta_sts', 'bimi'];\n\treturn results.map((result) => {\n\t\tif (!noSendCategories.includes(result.category)) return result;\n\t\tconst adjusted = result.findings.map((finding) => {\n\t\t\tif ((finding.severity === 'critical' || finding.severity === 'high') && isMissingRecordFinding(finding)) {\n\t\t\t\treturn {\n\t\t\t\t\t...finding,\n\t\t\t\t\tseverity: 'info' as const,\n\t\t\t\t\tdetail: `${finding.detail} (expected — domain SPF policy rejects all outbound mail)`,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn finding;\n\t\t});\n\t\treturn buildCheckResult(result.category, adjusted);\n\t});\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Email Security Maturity Staging.\n * Classifies a domain's email security posture into a maturity stage (0-4)\n * based on the results of individual DNS security checks.\n */\n\nimport type { CheckResult } from '../../lib/scoring';\n\nexport interface MaturityStage {\n\tstage: number;\n\tlabel: string;\n\tdescription: string;\n\tnextStep: string;\n}\n\n/**\n * Compute the email security maturity stage from scan check results.\n * Stages range from 0 (Unprotected) to 4 (Hardened).\n */\n/**\n * Cap the maturity stage based on the overall scan score.\n * Prevents a domain from being labeled \"Hardened\" or \"Enforcing\"\n * when the actual security score indicates significant issues.\n *\n * - Score < 50 (F grade): cap at Stage 2 maximum\n * - Score < 63 (D/D+ grade): cap at Stage 3 maximum\n * - Score >= 63: no cap applied\n *\n * Stages already at or below the cap are returned unchanged.\n */\nexport function capMaturityStage(maturity: MaturityStage, score: number): MaturityStage {\n\tif (score < 50 && maturity.stage > 2) {\n\t\treturn {\n\t\t\tstage: 2,\n\t\t\tlabel: 'Monitoring (score-capped)',\n\t\t\tdescription: 'Controls are present but the overall security score is too low for a higher maturity rating.',\n\t\t\tnextStep: 'Address critical and high-severity findings to improve the overall score before advancing maturity.',\n\t\t};\n\t}\n\n\tif (score < 63 && maturity.stage > 3) {\n\t\treturn {\n\t\t\tstage: 3,\n\t\t\tlabel: 'Enforcing (score-capped)',\n\t\t\tdescription: 'Controls are present but the overall security score is too low for the highest maturity rating.',\n\t\t\tnextStep: 'Resolve remaining findings to raise the score above the D grade range and achieve full hardening.',\n\t\t};\n\t}\n\n\treturn maturity;\n}\n\nexport function computeMaturityStage(checks: CheckResult[]): MaturityStage {\n\tconst byCategory = new Map(checks.map((c) => [c.category, c]));\n\n\tconst mxCheck = byCategory.get('mx');\n\tconst spfCheck = byCategory.get('spf');\n\tconst dmarcCheck = byCategory.get('dmarc');\n\tconst dkimCheck = byCategory.get('dkim');\n\tconst mtaStsCheck = byCategory.get('mta_sts');\n\tconst dnssecCheck = byCategory.get('dnssec');\n\tconst bimiCheck = byCategory.get('bimi');\n\n\t// Non-mail domains should not receive email maturity stages.\n\t// The numeric stage values here (0 = \"Unprotected\", 1 = \"DNS-Only\") intentionally\n\t// reuse the same numbers as the mail-domain scale. This is safe because `stage` is\n\t// only ever rendered as a display value alongside `label` — it is never used as a\n\t// numeric index or compared against mail-domain stages in any downstream logic.\n\tconst hasNoMx = mxCheck != null && mxCheck.findings.some((f) => f.title === 'No MX records found');\n\tif (hasNoMx) {\n\t\tconst hasDnssec = dnssecCheck?.passed ?? false;\n\t\treturn {\n\t\t\tstage: hasDnssec ? 1 : 0,\n\t\t\tlabel: hasDnssec ? 'DNS-Only' : 'Unprotected',\n\t\t\tdescription: hasDnssec\n\t\t\t\t? 'This domain does not accept email. DNS security (DNSSEC) is in place.'\n\t\t\t\t: 'This domain does not accept email and has no DNSSEC.',\n\t\t\tnextStep: hasDnssec ? '' : 'Enable DNSSEC to protect DNS resolution integrity.',\n\t\t};\n\t}\n\n\t// Determine SPF presence\n\tconst hasSpf = spfCheck != null && !spfCheck.findings.some((f) => /No SPF record/i.test(f.title));\n\n\t// Determine DMARC presence and policy\n\tconst hasDmarc = dmarcCheck != null && !dmarcCheck.findings.some((f) => /No DMARC record/i.test(f.title));\n\tconst dmarcPolicyNone = dmarcCheck?.findings.some((f) => /policy set to none/i.test(f.title)) ?? false;\n\tconst dmarcPolicyQuarantine = dmarcCheck?.findings.some((f) => /policy set to quarantine/i.test(f.title)) ?? false;\n\t// reject = no \"policy set to none\" and no \"policy set to quarantine\" and DMARC exists\n\tconst dmarcPolicyReject = hasDmarc && !dmarcPolicyNone && !dmarcPolicyQuarantine;\n\tconst hasRua = dmarcCheck != null && !dmarcCheck.findings.some((f) => /No aggregate reporting/i.test(f.title));\n\n\t// Determine MTA-STS, DNSSEC, BIMI\n\tconst hasMtaSts = mtaStsCheck?.passed ?? false;\n\tconst hasDnssec = dnssecCheck?.passed ?? false;\n\tconst hasBimi = bimiCheck?.findings.some((f) => /BIMI record configured/i.test(f.title)) ?? false;\n\n\t// DANE presence\n\tconst daneCheck = byCategory.get('dane');\n\tconst hasDane = daneCheck?.findings.some((f) => /DANE TLSA configured/i.test(f.title)) ?? false;\n\n\t// CAA presence (passed = CAA records found)\n\tconst caaCheck = byCategory.get('caa');\n\tconst hasCaa = caaCheck?.passed ?? false;\n\n\t// DKIM \"discovered\" = at least one selector physically found (not provider-implied)\n\t// Provider-implied findings have metadata.detectionMethod === 'provider-implied'\n\tconst hasDkimDiscovered =\n\t\tdkimCheck != null &&\n\t\t!dkimCheck.findings.some((f) => /No DKIM records found|DKIM selector not discovered/i.test(f.title)) &&\n\t\t!dkimCheck.findings.some((f) => f.metadata?.detectionMethod === 'provider-implied');\n\n\t// Stage 4 — Hardened: Stage 3 + at least 2 of (MTA-STS, DNSSEC, BIMI, DANE, CAA, DKIM-discovered)\n\t// DKIM is no longer required for Stage 3 — enforcement alone (SPF + DMARC p=quarantine/reject) qualifies\n\tconst isEnforcing = hasSpf && hasDmarc && (dmarcPolicyReject || dmarcPolicyQuarantine);\n\tconst hardeningCount = [hasMtaSts, hasDnssec, hasBimi, hasDane, hasCaa, hasDkimDiscovered].filter(Boolean).length;\n\n\tif (isEnforcing && hardeningCount >= 2) {\n\t\treturn {\n\t\t\tstage: 4,\n\t\t\tlabel: 'Hardened',\n\t\t\tdescription: 'Comprehensive email and DNS security posture with defense in depth.',\n\t\t\tnextStep: '',\n\t\t};\n\t}\n\n\t// Stage 3 — Enforcing: DMARC p=quarantine or p=reject, SPF exists, DKIM exists\n\tif (isEnforcing) {\n\t\treturn {\n\t\t\tstage: 3,\n\t\t\tlabel: 'Enforcing',\n\t\t\tdescription: 'Email authentication is actively enforcing — spoofed emails are blocked or quarantined.',\n\t\t\tnextStep: 'Add MTA-STS, DNSSEC, and BIMI to reach full hardening.',\n\t\t};\n\t}\n\n\t// Stage 2 — Monitoring: SPF + DMARC with p=none and rua= present\n\tif (hasSpf && hasDmarc && dmarcPolicyNone && hasRua) {\n\t\treturn {\n\t\t\tstage: 2,\n\t\t\tlabel: 'Monitoring',\n\t\t\tdescription: 'Email authentication is published and being monitored but not enforcing.',\n\t\t\tnextStep: 'After reviewing DMARC reports, move to p=quarantine and ensure DKIM is active.',\n\t\t};\n\t}\n\n\t// Stage 1 — Basic: SPF exists but DMARC is p=none or DMARC has no rua=\n\tif (hasSpf && hasDmarc) {\n\t\treturn {\n\t\t\tstage: 1,\n\t\t\tlabel: 'Basic',\n\t\t\tdescription: 'Basic email records exist but are not enforcing or monitoring.',\n\t\t\tnextStep: 'Add DMARC aggregate reporting (rua=) and monitor for 2-4 weeks before enforcing.',\n\t\t};\n\t}\n\n\t// Stage 0 — Unprotected\n\treturn {\n\t\tstage: 0,\n\t\tlabel: 'Unprotected',\n\t\tdescription: 'No email authentication — any server can send email as this domain.',\n\t\tnextStep: 'Publish SPF and DMARC records to begin protecting your domain.',\n\t};\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport type { ScanDomainResult } from '../scan-domain';\nimport type { OutputFormat } from '../../handlers/tool-args';\nimport { sanitizeOutputText } from '../../lib/output-sanitize';\nimport { resolveImpactNarrative } from '../explain-finding';\n\n/** Structured scan result for machine-readable consumption (e.g., CI/CD actions). */\nexport interface StructuredScanResult {\n\tdomain: string;\n\tscore: number;\n\tgrade: string;\n\tpassed: boolean;\n\tmaturityStage: number | null;\n\tmaturityLabel: string | null;\n\tcategoryScores: Record<string, number>;\n\tfindingCounts: { critical: number; high: number; medium: number; low: number };\n\tscoringProfile: string;\n\tscoringSignals: string[];\n\tscoringNote: string | null;\n\tadaptiveWeightDeltas: Record<string, number> | null;\n\t/** Percentile rank within the scoring profile population (0–100). Null when insufficient benchmark data. */\n\tpercentileRank: number | null;\n\t/** Composite email spoofability score (0–100, higher = more spoofable). Null when not computed. */\n\tspoofabilityScore: number | null;\n\t/** Category interaction effects applied as post-scoring adjustments. */\n\tinteractionEffects: Array<{ ruleId: string; penalty: number; narrative: string }>;\n\ttimestamp: string;\n\tcached: boolean;\n}\n\n/** Optional enrichment data for structured scan results. */\nexport interface ScanResultEnrichment {\n\tpercentileRank?: number | null;\n\tspoofabilityScore?: number | null;\n}\n\n/** Build a machine-readable structured result from a scan. */\nexport function buildStructuredScanResult(result: ScanDomainResult, enrichment?: ScanResultEnrichment): StructuredScanResult {\n\treturn {\n\t\tdomain: result.domain,\n\t\tscore: result.score.overall,\n\t\tgrade: result.score.grade,\n\t\tpassed: result.score.overall >= 50,\n\t\tmaturityStage: result.maturity?.stage ?? null,\n\t\tmaturityLabel: result.maturity?.label ?? null,\n\t\tcategoryScores: result.score.categoryScores,\n\t\tfindingCounts: {\n\t\t\tcritical: result.score.findings.filter((f) => f.severity === 'critical').length,\n\t\t\thigh: result.score.findings.filter((f) => f.severity === 'high').length,\n\t\t\tmedium: result.score.findings.filter((f) => f.severity === 'medium').length,\n\t\t\tlow: result.score.findings.filter((f) => f.severity === 'low').length,\n\t\t},\n\t\tscoringProfile: result.context?.profile ?? 'mail_enabled',\n\t\tscoringSignals: (result.context?.signals ?? []).map((s) => s.replace(/[<>&\"']/g, '')),\n\t\tscoringNote: result.scoringNote ?? null,\n\t\tadaptiveWeightDeltas: result.adaptiveWeightDeltas ?? null,\n\t\tpercentileRank: enrichment?.percentileRank ?? null,\n\t\tspoofabilityScore: enrichment?.spoofabilityScore ?? null,\n\t\tinteractionEffects: (result.interactionEffects ?? []).map((e) => ({\n\t\t\truleId: e.ruleId,\n\t\t\tpenalty: e.penalty,\n\t\t\tnarrative: e.narrative,\n\t\t})),\n\t\ttimestamp: result.timestamp,\n\t\tcached: result.cached,\n\t};\n}\n\nexport function formatScanReport(result: ScanDomainResult, format: OutputFormat = 'full'): string {\n\tconst lines: string[] = [];\n\n\tlines.push(`DNS Security Scan: ${result.domain}`);\n\tlines.push(`${'='.repeat(40)}`);\n\tlines.push(`Overall Score: ${result.score.overall}/100 (${result.score.grade})`);\n\tlines.push(`${result.score.summary}`);\n\tlines.push('');\n\n\tif (result.maturity) {\n\t\tif (format === 'compact') {\n\t\t\tlines.push(`Maturity: Stage ${result.maturity.stage} — ${result.maturity.label}`);\n\t\t} else {\n\t\t\tlines.push(`Email Security Maturity: Stage ${result.maturity.stage} — ${result.maturity.label}`);\n\t\t\tlines.push(result.maturity.description);\n\t\t\tif (result.maturity.nextStep) {\n\t\t\t\tlines.push(`Next step: ${result.maturity.nextStep}`);\n\t\t\t}\n\t\t}\n\t\tlines.push('');\n\t}\n\n\tif (format === 'full') {\n\t\tif (result.context) {\n\t\t\tconst signalSummary = result.context.signals.length > 0 ? result.context.signals.join(', ') : 'default';\n\t\t\tlines.push(`Scoring Profile: ${result.context.profile} (${signalSummary})`);\n\t\t\tlines.push('');\n\t\t}\n\n\t\tif (result.scoringNote) {\n\t\t\tlines.push(result.scoringNote);\n\t\t\tlines.push('');\n\t\t}\n\t}\n\n\tlines.push('Category Scores:');\n\tlines.push('-'.repeat(30));\n\tfor (const [category, score] of Object.entries(result.score.categoryScores)) {\n\t\tconst status = score >= 80 ? '✓' : score >= 50 ? '⚠' : '✗';\n\t\tlines.push(` ${status} ${category.toUpperCase().padEnd(10)} ${score}/100`);\n\t}\n\tlines.push('');\n\n\tconst nonInfoFindings = result.score.findings.filter((finding) => finding.severity !== 'info');\n\tif (nonInfoFindings.length > 0) {\n\t\tlines.push('Findings:');\n\t\tlines.push('-'.repeat(30));\n\t\tfor (const finding of nonInfoFindings) {\n\t\t\tif (format === 'compact') {\n\t\t\t\tlines.push(` [${finding.severity.toUpperCase()}] ${sanitizeOutputText(finding.title, 120)} — ${sanitizeOutputText(finding.detail, 200)}`);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlines.push(` [${finding.severity.toUpperCase()}] ${sanitizeOutputText(finding.title, 120)}`);\n\t\t\tlines.push(` ${sanitizeOutputText(finding.detail)}`);\n\t\t\tconst verificationStatus =\n\t\t\t\tfinding.category === 'subdomain_takeover' && finding.metadata?.verificationStatus\n\t\t\t\t\t? String(finding.metadata.verificationStatus)\n\t\t\t\t\t: undefined;\n\t\t\tif (verificationStatus) {\n\t\t\t\tlines.push(` Takeover Verification: ${sanitizeOutputText(verificationStatus, 80)}`);\n\t\t\t}\n\t\t\tconst confidence = finding.metadata?.confidence ? String(finding.metadata.confidence) : undefined;\n\t\t\tif (confidence) {\n\t\t\t\tlines.push(` Confidence: ${sanitizeOutputText(confidence, 80)}`);\n\t\t\t}\n\t\t\tconst narrative = resolveImpactNarrative({\n\t\t\t\tcategory: finding.category,\n\t\t\t\tseverity: finding.severity,\n\t\t\t\ttitle: finding.title,\n\t\t\t\tdetail: finding.detail,\n\t\t\t});\n\t\t\tif (narrative.impact) {\n\t\t\t\tlines.push(` Potential Impact: ${narrative.impact}`);\n\t\t\t}\n\t\t\tif (narrative.adverseConsequences) {\n\t\t\t\tlines.push(` Adverse Consequences: ${narrative.adverseConsequences}`);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tlines.push('No security issues found.');\n\t}\n\n\tif (format === 'full' && result.interactionEffects && result.interactionEffects.length > 0) {\n\t\tlines.push('');\n\t\tlines.push('Interaction Effects:');\n\t\tlines.push('-'.repeat(30));\n\t\tfor (const effect of result.interactionEffects) {\n\t\t\tlines.push(` [-${effect.penalty}] ${effect.narrative}`);\n\t\t}\n\t}\n\n\tif (result.cached) {\n\t\tlines.push('');\n\t\tlines.push('(Results served from cache)');\n\t}\n\n\tlines.push('');\n\tlines.push(`Scan completed: ${result.timestamp}`);\n\treturn lines.join('\\n');\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * scan-domain orchestrator tool.\n * Runs all DNS security checks in parallel via Promise.all\n * and computes an overall security score.\n *\n * Uses KV-backed cache with 5-minute TTL for scan results when available,\n * with in-memory fallback when KV is not configured.\n * Compatible with Cloudflare Workers runtime (no Node.js APIs).\n */\n\nimport {\n\ttype CheckCategory,\n\ttype CheckResult,\n\ttype DomainContext,\n\ttype DomainProfile,\n\ttype ScanScore,\n\tbuildCheckResult,\n\tcomputeScanScore,\n\tcreateFinding,\n\tdetectDomainContext,\n\tgetProfileWeights,\n} from '../lib/scoring';\nimport {\n\tadaptiveWeightsToContext,\n\tgenerateScoringNote,\n\ttype AdaptiveWeightsResponse,\n\ttype ScanTelemetry,\n} from '../lib/adaptive-weights';\nimport { applyInteractionPenalties, type InteractionEffect } from '../lib/category-interactions';\nimport { cacheGet, cacheSet, runWithCache } from '../lib/cache';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { checkSpf } from './check-spf';\nimport { checkDmarc } from './check-dmarc';\nimport { checkDkim, applyProviderDkimContext } from './check-dkim';\nimport { checkDnssec } from './check-dnssec';\nimport { checkSsl } from './check-ssl';\nimport { checkMtaSts } from './check-mta-sts';\nimport { checkNs } from './check-ns';\nimport { checkCaa } from './check-caa';\nimport { checkBimi } from './check-bimi';\nimport { checkTlsrpt } from './check-tlsrpt';\nimport { checkSubdomainTakeover } from './check-subdomain-takeover';\nimport { checkMx } from './check-mx';\nimport { checkHttpSecurity } from './check-http-security';\nimport { checkDane } from './check-dane';\nimport { checkDaneHttps } from './check-dane-https';\nimport { checkSvcbHttps } from './check-svcb-https';\nimport { applyScanPostProcessing } from './scan/post-processing';\nimport type { ScanRuntimeOptions } from './scan/post-processing';\nimport { capMaturityStage, computeMaturityStage } from './scan/maturity-staging';\nimport type { MaturityStage } from './scan/maturity-staging';\nexport { formatScanReport, buildStructuredScanResult } from './scan/format-report';\nexport type { StructuredScanResult, ScanResultEnrichment } from './scan/format-report';\nexport type { MaturityStage } from './scan/maturity-staging';\nexport type { ScanRuntimeOptions } from './scan/post-processing';\n\n/** Cache key prefix for scan and per-check results */\nconst CACHE_PREFIX = 'cache:';\n\n/** Maximum wall-clock time for a single check within scan_domain (ms). */\nconst PER_CHECK_TIMEOUT_MS = 8_000;\n\n/** Maximum wall-clock time for the entire scan_domain orchestration (ms). */\nconst SCAN_TIMEOUT_MS = 12_000;\n\n/** In-memory cache for adaptive weight responses from the ProfileAccumulator DO. */\nconst adaptiveWeightCache = new Map<string, { weights: AdaptiveWeightsResponse; expires: number }>();\n\n/** TTL for the in-memory adaptive weight cache (ms). */\nconst ADAPTIVE_CACHE_TTL_MS = 60_000;\n\n/** Maximum entries in the adaptive weight cache before eviction. */\nconst ADAPTIVE_CACHE_MAX_ENTRIES = 100;\n\n/** Timeout for fetching adaptive weights from the DO (ms). */\nconst ADAPTIVE_FETCH_TIMEOUT_MS = 200;\n\nexport interface ScanDomainResult {\n\tdomain: string;\n\tscore: ScanScore;\n\tchecks: CheckResult[];\n\tmaturity: MaturityStage;\n\tcontext: DomainContext;\n\tcached: boolean;\n\ttimestamp: string;\n\tscoringNote: string | null;\n\tadaptiveWeightDeltas: Record<string, number> | null;\n\t/** Category interaction effects applied as post-scoring adjustments. Empty when no interactions triggered. */\n\tinteractionEffects: InteractionEffect[];\n}\n\n/**\n * Run a full DNS security scan on a domain.\n * Executes all checks in parallel and computes an overall score.\n *\n * @param domain - The domain to scan (must already be validated and sanitized by the caller)\n * @param kv - Optional KV namespace for persistent scan result caching\n * @returns Full scan result with score, individual check results, and metadata\n */\nexport async function scanDomain(domain: string, kv?: KVNamespace, runtimeOptions?: ScanRuntimeOptions): Promise<ScanDomainResult> {\n\tconst explicitProfile = runtimeOptions?.profile;\n\tconst isExplicit = explicitProfile && explicitProfile !== 'auto';\n\tconst cacheKey = isExplicit\n\t\t? `${CACHE_PREFIX}${domain}:profile:${explicitProfile}`\n\t\t: `${CACHE_PREFIX}${domain}`;\n\n\t// Check cache first (skip when force_refresh is requested)\n\tif (!runtimeOptions?.forceRefresh) {\n\t\tconst cached = await cacheGet<ScanDomainResult>(cacheKey, kv);\n\t\tif (cached) {\n\t\t\treturn { ...cached, cached: true };\n\t\t}\n\t}\n\n\t// Run all checks in parallel with per-check timeouts, wrapped in an\n\t// overall scan timeout to guarantee a timely response.\n\t// Uses Promise.allSettled so that completed checks are preserved on timeout.\n\tconst ALL_CHECK_CATEGORIES: CheckCategory[] = [\n\t\t'spf', 'dmarc', 'dkim', 'dnssec', 'ssl', 'mta_sts', 'ns', 'caa', 'bimi', 'tlsrpt', 'subdomain_takeover', 'http_security', 'dane', 'mx', 'dane_https', 'svcb_https',\n\t];\n\n\t// Skip secondary DNS confirmation in scan context for speed — individual checks\n\t// still use secondary confirmation when called directly by users.\n\tconst scanDns: QueryDnsOptions = {\n\t\tskipSecondaryConfirmation: true,\n\t\tqueryCache: new Map(),\n\t\tsecondaryDoh: runtimeOptions?.secondaryDoh,\n\t};\n\n\tconst forceRefresh = runtimeOptions?.forceRefresh;\n\tconst cacheTtl = runtimeOptions?.cacheTtlSeconds;\n\n\tconst checkPromises = [\n\t\trunCachedCheck(domain, 'spf', () => safeCheck('spf', () => checkSpf(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'dmarc', () => safeCheck('dmarc', () => checkDmarc(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'dkim', () => safeCheck('dkim', () => checkDkim(domain, undefined, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'dnssec', () => safeCheck('dnssec', () => checkDnssec(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'ssl', () => safeCheck('ssl', () => checkSsl(domain)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'mta_sts', () => safeCheck('mta_sts', () => checkMtaSts(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'ns', () => safeCheck('ns', () => checkNs(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'caa', () => safeCheck('caa', () => checkCaa(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'bimi', () => safeCheck('bimi', () => checkBimi(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'tlsrpt', () => safeCheck('tlsrpt', () => checkTlsrpt(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'subdomain_takeover', () => safeCheck('subdomain_takeover', () => checkSubdomainTakeover(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'http_security', () => safeCheck('http_security', () => checkHttpSecurity(domain)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'dane', () => safeCheck('dane', () => checkDane(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'dane_https', () => safeCheck('dane_https', () => checkDaneHttps(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'svcb_https', () => safeCheck('svcb_https', () => checkSvcbHttps(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(\n\t\t\tdomain,\n\t\t\t'mx',\n\t\t\t() =>\n\t\t\t\tsafeCheck(\n\t\t\t\t\t'mx',\n\t\t\t\t\t() =>\n\t\t\t\t\t\tcheckMx(domain, {\n\t\t\t\t\t\t\tproviderSignaturesUrl: runtimeOptions?.providerSignaturesUrl,\n\t\t\t\t\t\t\tproviderSignaturesAllowedHosts: runtimeOptions?.providerSignaturesAllowedHosts,\n\t\t\t\t\t\t\tproviderSignaturesSha256: runtimeOptions?.providerSignaturesSha256,\n\t\t\t\t\t\t}, scanDns),\n\t\t\t\t),\n\t\t\tkv,\n\t\t\tcacheTtl,\n\t\t\tforceRefresh,\n\t\t),\n\t];\n\n\tlet timedOut = false;\n\tconst settled = await Promise.race([\n\t\tPromise.allSettled(checkPromises),\n\t\tnew Promise<PromiseSettledResult<CheckResult>[]>((resolve) =>\n\t\t\tsetTimeout(() => {\n\t\t\t\ttimedOut = true;\n\t\t\t\t// Snapshot whatever has settled so far by racing each promise with an immediate rejection\n\t\t\t\tresolve(\n\t\t\t\t\tPromise.allSettled(\n\t\t\t\t\t\tcheckPromises.map((p) => Promise.race([p, new Promise<never>((_, reject) => reject(new Error('__check_pending__')))])),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}, SCAN_TIMEOUT_MS),\n\t\t),\n\t]);\n\n\tlet checkResults = settled\n\t\t.filter((r): r is PromiseFulfilledResult<CheckResult> => r.status === 'fulfilled')\n\t\t.map((r) => r.value);\n\n\t// For any checks that didn't complete, add a timeout finding\n\tif (timedOut) {\n\t\tconst completedCategories = new Set(checkResults.map((r) => r.category));\n\t\tfor (const category of ALL_CHECK_CATEGORIES) {\n\t\t\tif (!completedCategories.has(category)) {\n\t\t\t\tcheckResults.push(\n\t\t\t\t\tbuildCheckResult(category, [\n\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\tcategory,\n\t\t\t\t\t\t\t`${category.toUpperCase()} check timed out`,\n\t\t\t\t\t\t\t'low',\n\t\t\t\t\t\t\t`Check did not complete within the ${SCAN_TIMEOUT_MS / 1000}s scan time limit. Try running this check individually.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tlet result: ScanDomainResult;\n\ttry {\n\t\tcheckResults = await applyScanPostProcessing(domain, checkResults, runtimeOptions);\n\n\t\t// Detect domain context from check results\n\t\tlet domainContext = detectDomainContext(checkResults);\n\n\t\t// If an explicit profile was requested, override detection\n\t\tif (isExplicit) {\n\t\t\tdomainContext = {\n\t\t\t\tprofile: explicitProfile as DomainProfile,\n\t\t\t\tsignals: [...domainContext.signals, `explicit profile override: ${explicitProfile}`],\n\t\t\t\tweights: getProfileWeights(explicitProfile as DomainProfile, runtimeOptions?.scoringConfig),\n\t\t\t\tdetectedProvider: domainContext.detectedProvider,\n\t\t\t};\n\t\t}\n\n\t\t// Apply provider-informed DKIM adjustment: when a known DKIM-signing\n\t\t// provider is detected via MX, downgrade the \"not found\" finding since\n\t\t// the provider likely signs by default with a custom selector.\n\t\tif (domainContext.detectedProvider) {\n\t\t\tconst dkimIdx = checkResults.findIndex((r) => r.category === 'dkim');\n\t\t\tif (dkimIdx !== -1) {\n\t\t\t\tcheckResults[dkimIdx] = applyProviderDkimContext(checkResults[dkimIdx], domainContext.detectedProvider);\n\t\t\t}\n\t\t}\n\n\t\t// Phase 1: only pass context to scoring when an explicit profile is set.\n\t\t// For 'auto' (or unset), detection runs and is reported but scoring\n\t\t// uses the default weights (identical to pre-profile behavior).\n\t\tconst scoringContext = isExplicit ? domainContext : undefined;\n\n\t\t// Attempt to fetch adaptive weights from the ProfileAccumulator DO\n\t\tlet adaptiveResponse: AdaptiveWeightsResponse | null = null;\n\t\tif (runtimeOptions?.profileAccumulator) {\n\t\t\tadaptiveResponse = await fetchAdaptiveWeights(\n\t\t\t\truntimeOptions.profileAccumulator,\n\t\t\t\tdomainContext.profile,\n\t\t\t\tdomainContext.detectedProvider,\n\t\t\t);\n\t\t}\n\n\t\t// Add bound hits to signals if present\n\t\tif (adaptiveResponse?.boundHits.length) {\n\t\t\tdomainContext.signals.push(`adaptive bound hits: ${adaptiveResponse.boundHits.join(', ')}`);\n\t\t}\n\n\t\tlet score: ScanScore;\n\t\tlet scoringNote: string | null = null;\n\t\tlet adaptiveWeightDeltas: Record<string, number> | null = null;\n\n\t\tif (adaptiveResponse && adaptiveResponse.sampleCount > 0) {\n\t\t\tconst adaptiveWeights = adaptiveWeightsToContext(adaptiveResponse.weights, domainContext.profile);\n\t\t\tif (adaptiveWeights) {\n\t\t\t\t// Compute adaptive score\n\t\t\t\tconst adaptiveContext: DomainContext = { ...domainContext, weights: adaptiveWeights };\n\t\t\t\tconst adaptiveScore = computeScanScore(checkResults, adaptiveContext, runtimeOptions?.scoringConfig);\n\n\t\t\t\t// Compute static score for comparison\n\t\t\t\tconst staticContext: DomainContext = {\n\t\t\t\t\t...domainContext,\n\t\t\t\t\tweights: getProfileWeights(domainContext.profile, runtimeOptions?.scoringConfig),\n\t\t\t\t};\n\t\t\t\tconst staticScore = computeScanScore(checkResults, scoringContext ?? staticContext, runtimeOptions?.scoringConfig);\n\n\t\t\t\t// Compute per-category weight deltas\n\t\t\t\tconst staticWeights = getProfileWeights(domainContext.profile, runtimeOptions?.scoringConfig);\n\t\t\t\tconst deltas: Record<string, number> = {};\n\t\t\t\tfor (const cat of Object.keys(staticWeights) as CheckCategory[]) {\n\t\t\t\t\tdeltas[cat] = adaptiveWeights[cat].importance - staticWeights[cat].importance;\n\t\t\t\t}\n\n\t\t\t\tconst scoreDelta = adaptiveScore.overall - staticScore.overall;\n\t\t\t\tscoringNote = generateScoringNote(deltas, scoreDelta, domainContext.detectedProvider);\n\t\t\t\tadaptiveWeightDeltas = deltas;\n\t\t\t\tscore = adaptiveScore;\n\t\t\t} else {\n\t\t\t\tscore = computeScanScore(checkResults, scoringContext, runtimeOptions?.scoringConfig);\n\t\t\t}\n\t\t} else {\n\t\t\tscore = computeScanScore(checkResults, scoringContext, runtimeOptions?.scoringConfig);\n\t\t}\n\n\t\t// Apply category interaction penalties (post-scoring adjustment)\n\t\tconst { adjustedScore, effects: interactionEffects } = applyInteractionPenalties(score, runtimeOptions?.scoringConfig);\n\t\tscore = adjustedScore;\n\n\t\tconst rawMaturity = computeMaturityStage(checkResults);\n\t\tconst maturity = capMaturityStage(rawMaturity, score.overall);\n\n\t\tresult = {\n\t\t\tdomain,\n\t\t\tscore,\n\t\t\tchecks: checkResults,\n\t\t\tmaturity,\n\t\t\tcontext: domainContext,\n\t\t\tcached: false,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tscoringNote,\n\t\t\tadaptiveWeightDeltas,\n\t\t\tinteractionEffects,\n\t\t};\n\n\t\t// POST telemetry to DO (best-effort, non-blocking)\n\t\tif (runtimeOptions?.profileAccumulator) {\n\t\t\tconst telemetry: ScanTelemetry = {\n\t\t\t\tprofile: domainContext.profile,\n\t\t\t\tprovider: domainContext.detectedProvider,\n\t\t\t\tcategoryFindings: checkResults.map((r) => ({ category: r.category, score: r.score, passed: r.passed })),\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\toverallScore: score.overall,\n\t\t\t};\n\t\t\tconst telemetryPromise = (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst stub = runtimeOptions.profileAccumulator!.get(\n\t\t\t\t\t\truntimeOptions.profileAccumulator!.idFromName('global'),\n\t\t\t\t\t);\n\t\t\t\t\tawait stub.fetch(\n\t\t\t\t\t\tnew Request('https://do/ingest', {\n\t\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\t\t\t\t\tbody: JSON.stringify(telemetry),\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t} catch {\n\t\t\t\t\t/* best-effort */\n\t\t\t\t}\n\t\t\t})();\n\t\t\tif (runtimeOptions.waitUntil) runtimeOptions.waitUntil(telemetryPromise);\n\t\t}\n\t} catch {\n\t\t// Post-processing or scoring failed — return whatever we have\n\t\tlet fallbackContext = detectDomainContext(checkResults);\n\t\tif (isExplicit) {\n\t\t\tfallbackContext = {\n\t\t\t\tprofile: explicitProfile as DomainProfile,\n\t\t\t\tsignals: [...fallbackContext.signals, `explicit profile override: ${explicitProfile}`],\n\t\t\t\tweights: getProfileWeights(explicitProfile as DomainProfile, runtimeOptions?.scoringConfig),\n\t\t\t\tdetectedProvider: fallbackContext.detectedProvider,\n\t\t\t};\n\t\t}\n\t\tconst fallbackScoringContext = isExplicit ? fallbackContext : undefined;\n\t\tconst score = computeScanScore(checkResults, fallbackScoringContext, runtimeOptions?.scoringConfig);\n\t\tconst rawMaturity = computeMaturityStage(checkResults);\n\t\tconst maturity = capMaturityStage(rawMaturity, score.overall);\n\t\tresult = {\n\t\t\tdomain,\n\t\t\tscore,\n\t\t\tchecks: checkResults,\n\t\t\tmaturity,\n\t\t\tcontext: fallbackContext,\n\t\t\tcached: false,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tscoringNote: null,\n\t\t\tadaptiveWeightDeltas: null,\n\t\t\tinteractionEffects: [],\n\t\t};\n\t}\n\n\t// Cache the result (use configurable TTL if provided)\n\t// Defer the write via waitUntil when available to avoid blocking the response.\n\tconst cachePromise = cacheSet(cacheKey, result, kv, runtimeOptions?.cacheTtlSeconds);\n\tif (runtimeOptions?.waitUntil) {\n\t\truntimeOptions.waitUntil(cachePromise);\n\t} else {\n\t\tawait cachePromise;\n\t}\n\n\treturn result;\n}\n\n/**\n * Fetch adaptive weights from the ProfileAccumulator DO with in-memory caching.\n * Returns null on failure or timeout (silently falls back to static weights).\n */\nasync function fetchAdaptiveWeights(\n\taccumulator: DurableObjectNamespace,\n\tprofile: string,\n\tprovider: string | null,\n): Promise<AdaptiveWeightsResponse | null> {\n\tconst cacheKey = `${profile}:${provider ?? ''}`;\n\tconst now = Date.now();\n\n\t// Check in-memory cache first\n\tconst cached = adaptiveWeightCache.get(cacheKey);\n\tif (cached && cached.expires > now) {\n\t\treturn cached.weights;\n\t}\n\n\ttry {\n\t\tconst stub = accumulator.get(accumulator.idFromName('global'));\n\t\tconst url = new URL('https://do/weights');\n\t\turl.searchParams.set('profile', profile);\n\t\tif (provider) url.searchParams.set('provider', provider);\n\n\t\tconst response = await Promise.race([\n\t\t\tstub.fetch(new Request(url.toString())),\n\t\t\tnew Promise<never>((_, reject) => setTimeout(() => reject(new Error('adaptive weight fetch timeout')), ADAPTIVE_FETCH_TIMEOUT_MS)),\n\t\t]);\n\n\t\tif (!response.ok) return null;\n\n\t\tconst data = (await response.json()) as AdaptiveWeightsResponse;\n\t\tif (adaptiveWeightCache.size >= ADAPTIVE_CACHE_MAX_ENTRIES) {\n\t\t\tevictAdaptiveWeightCache();\n\t\t}\n\t\tadaptiveWeightCache.set(cacheKey, { weights: data, expires: now + ADAPTIVE_CACHE_TTL_MS });\n\t\treturn data;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Evict entries from the adaptive weight cache.\n * Removes expired entries first, then if still at capacity, evicts the entry with the oldest expiry time.\n */\nexport function evictAdaptiveWeightCache(): void {\n\tconst now = Date.now();\n\n\t// First pass: remove all expired entries\n\tfor (const [key, entry] of adaptiveWeightCache) {\n\t\tif (entry.expires <= now) {\n\t\t\tadaptiveWeightCache.delete(key);\n\t\t}\n\t}\n\n\t// If still at capacity after removing expired entries, evict the oldest by expiry\n\tif (adaptiveWeightCache.size >= ADAPTIVE_CACHE_MAX_ENTRIES) {\n\t\tlet oldestKey: string | null = null;\n\t\tlet oldestExpiry = Infinity;\n\t\tfor (const [key, entry] of adaptiveWeightCache) {\n\t\t\tif (entry.expires < oldestExpiry) {\n\t\t\t\toldestExpiry = entry.expires;\n\t\t\t\toldestKey = key;\n\t\t\t}\n\t\t}\n\t\tif (oldestKey !== null) {\n\t\t\tadaptiveWeightCache.delete(oldestKey);\n\t\t}\n\t}\n}\n\n/** Exposed for testing only — do not use in production code. */\nexport const _adaptiveWeightCacheForTest = adaptiveWeightCache;\n\nasync function runCachedCheck(\n\tdomain: string,\n\tcategory: CheckCategory,\n\trun: () => Promise<CheckResult>,\n\tkv?: KVNamespace,\n\tttlSeconds?: number,\n\tskipCache?: boolean,\n): Promise<CheckResult> {\n\treturn runWithCache(`${CACHE_PREFIX}${domain}:check:${category}`, run, kv, ttlSeconds, skipCache);\n}\n\n/**\n * Run a single check with error handling and a per-check timeout.\n * If a check fails or exceeds the timeout, returns a failed CheckResult\n * with an error/timeout finding instead of throwing, so other checks\n * can still complete.\n */\nasync function safeCheck(category: CheckCategory, fn: () => Promise<CheckResult>): Promise<CheckResult> {\n\ttry {\n\t\tconst result = await Promise.race([\n\t\t\tfn(),\n\t\t\tnew Promise<never>((_, reject) => setTimeout(() => reject(new Error('Check timed out')), PER_CHECK_TIMEOUT_MS)),\n\t\t]);\n\t\treturn result;\n\t} catch (err) {\n\t\tconst rawMessage = err instanceof Error ? err.message : 'Check failed';\n\t\tconst SAFE_PREFIXES = ['DNS query', 'Check timed out', 'Check failed', 'Connection', 'timeout'];\n\t\tconst safeMessage = SAFE_PREFIXES.some((p) => rawMessage.startsWith(p)) ? rawMessage : 'Check failed';\n\t\tconst findings = [createFinding(category, `${category.toUpperCase()} check error`, 'high', `Check failed: ${safeMessage}`)];\n\t\treturn buildCheckResult(category, findings);\n\t}\n}\n\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/dns-types.ts","../src/lib/config.ts","../src/schemas/dns.ts","../src/lib/dns-transport.ts","../src/lib/dns-records.ts","../src/lib/adaptive-weights.ts","../src/lib/sanitize.ts","../src/lib/server-version.ts","../src/schemas/primitives.ts","../src/schemas/tool-args.ts","../src/schemas/tool-definitions.ts","../src/tools/check-bimi.ts","../src/tools/check-caa.ts","../src/tools/check-dkim.ts","../src/tools/check-dmarc.ts","../src/tools/check-dnssec.ts","../src/tools/lookalike-analysis.ts","../src/tools/check-lookalikes.ts","../src/tools/check-mta-sts.ts","../src/lib/provider-signature-source.ts","../src/lib/provider-signatures.ts","../src/tools/check-mx.ts","../src/tools/check-ns.ts","../src/tools/check-spf.ts","../src/tools/check-ssl.ts","../src/tools/check-subdomain-takeover.ts","../src/tools/check-tlsrpt.ts","../src/lib/output-sanitize.ts","../src/tools/explain-finding-data.ts","../src/tools/explain-finding.ts","../src/lib/category-interactions.ts","../src/lib/log.ts","../src/lib/cache.ts","../src/tools/check-http-security.ts","../src/tools/check-dane.ts","../src/tools/check-dane-https.ts","../src/tools/check-svcb-https.ts","../src/tools/check-subdomailing.ts","../src/tools/scan/post-processing.ts","../src/tools/scan/maturity-staging.ts","../src/tools/scan/format-report.ts","../src/tools/scan-domain.ts"],"names":["topCat","topDelta","z","makeQueryDNS","createFinding","buildCheckResult","checkDnssec","normalizeDomain","checkSubdomainTakeoverPkg","lines","scoreToGrade","checkSubdomailingCore","evidence","getParentDomain","hasDnssec","result","detectDomainContext","getProfileWeights"],"mappings":"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","file":"index.js","sourcesContent":["// SPDX-License-Identifier: BUSL-1.1\n\n/** Standard DNS record type codes */\nexport const RecordType = {\n\tA: 1,\n\tAAAA: 28,\n\tCNAME: 5,\n\tMX: 15,\n\tTXT: 16,\n\tNS: 2,\n\tSOA: 6,\n\tCAA: 257,\n\tTLSA: 52,\n\tDNSKEY: 48,\n\tDS: 43,\n\tRRSIG: 46,\n\tPTR: 12,\n\tSRV: 33,\n\tHTTPS: 65,\n} as const;\n\nexport type RecordTypeName = keyof typeof RecordType;\n\n/** A single DNS answer record from the DoH JSON response */\nexport interface DnsAnswer {\n\tname: string;\n\ttype: number;\n\tTTL: number;\n\tdata: string;\n}\n\n/** A single DNS authority record */\nexport interface DnsAuthority {\n\tname: string;\n\ttype: number;\n\tTTL: number;\n\tdata: string;\n}\n\n/** Cloudflare DoH JSON wire-format response */\nexport interface DohResponse {\n\tStatus: number;\n\tTC: boolean;\n\tRD: boolean;\n\tRA: boolean;\n\tAD: boolean;\n\tCD: boolean;\n\tQuestion: Array<{ name: string; type: number }>;\n\tAnswer?: DnsAnswer[];\n\tAuthority?: DnsAuthority[];\n}\n\n/** Configuration for a custom secondary DoH resolver (e.g., bv-dns on Oracle Cloud). */\nexport interface SecondaryDohConfig {\n\t/** DoH endpoint URL (e.g. https://doh.example.com/dns-query) */\n\tendpoint: string;\n\t/** Optional auth token sent as X-BV-Token header */\n\ttoken?: string;\n}\n\nexport interface QueryDnsOptions {\n\ttimeoutMs?: number;\n\tretries?: number;\n\tconfirmWithSecondaryOnEmpty?: boolean;\n\t/** When true, skip secondary resolver confirmation on empty results. Used in scan context for speed. */\n\tskipSecondaryConfirmation?: boolean;\n\t/** Scan-scoped DNS query cache. Stores Promises keyed by `domain:type:dnssecCheck` to deduplicate concurrent and sequential identical queries within a single scan. */\n\tqueryCache?: Map<string, Promise<DohResponse>>;\n\t/** Custom secondary DoH resolver. When set, used instead of Google DoH for empty-result confirmation. Falls back to Google if this resolver fails. */\n\tsecondaryDoh?: SecondaryDohConfig;\n}","// SPDX-License-Identifier: BUSL-1.1\n\nimport type { Tier } from '../schemas/primitives';\n\n/**\n * Centralized configuration for domain normalization and validation.\n */\nexport const BLOCKED_SUFFIXES = [\n\t'.local',\n\t'.localhost',\n\t'.internal',\n\t'.example',\n\t'.invalid',\n\t'.test',\n\t'.onion',\n\t'.lan',\n\t'.home',\n\t'.corp',\n\t'.intranet',\n];\nexport const BLOCKED_HOSTS = ['localhost', 'localhost.localdomain'];\nexport const BLOCKED_IP_PATTERNS = [\n\t/^127\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$/,\n\t/^10\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$/,\n\t/^172\\.(1[6-9]|2[0-9]|3[01])\\.[0-9]{1,3}\\.[0-9]{1,3}$/,\n\t/^192\\.168\\.[0-9]{1,3}\\.[0-9]{1,3}$/,\n\t/^169\\.254\\.[0-9]{1,3}\\.[0-9]{1,3}$/,\n\t/^0\\.0\\.0\\.0$/,\n\t/^::1$/,\n\t/^fc00:/i,\n\t/^fd[0-9a-f]{2}:/i,\n\t/^fe[89ab][0-9a-f]:/i,\n];\nexport const BLOCKED_DNS_REBINDING = ['.nip.io', '.sslip.io', '.xip.io', '.nip.direct'];\nexport const MAX_DOMAIN_LENGTH = 253;\nexport const MAX_LABEL_LENGTH = 63;\nexport const LABEL_REGEX = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/i;\n\n/** Hard limit on incoming JSON-RPC request body size (bytes). */\nexport const MAX_REQUEST_BODY_BYTES = 10_240;\n\n/** Timeout for outbound HTTPS fetches (SSL, MTA-STS policy, etc.). */\nexport const HTTPS_TIMEOUT_MS = 4_000;\n\n/** Default timeout for DNS-over-HTTPS queries. CF DoH p99 is <500ms. */\nexport const DNS_TIMEOUT_MS = 3_000;\n\n/** Default number of retry attempts for DNS-over-HTTPS queries. */\nexport const DNS_RETRIES = 1;\n\n/** Edge cache TTL (seconds) for outbound DoH fetch requests via Cloudflare's cf API. */\nexport const DOH_EDGE_CACHE_TTL = 300;\n\n/** Timeout (ms) after which a stuck INFLIGHT promise is evicted from the dedup map. */\nexport const INFLIGHT_CLEANUP_MS = 30_000;\n\n/** Base delay (ms) between DNS retry attempts. Actual delay = base * (attempt+1) + jitter. */\nexport const DNS_RETRY_BASE_DELAY_MS = 75;\n\n/**\n * When true, empty DoH answers from the primary resolver are optionally\n * confirmed with a secondary resolver to reduce false negatives.\n */\nexport const DNS_CONFIRM_WITH_SECONDARY_ON_EMPTY = true;\n\n/** Default cache TTL in seconds. Override via CACHE_TTL_SECONDS env var. */\nexport const DEFAULT_CACHE_TTL_SECONDS = 300;\n\n/**\n * Parse CACHE_TTL_SECONDS env var, clamping to [60, 3600].\n * Returns DEFAULT_CACHE_TTL_SECONDS when absent or invalid.\n */\nexport function parseCacheTtl(envValue?: string): number {\n\tif (!envValue) return DEFAULT_CACHE_TTL_SECONDS;\n\tconst parsed = Number(envValue);\n\tif (!Number.isFinite(parsed) || parsed < 60) return DEFAULT_CACHE_TTL_SECONDS;\n\treturn Math.min(parsed, 3600);\n}\n\n/**\n * Global daily free-tier request ceiling across all unauthenticated IPs.\n * Protects from abuse by capping free usage at a service-wide level.\n * Authenticated requests are exempt.\n */\nexport const GLOBAL_DAILY_TOOL_LIMIT = 500_000;\n\n/**\n * Free-tier daily tool quotas for unauthenticated callers.\n * Tools omitted from this map are governed only by baseline per-IP rate limits.\n */\n/** MCP API key tiers with daily scan quotas. Derived from the Zod TierSchema in schemas/primitives. */\nexport type McpApiKeyTier = Tier;\n\n/** Daily scan limits per API key tier (applies per tool unless overridden by TIER_TOOL_DAILY_LIMITS). */\nexport const TIER_DAILY_LIMITS: Record<McpApiKeyTier, number> = {\n\tfree: 50,\n\tagent: 200,\n\tdeveloper: 500,\n\tenterprise: 10_000,\n\tpartner: 100_000,\n\towner: Infinity,\n};\n\n/**\n * Per-tool daily limit overrides for specific tiers.\n * When a tier+tool combo exists here, it takes precedence over the flat TIER_DAILY_LIMITS value.\n */\nexport const TIER_TOOL_DAILY_LIMITS: Partial<Record<McpApiKeyTier, Record<string, number>>> = {\n\tpartner: {\n\t\tscan_domain: 100_000,\n\t\tscan: 100_000,\n\t\tcompare_baseline: 100_000,\n\t\tcheck_spf: 500_000,\n\t\tcheck_dmarc: 500_000,\n\t\tcheck_dkim: 500_000,\n\t\tcheck_mx: 500_000,\n\t\tcheck_ns: 500_000,\n\t\tcheck_ssl: 500_000,\n\t\tcheck_dnssec: 500_000,\n\t\tcheck_mta_sts: 500_000,\n\t\tcheck_caa: 500_000,\n\t\tcheck_bimi: 500_000,\n\t\tcheck_tlsrpt: 500_000,\n\t\tcheck_lookalikes: 50_000,\n\t\tcheck_shadow_domains: 50_000,\n\t\tcheck_txt_hygiene: 500_000,\n\t\tcheck_http_security: 500_000,\n\t\tcheck_dane: 500_000,\n\t\tcheck_mx_reputation: 50_000,\n\t\tcheck_srv: 500_000,\n\t\tcheck_zone_hygiene: 500_000,\n\t\tcheck_subdomailing: 500_000,\n\t\texplain_finding: 500_000,\n\t},\n};\n\nexport const FREE_TOOL_DAILY_LIMITS: Record<string, number> = {\n\tscan_domain: 75,\n\tscan: 75,\n\tbatch_scan: 20,\n\tcompare_domains: 15,\n\tcheck_spf: 200,\n\tcheck_dmarc: 200,\n\tcheck_dkim: 200,\n\tcheck_mx: 200,\n\tcheck_ns: 200,\n\tcheck_ssl: 200,\n\tcheck_dnssec: 200,\n\tcheck_mta_sts: 200,\n\tcheck_caa: 200,\n\tcheck_bimi: 200,\n\tcheck_tlsrpt: 200,\n\tcheck_lookalikes: 20,\n\texplain_finding: 200,\n\tcompare_baseline: 150,\n\tcheck_shadow_domains: 20,\n\tcheck_txt_hygiene: 200,\n\tcheck_http_security: 200,\n\tcheck_dane: 200,\n\tcheck_mx_reputation: 20,\n\tcheck_srv: 200,\n\tcheck_zone_hygiene: 200,\n\tcheck_subdomailing: 200,\n\tgenerate_fix_plan: 75,\n\tgenerate_spf_record: 200,\n\tgenerate_dmarc_record: 200,\n\tgenerate_dkim_config: 200,\n\tgenerate_mta_sts_policy: 200,\n\tget_benchmark: 100,\n\tget_provider_insights: 50,\n\tassess_spoofability: 150,\n\tcheck_resolver_consistency: 50,\n\tmap_supply_chain: 75,\n\tanalyze_drift: 75,\n\tvalidate_fix: 200,\n\tgenerate_rollout_plan: 150,\n\tresolve_spf_chain: 100,\n\tdiscover_subdomains: 50,\n\tmap_compliance: 75,\n\tsimulate_attack_paths: 75,\n};\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { z } from 'zod';\n\n/** DNS answer record from DoH response. */\nexport const DnsAnswerSchema = z.object({\n\tname: z.string(),\n\ttype: z.number(),\n\tTTL: z.number().optional(),\n\tdata: z.string(),\n});\n\n/** DNS authority record from DoH response. */\nexport const DnsAuthoritySchema = z.object({\n\tname: z.string(),\n\ttype: z.number(),\n\tTTL: z.number().optional(),\n\tdata: z.string(),\n});\n\n/** Complete DoH JSON response. Validates shape before casting. */\nexport const DohResponseSchema = z\n\t.object({\n\t\tStatus: z.number().finite(),\n\t\tTC: z.boolean().optional(),\n\t\tRD: z.boolean().optional(),\n\t\tRA: z.boolean().optional(),\n\t\tAD: z.boolean().optional(),\n\t\tCD: z.boolean().optional(),\n\t\tQuestion: z.array(z.object({ name: z.string(), type: z.unknown() })).optional(),\n\t\tAnswer: z.array(DnsAnswerSchema).optional(),\n\t\tAuthority: z.array(DnsAuthoritySchema).optional(),\n\t})\n\t.passthrough();\n\n/** Parsed CAA record. */\nexport const CaaRecordSchema = z.object({\n\tflags: z.number(),\n\ttag: z.string(),\n\tvalue: z.string(),\n});\n\n/** Parsed TLSA record. */\nexport const TlsaRecordSchema = z.object({\n\tusage: z.number(),\n\tselector: z.number(),\n\tmatchingType: z.number(),\n\tcertData: z.string(),\n});\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { DNS_TIMEOUT_MS, DNS_RETRIES, DNS_CONFIRM_WITH_SECONDARY_ON_EMPTY, DOH_EDGE_CACHE_TTL, DNS_RETRY_BASE_DELAY_MS } from './config';\nimport { type DohResponse, type QueryDnsOptions, RecordType, type RecordTypeName } from './dns-types';\nimport { DohResponseSchema } from '../schemas/dns';\n\nconst DOH_ENDPOINT = 'https://cloudflare-dns.com/dns-query';\nconst GOOGLE_DOH_ENDPOINT = 'https://dns.google/resolve';\n\nfunction buildDohUrl(endpoint: string, domain: string, type: RecordTypeName, dnssecCheck: boolean): string {\n\tconst params = new URLSearchParams({\n\t\tname: domain,\n\t\ttype,\n\t\t...(dnssecCheck ? { cd: '0' } : {}),\n\t});\n\n\treturn `${endpoint}?${params.toString()}`;\n}\n\nfunction hasTypedAnswers(response: DohResponse, type: RecordTypeName): boolean {\n\treturn (response.Answer ?? []).some((answer) => answer.type === RecordType[type]);\n}\n\nfunction retryDelay(attempt: number): Promise<void> {\n\treturn new Promise((r) => setTimeout(r, DNS_RETRY_BASE_DELAY_MS * (attempt + 1) + Math.random() * 50));\n}\n\n/**\n * Fetch a DoH response from a URL.\n *\n * @param token - Optional auth token sent as `X-BV-Token` (for custom secondary resolvers).\n * @param useEdgeCache - If true, attaches Cloudflare `cf` cache directive. Omit for external origins.\n */\nasync function fetchDohResponse(\n\turl: string,\n\ttimeoutMs: number,\n\topts?: { token?: string; useEdgeCache?: boolean },\n): Promise<DohResponse | null> {\n\ttry {\n\t\tconst headers: Record<string, string> = { Accept: 'application/dns-json' };\n\t\tif (opts?.token) headers['X-BV-Token'] = opts.token;\n\t\tconst response = await fetch(url, {\n\t\t\tmethod: 'GET',\n\t\t\theaders,\n\t\t\tsignal: AbortSignal.timeout(timeoutMs),\n\t\t\t...(opts?.useEdgeCache ? { cf: { cacheTtl: DOH_EDGE_CACHE_TTL, cacheEverything: true } } : {}),\n\t\t});\n\t\tif (!response.ok) return null;\n\t\tconst data = await response.json();\n\t\tconst parsed = DohResponseSchema.safeParse(data);\n\t\tif (!parsed.success) return null;\n\t\treturn parsed.data as DohResponse;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/** Error thrown when a DNS query fails */\nexport class DnsQueryError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly domain: string,\n\t\tpublic readonly recordType: string,\n\t\tpublic readonly status?: number,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'DnsQueryError';\n\t}\n}\n\n/**\n * Query Cloudflare DoH for DNS records.\n *\n * When `opts.queryCache` is provided, deduplicates concurrent and sequential\n * identical queries within a single scan by caching the Promise keyed by\n * `domain:type:dnssecCheck`. Failed queries are evicted so retries can re-attempt.\n *\n * @param domain - The domain name to query\n * @param type - DNS record type name (e.g. \"TXT\", \"MX\", \"A\")\n * @param dnssecCheck - If true, sets the CD=0 flag to request DNSSEC validation\n * @returns The full DoH JSON response\n */\nexport async function queryDns(domain: string, type: RecordTypeName, dnssecCheck = false, opts?: QueryDnsOptions): Promise<DohResponse> {\n\tconst cache = opts?.queryCache;\n\tif (!cache) {\n\t\treturn queryDnsUncached(domain, type, dnssecCheck, opts);\n\t}\n\n\tconst cacheKey = `${domain}:${type}:${dnssecCheck}`;\n\tconst existing = cache.get(cacheKey);\n\tif (existing) {\n\t\treturn existing;\n\t}\n\n\tconst promise = queryDnsUncached(domain, type, dnssecCheck, opts);\n\tcache.set(cacheKey, promise);\n\tpromise.catch(() => cache.delete(cacheKey));\n\treturn promise;\n}\n\nasync function queryDnsUncached(domain: string, type: RecordTypeName, dnssecCheck = false, opts?: QueryDnsOptions): Promise<DohResponse> {\n\tconst timeoutMs = opts?.timeoutMs ?? DNS_TIMEOUT_MS;\n\tconst retries = opts?.retries ?? DNS_RETRIES;\n\tconst confirmWithSecondaryOnEmpty = opts?.confirmWithSecondaryOnEmpty ?? DNS_CONFIRM_WITH_SECONDARY_ON_EMPTY;\n\tconst url = buildDohUrl(DOH_ENDPOINT, domain, type, dnssecCheck);\n\n\tfor (let attempt = 0; attempt <= retries; attempt++) {\n\t\tlet response: Response;\n\n\t\ttry {\n\t\t\tresponse = await fetch(url, {\n\t\t\t\tmethod: 'GET',\n\t\t\t\theaders: { Accept: 'application/dns-json' },\n\t\t\t\tsignal: AbortSignal.timeout(timeoutMs),\n\t\t\t\tcf: { cacheTtl: DOH_EDGE_CACHE_TTL, cacheEverything: true },\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tif (err instanceof DOMException && err.name === 'AbortError') {\n\t\t\t\tif (attempt < retries) {\n\t\t\t\t\tawait retryDelay(attempt);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthrow new DnsQueryError(`DNS query timed out after ${timeoutMs}ms`, domain, type);\n\t\t\t}\n\t\t\tif (attempt < retries) {\n\t\t\t\tawait retryDelay(attempt);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow new DnsQueryError(`DNS query failed: ${err instanceof Error ? err.message : String(err)}`, domain, type);\n\t\t}\n\n\t\tif (!response.ok) {\n\t\t\tif (attempt < retries && response.status >= 500) {\n\t\t\t\tawait retryDelay(attempt);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow new DnsQueryError(`DoH returned HTTP ${response.status}`, domain, type, response.status);\n\t\t}\n\n\t\tconst raw = await response.json();\n\t\tconst validated = DohResponseSchema.safeParse(raw);\n\t\tif (!validated.success) {\n\t\t\tthrow new DnsQueryError('Invalid DoH response format', domain, type);\n\t\t}\n\t\tconst data = validated.data as DohResponse;\n\n\t\tif (confirmWithSecondaryOnEmpty && !opts?.skipSecondaryConfirmation && !hasTypedAnswers(data, type)) {\n\t\t\t// Try custom secondary (bv-dns) first if configured\n\t\t\tif (opts?.secondaryDoh?.endpoint) {\n\t\t\t\tconst bvDns = await fetchDohResponse(\n\t\t\t\t\tbuildDohUrl(opts.secondaryDoh.endpoint, domain, type, dnssecCheck),\n\t\t\t\t\ttimeoutMs,\n\t\t\t\t\t{ token: opts.secondaryDoh.token },\n\t\t\t\t);\n\t\t\t\tif (bvDns && hasTypedAnswers(bvDns, type)) {\n\t\t\t\t\treturn bvDns;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Google DoH as final fallback\n\t\t\tconst google = await fetchDohResponse(\n\t\t\t\tbuildDohUrl(GOOGLE_DOH_ENDPOINT, domain, type, dnssecCheck),\n\t\t\t\ttimeoutMs,\n\t\t\t\t{ useEdgeCache: true },\n\t\t\t);\n\t\t\tif (google && hasTypedAnswers(google, type)) {\n\t\t\t\treturn google;\n\t\t\t}\n\t\t}\n\n\t\treturn data;\n\t}\n\n\tthrow new DnsQueryError('DNS query failed after retries', domain, type);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { queryDns } from './dns-transport';\nimport { RecordType, type QueryDnsOptions, type RecordTypeName } from './dns-types';\nimport { CaaRecordSchema, TlsaRecordSchema } from '../schemas/dns';\n\n/** Parsed CAA record with flags, tag, and value */\nexport interface CaaRecord {\n\tflags: number;\n\ttag: string;\n\tvalue: string;\n}\n\n/** Parsed PTR record hostname */\nexport interface PtrRecord {\n\thostname: string;\n}\n\n/** Parsed SRV record with priority, weight, port, and target */\nexport interface SrvRecord {\n\tpriority: number;\n\tweight: number;\n\tport: number;\n\ttarget: string;\n}\n\n/** Parsed TLSA record with usage, selector, matching type, and certificate data */\nexport interface TlsaRecord {\n\tusage: number;\n\tselector: number;\n\tmatchingType: number;\n\tcertData: string;\n}\n\n/**\n * Query DNS and return just the answer data strings.\n * Returns an empty array if no answers are found.\n */\nexport async function queryDnsRecords(domain: string, type: RecordTypeName, opts?: QueryDnsOptions): Promise<string[]> {\n\tconst resp = await queryDns(domain, type, false, opts);\n\treturn (resp.Answer ?? []).filter((answer) => answer.type === RecordType[type]).map((answer) => answer.data);\n}\n\n/**\n * Query TXT records, concatenate multi-string values, and unescape DNS\n * presentation-format backslash sequences.\n *\n * Cloudflare DoH returns TXT data with surrounding quotes and multiple\n * strings separated by `\" \"`. Per RFC 7208 §3.3, multi-string TXT records\n * MUST be concatenated without adding spaces. Some nameservers also emit\n * RFC 1035 §5.1 backslash escapes (e.g. `\\;` for a literal semicolon);\n * we unescape both `\\X` (single-char) and `\\DDD` (decimal octet) forms.\n */\nexport async function queryTxtRecords(domain: string, opts?: QueryDnsOptions): Promise<string[]> {\n\tconst records = await queryDnsRecords(domain, 'TXT', opts);\n\treturn records.map((record) =>\n\t\tunescapeDnsTxt(\n\t\t\trecord\n\t\t\t\t.replace(/\" \"/g, '')\n\t\t\t\t.replace(/^\"|\"$/g, ''),\n\t\t),\n\t);\n}\n\n/**\n * Unescape DNS presentation-format backslash sequences in TXT record data.\n * Handles `\\DDD` (decimal octet 000–255) and `\\X` (literal character).\n *\n * Some DoH providers double-escape (e.g. `\\\\;` in the JS string for what\n * should be a plain `;`), so we loop until the string stabilises.\n */\nexport function unescapeDnsTxt(text: string): string {\n\tconst unescape = (s: string) =>\n\t\ts.replace(/\\\\(\\d{3})|\\\\(.)/g, (_, decimal, ch) => {\n\t\t\tif (decimal !== undefined) {\n\t\t\t\tconst code = parseInt(decimal, 10);\n\t\t\t\treturn code <= 255 ? String.fromCharCode(code) : `\\\\${decimal}`;\n\t\t\t}\n\t\t\treturn ch;\n\t\t});\n\n\tlet result = text;\n\tfor (let i = 0; i < 2; i++) {\n\t\tconst next = unescape(result);\n\t\tif (next === result) break;\n\t\tresult = next;\n\t}\n\treturn result;\n}\n\n/**\n * Check if a domain has valid DNSSEC by examining the AD (Authenticated Data) flag.\n * Returns true if the response was DNSSEC-validated.\n */\nexport async function checkDnssec(domain: string, opts?: QueryDnsOptions): Promise<boolean> {\n\tconst resp = await queryDns(domain, 'A', true, opts);\n\treturn resp.AD === true;\n}\n\n/**\n * Parse a single CAA record data string.\n * Handles both human-readable format (e.g. `0 issue \"letsencrypt.org\"`)\n * and Cloudflare DoH hex wire format (e.g. `\\# 19 00 05 69 73 73 75 65...`).\n *\n * Wire format bytes: flags(1) + tag_length(1) + tag(tag_length) + value(rest)\n */\nexport function parseCaaRecord(data: string): CaaRecord | null {\n\tif (data.startsWith('\\\\#') || data.startsWith('#')) {\n\t\tconst parts = data.trim().split(/\\s+/);\n\t\tconst hexStart = parts[0] === '\\\\#' || parts[0] === '#' ? 2 : 1;\n\t\tconst hexBytes = parts.slice(hexStart);\n\t\tif (hexBytes.length < 3) return null;\n\n\t\tconst flags = parseInt(hexBytes[0], 16);\n\t\tconst tagLen = parseInt(hexBytes[1], 16);\n\t\tif (isNaN(flags) || isNaN(tagLen) || hexBytes.length < 2 + tagLen) return null;\n\n\t\tconst tag = hexBytes\n\t\t\t.slice(2, 2 + tagLen)\n\t\t\t.map((hexByte) => String.fromCharCode(parseInt(hexByte, 16)))\n\t\t\t.join('');\n\t\tconst value = hexBytes\n\t\t\t.slice(2 + tagLen)\n\t\t\t.map((hexByte) => String.fromCharCode(parseInt(hexByte, 16)))\n\t\t\t.join('');\n\n\t\tconst record = { flags, tag: tag.toLowerCase(), value };\n\t\treturn CaaRecordSchema.safeParse(record).success ? record : null;\n\t}\n\n\tconst match = data.match(/^(\\d+)\\s+(\\S+)\\s+\"?([^\"]*)\"?\\s*$/);\n\tif (match) {\n\t\tconst record = {\n\t\t\tflags: parseInt(match[1], 10),\n\t\t\ttag: match[2].toLowerCase(),\n\t\t\tvalue: match[3],\n\t\t};\n\t\treturn CaaRecordSchema.safeParse(record).success ? record : null;\n\t}\n\n\treturn null;\n}\n\n/**\n * Query CAA records and parse them into structured objects.\n * Handles both human-readable and hex wire format from DoH.\n */\nexport async function queryCaaRecords(domain: string, opts?: QueryDnsOptions): Promise<CaaRecord[]> {\n\tconst records = await queryDnsRecords(domain, 'CAA', opts);\n\treturn records.map(parseCaaRecord).filter((record): record is CaaRecord => record !== null);\n}\n\n/**\n * Query MX records and parse them into priority + exchange pairs.\n */\nexport async function queryMxRecords(domain: string, opts?: QueryDnsOptions): Promise<Array<{ priority: number; exchange: string }>> {\n\tconst records = await queryDnsRecords(domain, 'MX', opts);\n\treturn records.map((record) => {\n\t\tconst parts = record.split(' ');\n\t\treturn {\n\t\t\tpriority: parseInt(parts[0], 10),\n\t\t\texchange: parts.slice(1).join(' ').replace(/\\.$/, ''),\n\t\t};\n\t});\n}\n\n/**\n * Query PTR records for an IP address by constructing the reverse DNS name.\n * For IPv4 address `192.0.2.1`, queries `1.2.0.192.in-addr.arpa`.\n * Returns an array of PTR hostnames with trailing dots stripped.\n */\nexport async function queryPtrRecords(ip: string, opts?: QueryDnsOptions): Promise<string[]> {\n\tconst reverseName = ip.split('.').reverse().join('.') + '.in-addr.arpa';\n\tconst records = await queryDnsRecords(reverseName, 'PTR', opts);\n\treturn records.map((record) => record.replace(/\\.$/, ''));\n}\n\n/**\n * Query SRV records and parse them into structured objects.\n * SRV data format: `priority weight port target`\n */\nexport async function querySrvRecords(\n\tname: string,\n\topts?: QueryDnsOptions,\n): Promise<Array<{ priority: number; weight: number; port: number; target: string }>> {\n\tconst records = await queryDnsRecords(name, 'SRV', opts);\n\treturn records.map((record) => {\n\t\tconst parts = record.split(' ');\n\t\treturn {\n\t\t\tpriority: parseInt(parts[0], 10),\n\t\t\tweight: parseInt(parts[1], 10),\n\t\t\tport: parseInt(parts[2], 10),\n\t\t\ttarget: parts.slice(3).join(' ').replace(/\\.$/, ''),\n\t\t};\n\t});\n}\n\n/**\n * Parse a TLSA record data string into structured fields.\n * Handles both human-readable format (`usage selector matchingType certData`)\n * and hex wire format (data starting with `\\#`).\n *\n * Returns null if the data cannot be parsed.\n */\nexport function parseTlsaRecord(data: string): TlsaRecord | null {\n\tif (data.startsWith('\\\\#') || data.startsWith('#')) {\n\t\tconst parts = data.trim().split(/\\s+/);\n\t\tconst hexStart = parts[0] === '\\\\#' || parts[0] === '#' ? 2 : 1;\n\t\tconst hexBytes = parts.slice(hexStart);\n\t\tif (hexBytes.length < 4) return null;\n\n\t\tconst usage = parseInt(hexBytes[0], 16);\n\t\tconst selector = parseInt(hexBytes[1], 16);\n\t\tconst matchingType = parseInt(hexBytes[2], 16);\n\t\tif (isNaN(usage) || isNaN(selector) || isNaN(matchingType)) return null;\n\n\t\tconst certData = hexBytes.slice(3).join('');\n\t\tconst record = { usage, selector, matchingType, certData };\n\t\treturn TlsaRecordSchema.safeParse(record).success ? record : null;\n\t}\n\n\tconst parts = data.trim().split(/\\s+/);\n\tif (parts.length < 4) return null;\n\n\tconst usage = parseInt(parts[0], 10);\n\tconst selector = parseInt(parts[1], 10);\n\tconst matchingType = parseInt(parts[2], 10);\n\tif (isNaN(usage) || isNaN(selector) || isNaN(matchingType)) return null;\n\n\tconst certData = parts.slice(3).join('');\n\tconst record = { usage, selector, matchingType, certData };\n\treturn TlsaRecordSchema.safeParse(record).success ? record : null;\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Adaptive weight computation for context-aware scoring.\n *\n * Uses exponential moving averages (EMA) of per-category failure rates,\n * collected by the ProfileAccumulator Durable Object, to adjust static\n * importance weights at scoring time. A maturity-gated blend ensures\n * weights stay close to static until enough telemetry has accumulated.\n */\n\nimport type { CheckCategory } from './scoring-model';\nimport type { DomainProfile } from './context-profiles';\nimport { PROFILE_WEIGHTS } from './context-profiles';\n\n// ─── Telemetry interfaces ──────────────────────────────────────────────\n\n/** A single scan's telemetry payload sent to the ProfileAccumulator DO. */\nexport interface ScanTelemetry {\n\tprofile: string;\n\tprovider: string | null;\n\tcategoryFindings: Array<{ category: string; score: number; passed: boolean }>;\n\ttimestamp: number;\n\t/** Overall scan score (0–100). Used for intelligence layer aggregation (histogram, cohort, trends). */\n\toverallScore?: number;\n}\n\n/** Response from the adaptive weights endpoint. */\nexport interface AdaptiveWeightsResponse {\n\tprofile: string;\n\tprovider: string | null;\n\tsampleCount: number;\n\tblendFactor: number;\n\tweights: Record<string, number>;\n\tboundHits: string[];\n}\n\n/** Min/max bounds for an adaptive weight value. */\nexport interface WeightBound {\n\tmin: number;\n\tmax: number;\n}\n\n// ─── Constants ─────────────────────────────────────────────────────────\n\n/** How aggressively deviation from baseline adjusts the weight (0–1). */\nexport const SENSITIVITY = 0.5;\n\n/** Sample count at which blending reaches 100% adaptive. */\nexport const MATURITY_THRESHOLD = 200;\n\n/** EMA span (number of recent observations the average reflects). */\nexport const EMA_SPAN = 200;\n\n/** EMA smoothing factor derived from span. */\nexport const EMA_ALPHA = 2 / (EMA_SPAN + 1);\n\n/** Minimum |scoreDelta| before a scoring note is generated. */\nexport const SCORING_NOTE_DELTA_THRESHOLD = 3;\n\n/** Expected failure rate per category across all domains (prior). */\nexport const BASELINE_FAILURE_RATES: Record<string, number> = {\n\tdmarc: 0.40,\n\tspf: 0.25,\n\tdkim: 0.35,\n\tssl: 0.08,\n\tmta_sts: 0.85,\n\tdnssec: 0.80,\n\tmx: 0.05,\n\tcaa: 0.70,\n\tns: 0.03,\n\tbimi: 0.95,\n\ttlsrpt: 0.90,\n\tsubdomain_takeover: 0.10,\n\tlookalikes: 0.00,\n};\n\n// ─── Weight bounds ─────────────────────────────────────────────────────\n\n/** Categories treated as \"critical mail\" for bound computation in mail-centric profiles. */\nconst CRITICAL_MAIL_CATEGORIES = new Set<string>(['dmarc', 'spf', 'dkim', 'ssl']);\n\n/** Profiles where critical-mail floor applies. */\nconst CRITICAL_MAIL_PROFILES = new Set<string>(['mail_enabled', 'enterprise_mail']);\n\n/**\n * Compute default min/max bounds for an adaptive weight.\n *\n * Critical-mail categories get a higher floor (min 5) to prevent\n * important email-auth checks from being zeroed out.\n */\nexport function defaultBounds(staticWeight: number, isCriticalMail: boolean): WeightBound {\n\tconst minFloor = isCriticalMail ? 5 : 0;\n\treturn {\n\t\tmin: Math.max(minFloor, Math.floor(staticWeight * 0.5)),\n\t\tmax: Math.ceil(staticWeight * 2) + 3,\n\t};\n}\n\n/** Pre-computed bounds for every profile × category combination. */\nexport const WEIGHT_BOUNDS: Record<DomainProfile, Record<CheckCategory, WeightBound>> = (() => {\n\tconst profiles = Object.keys(PROFILE_WEIGHTS) as DomainProfile[];\n\tconst result = {} as Record<DomainProfile, Record<CheckCategory, WeightBound>>;\n\n\tfor (const profile of profiles) {\n\t\tconst weights = PROFILE_WEIGHTS[profile];\n\t\tconst categories = Object.keys(weights) as CheckCategory[];\n\t\tconst profileBounds = {} as Record<CheckCategory, WeightBound>;\n\n\t\tfor (const cat of categories) {\n\t\t\tconst isCritical = CRITICAL_MAIL_PROFILES.has(profile) && CRITICAL_MAIL_CATEGORIES.has(cat);\n\t\t\tprofileBounds[cat] = defaultBounds(weights[cat].importance, isCritical);\n\t\t}\n\n\t\tresult[profile] = profileBounds;\n\t}\n\n\treturn result;\n})();\n\n// ─── Computation functions ─────────────────────────────────────────────\n\n/**\n * Compute a single adaptive weight from EMA failure rate and baseline.\n *\n * @returns The clamped weight and whether a bound was hit ('min' | 'max' | null).\n */\nexport function computeAdaptiveWeight(params: {\n\tstaticWeight: number;\n\temaFailureRate: number;\n\tbaselineFailureRate: number;\n\tbounds: WeightBound;\n}): { weight: number; boundHit: 'min' | 'max' | null } {\n\tconst { staticWeight, emaFailureRate, baselineFailureRate, bounds } = params;\n\n\tconst deviation = emaFailureRate - baselineFailureRate;\n\tconst rawAdjustment = deviation * SENSITIVITY * staticWeight;\n\tconst adaptive = staticWeight + rawAdjustment;\n\tconst clamped = Math.max(bounds.min, Math.min(bounds.max, adaptive));\n\n\tlet boundHit: 'min' | 'max' | null = null;\n\tif (clamped <= bounds.min && adaptive < bounds.min) {\n\t\tboundHit = 'min';\n\t} else if (clamped >= bounds.max && adaptive > bounds.max) {\n\t\tboundHit = 'max';\n\t}\n\n\treturn { weight: clamped, boundHit };\n}\n\n/**\n * Blend static and adaptive weights based on sample maturity.\n *\n * Returns `(1 - blendFactor) * staticWeight + blendFactor * adaptiveWeight`\n * where `blendFactor = min(1.0, sampleCount / MATURITY_THRESHOLD)`.\n */\nexport function blendWeights(staticWeight: number, adaptiveWeight: number, sampleCount: number): number {\n\tconst blendFactor = Math.min(1.0, sampleCount / MATURITY_THRESHOLD);\n\treturn (1 - blendFactor) * staticWeight + blendFactor * adaptiveWeight;\n}\n\n// ─── Type adapter ──────────────────────────────────────────────────────\n\n/**\n * Convert a DO-returned weight map to a CheckCategory-keyed importance record.\n *\n * Falls back to the static profile weight for any category not present in the\n * DO response. Returns `null` if any value is non-finite or negative.\n */\nexport function adaptiveWeightsToContext(\n\tdoWeights: Record<string, number>,\n\tprofile: DomainProfile,\n): Record<CheckCategory, { importance: number }> | null {\n\tconst staticWeights = PROFILE_WEIGHTS[profile];\n\tconst categories = Object.keys(staticWeights) as CheckCategory[];\n\tconst result = {} as Record<CheckCategory, { importance: number }>;\n\n\tfor (const cat of categories) {\n\t\tconst value = cat in doWeights ? doWeights[cat] : staticWeights[cat].importance;\n\t\tif (!isFinite(value) || value < 0) {\n\t\t\treturn null;\n\t\t}\n\t\tresult[cat] = { importance: value };\n\t}\n\n\treturn result;\n}\n\n// ─── Scoring note generation ───────────────────────────────────────────\n\n/**\n * Generate a human-readable note explaining adaptive weight shifts.\n *\n * Returns `null` if the absolute score delta is below the threshold.\n */\nexport function generateScoringNote(\n\tweightDeltas: Record<string, number>,\n\tscoreDelta: number,\n\tprovider: string | null,\n): string | null {\n\tif (Math.abs(scoreDelta) < SCORING_NOTE_DELTA_THRESHOLD) {\n\t\treturn null;\n\t}\n\n\t// Collect significant deltas (|delta| >= 2) sorted by magnitude descending\n\tconst significant = Object.entries(weightDeltas)\n\t\t.filter(([, d]) => Math.abs(d) >= 2)\n\t\t.sort((a, b) => Math.abs(b[1]) - Math.abs(a[1]));\n\n\tif (significant.length === 0) {\n\t\t// No individually significant deltas but overall threshold met — use the largest anyway\n\t\tconst all = Object.entries(weightDeltas).sort((a, b) => Math.abs(b[1]) - Math.abs(a[1]));\n\t\tif (all.length === 0) return null;\n\t\tconst [topCat, topDelta] = all[0];\n\t\treturn formatNote(topCat, topDelta, provider);\n\t}\n\n\tif (significant.length >= 3) {\n\t\tconst [topCat] = significant[0];\n\t\treturn `Several checks were weighted differently based on patterns seen across similar domains. The biggest shift was in ${topCat.toUpperCase()}.`;\n\t}\n\n\tconst [topCat, topDelta] = significant[0];\n\treturn formatNote(topCat, topDelta, provider);\n}\n\n/** Format a single-category scoring note. */\nfunction formatNote(category: string, delta: number, provider: string | null): string {\n\tconst cat = category.toUpperCase();\n\n\tif (delta > 0 && provider) {\n\t\tconst providerDisplay = capitalizeWords(provider);\n\t\treturn `${cat} carried more weight because domains using ${providerDisplay} frequently have issues in this area.`;\n\t}\n\n\tif (delta > 0) {\n\t\treturn `${cat} carried more weight in this scan because it is a common issue across similar domains.`;\n\t}\n\n\treturn `${cat} carried less weight because similar domains rarely have issues there.`;\n}\n\n/** Capitalize the first letter of each word. */\nfunction capitalizeWords(s: string): string {\n\treturn s.replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n// For IDN/Unicode normalization\nimport * as punycode from 'punycode/';\n// Centralized normalization config\nimport {\n\tBLOCKED_SUFFIXES,\n\tBLOCKED_HOSTS,\n\tBLOCKED_IP_PATTERNS,\n\tBLOCKED_DNS_REBINDING,\n\tMAX_DOMAIN_LENGTH,\n\tMAX_LABEL_LENGTH,\n\tLABEL_REGEX,\n} from './config';\n/**\n * Input sanitization and validation utilities for the DNS Security MCP Server.\n * Handles domain validation, input cleaning, and MCP error response helpers.\n * Compatible with Cloudflare Workers runtime (no Node.js APIs).\n */\n\nexport interface ValidationResult {\n\tvalid: boolean;\n\terror?: string;\n}\n\n/**\n * Parse a numeric IPv4 segment using decimal, octal, or hex notation.\n * Returns null when the token is not a numeric IP segment.\n */\nfunction parseIpv4NumberToken(token: string): number | null {\n\tif (!token) return null;\n\n\tlet radix = 10;\n\tlet digits = token;\n\tif (/^0x[0-9a-f]+$/i.test(token)) {\n\t\tradix = 16;\n\t\tdigits = token.slice(2);\n\t} else if (/^0[0-7]+$/.test(token) && token.length > 1) {\n\t\tradix = 8;\n\t}\n\n\tif (digits.length === 0) return null;\n\tconst value = Number.parseInt(digits, radix);\n\tif (!Number.isFinite(value) || value < 0) return null;\n\treturn value;\n}\n\n/**\n * Canonicalize IPv4 literals that may use short/octal/hex forms.\n * Returns null when input is not an IPv4 host literal candidate.\n */\nfunction canonicalizeIpv4Literal(input: string): string | null {\n\tif (!/^[0-9a-fx.]+$/i.test(input)) return null;\n\n\tconst parts = input.split('.');\n\tif (parts.length < 1 || parts.length > 4) return null;\n\tif (parts.some((part) => part.length === 0)) return null;\n\n\tconst values: number[] = [];\n\tfor (const part of parts) {\n\t\tconst parsed = parseIpv4NumberToken(part);\n\t\tif (parsed === null) return null;\n\t\tvalues.push(parsed);\n\t}\n\n\tlet ipAsUint32 = 0;\n\tif (values.length === 1) {\n\t\tif (values[0] > 0xffffffff) return null;\n\t\tipAsUint32 = values[0] >>> 0;\n\t} else if (values.length === 2) {\n\t\tif (values[0] > 0xff || values[1] > 0xffffff) return null;\n\t\tipAsUint32 = ((values[0] << 24) | values[1]) >>> 0;\n\t} else if (values.length === 3) {\n\t\tif (values[0] > 0xff || values[1] > 0xff || values[2] > 0xffff) return null;\n\t\tipAsUint32 = ((values[0] << 24) | (values[1] << 16) | values[2]) >>> 0;\n\t} else {\n\t\tif (values.some((value) => value > 0xff)) return null;\n\t\tipAsUint32 = ((values[0] << 24) | (values[1] << 16) | (values[2] << 8) | values[3]) >>> 0;\n\t}\n\n\tconst oct1 = (ipAsUint32 >>> 24) & 0xff;\n\tconst oct2 = (ipAsUint32 >>> 16) & 0xff;\n\tconst oct3 = (ipAsUint32 >>> 8) & 0xff;\n\tconst oct4 = ipAsUint32 & 0xff;\n\treturn `${oct1}.${oct2}.${oct3}.${oct4}`;\n}\n\n/**\n * Validate and sanitize a domain name for DNS queries.\n * Rejects localhost, private/reserved TLDs, IP addresses, and malformed domains.\n */\n\nexport function validateDomain(input: string): ValidationResult {\n\tif (!input || typeof input !== 'string') {\n\t\treturn { valid: false, error: 'Domain name is required' };\n\t}\n\n\t// Check for invisible/non-printable Unicode (except space, dot, hyphen)\n\tconst invisiblePattern = /[\\p{C}\\p{Zl}\\p{Zp}\\u200B-\\u200D\\uFEFF]/gu;\n\tif (invisiblePattern.test(input)) {\n\t\treturn { valid: false, error: 'Domain contains invalid Unicode or cannot be converted to ASCII' };\n\t}\n\tconst cleaned = input.replace(invisiblePattern, '').trim();\n\tif (cleaned.length === 0) {\n\t\treturn { valid: false, error: 'Domain name is required' };\n\t}\n\n\t// Normalize Unicode to NFC, lowercase, remove trailing dot\n\tlet domain = cleaned.normalize('NFC').toLowerCase();\n\tif (domain.endsWith('.')) domain = domain.slice(0, -1);\n\n\t// Convert Unicode/emoji/IDN to punycode for validation\n\tlet asciiDomain: string;\n\ttry {\n\t\tasciiDomain = punycode.toASCII(domain);\n\t} catch {\n\t\treturn { valid: false, error: 'Domain contains invalid Unicode or cannot be converted to ASCII' };\n\t}\n\n\tif (asciiDomain.length > MAX_DOMAIN_LENGTH) {\n\t\treturn { valid: false, error: `Domain exceeds maximum length of ${MAX_DOMAIN_LENGTH} characters` };\n\t}\n\n\t// Check blocked exact hostnames\n\tif (BLOCKED_HOSTS.includes(asciiDomain)) {\n\t\treturn { valid: false, error: `Domain \"${asciiDomain}\" is not allowed: reserved hostname` };\n\t}\n\n\t// Check blocked suffixes\n\tfor (const suffix of BLOCKED_SUFFIXES) {\n\t\tif (asciiDomain === suffix.slice(1) || asciiDomain.endsWith(suffix)) {\n\t\t\treturn { valid: false, error: `Domain \"${asciiDomain}\" is not allowed: reserved TLD \"${suffix}\"` };\n\t\t}\n\t}\n\n\t// Canonicalize non-standard IPv4 literals (e.g. 127.1, 0177.0.0.1)\n\t// and reject all IP literal forms (public, private, and special).\n\tconst canonicalIpv4 = canonicalizeIpv4Literal(asciiDomain);\n\tif (canonicalIpv4) {\n\t\treturn { valid: false, error: `IP addresses are not allowed: \"${asciiDomain}\"` };\n\t}\n\n\t// Reject dotted numeric host literals that are IPv4-like but malformed/out-of-range.\n\tif (/^\\d+(?:\\.\\d+){1,3}$/.test(asciiDomain)) {\n\t\treturn { valid: false, error: `IP addresses are not allowed: \"${asciiDomain}\"` };\n\t}\n\n\t// Check if it looks like an IP address (blocked)\n\tfor (const pattern of BLOCKED_IP_PATTERNS) {\n\t\tif (pattern.test(asciiDomain)) {\n\t\t\treturn { valid: false, error: `IP addresses are not allowed: \"${asciiDomain}\"` };\n\t\t}\n\t}\n\n\t// Check for DNS rebinding services\n\tfor (const suffix of BLOCKED_DNS_REBINDING) {\n\t\tif (asciiDomain === suffix.slice(1) || asciiDomain.endsWith(suffix)) {\n\t\t\treturn { valid: false, error: 'Domain uses a DNS rebinding service and is not allowed' };\n\t\t}\n\t}\n\n\t// Validate domain label structure (punycode labels)\n\tconst labels = asciiDomain.split('.');\n\tif (labels.length < 2) {\n\t\treturn { valid: false, error: 'Domain must have at least two labels (e.g., example.com)' };\n\t}\n\tfor (const label of labels) {\n\t\tif (label.length === 0) {\n\t\t\treturn { valid: false, error: 'Domain contains empty label (consecutive dots)' };\n\t\t}\n\t\t// Strip HTML/script tags from label before including in error messages\n\t\tconst safeLabel = label.replace(/[<>]/g, '').slice(0, 63);\n\t\tif (label.length > MAX_LABEL_LENGTH) {\n\t\t\treturn { valid: false, error: `Label \"${safeLabel}\" exceeds maximum length of ${MAX_LABEL_LENGTH} characters` };\n\t\t}\n\t\tif (!LABEL_REGEX.test(label)) {\n\t\t\treturn { valid: false, error: `Label \"${safeLabel}\" contains invalid characters` };\n\t\t}\n\t}\n\n\treturn { valid: true };\n}\n\n/**\n * Sanitize a domain string: trim, lowercase, remove trailing dot.\n * Call validateDomain first to ensure the domain is valid.\n */\nexport function sanitizeDomain(input: string): string {\n\t// Remove invisible/non-printable Unicode (except space, dot, hyphen)\n\tconst cleaned = input.replace(/[\\p{C}\\p{Zl}\\p{Zp}\\u200B-\\u200D\\uFEFF]/gu, '').trim();\n\tif (cleaned.length === 0) return '';\n\tlet domain = cleaned.normalize('NFC').toLowerCase();\n\tif (domain.endsWith('.')) domain = domain.slice(0, -1);\n\t// Convert Unicode/emoji/IDN to punycode for DNS queries\n\ttry {\n\t\treturn punycode.toASCII(domain);\n\t} catch {\n\t\treturn '';\n\t}\n}\n\n/**\n * Sanitize arbitrary text input for safe logging/display.\n * Removes control characters except newlines and tabs, and truncates length.\n */\nexport function sanitizeInput(input: string, maxLength = 500): string {\n\tif (typeof input !== 'string') return '';\n\tconst sanitized = input.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]/g, '');\n\treturn sanitized.slice(0, maxLength);\n}\n\n\n","// SPDX-License-Identifier: BUSL-1.1\n\n/** Server version — keep in sync with package.json */\nexport const SERVER_VERSION = '2.2.2';\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { z } from 'zod';\n\n/**\n * Domain name — shape validation only (length 1-253).\n *\n * Intentional two-layer design: this schema validates the string shape so Zod can\n * reject obviously invalid input early (empty strings, oversized payloads). The\n * second layer — `validateDomain()` + `sanitizeDomain()` from `lib/sanitize.ts` —\n * handles structural validation (label rules, TLD checks), SSRF protection\n * (blocked IPs/TLDs), and punycode normalization. That second layer runs after Zod\n * in `extractAndValidateDomain()` (handlers/tool-args.ts).\n */\nexport const DomainSchema = z.string().min(1).max(253);\n\n/** Session ID — exactly 64 lowercase hex characters. */\nexport const SessionIdSchema = z.string().regex(/^[0-9a-f]{64}$/);\n\n/** DKIM selector — valid DNS label, max 63 chars. Trims and lowercases input before validation. */\nexport const DkimSelectorSchema = z.string().transform(s => s.trim().toLowerCase()).pipe(z.string().max(63).regex(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/));\n\n/** Internal route tool name — lowercase + underscores, max 30 chars. */\nexport const ToolNameSchema = z.string().min(1).max(30).regex(/^[a-z_]+$/);\n\n/** Safe label for array elements (provider names, MX hosts). */\nexport const SafeLabelSchema = z.string().min(1).max(253);\n\n/** Scoring profile (with auto). Used by scan_domain. Trims and lowercases input. */\nexport const ProfileSchema = z.string().transform(s => s.trim().toLowerCase()).pipe(z.enum(['auto', 'mail_enabled', 'enterprise_mail', 'non_mail', 'web_only', 'minimal']));\n\n/** Scoring profile (without auto). Used by get_benchmark, get_provider_insights. Trims and lowercases input. */\nexport const BenchmarkProfileSchema = z.string().transform(s => s.trim().toLowerCase()).pipe(z.enum(['mail_enabled', 'enterprise_mail', 'non_mail', 'web_only', 'minimal']));\n\n/** Output format. Trims and lowercases input before validation. */\nexport const FormatSchema = z.string().transform(s => s.trim().toLowerCase()).pipe(z.enum(['full', 'compact']));\n\n/** DNS record type for resolver consistency. Trims and uppercases input before validation. */\nexport const RecordTypeSchema = z.string().transform(s => s.trim().toUpperCase()).pipe(z.enum(['A', 'AAAA', 'MX', 'TXT', 'NS', 'CNAME', 'SOA', 'CAA']));\n\n/** Security grade. */\nexport const GradeSchema = z.enum(['A+', 'A', 'B+', 'B', 'C+', 'C', 'D+', 'D', 'F']);\n\n/** API key tier. */\nexport const TierSchema = z.enum(['free', 'agent', 'developer', 'enterprise', 'partner', 'owner']);\n\n/** DMARC policy for generate_dmarc_record. Trims and lowercases input. */\nexport const DmarcPolicySchema = z.string().transform(s => s.trim().toLowerCase()).pipe(z.enum(['none', 'quarantine', 'reject']));\n\n/** Explain finding status values. Trims and lowercases input. */\nexport const ExplainStatusSchema = z.string().transform(s => s.trim().toLowerCase()).pipe(z.enum(['pass', 'fail', 'warning', 'critical', 'high', 'medium', 'low', 'info']));\n\n/** Inferred types for external use. */\nexport type Profile = z.infer<typeof ProfileSchema>;\nexport type BenchmarkProfile = z.infer<typeof BenchmarkProfileSchema>;\nexport type OutputFormat = z.infer<typeof FormatSchema>;\nexport type Grade = z.infer<typeof GradeSchema>;\nexport type Tier = z.infer<typeof TierSchema>;\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { z } from 'zod';\nimport {\n\tDomainSchema,\n\tFormatSchema,\n\tProfileSchema,\n\tBenchmarkProfileSchema,\n\tDkimSelectorSchema,\n\tRecordTypeSchema,\n\tGradeSchema,\n\tSafeLabelSchema,\n\tDmarcPolicySchema,\n\tExplainStatusSchema,\n} from './primitives';\n\n/** Domain + optional format — shared by most check tools. */\nexport const BaseDomainArgs = z.object({\n\tdomain: DomainSchema.describe('Domain to check (e.g., example.com)'),\n\tformat: FormatSchema.optional().describe('Output verbosity. Auto-detected if omitted.'),\n}).passthrough();\n\n/** scan_domain */\nexport const ScanDomainArgs = z.object({\n\tdomain: DomainSchema.describe('Domain to check (e.g., example.com)'),\n\tprofile: ProfileSchema.optional().describe('Scoring profile. Default \"auto\" detects.'),\n\tforce_refresh: z.boolean().optional().describe('Bypass cache and run a fresh scan. Useful after DNS changes.'),\n\tformat: FormatSchema.optional().describe('Output verbosity. Auto-detected if omitted.'),\n}).passthrough();\n\n/** batch_scan */\nexport const BatchScanArgs = z.object({\n\tdomains: z.array(z.string().min(1).max(253)).min(1).max(10).describe('Domains to scan (max 10 per request)'),\n\tforce_refresh: z.boolean().optional().describe('Bypass cache and run fresh scans.'),\n\tformat: FormatSchema.optional().describe('Output verbosity. Auto-detected if omitted.'),\n}).passthrough();\n\n/** compare_domains */\nexport const CompareDomainsArgs = z.object({\n\tdomains: z.array(z.string().min(1).max(253)).min(2).max(5).describe('Domains to compare (2–5 domains)'),\n\tformat: FormatSchema.optional().describe('Output verbosity. Auto-detected if omitted.'),\n}).passthrough();\n\n/** check_dkim */\nexport const CheckDkimArgs = z.object({\n\tdomain: DomainSchema.describe('Domain to check (e.g., example.com)'),\n\tselector: DkimSelectorSchema.optional().describe('DKIM selector. Omit to probe common ones.'),\n\tformat: FormatSchema.optional().describe('Output verbosity. Auto-detected if omitted.'),\n}).passthrough();\n\n/** check_resolver_consistency */\nexport const CheckResolverConsistencyArgs = z.object({\n\tdomain: DomainSchema.describe('Domain to check (e.g., example.com)'),\n\trecord_type: RecordTypeSchema.optional().describe('Record type. Omit for A/AAAA/MX/TXT/NS.'),\n\tformat: FormatSchema.optional().describe('Output verbosity. Auto-detected if omitted.'),\n}).passthrough();\n\n/** generate_spf_record */\nexport const GenerateSpfArgs = z.object({\n\tdomain: DomainSchema.describe('Domain (e.g., example.com)'),\n\t// SafeLabelSchema provides min(1)/max(253); .regex() adds a stacking refinement in Zod v4 (does not override).\n\tinclude_providers: z.array(SafeLabelSchema.regex(/^[a-z0-9._-]+$/i)).max(15).optional().describe('Providers to include (e.g., [\"google\"]).'),\n\tformat: FormatSchema.optional().describe('Output verbosity. Auto-detected if omitted.'),\n}).passthrough();\n\n/** generate_dmarc_record */\nexport const GenerateDmarcArgs = z.object({\n\tdomain: DomainSchema.describe('Domain (e.g., example.com)'),\n\tpolicy: DmarcPolicySchema.optional().describe('Policy (default \"reject\").'),\n\trua_email: z.string().max(254).optional().describe('Report email. Default: dmarc-reports@{domain}.'),\n\tformat: FormatSchema.optional().describe('Output verbosity. Auto-detected if omitted.'),\n}).passthrough();\n\n/** generate_dkim_config */\nexport const GenerateDkimConfigArgs = z.object({\n\tdomain: DomainSchema.describe('Domain (e.g., example.com)'),\n\tprovider: z.string().max(100).optional().describe('Provider (e.g., \"google\"). Omit for generic.'),\n\tformat: FormatSchema.optional().describe('Output verbosity. Auto-detected if omitted.'),\n}).passthrough();\n\n/** generate_mta_sts_policy */\nexport const GenerateMtaStsArgs = z.object({\n\tdomain: DomainSchema.describe('Domain (e.g., example.com)'),\n\t// SafeLabelSchema provides min(1)/max(253); .regex() adds a stacking refinement in Zod v4 (does not override).\n\tmx_hosts: z.array(SafeLabelSchema.regex(/^[^\\s\\x00-\\x1f\\x7f]*$/)).max(20).optional().describe('MX hosts. Omit to detect from DNS.'),\n\tformat: FormatSchema.optional().describe('Output verbosity. Auto-detected if omitted.'),\n}).passthrough();\n\n/** explain_finding */\nexport const ExplainFindingArgs = z.object({\n\tcheckType: z.string().min(1).max(100).describe(\"Check type (e.g., 'SPF', 'DMARC').\"),\n\tstatus: ExplainStatusSchema.describe('Finding severity or status.'),\n\tdetails: z.string().max(2000).optional().describe('Additional detail from check result.'),\n\tformat: FormatSchema.optional().describe('Output verbosity. Auto-detected if omitted.'),\n}).passthrough();\n\n/** compare_baseline */\nexport const CompareBaselineArgs = z.object({\n\tdomain: DomainSchema.describe('Domain to scan and compare.'),\n\tformat: FormatSchema.optional().describe('Output verbosity. Auto-detected if omitted.'),\n\tbaseline: z.object({\n\t\tgrade: GradeSchema.optional().describe('Min grade (e.g., \"B+\").'),\n\t\tscore: z.number().min(0).max(100).optional().describe('Min score (0-100).'),\n\t\trequire_dmarc_enforce: z.boolean().optional().describe('Require DMARC enforce.'),\n\t\trequire_spf: z.boolean().optional().describe('Require SPF.'),\n\t\trequire_dkim: z.boolean().optional().describe('Require DKIM.'),\n\t\trequire_dnssec: z.boolean().optional().describe('Require DNSSEC.'),\n\t\trequire_mta_sts: z.boolean().optional().describe('Require MTA-STS.'),\n\t\trequire_caa: z.boolean().optional().describe('Require CAA.'),\n\t\tmax_critical_findings: z.number().int().min(0).optional().describe('Max critical findings (default 0).'),\n\t\tmax_high_findings: z.number().int().min(0).optional().describe('Max high findings allowed.'),\n\t}).passthrough().describe('Policy baseline requirements.'),\n}).passthrough();\n\n/** get_benchmark */\nexport const GetBenchmarkArgs = z.object({\n\tprofile: BenchmarkProfileSchema.optional().describe('Profile to benchmark (default \"mail_enabled\").'),\n\tformat: FormatSchema.optional().describe('Output verbosity. Auto-detected if omitted.'),\n}).passthrough();\n\n/** get_provider_insights */\nexport const GetProviderInsightsArgs = z.object({\n\tprovider: z.string().min(1).describe('Provider (e.g., \"google workspace\").'),\n\tprofile: BenchmarkProfileSchema.optional().describe('Profile (default \"mail_enabled\").'),\n\tformat: FormatSchema.optional().describe('Output verbosity. Auto-detected if omitted.'),\n}).passthrough();\n\n/** assess_spoofability — same as BaseDomainArgs */\nexport const AssessSpoofabilityArgs = BaseDomainArgs;\n\n/** generate_fix_plan — same as BaseDomainArgs */\nexport const GenerateFixPlanArgs = BaseDomainArgs;\n\nconst CheckNameSchema = z.string().transform((v) => v.toLowerCase().trim()).pipe(\n\tz.enum(['spf', 'dmarc', 'dkim', 'dnssec', 'ssl', 'mta_sts', 'ns', 'caa', 'bimi', 'tlsrpt', 'http_security', 'dane']),\n);\n\nconst TimelineSchema = z.string().transform((v) => v.toLowerCase()).pipe(\n\tz.enum(['aggressive', 'standard', 'conservative']),\n);\n\nconst TargetPolicySchema = z.string().transform((v) => v.toLowerCase()).pipe(\n\tz.enum(['quarantine', 'reject']),\n);\n\n/** validate_fix */\nexport const ValidateFixArgs = z.object({\n\tdomain: DomainSchema.describe('Domain to validate the fix for'),\n\tcheck: CheckNameSchema.describe('Check name to re-run (e.g., \"dmarc\", \"spf\")'),\n\texpected: z.string().max(1000).optional().describe('Expected DNS record value to verify against'),\n\tformat: FormatSchema.optional().describe('Output verbosity. Auto-detected if omitted.'),\n}).passthrough();\n\n/** map_supply_chain — same as BaseDomainArgs */\nexport const MapSupplyChainArgs = BaseDomainArgs;\n\n/** analyze_drift */\nexport const AnalyzeDriftArgs = z.object({\n\tdomain: DomainSchema.describe('Domain to analyze drift for'),\n\tbaseline: z.string().min(1).max(50_000).describe('Previous ScanScore JSON or \"cached\" to use last cached scan'),\n\tformat: FormatSchema.optional().describe('Output verbosity. Auto-detected if omitted.'),\n}).passthrough();\n\n/** generate_rollout_plan */\nexport const GenerateRolloutPlanArgs = z.object({\n\tdomain: DomainSchema.describe('Domain to generate rollout plan for'),\n\ttarget_policy: TargetPolicySchema.optional().describe('Target DMARC policy (default: reject)'),\n\ttimeline: TimelineSchema.optional().describe('Rollout speed: aggressive, standard, conservative (default: standard)'),\n\tformat: FormatSchema.optional().describe('Output verbosity. Auto-detected if omitted.'),\n}).passthrough();\n\n/**\n * Map of every tool name to its Zod argument schema.\n * Used for runtime validation in tools.ts and for inputSchema generation.\n */\nexport const TOOL_SCHEMA_MAP: Record<string, z.ZodTypeAny> = {\n\tcheck_mx: BaseDomainArgs,\n\tcheck_spf: BaseDomainArgs,\n\tcheck_dmarc: BaseDomainArgs,\n\tcheck_dkim: CheckDkimArgs,\n\tcheck_dnssec: BaseDomainArgs,\n\tcheck_ssl: BaseDomainArgs,\n\tcheck_mta_sts: BaseDomainArgs,\n\tcheck_ns: BaseDomainArgs,\n\tcheck_caa: BaseDomainArgs,\n\tcheck_bimi: BaseDomainArgs,\n\tcheck_tlsrpt: BaseDomainArgs,\n\tcheck_lookalikes: BaseDomainArgs,\n\tcheck_shadow_domains: BaseDomainArgs,\n\tcheck_txt_hygiene: BaseDomainArgs,\n\tcheck_http_security: BaseDomainArgs,\n\tcheck_dane: BaseDomainArgs,\n\tcheck_dane_https: BaseDomainArgs,\n\tcheck_svcb_https: BaseDomainArgs,\n\tcheck_mx_reputation: BaseDomainArgs,\n\tcheck_srv: BaseDomainArgs,\n\tcheck_zone_hygiene: BaseDomainArgs,\n\tcheck_subdomailing: BaseDomainArgs,\n\tscan_domain: ScanDomainArgs,\n\tbatch_scan: BatchScanArgs,\n\tcompare_domains: CompareDomainsArgs,\n\tcompare_baseline: CompareBaselineArgs,\n\tgenerate_fix_plan: GenerateFixPlanArgs,\n\tgenerate_spf_record: GenerateSpfArgs,\n\tgenerate_dmarc_record: GenerateDmarcArgs,\n\tgenerate_dkim_config: GenerateDkimConfigArgs,\n\tgenerate_mta_sts_policy: GenerateMtaStsArgs,\n\tget_benchmark: GetBenchmarkArgs,\n\tget_provider_insights: GetProviderInsightsArgs,\n\tassess_spoofability: AssessSpoofabilityArgs,\n\tcheck_resolver_consistency: CheckResolverConsistencyArgs,\n\texplain_finding: ExplainFindingArgs,\n\tvalidate_fix: ValidateFixArgs,\n\tmap_supply_chain: MapSupplyChainArgs,\n\tanalyze_drift: AnalyzeDriftArgs,\n\tgenerate_rollout_plan: GenerateRolloutPlanArgs,\n\tresolve_spf_chain: BaseDomainArgs,\n\tdiscover_subdomains: BaseDomainArgs,\n\tmap_compliance: BaseDomainArgs,\n\tsimulate_attack_paths: BaseDomainArgs,\n};\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { z } from 'zod';\nimport {\n\tBaseDomainArgs,\n\tScanDomainArgs,\n\tBatchScanArgs,\n\tCompareDomainsArgs,\n\tCheckDkimArgs,\n\tCheckResolverConsistencyArgs,\n\tGenerateSpfArgs,\n\tGenerateDmarcArgs,\n\tGenerateDkimConfigArgs,\n\tGenerateMtaStsArgs,\n\tExplainFindingArgs,\n\tCompareBaselineArgs,\n\tGetBenchmarkArgs,\n\tGetProviderInsightsArgs,\n\tValidateFixArgs,\n\tMapSupplyChainArgs,\n\tAnalyzeDriftArgs,\n\tGenerateRolloutPlanArgs,\n\tTOOL_SCHEMA_MAP,\n} from './tool-args';\n\nexport type ToolGroup = 'email_auth' | 'infrastructure' | 'brand_threats' | 'dns_hygiene' | 'intelligence' | 'remediation' | 'meta';\nexport type ToolTier = 'core' | 'protective' | 'hardening';\n\nexport interface McpTool {\n\tname: string;\n\tdescription: string;\n\tinputSchema: {\n\t\ttype: string;\n\t\tproperties: Record<string, unknown>;\n\t\trequired?: string[];\n\t\t[key: string]: unknown;\n\t};\n\tannotations?: {\n\t\ttitle?: string;\n\t\treadOnlyHint?: boolean;\n\t\tdestructiveHint?: boolean;\n\t\tidempotentHint?: boolean;\n\t\topenWorldHint?: boolean;\n\t};\n\t/** Functional group for client-side tool discoverability. Not used in dispatch. */\n\tgroup: ToolGroup;\n\t/** Scoring tier from the three-tier model. Absent for non-scoring tools (meta/intelligence/remediation). */\n\ttier?: ToolTier;\n\t/** True when this tool is included in the scan_domain parallel orchestration. */\n\tscanIncluded: boolean;\n}\n\ninterface ToolDef {\n\tdescription: string;\n\tschema: z.ZodTypeAny;\n\tgroup: ToolGroup;\n\ttier?: ToolTier;\n\tscanIncluded: boolean;\n}\n\n/** DNS/security acronyms that should be uppercased in human-readable tool titles. */\nconst KNOWN_ACRONYMS = new Set(['mx', 'spf', 'dmarc', 'dkim', 'dnssec', 'ssl', 'mta', 'sts', 'ns', 'caa', 'bimi', 'tlsrpt', 'http', 'https', 'dane', 'svcb', 'srv', 'txt', 'doh', 'rpm']);\n\n/** Convert a snake_case tool name to a human-readable title. e.g. \"check_mta_sts\" → \"Check MTA STS\" */\nfunction toolNameToTitle(name: string): string {\n\treturn name\n\t\t.split('_')\n\t\t.map((word) => (KNOWN_ACRONYMS.has(word) ? word.toUpperCase() : word.charAt(0).toUpperCase() + word.slice(1)))\n\t\t.join(' ');\n}\n\n/** Convert a Zod schema to a JSON Schema object suitable for MCP inputSchema. */\nfunction toInputSchema(schema: z.ZodTypeAny): McpTool['inputSchema'] {\n\tconst jsonSchema = z.toJSONSchema(schema) as Record<string, unknown>;\n\tdelete jsonSchema.$schema;\n\t// Clean up additionalProperties: {} (equivalent to not having it, but cleaner)\n\tif (\n\t\tjsonSchema.additionalProperties !== undefined &&\n\t\ttypeof jsonSchema.additionalProperties === 'object' &&\n\t\tjsonSchema.additionalProperties !== null &&\n\t\tObject.keys(jsonSchema.additionalProperties).length === 0\n\t) {\n\t\tdelete jsonSchema.additionalProperties;\n\t}\n\treturn jsonSchema as McpTool['inputSchema'];\n}\n\n/** All 43 MCP tool definitions. */\nconst TOOL_DEFS: Record<string, ToolDef> = {\n\tcheck_mx: {\n\t\tdescription: 'Validate MX records and email provider detection.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'email_auth',\n\t\ttier: 'protective',\n\t\tscanIncluded: true,\n\t},\n\tcheck_spf: {\n\t\tdescription: 'Validate SPF syntax, policy, and trust surface.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'email_auth',\n\t\ttier: 'core',\n\t\tscanIncluded: true,\n\t},\n\tcheck_dmarc: {\n\t\tdescription: 'Validate DMARC policy, alignment, and reporting.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'email_auth',\n\t\ttier: 'core',\n\t\tscanIncluded: true,\n\t},\n\tcheck_dkim: {\n\t\tdescription: 'Probe DKIM selectors and validate key strength.',\n\t\tschema: CheckDkimArgs,\n\t\tgroup: 'email_auth',\n\t\ttier: 'core',\n\t\tscanIncluded: true,\n\t},\n\tcheck_dnssec: {\n\t\tdescription: 'Verify DNSSEC validation and DNSKEY/DS records.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'infrastructure',\n\t\ttier: 'core',\n\t\tscanIncluded: true,\n\t},\n\tcheck_ssl: {\n\t\tdescription: 'Verify SSL/TLS certificate and HTTPS config.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'infrastructure',\n\t\ttier: 'core',\n\t\tscanIncluded: true,\n\t},\n\tcheck_mta_sts: {\n\t\tdescription: 'Validate MTA-STS SMTP encryption policy.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'email_auth',\n\t\ttier: 'protective',\n\t\tscanIncluded: true,\n\t},\n\tcheck_ns: {\n\t\tdescription: 'Analyze NS delegation and provider diversity.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'infrastructure',\n\t\ttier: 'protective',\n\t\tscanIncluded: true,\n\t},\n\tcheck_caa: {\n\t\tdescription: 'Check authorized Certificate Authorities via CAA.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'infrastructure',\n\t\ttier: 'protective',\n\t\tscanIncluded: true,\n\t},\n\tcheck_bimi: {\n\t\tdescription: 'Validate BIMI record and VMC evidence.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'brand_threats',\n\t\ttier: 'hardening',\n\t\tscanIncluded: true,\n\t},\n\tcheck_tlsrpt: {\n\t\tdescription: 'Validate TLS-RPT SMTP failure reporting.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'brand_threats',\n\t\ttier: 'hardening',\n\t\tscanIncluded: true,\n\t},\n\tcheck_http_security: {\n\t\tdescription: 'Audit HTTP security headers (CSP, COOP, etc.).',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'infrastructure',\n\t\ttier: 'protective',\n\t\tscanIncluded: true,\n\t},\n\tcheck_dane: {\n\t\tdescription: 'Verify DANE/TLSA certificate pinning.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'infrastructure',\n\t\ttier: 'hardening',\n\t\tscanIncluded: true,\n\t},\n\tcheck_dane_https: {\n\t\tdescription: 'Verify DANE certificate pinning for HTTPS via TLSA records at _443._tcp.{domain}.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'infrastructure',\n\t\ttier: 'protective',\n\t\tscanIncluded: true,\n\t},\n\tcheck_svcb_https: {\n\t\tdescription: 'Validate HTTPS/SVCB records (RFC 9460) for modern transport capability advertisement.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'infrastructure',\n\t\ttier: 'protective',\n\t\tscanIncluded: true,\n\t},\n\tcheck_lookalikes: {\n\t\tdescription: 'Detect active typosquat/lookalike domains. Standalone.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'brand_threats',\n\t\ttier: 'protective',\n\t\tscanIncluded: false,\n\t},\n\tcheck_subdomailing: {\n\t\tdescription: 'Detect SubdoMailing risk by analyzing SPF include chain for takeover-vulnerable domains.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'email_auth',\n\t\ttier: 'protective',\n\t\tscanIncluded: true,\n\t},\n\tscan_domain: {\n\t\tdescription: 'Full DNS and email security audit. Score, grade, maturity, findings. Start here.',\n\t\tschema: ScanDomainArgs,\n\t\tgroup: 'meta',\n\t\tscanIncluded: false,\n\t},\n\tbatch_scan: {\n\t\tdescription: 'Scan up to 10 domains at once. Returns score, grade, and finding counts per domain.',\n\t\tschema: BatchScanArgs,\n\t\tgroup: 'meta',\n\t\tscanIncluded: false,\n\t},\n\tcompare_domains: {\n\t\tdescription: 'Side-by-side security comparison of 2–5 domains. Shows scores, category gaps, and unique weaknesses.',\n\t\tschema: CompareDomainsArgs,\n\t\tgroup: 'meta',\n\t\tscanIncluded: false,\n\t},\n\tcompare_baseline: {\n\t\tdescription: 'Compare domain security against a policy baseline.',\n\t\tschema: CompareBaselineArgs,\n\t\tgroup: 'meta',\n\t\tscanIncluded: false,\n\t},\n\tcheck_shadow_domains: {\n\t\tdescription: 'Find TLD variants with email auth gaps. Standalone.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'brand_threats',\n\t\ttier: 'protective',\n\t\tscanIncluded: false,\n\t},\n\tcheck_txt_hygiene: {\n\t\tdescription: 'Audit TXT records for stale entries and SaaS exposure.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'dns_hygiene',\n\t\ttier: 'hardening',\n\t\tscanIncluded: false,\n\t},\n\tcheck_mx_reputation: {\n\t\tdescription: 'Check MX blocklist status and reverse DNS.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'email_auth',\n\t\ttier: 'hardening',\n\t\tscanIncluded: false,\n\t},\n\tcheck_srv: {\n\t\tdescription: 'Probe SRV records for service footprint.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'infrastructure',\n\t\ttier: 'hardening',\n\t\tscanIncluded: false,\n\t},\n\tcheck_zone_hygiene: {\n\t\tdescription: 'Audit SOA propagation and sensitive subdomains.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'infrastructure',\n\t\ttier: 'hardening',\n\t\tscanIncluded: false,\n\t},\n\tgenerate_fix_plan: {\n\t\tdescription: 'Generate prioritized remediation plan with effort estimates.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'remediation',\n\t\tscanIncluded: false,\n\t},\n\tgenerate_spf_record: {\n\t\tdescription: 'Generate corrected SPF record from detected providers.',\n\t\tschema: GenerateSpfArgs,\n\t\tgroup: 'remediation',\n\t\tscanIncluded: false,\n\t},\n\tgenerate_dmarc_record: {\n\t\tdescription: 'Generate DMARC record with configurable policy.',\n\t\tschema: GenerateDmarcArgs,\n\t\tgroup: 'remediation',\n\t\tscanIncluded: false,\n\t},\n\tgenerate_dkim_config: {\n\t\tdescription: 'Generate DKIM setup instructions and DNS record.',\n\t\tschema: GenerateDkimConfigArgs,\n\t\tgroup: 'remediation',\n\t\tscanIncluded: false,\n\t},\n\tgenerate_mta_sts_policy: {\n\t\tdescription: 'Generate MTA-STS record and policy file.',\n\t\tschema: GenerateMtaStsArgs,\n\t\tgroup: 'remediation',\n\t\tscanIncluded: false,\n\t},\n\tget_benchmark: {\n\t\tdescription: 'Get score benchmarks: percentiles, mean, top failures.',\n\t\tschema: GetBenchmarkArgs,\n\t\tgroup: 'intelligence',\n\t\tscanIncluded: false,\n\t},\n\tget_provider_insights: {\n\t\tdescription: 'Get provider cohort benchmarks and common issues.',\n\t\tschema: GetProviderInsightsArgs,\n\t\tgroup: 'intelligence',\n\t\tscanIncluded: false,\n\t},\n\tassess_spoofability: {\n\t\tdescription: 'Composite email spoofability score (0-100).',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'intelligence',\n\t\tscanIncluded: false,\n\t},\n\tcheck_resolver_consistency: {\n\t\tdescription: 'Check DNS consistency across 4 public resolvers.',\n\t\tschema: CheckResolverConsistencyArgs,\n\t\tgroup: 'infrastructure',\n\t\tscanIncluded: false,\n\t},\n\texplain_finding: {\n\t\tdescription: 'Explain a finding with impact and remediation.',\n\t\tschema: ExplainFindingArgs,\n\t\tgroup: 'meta',\n\t\tscanIncluded: false,\n\t},\n\tmap_supply_chain: {\n\t\tdescription: 'Map third-party service dependencies from DNS records. Correlates SPF, NS, TXT verifications, SRV services, and CAA to show who can send as you, control your DNS, and what services are integrated.',\n\t\tschema: MapSupplyChainArgs,\n\t\tgroup: 'intelligence',\n\t\tscanIncluded: false,\n\t},\n\tanalyze_drift: {\n\t\tdescription: 'Compare current security posture against a previous baseline. Shows what improved, regressed, or changed.',\n\t\tschema: AnalyzeDriftArgs,\n\t\tgroup: 'intelligence',\n\t\tscanIncluded: false,\n\t},\n\tvalidate_fix: {\n\t\tdescription: 'Re-check a specific control after applying a fix. Confirms whether the finding is resolved.',\n\t\tschema: ValidateFixArgs,\n\t\tgroup: 'remediation',\n\t\tscanIncluded: false,\n\t},\n\tgenerate_rollout_plan: {\n\t\tdescription: 'Generate a phased DMARC enforcement timeline with exact DNS records per phase.',\n\t\tschema: GenerateRolloutPlanArgs,\n\t\tgroup: 'remediation',\n\t\tscanIncluded: false,\n\t},\n\tresolve_spf_chain: {\n\t\tdescription: 'Recursively resolve the full SPF include chain. Shows lookup count, tree depth, and flags issues like circular includes or exceeding the 10-lookup limit.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'intelligence',\n\t\tscanIncluded: false,\n\t},\n\tdiscover_subdomains: {\n\t\tdescription: 'Discover subdomains via Certificate Transparency logs. Reveals shadow IT, forgotten services, and unauthorized certificate issuance.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'intelligence',\n\t\tscanIncluded: false,\n\t},\n\tmap_compliance: {\n\t\tdescription: 'Map scan findings to compliance frameworks: NIST 800-177, PCI DSS 4.0, SOC 2, CIS Controls. Shows pass/fail/partial status per control.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'intelligence',\n\t\tscanIncluded: false,\n\t},\n\tsimulate_attack_paths: {\n\t\tdescription: 'Analyze current DNS posture and enumerate specific attack paths an adversary could exploit, with severity, feasibility, steps, and mitigations.',\n\t\tschema: BaseDomainArgs,\n\t\tgroup: 'intelligence',\n\t\tscanIncluded: false,\n\t},\n};\n\nexport const TOOLS: McpTool[] = Object.entries(TOOL_DEFS).map(([name, def]) => ({\n\tname,\n\tdescription: def.description,\n\tinputSchema: toInputSchema(def.schema),\n\tannotations: {\n\t\ttitle: toolNameToTitle(name),\n\t\treadOnlyHint: true,\n\t\tdestructiveHint: false,\n\t\tidempotentHint: true,\n\t\topenWorldHint: true,\n\t},\n\tgroup: def.group,\n\t...(def.tier !== undefined && { tier: def.tier }),\n\tscanIncluded: def.scanIncluded,\n}));\n\nexport { TOOL_SCHEMA_MAP };\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * BIMI (Brand Indicators for Message Identification) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkBIMI } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check BIMI records for a domain.\n * Validates the presence and configuration of BIMI TXT records,\n * including logo URL format and VMC authority evidence.\n */\nexport async function checkBimi(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkBIMI(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? 5000, fetchFn: fetch },\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * CAA (Certificate Authority Authorization) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkCAA } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check CAA records for a domain.\n * Validates that CAA records exist and are properly configured.\n */\nexport async function checkCaa(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkCAA(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? 5000 },\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DKIM (DomainKeys Identified Mail) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n * Retains applyProviderDkimContext for scan_domain post-processing.\n */\n\nimport { checkDKIM, createFinding, buildCheckResult } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\n/**\n * Email providers with high confidence of default DKIM signing.\n */\nconst HIGH_CONFIDENCE_DKIM_PROVIDERS = new Set([\n\t'amazon ses',\n\t'sendgrid',\n\t'mailgun',\n\t'postmark',\n\t'google workspace',\n\t'microsoft 365',\n]);\n\n/**\n * Email providers that typically sign with DKIM but vary by configuration.\n */\nconst MEDIUM_CONFIDENCE_DKIM_PROVIDERS = new Set(['proofpoint', 'mimecast']);\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check DKIM records for a domain.\n * Probes common selectors at <selector>._domainkey.<domain>.\n * Optionally accepts a specific selector to check.\n */\nexport async function checkDkim(domain: string, selector?: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkDKIM(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? 5000, selector },\n\t) as Promise<CheckResult>;\n}\n\n/**\n * Apply provider-informed context to DKIM results.\n * Called as a post-processing step in scan_domain after MX-based provider detection completes.\n * When a known DKIM-signing provider is detected, downgrades the \"No DKIM records found\"\n * finding from HIGH to MEDIUM since the provider likely signs outbound mail by default.\n */\nexport function applyProviderDkimContext(dkimResult: CheckResult, provider: string): CheckResult {\n\tconst normalizedProvider = provider.toLowerCase();\n\tconst notFoundIdx = dkimResult.findings.findIndex(\n\t\t(f) => /No DKIM records found/i.test(f.title) && f.severity === 'high',\n\t);\n\tif (notFoundIdx === -1) return dkimResult;\n\n\tconst selectorsChecked = (dkimResult.findings[notFoundIdx].metadata?.selectorsChecked as string[]) ?? [];\n\tconst newFindings = [...dkimResult.findings];\n\n\tif (HIGH_CONFIDENCE_DKIM_PROVIDERS.has(normalizedProvider)) {\n\t\tnewFindings[notFoundIdx] = createFinding(\n\t\t\t'dkim',\n\t\t\t'DKIM selector not discovered',\n\t\t\t'medium',\n\t\t\t`No DKIM selectors were found among the tested set, but ${provider} is detected as the email provider and signs outbound mail by default. DKIM is likely present with a custom selector.`,\n\t\t\t{\n\t\t\t\tconfidence: 'heuristic',\n\t\t\t\tdetectionMethod: 'provider-implied',\n\t\t\t\tprovider: normalizedProvider,\n\t\t\t\tselectorsChecked,\n\t\t\t},\n\t\t);\n\t} else if (MEDIUM_CONFIDENCE_DKIM_PROVIDERS.has(normalizedProvider)) {\n\t\tnewFindings[notFoundIdx] = createFinding(\n\t\t\t'dkim',\n\t\t\t'DKIM selector not discovered',\n\t\t\t'medium',\n\t\t\t`No DKIM selectors were found among the tested set. ${provider} is detected as the email provider and typically signs outbound mail.`,\n\t\t\t{\n\t\t\t\tconfidence: 'heuristic',\n\t\t\t\tdetectionMethod: 'provider-implied',\n\t\t\t\tprovider: normalizedProvider,\n\t\t\t\tselectorsChecked,\n\t\t\t},\n\t\t);\n\t\tnewFindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dkim',\n\t\t\t\t'DKIM provider signing unverified',\n\t\t\t\t'low',\n\t\t\t\t`${provider} signing policy varies by configuration — DKIM presence cannot be confirmed without selector discovery.`,\n\t\t\t\t{ confidence: 'heuristic' },\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('dkim', newFindings) as CheckResult;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DMARC (Domain-based Message Authentication, Reporting & Conformance) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkDMARC } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\nexport { parseDmarcTags } from '@blackveil/dns-checks';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check DMARC records for a domain.\n * Queries _dmarc.<domain> TXT records and validates policy configuration.\n */\nexport async function checkDmarc(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkDMARC(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? 5000 },\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DNSSEC (DNS Security Extensions) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkDNSSEC } from '@blackveil/dns-checks';\nimport { queryDns, queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { buildCheckResult, createFinding } from '../lib/scoring';\nimport type { CheckResult } from '../lib/scoring';\n\nexport { parseDnskeyAlgorithm, parseDsRecord } from '@blackveil/dns-checks';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check DNSSEC configuration for a domain.\n * Verifies the AD (Authenticated Data) flag, checks for DNSKEY/DS records,\n * and audits algorithm and digest type security.\n * Augments results with dnssecSource metadata: 'domain_configured' or 'tld_inherited'.\n */\nexport async function checkDnssec(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tconst baseResult = await checkDNSSEC(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{\n\t\t\ttimeout: dnsOptions?.timeoutMs ?? 5000,\n\t\t\trawQueryDNS: async (d, type, dnssecFlag) => {\n\t\t\t\tconst resp = await queryDns(d, type as Parameters<typeof queryDns>[1], dnssecFlag ?? false, dnsOptions);\n\t\t\t\treturn { AD: resp.AD, Answer: resp.Answer };\n\t\t\t},\n\t\t},\n\t) as CheckResult;\n\n\t// Skip augmentation when DNSSEC is definitively absent, failed, or misconfigured at the domain level.\n\t// 'DNSSEC chain of trust incomplete' means the domain has DNSKEY but no DS — it is domain-operator-configured\n\t// (just broken), not TLD-inherited. 'DNSSEC validation failing' means records exist but fail verification.\n\tconst dnssecAbsent =\n\t\tbaseResult.findings.some((f) => f.title === 'DNSSEC not enabled') ||\n\t\tbaseResult.findings.some((f) => f.title === 'DNSSEC check failed') ||\n\t\tbaseResult.findings.some((f) => f.title === 'DNSSEC chain of trust incomplete') ||\n\t\tbaseResult.findings.some((f) => f.title === 'DNSSEC validation failing');\n\tif (dnssecAbsent) {\n\t\treturn baseResult;\n\t}\n\n\t// Detect whether the domain has its own DNSKEY/DS (domain_configured) or inherits from TLD\n\tconst [dnskeyResult, dsResult] = await Promise.allSettled([\n\t\tqueryDnsRecords(domain, 'DNSKEY', dnsOptions),\n\t\tqueryDnsRecords(domain, 'DS', dnsOptions),\n\t]);\n\n\tconst hasDnskey = dnskeyResult.status === 'fulfilled' && dnskeyResult.value.length > 0;\n\tconst hasDs = dsResult.status === 'fulfilled' && dsResult.value.length > 0;\n\tconst dnssecSource = hasDnskey && hasDs ? 'domain_configured' : 'tld_inherited';\n\n\tif (dnssecSource === 'tld_inherited') {\n\t\tconst inheritedFinding = createFinding(\n\t\t\t'dnssec',\n\t\t\t'DNSSEC inherited from TLD',\n\t\t\t'info',\n\t\t\t`DNSSEC validation passes but ${domain} does not have its own DNSKEY or DS records. DNSSEC protection is inherited from the TLD registry, not configured by the domain owner.`,\n\t\t\t{ dnssecSource: 'tld_inherited' },\n\t\t);\n\t\treturn buildCheckResult('dnssec', [...baseResult.findings, inheritedFinding]);\n\t}\n\n\t// domain_configured — tag the first non-info finding with the source, or add a carrier finding\n\tif (baseResult.findings.length > 0) {\n\t\tconst [first, ...rest] = baseResult.findings;\n\t\tconst tagged = { ...first, metadata: { ...(first.metadata ?? {}), dnssecSource: 'domain_configured' } };\n\t\treturn buildCheckResult('dnssec', [tagged, ...rest]);\n\t}\n\n\tconst configuredFinding = createFinding(\n\t\t'dnssec',\n\t\t'DNSSEC configured by domain owner',\n\t\t'info',\n\t\t`${domain} has DNSKEY and DS records — DNSSEC is explicitly configured by the domain owner.`,\n\t\t{ dnssecSource: 'domain_configured' },\n\t);\n\treturn buildCheckResult('dnssec', [configuredFinding]);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Lookalike domain generation utilities.\n * Generates typosquat/lookalike domain permutations using multiple strategies:\n * adjacent key swaps, character omission, character duplication, dot insertion,\n * common TLD swaps, and homoglyph substitution.\n */\n\nimport { LABEL_REGEX, MAX_DOMAIN_LENGTH, MAX_LABEL_LENGTH } from '../lib/config';\n\n/** QWERTY keyboard adjacency map for typosquat detection */\nconst QWERTY_ADJACENT: Record<string, string[]> = {\n\tq: ['w', 'a'],\n\tw: ['q', 'e', 's', 'a'],\n\te: ['w', 'r', 'd', 's'],\n\tr: ['e', 't', 'f', 'd'],\n\tt: ['r', 'y', 'g', 'f'],\n\ty: ['t', 'u', 'h', 'g'],\n\tu: ['y', 'i', 'j', 'h'],\n\ti: ['u', 'o', 'k', 'j'],\n\to: ['i', 'p', 'l', 'k'],\n\tp: ['o', 'l'],\n\ta: ['q', 'w', 's', 'z'],\n\ts: ['a', 'w', 'e', 'd', 'z', 'x'],\n\td: ['s', 'e', 'r', 'f', 'x', 'c'],\n\tf: ['d', 'r', 't', 'g', 'c', 'v'],\n\tg: ['f', 't', 'y', 'h', 'v', 'b'],\n\th: ['g', 'y', 'u', 'j', 'b', 'n'],\n\tj: ['h', 'u', 'i', 'k', 'n', 'm'],\n\tk: ['j', 'i', 'o', 'l', 'm'],\n\tl: ['k', 'o', 'p'],\n\tz: ['a', 's', 'x'],\n\tx: ['z', 's', 'd', 'c'],\n\tc: ['x', 'd', 'f', 'v'],\n\tv: ['c', 'f', 'g', 'b'],\n\tb: ['v', 'g', 'h', 'n'],\n\tn: ['b', 'h', 'j', 'm'],\n\tm: ['n', 'j', 'k'],\n};\n\n/** Homoglyph substitution pairs (one substitution at a time) */\nconst HOMOGLYPHS: Array<[string, string]> = [\n\t['o', '0'],\n\t['0', 'o'],\n\t['l', '1'],\n\t['1', 'l'],\n\t['i', '1'],\n\t['1', 'i'],\n\t['l', 'i'],\n\t['i', 'l'],\n\t['rn', 'm'],\n\t['m', 'rn'],\n\t['vv', 'w'],\n\t['w', 'vv'],\n];\n\n/** Common TLD swap pairs */\nconst TLD_SWAPS: Array<[string, string]> = [\n\t['.com', '.co'],\n\t['.com', '.net'],\n\t['.com', '.org'],\n\t['.com', '.io'],\n\t['.co.nz', '.com'],\n\t['.com.au', '.com'],\n];\n\n/** Maximum number of permutations to return */\nconst MAX_PERMUTATIONS = 50;\n\n/**\n * Split a domain into base (before TLD) and TLD parts.\n * Handles multi-part TLDs like .co.nz and .com.au.\n */\nfunction splitDomainTld(domain: string): { base: string; tld: string } {\n\tconst multiPartTlds = ['.co.nz', '.com.au', '.co.uk', '.org.uk', '.net.au', '.org.au'];\n\tfor (const multiTld of multiPartTlds) {\n\t\tif (domain.endsWith(multiTld)) {\n\t\t\treturn { base: domain.slice(0, -multiTld.length), tld: multiTld };\n\t\t}\n\t}\n\tconst lastDot = domain.lastIndexOf('.');\n\tif (lastDot === -1) return { base: domain, tld: '' };\n\treturn { base: domain.slice(0, lastDot), tld: domain.slice(lastDot) };\n}\n\n/**\n * Check whether a domain string is structurally valid.\n * Labels must be 1-63 chars, alphanumeric + hyphens, total <= 253 chars.\n */\nfunction isDomainValid(domain: string): boolean {\n\tif (domain.length > MAX_DOMAIN_LENGTH) return false;\n\tconst labels = domain.split('.');\n\tif (labels.length < 2) return false;\n\tfor (const label of labels) {\n\t\tif (label.length === 0 || label.length > MAX_LABEL_LENGTH) return false;\n\t\tif (!LABEL_REGEX.test(label)) return false;\n\t}\n\treturn true;\n}\n\n/**\n * Generate lookalike/typosquat domain permutations for a given domain.\n * Applies six strategies: adjacent key swaps, character omission, character duplication,\n * dot insertion, common TLD swaps, and homoglyph substitution.\n *\n * Returns up to 50 unique, valid, alphabetically sorted permutations.\n */\nexport function generateLookalikes(domain: string): string[] {\n\tconst normalizedDomain = domain.toLowerCase();\n\tconst { base, tld } = splitDomainTld(normalizedDomain);\n\tconst candidates = new Set<string>();\n\n\t// 1. Adjacent key swaps — swap each char in base with QWERTY adjacent keys\n\tfor (let i = 0; i < base.length; i++) {\n\t\tconst ch = base[i];\n\t\tconst adjacent = QWERTY_ADJACENT[ch];\n\t\tif (adjacent) {\n\t\t\tfor (const adj of adjacent) {\n\t\t\t\tconst permuted = base.slice(0, i) + adj + base.slice(i + 1);\n\t\t\t\tcandidates.add(permuted + tld);\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. Character omission — remove one char at a time from base\n\tfor (let i = 0; i < base.length; i++) {\n\t\tconst permuted = base.slice(0, i) + base.slice(i + 1);\n\t\tif (permuted.length > 0) {\n\t\t\tcandidates.add(permuted + tld);\n\t\t}\n\t}\n\n\t// 3. Character duplication — double one char at a time in base\n\tfor (let i = 0; i < base.length; i++) {\n\t\tconst permuted = base.slice(0, i) + base[i] + base[i] + base.slice(i + 1);\n\t\tcandidates.add(permuted + tld);\n\t}\n\n\t// 4. Dot insertion — insert dots between chars in base (both parts must be >= 2 chars)\n\tfor (let i = 1; i < base.length; i++) {\n\t\tconst left = base.slice(0, i);\n\t\tconst right = base.slice(i);\n\t\tif (left.length >= 2 && right.length >= 2) {\n\t\t\tcandidates.add(left + '.' + right + tld);\n\t\t}\n\t}\n\n\t// 5. Common TLD swaps — swap to different TLD if original matches\n\tfor (const [fromTld, toTld] of TLD_SWAPS) {\n\t\tif (tld === fromTld) {\n\t\t\tcandidates.add(base + toTld);\n\t\t} else if (tld === toTld) {\n\t\t\tcandidates.add(base + fromTld);\n\t\t}\n\t}\n\n\t// 6. Homoglyph substitution — one substitution at a time in base\n\tfor (const [from, to] of HOMOGLYPHS) {\n\t\tlet searchIdx = 0;\n\t\twhile (searchIdx <= base.length - from.length) {\n\t\t\tconst idx = base.indexOf(from, searchIdx);\n\t\t\tif (idx === -1) break;\n\t\t\tconst permuted = base.slice(0, idx) + to + base.slice(idx + from.length);\n\t\t\tcandidates.add(permuted + tld);\n\t\t\tsearchIdx = idx + 1;\n\t\t}\n\t}\n\n\t// Filter, dedup, and cap\n\tconst results = Array.from(candidates)\n\t\t.filter((candidate) => candidate !== normalizedDomain && isDomainValid(candidate))\n\t\t.sort();\n\n\treturn results.slice(0, MAX_PERMUTATIONS);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Lookalike domain detection tool.\n * Generates typosquat/lookalike domain permutations and checks for\n * active DNS registrations and mail infrastructure.\n * Standalone check — not included in scan_domain due to query volume.\n */\n\nimport { queryDnsRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult, Finding } from '../lib/scoring';\nimport { buildCheckResult, createFinding } from '../lib/scoring';\nimport { generateLookalikes } from './lookalike-analysis';\n\n/** Default and minimum batch sizes for adaptive batching */\nexport const INITIAL_BATCH_SIZE = 10;\nexport const MIN_BATCH_SIZE = 3;\nexport const BACKOFF_DELAY_MS = 500;\nexport const FAILURE_THRESHOLD = 2;\n\n/** Maximum wall-clock time for the entire lookalike check (ms). */\nconst LOOKALIKE_TIMEOUT_MS = 20_000;\n\n/** Canary label used for wildcard detection on parent domains */\nexport const WILDCARD_CANARY_LABEL = '_bv-wc-probe';\n\n/** Lean DNS options for Phase 1 existence checks — fast, no retries, no secondary confirmation. */\nexport const PHASE1_DNS_OPTS: QueryDnsOptions = {\n\ttimeoutMs: 2000,\n\tretries: 0,\n\tskipSecondaryConfirmation: true,\n};\n\ninterface LookalikeResult {\n\tdomain: string;\n\thasA: boolean;\n\thasMX: boolean;\n}\n\n/** Minimum number of NS records that must overlap to consider domains as sharing nameservers. */\nconst SHARED_NS_THRESHOLD = 1;\n\n/**\n * Check whether an MX record represents real mail infrastructure.\n * RFC 7505 null MX (\"0 .\") explicitly means \"no mail accepted\" and must be excluded.\n */\nfunction isRealMxRecord(data: string): boolean {\n\t// Null MX: priority 0, exchange \".\" — RFC 7505\n\tconst trimmed = data.trim();\n\treturn trimmed !== '0 .' && trimmed !== '0\\t.';\n}\n\n/**\n * Check a single lookalike domain for DNS and MX records.\n * Filters out null MX records (RFC 7505) to avoid false positives.\n */\nasync function probeLookalike(domain: string): Promise<LookalikeResult> {\n\tconst [aRecords, mxRecords] = await Promise.allSettled([\n\t\tqueryDnsRecords(domain, 'A'),\n\t\tqueryDnsRecords(domain, 'MX'),\n\t]);\n\n\tconst realMxRecords =\n\t\tmxRecords.status === 'fulfilled' ? mxRecords.value.filter(isRealMxRecord) : [];\n\n\treturn {\n\t\tdomain,\n\t\thasA: aRecords.status === 'fulfilled' && aRecords.value.length > 0,\n\t\thasMX: realMxRecords.length > 0,\n\t};\n}\n\n/**\n * Count the number of labels (dot-separated segments) in a domain.\n */\nfunction labelCount(domain: string): number {\n\treturn domain.split('.').length;\n}\n\n/**\n * Extract the parent domain from a dot-insertion permutation.\n * E.g., \"blackve.ilsecurity.com\" → \"ilsecurity.com\"\n */\nfunction getParentDomain(domain: string): string {\n\tconst parts = domain.split('.');\n\treturn parts.slice(1).join('.');\n}\n\n/**\n * Detect wildcard DNS on a set of parent domains by probing a canary subdomain.\n * Returns a Set of parent domains that have wildcard A records.\n */\nasync function detectWildcardParents(parentDomains: string[]): Promise<Set<string>> {\n\tconst wildcardParents = new Set<string>();\n\tconst probes = parentDomains.map(async (parent) => {\n\t\ttry {\n\t\t\tconst canary = `${WILDCARD_CANARY_LABEL}.${parent}`;\n\t\t\tconst records = await queryDnsRecords(canary, 'A');\n\t\t\tif (records.length > 0) {\n\t\t\t\twildcardParents.add(parent);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Query failed — not a wildcard\n\t\t}\n\t});\n\tawait Promise.allSettled(probes);\n\treturn wildcardParents;\n}\n\n/**\n * Phase 1: Fast NS existence check for all domains in parallel.\n * Returns only domains that have NS records (i.e., are registered),\n * along with their normalized NS record data for ownership comparison.\n */\nasync function filterByNsExistence(domains: string[]): Promise<{ registered: string[]; nsMap: Map<string, Set<string>> }> {\n\tconst nsMap = new Map<string, Set<string>>();\n\tconst results = await Promise.allSettled(\n\t\tdomains.map(async (domain) => {\n\t\t\tconst ns = await queryDnsRecords(domain, 'NS', PHASE1_DNS_OPTS);\n\t\t\tif (ns.length > 0) {\n\t\t\t\tnsMap.set(domain, normalizeNsSet(ns));\n\t\t\t}\n\t\t\treturn { domain, hasNs: ns.length > 0 };\n\t\t}),\n\t);\n\tconst registered = results\n\t\t.filter(\n\t\t\t(r): r is PromiseFulfilledResult<{ domain: string; hasNs: boolean }> =>\n\t\t\t\tr.status === 'fulfilled' && r.value.hasNs,\n\t\t)\n\t\t.map((r) => r.value.domain);\n\treturn { registered, nsMap };\n}\n\n/**\n * Normalize a set of NS record values for comparison.\n * Strips trailing dots, lowercases, and returns a Set.\n */\nfunction normalizeNsSet(nsRecords: string[]): Set<string> {\n\treturn new Set(nsRecords.map((ns) => ns.replace(/\\.$/, '').toLowerCase()));\n}\n\n/**\n * Check whether two NS sets share at least SHARED_NS_THRESHOLD nameservers.\n * Shared nameservers are a strong signal that both domains are controlled by the same entity.\n */\nfunction sharesNameservers(primaryNs: Set<string>, lookalikeNs: Set<string>): boolean {\n\tlet overlap = 0;\n\tfor (const ns of lookalikeNs) {\n\t\tif (primaryNs.has(ns)) {\n\t\t\toverlap++;\n\t\t\tif (overlap >= SHARED_NS_THRESHOLD) return true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Query NS records for the primary domain to use for ownership comparison.\n * Returns an empty set if the query fails.\n */\nasync function queryPrimaryNs(domain: string): Promise<Set<string>> {\n\ttry {\n\t\tconst ns = await queryDnsRecords(domain, 'NS', PHASE1_DNS_OPTS);\n\t\treturn normalizeNsSet(ns);\n\t} catch {\n\t\treturn new Set<string>();\n\t}\n}\n\n/**\n * Run permutation probes with adaptive batch sizing and backoff.\n * Starts at INITIAL_BATCH_SIZE, halves on repeated failures (floor at MIN_BATCH_SIZE),\n * recovers on clean batches.\n */\nasync function probeWithAdaptiveBatching(\n\tpermutations: string[],\n): Promise<PromiseSettledResult<LookalikeResult>[]> {\n\tconst allResults: PromiseSettledResult<LookalikeResult>[] = [];\n\tlet batchSize = INITIAL_BATCH_SIZE;\n\tlet delayMs = 0;\n\n\tfor (let i = 0; i < permutations.length; i += batchSize) {\n\t\tif (delayMs > 0) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, delayMs));\n\t\t}\n\n\t\tconst batch = permutations.slice(i, i + batchSize);\n\t\tconst batchResults = await Promise.allSettled(batch.map((d) => probeLookalike(d)));\n\t\tallResults.push(...batchResults);\n\n\t\t// Count failures in this batch\n\t\tconst failures = batchResults.filter((r) => r.status === 'rejected').length;\n\t\tif (failures > FAILURE_THRESHOLD) {\n\t\t\t// Back off: halve batch size (floor to MIN_BATCH_SIZE) and add delay\n\t\t\tbatchSize = Math.max(MIN_BATCH_SIZE, Math.floor(batchSize / 2));\n\t\t\tdelayMs = BACKOFF_DELAY_MS;\n\t\t} else if (delayMs > 0 && failures === 0) {\n\t\t\t// Recover: if a clean batch after backoff, try increasing again\n\t\t\tbatchSize = Math.min(INITIAL_BATCH_SIZE, batchSize + 2);\n\t\t\tdelayMs = 0;\n\t\t}\n\t}\n\n\treturn allResults;\n}\n\n/**\n * Detect registered lookalike/typosquat domains with DNS or mail infrastructure.\n * Generates domain permutations and checks for active registrations using adaptive batching.\n * Filters out false positives from wildcard DNS on parent domains and null MX records.\n */\nexport async function checkLookalikes(domain: string): Promise<CheckResult> {\n\treturn Promise.race([\n\t\tcheckLookalikesCore(domain),\n\t\tnew Promise<never>((_, reject) => setTimeout(() => reject(new Error('Lookalike check timed out')), LOOKALIKE_TIMEOUT_MS)),\n\t]).catch(() => {\n\t\treturn buildCheckResult('lookalikes', [\n\t\t\tcreateFinding(\n\t\t\t\t'lookalikes',\n\t\t\t\t'Lookalike check incomplete',\n\t\t\t\t'info',\n\t\t\t\t'Lookalike check did not complete. This check generates many DNS queries — try again shortly, as partial results are cached.',\n\t\t\t),\n\t\t]);\n\t});\n}\n\nasync function checkLookalikesCore(domain: string): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\tconst permutations = generateLookalikes(domain);\n\n\tif (permutations.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'lookalikes',\n\t\t\t\t'No active lookalike domains detected',\n\t\t\t\t'info',\n\t\t\t\t`No lookalike domain permutations could be generated for ${domain}.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('lookalikes', findings);\n\t}\n\n\t// Identify dot-insertion permutations (they have more labels than the original domain)\n\tconst originalLabelCount = labelCount(domain);\n\tconst dotInsertionParents = new Map<string, string[]>(); // parent → [permutations]\n\tconst nonDotInsertionPerms: string[] = [];\n\n\tfor (const perm of permutations) {\n\t\tif (labelCount(perm) > originalLabelCount) {\n\t\t\tconst parent = getParentDomain(perm);\n\t\t\tconst existing = dotInsertionParents.get(parent);\n\t\t\tif (existing) {\n\t\t\t\texisting.push(perm);\n\t\t\t} else {\n\t\t\t\tdotInsertionParents.set(parent, [perm]);\n\t\t\t}\n\t\t} else {\n\t\t\tnonDotInsertionPerms.push(perm);\n\t\t}\n\t}\n\n\t// Detect wildcard DNS on parent domains of dot-insertion permutations\n\tconst wildcardParents = dotInsertionParents.size > 0\n\t\t? await detectWildcardParents([...dotInsertionParents.keys()])\n\t\t: new Set<string>();\n\n\t// Filter out permutations whose parent has wildcard DNS\n\tconst filteredDotInsertionPerms: string[] = [];\n\tfor (const [parent, perms] of dotInsertionParents) {\n\t\tif (!wildcardParents.has(parent)) {\n\t\t\tfilteredDotInsertionPerms.push(...perms);\n\t\t}\n\t}\n\n\tconst permsToProbe = [...nonDotInsertionPerms, ...filteredDotInsertionPerms];\n\n\t// Phase 1: Fast NS existence check — filter out unregistered domains\n\t// Also query the primary domain's NS for ownership comparison\n\tconst [nsResult, primaryNs] = await Promise.all([\n\t\tfilterByNsExistence(permsToProbe),\n\t\tqueryPrimaryNs(domain),\n\t]);\n\tconst { registered: registeredPerms, nsMap: lookalikeNsMap } = nsResult;\n\n\tif (registeredPerms.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'lookalikes',\n\t\t\t\t'No active lookalike domains detected',\n\t\t\t\t'info',\n\t\t\t\t`Checked ${permutations.length} domain permutations of ${domain}. No active registrations detected.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('lookalikes', findings);\n\t}\n\n\t// Phase 2: Detail probe only registered domains\n\tconst probeResults = await probeWithAdaptiveBatching(registeredPerms);\n\tconst results: LookalikeResult[] = [];\n\tfor (const result of probeResults) {\n\t\tif (result.status === 'fulfilled') {\n\t\t\tresults.push(result.value);\n\t\t}\n\t}\n\n\t// Classify results — check for shared nameservers with primary domain to detect defensive registrations\n\tlet highCount = 0;\n\tfor (const result of results) {\n\t\tconst lookalikeNs = lookalikeNsMap.get(result.domain);\n\t\tconst sameOwner = primaryNs.size > 0 && lookalikeNs !== undefined && sharesNameservers(primaryNs, lookalikeNs);\n\n\t\tif (sameOwner) {\n\t\t\t// Shared nameservers — likely a defensive registration by the same entity\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'lookalikes',\n\t\t\t\t\t`Lookalike domain likely owned by same entity: ${result.domain}`,\n\t\t\t\t\t'info',\n\t\t\t\t\t`The domain ${result.domain} shares nameservers with ${domain}, indicating it is likely a defensive registration by the same owner.${result.hasMX ? ' Has active mail infrastructure.' : ''}${result.hasA ? ' Has web presence.' : ''}`,\n\t\t\t\t\t{ lookalikeDomain: result.domain, hasA: result.hasA, hasMX: result.hasMX, sharedNs: true },\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (result.hasMX) {\n\t\t\thighCount++;\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'lookalikes',\n\t\t\t\t\t`Lookalike domain with mail infrastructure: ${result.domain}`,\n\t\t\t\t\t'high',\n\t\t\t\t\t`The domain ${result.domain} is registered with active mail servers (MX records), which could be used for phishing or email spoofing targeting ${domain}.`,\n\t\t\t\t\t{ lookalikeDomain: result.domain, hasA: result.hasA, hasMX: result.hasMX },\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (result.hasA) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'lookalikes',\n\t\t\t\t\t`Lookalike domain registered: ${result.domain}`,\n\t\t\t\t\t'medium',\n\t\t\t\t\t`The domain ${result.domain} is registered (has web presence) but no mail infrastructure detected. It could still be used for phishing websites targeting ${domain}.`,\n\t\t\t\t\t{ lookalikeDomain: result.domain, hasA: result.hasA, hasMX: result.hasMX },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Summary finding for high-severity lookalikes\n\tif (highCount > 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'lookalikes',\n\t\t\t\t`${highCount} lookalike domain${highCount > 1 ? 's' : ''} with mail capability detected`,\n\t\t\t\t'high',\n\t\t\t\t`${highCount} lookalike domain${highCount > 1 ? 's' : ''} of ${domain} ${highCount > 1 ? 'have' : 'has'} active mail infrastructure, presenting a phishing risk. Consider monitoring these domains and implementing DMARC with p=reject to protect your brand.`,\n\t\t\t\t{ lookalikeDomainCount: highCount },\n\t\t\t),\n\t\t);\n\t}\n\n\t// If no active lookalikes found\n\tif (findings.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'lookalikes',\n\t\t\t\t'No active lookalike domains detected',\n\t\t\t\t'info',\n\t\t\t\t`Checked ${permutations.length} domain permutations of ${domain}. No active registrations with DNS or mail infrastructure detected.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('lookalikes', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * MTA-STS (Mail Transfer Agent Strict Transport Security) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkMTASTS } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\nimport { HTTPS_TIMEOUT_MS } from '../lib/config';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check MTA-STS configuration for a domain.\n * Queries _mta-sts.<domain> TXT records and optionally fetches the policy file.\n */\nexport async function checkMtaSts(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkMTASTS(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? HTTPS_TIMEOUT_MS, fetchFn: fetch },\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nexport interface ProviderSignature {\n\tname: string;\n\tdomains: string[];\n\tselectorHints?: string[];\n}\n\nexport interface ProviderSignaturePayload {\n\tversion?: string;\n\tinbound?: ProviderSignature[];\n\toutbound?: ProviderSignature[];\n}\n\nexport interface ProviderSourceResult {\n\tversion: string;\n\tsource: 'runtime' | 'stale' | 'built-in';\n\tfetchedAt: string;\n\tdegraded: boolean;\n\tinbound: ProviderSignature[];\n\toutbound: ProviderSignature[];\n}\n\nexport interface LoadProviderSignaturesOptions {\n\tsourceUrl?: string;\n\tallowedHosts?: string[];\n\texpectedSha256?: string;\n\ttimeoutMs?: number;\n\tretries?: number;\n}\n\nexport const DEFAULT_TIMEOUT_MS = 2500;\nexport const DEFAULT_RETRIES = 1;\nexport const RUNTIME_SIGNATURE_CACHE_TTL_MS = 5 * 60 * 1000;\n\nexport const BUILT_IN_SIGNATURES: ProviderSignaturePayload = {\n\tversion: 'built-in-2026-03-04',\n\tinbound: [\n\t\t{ name: 'Google Workspace', domains: ['google.com', 'googlemail.com'], selectorHints: ['google'] },\n\t\t{ name: 'Microsoft 365', domains: ['outlook.com', 'protection.outlook.com'], selectorHints: ['selector1', 'selector2'] },\n\t\t{ name: 'Proofpoint', domains: ['pphosted.com'] },\n\t\t{ name: 'Mimecast', domains: ['mimecast.com'], selectorHints: ['mimecast'] },\n\t\t{ name: 'Mailgun', domains: ['mailgun.org'] },\n\t\t{ name: 'SendGrid', domains: ['sendgrid.net'] },\n\t\t{ name: 'Amazon SES', domains: ['amazonses.com'] },\n\t],\n\toutbound: [],\n};\n\nexport function normalizeSha256(value: string): string {\n\treturn value.trim().toLowerCase().replace(/^sha256:/, '');\n}\n\nexport function normalizeAllowedHosts(input: string[] | undefined): string[] {\n\tif (!Array.isArray(input)) return [];\n\treturn input.map((host) => host.trim().toLowerCase()).filter((host) => host.length > 0);\n}\n\nexport function validateRuntimeSourceUrl(sourceUrl: string, allowedHosts: string[]): URL {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(sourceUrl);\n\t} catch {\n\t\tthrow new Error('Invalid provider signature source URL');\n\t}\n\n\tif (url.protocol !== 'https:') {\n\t\tthrow new Error('Invalid provider signature source URL: HTTPS is required');\n\t}\n\n\tif (allowedHosts.length > 0 && !allowedHosts.includes(url.hostname.toLowerCase())) {\n\t\tthrow new Error('Invalid provider signature source URL: host is not allowlisted');\n\t}\n\n\treturn url;\n}\n\nasync function sha256Hex(input: string): Promise<string> {\n\tconst digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(input));\n\treturn Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\nfunction normalizeDomain(value: string): string {\n\treturn value.trim().toLowerCase().replace(/\\.$/, '');\n}\n\nfunction normalizeProviderSignatures(input: ProviderSignature[] | undefined): ProviderSignature[] {\n\tif (!Array.isArray(input)) return [];\n\n\treturn input\n\t\t.map((provider) => {\n\t\t\tconst name = typeof provider?.name === 'string' ? provider.name.trim() : '';\n\t\t\tconst domains = Array.isArray(provider?.domains)\n\t\t\t\t? provider.domains.map((domain) => normalizeDomain(String(domain))).filter((domain) => domain.length > 0)\n\t\t\t\t: [];\n\t\t\tconst selectorHints = Array.isArray(provider?.selectorHints)\n\t\t\t\t? provider.selectorHints.map((selector) => String(selector).trim().toLowerCase()).filter((selector) => selector.length > 0)\n\t\t\t\t: [];\n\t\t\treturn { name, domains, ...(selectorHints.length > 0 ? { selectorHints } : {}) };\n\t\t})\n\t\t.filter((provider) => provider.name.length > 0 && provider.domains.length > 0);\n}\n\nexport function buildResult(\n\tpayload: ProviderSignaturePayload,\n\tsource: ProviderSourceResult['source'],\n\tdegraded: boolean,\n): ProviderSourceResult {\n\tconst inbound = normalizeProviderSignatures(payload.inbound);\n\tconst outbound = normalizeProviderSignatures(payload.outbound);\n\n\treturn {\n\t\tversion: payload.version?.trim() || BUILT_IN_SIGNATURES.version || 'unknown',\n\t\tsource,\n\t\tfetchedAt: new Date().toISOString(),\n\t\tdegraded,\n\t\tinbound,\n\t\toutbound,\n\t};\n}\n\nexport function isValidSignaturePayload(payload: unknown): payload is ProviderSignaturePayload {\n\tif (!payload || typeof payload !== 'object') return false;\n\tconst record = payload as Record<string, unknown>; // typeof payload === 'object' is checked above\n\tif (record.version !== undefined && typeof record.version !== 'string') return false;\n\tif (record.inbound !== undefined && !Array.isArray(record.inbound)) return false;\n\tif (record.outbound !== undefined && !Array.isArray(record.outbound)) return false;\n\treturn true;\n}\n\nexport async function fetchProviderPayload(\n\turl: string,\n\ttimeoutMs: number,\n\tretries: number,\n\texpectedSha256?: string,\n): Promise<ProviderSignaturePayload | null> {\n\tfor (let attempt = 0; attempt <= retries; attempt++) {\n\t\tconst controller = new AbortController();\n\t\tconst timeout = setTimeout(() => controller.abort(), timeoutMs);\n\t\ttry {\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tmethod: 'GET',\n\t\t\t\theaders: { Accept: 'application/json' },\n\t\t\t\tsignal: controller.signal,\n\t\t\t\tredirect: 'manual',\n\t\t\t});\n\t\t\tif (response.status >= 300 && response.status < 400) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (!response.ok) {\n\t\t\t\tif (attempt < retries && response.status >= 500) continue;\n\t\t\t\tthrow new Error(`Provider signature source returned HTTP ${response.status}`);\n\t\t\t}\n\n\t\t\tconst MAX_BODY_BYTES = 1_048_576; // 1 MB — provider signature JSON from pinned source\n\t\t\tconst contentLength = parseInt(response.headers?.get('content-length') ?? '0', 10);\n\t\t\tif (contentLength > MAX_BODY_BYTES) {\n\t\t\t\tthrow new Error(`Provider signature source exceeds ${MAX_BODY_BYTES} bytes (Content-Length: ${contentLength})`);\n\t\t\t}\n\t\t\tconst rawPayload = await response.text();\n\t\t\tif (rawPayload.length > MAX_BODY_BYTES) {\n\t\t\t\tthrow new Error(`Provider signature source exceeds ${MAX_BODY_BYTES} bytes`);\n\t\t\t}\n\t\t\tif (!expectedSha256) {\n\t\t\t\tthrow new Error('Provider signature source requires a pinned SHA-256 digest');\n\t\t\t}\n\n\t\t\tconst digest = await sha256Hex(rawPayload);\n\t\t\tif (digest !== normalizeSha256(expectedSha256)) {\n\t\t\t\tthrow new Error('Provider signature source failed SHA-256 verification');\n\t\t\t}\n\n\t\t\tconst payload = JSON.parse(rawPayload) as unknown;\n\t\t\tif (!isValidSignaturePayload(payload)) {\n\t\t\t\tthrow new Error('Provider signature source returned an invalid payload shape');\n\t\t\t}\n\n\t\t\treturn payload;\n\t\t} catch (error) {\n\t\t\tif (attempt < retries) continue;\n\t\t\tif (error instanceof DOMException && error.name === 'AbortError') {\n\t\t\t\tthrow new Error(`Provider signature source timed out after ${timeoutMs}ms`);\n\t\t\t}\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tclearTimeout(timeout);\n\t\t}\n\t}\n\n\tthrow new Error('Failed to load provider signatures');\n}","// SPDX-License-Identifier: BUSL-1.1\n\nimport {\n\tBUILT_IN_SIGNATURES,\n\tbuildResult,\n\tDEFAULT_RETRIES,\n\tDEFAULT_TIMEOUT_MS,\n\tfetchProviderPayload,\n\ttype LoadProviderSignaturesOptions,\n\tnormalizeAllowedHosts,\n\ttype ProviderSignature,\n\ttype ProviderSourceResult,\n\tRUNTIME_SIGNATURE_CACHE_TTL_MS,\n\tvalidateRuntimeSourceUrl,\n} from './provider-signature-source';\n\ninterface ProviderMatchEvidence {\n\tprovider: string;\n\tmatches: string[];\n}\n\nlet lastKnownGood: ProviderSourceResult | null = null;\nlet runtimeSignatureCache: {\n\tsourceUrl: string;\n\tresult: ProviderSourceResult;\n\texpiresAt: number;\n} | null = null;\n\nfunction normalizeDomain(value: string): string {\n\treturn value.trim().toLowerCase().replace(/\\.$/, '');\n}\n\nfunction boundarySuffixMatch(hostname: string, suffix: string): boolean {\n\tconst host = normalizeDomain(hostname);\n\tconst normalizedSuffix = normalizeDomain(suffix);\n\tif (!host || !normalizedSuffix) return false;\n\treturn host === normalizedSuffix || host.endsWith(`.${normalizedSuffix}`);\n}\n\n\nexport async function loadProviderSignatures(options?: LoadProviderSignaturesOptions): Promise<ProviderSourceResult> {\n\tconst timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\tconst retries = options?.retries ?? DEFAULT_RETRIES;\n\tconst sourceUrl = options?.sourceUrl?.trim();\n\tconst allowedHosts = normalizeAllowedHosts(options?.allowedHosts);\n\tconst expectedSha256 = options?.expectedSha256?.trim();\n\n\tif (!sourceUrl) {\n\t\treturn buildResult(BUILT_IN_SIGNATURES, 'built-in', false);\n\t}\n\n\tconst now = Date.now();\n\tif (runtimeSignatureCache && runtimeSignatureCache.sourceUrl === sourceUrl && runtimeSignatureCache.expiresAt > now) {\n\t\treturn runtimeSignatureCache.result;\n\t}\n\n\ttry {\n\t\tconst validatedUrl = validateRuntimeSourceUrl(sourceUrl, allowedHosts);\n\t\tconst payload = await fetchProviderPayload(validatedUrl.toString(), timeoutMs, retries, expectedSha256);\n\t\tif (!payload) {\n\t\t\tthrow new Error('Provider signature source returned a redirect');\n\t\t}\n\t\tconst result = buildResult(payload, 'runtime', false);\n\t\tlastKnownGood = result;\n\t\truntimeSignatureCache = {\n\t\t\tsourceUrl,\n\t\t\tresult,\n\t\t\texpiresAt: now + RUNTIME_SIGNATURE_CACHE_TTL_MS,\n\t\t};\n\t\treturn result;\n\t} catch {\n\t\tif (lastKnownGood) {\n\t\t\tconst staleResult = { ...lastKnownGood, source: 'stale' as const, degraded: true, fetchedAt: new Date().toISOString() };\n\t\t\truntimeSignatureCache = {\n\t\t\t\tsourceUrl,\n\t\t\t\tresult: staleResult,\n\t\t\t\texpiresAt: now + RUNTIME_SIGNATURE_CACHE_TTL_MS,\n\t\t\t};\n\t\t\treturn staleResult;\n\t\t}\n\t\tconst fallbackResult = buildResult(BUILT_IN_SIGNATURES, 'built-in', true);\n\t\truntimeSignatureCache = {\n\t\t\tsourceUrl,\n\t\t\tresult: fallbackResult,\n\t\t\texpiresAt: now + RUNTIME_SIGNATURE_CACHE_TTL_MS,\n\t\t};\n\t\treturn fallbackResult;\n\t}\n}\n\n/**\n * Test helper to reset provider signature loader state between cases.\n * @internal Exported for test use only.\n */\nexport function resetProviderSignatureState(): void {\n\tlastKnownGood = null;\n\truntimeSignatureCache = null;\n}\n\nexport function detectProviderMatches(hosts: string[], signatures: ProviderSignature[]): ProviderMatchEvidence[] {\n\tconst normalizedHosts = hosts.map((host) => normalizeDomain(host)).filter((host) => host.length > 0);\n\tconst matches: ProviderMatchEvidence[] = [];\n\n\tfor (const provider of signatures) {\n\t\tconst providerMatches = new Set<string>();\n\t\tfor (const host of normalizedHosts) {\n\t\t\tif (provider.domains.some((domain) => boundarySuffixMatch(host, domain))) {\n\t\t\t\tproviderMatches.add(host);\n\t\t\t}\n\t\t}\n\t\tif (providerMatches.size > 0) {\n\t\t\tmatches.push({ provider: provider.name, matches: Array.from(providerMatches) });\n\t\t}\n\t}\n\n\treturn matches;\n}\n\nexport function detectProviderMatchesBySelectors(selectors: string[], signatures: ProviderSignature[]): ProviderMatchEvidence[] {\n\tconst normalizedSelectors = selectors.map((selector) => selector.trim().toLowerCase()).filter((selector) => selector.length > 0);\n\tconst matches: ProviderMatchEvidence[] = [];\n\n\tfor (const provider of signatures) {\n\t\tconst hints = provider.selectorHints ?? [];\n\t\tif (hints.length === 0) continue;\n\n\t\tconst providerMatches = normalizedSelectors.filter((selector) => hints.includes(selector));\n\t\tif (providerMatches.length > 0) {\n\t\t\tmatches.push({ provider: provider.name, matches: Array.from(new Set(providerMatches)) });\n\t\t}\n\t}\n\n\treturn matches;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * MX record check tool for MCP server.\n * Thin wrapper around @blackveil/dns-checks — delegates core logic to the shared package.\n * Adds provider detection post-processing on top of the package result.\n */\n\nimport { checkMX, createFinding } from '@blackveil/dns-checks';\nimport type { CheckResult } from '../lib/scoring';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { detectProviderMatches, loadProviderSignatures } from '../lib/provider-signatures';\n\nexport interface CheckMxOptions {\n\tproviderSignaturesUrl?: string;\n\tproviderSignaturesAllowedHosts?: string[];\n\tproviderSignaturesSha256?: string;\n}\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/** Check MX record configuration for a domain */\nexport async function checkMx(domain: string, options?: CheckMxOptions, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tconst timeout = dnsOptions?.timeoutMs ?? 5000;\n\n\t// Run core MX check from shared package\n\tconst baseResult = await checkMX(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout },\n\t) as CheckResult;\n\n\t// Early return if MX check already returned critical/error findings (no MX records, etc.)\n\t// Only add provider detection when we have meaningful MX records\n\tconst hasCritical = baseResult.findings.some((f) => f.severity === 'critical');\n\tconst hasMediumQueryFailed = baseResult.findings.some((f) => f.title === 'DNS query failed');\n\tif (hasCritical || hasMediumQueryFailed) {\n\t\treturn baseResult;\n\t}\n\n\t// Provider detection post-processing\n\tconst findings = [...baseResult.findings];\n\n\ttry {\n\t\t// Re-query MX records to get raw strings for provider matching\n\t\tconst mxAnswers = await queryDnsRecords(domain, 'MX', dnsOptions);\n\t\tconst mxTargets = mxAnswers.map((answer) => {\n\t\t\tconst parts = answer.split(' ');\n\t\t\treturn (parts.slice(1).join(' ') || '').replace(/\\.$/, '').toLowerCase();\n\t\t}).filter(Boolean);\n\n\t\tif (mxTargets.length > 0) {\n\t\t\tconst providerSignatures = await loadProviderSignatures({\n\t\t\t\tsourceUrl: options?.providerSignaturesUrl,\n\t\t\t\tallowedHosts: options?.providerSignaturesAllowedHosts,\n\t\t\t\texpectedSha256: options?.providerSignaturesSha256,\n\t\t\t});\n\t\t\tconst inboundMatches = detectProviderMatches(mxTargets, providerSignatures.inbound);\n\n\t\t\tif (inboundMatches.length > 0) {\n\t\t\t\tconst providerNames = inboundMatches.map((m) => m.provider).join(', ');\n\t\t\t\tconst evidence = inboundMatches.map((m) => `${m.provider}: ${m.matches.join(', ')}`).join('; ');\n\t\t\t\tconst providerConfidence = providerSignatures.source === 'runtime' ? 0.95 : providerSignatures.source === 'stale' ? 0.75 : 0.7;\n\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding('mx', 'Managed email provider detected', 'info', `Inbound provider(s): ${providerNames}. Evidence: ${evidence}.`, {\n\t\t\t\t\t\tdetectionType: 'inbound',\n\t\t\t\t\t\tproviders: inboundMatches.map((m) => ({ name: m.provider, matches: m.matches })),\n\t\t\t\t\t\tproviderConfidence,\n\t\t\t\t\t\tsignatureSource: providerSignatures.source,\n\t\t\t\t\t\tsignatureVersion: providerSignatures.version,\n\t\t\t\t\t\tsignatureFetchedAt: providerSignatures.fetchedAt,\n\t\t\t\t\t}) as (typeof findings)[0],\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (providerSignatures.degraded) {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'mx',\n\t\t\t\t\t\t'Provider signature source unavailable',\n\t\t\t\t\t\t'info',\n\t\t\t\t\t\t`Provider detection used ${providerSignatures.source === 'stale' ? 'stale cached' : 'built-in fallback'} signatures.`,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdetectionType: 'inbound',\n\t\t\t\t\t\t\tproviderConfidence: providerSignatures.source === 'stale' ? 0.55 : 0.45,\n\t\t\t\t\t\t\tsignatureSource: providerSignatures.source,\n\t\t\t\t\t\t\tsignatureVersion: providerSignatures.version,\n\t\t\t\t\t\t\tsignatureFetchedAt: providerSignatures.fetchedAt,\n\t\t\t\t\t\t},\n\t\t\t\t\t) as (typeof findings)[0],\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Provider detection failure is non-critical — return base result\n\t}\n\n\treturn { ...baseResult, findings };\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * NS (Name Server) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkNS } from '@blackveil/dns-checks';\nimport { queryDns, queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check nameserver configuration for a domain.\n * Validates NS records exist, checks for diversity, and verifies responsiveness.\n */\nexport async function checkNs(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkNS(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{\n\t\t\ttimeout: dnsOptions?.timeoutMs ?? 5000,\n\t\t\trawQueryDNS: async (d, type, dnssecFlag) => {\n\t\t\t\tconst resp = await queryDns(d, type as Parameters<typeof queryDns>[1], dnssecFlag ?? false, dnsOptions);\n\t\t\t\treturn { AD: resp.AD, Answer: resp.Answer };\n\t\t\t},\n\t\t},\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * SPF (Sender Policy Framework) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkSPF } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\n/**\n * Build a DNSQueryFunction adapter that routes TXT queries through queryTxtRecords\n * (which strips surrounding quotes from DoH TXT data) and all other record types\n * through queryDnsRecords.\n */\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check SPF records for a domain.\n * Looks for v=spf1 TXT records and validates their configuration.\n * Recursively expands include chains to compute true DNS lookup count.\n */\nexport async function checkSpf(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkSPF(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? 5000 },\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * SSL/TLS certificate check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkSSL } from '@blackveil/dns-checks';\nimport type { CheckResult } from '../lib/scoring';\nimport { HTTPS_TIMEOUT_MS } from '../lib/config';\n\n/**\n * Check SSL/TLS configuration for a domain.\n * Validates HTTPS connectivity, HSTS headers, and HTTP→HTTPS redirect.\n */\nexport async function checkSsl(domain: string): Promise<CheckResult> {\n\treturn checkSSL(domain, fetch, { timeout: HTTPS_TIMEOUT_MS }) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Subdomain Takeover / Dangling CNAME Detection Tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkSubdomainTakeover as checkSubdomainTakeoverPkg } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\nimport { HTTPS_TIMEOUT_MS } from '../lib/config';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check for dangling CNAME records on known/active subdomains.\n * Flags orphaned records and potential takeover vectors.\n */\nexport async function checkSubdomainTakeover(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkSubdomainTakeoverPkg(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? HTTPS_TIMEOUT_MS, fetchFn: fetch },\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * TLS-RPT (SMTP TLS Reporting) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkTLSRPT } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check TLS-RPT records for a domain.\n * Validates the presence and configuration of SMTP TLS Reporting records.\n */\nexport async function checkTlsrpt(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkTLSRPT(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? 5000 },\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { sanitizeInput } from './sanitize';\n\nconst MARKDOWN_SYNTAX = /[`*_#[\\]()>|<]/g;\n\n/**\n * Characters that can inject HTML or dangerous markdown constructs.\n * Excludes `_` (common in DNS names like `_dmarc`, `_mta-sts`) and\n * `()` (used in natural-language detail text) which are safe in finding details.\n */\nconst DNS_DATA_UNSAFE = /[`*#[\\]>|<]/g;\n\n/**\n * Sanitize DNS-sourced data before it enters finding detail strings.\n * Strips C0 control characters (preserving tab/newline), replaces HTML/markdown\n * injection characters, but does NOT truncate — DNS data in findings can be\n * longer than display output.\n */\nexport function sanitizeDnsData(input: string): string {\n\treturn input\n\t\t.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]/g, '')\n\t\t.replace(DNS_DATA_UNSAFE, ' ')\n\t\t.replace(/\\s+/g, ' ')\n\t\t.trim();\n}\n\nexport function sanitizeOutputText(input: string, maxLength = 240): string {\n\tconst trimmed = sanitizeInput(input, maxLength * 2)\n\t\t.replace(/\\x1b\\[[0-9;]*[a-zA-Z]/g, '')\n\t\t.replace(MARKDOWN_SYNTAX, ' ')\n\t\t.replace(/\\s+/g, ' ')\n\t\t.trim();\n\n\tif (trimmed.length <= maxLength) {\n\t\treturn trimmed;\n\t}\n\n\treturn `${trimmed.slice(0, maxLength - 3).trimEnd()}...`;\n}","export interface ExplanationTemplate {\n\ttitle: string;\n\tseverity: string;\n\texplanation: string;\n\timpact?: string;\n\tadverseConsequences?: string;\n\trecommendation: string;\n\treferences: string[];\n}\n\nexport interface ImpactNarrative {\n\timpact?: string;\n\tadverseConsequences?: string;\n}\n\nexport interface SpecificImpactRule extends ImpactNarrative {\n\tcheckType?: string;\n\ttitleIncludes?: string[];\n\tdetailIncludes?: string[];\n}\n\nexport const EXPLANATIONS: Record<string, ExplanationTemplate> = {\n\tSUBDOMAIN_TAKEOVER_CRITICAL: {\n\t\ttitle: 'Dangling CNAME — Subdomain Takeover Risk',\n\t\tseverity: 'critical',\n\t\texplanation:\n\t\t\t'A subdomain points to a third-party service (e.g., CloudFront, Heroku) that does not resolve. This is a potential subdomain takeover vector, allowing attackers to claim the orphaned resource and control the subdomain.',\n\t\timpact: 'Attackers may host malicious content or capture traffic on a trusted subdomain, enabling phishing and session abuse.',\n\t\tadverseConsequences:\n\t\t\t'Brand trust can be damaged, users can be redirected to attacker infrastructure, and incident response costs can increase.',\n\t\trecommendation: 'Remove or update the CNAME record to point to a valid, owned resource. Regularly audit DNS for orphaned records.',\n\t\treferences: [\n\t\t\t'https://github.com/EdOverflow/can-i-take-over-xyz',\n\t\t\t'https://www.hackerone.com/blog/Guide-Subdomain-Takeover',\n\t\t\t'https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html',\n\t\t],\n\t},\n\tSUBDOMAIN_TAKEOVER_HIGH: {\n\t\ttitle: 'CNAME Resolution Failed — Manual Review Needed',\n\t\tseverity: 'high',\n\t\texplanation:\n\t\t\t'A subdomain CNAME points to a third-party service but the target could not be resolved. This may indicate a takeover risk or DNS misconfiguration.',\n\t\timpact: 'If the target is orphaned, an attacker may be able to claim it and gain control of the affected subdomain.',\n\t\tadverseConsequences: 'Users may be exposed to fraudulent pages and the organization may face reputation damage until DNS is remediated.',\n\t\trecommendation: 'Manually review the CNAME target and remove or update if orphaned. Use DNS monitoring tools for ongoing checks.',\n\t\treferences: [\n\t\t\t'https://github.com/EdOverflow/can-i-take-over-xyz',\n\t\t\t'https://www.hackerone.com/blog/Guide-Subdomain-Takeover',\n\t\t],\n\t},\n\tSUBDOMAIN_TAKEOVER_INFO: {\n\t\ttitle: 'No Dangling CNAME Records Found',\n\t\tseverity: 'info',\n\t\texplanation: 'No subdomain takeover vectors detected among known/active subdomains. DNS configuration is secure for this check.',\n\t\trecommendation: 'Continue regular DNS audits and monitoring for new subdomains or changes.',\n\t\treferences: ['https://github.com/EdOverflow/can-i-take-over-xyz'],\n\t},\n\tSUBDOMAILING_CRITICAL: {\n\t\ttitle: 'Dangling CNAME in SPF Include Chain — SubdoMailing Risk',\n\t\tseverity: 'critical',\n\t\texplanation:\n\t\t\t'An SPF include domain has a dangling CNAME record pointing to a third-party service that does not resolve. An attacker could register the orphaned resource, gain control of the SPF include, and send authenticated email as the target domain.',\n\t\timpact: 'Full email authentication bypass — attacker-sent messages pass SPF checks and may pass DMARC alignment.',\n\t\tadverseConsequences:\n\t\t\t'Targeted phishing campaigns sent from a trusted domain identity, bypassing email security filters at scale.',\n\t\trecommendation: 'Remove the include mechanism from the SPF record or update it to point to a valid, owned resource. Audit all SPF includes periodically.',\n\t\treferences: [\n\t\t\t'https://guardio.co/blog/subdomailing',\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc7208',\n\t\t\t'https://github.com/EdOverflow/can-i-take-over-xyz',\n\t\t],\n\t},\n\tSUBDOMAILING_HIGH: {\n\t\ttitle: 'Dangling NS Delegation in SPF Include Chain',\n\t\tseverity: 'high',\n\t\texplanation:\n\t\t\t'An SPF include domain has nameservers that do not resolve. An attacker could register the NS target domains and take control of DNS for the include domain, enabling SPF authorization hijacking.',\n\t\timpact: 'Potential email authentication bypass if the attacker registers the unresolvable nameserver domains.',\n\t\tadverseConsequences:\n\t\t\t'Spoofed emails could pass SPF validation, eroding trust and enabling impersonation attacks.',\n\t\trecommendation: 'Remove the include mechanism or ensure its nameservers resolve correctly. Consider consolidating SPF includes to domains under your direct control.',\n\t\treferences: [\n\t\t\t'https://guardio.co/blog/subdomailing',\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc7208',\n\t\t],\n\t},\n\tSUBDOMAILING_LOW: {\n\t\ttitle: 'Void SPF Include',\n\t\tseverity: 'low',\n\t\texplanation:\n\t\t\t'An SPF include domain has no SPF record. While not immediately exploitable, this wastes a DNS lookup and could become a risk if the domain is abandoned or expires.',\n\t\trecommendation: 'Remove unused include mechanisms from the SPF record to reduce lookup waste and attack surface.',\n\t\treferences: [\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc7208',\n\t\t],\n\t},\n\tSUBDOMAILING_INFO: {\n\t\ttitle: 'No SubdoMailing Risk Detected',\n\t\tseverity: 'info',\n\t\texplanation: 'All SPF include and redirect domains resolve correctly with no takeover indicators. The SPF include chain is secure for this check.',\n\t\trecommendation: 'Continue periodic audits of SPF include domains, especially after vendor changes.',\n\t\treferences: [\n\t\t\t'https://guardio.co/blog/subdomailing',\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc7208',\n\t\t],\n\t},\n\tSPF_PASS: {\n\t\ttitle: 'SPF Validated',\n\t\tseverity: 'pass',\n\t\texplanation:\n\t\t\t'SPF (Sender Policy Framework) is properly configured. The domain specifies which mail servers are authorized to send email on its behalf.',\n\t\trecommendation: 'Maintain your current SPF configuration. Ensure you update it when adding new email sending sources.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7208'],\n\t},\n\tSPF_FAIL: {\n\t\ttitle: 'SPF Validation Failed',\n\t\tseverity: 'fail',\n\t\texplanation: 'SPF validation failed - emails from this domain are being rejected because the sending server is not authorized.',\n\t\timpact: 'Email authentication becomes unreliable, and spoofed or misrouted messages may evade expected controls.',\n\t\tadverseConsequences:\n\t\t\t'Legitimate email delivery can degrade, while impersonation attempts can increase helpdesk and abuse handling load.',\n\t\trecommendation:\n\t\t\t'Review your SPF record and ensure all legitimate email sources are included. Common issue: using -all but missing include statements.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7208', 'https://www.cloudflare.com/learning/dns/dns-records/dns-spf-record/'],\n\t},\n\tSPF_WARNING: {\n\t\ttitle: 'SPF Soft Fail',\n\t\tseverity: 'warning',\n\t\texplanation: 'SPF uses a soft fail (~all) policy. Emails that fail SPF will be accepted but may be flagged as suspicious.',\n\t\timpact: 'Failing SPF messages are often still accepted, so spoofed mail may continue reaching recipients.',\n\t\tadverseConsequences: 'Phishing risk remains elevated and security teams may need to manually triage suspicious mail.',\n\t\trecommendation: 'Upgrade to hard fail (-all) after verifying all legitimate sources are in your SPF record.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7208#section-8.1'],\n\t},\n\tSPF_MISSING: {\n\t\ttitle: 'No SPF Record Found',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t'SPF (Sender Policy Framework) is a DNS TXT record that specifies which mail servers are authorized to send email on behalf of your domain. Without SPF, any server can send email pretending to be from your domain.',\n\t\timpact: 'Any internet host can attempt to send email as your domain, making sender impersonation significantly easier.',\n\t\tadverseConsequences: 'Spoofing and phishing campaigns can harm brand trust, increase abuse complaints, and impair deliverability.',\n\t\trecommendation: \"Add a TXT record to your domain's DNS with a valid SPF policy. Start with: v=spf1 include:<your-email-provider> -all\",\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7208', 'https://www.cloudflare.com/learning/dns/dns-records/dns-spf-record/'],\n\t},\n\tDMARC_PASS: {\n\t\ttitle: 'DMARC Policy Validated',\n\t\tseverity: 'pass',\n\t\texplanation:\n\t\t\t'DMARC (Domain-based Message Authentication, Reporting & Conformance) is properly configured with a policy that provides protection against email spoofing.',\n\t\trecommendation:\n\t\t\t'Monitor your DMARC reports to ensure legitimate email is not being blocked. Consider enabling reject policy for stronger protection.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7489'],\n\t},\n\tDMARC_FAIL: {\n\t\ttitle: 'No DMARC Record Found',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t'DMARC builds on SPF and DKIM to provide email authentication policy. Without DMARC, receivers have no policy guidance for handling authentication failures.',\n\t\timpact: 'Receiving systems cannot consistently quarantine or reject forged messages that fail authentication.',\n\t\tadverseConsequences: 'Domain spoofing can reach inboxes more often, increasing phishing exposure and reputational damage.',\n\t\trecommendation: 'Add a TXT record at _dmarc.<domain> with at minimum: v=DMARC1; p=quarantine; rua=mailto:dmarc@<domain>',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7489', 'https://www.cloudflare.com/learning/dns/dns-records/dns-dmarc-record/'],\n\t},\n\tDMARC_WARNING: {\n\t\ttitle: 'DMARC Policy Not Enforcing',\n\t\tseverity: 'warning',\n\t\texplanation: \"DMARC policy is set to 'none' (monitoring only) or 'quarantine'. This provides limited protection against spoofing.\",\n\t\timpact: 'Authentication failures may not be fully blocked, allowing some malicious mail to be delivered.',\n\t\tadverseConsequences: 'Attackers can still impersonate the domain in recipient inboxes, leading to fraud and support overhead.',\n\t\trecommendation: \"After reviewing DMARC reports, upgrade the policy to 'reject' to actively protect against email spoofing.\",\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7489#section-6.3'],\n\t},\n\tDKIM_PASS: {\n\t\ttitle: 'DKIM Validated',\n\t\tseverity: 'pass',\n\t\texplanation:\n\t\t\t'DKIM (DomainKeys Identified Mail) is properly configured. Outgoing emails are digitally signed and can be verified by receivers.',\n\t\trecommendation: 'Maintain your DKIM configuration. Rotate keys periodically as per your security policy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc6376'],\n\t},\n\tDKIM_FAIL: {\n\t\ttitle: 'No DKIM Records Found',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t\"DKIM adds a digital signature to outgoing emails, allowing receivers to verify the email was sent by an authorized server and wasn't modified in transit.\",\n\t\timpact: 'Receivers lose a key authenticity signal, which weakens anti-spoofing and anti-tampering protections.',\n\t\tadverseConsequences:\n\t\t\t'Legitimate email may be distrusted while fraudulent messages are harder to distinguish, hurting deliverability and trust.',\n\t\trecommendation: 'Configure DKIM signing with your email provider. They will provide the DKIM DNS records to publish.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc6376', 'https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/'],\n\t},\n\tDNSSEC_PASS: {\n\t\ttitle: 'DNSSEC Enabled',\n\t\tseverity: 'pass',\n\t\texplanation:\n\t\t\t'DNSSEC is properly configured with valid cryptographic signatures. This protects against DNS spoofing and cache poisoning attacks.',\n\t\trecommendation: 'Maintain your DNSSEC configuration. Monitor for any validation failures in your logs.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc4033'],\n\t},\n\tDNSSEC_FAIL: {\n\t\ttitle: 'DNSSEC Not Validated',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t\"DNSSEC adds cryptographic signatures to DNS records, preventing DNS spoofing and cache poisoning attacks. Without DNSSEC, attackers can redirect your domain's traffic.\",\n\t\timpact: 'DNS responses can be forged in transit, enabling redirection to attacker-controlled infrastructure.',\n\t\tadverseConsequences: 'Users may be sent to malicious destinations, causing credential theft, service disruption, and incident response costs.',\n\t\trecommendation: 'Enable DNSSEC through your domain registrar and DNS provider. Most providers offer one-click DNSSEC activation.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc4033', 'https://www.cloudflare.com/dns/dnssec/how-dnssec-works/'],\n\t},\n\tSSL_PASS: {\n\t\ttitle: 'SSL/TLS Validated',\n\t\tseverity: 'pass',\n\t\texplanation: 'The domain properly serves content over HTTPS with a valid certificate.',\n\t\trecommendation: 'Maintain your SSL certificate. Consider implementing HSTS for additional security.',\n\t\treferences: ['https://https.cio.gov/hsts/'],\n\t},\n\tSSL_FAIL: {\n\t\ttitle: 'HTTPS Not Available',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t'The domain does not have a valid SSL/TLS certificate or the HTTPS server is not responding. This means traffic to the domain is not encrypted.',\n\t\timpact: 'Network attackers can intercept or tamper with data exchanged between users and the site.',\n\t\tadverseConsequences: 'Credentials and sensitive data may be exposed, and browser trust warnings can reduce conversion and user confidence.',\n\t\trecommendation: \"Install a valid SSL/TLS certificate. Free certificates are available from Let's Encrypt or Cloudflare.\",\n\t\treferences: ['https://letsencrypt.org/', 'https://www.cloudflare.com/ssl/'],\n\t},\n\tSSL_WARNING: {\n\t\ttitle: 'Mixed Content or Redirect Issues',\n\t\tseverity: 'warning',\n\t\texplanation: 'HTTPS is available but there may be issues with redirects or mixed content.',\n\t\timpact: 'Some resources may still load insecurely, creating opportunities for content manipulation or privacy leakage.',\n\t\tadverseConsequences: 'User sessions and page integrity can be weakened, and security posture may fail audit expectations.',\n\t\trecommendation: 'Ensure all resources load over HTTPS and implement proper redirects from HTTP to HTTPS.',\n\t\treferences: ['https://www.cloudflare.com/ssl/'],\n\t},\n\tSSL_MEDIUM: {\n\t\ttitle: 'HSTS or Redirect Issues',\n\t\tseverity: 'medium',\n\t\texplanation:\n\t\t\t'HTTPS is available but the domain is missing HSTS (Strict-Transport-Security) headers or does not redirect HTTP to HTTPS. Without HSTS, browsers may still attempt insecure connections.',\n\t\timpact: 'Clients may be downgraded to insecure HTTP connections, especially on first visit or hostile networks.',\n\t\tadverseConsequences: 'Session data can be exposed in transit and users remain vulnerable to downgrade or interception attacks.',\n\t\trecommendation:\n\t\t\t'Add a Strict-Transport-Security header with max-age of at least 1 year (31536000). Configure your web server to redirect all HTTP requests to HTTPS.',\n\t\treferences: ['https://https.cio.gov/hsts/', 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security'],\n\t},\n\tSSL_LOW: {\n\t\ttitle: 'HSTS Configuration Suboptimal',\n\t\tseverity: 'low',\n\t\texplanation:\n\t\t\t'HSTS is configured but could be improved. Common issues include a short max-age value or missing includeSubDomains directive.',\n\t\timpact: 'Partial HSTS coverage leaves windows where transport security guarantees are weaker than expected.',\n\t\tadverseConsequences: 'Subdomains or returning sessions may still face avoidable downgrade exposure and policy non-compliance findings.',\n\t\trecommendation:\n\t\t\t'Set max-age to at least 31536000 (1 year) and include the includeSubDomains directive. Consider adding your domain to the HSTS preload list.',\n\t\treferences: [\n\t\t\t'https://hstspreload.org/',\n\t\t\t'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security',\n\t\t],\n\t},\n\tMTA_STS_PASS: {\n\t\ttitle: 'MTA-STS Enabled',\n\t\tseverity: 'pass',\n\t\texplanation: 'MTA-STS (Mail Transfer Agent Strict Transport Security) is properly configured and enforces TLS for incoming email.',\n\t\trecommendation: 'Monitor your MTA-STS reports to ensure legitimate mail servers can deliver successfully.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc8461'],\n\t},\n\tMTA_STS_FAIL: {\n\t\ttitle: 'No MTA-STS Record Found',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t'MTA-STS enforces TLS encryption for incoming email, preventing downgrade attacks where an attacker forces email to be sent unencrypted.',\n\t\timpact: 'Inbound SMTP sessions are more susceptible to TLS downgrade and interception attempts.',\n\t\tadverseConsequences: 'Sensitive email content can be exposed in transit, raising confidentiality and compliance risks.',\n\t\trecommendation:\n\t\t\t'Publish an MTA-STS TXT record at _mta-sts.<domain> and host a policy file at https://mta-sts.<domain>/.well-known/mta-sts.txt',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc8461'],\n\t},\n\tMTA_STS_WARNING: {\n\t\ttitle: 'MTA-STS in Testing Mode',\n\t\tseverity: 'warning',\n\t\texplanation: 'MTA-STS is configured but in testing mode (mode=testing) rather than enforcement mode.',\n\t\timpact: 'Delivery behavior is monitored but not enforced, so some insecure transport paths may still be accepted.',\n\t\tadverseConsequences: 'Security gaps can persist longer and confidentiality controls for inbound mail remain partially effective.',\n\t\trecommendation: 'After verifying all mail servers can successfully deliver over TLS, upgrade to mode=enforce.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc8461'],\n\t},\n\tNS_PASS: {\n\t\ttitle: 'Nameservers Validated',\n\t\tseverity: 'pass',\n\t\texplanation: 'The domain has properly configured nameservers that are responding to queries.',\n\t\trecommendation: 'Maintain your current nameserver configuration. Use at least two geographically distributed nameservers for redundancy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc1035'],\n\t},\n\tNS_FAIL: {\n\t\ttitle: 'Nameserver Issues Detected',\n\t\tseverity: 'fail',\n\t\texplanation: 'One or more nameservers for this domain are not responding or are misconfigured, which can cause DNS resolution failures.',\n\t\timpact: 'Resolvers may fail to resolve the domain, degrading access to web, API, and mail services.',\n\t\tadverseConsequences: 'Users can experience outages, failed transactions, and business continuity disruptions.',\n\t\trecommendation: 'Verify all listed nameservers are operational and properly configured. Ensure NS records match those at the registrar.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc1035', 'https://www.cloudflare.com/learning/dns/dns-records/dns-ns-record/'],\n\t},\n\tNS_WARNING: {\n\t\ttitle: 'Nameserver Configuration Suboptimal',\n\t\tseverity: 'warning',\n\t\texplanation: 'Nameservers are functional but the configuration could be improved for better reliability or security.',\n\t\timpact: 'Single points of failure or weak diversity can reduce DNS resilience during provider or network incidents.',\n\t\tadverseConsequences: 'Availability and latency can degrade under stress, increasing user-facing instability.',\n\t\trecommendation: 'Consider adding additional nameservers for redundancy and ensuring they are geographically distributed.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc1035'],\n\t},\n\tCAA_PASS: {\n\t\ttitle: 'CAA Records Configured',\n\t\tseverity: 'pass',\n\t\texplanation: 'CAA (Certificate Authority Authorization) records are properly configured, restricting which CAs can issue certificates for this domain.',\n\t\trecommendation: 'Maintain your CAA records. Review periodically to ensure they reflect your current certificate issuance needs.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc8659'],\n\t},\n\tCAA_FAIL: {\n\t\ttitle: 'No CAA Records Found',\n\t\tseverity: 'fail',\n\t\texplanation: 'No CAA records are present for this domain. Without CAA, any certificate authority can issue certificates for your domain.',\n\t\timpact: 'Certificate issuance controls are broad, increasing the chance of unauthorized or misissued certificates.',\n\t\tadverseConsequences: 'Attackers may abuse misissuance for impersonation and interception, with trust and compliance implications.',\n\t\trecommendation: 'Add CAA DNS records to restrict certificate issuance to your authorized CAs (e.g., \"0 issue letsencrypt.org\").',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc8659', 'https://www.cloudflare.com/learning/dns/dns-records/dns-caa-record/'],\n\t},\n\tCAA_WARNING: {\n\t\ttitle: 'CAA Configuration Incomplete',\n\t\tseverity: 'warning',\n\t\texplanation: 'CAA records exist but may not fully restrict certificate issuance. Consider adding iodef or wildcard policies.',\n\t\timpact: 'Incomplete CAA policy can leave gaps in issuance constraints for wildcard or incident-reporting scenarios.',\n\t\tadverseConsequences: 'Certificate governance may be weaker than intended, increasing operational and audit risk.',\n\t\trecommendation: 'Review your CAA records and add an iodef tag for incident reporting. Consider restricting wildcard certificate issuance separately.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc8659'],\n\t},\n\tMX_PASS: {\n\t\ttitle: 'MX Records Validated',\n\t\tseverity: 'pass',\n\t\texplanation: 'MX (Mail Exchange) records are properly configured, directing email to the correct mail servers.',\n\t\trecommendation: 'Maintain your MX records. Ensure backup MX entries exist for redundancy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321'],\n\t},\n\tMX_FAIL: {\n\t\ttitle: 'No MX Records Found',\n\t\tseverity: 'fail',\n\t\texplanation: 'No MX records are present for this domain. Without MX records, email delivery to this domain will fail or fall back to A record delivery.',\n\t\timpact: 'Mail routing is unreliable or unavailable for intended recipients on this domain.',\n\t\tadverseConsequences: 'Inbound communications may be lost, causing business disruption and missed security notifications.',\n\t\trecommendation: 'Add MX records pointing to your mail server. If this domain does not handle email, consider adding a null MX record (0 .).',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321', 'https://datatracker.ietf.org/doc/html/rfc7505'],\n\t},\n\tMX_WARNING: {\n\t\ttitle: 'MX Configuration Suboptimal',\n\t\tseverity: 'warning',\n\t\texplanation: 'MX records exist but the configuration could be improved, such as missing backup MX or unusual priority values.',\n\t\timpact: 'Mail delivery reliability is reduced during server failures or routing anomalies.',\n\t\tadverseConsequences: 'Message delays and intermittent delivery failures can affect operations and customer support.',\n\t\trecommendation: 'Review MX priorities and add at least one backup MX record for redundancy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321'],\n\t},\n\tMX_INFO: {\n\t\ttitle: 'MX Records Present',\n\t\tseverity: 'info',\n\t\texplanation: 'Mail exchange records are properly configured for this domain.',\n\t\trecommendation: 'No action required. Ensure backup MX records exist for redundancy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321'],\n\t},\n\tMX_LOW: {\n\t\ttitle: 'MX Configuration Could Be Improved',\n\t\tseverity: 'low',\n\t\texplanation: 'MX records are present but the configuration has minor issues such as missing backup MX records.',\n\t\timpact: 'Resilience to mail infrastructure outages is lower than recommended.',\n\t\tadverseConsequences: 'Short outages can become user-visible delivery delays and increase operational toil.',\n\t\trecommendation: 'Add at least one backup MX record with a different priority for redundancy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321'],\n\t},\n\tMX_HIGH: {\n\t\ttitle: 'MX Configuration Error',\n\t\tseverity: 'medium',\n\t\texplanation:\n\t\t\t'MX records have a configuration error such as pointing to an IP address instead of a hostname (violating RFC 5321) or referencing a hostname that does not resolve to any address record.',\n\t\timpact: 'Standards-incompatible or unresolvable MX targets can cause mail rejection or routing failures across sending systems.',\n\t\tadverseConsequences: 'Business-critical messages may bounce, delaying incident response and external communication.',\n\t\trecommendation:\n\t\t\t'Update MX records to point to valid hostnames, not IP addresses. Ensure all MX targets resolve to valid A/AAAA records.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321'],\n\t},\n\tMX_MEDIUM: {\n\t\ttitle: 'No MX Records Found',\n\t\tseverity: 'medium',\n\t\texplanation:\n\t\t\t'No MX records are present for this domain. Email delivery will fall back to A record delivery or fail entirely.',\n\t\timpact: 'Email reception may fail or behave inconsistently depending on sender fallback behavior.',\n\t\tadverseConsequences: 'Organizations may miss customer, partner, or security messages, creating operational and reputational risk.',\n\t\trecommendation:\n\t\t\t'If this domain should receive email, add MX records. If not, publish a null MX record per RFC 7505 to explicitly declare that.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321', 'https://datatracker.ietf.org/doc/html/rfc7505'],\n\t},\n\tDANE_HTTPS_PASS: {\n\t\ttitle: 'DANE TLSA Configured for HTTPS',\n\t\tseverity: 'pass',\n\t\texplanation:\n\t\t\t'TLSA records at _443._tcp.{domain} pin the web server certificate to DNS, providing an additional layer of TLS trust beyond the CA system. Combined with DNSSEC, this prevents unauthorized CAs from issuing fraudulent certificates for the domain.',\n\t\trecommendation: 'Maintain your DANE HTTPS configuration. Ensure TLSA records are updated whenever TLS certificates are renewed.',\n\t\treferences: [\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc6698',\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc7671',\n\t\t],\n\t},\n\tDANE_HTTPS_FAIL: {\n\t\ttitle: 'No DANE TLSA for HTTPS',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t'No TLSA records were found at _443._tcp.{domain}. DANE certificate pinning for HTTPS provides an additional trust anchor beyond the CA system, preventing unauthorized certificate issuance attacks.',\n\t\timpact: 'Certificate issuance for this domain relies solely on the CA trust hierarchy.',\n\t\tadverseConsequences:\n\t\t\t'A compromised or rogue CA can issue a valid certificate for the domain, enabling MITM attacks that bypass standard browser trust checks.',\n\t\trecommendation:\n\t\t\t'Implement DANE-EE (usage 3) TLSA records at _443._tcp.{domain} and ensure DNSSEC is enabled. Use SHA-256 (matching type 1) or SHA-512 (matching type 2) for the certificate data hash.',\n\t\treferences: [\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc6698',\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc7671',\n\t\t],\n\t},\n\tDANE_HTTPS_WARNING: {\n\t\ttitle: 'DANE HTTPS Configuration Warning',\n\t\tseverity: 'warning',\n\t\texplanation:\n\t\t\t'DANE TLSA records exist for the HTTPS endpoint but the configuration has issues that reduce their security value, such as DANE without DNSSEC or weak matching types.',\n\t\timpact: 'DANE protection is partially effective but can be bypassed or subverted.',\n\t\tadverseConsequences:\n\t\t\t'Attackers may be able to spoof or modify TLSA records if DNSSEC is absent, negating the security benefit of DANE.',\n\t\trecommendation:\n\t\t\t'Enable DNSSEC on the domain and use DANE-EE (usage 3) with SHA-256 matching (type 1) for best security.',\n\t\treferences: [\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc6698',\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc7671',\n\t\t],\n\t},\n\tDANE_HTTPS_INFO: {\n\t\ttitle: 'DANE HTTPS Record Present',\n\t\tseverity: 'info',\n\t\texplanation: 'A TLSA record is configured at _443._tcp.{domain}, enabling DANE certificate pinning for HTTPS.',\n\t\trecommendation: 'Keep TLSA records synchronized with your TLS certificate. Automate renewal if possible.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc6698'],\n\t},\n\tSVCB_HTTPS_PASS: {\n\t\ttitle: 'HTTPS Record Configured',\n\t\tseverity: 'pass',\n\t\texplanation:\n\t\t\t'HTTPS/SVCB records (RFC 9460) are present and advertise modern transport capabilities. This enables clients to negotiate HTTP/2 or HTTP/3 without an initial redirect and optionally distributes ECH parameters for privacy.',\n\t\trecommendation: 'Maintain your HTTPS records. Consider enabling ECH for enhanced connection privacy.',\n\t\treferences: [\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc9460',\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc8446',\n\t\t],\n\t},\n\tSVCB_HTTPS_FAIL: {\n\t\ttitle: 'No HTTPS Record Found',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t'No HTTPS record (type 65, RFC 9460) was found for this domain. HTTPS records advertise modern transport capabilities (ALPN, ECH) and allow clients to connect securely and efficiently without an initial redirect round-trip.',\n\t\timpact: 'Clients cannot discover HTTP/2 or HTTP/3 support via DNS, requiring an additional round-trip.',\n\t\tadverseConsequences:\n\t\t\t'Connection setup is slower, privacy from ECH is unavailable, and the domain misses opportunities for TLS optimization.',\n\t\trecommendation:\n\t\t\t'Publish an HTTPS record with at minimum alpn=\"h2,h3\" to enable HTTP/2 and HTTP/3 advertisement. If using Cloudflare or similar CDN, this may be automatically managed.',\n\t\treferences: [\n\t\t\t'https://datatracker.ietf.org/doc/html/rfc9460',\n\t\t\t'https://blog.cloudflare.com/speeding-up-https-and-http-3-negotiation-with-dns/',\n\t\t],\n\t},\n\tSVCB_HTTPS_WARNING: {\n\t\ttitle: 'HTTPS Record Configuration Warning',\n\t\tseverity: 'warning',\n\t\texplanation:\n\t\t\t'HTTPS records are present but the configuration is suboptimal — for example, no ALPN parameters or missing HTTP/2 support.',\n\t\timpact: 'Clients cannot fully leverage the capabilities advertised in the HTTPS record.',\n\t\tadverseConsequences:\n\t\t\t'Performance benefits from SVCB are partially lost and ECH privacy may be unavailable.',\n\t\trecommendation:\n\t\t\t'Update HTTPS records to include alpn=\"h2,h3\" and consider adding ECH parameters. Ensure alias mode targets also have valid HTTPS records.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc9460'],\n\t},\n\tSVCB_HTTPS_INFO: {\n\t\ttitle: 'HTTPS Record Present',\n\t\tseverity: 'info',\n\t\texplanation: 'An HTTPS/SVCB record is configured, advertising modern connection capabilities for this domain.',\n\t\trecommendation: 'No action required. Consider adding ECH for enhanced privacy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc9460'],\n\t},\n};\n\nexport const DEFAULT_EXPLANATION: ExplanationTemplate = {\n\ttitle: 'Security Check Complete',\n\tseverity: 'info',\n\texplanation: \"This check has been completed. Review the findings above for details on your domain's security posture.\",\n\trecommendation: 'Refer to the specific check documentation for detailed remediation steps.',\n\treferences: ['https://www.cloudflare.com/learning/dns/what-is-dns/'],\n};\n\nexport const CATEGORY_TO_CHECKTYPE: Record<string, string> = {\n\tspf: 'SPF',\n\tdmarc: 'DMARC',\n\tdkim: 'DKIM',\n\tdnssec: 'DNSSEC',\n\tssl: 'SSL',\n\tmta_sts: 'MTA_STS',\n\tns: 'NS',\n\tcaa: 'CAA',\n\tmx: 'MX',\n\tsubdomain_takeover: 'SUBDOMAIN_TAKEOVER',\n\tsubdomailing: 'SUBDOMAILING',\n\tdane_https: 'DANE_HTTPS',\n\tsvcb_https: 'SVCB_HTTPS',\n};\n\nexport const CATEGORY_FALLBACK_IMPACT: Record<string, ImpactNarrative> = {\n\tSPF: {\n\t\timpact: 'SPF coverage is weak, so unauthorized senders can spoof domain identity more easily.',\n\t\tadverseConsequences: 'Phishing attempts and deliverability disputes increase security and support workload.',\n\t},\n\tDMARC: {\n\t\timpact: 'DMARC enforcement is reduced or absent at receiving systems.',\n\t\tadverseConsequences: 'Forged messages are more likely to reach users and erode brand trust.',\n\t},\n\tDKIM: {\n\t\timpact: 'DKIM assurance is weak, reducing message integrity and sender-authenticity confidence.',\n\t\tadverseConsequences: 'Legitimate messages may be distrusted while impersonation attempts become harder to detect.',\n\t},\n\tDNSSEC: {\n\t\timpact: 'DNS answers are more exposed to spoofing and tampering in transit.',\n\t\tadverseConsequences: 'Users can be redirected to attacker infrastructure, causing security and availability incidents.',\n\t},\n\tSSL: {\n\t\timpact: 'Transport security guarantees are reduced, increasing interception and tampering risk.',\n\t\tadverseConsequences: 'Sensitive user data may be exposed and browser trust can decline.',\n\t},\n\tMTA_STS: {\n\t\timpact: 'Inbound SMTP delivery is not consistently protected from downgrade attacks.',\n\t\tadverseConsequences: 'Confidential email content may be exposed in transit, increasing compliance risk.',\n\t},\n\tNS: {\n\t\timpact: 'DNS resolution reliability is reduced, which weakens service reachability.',\n\t\tadverseConsequences: 'Users may experience outages and business transactions may fail.',\n\t},\n\tCAA: {\n\t\timpact: 'Certificate issuance controls are weak, raising unauthorized issuance risk.',\n\t\tadverseConsequences: 'Domain impersonation and TLS trust incidents become more likely.',\n\t},\n\tMX: {\n\t\timpact: 'Mail routing reliability is reduced by MX configuration gaps or errors.',\n\t\tadverseConsequences: 'Important communications can be delayed, bounced, or lost.',\n\t},\n\tSUBDOMAIN_TAKEOVER: {\n\t\timpact: 'An orphaned delegated subdomain may be claimable by an attacker.',\n\t\tadverseConsequences: 'Users can be redirected to malicious content hosted under a trusted hostname.',\n\t},\n\tSUBDOMAILING: {\n\t\timpact: 'SPF include chain references a takeover-vulnerable domain, potentially allowing unauthorized email sending.',\n\t\tadverseConsequences: 'Attackers could send authenticated phishing emails from the trusted domain, bypassing email security controls.',\n\t},\n\tDANE_HTTPS: {\n\t\timpact: 'HTTPS certificate pinning via DANE is absent or misconfigured, leaving TLS trust dependent solely on the CA system.',\n\t\tadverseConsequences: 'A rogue or compromised CA can issue a fraudulent certificate, enabling undetected MITM attacks.',\n\t},\n\tSVCB_HTTPS: {\n\t\timpact: 'Modern transport capabilities (ALPN, ECH) cannot be advertised via DNS, reducing connection efficiency and privacy.',\n\t\tadverseConsequences: 'Clients require additional round-trips to negotiate protocols, and ECH-based privacy is unavailable.',\n\t},\n};\n\nexport const SEVERITY_FALLBACK_IMPACT: Record<string, ImpactNarrative> = {\n\tcritical: {\n\t\timpact: 'This is a high-likelihood weakness with immediate exploitation potential.',\n\t\tadverseConsequences: 'Compromise, disruption, or abuse can occur without prompt remediation.',\n\t},\n\thigh: {\n\t\timpact: 'This weakness materially increases attack surface and failure risk.',\n\t\tadverseConsequences: 'Business operations, user trust, and response workload can be negatively affected.',\n\t},\n\tmedium: {\n\t\timpact: 'This issue weakens defenses and compounds risk when paired with other gaps.',\n\t\tadverseConsequences: 'Over time it can degrade reliability, security assurance, and compliance posture.',\n\t},\n\twarning: {\n\t\timpact: 'This configuration is partially protective but leaves avoidable exposure.',\n\t\tadverseConsequences: 'If unresolved, incidents become harder to prevent or contain.',\n\t},\n\tfail: {\n\t\timpact: 'A required control is missing or not functioning as intended.',\n\t\tadverseConsequences: 'Security and availability incidents become more likely until it is corrected.',\n\t},\n\tlow: {\n\t\timpact: 'This is a minor weakness that still reduces resilience.',\n\t\tadverseConsequences: 'Operational friction and audit findings can increase over time.',\n\t},\n};\n\nexport const SPECIFIC_IMPACT_RULES: SpecificImpactRule[] = [\n\t{\n\t\tcheckType: 'DKIM',\n\t\ttitleIncludes: ['weak rsa key'],\n\t\timpact: 'Weak DKIM keys are easier to forge, reducing message authenticity assurance.',\n\t\tadverseConsequences: 'Attackers can impersonate trusted senders more easily, increasing fraud and phishing risk.',\n\t},\n\t{\n\t\tcheckType: 'SSL',\n\t\ttitleIncludes: ['no hsts header', 'no http to https redirect', 'mixed content'],\n\t\timpact: 'Users are exposed to insecure transport paths that permit interception or downgrade attacks.',\n\t\tadverseConsequences: 'Sensitive sessions and data can leak on hostile networks, weakening trust and compliance posture.',\n\t},\n\t{\n\t\tcheckType: 'DMARC',\n\t\ttitleIncludes: ['no aggregate reporting'],\n\t\timpact: 'Authentication failures and spoofing activity become harder to observe at scale.',\n\t\tadverseConsequences: 'Threats can persist longer without detection, increasing response time and abuse volume.',\n\t},\n\t{\n\t\tcheckType: 'MX',\n\t\ttitleIncludes: ['no mx records found', 'mx configuration error'],\n\t\timpact: 'Inbound email delivery becomes unreliable or fails for recipients on this domain.',\n\t\tadverseConsequences: 'Critical business and security communications may be delayed, bounced, or silently lost.',\n\t},\n\t{\n\t\tcheckType: 'NS',\n\t\ttitleIncludes: ['no soa record', 'nameserver', 'low nameserver diversity'],\n\t\timpact: 'DNS resilience and consistency are reduced, increasing partial or full resolution outage risk.',\n\t\tadverseConsequences: 'Availability incidents can affect websites, APIs, and transactional workflows.',\n\t},\n\t{\n\t\tcheckType: 'CAA',\n\t\ttitleIncludes: ['no caa records', 'issuewild', 'iodef'],\n\t\timpact: 'Certificate governance controls are weakened, especially for unauthorized or wildcard issuance.',\n\t\tadverseConsequences: 'TLS trust incidents and audit findings become more likely if certificate misuse occurs.',\n\t},\n\t{\n\t\tcheckType: 'SPF',\n\t\ttitleIncludes: ['permissive spf: +all', 'multiple spf records'],\n\t\tdetailIncludes: ['+all', 'multiple records'],\n\t\timpact: 'SPF policy becomes ineffective or ambiguous, allowing unauthorized senders to appear legitimate.',\n\t\tadverseConsequences: 'Spoofing, phishing, and deliverability failures can increase simultaneously.',\n\t},\n\t{\n\t\tcheckType: 'MTA_STS',\n\t\ttitleIncludes: ['no mta-sts', 'testing mode', 'tls-rpt'],\n\t\timpact: 'SMTP transport protections are not consistently enforced for inbound mail delivery.',\n\t\tadverseConsequences: 'Confidential email may traverse weaker paths, increasing confidentiality and regulatory risk.',\n\t},\n];","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Explain Finding tool.\n * Provides static explanations for DNS security findings.\n * No AI binding required - uses a built-in knowledge base.\n */\n\nimport type { OutputFormat } from '../handlers/tool-args';\nimport { sanitizeOutputText } from '../lib/output-sanitize';\n\nimport {\n\tCATEGORY_FALLBACK_IMPACT,\n\tCATEGORY_TO_CHECKTYPE,\n\tDEFAULT_EXPLANATION,\n\tEXPLANATIONS,\n\ttype ExplanationTemplate,\n\ttype ImpactNarrative,\n\tSEVERITY_FALLBACK_IMPACT,\n\tSPECIFIC_IMPACT_RULES,\n} from './explain-finding-data';\n\nexport interface ExplanationResult {\n\tcheckType: string;\n\tstatus: string;\n\tdetails?: string;\n\ttitle: string;\n\tseverity: string;\n\texplanation: string;\n\timpact?: string;\n\tadverseConsequences?: string;\n\trecommendation: string;\n\treferences: string[];\n}\n\ntype ExplanationEntry = ExplanationTemplate;\n\nfunction matchesRule(ruleValues: string[] | undefined, source: string): boolean {\n\tif (!ruleValues || ruleValues.length === 0) return true;\n\treturn ruleValues.some((value) => source.includes(value));\n}\n\nfunction resolveSpecificNarrative(params: {\n\tcheckType?: string;\n\ttitle?: string;\n\tdetail?: string;\n}): ImpactNarrative | undefined {\n\tconst checkType = params.checkType?.toUpperCase();\n\tconst title = params.title?.toLowerCase() ?? '';\n\tconst detail = params.detail?.toLowerCase() ?? '';\n\n\tfor (const rule of SPECIFIC_IMPACT_RULES) {\n\t\tif (rule.checkType && checkType && rule.checkType !== checkType) continue;\n\t\tif (!matchesRule(rule.titleIncludes, title)) continue;\n\t\tif (!matchesRule(rule.detailIncludes, detail)) continue;\n\t\treturn {\n\t\t\timpact: rule.impact,\n\t\t\tadverseConsequences: rule.adverseConsequences,\n\t\t};\n\t}\n\n\treturn undefined;\n}\n\nfunction getNarrativeFromEntry(entry: ExplanationEntry | undefined): ImpactNarrative | undefined {\n\tif (!entry) return undefined;\n\tif (!entry.impact && !entry.adverseConsequences) return undefined;\n\treturn {\n\t\timpact: entry.impact,\n\t\tadverseConsequences: entry.adverseConsequences,\n\t};\n}\n\n/**\n * Resolve impact/adverse-consequence narrative for a finding context.\n * Uses explicit explanation entries first, then category, then severity fallback.\n */\nexport function resolveImpactNarrative(params: {\n\tcheckType?: string;\n\tcategory?: string;\n\tstatus?: string;\n\tseverity?: string;\n\ttitle?: string;\n\tdetail?: string;\n}): ImpactNarrative {\n\tconst normalizedCheckType = params.checkType?.toUpperCase();\n\tconst normalizedStatus = params.status?.toUpperCase();\n\tconst normalizedSeverity = params.severity?.toLowerCase();\n\tconst derivedCheckType = params.category ? CATEGORY_TO_CHECKTYPE[params.category.toLowerCase()] : undefined;\n\n\tif (normalizedCheckType && normalizedStatus) {\n\t\tconst narrative = getNarrativeFromEntry(EXPLANATIONS[`${normalizedCheckType}_${normalizedStatus}`]);\n\t\tif (narrative) return narrative;\n\t}\n\n\tif (normalizedCheckType && normalizedSeverity) {\n\t\tconst narrative = getNarrativeFromEntry(EXPLANATIONS[`${normalizedCheckType}_${normalizedSeverity.toUpperCase()}`]);\n\t\tif (narrative) return narrative;\n\t}\n\n\tif (derivedCheckType && normalizedStatus) {\n\t\tconst narrative = getNarrativeFromEntry(EXPLANATIONS[`${derivedCheckType}_${normalizedStatus}`]);\n\t\tif (narrative) return narrative;\n\t}\n\n\tif (derivedCheckType && normalizedSeverity) {\n\t\tconst narrative = getNarrativeFromEntry(EXPLANATIONS[`${derivedCheckType}_${normalizedSeverity.toUpperCase()}`]);\n\t\tif (narrative) return narrative;\n\t}\n\n\tconst specificNarrative = resolveSpecificNarrative({\n\t\tcheckType: normalizedCheckType ?? derivedCheckType,\n\t\ttitle: params.title,\n\t\tdetail: params.detail,\n\t});\n\tif (specificNarrative) return specificNarrative;\n\n\tif (normalizedCheckType && CATEGORY_FALLBACK_IMPACT[normalizedCheckType]) {\n\t\treturn CATEGORY_FALLBACK_IMPACT[normalizedCheckType];\n\t}\n\n\tif (derivedCheckType && CATEGORY_FALLBACK_IMPACT[derivedCheckType]) {\n\t\treturn CATEGORY_FALLBACK_IMPACT[derivedCheckType];\n\t}\n\n\tif (normalizedSeverity && SEVERITY_FALLBACK_IMPACT[normalizedSeverity]) {\n\t\treturn SEVERITY_FALLBACK_IMPACT[normalizedSeverity];\n\t}\n\n\treturn {};\n}\n\nexport function explainFinding(checkType: string, status: string, details?: string): ExplanationResult {\n\tconst normalizedType = checkType.toUpperCase();\n\tconst key = `${normalizedType}_${status.toUpperCase()}`;\n\n\t// 1. Try checkType_STATUS key\n\tlet entry: ExplanationTemplate | undefined = EXPLANATIONS[key];\n\n\t// 2. Fall back to default\n\tif (!entry) {\n\t\tentry = DEFAULT_EXPLANATION;\n\t}\n\n\tconst narrative = resolveImpactNarrative({ checkType: normalizedType, status, detail: details });\n\n\treturn {\n\t\tcheckType: normalizedType,\n\t\tstatus,\n\t\tdetails,\n\t\t...entry,\n\t\timpact: entry.impact ?? narrative.impact,\n\t\tadverseConsequences: entry.adverseConsequences ?? narrative.adverseConsequences,\n\t};\n}\n\nexport function formatExplanation(result: ExplanationResult, format: OutputFormat = 'full'): string {\n\tif (format === 'compact') {\n\t\tconst lines = [\n\t\t\t`${result.title} (${result.checkType} | ${result.status})`,\n\t\t\tsanitizeOutputText(result.explanation, 200),\n\t\t\t`Recommendation: ${sanitizeOutputText(result.recommendation, 200)}`,\n\t\t];\n\t\treturn lines.join('\\n');\n\t}\n\n\tconst lines = [`## ${result.title}`, `**Check Type:** ${result.checkType} | **Status:** ${result.status}`, ''];\n\n\tlines.push(`### What this means`, result.explanation, '');\n\n\tif (result.impact) {\n\t\tlines.push(`### Potential Impact`, result.impact, '');\n\t}\n\n\tif (result.adverseConsequences) {\n\t\tlines.push(`### Adverse Consequences`, result.adverseConsequences, '');\n\t}\n\n\tlines.push(`### Recommendation`, result.recommendation, '', `### References`, ...result.references.map((reference) => `- ${reference}`));\n\treturn lines.join('\\n');\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Category interaction scoring — post-scoring adjustments for correlated weaknesses.\n *\n * Applied after computeScanScore() as a separate penalty layer.\n * Does NOT modify categoryScores — only adjusts the overall score.\n * Existing compare_baseline CI/CD workflows continue to work identically.\n */\n\nimport type { CheckCategory, ScanScore } from './scoring-model';\nimport { scoreToGrade } from './scoring-engine';\nimport type { ScoringConfig } from './scoring-config';\n\n/** A condition that must be met for an interaction rule to fire. */\ninterface InteractionCondition {\n\tcategory: CheckCategory;\n\t/** Maximum category score for the condition to be true (score <= maxScore). */\n\tmaxScore?: number;\n\t/** Minimum category score for the condition to be true (score >= minScore). */\n\tminScore?: number;\n}\n\n/** An interaction rule that applies a penalty when all conditions are met. */\nexport interface InteractionRule {\n\t/** Unique identifier for the interaction. */\n\tid: string;\n\t/** All conditions must be satisfied for the penalty to apply. */\n\tconditions: InteractionCondition[];\n\t/** Additional points deducted from the overall score. */\n\toverallPenalty: number;\n\t/** Human-readable explanation of the interaction effect. */\n\tnarrative: string;\n}\n\n/** Result of applying interaction rules to a scan score. */\nexport interface InteractionEffect {\n\truleId: string;\n\tpenalty: number;\n\tnarrative: string;\n}\n\n/** Interaction rules — correlated weaknesses that amplify risk. */\nexport const INTERACTION_RULES: InteractionRule[] = [\n\t{\n\t\tid: 'weak_dkim_permissive_dmarc',\n\t\tconditions: [\n\t\t\t{ category: 'dkim', maxScore: 40 },\n\t\t\t{ category: 'dmarc', maxScore: 60 },\n\t\t],\n\t\toverallPenalty: 5,\n\t\tnarrative: 'Weak DKIM combined with permissive DMARC creates multiplicative spoofing risk — attackers can forge messages that pass relaxed alignment checks.',\n\t},\n\t{\n\t\tid: 'no_spf_no_dmarc',\n\t\tconditions: [\n\t\t\t{ category: 'spf', maxScore: 0 },\n\t\t\t{ category: 'dmarc', maxScore: 0 },\n\t\t],\n\t\toverallPenalty: 10,\n\t\tnarrative: 'Complete absence of both SPF and DMARC means any server can send as this domain with no detection mechanism.',\n\t},\n\t{\n\t\tid: 'weak_dnssec_enforcing_dmarc',\n\t\tconditions: [\n\t\t\t{ category: 'dmarc', minScore: 80 },\n\t\t\t{ category: 'dnssec', maxScore: 40 },\n\t\t],\n\t\toverallPenalty: 3,\n\t\tnarrative: 'Strong email authentication is in place but DNSSEC is weak or absent — DNS tampering could undermine authentication records.',\n\t},\n\t{\n\t\tid: 'no_spf_no_dkim',\n\t\tconditions: [\n\t\t\t{ category: 'spf', maxScore: 0 },\n\t\t\t{ category: 'dkim', maxScore: 0 },\n\t\t],\n\t\toverallPenalty: 5,\n\t\tnarrative: 'Neither SPF nor DKIM is configured — DMARC alignment cannot be satisfied through either mechanism, making enforcement ineffective even if DMARC is published.',\n\t},\n\t{\n\t\tid: 'weak_ssl_no_http_security',\n\t\tconditions: [\n\t\t\t{ category: 'ssl', maxScore: 40 },\n\t\t\t{ category: 'http_security', maxScore: 30 },\n\t\t],\n\t\toverallPenalty: 3,\n\t\tnarrative: 'Weak SSL/TLS combined with missing HTTP security headers exposes the domain to man-in-the-middle attacks and content injection.',\n\t},\n];\n\n/** Check if a single condition is satisfied by the category scores. */\nfunction conditionMet(condition: InteractionCondition, categoryScores: Record<string, number>): boolean {\n\tconst score = categoryScores[condition.category];\n\tif (score === undefined) return false;\n\n\tif (condition.maxScore !== undefined && score > condition.maxScore) return false;\n\tif (condition.minScore !== undefined && score < condition.minScore) return false;\n\n\treturn true;\n}\n\n/**\n * Apply interaction penalties to a scan score.\n *\n * This is a post-scoring adjustment — categoryScores remain unchanged,\n * only the overall score and grade are updated.\n *\n * @param score - The computed scan score from computeScanScore()\n * @param config - Optional scoring config for grade computation\n * @returns Updated score with interaction penalties applied, plus the list of triggered effects\n */\nexport function applyInteractionPenalties(\n\tscore: ScanScore,\n\tconfig?: ScoringConfig,\n): { adjustedScore: ScanScore; effects: InteractionEffect[] } {\n\tconst effects: InteractionEffect[] = [];\n\tlet totalPenalty = 0;\n\n\tfor (const rule of INTERACTION_RULES) {\n\t\tconst allMet = rule.conditions.every((c) => conditionMet(c, score.categoryScores));\n\t\tif (allMet) {\n\t\t\teffects.push({\n\t\t\t\truleId: rule.id,\n\t\t\t\tpenalty: rule.overallPenalty,\n\t\t\t\tnarrative: rule.narrative,\n\t\t\t});\n\t\t\ttotalPenalty += rule.overallPenalty;\n\t\t}\n\t}\n\n\tif (totalPenalty === 0) {\n\t\treturn { adjustedScore: score, effects };\n\t}\n\n\tconst adjustedOverall = Math.max(0, score.overall - totalPenalty);\n\tconst adjustedGrade = scoreToGrade(adjustedOverall, config);\n\n\t// Update summary if grade changed\n\tlet summary = score.summary;\n\tif (adjustedGrade !== score.grade) {\n\t\tsummary = summary.replace(`Grade: ${score.grade}`, `Grade: ${adjustedGrade}`);\n\t}\n\n\treturn {\n\t\tadjustedScore: {\n\t\t\t...score,\n\t\t\toverall: adjustedOverall,\n\t\t\tgrade: adjustedGrade,\n\t\t\tsummary,\n\t\t},\n\t\teffects,\n\t};\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Structured logging utility for Cloudflare Worker (MCP server)\n * Logs JSON objects with request, tool, result, and error metadata\n * Usage: logEvent({ ... })\n */\n\nexport type LogEvent = {\n\ttimestamp: string;\n\trequestId?: string;\n\tip?: string;\n\ttool?: string;\n\tdomain?: string;\n\tseverity?: 'info' | 'warn' | 'error';\n\tcategory?: string;\n\tresult?: string;\n\tdetails?: unknown;\n\terror?: string;\n\tdurationMs?: number;\n\tuserAgent?: string;\n};\n\nconst REDACTED = '[redacted]';\nconst MAX_LOG_STRING_LENGTH = 256;\nconst SENSITIVE_KEY_PATTERN = /(^ip$|authorization|mcp-session-id|session|token|api[-_]?key|secret|password|cookie|rawbody)/i;\n\nfunction isSensitiveKey(key: string): boolean {\n\treturn !/^has[A-Z]/.test(key) && SENSITIVE_KEY_PATTERN.test(key);\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction sanitizeString(value: string): string {\n\t// Strip control characters (except tab) to prevent log injection via newlines/ANSI sequences\n\tconst stripped = value.replace(/[\\x00-\\x08\\x0a-\\x1f\\x7f]/g, ' ');\n\treturn stripped.length > MAX_LOG_STRING_LENGTH ? `${stripped.slice(0, MAX_LOG_STRING_LENGTH)}...` : stripped;\n}\n\nexport function sanitizeLogValue(value: unknown, key?: string): unknown {\n\tif (key && isSensitiveKey(key)) {\n\t\treturn REDACTED;\n\t}\n\n\tif (typeof value === 'string') {\n\t\treturn sanitizeString(value);\n\t}\n\n\tif (Array.isArray(value)) {\n\t\treturn value.map((item) => sanitizeLogValue(item));\n\t}\n\n\tif (isPlainObject(value)) {\n\t\tconst sanitized: Record<string, unknown> = {};\n\t\tfor (const [entryKey, entryValue] of Object.entries(value)) {\n\t\t\tsanitized[entryKey] = sanitizeLogValue(entryValue, entryKey);\n\t\t}\n\t\treturn sanitized;\n\t}\n\n\treturn value;\n}\n\nexport function sanitizeHeadersForLog(headers: Headers | Record<string, string>): Record<string, string> {\n\tconst sanitized: Record<string, string> = {};\n\tif (headers instanceof Headers) {\n\t\theaders.forEach((value, rawKey) => {\n\t\t\tconst key = rawKey.toLowerCase();\n\t\t\tsanitized[key] = isSensitiveKey(key) ? REDACTED : sanitizeString(value);\n\t\t});\n\t\treturn sanitized;\n\t}\n\n\tfor (const [rawKey, value] of Object.entries(headers)) {\n\t\tconst key = rawKey.toLowerCase();\n\t\tsanitized[key] = isSensitiveKey(key) ? REDACTED : sanitizeString(value);\n\t}\n\treturn sanitized;\n}\n\n/**\n * Emit a structured log event (console.log as JSON)\n */\nexport function logEvent(event: LogEvent): void {\n\tconst log = {\n\t\t...event,\n\t\ttimestamp: event.timestamp || new Date().toISOString(),\n\t\tdetails: sanitizeLogValue(event.details),\n\t\terror: typeof event.error === 'string' ? sanitizeString(event.error) : event.error,\n\t};\n\tconsole.log(JSON.stringify(log));\n}\n\n/**\n * Helper for error logging\n */\nexport function logError(error: Error | string, context?: Partial<LogEvent>): void {\n\tlogEvent({\n\t\ttimestamp: new Date().toISOString(),\n\t\tseverity: 'error',\n\t\terror: typeof error === 'string' ? error : error.message,\n\t\t...context,\n\t});\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { INFLIGHT_CLEANUP_MS } from './config';\nimport { logError } from './log';\n\n/**\n * TTL cache for DNS scan results.\n *\n * Uses Cloudflare KV for persistent caching when available,\n * with in-memory fallback when KV is not configured.\n *\n * Cloudflare Workers compatible - no Node.js APIs.\n */\n\ninterface CacheEntry<T> {\n\tvalue: T;\n\texpiresAt: number;\n}\n\ninterface CacheOptions {\n\t/** Time-to-live in milliseconds. Default: 5 minutes (300_000ms) */\n\tttlMs?: number;\n\t/** Maximum number of entries. Default: 1000 */\n\tmaxEntries?: number;\n}\n\nconst DEFAULT_TTL_MS = 5 * 60 * 1000; // 5 minutes\nconst DEFAULT_TTL_SECONDS = 300; // 5 minutes in seconds (for KV expirationTtl)\nconst DEFAULT_MAX_ENTRIES = 1000;\n\nexport class TTLCache<T = unknown> {\n\tprivate readonly store = new Map<string, CacheEntry<T>>();\n\tprivate readonly ttlMs: number;\n\tprivate readonly maxEntries: number;\n\n\tconstructor(options: CacheOptions = {}) {\n\t\tthis.ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;\n\t\tthis.maxEntries = options.maxEntries ?? DEFAULT_MAX_ENTRIES;\n\t}\n\n\t/**\n\t * Get a cached value by key. Returns undefined if not found or expired.\n\t */\n\tget(key: string): T | undefined {\n\t\tconst entry = this.store.get(key);\n\t\tif (!entry) {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (Date.now() > entry.expiresAt) {\n\t\t\tthis.store.delete(key);\n\t\t\treturn undefined;\n\t\t}\n\t\treturn entry.value;\n\t}\n\n\t/**\n\t * Set a value in the cache with optional custom TTL.\n\t */\n\tset(key: string, value: T, ttlMs?: number): void {\n\t\t// Evict expired entries if at capacity\n\t\tif (this.store.size >= this.maxEntries && !this.store.has(key)) {\n\t\t\tthis.evictExpired();\n\t\t}\n\t\t// If still at capacity after eviction, remove oldest entry\n\t\tif (this.store.size >= this.maxEntries && !this.store.has(key)) {\n\t\t\tconst firstKey = this.store.keys().next().value;\n\t\t\tif (firstKey !== undefined) {\n\t\t\t\tthis.store.delete(firstKey);\n\t\t\t}\n\t\t}\n\t\tthis.store.set(key, {\n\t\t\tvalue,\n\t\t\texpiresAt: Date.now() + (ttlMs ?? this.ttlMs),\n\t\t});\n\t}\n\n\t/**\n\t * Check if a key exists and is not expired.\n\t */\n\thas(key: string): boolean {\n\t\treturn this.get(key) !== undefined;\n\t}\n\n\t/**\n\t * Delete a specific key from the cache.\n\t */\n\tdelete(key: string): boolean {\n\t\treturn this.store.delete(key);\n\t}\n\n\t/**\n\t * Remove all entries from the cache.\n\t */\n\tclear(): void {\n\t\tthis.store.clear();\n\t}\n\n\t/**\n\t * Get the number of entries (including potentially expired ones).\n\t */\n\tget size(): number {\n\t\treturn this.store.size;\n\t}\n\n\t/**\n\t * Remove all expired entries from the cache.\n\t */\n\tevictExpired(): number {\n\t\tconst now = Date.now();\n\t\tlet evicted = 0;\n\t\tfor (const [key, entry] of this.store) {\n\t\t\tif (now > entry.expiresAt) {\n\t\t\t\tthis.store.delete(key);\n\t\t\t\tevicted++;\n\t\t\t}\n\t\t}\n\t\treturn evicted;\n\t}\n}\n\n/** In-flight promise map for cache stampede (thundering herd) protection */\nconst INFLIGHT = new Map<string, Promise<unknown>>();\n\n/** In-memory cache instance used as fallback when KV is unavailable */\nexport const IN_MEMORY_CACHE = new TTLCache<unknown>({\n\tttlMs: DEFAULT_TTL_MS,\n\tmaxEntries: DEFAULT_MAX_ENTRIES,\n});\n\n// ---------------------------------------------------------------------------\n// KV-backed cache functions\n// ---------------------------------------------------------------------------\n\n/**\n * Get a cached value by key.\n * Uses KV when available, falls back to in-memory.\n *\n * @param key - Cache key\n * @param kv - Optional KV namespace for persistent caching\n */\nexport async function cacheGet<T>(key: string, kv?: KVNamespace): Promise<T | undefined> {\n if (kv) {\n\t try {\n\t\t const val = await kv.get(key, 'json');\n\t\t return (val ?? undefined) as T | undefined; // KV.get('json') returns unknown; generic T is caller-enforced\n\t } catch {\n\t\t // KV error — log warning and fall through to in-memory\n\t\t logError('[cache] KV get failed, falling back to in-memory');\n\t }\n }\n return IN_MEMORY_CACHE.get(key) as T | undefined;\n}\n\n/**\n * Set a cached value with configurable TTL.\n * Uses KV when available, falls back to in-memory.\n *\n * @param key - Cache key\n * @param value - Value to cache (must be JSON-serializable for KV)\n * @param kv - Optional KV namespace for persistent caching\n * @param ttlSeconds - Cache TTL in seconds (default: 300 = 5 minutes)\n */\n/**\n * Set a cached value, deferring the KV write via ctx.waitUntil() to avoid blocking the response.\n * Falls back to synchronous cacheSet when no ExecutionContext is provided.\n */\nexport function cacheSetDeferred(key: string, value: unknown, ctx: ExecutionContext, kv?: KVNamespace, ttlSeconds?: number): void {\n\tctx.waitUntil(cacheSet(key, value, kv, ttlSeconds));\n}\n\nexport async function cacheSet(key: string, value: unknown, kv?: KVNamespace, ttlSeconds?: number): Promise<void> {\n const ttl = ttlSeconds ?? DEFAULT_TTL_SECONDS;\n if (kv) {\n\t try {\n\t\t await kv.put(key, JSON.stringify(value), { expirationTtl: ttl });\n\t\t return;\n\t } catch {\n\t\t // KV error — log warning and fall through to in-memory\n\t\t logError('[cache] KV put failed, falling back to in-memory');\n\t }\n }\n IN_MEMORY_CACHE.set(key, value, ttl * 1000);\n}\n\n/**\n * Run a function with cache-aside logic: returns cached value if available,\n * otherwise executes the function and caches the result.\n * Includes in-flight deduplication to prevent cache stampedes.\n *\n * @param key - Cache key\n * @param run - Async function to execute on cache miss\n * @param kv - Optional KV namespace for persistent caching\n * @param ttlSeconds - Cache TTL in seconds (default: 300 = 5 minutes)\n * @param skipCache - When true, bypass cache lookup and always execute the function (result is still cached)\n * @returns The cached or freshly computed result\n */\nexport async function runWithCache<T>(key: string, run: () => Promise<T>, kv?: KVNamespace, ttlSeconds?: number, skipCache?: boolean): Promise<T> {\n\tif (!skipCache) {\n\t\tconst cached = await cacheGet<T>(key, kv);\n\t\tif (cached !== undefined) return cached;\n\t}\n\n\tconst existing = INFLIGHT.get(key);\n\tif (existing) return existing as Promise<T>; // INFLIGHT map stores Promise<unknown>; keyed by same cache key ensures type match\n\n\tconst cleanup = setTimeout(() => INFLIGHT.delete(key), INFLIGHT_CLEANUP_MS);\n\tconst promise = run()\n\t\t.then(async (result) => {\n\t\t\tawait cacheSet(key, result, kv, ttlSeconds);\n\t\t\treturn result;\n\t\t})\n\t\t.finally(() => {\n\t\t\tclearTimeout(cleanup);\n\t\t\tINFLIGHT.delete(key);\n\t\t});\n\n\tINFLIGHT.set(key, promise);\n\treturn promise;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * HTTP security headers check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n * Post-augments with CDN provider detection from response headers.\n */\n\nimport { checkHTTPSecurity } from '@blackveil/dns-checks';\nimport type { CheckResult } from '../lib/scoring';\nimport { createFinding } from '../lib/scoring';\nimport { HTTPS_TIMEOUT_MS } from '../lib/config';\n\n/** Detect CDN provider from HTTP response headers. Returns provider name or null. */\nfunction detectCdnProvider(headers: Headers): string | null {\n\tif (headers.get('cf-ray') || headers.get('server')?.toLowerCase().includes('cloudflare')) {\n\t\treturn 'Cloudflare';\n\t}\n\tif (headers.get('x-vercel-id') || headers.get('x-vercel-cache')) {\n\t\treturn 'Vercel';\n\t}\n\tif (headers.get('x-amz-cf-id') || headers.get('via')?.includes('CloudFront')) {\n\t\treturn 'CloudFront';\n\t}\n\tconst servedBy = headers.get('x-served-by') ?? '';\n\tif (servedBy.includes('cache') || headers.get('via')?.toLowerCase().includes('varnish')) {\n\t\treturn 'Fastly';\n\t}\n\tif (headers.get('x-akamai-transformed') || headers.get('x-check-cacheable')) {\n\t\treturn 'Akamai';\n\t}\n\treturn null;\n}\n\n/**\n * Check HTTP security headers for a domain.\n * Fetches the HTTPS endpoint and analyzes browser security headers.\n * Detects CDN provider and adds an info finding when CDN headers are present.\n */\nexport async function checkHttpSecurity(domain: string): Promise<CheckResult> {\n\tlet capturedHeaders: Headers | null = null;\n\tconst capturingFetch: typeof fetch = async (input, init) => {\n\t\tconst response = await fetch(input, init);\n\t\tcapturedHeaders = response.headers;\n\t\treturn response;\n\t};\n\n\tconst result = await checkHTTPSecurity(domain, capturingFetch, { timeout: HTTPS_TIMEOUT_MS }) as CheckResult;\n\n\tif (!capturedHeaders) return result;\n\n\tconst cdnProvider = detectCdnProvider(capturedHeaders);\n\tif (!cdnProvider) return result;\n\n\t// Only annotate CDN when headers were actually analyzed.\n\t// If the check was blocked (WAF, connection refused, etc.) or timed out,\n\t// capturedHeaders may reflect the error response, not the security response.\n\tconst isUnanalyzable =\n\t\tresult.checkStatus === 'error' ||\n\t\tresult.checkStatus === 'timeout' ||\n\t\tresult.findings.some((f) => f.metadata?.missingControl === true);\n\tif (isUnanalyzable) return result;\n\n\tconst cdnFinding = createFinding(\n\t\t'http_security',\n\t\t`HTTP headers via ${cdnProvider} CDN`,\n\t\t'info',\n\t\t`HTTP security headers may be provided by ${cdnProvider} CDN rather than the origin server. CDN-applied headers do not reflect the origin server's security configuration.`,\n\t\t{ cdnProvider },\n\t);\n\n\treturn { ...result, findings: [...result.findings, cdnFinding] };\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DANE (DNS-Based Authentication of Named Entities) check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkDANE } from '@blackveil/dns-checks';\nimport { queryDns, queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check DANE TLSA records for a domain's MX servers and HTTPS endpoint.\n */\nexport async function checkDane(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkDANE(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{\n\t\t\ttimeout: dnsOptions?.timeoutMs ?? 5000,\n\t\t\trawQueryDNS: async (d, type, dnssecFlag) => {\n\t\t\t\tconst resp = await queryDns(d, type as Parameters<typeof queryDns>[1], dnssecFlag ?? false, dnsOptions);\n\t\t\t\treturn { AD: resp.AD, Answer: resp.Answer };\n\t\t\t},\n\t\t},\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DANE-HTTPS check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkDANEHTTPS } from '@blackveil/dns-checks';\nimport { queryDns, queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check DANE TLSA records for a domain's HTTPS endpoint (_443._tcp.{domain}).\n */\nexport async function checkDaneHttps(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkDANEHTTPS(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{\n\t\t\ttimeout: dnsOptions?.timeoutMs ?? 5000,\n\t\t\trawQueryDNS: async (d, type, dnssecFlag) => {\n\t\t\t\tconst resp = await queryDns(d, type as Parameters<typeof queryDns>[1], dnssecFlag ?? false, dnsOptions);\n\t\t\t\treturn { AD: resp.AD, Answer: resp.Answer };\n\t\t\t},\n\t\t},\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * SVCB/HTTPS DNS record check tool (RFC 9460).\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkSVCBHTTPS } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check HTTPS/SVCB records (RFC 9460) for a domain.\n */\nexport async function checkSvcbHttps(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkSVCBHTTPS(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? 5000 },\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * SubdoMailing check tool.\n * Thin wrapper around @blackveil/dns-checks — delegates all logic to the shared package.\n */\n\nimport { checkSubdomailing as checkSubdomailingCore } from '@blackveil/dns-checks';\nimport { queryDnsRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult } from '../lib/scoring';\n\nfunction makeQueryDNS(dnsOptions?: QueryDnsOptions) {\n\treturn async (domain: string, type: string): Promise<string[]> => {\n\t\tif (type === 'TXT') {\n\t\t\treturn queryTxtRecords(domain, dnsOptions);\n\t\t}\n\t\treturn queryDnsRecords(domain, type as Parameters<typeof queryDnsRecords>[1], dnsOptions);\n\t};\n}\n\n/**\n * Check for SubdoMailing risk by analyzing SPF include chain for takeover-vulnerable domains.\n */\nexport async function checkSubdomailing(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\treturn checkSubdomailingCore(\n\t\tdomain,\n\t\tmakeQueryDNS(dnsOptions),\n\t\t{ timeout: dnsOptions?.timeoutMs ?? 5000 },\n\t) as Promise<CheckResult>;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { type CheckCategory, type CheckResult, type Finding, buildCheckResult, createFinding } from '../../lib/scoring';\nimport { queryTxtRecords } from '../../lib/dns';\nimport { detectProviderMatches, detectProviderMatchesBySelectors, loadProviderSignatures } from '../../lib/provider-signatures';\nimport { parseDmarcTags } from '../check-dmarc';\n\nexport interface ScanRuntimeOptions {\n\tproviderSignaturesUrl?: string;\n\tproviderSignaturesAllowedHosts?: string[];\n\tproviderSignaturesSha256?: string;\n\tprofile?: 'mail_enabled' | 'enterprise_mail' | 'non_mail' | 'web_only' | 'minimal' | 'auto';\n\tprofileAccumulator?: DurableObjectNamespace;\n\twaitUntil?: (promise: Promise<unknown>) => void;\n\tscoringConfig?: import('../../lib/scoring-config').ScoringConfig;\n\t/** Override cache TTL in seconds (default: 300). Clamped to [60, 3600]. */\n\tcacheTtlSeconds?: number;\n\t/** Custom secondary DoH resolver config (bv-dns). Threaded to scanDns but only active when skipSecondaryConfirmation is false. */\n\tsecondaryDoh?: import('../../lib/dns-types').SecondaryDohConfig;\n\t/** Bypass cache and run a fresh scan. Useful for troubleshooting after DNS changes. */\n\tforceRefresh?: boolean;\n}\n\nexport async function applyScanPostProcessing(\n\tdomain: string,\n\tcheckResults: CheckResult[],\n\truntimeOptions?: ScanRuntimeOptions,\n): Promise<CheckResult[]> {\n\tlet results = checkResults;\n\tconst mxResult = results.find((result) => result.category === 'mx');\n\tconst hasNoMx = mxResult ? mxResult.findings.some((finding: Finding) => finding.title === 'No MX records found') : false;\n\n\tif (hasNoMx) {\n\t\tconst apexCovers = await checkApexDmarcPolicy(domain);\n\t\tresults = adjustForNonMailDomain(results, apexCovers);\n\t\tresults = adjustBimiForNonMailDomain(results);\n\t} else if (mxResult) {\n\t\tresults = clarifyMtaStsForMailDomain(domain, results);\n\t}\n\n\t// Detect no-send SPF policy (v=spf1 -all with no authorizing mechanisms)\n\tconst spfResult = results.find((result) => result.category === 'spf');\n\tconst hasNoSendPolicy = spfResult?.findings.some((f: Finding) => f.metadata?.noSendPolicy === true) ?? false;\n\tif (hasNoSendPolicy && !hasNoMx) {\n\t\tresults = adjustForNoSendDomain(results);\n\t}\n\n\treturn addOutboundProviderInference(results, runtimeOptions);\n}\n\nfunction extractSpfSignalDomains(result: CheckResult | undefined): string[] {\n\tif (!result) return [];\n\n\tconst domains = new Set<string>();\n\tfor (const finding of result.findings) {\n\t\tconst metadata = finding.metadata;\n\t\tif (!metadata || typeof metadata !== 'object') continue;\n\n\t\tconst includeDomains = metadata.includeDomains;\n\t\tif (Array.isArray(includeDomains)) {\n\t\t\tfor (const domain of includeDomains) {\n\t\t\t\tif (typeof domain === 'string' && domain.trim().length > 0) {\n\t\t\t\t\tdomains.add(domain.trim().toLowerCase());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst redirectDomain = metadata.redirectDomain;\n\t\tif (typeof redirectDomain === 'string' && redirectDomain.trim().length > 0) {\n\t\t\tdomains.add(redirectDomain.trim().toLowerCase());\n\t\t}\n\t}\n\n\treturn Array.from(domains);\n}\n\nfunction extractDkimSignalSelectors(result: CheckResult | undefined): string[] {\n\tif (!result) return [];\n\n\tconst selectors = new Set<string>();\n\tfor (const finding of result.findings) {\n\t\tconst metadata = finding.metadata;\n\t\tif (!metadata || typeof metadata !== 'object') continue;\n\n\t\tconst selectorsFound = metadata.selectorsFound;\n\t\tif (!Array.isArray(selectorsFound)) continue;\n\n\t\tfor (const selector of selectorsFound) {\n\t\t\tif (typeof selector === 'string' && selector.trim().length > 0) {\n\t\t\t\tselectors.add(selector.trim().toLowerCase());\n\t\t\t}\n\t\t}\n\t}\n\n\treturn Array.from(selectors);\n}\n\nfunction upsertCheckResult(results: CheckResult[], updated: CheckResult): CheckResult[] {\n\treturn results.map((result) => (result.category === updated.category ? updated : result));\n}\n\nasync function addOutboundProviderInference(results: CheckResult[], runtimeOptions?: ScanRuntimeOptions): Promise<CheckResult[]> {\n\tconst spfResult = results.find((result) => result.category === 'spf');\n\tconst dkimResult = results.find((result) => result.category === 'dkim');\n\n\tconst signalDomains = extractSpfSignalDomains(spfResult);\n\tconst dkimSelectors = extractDkimSignalSelectors(dkimResult);\n\tif (signalDomains.length === 0 && dkimSelectors.length === 0) return results;\n\n\tconst signatures = await loadProviderSignatures({\n\t\tsourceUrl: runtimeOptions?.providerSignaturesUrl,\n\t\tallowedHosts: runtimeOptions?.providerSignaturesAllowedHosts,\n\t\texpectedSha256: runtimeOptions?.providerSignaturesSha256,\n\t});\n\tconst signatureSet = signatures.outbound.length > 0 ? signatures.outbound : signatures.inbound;\n\tconst hostMatches = detectProviderMatches(signalDomains, signatureSet);\n\tconst selectorMatches = detectProviderMatchesBySelectors(dkimSelectors, signatureSet);\n\n\tconst mergedMatches = new Map<string, Set<string>>();\n\tfor (const match of [...hostMatches, ...selectorMatches]) {\n\t\tif (!mergedMatches.has(match.provider)) {\n\t\t\tmergedMatches.set(match.provider, new Set<string>());\n\t\t}\n\t\tfor (const evidence of match.matches) {\n\t\t\tmergedMatches.get(match.provider)?.add(evidence);\n\t\t}\n\t}\n\n\tconst outboundMatches = Array.from(mergedMatches.entries()).map(([provider, matches]) => ({\n\t\tprovider,\n\t\tmatches: Array.from(matches),\n\t}));\n\tif (outboundMatches.length === 0) return results;\n\n\tconst providerNames = outboundMatches.map((match) => match.provider).join(', ');\n\tconst evidence = outboundMatches.map((match) => `${match.provider}: ${match.matches.join(', ')}`).join('; ');\n\tconst signalBoost = signalDomains.length > 0 && dkimSelectors.length > 0 ? 0.05 : 0;\n\tconst baseConfidence = signatures.source === 'runtime' ? 0.85 : signatures.source === 'stale' ? 0.7 : 0.65;\n\tconst providerConfidence = Math.min(0.95, baseConfidence + signalBoost);\n\n\tconst spfBaseline = spfResult ?? buildCheckResult('spf', []);\n\tconst updatedSpf = buildCheckResult('spf', [\n\t\t...spfBaseline.findings,\n\t\tcreateFinding('spf', 'Outbound email provider inferred', 'info', `Outbound provider(s): ${providerNames}. Evidence: ${evidence}.`, {\n\t\t\tdetectionType: 'outbound',\n\t\t\tproviders: outboundMatches.map((match) => ({ name: match.provider, matches: match.matches })),\n\t\t\tsignalsUsed: {\n\t\t\t\tspfDomains: signalDomains,\n\t\t\t\tdkimSelectors,\n\t\t\t},\n\t\t\tproviderConfidence,\n\t\t\tsignatureSource: signatures.source,\n\t\t\tsignatureVersion: signatures.version,\n\t\t\tsignatureFetchedAt: signatures.fetchedAt,\n\t\t}),\n\t]);\n\n\treturn upsertCheckResult(results, updatedSpf);\n}\n\nfunction getParentDomain(domain: string): string | null {\n\tconst parts = domain.split('.');\n\tif (parts.length <= 2) return null;\n\treturn parts.slice(1).join('.');\n}\n\nasync function checkApexDmarcPolicy(domain: string): Promise<boolean> {\n\tconst parent = getParentDomain(domain);\n\tif (!parent) return false;\n\n\ttry {\n\t\tconst records = await queryTxtRecords(`_dmarc.${parent}`);\n\t\tconst dmarcRecord = records.find((record) => record.toLowerCase().startsWith('v=dmarc1'));\n\t\tif (!dmarcRecord) return false;\n\n\t\tconst tags = parseDmarcTags(dmarcRecord);\n\t\tconst effectivePolicy = tags.get('sp') || tags.get('p') || '';\n\t\treturn effectivePolicy === 'quarantine' || effectivePolicy === 'reject';\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction isMissingRecordFinding(finding: { title: string; detail: string }): boolean {\n\t// Match against title only (controlled by check modules, not DNS data) to avoid ReDoS on attacker-controlled detail strings\n\tconst title = finding.title.toLowerCase();\n\treturn (\n\t\ttitle.includes('missing') ||\n\t\ttitle.includes('not found') ||\n\t\ttitle.includes('no mta-sts') ||\n\t\ttitle.includes('no dkim') ||\n\t\t/^no\\s+\\S+\\s+record/.test(title)\n\t);\n}\n\nfunction clarifyMtaStsForMailDomain(domain: string, results: CheckResult[]): CheckResult[] {\n\treturn results.map((result) => {\n\t\tif (result.category !== 'mta_sts') return result;\n\t\tconst adjusted = result.findings.map((finding: Finding) => {\n\t\t\tif (finding.title === 'No MTA-STS or TLS-RPT records found') {\n\t\t\t\treturn {\n\t\t\t\t\t...finding,\n\t\t\t\t\tdetail: `Neither MTA-STS nor TLS-RPT records are present for ${domain}. Since this domain has MX records and accepts email, adding MTA-STS and TLS-RPT is recommended to protect inbound email in transit.`,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn finding;\n\t\t});\n\t\treturn buildCheckResult(result.category, adjusted);\n\t});\n}\n\nfunction adjustForNonMailDomain(results: CheckResult[], apexDmarcCovers: boolean): CheckResult[] {\n\tconst emailCategories: CheckCategory[] = ['spf', 'dmarc', 'dkim', 'mta_sts', 'subdomailing'];\n\treturn results.map((result) => {\n\t\tif (!emailCategories.includes(result.category)) return result;\n\t\tconst adjusted = result.findings.map((finding: Finding) => {\n\t\t\tif ((finding.severity === 'critical' || finding.severity === 'high') && isMissingRecordFinding(finding)) {\n\t\t\t\tconst reason = apexDmarcCovers\n\t\t\t\t\t? 'expected — no MX records and parent domain DMARC policy covers subdomains'\n\t\t\t\t\t: 'expected — domain has no MX records';\n\t\t\t\treturn { ...finding, severity: 'info' as const, detail: `${finding.detail} (${reason})` };\n\t\t\t}\n\t\t\treturn finding;\n\t\t});\n\t\treturn buildCheckResult(result.category, adjusted);\n\t});\n}\n\nfunction adjustBimiForNonMailDomain(results: CheckResult[]): CheckResult[] {\n\treturn results.map((result) => {\n\t\tif (result.category !== 'bimi') return result;\n\t\tconst adjusted = result.findings.map((finding: Finding) => {\n\t\t\tif (finding.title === 'No BIMI record found' && finding.detail.includes('eligible for BIMI')) {\n\t\t\t\tconst bimiDomain = finding.detail.match(/at (default\\._bimi\\.\\S+)/)?.[1] ?? `default._bimi.unknown`;\n\t\t\t\treturn {\n\t\t\t\t\t...finding,\n\t\t\t\t\tdetail: `No BIMI record found at ${bimiDomain}. This domain does not appear to send email, so BIMI is not applicable.`,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn finding;\n\t\t});\n\t\treturn buildCheckResult(result.category, adjusted);\n\t});\n}\n\nfunction adjustForNoSendDomain(results: CheckResult[]): CheckResult[] {\n\tconst noSendCategories: CheckCategory[] = ['dkim', 'mta_sts', 'bimi'];\n\treturn results.map((result) => {\n\t\tif (!noSendCategories.includes(result.category)) return result;\n\t\tconst adjusted = result.findings.map((finding: Finding) => {\n\t\t\tif ((finding.severity === 'critical' || finding.severity === 'high') && isMissingRecordFinding(finding)) {\n\t\t\t\treturn {\n\t\t\t\t\t...finding,\n\t\t\t\t\tseverity: 'info' as const,\n\t\t\t\t\tdetail: `${finding.detail} (expected — domain SPF policy rejects all outbound mail)`,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn finding;\n\t\t});\n\t\treturn buildCheckResult(result.category, adjusted);\n\t});\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Email Security Maturity Staging.\n * Classifies a domain's email security posture into a maturity stage (0-4)\n * based on the results of individual DNS security checks.\n */\n\nimport type { CheckResult, Finding } from '../../lib/scoring';\n\nexport interface MaturityStage {\n\tstage: number;\n\tlabel: string;\n\tdescription: string;\n\tnextStep: string;\n}\n\n/**\n * Compute the email security maturity stage from scan check results.\n * Stages range from 0 (Unprotected) to 4 (Hardened).\n */\n/**\n * Cap the maturity stage based on the overall scan score.\n * Prevents a domain from being labeled \"Hardened\" or \"Enforcing\"\n * when the actual security score indicates significant issues.\n *\n * - Score < 50 (F grade): cap at Stage 2 maximum\n * - Score < 63 (D/D+ grade): cap at Stage 3 maximum\n * - Score >= 63: no cap applied\n *\n * Stages already at or below the cap are returned unchanged.\n */\nexport function capMaturityStage(maturity: MaturityStage, score: number): MaturityStage {\n\tif (score < 50 && maturity.stage > 2) {\n\t\treturn {\n\t\t\tstage: 2,\n\t\t\tlabel: 'Monitoring (score-capped)',\n\t\t\tdescription: 'Controls are present but the overall security score is too low for a higher maturity rating.',\n\t\t\tnextStep: 'Address critical and high-severity findings to improve the overall score before advancing maturity.',\n\t\t};\n\t}\n\n\tif (score < 63 && maturity.stage > 3) {\n\t\treturn {\n\t\t\tstage: 3,\n\t\t\tlabel: 'Enforcing (score-capped)',\n\t\t\tdescription: 'Controls are present but the overall security score is too low for the highest maturity rating.',\n\t\t\tnextStep: 'Resolve remaining findings to raise the score above the D grade range and achieve full hardening.',\n\t\t};\n\t}\n\n\treturn maturity;\n}\n\nexport function computeMaturityStage(checks: CheckResult[]): MaturityStage {\n\tconst byCategory = new Map(checks.map((c) => [c.category, c]));\n\n\tconst mxCheck = byCategory.get('mx');\n\tconst spfCheck = byCategory.get('spf');\n\tconst dmarcCheck = byCategory.get('dmarc');\n\tconst dkimCheck = byCategory.get('dkim');\n\tconst mtaStsCheck = byCategory.get('mta_sts');\n\tconst dnssecCheck = byCategory.get('dnssec');\n\tconst bimiCheck = byCategory.get('bimi');\n\n\t// Non-mail domains should not receive email maturity stages.\n\t// The numeric stage values here (0 = \"Unprotected\", 1 = \"DNS-Only\") intentionally\n\t// reuse the same numbers as the mail-domain scale. This is safe because `stage` is\n\t// only ever rendered as a display value alongside `label` — it is never used as a\n\t// numeric index or compared against mail-domain stages in any downstream logic.\n\tconst hasNoMx = mxCheck != null && mxCheck.findings.some((f: Finding) => f.title === 'No MX records found');\n\tif (hasNoMx) {\n\t\tconst hasDnssec = dnssecCheck?.passed ?? false;\n\t\treturn {\n\t\t\tstage: hasDnssec ? 1 : 0,\n\t\t\tlabel: hasDnssec ? 'DNS-Only' : 'Unprotected',\n\t\t\tdescription: hasDnssec\n\t\t\t\t? 'This domain does not accept email. DNS security (DNSSEC) is in place.'\n\t\t\t\t: 'This domain does not accept email and has no DNSSEC.',\n\t\t\tnextStep: hasDnssec ? '' : 'Enable DNSSEC to protect DNS resolution integrity.',\n\t\t};\n\t}\n\n\t// Determine SPF presence\n\tconst hasSpf = spfCheck != null && !spfCheck.findings.some((f: Finding) => /No SPF record/i.test(f.title));\n\n\t// Determine DMARC presence and policy\n\tconst hasDmarc = dmarcCheck != null && !dmarcCheck.findings.some((f: Finding) => /No DMARC record/i.test(f.title));\n\tconst dmarcPolicyNone = dmarcCheck?.findings.some((f: Finding) => /policy set to none/i.test(f.title)) ?? false;\n\tconst dmarcPolicyQuarantine = dmarcCheck?.findings.some((f: Finding) => /policy set to quarantine/i.test(f.title)) ?? false;\n\t// reject = no \"policy set to none\" and no \"policy set to quarantine\" and DMARC exists\n\tconst dmarcPolicyReject = hasDmarc && !dmarcPolicyNone && !dmarcPolicyQuarantine;\n\tconst hasRua = dmarcCheck != null && !dmarcCheck.findings.some((f: Finding) => /No aggregate reporting/i.test(f.title));\n\n\t// Determine MTA-STS, DNSSEC, BIMI\n\tconst hasMtaSts = mtaStsCheck?.passed ?? false;\n\tconst hasDnssec = dnssecCheck?.passed ?? false;\n\tconst hasBimi = bimiCheck?.findings.some((f: Finding) => /BIMI record configured/i.test(f.title)) ?? false;\n\n\t// DANE presence\n\tconst daneCheck = byCategory.get('dane');\n\tconst hasDane = daneCheck?.findings.some((f: Finding) => /DANE TLSA configured/i.test(f.title)) ?? false;\n\n\t// CAA presence (passed = CAA records found)\n\tconst caaCheck = byCategory.get('caa');\n\tconst hasCaa = caaCheck?.passed ?? false;\n\n\t// DKIM \"discovered\" = at least one selector physically found (not provider-implied)\n\t// Provider-implied findings have metadata.detectionMethod === 'provider-implied'\n\tconst hasDkimDiscovered =\n\t\tdkimCheck != null &&\n\t\t!dkimCheck.findings.some((f: Finding) => /No DKIM records found|DKIM selector not discovered/i.test(f.title)) &&\n\t\t!dkimCheck.findings.some((f: Finding) => f.metadata?.detectionMethod === 'provider-implied');\n\n\t// Stage 4 — Hardened: Stage 3 + at least 2 of (MTA-STS, DNSSEC, BIMI, DANE, CAA, DKIM-discovered)\n\t// DKIM is no longer required for Stage 3 — enforcement alone (SPF + DMARC p=quarantine/reject) qualifies\n\tconst isEnforcing = hasSpf && hasDmarc && (dmarcPolicyReject || dmarcPolicyQuarantine);\n\tconst hardeningCount = [hasMtaSts, hasDnssec, hasBimi, hasDane, hasCaa, hasDkimDiscovered].filter(Boolean).length;\n\n\tif (isEnforcing && hardeningCount >= 2) {\n\t\treturn {\n\t\t\tstage: 4,\n\t\t\tlabel: 'Hardened',\n\t\t\tdescription: 'Comprehensive email and DNS security posture with defense in depth.',\n\t\t\tnextStep: '',\n\t\t};\n\t}\n\n\t// Stage 3 — Enforcing: DMARC p=quarantine or p=reject, SPF exists, DKIM exists\n\tif (isEnforcing) {\n\t\treturn {\n\t\t\tstage: 3,\n\t\t\tlabel: 'Enforcing',\n\t\t\tdescription: 'Email authentication is actively enforcing — spoofed emails are blocked or quarantined.',\n\t\t\tnextStep: 'Add MTA-STS, DNSSEC, and BIMI to reach full hardening.',\n\t\t};\n\t}\n\n\t// Stage 2 — Monitoring: SPF + DMARC with p=none and rua= present\n\tif (hasSpf && hasDmarc && dmarcPolicyNone && hasRua) {\n\t\treturn {\n\t\t\tstage: 2,\n\t\t\tlabel: 'Monitoring',\n\t\t\tdescription: 'Email authentication is published and being monitored but not enforcing.',\n\t\t\tnextStep: 'After reviewing DMARC reports, move to p=quarantine and ensure DKIM is active.',\n\t\t};\n\t}\n\n\t// Stage 1 — Basic: SPF exists but DMARC is p=none or DMARC has no rua=\n\tif (hasSpf && hasDmarc) {\n\t\treturn {\n\t\t\tstage: 1,\n\t\t\tlabel: 'Basic',\n\t\t\tdescription: 'Basic email records exist but are not enforcing or monitoring.',\n\t\t\tnextStep: 'Add DMARC aggregate reporting (rua=) and monitor for 2-4 weeks before enforcing.',\n\t\t};\n\t}\n\n\t// Stage 0 — Unprotected\n\treturn {\n\t\tstage: 0,\n\t\tlabel: 'Unprotected',\n\t\tdescription: 'No email authentication — any server can send email as this domain.',\n\t\tnextStep: 'Publish SPF and DMARC records to begin protecting your domain.',\n\t};\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport type { ScanDomainResult } from '../scan-domain';\nimport type { Finding } from '../../lib/scoring';\nimport type { OutputFormat } from '../../handlers/tool-args';\nimport { sanitizeOutputText } from '../../lib/output-sanitize';\nimport { resolveImpactNarrative } from '../explain-finding';\n\n/** Structured scan result for machine-readable consumption (e.g., CI/CD actions). */\nexport interface StructuredScanResult {\n\tdomain: string;\n\tscore: number;\n\tgrade: string;\n\tpassed: boolean;\n\tmaturityStage: number | null;\n\tmaturityLabel: string | null;\n\tcategoryScores: Record<string, number>;\n\tfindingCounts: { critical: number; high: number; medium: number; low: number };\n\tscoringProfile: string;\n\tscoringSignals: string[];\n\tscoringNote: string | null;\n\tadaptiveWeightDeltas: Record<string, number> | null;\n\t/** Percentile rank within the scoring profile population (0–100). Null when insufficient benchmark data. */\n\tpercentileRank: number | null;\n\t/** Composite email spoofability score (0–100, higher = more spoofable). Null when not computed. */\n\tspoofabilityScore: number | null;\n\t/** Category interaction effects applied as post-scoring adjustments. */\n\tinteractionEffects: Array<{ ruleId: string; penalty: number; narrative: string }>;\n\t/** Execution status per check category. 'completed' = ran normally, 'timeout' = per-check timeout, 'error' = threw. */\n\tcheckStatuses: Record<string, 'completed' | 'timeout' | 'error'>;\n\t/** DNSSEC configuration source. 'domain_configured' = domain has own DNSKEY/DS; 'tld_inherited' = inherited from TLD registry. null = not yet available. */\n\tdnssecSource: 'domain_configured' | 'tld_inherited' | null;\n\t/** CDN provider detected from HTTP response headers. null when no CDN detected or check did not run. */\n\tcdnProvider: string | null;\n\t/** Email categories that scored 100 due to web-only/non-mail profile (no MX). Downstream consumers should treat these as N/A rather than perfect. */\n\tnotApplicableCategories: string[];\n\ttimestamp: string;\n\tcached: boolean;\n}\n\n/** Optional enrichment data for structured scan results. */\nexport interface ScanResultEnrichment {\n\tpercentileRank?: number | null;\n\tspoofabilityScore?: number | null;\n}\n\n/** Build a machine-readable structured result from a scan. */\nexport function buildStructuredScanResult(result: ScanDomainResult, enrichment?: ScanResultEnrichment): StructuredScanResult {\n\t// checkStatuses\n\tconst checkStatuses: Record<string, 'completed' | 'timeout' | 'error'> = {};\n\tfor (const check of result.checks) {\n\t\tcheckStatuses[check.category] = check.checkStatus ?? 'completed';\n\t}\n\n\t// dnssecSource\n\tconst dnssecCheck = result.checks.find((c) => c.category === 'dnssec');\n\tlet dnssecSource: 'domain_configured' | 'tld_inherited' | null = null;\n\tif (dnssecCheck) {\n\t\tfor (const f of dnssecCheck.findings) {\n\t\t\tconst src = f.metadata?.dnssecSource;\n\t\t\tif (src === 'domain_configured' || src === 'tld_inherited') {\n\t\t\t\tdnssecSource = src as 'domain_configured' | 'tld_inherited';\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (dnssecSource === null && dnssecCheck.passed && (checkStatuses['dnssec'] ?? 'completed') === 'completed') {\n\t\t\tdnssecSource = 'domain_configured';\n\t\t}\n\t}\n\n\t// cdnProvider\n\tconst httpCheck = result.checks.find((c) => c.category === 'http_security');\n\tlet cdnProvider: string | null = null;\n\tif (httpCheck) {\n\t\tfor (const f of httpCheck.findings) {\n\t\t\tconst cdn = f.metadata?.cdnProvider;\n\t\t\tif (typeof cdn === 'string') {\n\t\t\t\tcdnProvider = cdn;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// notApplicableCategories\n\tconst emailCategories = ['spf', 'dmarc', 'dkim', 'mta_sts'];\n\tconst isNonMailProfile = ['non_mail', 'web_only'].includes(result.context?.profile ?? '');\n\tconst notApplicableCategories: string[] = [];\n\tif (isNonMailProfile) {\n\t\tfor (const check of result.checks) {\n\t\t\tif (emailCategories.includes(check.category)) {\n\t\t\t\tconst allInfo = check.findings.length > 0 && check.findings.every((f: Finding) => f.severity === 'info');\n\t\t\t\tconst noFindings = check.findings.length === 0 && check.score === 100;\n\t\t\t\tif (allInfo || noFindings) {\n\t\t\t\t\tnotApplicableCategories.push(check.category);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tdomain: result.domain,\n\t\tscore: result.score.overall,\n\t\tgrade: result.score.grade,\n\t\tpassed: result.score.overall >= 50,\n\t\tmaturityStage: result.maturity?.stage ?? null,\n\t\tmaturityLabel: result.maturity?.label ?? null,\n\t\tcategoryScores: result.score.categoryScores,\n\t\tfindingCounts: {\n\t\t\tcritical: result.score.findings.filter((f: Finding) => f.severity === 'critical').length,\n\t\t\thigh: result.score.findings.filter((f: Finding) => f.severity === 'high').length,\n\t\t\tmedium: result.score.findings.filter((f: Finding) => f.severity === 'medium').length,\n\t\t\tlow: result.score.findings.filter((f: Finding) => f.severity === 'low').length,\n\t\t},\n\t\tscoringProfile: result.context?.profile ?? 'mail_enabled',\n\t\tscoringSignals: (result.context?.signals ?? []).map((s: string) => s.replace(/[<>&\"']/g, '')),\n\t\tscoringNote: result.scoringNote ?? null,\n\t\tadaptiveWeightDeltas: result.adaptiveWeightDeltas ?? null,\n\t\tpercentileRank: enrichment?.percentileRank ?? null,\n\t\tspoofabilityScore: enrichment?.spoofabilityScore ?? null,\n\t\tinteractionEffects: (result.interactionEffects ?? []).map((e) => ({\n\t\t\truleId: e.ruleId,\n\t\t\tpenalty: e.penalty,\n\t\t\tnarrative: e.narrative,\n\t\t})),\n\t\tcheckStatuses,\n\t\tdnssecSource,\n\t\tcdnProvider,\n\t\tnotApplicableCategories,\n\t\ttimestamp: result.timestamp,\n\t\tcached: result.cached,\n\t};\n}\n\nexport function formatScanReport(result: ScanDomainResult, format: OutputFormat = 'full'): string {\n\tconst lines: string[] = [];\n\n\tlines.push(`DNS Security Scan: ${result.domain}`);\n\tlines.push(`${'='.repeat(40)}`);\n\tlines.push(`Overall Score: ${result.score.overall}/100 (${result.score.grade})`);\n\tlines.push(`${result.score.summary}`);\n\tlines.push('');\n\n\tif (result.maturity) {\n\t\tif (format === 'compact') {\n\t\t\tlines.push(`Maturity: Stage ${result.maturity.stage} — ${result.maturity.label}`);\n\t\t} else {\n\t\t\tlines.push(`Email Security Maturity: Stage ${result.maturity.stage} — ${result.maturity.label}`);\n\t\t\tlines.push(result.maturity.description);\n\t\t\tif (result.maturity.nextStep) {\n\t\t\t\tlines.push(`Next step: ${result.maturity.nextStep}`);\n\t\t\t}\n\t\t}\n\t\tlines.push('');\n\t}\n\n\tif (format === 'full') {\n\t\tif (result.context) {\n\t\t\tconst signalSummary = result.context.signals.length > 0 ? result.context.signals.join(', ') : 'default';\n\t\t\tlines.push(`Scoring Profile: ${result.context.profile} (${signalSummary})`);\n\t\t\tlines.push('');\n\t\t}\n\n\t\tif (result.scoringNote) {\n\t\t\tlines.push(result.scoringNote);\n\t\t\tlines.push('');\n\t\t}\n\t}\n\n\tconst isNonMailProfile = ['non_mail', 'web_only'].includes(result.context?.profile ?? '');\n\tconst naEmailCategories = new Set(['spf', 'dmarc', 'dkim', 'mta_sts']);\n\n\tlines.push('Category Scores:');\n\tlines.push('-'.repeat(30));\n\tfor (const [category, score] of Object.entries(result.score.categoryScores) as [string, number][]) {\n\t\tif (isNonMailProfile && naEmailCategories.has(category)) {\n\t\t\tconst check = result.checks?.find((c) => c.category === category);\n\t\t\tconst allInfo = check && check.findings.length > 0 && check.findings.every((f: Finding) => f.severity === 'info');\n\t\t\tconst noFindings = !check || (check.findings.length === 0 && score === 100);\n\t\t\tif (allInfo || noFindings) {\n\t\t\t\tlines.push(` ∅ ${category.toUpperCase().padEnd(10)} N/A (web-only, no MX records)`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tconst status = score >= 80 ? '✓' : score >= 50 ? '⚠' : '✗';\n\t\tlines.push(` ${status} ${category.toUpperCase().padEnd(10)} ${score}/100`);\n\t}\n\tlines.push('');\n\n\tconst nonInfoFindings = result.score.findings.filter((finding: Finding) => finding.severity !== 'info');\n\tif (nonInfoFindings.length > 0) {\n\t\tlines.push('Findings:');\n\t\tlines.push('-'.repeat(30));\n\t\tfor (const finding of nonInfoFindings) {\n\t\t\tif (format === 'compact') {\n\t\t\t\tconst isHighPriority = finding.severity === 'critical' || finding.severity === 'high';\n\t\t\t\tconst detailLimit = isHighPriority ? 4000 : 300;\n\t\t\t\tlines.push(` [${finding.severity.toUpperCase()}] ${sanitizeOutputText(finding.title, 120)} — ${sanitizeOutputText(finding.detail, detailLimit)}`);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlines.push(` [${finding.severity.toUpperCase()}] ${sanitizeOutputText(finding.title, 120)}`);\n\t\t\tlines.push(` ${sanitizeOutputText(finding.detail)}`);\n\t\t\tconst verificationStatus =\n\t\t\t\tfinding.category === 'subdomain_takeover' && finding.metadata?.verificationStatus\n\t\t\t\t\t? String(finding.metadata.verificationStatus)\n\t\t\t\t\t: undefined;\n\t\t\tif (verificationStatus) {\n\t\t\t\tlines.push(` Takeover Verification: ${sanitizeOutputText(verificationStatus, 80)}`);\n\t\t\t}\n\t\t\tconst confidence = finding.metadata?.confidence ? String(finding.metadata.confidence) : undefined;\n\t\t\tif (confidence) {\n\t\t\t\tlines.push(` Confidence: ${sanitizeOutputText(confidence, 80)}`);\n\t\t\t}\n\t\t\tconst narrative = resolveImpactNarrative({\n\t\t\t\tcategory: finding.category,\n\t\t\t\tseverity: finding.severity,\n\t\t\t\ttitle: finding.title,\n\t\t\t\tdetail: finding.detail,\n\t\t\t});\n\t\t\tif (narrative.impact) {\n\t\t\t\tlines.push(` Potential Impact: ${narrative.impact}`);\n\t\t\t}\n\t\t\tif (narrative.adverseConsequences) {\n\t\t\t\tlines.push(` Adverse Consequences: ${narrative.adverseConsequences}`);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tlines.push('No security issues found.');\n\t}\n\n\tif (format === 'full' && result.interactionEffects && result.interactionEffects.length > 0) {\n\t\tlines.push('');\n\t\tlines.push('Interaction Effects:');\n\t\tlines.push('-'.repeat(30));\n\t\tfor (const effect of result.interactionEffects) {\n\t\t\tlines.push(` [-${effect.penalty}] ${effect.narrative}`);\n\t\t}\n\t}\n\n\tif (result.cached) {\n\t\tlines.push('');\n\t\tlines.push('(Results served from cache)');\n\t}\n\n\tlines.push('');\n\tlines.push(`Scan completed: ${result.timestamp}`);\n\treturn lines.join('\\n');\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * scan-domain orchestrator tool.\n * Runs all DNS security checks in parallel via Promise.all\n * and computes an overall security score.\n *\n * Uses KV-backed cache with 5-minute TTL for scan results when available,\n * with in-memory fallback when KV is not configured.\n * Compatible with Cloudflare Workers runtime (no Node.js APIs).\n */\n\nimport {\n\ttype CheckCategory,\n\ttype CheckResult,\n\ttype DomainContext,\n\ttype DomainProfile,\n\ttype ScanScore,\n\tbuildCheckResult,\n\tcomputeScanScore,\n\tcreateFinding,\n\tdetectDomainContext,\n\tgetProfileWeights,\n} from '../lib/scoring';\nimport {\n\tadaptiveWeightsToContext,\n\tgenerateScoringNote,\n\ttype AdaptiveWeightsResponse,\n\ttype ScanTelemetry,\n} from '../lib/adaptive-weights';\nimport { applyInteractionPenalties, type InteractionEffect } from '../lib/category-interactions';\nimport { cacheGet, cacheSet, runWithCache } from '../lib/cache';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { checkSpf } from './check-spf';\nimport { checkDmarc } from './check-dmarc';\nimport { checkDkim, applyProviderDkimContext } from './check-dkim';\nimport { checkDnssec } from './check-dnssec';\nimport { checkSsl } from './check-ssl';\nimport { checkMtaSts } from './check-mta-sts';\nimport { checkNs } from './check-ns';\nimport { checkCaa } from './check-caa';\nimport { checkBimi } from './check-bimi';\nimport { checkTlsrpt } from './check-tlsrpt';\nimport { checkSubdomainTakeover } from './check-subdomain-takeover';\nimport { checkMx } from './check-mx';\nimport { checkHttpSecurity } from './check-http-security';\nimport { checkDane } from './check-dane';\nimport { checkDaneHttps } from './check-dane-https';\nimport { checkSvcbHttps } from './check-svcb-https';\nimport { checkSubdomailing } from './check-subdomailing';\nimport { applyScanPostProcessing } from './scan/post-processing';\nimport type { ScanRuntimeOptions } from './scan/post-processing';\nimport { capMaturityStage, computeMaturityStage } from './scan/maturity-staging';\nimport type { MaturityStage } from './scan/maturity-staging';\nexport { formatScanReport, buildStructuredScanResult } from './scan/format-report';\nexport type { StructuredScanResult, ScanResultEnrichment } from './scan/format-report';\nexport type { MaturityStage } from './scan/maturity-staging';\nexport type { ScanRuntimeOptions } from './scan/post-processing';\n\n/** Cache key prefix for scan and per-check results */\nconst CACHE_PREFIX = 'cache:';\n\n/** Maximum wall-clock time for a single check within scan_domain (ms). */\nconst PER_CHECK_TIMEOUT_MS = 8_000;\n\n/** Maximum wall-clock time for the entire scan_domain orchestration (ms). */\nconst SCAN_TIMEOUT_MS = 12_000;\n\n/** In-memory cache for adaptive weight responses from the ProfileAccumulator DO. */\nconst adaptiveWeightCache = new Map<string, { weights: AdaptiveWeightsResponse; expires: number }>();\n\n/** TTL for the in-memory adaptive weight cache (ms). */\nconst ADAPTIVE_CACHE_TTL_MS = 60_000;\n\n/** Maximum entries in the adaptive weight cache before eviction. */\nconst ADAPTIVE_CACHE_MAX_ENTRIES = 100;\n\n/** Timeout for fetching adaptive weights from the DO (ms). */\nconst ADAPTIVE_FETCH_TIMEOUT_MS = 200;\n\nexport interface ScanDomainResult {\n\tdomain: string;\n\tscore: ScanScore;\n\tchecks: CheckResult[];\n\tmaturity: MaturityStage;\n\tcontext: DomainContext;\n\tcached: boolean;\n\ttimestamp: string;\n\tscoringNote: string | null;\n\tadaptiveWeightDeltas: Record<string, number> | null;\n\t/** Category interaction effects applied as post-scoring adjustments. Empty when no interactions triggered. */\n\tinteractionEffects: InteractionEffect[];\n}\n\n/**\n * Run a full DNS security scan on a domain.\n * Executes all checks in parallel and computes an overall score.\n *\n * @param domain - The domain to scan (must already be validated and sanitized by the caller)\n * @param kv - Optional KV namespace for persistent scan result caching\n * @returns Full scan result with score, individual check results, and metadata\n */\nexport async function scanDomain(domain: string, kv?: KVNamespace, runtimeOptions?: ScanRuntimeOptions): Promise<ScanDomainResult> {\n\tconst explicitProfile = runtimeOptions?.profile;\n\tconst isExplicit = explicitProfile && explicitProfile !== 'auto';\n\tconst cacheKey = isExplicit\n\t\t? `${CACHE_PREFIX}${domain}:profile:${explicitProfile}`\n\t\t: `${CACHE_PREFIX}${domain}`;\n\n\t// Check cache first (skip when force_refresh is requested)\n\tif (!runtimeOptions?.forceRefresh) {\n\t\tconst cached = await cacheGet<ScanDomainResult>(cacheKey, kv);\n\t\tif (cached) {\n\t\t\treturn { ...cached, cached: true };\n\t\t}\n\t}\n\n\t// Run all checks in parallel with per-check timeouts, wrapped in an\n\t// overall scan timeout to guarantee a timely response.\n\t// Uses Promise.allSettled so that completed checks are preserved on timeout.\n\tconst ALL_CHECK_CATEGORIES: CheckCategory[] = [\n\t\t'spf', 'dmarc', 'dkim', 'dnssec', 'ssl', 'mta_sts', 'ns', 'caa', 'bimi', 'tlsrpt', 'subdomain_takeover', 'http_security', 'dane', 'mx', 'dane_https', 'svcb_https', 'subdomailing',\n\t];\n\n\t// Skip secondary DNS confirmation in scan context for speed — individual checks\n\t// still use secondary confirmation when called directly by users.\n\tconst scanDns: QueryDnsOptions = {\n\t\tskipSecondaryConfirmation: true,\n\t\tqueryCache: new Map(),\n\t\tsecondaryDoh: runtimeOptions?.secondaryDoh,\n\t};\n\n\tconst forceRefresh = runtimeOptions?.forceRefresh;\n\tconst cacheTtl = runtimeOptions?.cacheTtlSeconds;\n\n\tconst checkPromises = [\n\t\trunCachedCheck(domain, 'spf', () => safeCheck('spf', () => checkSpf(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'dmarc', () => safeCheck('dmarc', () => checkDmarc(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'dkim', () => safeCheck('dkim', () => checkDkim(domain, undefined, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'dnssec', () => safeCheck('dnssec', () => checkDnssec(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'ssl', () => safeCheck('ssl', () => checkSsl(domain)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'mta_sts', () => safeCheck('mta_sts', () => checkMtaSts(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'ns', () => safeCheck('ns', () => checkNs(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'caa', () => safeCheck('caa', () => checkCaa(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'bimi', () => safeCheck('bimi', () => checkBimi(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'tlsrpt', () => safeCheck('tlsrpt', () => checkTlsrpt(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'subdomain_takeover', () => safeCheck('subdomain_takeover', () => checkSubdomainTakeover(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'http_security', () => safeCheck('http_security', () => checkHttpSecurity(domain)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'dane', () => safeCheck('dane', () => checkDane(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'dane_https', () => safeCheck('dane_https', () => checkDaneHttps(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'svcb_https', () => safeCheck('svcb_https', () => checkSvcbHttps(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(domain, 'subdomailing', () => safeCheck('subdomailing', () => checkSubdomailing(domain, scanDns)), kv, cacheTtl, forceRefresh),\n\t\trunCachedCheck(\n\t\t\tdomain,\n\t\t\t'mx',\n\t\t\t() =>\n\t\t\t\tsafeCheck(\n\t\t\t\t\t'mx',\n\t\t\t\t\t() =>\n\t\t\t\t\t\tcheckMx(domain, {\n\t\t\t\t\t\t\tproviderSignaturesUrl: runtimeOptions?.providerSignaturesUrl,\n\t\t\t\t\t\t\tproviderSignaturesAllowedHosts: runtimeOptions?.providerSignaturesAllowedHosts,\n\t\t\t\t\t\t\tproviderSignaturesSha256: runtimeOptions?.providerSignaturesSha256,\n\t\t\t\t\t\t}, scanDns),\n\t\t\t\t),\n\t\t\tkv,\n\t\t\tcacheTtl,\n\t\t\tforceRefresh,\n\t\t),\n\t];\n\n\tlet timedOut = false;\n\tconst settled = await Promise.race([\n\t\tPromise.allSettled(checkPromises),\n\t\tnew Promise<PromiseSettledResult<CheckResult>[]>((resolve) =>\n\t\t\tsetTimeout(() => {\n\t\t\t\ttimedOut = true;\n\t\t\t\t// Snapshot whatever has settled so far by racing each promise with an immediate rejection\n\t\t\t\tresolve(\n\t\t\t\t\tPromise.allSettled(\n\t\t\t\t\t\tcheckPromises.map((p) => Promise.race([p, new Promise<never>((_, reject) => reject(new Error('__check_pending__')))])),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}, SCAN_TIMEOUT_MS),\n\t\t),\n\t]);\n\n\tlet checkResults = settled\n\t\t.filter((r): r is PromiseFulfilledResult<CheckResult> => r.status === 'fulfilled')\n\t\t.map((r) => r.value);\n\n\t// Track categories with degraded status before post-processing strips checkStatus.\n\t// Post-processing calls buildCheckResult() which creates new objects without checkStatus,\n\t// so we must record these statuses separately and re-apply them after post-processing.\n\tconst degradedStatuses = new Map<CheckCategory, 'error' | 'timeout'>();\n\tfor (const r of checkResults) {\n\t\tif (r.checkStatus === 'error' || r.checkStatus === 'timeout') {\n\t\t\tdegradedStatuses.set(r.category, r.checkStatus);\n\t\t}\n\t}\n\n\t// For any checks that didn't complete, add a timeout finding\n\tif (timedOut) {\n\t\tconst completedCategories = new Set(checkResults.map((r) => r.category));\n\t\tfor (const category of ALL_CHECK_CATEGORIES) {\n\t\t\tif (!completedCategories.has(category)) {\n\t\t\t\tconst findings = [\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\tcategory,\n\t\t\t\t\t\t`${category.toUpperCase()} check timed out`,\n\t\t\t\t\t\t'low',\n\t\t\t\t\t\t`Check did not complete within the ${SCAN_TIMEOUT_MS / 1000}s scan time limit. Try running this check individually.`,\n\t\t\t\t\t),\n\t\t\t\t];\n\t\t\t\tconst result = buildCheckResult(category, findings);\n\t\t\t\tcheckResults.push({ ...result, score: 0, checkStatus: 'timeout' as const });\n\t\t\t\tdegradedStatuses.set(category, 'timeout');\n\t\t\t}\n\t\t}\n\t}\n\n\tlet result: ScanDomainResult;\n\ttry {\n\t\tcheckResults = await applyScanPostProcessing(domain, checkResults, runtimeOptions);\n\n\t\t// Re-apply score=0 and checkStatus for checks that errored or timed out.\n\t\t// Post-processing calls buildCheckResult() which creates new objects that lose checkStatus,\n\t\t// so we re-enforce the zero score and status using the degradedStatuses map recorded above.\n\t\tif (degradedStatuses.size > 0) {\n\t\t\tcheckResults = checkResults.map((r) => {\n\t\t\t\tconst status = degradedStatuses.get(r.category);\n\t\t\t\treturn status ? { ...r, score: 0, checkStatus: status } : r;\n\t\t\t});\n\t\t}\n\n\t\t// Detect domain context from check results\n\t\tlet domainContext = detectDomainContext(checkResults);\n\n\t\t// If an explicit profile was requested, override detection\n\t\tif (isExplicit) {\n\t\t\tdomainContext = {\n\t\t\t\tprofile: explicitProfile as DomainProfile,\n\t\t\t\tsignals: [...domainContext.signals, `explicit profile override: ${explicitProfile}`],\n\t\t\t\tweights: getProfileWeights(explicitProfile as DomainProfile, runtimeOptions?.scoringConfig),\n\t\t\t\tdetectedProvider: domainContext.detectedProvider,\n\t\t\t};\n\t\t}\n\n\t\t// Apply provider-informed DKIM adjustment: when a known DKIM-signing\n\t\t// provider is detected via MX, downgrade the \"not found\" finding since\n\t\t// the provider likely signs by default with a custom selector.\n\t\tif (domainContext.detectedProvider) {\n\t\t\tconst dkimIdx = checkResults.findIndex((r) => r.category === 'dkim');\n\t\t\tif (dkimIdx !== -1) {\n\t\t\t\tcheckResults[dkimIdx] = applyProviderDkimContext(checkResults[dkimIdx], domainContext.detectedProvider);\n\t\t\t}\n\t\t}\n\n\t\t// Phase 1: only pass context to scoring when an explicit profile is set.\n\t\t// For 'auto' (or unset), detection runs and is reported but scoring\n\t\t// uses the default weights (identical to pre-profile behavior).\n\t\tconst scoringContext = isExplicit ? domainContext : undefined;\n\n\t\t// Attempt to fetch adaptive weights from the ProfileAccumulator DO\n\t\tlet adaptiveResponse: AdaptiveWeightsResponse | null = null;\n\t\tif (runtimeOptions?.profileAccumulator) {\n\t\t\tadaptiveResponse = await fetchAdaptiveWeights(\n\t\t\t\truntimeOptions.profileAccumulator,\n\t\t\t\tdomainContext.profile,\n\t\t\t\tdomainContext.detectedProvider,\n\t\t\t);\n\t\t}\n\n\t\t// Add bound hits to signals if present\n\t\tif (adaptiveResponse?.boundHits.length) {\n\t\t\tdomainContext.signals.push(`adaptive bound hits: ${adaptiveResponse.boundHits.join(', ')}`);\n\t\t}\n\n\t\tlet score: ScanScore;\n\t\tlet scoringNote: string | null = null;\n\t\tlet adaptiveWeightDeltas: Record<string, number> | null = null;\n\n\t\tif (adaptiveResponse && adaptiveResponse.sampleCount > 0) {\n\t\t\tconst adaptiveWeights = adaptiveWeightsToContext(adaptiveResponse.weights, domainContext.profile);\n\t\t\tif (adaptiveWeights) {\n\t\t\t\t// Compute adaptive score\n\t\t\t\tconst adaptiveContext: DomainContext = { ...domainContext, weights: adaptiveWeights };\n\t\t\t\tconst adaptiveScore = computeScanScore(checkResults, adaptiveContext, runtimeOptions?.scoringConfig);\n\n\t\t\t\t// Compute static score for comparison\n\t\t\t\tconst staticContext: DomainContext = {\n\t\t\t\t\t...domainContext,\n\t\t\t\t\tweights: getProfileWeights(domainContext.profile, runtimeOptions?.scoringConfig),\n\t\t\t\t};\n\t\t\t\tconst staticScore = computeScanScore(checkResults, scoringContext ?? staticContext, runtimeOptions?.scoringConfig);\n\n\t\t\t\t// Compute per-category weight deltas\n\t\t\t\tconst staticWeights = getProfileWeights(domainContext.profile, runtimeOptions?.scoringConfig);\n\t\t\t\tconst deltas: Record<string, number> = {};\n\t\t\t\tfor (const cat of Object.keys(staticWeights) as CheckCategory[]) {\n\t\t\t\t\tdeltas[cat] = adaptiveWeights[cat].importance - staticWeights[cat].importance;\n\t\t\t\t}\n\n\t\t\t\tconst scoreDelta = adaptiveScore.overall - staticScore.overall;\n\t\t\t\tscoringNote = generateScoringNote(deltas, scoreDelta, domainContext.detectedProvider);\n\t\t\t\tadaptiveWeightDeltas = deltas;\n\t\t\t\t// Use the SAME scoring call as the non-adaptive path for determinism.\n\t\t\t\t// Both paths must produce identical results regardless of whether the\n\t\t\t\t// ProfileAccumulatorDO responds. The adaptive delta is reported in\n\t\t\t\t// scoringNote for analytics consumers.\n\t\t\t\tscore = computeScanScore(checkResults, scoringContext, runtimeOptions?.scoringConfig);\n\t\t\t} else {\n\t\t\t\tscore = computeScanScore(checkResults, scoringContext, runtimeOptions?.scoringConfig);\n\t\t\t}\n\t\t} else {\n\t\t\tscore = computeScanScore(checkResults, scoringContext, runtimeOptions?.scoringConfig);\n\t\t}\n\n\t\t// Apply category interaction penalties (post-scoring adjustment)\n\t\tconst { adjustedScore, effects: interactionEffects } = applyInteractionPenalties(score, runtimeOptions?.scoringConfig);\n\t\tscore = adjustedScore;\n\n\t\tconst rawMaturity = computeMaturityStage(checkResults);\n\t\tconst maturity = capMaturityStage(rawMaturity, score.overall);\n\n\t\tresult = {\n\t\t\tdomain,\n\t\t\tscore,\n\t\t\tchecks: checkResults,\n\t\t\tmaturity,\n\t\t\tcontext: domainContext,\n\t\t\tcached: false,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tscoringNote,\n\t\t\tadaptiveWeightDeltas,\n\t\t\tinteractionEffects,\n\t\t};\n\n\t\t// POST telemetry to DO (best-effort, non-blocking)\n\t\tif (runtimeOptions?.profileAccumulator) {\n\t\t\tconst telemetry: ScanTelemetry = {\n\t\t\t\tprofile: domainContext.profile,\n\t\t\t\tprovider: domainContext.detectedProvider,\n\t\t\t\tcategoryFindings: checkResults.map((r) => ({ category: r.category, score: r.score, passed: r.passed })),\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\toverallScore: score.overall,\n\t\t\t};\n\t\t\tconst telemetryPromise = (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst stub = runtimeOptions.profileAccumulator!.get(\n\t\t\t\t\t\truntimeOptions.profileAccumulator!.idFromName('global'),\n\t\t\t\t\t);\n\t\t\t\t\tawait stub.fetch(\n\t\t\t\t\t\tnew Request('https://do/ingest', {\n\t\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\t\t\t\t\tbody: JSON.stringify(telemetry),\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t} catch {\n\t\t\t\t\t/* best-effort */\n\t\t\t\t}\n\t\t\t})();\n\t\t\tif (runtimeOptions.waitUntil) runtimeOptions.waitUntil(telemetryPromise);\n\t\t}\n\t} catch {\n\t\t// Post-processing or scoring failed — return whatever we have.\n\t\t// Re-apply degraded status overrides in case post-processing ran partially.\n\t\tif (degradedStatuses.size > 0) {\n\t\t\tcheckResults = checkResults.map((r) => {\n\t\t\t\tconst status = degradedStatuses.get(r.category);\n\t\t\t\treturn status ? { ...r, score: 0, checkStatus: status } : r;\n\t\t\t});\n\t\t}\n\t\tlet fallbackContext = detectDomainContext(checkResults);\n\t\tif (isExplicit) {\n\t\t\tfallbackContext = {\n\t\t\t\tprofile: explicitProfile as DomainProfile,\n\t\t\t\tsignals: [...fallbackContext.signals, `explicit profile override: ${explicitProfile}`],\n\t\t\t\tweights: getProfileWeights(explicitProfile as DomainProfile, runtimeOptions?.scoringConfig),\n\t\t\t\tdetectedProvider: fallbackContext.detectedProvider,\n\t\t\t};\n\t\t}\n\t\tconst fallbackScoringContext = isExplicit ? fallbackContext : undefined;\n\t\tconst score = computeScanScore(checkResults, fallbackScoringContext, runtimeOptions?.scoringConfig);\n\t\tconst rawMaturity = computeMaturityStage(checkResults);\n\t\tconst maturity = capMaturityStage(rawMaturity, score.overall);\n\t\tresult = {\n\t\t\tdomain,\n\t\t\tscore,\n\t\t\tchecks: checkResults,\n\t\t\tmaturity,\n\t\t\tcontext: fallbackContext,\n\t\t\tcached: false,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tscoringNote: null,\n\t\t\tadaptiveWeightDeltas: null,\n\t\t\tinteractionEffects: [],\n\t\t};\n\t}\n\n\t// Cache the result (use configurable TTL if provided)\n\t// Defer the write via waitUntil when available to avoid blocking the response.\n\tconst cachePromise = cacheSet(cacheKey, result, kv, runtimeOptions?.cacheTtlSeconds);\n\tif (runtimeOptions?.waitUntil) {\n\t\truntimeOptions.waitUntil(cachePromise);\n\t} else {\n\t\tawait cachePromise;\n\t}\n\n\treturn result;\n}\n\n/**\n * Fetch adaptive weights from the ProfileAccumulator DO with in-memory caching.\n * Returns null on failure or timeout (silently falls back to static weights).\n */\nasync function fetchAdaptiveWeights(\n\taccumulator: DurableObjectNamespace,\n\tprofile: string,\n\tprovider: string | null,\n): Promise<AdaptiveWeightsResponse | null> {\n\tconst cacheKey = `${profile}:${provider ?? ''}`;\n\tconst now = Date.now();\n\n\t// Check in-memory cache first\n\tconst cached = adaptiveWeightCache.get(cacheKey);\n\tif (cached && cached.expires > now) {\n\t\treturn cached.weights;\n\t}\n\n\ttry {\n\t\tconst stub = accumulator.get(accumulator.idFromName('global'));\n\t\tconst url = new URL('https://do/weights');\n\t\turl.searchParams.set('profile', profile);\n\t\tif (provider) url.searchParams.set('provider', provider);\n\n\t\tconst response = await Promise.race([\n\t\t\tstub.fetch(new Request(url.toString())),\n\t\t\tnew Promise<never>((_, reject) => setTimeout(() => reject(new Error('adaptive weight fetch timeout')), ADAPTIVE_FETCH_TIMEOUT_MS)),\n\t\t]);\n\n\t\tif (!response.ok) return null;\n\n\t\tconst data = (await response.json()) as AdaptiveWeightsResponse;\n\t\tif (adaptiveWeightCache.size >= ADAPTIVE_CACHE_MAX_ENTRIES) {\n\t\t\tevictAdaptiveWeightCache();\n\t\t}\n\t\tadaptiveWeightCache.set(cacheKey, { weights: data, expires: now + ADAPTIVE_CACHE_TTL_MS });\n\t\treturn data;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Evict entries from the adaptive weight cache.\n * Removes expired entries first, then if still at capacity, evicts the entry with the oldest expiry time.\n */\nexport function evictAdaptiveWeightCache(): void {\n\tconst now = Date.now();\n\n\t// First pass: remove all expired entries\n\tfor (const [key, entry] of adaptiveWeightCache) {\n\t\tif (entry.expires <= now) {\n\t\t\tadaptiveWeightCache.delete(key);\n\t\t}\n\t}\n\n\t// If still at capacity after removing expired entries, evict the oldest by expiry\n\tif (adaptiveWeightCache.size >= ADAPTIVE_CACHE_MAX_ENTRIES) {\n\t\tlet oldestKey: string | null = null;\n\t\tlet oldestExpiry = Infinity;\n\t\tfor (const [key, entry] of adaptiveWeightCache) {\n\t\t\tif (entry.expires < oldestExpiry) {\n\t\t\t\toldestExpiry = entry.expires;\n\t\t\t\toldestKey = key;\n\t\t\t}\n\t\t}\n\t\tif (oldestKey !== null) {\n\t\t\tadaptiveWeightCache.delete(oldestKey);\n\t\t}\n\t}\n}\n\n/** Exposed for testing only — do not use in production code. */\nexport const _adaptiveWeightCacheForTest = adaptiveWeightCache;\n\nasync function runCachedCheck(\n\tdomain: string,\n\tcategory: CheckCategory,\n\trun: () => Promise<CheckResult>,\n\tkv?: KVNamespace,\n\tttlSeconds?: number,\n\tskipCache?: boolean,\n): Promise<CheckResult> {\n\treturn runWithCache(`${CACHE_PREFIX}${domain}:check:${category}`, run, kv, ttlSeconds, skipCache);\n}\n\n/**\n * Run a single check with error handling and a per-check timeout.\n * If a check fails or exceeds the timeout, returns a failed CheckResult\n * with an error/timeout finding instead of throwing, so other checks\n * can still complete.\n */\nasync function safeCheck(category: CheckCategory, fn: () => Promise<CheckResult>): Promise<CheckResult> {\n\ttry {\n\t\tconst result = await Promise.race([\n\t\t\tfn(),\n\t\t\tnew Promise<never>((_, reject) => setTimeout(() => reject(new Error('Check timed out')), PER_CHECK_TIMEOUT_MS)),\n\t\t]);\n\t\treturn result;\n\t} catch (err) {\n\t\tconst rawMessage = err instanceof Error ? err.message : 'Check failed';\n\t\tconst SAFE_PREFIXES = ['DNS query', 'Check timed out', 'Check failed', 'Connection', 'timeout'];\n\t\tconst safeMessage = SAFE_PREFIXES.some((p) => rawMessage.startsWith(p)) ? rawMessage : 'Check failed';\n\t\tconst findings = [createFinding(category, `${category.toUpperCase()} check error`, 'high', `Check failed: ${safeMessage}`)];\n\t\tconst result = buildCheckResult(category, findings);\n\t\treturn { ...result, score: 0, checkStatus: 'error' as const };\n\t}\n}\n\n"]}
|