pagegraph 0.5.0 → 0.5.1
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/dist/audit.d.ts +3 -3
- package/dist/audit.js +1928 -1
- package/dist/audit.js.map +1 -0
- package/dist/cli.js +33482 -35
- package/dist/cli.js.map +1 -1
- package/dist/index.js +449 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/audit-B96V1x3q.js +0 -1929
- package/dist/audit-B96V1x3q.js.map +0 -1
- package/dist/inspect-html-CHuoiO2s.js +0 -452
- package/dist/inspect-html-CHuoiO2s.js.map +0 -1
- package/dist/main-GFEobQTH.js +0 -750
- package/dist/main-GFEobQTH.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","names":["Data","Data","Data","errorMessage","requestHttps","requestHttp","request","request","requestHttp","Schema","Data","errorMessage","Data","Schema","request","requestHttps","requestHttp"],"sources":["../src/audit/rules.ts","../src/audit/scanner-registry.ts","../src/audit/audit.ts","../src/audit/model.ts","../src/audit/diff.ts","../src/audit/layers.ts","../src/audit/scanner.ts","../src/audit/render.ts","../src/audit/network.ts","../src/audit/scanners/http.ts","../src/audit/proxy.ts","../src/audit/scanners/lighthouse.ts","../src/audit/scanners/hosted.ts"],"sourcesContent":["import type { AuditFinding, AuditOptions } from \"./model\";\nimport type { ScannerInput, ScannerObservation, ScannerRule } from \"./scanner\";\n\nconst record = (value: unknown): Record<string, unknown> | undefined =>\n typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n\nconst stringAt = (value: unknown, ...keys: string[]): string | undefined => {\n let current: unknown = value;\n for (const key of keys) {\n const object = record(current);\n current = object?.[key];\n }\n return typeof current === \"string\" ? current : undefined;\n};\n\nconst firstString = (\n value: unknown,\n paths: readonly (readonly string[])[],\n): string | undefined => {\n for (const path of paths) {\n const found = stringAt(value, ...path);\n if (found !== undefined) return found;\n }\n return undefined;\n};\n\nconst pageEvidence = (value: unknown): unknown => {\n if (!Array.isArray(value)) return value;\n return (\n value.find((entry) => stringAt(entry, \"kind\") === \"page-html\") ??\n value.find((entry) => stringAt(entry, \"kind\") === \"page-head\") ??\n value[0]\n );\n};\n\nconst finding = (\n input: ScannerInput,\n rule: string,\n message: string,\n fix: string,\n observed?: unknown,\n severity: AuditFinding[\"severity\"] = \"structural\",\n): AuditFinding => ({\n scanner: \"rules\",\n target: input.target.url,\n severity,\n rule,\n message,\n fix,\n ...(observed === undefined ? {} : { observed }),\n});\n\n/** Generic page-quality rules. They accept the normalized evidence shape used\n * by HTTP and hosted scanners, while remaining pure and dependency-free. */\nexport const pageRules: readonly ScannerRule[] = [\n {\n id: \"http-status\",\n evaluate: (observation, input) => {\n const status = record(pageEvidence(observation.evidence))?.status;\n return typeof status === \"number\" && status >= 400\n ? [\n finding(\n input,\n \"http-status\",\n `Fetch returned HTTP ${status}.`,\n \"Return a successful HTTP status.\",\n status,\n ),\n ]\n : [];\n },\n },\n {\n id: \"title-length\",\n evaluate: (observation, input) => {\n const evidence = pageEvidence(observation.evidence);\n const title = firstString(evidence, [\n [\"title\"],\n [\"document\", \"title\"],\n [\"head\", \"title\"],\n ]);\n const policy = input.options.policy;\n const min = policy?.titleMinLength ?? 10;\n const max = policy?.titleMaxLength ?? 70;\n if (title === undefined || title.trim() === \"\") {\n return [\n finding(\n input,\n \"missing-title\",\n \"Page is missing a usable title.\",\n \"Add a descriptive <title>.\",\n ),\n ];\n }\n if (title.length < min || title.length > max) {\n return [\n finding(\n input,\n \"title-length\",\n `Title length ${title.length} is outside ${min}-${max} characters.`,\n `Keep the title between ${min} and ${max} characters.`,\n title,\n \"editorial\",\n ),\n ];\n }\n return [];\n },\n },\n {\n id: \"description-length\",\n evaluate: (observation, input) => {\n const evidence = pageEvidence(observation.evidence);\n const description = firstString(evidence, [\n [\"description\"],\n [\"metaDescription\"],\n [\"document\", \"description\"],\n [\"head\", \"description\"],\n ]);\n const policy = input.options.policy;\n const min = policy?.descriptionMinLength ?? 50;\n const max = policy?.descriptionMaxLength ?? 160;\n if (description === undefined || description.trim() === \"\") {\n return [\n finding(\n input,\n \"missing-description\",\n \"Page is missing a meta description.\",\n \"Add a concise description that summarizes the page.\",\n ),\n ];\n }\n if (description.length < min || description.length > max) {\n return [\n finding(\n input,\n \"description-length\",\n `Meta description length ${description.length} is outside ${min}-${max} characters.`,\n `Keep the meta description between ${min} and ${max} characters.`,\n description,\n \"editorial\",\n ),\n ];\n }\n return [];\n },\n },\n {\n id: \"canonical\",\n evaluate: (observation, input) => {\n if (input.options.policy?.requireCanonical === false) return [];\n const canonical = firstString(pageEvidence(observation.evidence), [\n [\"canonical\"],\n [\"canonicalUrl\"],\n [\"document\", \"canonical\"],\n [\"document\", \"canonicalUrl\"],\n [\"head\", \"canonical\"],\n ]);\n if (canonical === undefined) {\n return [\n finding(\n input,\n \"missing-canonical\",\n \"Page is missing a canonical URL.\",\n \"Add a canonical link that identifies the preferred URL.\",\n ),\n ];\n }\n try {\n const observed = new URL(canonical, input.target.url);\n const expected = new URL(\n firstString(pageEvidence(observation.evidence), [[\"finalUrl\"]]) ??\n input.target.url,\n );\n observed.hash = \"\";\n expected.hash = \"\";\n return observed.href === expected.href\n ? []\n : [\n finding(\n input,\n \"canonical-mismatch\",\n `Canonical points to ${observed.href} instead of the audited URL.`,\n \"Use a self-referencing canonical unless this page is intentionally consolidated.\",\n observed.href,\n ),\n ];\n } catch {\n return [\n finding(\n input,\n \"invalid-canonical\",\n \"Page canonical is not a valid URL.\",\n \"Use an absolute or resolvable canonical URL.\",\n canonical,\n ),\n ];\n }\n },\n },\n];\n\nexport const evaluateRules = (\n rules: readonly ScannerRule[],\n observation: ScannerObservation,\n input: ScannerInput,\n): readonly AuditFinding[] =>\n rules.flatMap((rule) => rule.evaluate(observation, input));\n\n/** Default policy for a web-page audit. */\nexport const defaultAuditOptions: AuditOptions = {\n concurrency: 4,\n policy: {\n titleMinLength: 10,\n titleMaxLength: 70,\n descriptionMinLength: 50,\n descriptionMaxLength: 160,\n requireCanonical: true,\n },\n};\n","import * as Context from \"effect/Context\";\nimport * as Layer from \"effect/Layer\";\n\nimport type { Scanner } from \"./scanner\";\n\nexport interface ScannerRegistryShape {\n readonly all: () => readonly Scanner[];\n readonly get: (id: string) => Scanner | undefined;\n}\n\n/** Registry is deliberately a small service: callers depend on the protocol,\n * not on a concrete list of scanner implementations. */\nexport namespace ScannerRegistry {\n export class Service extends Context.Service<Service, ScannerRegistryShape>()(\n \"pagegraph/ScannerRegistry\",\n ) {}\n}\n\nexport const makeScannerRegistry = (\n scanners: Iterable<Scanner>,\n): ScannerRegistryShape => {\n const values = [...scanners];\n const byId = new Map(values.map((value) => [value.id, value]));\n return {\n all: () => values,\n get: (id) => byId.get(id),\n };\n};\n\nexport const ScannerRegistryLive = (\n scanners: Iterable<Scanner>,\n): Layer.Layer<ScannerRegistry.Service> =>\n Layer.succeed(ScannerRegistry.Service, makeScannerRegistry(scanners));\n","import * as Context from \"effect/Context\";\nimport * as Data from \"effect/Data\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\n\nimport type {\n AuditFinding,\n AuditOptions,\n AuditReport,\n ScannerResult,\n} from \"./model\";\nimport { evaluateRules, pageRules } from \"./rules\";\nimport { ScannerRegistry } from \"./scanner-registry\";\nimport type { Scanner, ScannerInput } from \"./scanner\";\n\nexport class InvalidTarget extends Data.TaggedError(\"InvalidTarget\")<{\n readonly target: string;\n readonly message: string;\n}> {}\n\nexport type AuditError = InvalidTarget;\n\nexport interface AuditRequest {\n readonly targets: readonly string[];\n readonly options?: AuditOptions;\n readonly scanners?: readonly string[];\n}\n\nexport interface AuditService {\n readonly run: (\n request: AuditRequest,\n ) => Effect.Effect<AuditReport, AuditError>;\n}\n\nexport namespace Audit {\n export class Service extends Context.Service<Service, AuditService>()(\n \"pagegraph/Audit\",\n ) {}\n}\n\nconst validateTarget = (\n target: string,\n): Effect.Effect<{ readonly url: string }, InvalidTarget> =>\n Effect.try({\n try: () => {\n const url = new URL(target);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new Error(\"only http and https URLs are supported\");\n }\n if (url.username || url.password) {\n throw new Error(\"credentials in URLs are not supported\");\n }\n return { url: url.toString() };\n },\n catch: (cause) =>\n new InvalidTarget({\n target,\n message: cause instanceof Error ? cause.message : \"invalid URL\",\n }),\n });\n\nconst runOne = Effect.fn(\"Audit.runScanner\")(function* (\n scanner: Scanner,\n target: { readonly url: string },\n options: AuditOptions,\n): Effect.fn.Return<ScannerResult> {\n const input: ScannerInput = { target, options };\n const result = yield* scanner.scan(input).pipe(\n Effect.map((observation) => ({\n scanner: scanner.id,\n target: target.url,\n status: \"ok\" as const,\n ...(observation.evidence === undefined\n ? {}\n : { evidence: observation.evidence }),\n // Page metadata rules apply to the HTTP page evidence only. Lighthouse\n // and hosted scanners have different evidence domains and must not emit\n // false missing-title/description findings.\n findings: [\n ...(observation.findings ?? []),\n ...evaluateRules(\n [\n ...(scanner.rules ?? []),\n ...(scanner.id === \"http\" ? pageRules : []),\n ],\n observation,\n input,\n ),\n ],\n })),\n Effect.catchTag(\"ScannerFailure\", (error) =>\n Effect.succeed({\n scanner: scanner.id,\n target: target.url,\n status: \"error\" as const,\n findings: [],\n error: error instanceof Error ? error.message : String(error),\n }),\n ),\n );\n return result;\n});\n\nconst runAudit = Effect.fn(\"Audit.run\")(function* (\n registry: ScannerRegistry.Service[\"Service\"],\n request: AuditRequest,\n) {\n const targets = yield* Effect.forEach(request.targets, validateTarget);\n const options = {\n ...defaultOptions,\n ...(request.options ?? {}),\n policy: { ...defaultOptions.policy, ...(request.options?.policy ?? {}) },\n };\n const available = registry.all();\n const scanners =\n request.scanners === undefined\n ? available\n : available.filter((scanner) => request.scanners!.includes(scanner.id));\n const pairs = targets.flatMap((target) =>\n scanners.map((scanner) => ({ target, scanner })),\n );\n const results = yield* Effect.forEach(\n pairs,\n ({ target, scanner }) => runOne(scanner, target, options),\n { concurrency: Math.max(1, Math.floor(options.concurrency ?? 4)) },\n );\n const findings: AuditFinding[] = results.flatMap((result) => result.findings);\n const warnings = results\n .filter((result) => result.status === \"error\")\n .map(\n (result) =>\n `${result.scanner} failed for ${result.target}: ${result.error ?? \"unknown error\"}`,\n );\n const generatedAt = yield* Effect.clockWith((clock) =>\n Effect.map(clock.currentTimeMillis, (millis) =>\n new Date(millis).toISOString(),\n ),\n );\n return {\n schemaVersion: 1 as const,\n generatedAt,\n targets: targets.map(({ url }) => url),\n results,\n findings,\n warnings,\n };\n});\n\nconst defaultOptions: Required<Pick<AuditOptions, \"concurrency\" | \"policy\">> = {\n concurrency: 4,\n policy: {\n titleMinLength: 10,\n titleMaxLength: 70,\n descriptionMinLength: 50,\n descriptionMaxLength: 160,\n requireCanonical: true,\n },\n};\n\nexport const makeAudit = (\n registry: ScannerRegistry.Service[\"Service\"],\n): AuditService => ({\n run: (request) => runAudit(registry, request),\n});\n\nexport const AuditLive = Layer.effect(\n Audit.Service,\n Effect.map(ScannerRegistry.Service, makeAudit),\n);\n","import { Schema } from \"effect\";\n\n/** A stable identifier for a scanner, such as `http` or `lighthouse`. */\nexport type ScannerId = string;\n\nexport const formFactors = [\"mobile\", \"desktop\"] as const;\nexport type FormFactor = (typeof formFactors)[number];\n\nexport type FindingSeverity = \"structural\" | \"editorial\";\n\nexport const FindingSeverity = Schema.Literals([\n \"structural\",\n \"editorial\",\n] as const);\n\n/** A machine-readable audit finding. Values are intentionally open-ended so\n * scanner authors can retain the evidence that led to a finding. */\nexport const AuditFinding = Schema.Struct({\n scanner: Schema.String,\n target: Schema.String,\n severity: FindingSeverity,\n rule: Schema.String,\n message: Schema.String,\n fix: Schema.optionalKey(Schema.String),\n observed: Schema.optionalKey(Schema.Unknown),\n expected: Schema.optionalKey(Schema.Unknown),\n});\nexport type AuditFinding = typeof AuditFinding.Type;\n\nexport const ScannerStatus = Schema.Literals([\"ok\", \"error\"] as const);\nexport type ScannerStatus = typeof ScannerStatus.Type;\n\n/** The result of one scanner against one target. Scanner failures are data in\n * a report rather than an un-attributed failure of the entire audit. */\nexport const ScannerResult = Schema.Struct({\n scanner: Schema.String,\n target: Schema.String,\n status: ScannerStatus,\n evidence: Schema.optionalKey(Schema.Unknown),\n findings: Schema.Array(AuditFinding),\n error: Schema.optionalKey(Schema.String),\n});\nexport type ScannerResult = typeof ScannerResult.Type;\n\nexport const AuditPolicy = Schema.Struct({\n titleMinLength: Schema.optionalKey(Schema.Number),\n titleMaxLength: Schema.optionalKey(Schema.Number),\n descriptionMinLength: Schema.optionalKey(Schema.Number),\n descriptionMaxLength: Schema.optionalKey(Schema.Number),\n requireCanonical: Schema.optionalKey(Schema.Boolean),\n});\nexport type AuditPolicy = typeof AuditPolicy.Type;\n\n/** JSON/Markdown report contract for `pagegraph audit`. */\nexport const AuditReport = Schema.Struct({\n schemaVersion: Schema.Literal(1),\n generatedAt: Schema.String,\n targets: Schema.Array(Schema.String),\n results: Schema.Array(ScannerResult),\n findings: Schema.Array(AuditFinding),\n warnings: Schema.Array(Schema.String),\n});\nexport type AuditReport = typeof AuditReport.Type;\n\nexport interface AuditTarget {\n readonly url: string;\n}\n\n/** Portable HTTP evidence model used by the built-in network scanner. These\n * types stay free of Node and Effect so reports can be rendered in any host. */\nexport type ProbeKind =\n | \"page-head\"\n | \"page-html\"\n | \"page-markdown\"\n | \"robots\"\n | \"sitemap\"\n | \"llms\"\n | \"auth\"\n | \"integrations\"\n | \"agent-card\"\n | \"agent-skills\"\n | \"oauth-protected-resource\"\n | \"oauth-authorization-server\"\n | \"openapi\";\n\nexport interface ProbeRequest {\n readonly kind: ProbeKind;\n readonly method: \"HEAD\" | \"GET\";\n readonly accept: string;\n readonly url: URL;\n}\n\nexport interface ProbeOptions {\n readonly timeoutMs: number;\n readonly maxBodyBytes: number;\n readonly allowPrivate: boolean;\n}\n\nexport interface DocumentSignals {\n readonly title: string | null;\n readonly description: string | null;\n readonly canonicalUrl: string | null;\n readonly robots: string | null;\n readonly jsonLdCount: number;\n readonly modulePreloadCount: number;\n readonly scriptCount: number;\n readonly stylesheetCount: number;\n readonly wordCount: number | null;\n readonly jsonValid: boolean | null;\n}\n\nexport interface HttpProbe {\n readonly kind: ProbeKind;\n readonly method: \"HEAD\" | \"GET\";\n readonly accept: string;\n readonly requestedUrl: string;\n readonly finalUrl: string | null;\n readonly redirects: readonly string[];\n readonly status: number | null;\n readonly ok: boolean;\n readonly headersMs: number | null;\n readonly totalMs: number;\n readonly responseHeaders: Readonly<Record<string, string>>;\n readonly capturedBodyBytes: number;\n readonly capturedBodySha256: string | null;\n readonly bodyTruncated: boolean;\n readonly bodyExcerpt: string | null;\n readonly document: DocumentSignals | null;\n readonly error: string | null;\n}\n\nexport interface AuditOptions {\n readonly concurrency?: number;\n readonly policy?: AuditPolicy;\n readonly formFactors?: readonly FormFactor[];\n readonly runs?: number;\n readonly lighthouse?: boolean;\n readonly scanners?: boolean;\n readonly requestTimeoutMs?: number;\n readonly scannerTimeoutMs?: number;\n readonly maxBodyBytes?: number;\n readonly allowPrivate?: boolean;\n readonly scannerOrigins?: Readonly<Record<string, string>>;\n readonly targets?: readonly URL[];\n readonly [key: string]: unknown;\n}\n\nexport interface LighthouseMetric {\n readonly id: string;\n readonly title: string;\n readonly numericValue: number | null;\n readonly numericUnit: string | null;\n readonly displayValue: string | null;\n readonly score: number | null;\n}\n\nexport interface LighthouseCategory {\n readonly id: string;\n readonly title: string;\n readonly score: number | null;\n}\n\nexport interface LighthouseOpportunity {\n readonly id: string;\n readonly title: string;\n readonly displayValue: string | null;\n readonly savingsMs: number | null;\n readonly savingsBytes: number | null;\n}\n\nexport interface LighthouseRun {\n readonly requestedUrl: string;\n readonly finalUrl: string | null;\n readonly formFactor: FormFactor;\n readonly run: number;\n readonly lighthouseVersion: string | null;\n readonly userAgent: string | null;\n readonly fetchTime: string | null;\n readonly categories: Readonly<Record<string, LighthouseCategory>>;\n readonly metrics: Readonly<Record<string, LighthouseMetric>>;\n readonly opportunities: readonly LighthouseOpportunity[];\n readonly warnings: readonly string[];\n readonly error: string | null;\n}\n","import { Data, Schema } from \"effect\";\n\nimport {\n AuditFinding,\n FindingSeverity,\n ScannerStatus,\n type AuditReport,\n} from \"./model\";\n\nconst DiffFindingGroup = Schema.Struct({\n target: Schema.String,\n scanner: Schema.String,\n rule: Schema.String,\n severity: FindingSeverity,\n findings: Schema.Array(AuditFinding),\n});\n\nconst FindingAdded = Schema.TaggedStruct(\"FindingAdded\", {\n group: DiffFindingGroup,\n});\nconst FindingRemoved = Schema.TaggedStruct(\"FindingRemoved\", {\n group: DiffFindingGroup,\n});\nconst FindingChanged = Schema.TaggedStruct(\"FindingChanged\", {\n target: Schema.String,\n scanner: Schema.String,\n rule: Schema.String,\n beforeSeverity: FindingSeverity,\n afterSeverity: FindingSeverity,\n before: Schema.Array(AuditFinding),\n after: Schema.Array(AuditFinding),\n});\nconst ScannerDegraded = Schema.TaggedStruct(\"ScannerDegraded\", {\n target: Schema.String,\n scanner: Schema.String,\n});\nconst ScannerRecovered = Schema.TaggedStruct(\"ScannerRecovered\", {\n target: Schema.String,\n scanner: Schema.String,\n});\nconst TargetAdded = Schema.TaggedStruct(\"TargetAdded\", {\n target: Schema.String,\n});\nconst TargetRemoved = Schema.TaggedStruct(\"TargetRemoved\", {\n target: Schema.String,\n});\nconst ScannerAdded = Schema.TaggedStruct(\"ScannerAdded\", {\n target: Schema.String,\n scanner: Schema.String,\n status: ScannerStatus,\n});\nconst ScannerRemoved = Schema.TaggedStruct(\"ScannerRemoved\", {\n target: Schema.String,\n scanner: Schema.String,\n});\n\n/** One normalized semantic change between two audit reports. */\nexport const AuditDiffChange = Schema.Union([\n FindingAdded,\n FindingRemoved,\n FindingChanged,\n ScannerDegraded,\n ScannerRecovered,\n TargetAdded,\n TargetRemoved,\n ScannerAdded,\n ScannerRemoved,\n]).pipe(Schema.toTaggedUnion(\"_tag\"));\nexport type AuditDiffChange = typeof AuditDiffChange.Type;\n\nexport const AuditDiffOutcome = Schema.Literals([\n \"unchanged\",\n \"changed\",\n \"regressed\",\n] as const);\nexport type AuditDiffOutcome = typeof AuditDiffOutcome.Type;\n\nexport const AuditDiffSummary = Schema.Struct({\n structuralRegressions: Schema.Number,\n editorialRegressions: Schema.Number,\n scannerRegressions: Schema.Number,\n coverageRegressions: Schema.Number,\n improvements: Schema.Number,\n informationalChanges: Schema.Number,\n});\nexport type AuditDiffSummary = typeof AuditDiffSummary.Type;\n\nconst AuditDiffSource = Schema.Struct({\n reportSchemaVersion: Schema.Literal(1),\n generatedAt: Schema.String,\n targets: Schema.Array(Schema.String),\n});\n\n/** Versioned machine-readable contract emitted by `pagegraph diff --json`. */\nexport const AuditDiff = Schema.Struct({\n kind: Schema.Literal(\"audit-diff\"),\n schemaVersion: Schema.Literal(1),\n before: AuditDiffSource,\n after: AuditDiffSource,\n outcome: AuditDiffOutcome,\n summary: AuditDiffSummary,\n changes: Schema.Array(AuditDiffChange),\n ignored: Schema.Tuple([\n Schema.Literal(\"generatedAt\"),\n Schema.Literal(\"warnings\"),\n Schema.Literal(\"results[].evidence\"),\n ]),\n});\nexport type AuditDiff = typeof AuditDiff.Type;\n\nexport type AuditComparisonResult = Data.TaggedEnum<{\n Success: { readonly diff: AuditDiff };\n InvalidReport: { readonly issues: ReadonlyArray<string> };\n}>;\nexport const AuditComparisonResult = Data.taggedEnum<AuditComparisonResult>();\n\ntype FindingGroup = {\n readonly target: string;\n readonly scanner: string;\n readonly rule: string;\n readonly severity: FindingSeverity;\n readonly findings: ReadonlyArray<AuditFinding>;\n};\n\nconst compareStrings = (left: string, right: string): number =>\n left < right ? -1 : left > right ? 1 : 0;\n\nconst canonicalize = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(canonicalize);\n if (value !== null && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value)\n .sort(([left], [right]) => compareStrings(left, right))\n .map(([key, entry]) => [key, canonicalize(entry)]),\n );\n }\n return value;\n};\n\nconst canonicalJson = (value: unknown): string =>\n JSON.stringify(canonicalize(value));\n\nconst tupleKey = (...parts: ReadonlyArray<string>): string =>\n JSON.stringify(parts);\n\nconst severityOf = (\n findings: ReadonlyArray<AuditFinding>,\n): FindingSeverity =>\n findings.some((finding) => finding.severity === \"structural\")\n ? \"structural\"\n : \"editorial\";\n\nconst findingsByIdentity = (\n findings: ReadonlyArray<AuditFinding>,\n): Map<string, FindingGroup> => {\n const groups = new Map<string, AuditFinding[]>();\n for (const finding of findings) {\n const key = tupleKey(finding.target, finding.scanner, finding.rule);\n const group = groups.get(key);\n if (group) group.push(finding);\n else groups.set(key, [finding]);\n }\n\n return new Map(\n [...groups.entries()].map(([key, group]) => {\n const sorted = group.toSorted((left, right) =>\n compareStrings(canonicalJson(left), canonicalJson(right)),\n );\n const first = sorted[0]!;\n return [\n key,\n {\n target: first.target,\n scanner: first.scanner,\n rule: first.rule,\n severity: severityOf(sorted),\n findings: sorted,\n },\n ];\n }),\n );\n};\n\nconst validateReport = (\n label: \"before\" | \"after\",\n report: AuditReport,\n): ReadonlyArray<string> => {\n const issues: string[] = [];\n const targets = new Set<string>();\n for (const target of report.targets) {\n if (targets.has(target)) issues.push(`${label}: duplicate target ${target}`);\n targets.add(target);\n }\n\n const results = new Set<string>();\n for (const result of report.results) {\n if (!targets.has(result.target)) {\n issues.push(\n `${label}: scanner ${result.scanner} references undeclared target ${result.target}`,\n );\n }\n const key = tupleKey(result.target, result.scanner);\n if (results.has(key)) {\n issues.push(\n `${label}: duplicate scanner result ${result.scanner} for ${result.target}`,\n );\n }\n results.add(key);\n for (const finding of result.findings) {\n if (finding.target !== result.target) {\n issues.push(\n `${label}: finding ${finding.rule} targets ${finding.target} inside result for ${result.target}`,\n );\n }\n }\n }\n\n const flattened = report.results\n .flatMap((result) => result.findings)\n .map(canonicalJson)\n .sort(compareStrings);\n const topLevel = report.findings.map(canonicalJson).sort(compareStrings);\n if (canonicalJson(flattened) !== canonicalJson(topLevel)) {\n issues.push(`${label}: top-level findings do not match result findings`);\n }\n\n return issues;\n};\n\nconst resultMap = (report: AuditReport) =>\n new Map(\n report.results.map((result) => [\n tupleKey(result.target, result.scanner),\n result,\n ]),\n );\n\nconst changeSortKey = (change: AuditDiffChange): string => {\n switch (change._tag) {\n case \"FindingAdded\":\n case \"FindingRemoved\":\n return tupleKey(\n change.group.target,\n change.group.scanner,\n change.group.rule,\n change._tag,\n );\n case \"FindingChanged\":\n return tupleKey(change.target, change.scanner, change.rule, change._tag);\n case \"ScannerAdded\":\n case \"ScannerRemoved\":\n case \"ScannerDegraded\":\n case \"ScannerRecovered\":\n return tupleKey(change.target, change.scanner, \"\", change._tag);\n case \"TargetAdded\":\n case \"TargetRemoved\":\n return tupleKey(change.target, \"\", \"\", change._tag);\n }\n};\n\nconst summarize = (changes: ReadonlyArray<AuditDiffChange>): AuditDiffSummary => {\n let structuralRegressions = 0;\n let editorialRegressions = 0;\n let scannerRegressions = 0;\n let coverageRegressions = 0;\n let improvements = 0;\n let informationalChanges = 0;\n\n for (const change of changes) {\n switch (change._tag) {\n case \"FindingAdded\":\n if (change.group.severity === \"structural\") structuralRegressions++;\n else editorialRegressions++;\n break;\n case \"FindingRemoved\":\n case \"ScannerRecovered\":\n improvements++;\n break;\n case \"FindingChanged\":\n if (\n change.beforeSeverity === \"editorial\" &&\n change.afterSeverity === \"structural\"\n ) {\n structuralRegressions++;\n } else if (\n change.beforeSeverity === \"structural\" &&\n change.afterSeverity === \"editorial\"\n ) {\n improvements++;\n } else {\n informationalChanges++;\n }\n break;\n case \"ScannerDegraded\":\n scannerRegressions++;\n break;\n case \"TargetRemoved\":\n case \"ScannerRemoved\":\n coverageRegressions++;\n break;\n case \"TargetAdded\":\n informationalChanges++;\n break;\n case \"ScannerAdded\":\n if (change.status === \"error\") scannerRegressions++;\n else informationalChanges++;\n break;\n }\n }\n\n return {\n structuralRegressions,\n editorialRegressions,\n scannerRegressions,\n coverageRegressions,\n improvements,\n informationalChanges,\n };\n};\n\nconst outcomeOf = (\n summary: AuditDiffSummary,\n changes: ReadonlyArray<AuditDiffChange>,\n): AuditDiffOutcome => {\n if (\n summary.structuralRegressions > 0 ||\n summary.scannerRegressions > 0 ||\n summary.coverageRegressions > 0\n ) {\n return \"regressed\";\n }\n return changes.length > 0 ? \"changed\" : \"unchanged\";\n};\n\n/** Compare two decoded audit reports while ignoring non-semantic scanner evidence. */\nexport const compareAuditReports = (\n before: AuditReport,\n after: AuditReport,\n): AuditComparisonResult => {\n const issues = [\n ...validateReport(\"before\", before),\n ...validateReport(\"after\", after),\n ];\n if (issues.length > 0) return AuditComparisonResult.InvalidReport({ issues });\n\n const changes: AuditDiffChange[] = [];\n const beforeTargets = new Set(before.targets);\n const afterTargets = new Set(after.targets);\n for (const target of beforeTargets) {\n if (!afterTargets.has(target)) changes.push({ _tag: \"TargetRemoved\", target });\n }\n for (const target of afterTargets) {\n if (!beforeTargets.has(target)) changes.push({ _tag: \"TargetAdded\", target });\n }\n\n const beforeResults = resultMap(before);\n const afterResults = resultMap(after);\n for (const [key, result] of beforeResults) {\n const next = afterResults.get(key);\n if (next === undefined) {\n changes.push({\n _tag: \"ScannerRemoved\",\n target: result.target,\n scanner: result.scanner,\n });\n } else if (result.status === \"ok\" && next.status === \"error\") {\n changes.push({\n _tag: \"ScannerDegraded\",\n target: result.target,\n scanner: result.scanner,\n });\n } else if (result.status === \"error\" && next.status === \"ok\") {\n changes.push({\n _tag: \"ScannerRecovered\",\n target: result.target,\n scanner: result.scanner,\n });\n }\n }\n for (const [key, result] of afterResults) {\n if (!beforeResults.has(key)) {\n changes.push({\n _tag: \"ScannerAdded\",\n target: result.target,\n scanner: result.scanner,\n status: result.status,\n });\n }\n }\n\n const beforeFindings = findingsByIdentity(before.findings);\n const afterFindings = findingsByIdentity(after.findings);\n for (const [key, group] of beforeFindings) {\n const next = afterFindings.get(key);\n if (next === undefined) {\n changes.push({ _tag: \"FindingRemoved\", group });\n } else if (\n canonicalJson(group.findings) !== canonicalJson(next.findings)\n ) {\n changes.push({\n _tag: \"FindingChanged\",\n target: group.target,\n scanner: group.scanner,\n rule: group.rule,\n beforeSeverity: group.severity,\n afterSeverity: next.severity,\n before: group.findings,\n after: next.findings,\n });\n }\n }\n for (const [key, group] of afterFindings) {\n if (!beforeFindings.has(key)) {\n changes.push({ _tag: \"FindingAdded\", group });\n }\n }\n\n changes.sort((left, right) =>\n compareStrings(changeSortKey(left), changeSortKey(right)),\n );\n const summary = summarize(changes);\n const targets = (report: AuditReport) => report.targets.toSorted(compareStrings);\n return AuditComparisonResult.Success({\n diff: {\n kind: \"audit-diff\",\n schemaVersion: 1,\n before: {\n reportSchemaVersion: 1,\n generatedAt: before.generatedAt,\n targets: targets(before),\n },\n after: {\n reportSchemaVersion: 1,\n generatedAt: after.generatedAt,\n targets: targets(after),\n },\n outcome: outcomeOf(summary, changes),\n summary,\n changes,\n ignored: [\"generatedAt\", \"warnings\", \"results[].evidence\"],\n },\n });\n};\n","import * as Layer from \"effect/Layer\";\n\nimport { Audit, AuditLive } from \"./audit\";\nimport { ScannerRegistry, ScannerRegistryLive } from \"./scanner-registry\";\nimport type { Scanner } from \"./scanner\";\n\n/** Compose the default audit services with an explicit scanner set. */\nexport const AuditLayer = (\n scanners: Iterable<Scanner>,\n): Layer.Layer<Audit.Service> =>\n AuditLive.pipe(Layer.provide(ScannerRegistryLive(scanners)));\n\nexport { Audit, ScannerRegistry };\nexport { AuditLive };\n","import * as Data from \"effect/Data\";\nimport * as Effect from \"effect/Effect\";\n\nimport type {\n AuditFinding,\n AuditOptions,\n AuditTarget,\n ScannerId,\n} from \"./model\";\n\n/** A typed, attributed failure from a scanner. The audit service catches this\n * at the scanner boundary and preserves it in the report. */\nexport class ScannerFailure extends Data.TaggedError(\"ScannerFailure\")<{\n readonly scanner: ScannerId;\n readonly target: string;\n readonly message: string;\n readonly cause?: unknown;\n}> {}\n\nexport interface ScannerInput {\n readonly target: AuditTarget;\n readonly options: AuditOptions;\n}\n\nexport interface ScannerObservation {\n readonly evidence?: unknown;\n readonly findings?: readonly AuditFinding[];\n}\n\nexport interface ScannerRule {\n readonly id: string;\n readonly evaluate: (\n observation: ScannerObservation,\n input: ScannerInput,\n ) => readonly AuditFinding[];\n}\n\n/** Value-level scanner protocol. Concrete adapters remain ordinary values and\n * can be substituted in tests or composed into a registry layer. */\nexport interface Scanner {\n readonly id: ScannerId;\n readonly description?: string;\n readonly rules?: readonly ScannerRule[];\n readonly scan: (\n input: ScannerInput,\n ) => Effect.Effect<ScannerObservation, ScannerFailure>;\n}\n\nexport const scanner = (definition: Scanner): Scanner => definition;\n","import { mkdir, rename, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport type { AuditDiff, AuditDiffChange } from \"./diff\";\nimport type { AuditReport } from \"./model\";\n\nconst cell = (value: unknown): string =>\n String(value ?? \"—\")\n .replaceAll(\"|\", \"\\\\|\")\n .replaceAll(\"\\n\", \" \");\n\nexport const renderAuditMarkdown = (report: AuditReport): string => {\n const structural = report.findings.filter(\n (finding) => finding.severity === \"structural\",\n );\n const editorial = report.findings.filter(\n (finding) => finding.severity === \"editorial\",\n );\n const lines = [\n \"# SEO audit\",\n \"\",\n `Generated: ${report.generatedAt}`,\n `Targets: ${report.targets.length} · Structural: ${structural.length} · Editorial: ${editorial.length}`,\n \"\",\n \"## Scanner results\",\n \"\",\n \"| Scanner | Target | Status | Findings |\",\n \"| --- | --- | --- | ---: |\",\n ...report.results.map(\n (result) =>\n `| ${cell(result.scanner)} | ${cell(result.target)} | ${cell(result.status)} | ${result.findings.length} |`,\n ),\n ];\n\n if (report.findings.length > 0) {\n lines.push(\n \"\",\n \"## Findings\",\n \"\",\n \"| Severity | Rule | Target | Finding |\",\n \"| --- | --- | --- | --- |\",\n ...report.findings.map(\n (finding) =>\n `| ${cell(finding.severity)} | ${cell(finding.rule)} | ${cell(finding.target)} | ${cell(finding.message)} |`,\n ),\n );\n }\n\n if (report.warnings.length > 0) {\n lines.push(\n \"\",\n \"## Warnings\",\n \"\",\n ...report.warnings.map((warning) => `- ${warning}`),\n );\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n};\n\nconst renderDiffChange = (change: AuditDiffChange): string => {\n switch (change._tag) {\n case \"FindingAdded\":\n return `+ [${change.group.severity}] ${change.group.rule} · ${change.group.target} (${change.group.scanner})`;\n case \"FindingRemoved\":\n return `- [${change.group.severity}] ${change.group.rule} · ${change.group.target} (${change.group.scanner})`;\n case \"FindingChanged\":\n return `~ [${change.beforeSeverity} → ${change.afterSeverity}] ${change.rule} · ${change.target} (${change.scanner})`;\n case \"ScannerDegraded\":\n return `✗ scanner ${change.scanner} degraded · ${change.target}`;\n case \"ScannerRecovered\":\n return `✓ scanner ${change.scanner} recovered · ${change.target}`;\n case \"TargetAdded\":\n return `+ target coverage · ${change.target}`;\n case \"TargetRemoved\":\n return `- target coverage · ${change.target}`;\n case \"ScannerAdded\":\n return `+ scanner coverage ${change.scanner} (${change.status}) · ${change.target}`;\n case \"ScannerRemoved\":\n return `- scanner coverage ${change.scanner} · ${change.target}`;\n }\n};\n\nconst diffSection = (\n title: string,\n changes: ReadonlyArray<AuditDiffChange>,\n): ReadonlyArray<string> =>\n changes.length === 0\n ? []\n : [\"\", `## ${title}`, \"\", ...changes.map(renderDiffChange)];\n\n/** Human-readable rendering of the semantic comparison contract. */\nexport const renderAuditDiff = (diff: AuditDiff): string => {\n const regressions: AuditDiffChange[] = [];\n const editorial: AuditDiffChange[] = [];\n const improvements: AuditDiffChange[] = [];\n const informational: AuditDiffChange[] = [];\n\n for (const change of diff.changes) {\n switch (change._tag) {\n case \"FindingAdded\":\n if (change.group.severity === \"structural\") regressions.push(change);\n else editorial.push(change);\n break;\n case \"FindingChanged\":\n if (\n change.beforeSeverity === \"editorial\" &&\n change.afterSeverity === \"structural\"\n ) {\n regressions.push(change);\n } else if (\n change.beforeSeverity === \"structural\" &&\n change.afterSeverity === \"editorial\"\n ) {\n improvements.push(change);\n } else {\n informational.push(change);\n }\n break;\n case \"ScannerDegraded\":\n case \"TargetRemoved\":\n case \"ScannerRemoved\":\n regressions.push(change);\n break;\n case \"FindingRemoved\":\n case \"ScannerRecovered\":\n improvements.push(change);\n break;\n case \"TargetAdded\":\n informational.push(change);\n break;\n case \"ScannerAdded\":\n if (change.status === \"error\") regressions.push(change);\n else informational.push(change);\n break;\n }\n }\n\n const symbol =\n diff.outcome === \"regressed\"\n ? \"✗\"\n : diff.outcome === \"changed\"\n ? \"!\"\n : \"✓\";\n const lines = [\n \"# SEO audit diff\",\n \"\",\n `${symbol} Outcome: ${diff.outcome}`,\n `Before: ${diff.before.generatedAt} · ${diff.before.targets.length} target(s)`,\n `After: ${diff.after.generatedAt} · ${diff.after.targets.length} target(s)`,\n ];\n\n if (diff.changes.length === 0) {\n lines.push(\"\", \"No semantic changes. Volatile scanner evidence was ignored.\");\n } else {\n lines.push(\n ...diffSection(\"Regressions\", regressions),\n ...diffSection(\"Editorial changes\", editorial),\n ...diffSection(\"Improvements\", improvements),\n ...diffSection(\"Other changes\", informational),\n );\n }\n\n lines.push(\n \"\",\n `Ignored: ${diff.ignored.join(\", \")}`,\n \"\",\n `Summary: ${diff.summary.structuralRegressions} structural · ${diff.summary.editorialRegressions} editorial · ${diff.summary.scannerRegressions} scanner · ${diff.summary.coverageRegressions} coverage regression(s)`,\n );\n return `${lines.join(\"\\n\")}\\n`;\n};\n\nconst atomicWrite = async (path: string, contents: string): Promise<void> => {\n const temporary = `${path}.${process.pid}.${crypto.randomUUID()}.tmp`;\n await writeFile(temporary, contents, \"utf8\");\n await rename(temporary, path);\n};\n\nexport const writeAuditFiles = async (\n report: AuditReport,\n outputDirectory: string,\n): Promise<{ readonly json: string; readonly markdown: string }> => {\n await mkdir(outputDirectory, { recursive: true });\n const stamp = report.generatedAt.replaceAll(\":\", \"-\");\n const json = join(outputDirectory, `${stamp}.json`);\n const markdown = join(outputDirectory, `${stamp}.md`);\n await Promise.all([\n atomicWrite(json, `${JSON.stringify(report, null, 2)}\\n`),\n atomicWrite(markdown, renderAuditMarkdown(report)),\n ]);\n return { json, markdown };\n};\n","import { lookup } from \"node:dns/promises\";\nimport { BlockList, isIP, type LookupFunction } from \"node:net\";\n\nexport interface ResolvedAddress {\n readonly address: string;\n readonly family: 4 | 6;\n}\n\nexport type HostResolver = (\n hostname: string,\n) => Promise<ReadonlyArray<ResolvedAddress>>;\n\nconst blockedIpv4Addresses = new BlockList();\nblockedIpv4Addresses.addAddress(\"168.63.129.16\", \"ipv4\");\n\nfor (const [network, prefix] of [\n [\"0.0.0.0\", 8],\n [\"10.0.0.0\", 8],\n [\"100.64.0.0\", 10],\n [\"127.0.0.0\", 8],\n [\"169.254.0.0\", 16],\n [\"172.16.0.0\", 12],\n [\"192.0.0.0\", 24],\n [\"192.0.2.0\", 24],\n [\"192.88.99.0\", 24],\n [\"192.168.0.0\", 16],\n [\"198.18.0.0\", 15],\n [\"198.51.100.0\", 24],\n [\"203.0.113.0\", 24],\n [\"224.0.0.0\", 4],\n [\"240.0.0.0\", 4],\n] as const) {\n blockedIpv4Addresses.addSubnet(network, prefix, \"ipv4\");\n}\n\nconst ipv4Groups = (address: string): [number, number] => {\n const octets = address.split(\".\").map(Number);\n if (\n octets.length !== 4 ||\n octets.some((octet) => !Number.isInteger(octet) || octet < 0 || octet > 255)\n ) {\n throw new Error(`Invalid embedded IPv4 address: ${address}`);\n }\n return [(octets[0]! << 8) | octets[1]!, (octets[2]! << 8) | octets[3]!];\n};\n\nconst ipv6Value = (address: string): bigint => {\n const [head = \"\", tail, extra] = address.toLowerCase().split(\"::\");\n if (extra !== undefined) throw new Error(`Invalid IPv6 address: ${address}`);\n const parseGroups = (side: string): Array<number> =>\n side === \"\"\n ? []\n : side\n .split(\":\")\n .flatMap((group) =>\n group.includes(\".\")\n ? ipv4Groups(group)\n : [Number.parseInt(group, 16)],\n );\n const left = parseGroups(head);\n const right = parseGroups(tail ?? \"\");\n if (\n left.some(\n (group) => !Number.isInteger(group) || group < 0 || group > 0xffff,\n )\n ) {\n throw new Error(`Invalid IPv6 address: ${address}`);\n }\n const missing = 8 - left.length - right.length;\n if ((tail === undefined && missing !== 0) || missing < 0) {\n throw new Error(`Invalid IPv6 address: ${address}`);\n }\n return [...left, ...Array<number>(missing).fill(0), ...right].reduce(\n (value, group) => (value << 16n) | BigInt(group),\n 0n,\n );\n};\n\nconst blockedIpv6Ranges = [\n [\"::\", 128],\n [\"::1\", 128],\n [\"::\", 96],\n [\"::ffff:0:0\", 96],\n [\"::ffff:0:0:0\", 96],\n [\"64:ff9b::\", 96],\n [\"64:ff9b:1::\", 48],\n [\"100::\", 64],\n [\"2001::\", 23],\n [\"2001:db8::\", 32],\n [\"2002::\", 16],\n [\"3fff::\", 20],\n [\"5f00::\", 16],\n [\"fc00::\", 7],\n [\"fe80::\", 10],\n [\"ff00::\", 8],\n] as const;\n\nconst isBlockedIpv6 = (address: string): boolean => {\n try {\n const value = ipv6Value(address);\n return blockedIpv6Ranges.some(([network, prefix]) => {\n const shift = BigInt(128 - prefix);\n return value >> shift === ipv6Value(network) >> shift;\n });\n } catch {\n return true;\n }\n};\n\nexport const networkHostname = (hostname: string): string =>\n hostname.startsWith(\"[\") && hostname.endsWith(\"]\")\n ? hostname.slice(1, -1)\n : hostname;\n\nexport const isPrivateAddress = (address: string): boolean => {\n const family = isIP(address);\n if (family === 4) return blockedIpv4Addresses.check(address, \"ipv4\");\n if (family === 6) return isBlockedIpv6(address);\n return true;\n};\n\nexport const resolveHostname: HostResolver = async (hostname) => {\n const normalized = networkHostname(hostname);\n const literalFamily = isIP(normalized);\n if (literalFamily === 4 || literalFamily === 6) {\n return [{ address: normalized, family: literalFamily }];\n }\n const addresses = await lookup(normalized, { all: true, verbatim: true });\n return addresses.flatMap(({ address, family }) =>\n family === 4 || family === 6 ? [{ address, family }] : [],\n );\n};\n\n/** Resolve every DNS answer before connecting. A host is rejected if any answer is private. */\nexport const resolveTargetUrl = async (\n url: URL,\n allowPrivate: boolean,\n resolve: HostResolver = resolveHostname,\n): Promise<ReadonlyArray<ResolvedAddress>> => {\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n throw new Error(`Unsupported URL protocol: ${url.protocol}`);\n }\n if (url.username || url.password)\n throw new Error(\"Target URLs must not contain credentials\");\n const hostname = networkHostname(url.hostname).toLowerCase();\n if (\n !allowPrivate &&\n (hostname === \"localhost\" || hostname.endsWith(\".local\"))\n ) {\n throw new Error(`Private target is not allowed: ${hostname}`);\n }\n const addresses = await resolve(hostname);\n if (\n addresses.length === 0 ||\n addresses.some(({ address, family }) => isIP(address) !== family) ||\n (!allowPrivate &&\n addresses.some(({ address }) => isPrivateAddress(address)))\n ) {\n throw new Error(`Private target is not allowed: ${hostname}`);\n }\n return addresses;\n};\n\n/** A lookup callback pinned to the already validated DNS answers. */\nexport const pinnedLookup = (\n addresses: ReadonlyArray<ResolvedAddress>,\n): LookupFunction => {\n const [first] = addresses;\n if (first === undefined)\n throw new Error(\"Cannot create a pinned lookup without an address\");\n return (_hostname, options, callback) => {\n if (options.all) {\n callback(\n null,\n addresses.map(({ address, family }) => ({ address, family })),\n );\n return;\n }\n callback(null, first.address, first.family);\n };\n};\n","import { createHash } from \"node:crypto\";\nimport type { IncomingHttpHeaders, IncomingMessage } from \"node:http\";\nimport { request as requestHttp } from \"node:http\";\nimport { request as requestHttps } from \"node:https\";\nimport { isIP } from \"node:net\";\nimport { checkServerIdentity } from \"node:tls\";\n\nimport * as Data from \"effect/Data\";\nimport * as Effect from \"effect/Effect\";\n\nimport type {\n DocumentSignals,\n HttpProbe,\n ProbeKind,\n ProbeOptions,\n ProbeRequest,\n} from \"../model\";\nimport {\n networkHostname,\n pinnedLookup,\n resolveTargetUrl,\n type HostResolver,\n} from \"../network\";\nimport { ScannerFailure, type Scanner, type ScannerInput } from \"../scanner\";\n\nexport class HttpProbeError extends Data.TaggedError(\"HttpProbeError\")<{\n readonly message: string;\n readonly cause?: unknown;\n}> {}\n\nconst errorMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error);\n\nconst discoveryPaths: ReadonlyArray<{\n readonly kind: ProbeKind;\n readonly path: string;\n readonly accept: string;\n}> = [\n { kind: \"robots\", path: \"/robots.txt\", accept: \"text/plain, */*;q=0.1\" },\n {\n kind: \"sitemap\",\n path: \"/sitemap.xml\",\n accept: \"application/xml, text/xml;q=0.9, */*;q=0.1\",\n },\n {\n kind: \"llms\",\n path: \"/llms.txt\",\n accept: \"text/plain, text/markdown;q=0.9, */*;q=0.1\",\n },\n];\n\nconst selectedHeaders = [\n \"cache-control\",\n \"cf-cache-status\",\n \"content-language\",\n \"content-length\",\n \"content-signal\",\n \"content-type\",\n \"link\",\n \"server\",\n \"vary\",\n \"x-robots-tag\",\n] as const;\n\nexport const validateTargetUrl = async (\n url: URL,\n allowPrivate: boolean,\n resolve?: HostResolver,\n): Promise<void> => {\n await resolveTargetUrl(url, allowPrivate, resolve);\n};\n\nexport const buildProbeRequests = (\n targets: ReadonlyArray<URL>,\n extraDiscovery: ReadonlyArray<{\n readonly kind: ProbeKind;\n readonly path: string;\n readonly accept: string;\n }> = [],\n): ReadonlyArray<ProbeRequest> => {\n const requests: Array<ProbeRequest> = [];\n const seenDiscoveryOrigins = new Set<string>();\n for (const target of targets) {\n requests.push(\n {\n kind: \"page-head\",\n method: \"HEAD\",\n accept: \"text/html, */*;q=0.1\",\n url: target,\n },\n {\n kind: \"page-html\",\n method: \"GET\",\n accept: \"text/html, */*;q=0.1\",\n url: target,\n },\n {\n kind: \"page-markdown\",\n method: \"GET\",\n accept: \"text/markdown, text/plain;q=0.8, */*;q=0.1\",\n url: target,\n },\n );\n if (seenDiscoveryOrigins.has(target.origin)) continue;\n seenDiscoveryOrigins.add(target.origin);\n for (const discovery of [...discoveryPaths, ...extraDiscovery]) {\n requests.push({\n kind: discovery.kind,\n method: \"GET\",\n accept: discovery.accept,\n url: new URL(discovery.path, target.origin),\n });\n }\n }\n return requests;\n};\n\nconst responseHeaders = (\n headers: IncomingHttpHeaders,\n): Readonly<Record<string, string>> => {\n const values: Record<string, string> = {};\n for (const header of selectedHeaders) {\n const value = headers[header];\n if (value !== undefined)\n values[header] = Array.isArray(value) ? value.join(\", \") : value;\n }\n return values;\n};\n\nconst attribute = (tag: string, name: string): string | null => {\n const match = new RegExp(\n `${name}\\\\s*=\\\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\\\s>]+))`,\n \"i\",\n ).exec(tag);\n return match?.[1] ?? match?.[2] ?? match?.[3] ?? null;\n};\n\nconst metaContent = (\n html: string,\n key: \"description\" | \"robots\",\n): string | null => {\n for (const match of html.matchAll(/<meta\\b[^>]*>/gi)) {\n const tag = match[0];\n if (attribute(tag, \"name\")?.toLowerCase() === key)\n return attribute(tag, \"content\");\n }\n return null;\n};\n\nconst canonicalUrl = (html: string): string | null => {\n for (const match of html.matchAll(/<link\\b[^>]*>/gi)) {\n const tag = match[0];\n if (\n (attribute(tag, \"rel\")?.toLowerCase().split(/\\s+/) ?? []).includes(\n \"canonical\",\n )\n )\n return attribute(tag, \"href\");\n }\n return null;\n};\n\nconst countMatches = (value: string, pattern: RegExp): number =>\n [...value.matchAll(pattern)].length;\n\nexport const extractDocumentSignals = (\n body: string,\n contentType: string,\n requestedUrl: URL,\n): DocumentSignals => {\n const isHtml = contentType.includes(\"text/html\");\n const isMarkdown = contentType.includes(\"text/markdown\");\n const looksJson =\n contentType.includes(\"json\") || requestedUrl.pathname.endsWith(\".json\");\n const titleMatch = isHtml\n ? /<title\\b[^>]*>([\\s\\S]*?)<\\/title>/i.exec(body)\n : null;\n let jsonValid: boolean | null = null;\n if (looksJson && body.trim().length > 0) {\n try {\n JSON.parse(body);\n jsonValid = true;\n } catch {\n jsonValid = false;\n }\n }\n return {\n title: titleMatch?.[1]?.replace(/\\s+/g, \" \").trim() ?? null,\n description: isHtml ? metaContent(body, \"description\") : null,\n canonicalUrl: isHtml ? canonicalUrl(body) : null,\n robots: isHtml ? metaContent(body, \"robots\") : null,\n jsonLdCount: isHtml\n ? countMatches(\n body,\n /<script\\b[^>]*type\\s*=\\s*[\"']application\\/ld\\+json[\"'][^>]*>/gi,\n )\n : 0,\n modulePreloadCount: isHtml\n ? countMatches(\n body,\n /<link\\b[^>]*rel\\s*=\\s*[\"'][^\"']*modulepreload[^\"']*[\"'][^>]*>/gi,\n )\n : 0,\n scriptCount: isHtml ? countMatches(body, /<script\\b/gi) : 0,\n stylesheetCount: isHtml\n ? countMatches(\n body,\n /<link\\b[^>]*rel\\s*=\\s*[\"'][^\"']*stylesheet[^\"']*[\"'][^>]*>/gi,\n )\n : 0,\n wordCount: isMarkdown\n ? body.trim().split(/\\s+/).filter(Boolean).length\n : null,\n jsonValid,\n };\n};\n\nconst readBoundedBody = async (\n response: IncomingMessage,\n maxBodyBytes: number,\n): Promise<{ readonly bytes: Uint8Array; readonly truncated: boolean }> => {\n const chunks: Array<Uint8Array> = [];\n let length = 0;\n let truncated = false;\n for await (const chunk of response) {\n const value = new Uint8Array(chunk);\n const remaining = maxBodyBytes - length;\n if (value.byteLength > remaining) {\n if (remaining > 0) chunks.push(value.slice(0, remaining));\n length += Math.max(remaining, 0);\n truncated = true;\n response.destroy();\n break;\n }\n chunks.push(value);\n length += value.byteLength;\n }\n const bytes = new Uint8Array(length);\n let offset = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return { bytes, truncated };\n};\n\nconst bodyExcerpt = (body: string, contentType: string): string | null => {\n if (contentType.includes(\"text/html\") || body.length === 0) return null;\n return [...body]\n .filter((character) => {\n const code = character.charCodeAt(0);\n return code === 9 || code === 10 || code === 13 || code >= 32;\n })\n .join(\"\")\n .slice(0, 600);\n};\n\nconst requestPinned = async (\n url: URL,\n request: ProbeRequest,\n options: ProbeOptions & { readonly resolve?: HostResolver },\n): Promise<IncomingMessage> => {\n const addresses = await resolveTargetUrl(\n url,\n options.allowPrivate,\n options.resolve,\n );\n const transport = url.protocol === \"https:\" ? requestHttps : requestHttp;\n const hostname = networkHostname(url.hostname);\n return new Promise((resolve, reject) => {\n const outgoing = transport({\n hostname,\n port: url.port || undefined,\n path: `${url.pathname}${url.search}`,\n method: request.method,\n headers: {\n accept: request.accept,\n host: url.host,\n \"user-agent\": \"pagegraph/0.4 (+https://tanstack.com)\",\n },\n agent: false,\n lookup: pinnedLookup(addresses),\n signal: AbortSignal.timeout(options.timeoutMs),\n ...(url.protocol === \"https:\"\n ? {\n servername: isIP(hostname) === 0 ? hostname : undefined,\n checkServerIdentity: (\n _host: string,\n certificate: Parameters<typeof checkServerIdentity>[1],\n ) => checkServerIdentity(hostname, certificate),\n }\n : undefined),\n });\n outgoing.once(\"response\", resolve);\n outgoing.once(\"error\", reject);\n outgoing.end();\n });\n};\n\nexport const probeHttp = async (\n request: ProbeRequest,\n options: ProbeOptions & { readonly resolve?: HostResolver },\n): Promise<HttpProbe> => {\n const startedAt = performance.now();\n const redirects: Array<string> = [];\n let headersAt: number | null = null;\n try {\n let currentUrl = request.url;\n let response: IncomingMessage | null = null;\n for (let redirectCount = 0; redirectCount <= 10; redirectCount += 1) {\n response = await requestPinned(currentUrl, request, options);\n headersAt = performance.now();\n const location = response.headers.location;\n const status = response.statusCode ?? 0;\n if (status < 300 || status >= 400 || location === undefined) break;\n if (redirectCount === 10) throw new Error(\"Redirect limit exceeded\");\n response.destroy();\n currentUrl = new URL(location, currentUrl);\n redirects.push(currentUrl.href);\n }\n if (response === null)\n throw new Error(\"Request did not produce a response\");\n const bounded =\n request.method === \"HEAD\"\n ? { bytes: new Uint8Array(), truncated: false }\n : await readBoundedBody(response, options.maxBodyBytes);\n const contentType =\n typeof response.headers[\"content-type\"] === \"string\"\n ? response.headers[\"content-type\"]\n : \"\";\n const body = new TextDecoder().decode(bounded.bytes);\n return {\n kind: request.kind,\n method: request.method,\n accept: request.accept,\n requestedUrl: request.url.href,\n finalUrl: currentUrl.href,\n redirects,\n status: response.statusCode ?? null,\n ok:\n response.statusCode !== undefined &&\n response.statusCode >= 200 &&\n response.statusCode < 300,\n headersMs:\n headersAt === null\n ? null\n : Math.round((headersAt - startedAt) * 10) / 10,\n totalMs: Math.round((performance.now() - startedAt) * 10) / 10,\n responseHeaders: responseHeaders(response.headers),\n capturedBodyBytes: bounded.bytes.byteLength,\n capturedBodySha256:\n bounded.bytes.byteLength === 0\n ? null\n : createHash(\"sha256\").update(bounded.bytes).digest(\"hex\"),\n bodyTruncated: bounded.truncated,\n bodyExcerpt: bodyExcerpt(body, contentType),\n document:\n body.length === 0\n ? null\n : extractDocumentSignals(body, contentType, currentUrl),\n error: null,\n };\n } catch (error) {\n return {\n kind: request.kind,\n method: request.method,\n accept: request.accept,\n requestedUrl: request.url.href,\n finalUrl: null,\n redirects,\n status: null,\n ok: false,\n headersMs:\n headersAt === null\n ? null\n : Math.round((headersAt - startedAt) * 10) / 10,\n totalMs: Math.round((performance.now() - startedAt) * 10) / 10,\n responseHeaders: {},\n capturedBodyBytes: 0,\n capturedBodySha256: null,\n bodyTruncated: false,\n bodyExcerpt: null,\n document: null,\n error: errorMessage(error),\n };\n }\n};\n\nexport const probeAll = async (\n requests: ReadonlyArray<ProbeRequest>,\n options: ProbeOptions & { readonly resolve?: HostResolver },\n): Promise<ReadonlyArray<HttpProbe>> => {\n const results: Array<HttpProbe | undefined> = Array.from({\n length: requests.length,\n });\n const pending = requests.map((request, index) => ({ index, request }));\n const workers = Array.from(\n { length: Math.min(4, Math.max(1, pending.length)) },\n async () => {\n while (pending.length > 0) {\n const item = pending.shift();\n if (item !== undefined)\n results[item.index] = await probeHttp(item.request, options);\n }\n },\n );\n await Promise.all(workers);\n return results.map((result, index) => {\n if (result === undefined)\n throw new Error(`Probe ${index} did not produce a result`);\n return result;\n });\n};\n\n/** Effect boundary retained at the scanner seam; failures remain per-probe data. */\nexport const probeHttpEffect = Effect.fn(\"SeoAudit.probeHttp\")(function* (\n request: ProbeRequest,\n options: ProbeOptions & { readonly resolve?: HostResolver },\n) {\n return yield* Effect.tryPromise({\n try: () => probeHttp(request, options),\n catch: (cause) =>\n new HttpProbeError({ message: errorMessage(cause), cause }),\n });\n});\n\nexport const makeHttpScanner = (\n options: ProbeOptions & {\n readonly resolve?: HostResolver;\n readonly discovery?: ReadonlyArray<{\n readonly kind: ProbeKind;\n readonly path: string;\n readonly accept: string;\n }>;\n },\n): Scanner => ({\n id: \"http\",\n description: \"HTTP metadata, discovery, and content-negotiation probes\",\n scan: (input: ScannerInput) =>\n Effect.fn(\"SeoAudit.scanHttp\")(function* () {\n const target = new URL(input.target.url);\n const evidence = yield* Effect.tryPromise({\n try: () =>\n probeAll(buildProbeRequests([target], options.discovery), options),\n catch: (cause) =>\n new ScannerFailure({\n scanner: \"http\",\n target: target.href,\n message: errorMessage(cause),\n cause,\n }),\n });\n const acquisitionErrors = evidence.flatMap((probe) =>\n probe.status === null && probe.error !== null ? [probe.error] : [],\n );\n if (acquisitionErrors.length === evidence.length) {\n return yield* new ScannerFailure({\n scanner: \"http\",\n target: target.href,\n message: `Every HTTP probe failed: ${[...new Set(acquisitionErrors)].join(\"; \")}`,\n });\n }\n return { evidence };\n })(),\n});\n","import {\n request as requestHttp,\n createServer,\n type IncomingHttpHeaders,\n} from \"node:http\";\nimport { connect, type Socket } from \"node:net\";\n\nimport {\n networkHostname,\n pinnedLookup,\n resolveTargetUrl,\n type HostResolver,\n} from \"./network\";\n\nexport interface AuditProxy {\n readonly url: string;\n readonly close: () => Promise<void>;\n}\n\nconst proxyRequestHeaders = (\n headers: IncomingHttpHeaders,\n target: URL,\n): IncomingHttpHeaders => {\n const forwarded: IncomingHttpHeaders = { ...headers, host: target.host };\n delete forwarded[\"proxy-authorization\"];\n delete forwarded[\"proxy-connection\"];\n return forwarded;\n};\n\nconst connectAuthority = (authority: string): URL => {\n const target = new URL(`http://${authority}`);\n if (\n target.username ||\n target.password ||\n target.pathname !== \"/\" ||\n target.search ||\n target.hash\n ) {\n throw new Error(\"Invalid proxy CONNECT authority\");\n }\n return target;\n};\n\nconst connectPinned = (\n target: URL,\n addresses: Awaited<ReturnType<typeof resolveTargetUrl>>,\n port: number,\n timeoutMs: number,\n track: (socket: Socket) => void,\n): Promise<Socket> =>\n new Promise((resolve, reject) => {\n const socket = connect({\n host: networkHostname(target.hostname),\n port,\n autoSelectFamily: true,\n lookup: pinnedLookup(addresses),\n });\n track(socket);\n socket.setTimeout(timeoutMs, () =>\n socket.destroy(new Error(\"Proxy connection timed out\")),\n );\n socket.once(\"connect\", () => resolve(socket));\n socket.once(\"error\", reject);\n });\n\n/**\n * Start a loopback-only validating proxy for browser scanners. Every request,\n * including CONNECT and every redirect hop, is DNS-pinned and revalidated.\n */\nexport const startAuditProxy = async (options: {\n readonly allowPrivate: boolean;\n readonly resolve?: HostResolver;\n readonly timeoutMs?: number;\n}): Promise<AuditProxy> => {\n const sockets = new Set<Socket>();\n const timeoutMs = options.timeoutMs ?? 45_000;\n let closed = false;\n let closePromise: Promise<void> | undefined;\n const track = (socket: Socket): void => {\n sockets.add(socket);\n socket.once(\"close\", () => sockets.delete(socket));\n };\n const server = createServer(async (request, response) => {\n try {\n if (request.url === undefined)\n throw new Error(\"Proxy request URL is missing\");\n const target = new URL(request.url);\n if (target.protocol !== \"http:\")\n throw new Error(\"HTTPS proxy requests must use CONNECT\");\n const addresses = await resolveTargetUrl(\n target,\n options.allowPrivate,\n options.resolve,\n );\n if (closed || request.destroyed) throw new Error(\"Audit proxy is closed\");\n const upstream = requestHttp({\n hostname: networkHostname(target.hostname),\n port: target.port || undefined,\n path: `${target.pathname}${target.search}`,\n method: request.method,\n headers: proxyRequestHeaders(request.headers, target),\n agent: false,\n lookup: pinnedLookup(addresses),\n });\n upstream.once(\"socket\", track);\n upstream.setTimeout(timeoutMs, () =>\n upstream.destroy(new Error(\"Proxy request timed out\")),\n );\n upstream.once(\"response\", (upstreamResponse) => {\n response.writeHead(\n upstreamResponse.statusCode ?? 502,\n upstreamResponse.headers,\n );\n upstreamResponse.pipe(response);\n });\n upstream.once(\"error\", (error) => {\n if (!response.headersSent)\n response.writeHead(502, { \"content-type\": \"text/plain\" });\n response.end(error.message);\n });\n request.pipe(upstream);\n } catch (error) {\n response.writeHead(403, { \"content-type\": \"text/plain\" });\n response.end(error instanceof Error ? error.message : String(error));\n }\n });\n server.on(\"connection\", track);\n server.on(\"connect\", async (request, client, head) => {\n try {\n if (request.url === undefined)\n throw new Error(\"Proxy CONNECT authority is missing\");\n const target = connectAuthority(request.url);\n const port = target.port === \"\" ? 443 : Number(target.port);\n if (!Number.isInteger(port) || port < 1 || port > 65_535) {\n throw new Error(\"Invalid proxy CONNECT port\");\n }\n const addresses = await resolveTargetUrl(\n target,\n options.allowPrivate,\n options.resolve,\n );\n if (closed || client.destroyed) throw new Error(\"Audit proxy is closed\");\n const upstream = await connectPinned(\n target,\n addresses,\n port,\n timeoutMs,\n track,\n );\n client.write(\"HTTP/1.1 200 Connection Established\\r\\n\\r\\n\");\n if (head.byteLength > 0) upstream.write(head);\n upstream.pipe(client);\n client.pipe(upstream);\n } catch (error) {\n client.end(\n `HTTP/1.1 403 Forbidden\\r\\nConnection: close\\r\\nContent-Type: text/plain\\r\\n\\r\\n${error instanceof Error ? error.message : String(error)}`,\n );\n }\n });\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(0, \"127.0.0.1\", resolve);\n });\n const address = server.address();\n if (address === null || typeof address === \"string\")\n throw new Error(\"Audit proxy did not bind\");\n return {\n url: `http://127.0.0.1:${address.port}`,\n close: () => {\n closePromise ??= new Promise<void>((resolve, reject) => {\n closed = true;\n for (const socket of sockets) socket.destroy();\n server.close((error) => (error ? reject(error) : resolve()));\n });\n return closePromise;\n },\n };\n};\n","import { spawn } from \"node:child_process\";\nimport { createRequire } from \"node:module\";\nimport { mkdtemp, readFile, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport * as Data from \"effect/Data\";\nimport * as Effect from \"effect/Effect\";\nimport * as Option from \"effect/Option\";\nimport * as Schema from \"effect/Schema\";\n\nimport type {\n FormFactor,\n LighthouseCategory,\n LighthouseMetric,\n LighthouseOpportunity,\n LighthouseRun,\n} from \"../model\";\nimport { startAuditProxy, type AuditProxy } from \"../proxy\";\nimport { ScannerFailure, type Scanner, type ScannerInput } from \"../scanner\";\n\nconst require = createRequire(import.meta.url);\nconst metricIds = [\n \"first-contentful-paint\",\n \"largest-contentful-paint\",\n \"total-blocking-time\",\n \"cumulative-layout-shift\",\n \"speed-index\",\n] as const;\ntype UnknownRecord = Readonly<Record<string, unknown>>;\nconst UnknownRecord = Schema.Record(Schema.String, Schema.Unknown);\nconst decodeUnknownRecord = Schema.decodeUnknownOption(UnknownRecord);\nconst asRecord = (value: unknown): UnknownRecord | null =>\n Option.getOrNull(decodeUnknownRecord(value));\nconst asString = (value: unknown): string | null =>\n typeof value === \"string\" ? value : null;\nconst asNumber = (value: unknown): number | null =>\n typeof value === \"number\" && Number.isFinite(value) ? value : null;\n\nexport class LighthouseError extends Data.TaggedError(\"LighthouseError\")<{\n readonly message: string;\n readonly cause?: unknown;\n}> {}\n\nconst errorMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error);\n\nconst resolveLighthouse = (): {\n readonly cli: string;\n readonly packageJson: string;\n} => {\n try {\n const packageJson = require.resolve(\"lighthouse/package.json\");\n return { packageJson, cli: require.resolve(\"lighthouse/cli/index.js\") };\n } catch (cause) {\n throw new LighthouseError({\n message:\n \"Lighthouse is not installed. Install it as an optional dependency to enable browser audits.\",\n cause,\n });\n }\n};\n\nconst parseCategories = (\n value: unknown,\n): Readonly<Record<string, LighthouseCategory>> => {\n const categories: Record<string, LighthouseCategory> = {};\n for (const [id, candidate] of Object.entries(asRecord(value) ?? {})) {\n const category = asRecord(candidate);\n if (category !== null)\n categories[id] = {\n id,\n title: asString(category.title) ?? id,\n score: asNumber(category.score),\n };\n }\n return categories;\n};\n\nconst parseMetrics = (\n auditsValue: unknown,\n): Readonly<Record<string, LighthouseMetric>> => {\n const metrics: Record<string, LighthouseMetric> = {};\n const audits = asRecord(auditsValue) ?? {};\n for (const id of metricIds) {\n const audit = asRecord(audits[id]);\n if (audit !== null)\n metrics[id] = {\n id,\n title: asString(audit.title) ?? id,\n numericValue: asNumber(audit.numericValue),\n numericUnit: asString(audit.numericUnit),\n displayValue: asString(audit.displayValue),\n score: asNumber(audit.score),\n };\n }\n return metrics;\n};\n\nconst parseOpportunities = (\n auditsValue: unknown,\n): ReadonlyArray<LighthouseOpportunity> => {\n const opportunities: Array<LighthouseOpportunity> = [];\n for (const [id, candidate] of Object.entries(asRecord(auditsValue) ?? {})) {\n const audit = asRecord(candidate);\n const details = asRecord(audit?.details);\n if (audit === null || details?.type !== \"opportunity\") continue;\n const savingsMs = asNumber(details.overallSavingsMs);\n const savingsBytes = asNumber(details.overallSavingsBytes);\n if ((savingsMs ?? 0) <= 0 && (savingsBytes ?? 0) <= 0) continue;\n opportunities.push({\n id,\n title: asString(audit.title) ?? id,\n displayValue: asString(audit.displayValue),\n savingsMs,\n savingsBytes,\n });\n }\n return opportunities.sort(\n (left, right) =>\n (right.savingsMs ?? 0) - (left.savingsMs ?? 0) ||\n (right.savingsBytes ?? 0) - (left.savingsBytes ?? 0),\n );\n};\n\nconst parseWarnings = (value: unknown): ReadonlyArray<string> =>\n Array.isArray(value)\n ? value.filter((item): item is string => typeof item === \"string\")\n : [];\n\nexport const parseLighthouseResult = (\n value: unknown,\n requestedUrl: string,\n formFactor: FormFactor,\n run: number,\n): LighthouseRun => {\n const result = asRecord(value);\n if (result === null)\n throw new LighthouseError({\n message: \"Lighthouse returned a non-object result\",\n });\n const environment = asRecord(result.environment);\n return {\n requestedUrl,\n finalUrl: asString(result.finalDisplayedUrl) ?? asString(result.finalUrl),\n formFactor,\n run,\n lighthouseVersion: asString(result.lighthouseVersion),\n userAgent: asString(environment?.hostUserAgent),\n fetchTime: asString(result.fetchTime),\n categories: parseCategories(result.categories),\n metrics: parseMetrics(result.audits),\n opportunities: parseOpportunities(result.audits),\n warnings: parseWarnings(result.runWarnings),\n error: null,\n };\n};\n\nexport const lighthouseVersion = async (): Promise<string | null> => {\n try {\n const { packageJson } = resolveLighthouse();\n const value: unknown = JSON.parse(await readFile(packageJson, \"utf8\"));\n return asString(asRecord(value)?.version);\n } catch {\n return null;\n }\n};\n\nexport const lighthouseChromeFlags = (proxyUrl: string): string =>\n [\n \"--headless=new\",\n `--proxy-server=${proxyUrl}`,\n \"--proxy-bypass-list=<-loopback>\",\n \"--disable-quic\",\n \"--force-webrtc-ip-handling-policy=disable_non_proxied_udp\",\n ].join(\" \");\n\nexport const windowsProcessTreeKill = (\n pid: number,\n): { readonly command: string; readonly arguments: readonly string[] } => ({\n command: \"taskkill\",\n arguments: [\"/pid\", String(pid), \"/T\", \"/F\"],\n});\n\nexport const runLighthouseProcess = async (\n cli: string,\n arguments_: ReadonlyArray<string>,\n timeoutMs: number,\n killGraceMs = 1_000,\n): Promise<void> => {\n const child = spawn(process.execPath, [cli, ...arguments_], {\n detached: process.platform !== \"win32\",\n stdio: [\"ignore\", \"ignore\", \"pipe\"],\n });\n let stderr = \"\";\n child.stderr.setEncoding(\"utf8\");\n child.stderr.on(\"data\", (chunk: string) => {\n if (stderr.length < 16_000) stderr += chunk;\n });\n const signal = (name: NodeJS.Signals): void => {\n if (child.pid === undefined) return;\n if (process.platform === \"win32\") {\n const taskkill = windowsProcessTreeKill(child.pid);\n const killer = spawn(taskkill.command, taskkill.arguments, {\n stdio: \"ignore\",\n windowsHide: true,\n });\n const fallback = () => {\n try {\n child.kill(\"SIGKILL\");\n } catch {\n // The process already exited between the timeout and escalation.\n }\n };\n killer.once(\"error\", fallback);\n killer.once(\"exit\", (code) => {\n if (code !== 0) fallback();\n });\n return;\n }\n try {\n process.kill(-child.pid, name);\n } catch {\n child.kill(name);\n }\n };\n let timedOut = false;\n let forceKill: ReturnType<typeof setTimeout> | undefined;\n let abandon: ReturnType<typeof setTimeout> | undefined;\n let timeout: ReturnType<typeof setTimeout> | undefined;\n const exitCode = await new Promise<number>((resolveExit, reject) => {\n timeout = setTimeout(() => {\n timedOut = true;\n signal(\"SIGTERM\");\n forceKill = setTimeout(() => signal(\"SIGKILL\"), killGraceMs);\n abandon = setTimeout(\n () =>\n reject(\n new LighthouseError({\n message: `Lighthouse timed out after ${timeoutMs}ms and did not exit after SIGKILL`,\n }),\n ),\n killGraceMs * 2,\n );\n }, timeoutMs);\n child.once(\"error\", reject);\n child.once(\"exit\", (code) => resolveExit(code ?? 1));\n }).finally(() => {\n if (timeout !== undefined) clearTimeout(timeout);\n if (forceKill !== undefined) clearTimeout(forceKill);\n if (abandon !== undefined) clearTimeout(abandon);\n });\n if (timedOut)\n throw new LighthouseError({\n message: `Lighthouse timed out after ${timeoutMs}ms`,\n });\n if (exitCode !== 0)\n throw new LighthouseError({\n message: `Lighthouse exited with ${exitCode}${stderr.trim() ? `: ${stderr.trim()}` : \"\"}`,\n });\n};\n\nexport interface LighthouseOptions {\n readonly url: URL;\n readonly formFactor: FormFactor;\n readonly run: number;\n readonly allowPrivate: boolean;\n readonly timeoutMs?: number;\n}\n\nconst runLighthouseInDirectory = async (\n options: LighthouseOptions,\n directory: string,\n): Promise<LighthouseRun> => {\n const version = await lighthouseVersion();\n const base = {\n requestedUrl: options.url.href,\n finalUrl: null,\n formFactor: options.formFactor,\n run: options.run,\n lighthouseVersion: version,\n userAgent: null,\n fetchTime: null,\n categories: {},\n metrics: {},\n opportunities: [],\n warnings: [],\n };\n let proxy: AuditProxy | undefined;\n try {\n const { cli } = resolveLighthouse();\n const output = join(directory, \"result.json\");\n proxy = await startAuditProxy({\n allowPrivate: options.allowPrivate,\n timeoutMs: options.timeoutMs ?? 180_000,\n });\n const args = [\n options.url.href,\n \"--output=json\",\n `--output-path=${output}`,\n \"--quiet\",\n \"--max-wait-for-load=45000\",\n `--chrome-flags=${lighthouseChromeFlags(proxy.url)}`,\n ];\n if (options.formFactor === \"desktop\") args.push(\"--preset=desktop\");\n await runLighthouseProcess(cli, args, options.timeoutMs ?? 180_000);\n return parseLighthouseResult(\n JSON.parse(await readFile(output, \"utf8\")),\n options.url.href,\n options.formFactor,\n options.run,\n );\n } catch (error) {\n return { ...base, error: errorMessage(error) };\n } finally {\n await proxy?.close();\n }\n};\n\nexport const runLighthouse = async (\n options: LighthouseOptions,\n): Promise<LighthouseRun> => {\n let directory: string | undefined;\n try {\n directory = await mkdtemp(join(tmpdir(), \"tanstack-seo-lighthouse-\"));\n return await runLighthouseInDirectory(options, directory);\n } finally {\n if (directory !== undefined)\n await rm(directory, { recursive: true, force: true });\n }\n};\n\nexport const runLighthouseEffect = Effect.fn(\"SeoAudit.runLighthouse\")(\n function* (options: LighthouseOptions) {\n const directory = yield* Effect.acquireRelease(\n Effect.tryPromise({\n try: () => mkdtemp(join(tmpdir(), \"tanstack-seo-lighthouse-\")),\n catch: (cause) =>\n new LighthouseError({ message: errorMessage(cause), cause }),\n }),\n (path) =>\n Effect.promise(() => rm(path, { recursive: true, force: true })),\n );\n return yield* Effect.tryPromise({\n try: () => runLighthouseInDirectory(options, directory),\n catch: (cause) =>\n new LighthouseError({ message: errorMessage(cause), cause }),\n });\n },\n);\n\nexport const makeLighthouseScanner = (\n options: Omit<LighthouseOptions, \"url\" | \"formFactor\" | \"run\">,\n dependencies: {\n readonly run?: (options: LighthouseOptions) => Promise<LighthouseRun>;\n } = {},\n): Scanner => ({\n id: \"lighthouse\",\n description: \"Lighthouse performance and accessibility measurements\",\n scan: (input: ScannerInput) =>\n Effect.fn(\"SeoAudit.scanLighthouse\")(function* () {\n const target = new URL(input.target.url);\n const requestedFormFactors =\n input.options.formFactors === undefined ||\n input.options.formFactors.length === 0\n ? ([\"mobile\"] as const)\n : input.options.formFactors;\n const requestedRuns = Math.max(1, Math.floor(input.options.runs ?? 1));\n const runs = [...new Set(requestedFormFactors)].flatMap((formFactor) =>\n Array.from({ length: requestedRuns }, (_, index) => ({\n formFactor,\n run: index + 1,\n })),\n );\n const observations = yield* Effect.forEach(\n runs,\n ({ formFactor, run }) =>\n Effect.tryPromise({\n try: () =>\n (dependencies.run ?? runLighthouse)({\n ...options,\n url: target,\n formFactor,\n run,\n }),\n catch: (cause) =>\n new ScannerFailure({\n scanner: \"lighthouse\",\n target: target.href,\n message: errorMessage(cause),\n cause,\n }),\n }),\n { concurrency: 1 },\n );\n const errors = observations.flatMap((observation) =>\n observation.error === null ? [] : [observation.error],\n );\n if (errors.length === observations.length) {\n return yield* new ScannerFailure({\n scanner: \"lighthouse\",\n target: target.href,\n message: errors[0] ?? \"Every Lighthouse run failed.\",\n });\n }\n return { evidence: observations };\n })(),\n});\n","import type { IncomingMessage } from \"node:http\";\nimport { request as requestHttp } from \"node:http\";\nimport { request as requestHttps } from \"node:https\";\nimport { isIP } from \"node:net\";\nimport { checkServerIdentity } from \"node:tls\";\n\nimport * as Data from \"effect/Data\";\nimport * as Effect from \"effect/Effect\";\nimport * as Option from \"effect/Option\";\nimport * as Schema from \"effect/Schema\";\n\nimport { networkHostname, pinnedLookup, resolveTargetUrl } from \"../network\";\nimport { ScannerFailure, type Scanner } from \"../scanner\";\n\n/** Hosted services are intentionally opt-in: a generic SEO audit never sends URLs to them. */\nexport interface HostedScannerOrigins {\n readonly isitagentready: string;\n readonly isAgentic: string;\n}\n\nexport const defaultHostedScannerOrigins: HostedScannerOrigins = {\n isitagentready: \"https://isitagentready.com\",\n isAgentic: \"https://is-agentic.com\",\n};\n\nexport interface HostedScannerOptions {\n readonly allowPrivate: boolean;\n /** Whether a private target URL may be disclosed to the hosted service. Defaults to false. */\n readonly allowPrivateTargets?: boolean;\n readonly timeoutMs: number;\n readonly maxBodyBytes: number;\n readonly origins: HostedScannerOrigins;\n}\n\nexport interface HostedScannerReport {\n readonly scanner: \"isitagentready\" | \"is-agentic\";\n readonly target: string;\n readonly requestedUrl: string;\n readonly reportUrl: string | null;\n readonly scannedAt: string | null;\n readonly score: number | null;\n readonly scoreLabel: string | null;\n readonly level: number | null;\n readonly levelName: string | null;\n readonly summary: string | null;\n readonly checks: ReadonlyArray<{\n readonly id: string;\n readonly category: string | null;\n readonly status: string;\n readonly message: string | null;\n }>;\n readonly findings: ReadonlyArray<{\n readonly result: string;\n readonly tier: string | null;\n readonly name: string;\n readonly details: string | null;\n readonly recommendation: string | null;\n }>;\n readonly totalMs: number;\n readonly error: string | null;\n}\n\nexport class HostedScannerError extends Data.TaggedError(\"HostedScannerError\")<{\n readonly message: string;\n readonly cause?: unknown;\n}> {}\n\nconst errorMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error);\nconst userAgent = \"TanStackSeoAudit/1.0\";\n\nconst IsitagentreadyCheck = Schema.Struct({\n status: Schema.String,\n message: Schema.optionalKey(Schema.String),\n});\nconst IsitagentreadyPayload = Schema.Struct({\n scannedAt: Schema.optionalKey(Schema.String),\n scanned_at: Schema.optionalKey(Schema.String),\n level: Schema.optionalKey(Schema.Finite),\n levelName: Schema.optionalKey(Schema.String),\n level_name: Schema.optionalKey(Schema.String),\n checks: Schema.optionalKey(\n Schema.Record(\n Schema.String,\n Schema.Record(Schema.String, IsitagentreadyCheck),\n ),\n ),\n nextLevel: Schema.optionalKey(\n Schema.Struct({\n name: Schema.optionalKey(Schema.String),\n requirements: Schema.optionalKey(\n Schema.Array(\n Schema.Struct({\n check: Schema.optionalKey(Schema.String),\n description: Schema.optionalKey(Schema.String),\n prompt: Schema.optionalKey(Schema.String),\n }),\n ),\n ),\n }),\n ),\n next_level: Schema.optionalKey(\n Schema.Struct({\n name: Schema.optionalKey(Schema.String),\n requirements: Schema.optionalKey(\n Schema.Array(\n Schema.Struct({\n check: Schema.optionalKey(Schema.String),\n description: Schema.optionalKey(Schema.String),\n prompt: Schema.optionalKey(Schema.String),\n }),\n ),\n ),\n }),\n ),\n});\nconst IsAgenticPayload = Schema.Struct({\n score: Schema.optionalKey(Schema.Finite),\n score_label: Schema.optionalKey(Schema.String),\n report_url: Schema.optionalKey(Schema.String),\n scanned_at: Schema.optionalKey(Schema.String),\n score_breakdown: Schema.optionalKey(\n Schema.Struct({\n essential: Schema.optionalKey(\n Schema.Struct({ earned: Schema.Finite, available: Schema.Finite }),\n ),\n recommended: Schema.optionalKey(\n Schema.Struct({ earned: Schema.Finite, available: Schema.Finite }),\n ),\n }),\n ),\n issues: Schema.optionalKey(\n Schema.Array(\n Schema.Struct({\n result: Schema.String,\n tier: Schema.optionalKey(Schema.String),\n name: Schema.String,\n details: Schema.optionalKey(Schema.String),\n recommendation: Schema.optionalKey(Schema.String),\n }),\n ),\n ),\n});\nconst SseEvent = Schema.Struct({ type: Schema.String });\nconst IsitagentreadyJson = Schema.fromJsonString(IsitagentreadyPayload);\nconst IsAgenticJson = Schema.fromJsonString(IsAgenticPayload);\nconst SseEventJson = Schema.fromJsonString(SseEvent);\nconst decodeIsitagentready = Schema.decodeUnknownSync(IsitagentreadyPayload);\nconst decodeIsAgentic = Schema.decodeUnknownSync(IsAgenticPayload);\nconst decodeIsitagentreadyJson = Schema.decodeUnknownEffect(IsitagentreadyJson);\nconst decodeIsAgenticJson = Schema.decodeUnknownEffect(IsAgenticJson);\nconst decodeSseEventJson = Schema.decodeUnknownOption(SseEventJson);\n\nconst enabledChecks = [\n \"robotsTxt\",\n \"sitemap\",\n \"linkHeaders\",\n \"dnsAid\",\n \"markdownNegotiation\",\n \"robotsTxtAiRules\",\n \"contentSignals\",\n \"webBotAuth\",\n \"apiCatalog\",\n \"oauthDiscovery\",\n \"oauthProtectedResource\",\n \"authMd\",\n \"mcpServerCard\",\n \"agentSkills\",\n \"webMcp\",\n \"ard\",\n \"x402\",\n \"mpp\",\n \"ucp\",\n \"acp\",\n] as const;\nconst encodeRequest = Schema.encodeSync(\n Schema.fromJsonString(\n Schema.Struct({\n url: Schema.String,\n enabledChecks: Schema.Array(Schema.Literals(enabledChecks)),\n }),\n ),\n);\n\nexport const parseSseDataFrames = (\n buffer: string,\n): {\n readonly events: ReadonlyArray<{ readonly type: string }>;\n readonly rest: string;\n} => {\n let rest = buffer.replaceAll(\"\\r\\n\", \"\\n\");\n const events: Array<{ readonly type: string }> = [];\n let boundary = rest.indexOf(\"\\n\\n\");\n while (boundary !== -1) {\n const frame = rest.slice(0, boundary);\n rest = rest.slice(boundary + 2);\n const data = frame\n .split(\"\\n\")\n .filter((line) => line.startsWith(\"data:\"))\n .map((line) => line.slice(5).trimStart())\n .join(\"\\n\");\n if (data.length > 0) {\n const event = Option.getOrNull(decodeSseEventJson(data));\n if (event !== null) events.push(event);\n }\n boundary = rest.indexOf(\"\\n\\n\");\n }\n return { events, rest };\n};\n\nconst pinnedResponse = async (request: {\n readonly method: \"GET\" | \"POST\";\n readonly url: URL;\n readonly headers: Readonly<Record<string, string>>;\n readonly body?: string;\n readonly allowPrivate: boolean;\n readonly timeoutMs: number;\n}): Promise<IncomingMessage> => {\n const addresses = await resolveTargetUrl(request.url, request.allowPrivate);\n const transport =\n request.url.protocol === \"https:\" ? requestHttps : requestHttp;\n const hostname = networkHostname(request.url.hostname);\n const headers: Record<string, string | number> = {\n ...request.headers,\n host: request.url.host,\n \"user-agent\": userAgent,\n };\n if (request.body !== undefined)\n headers[\"content-length\"] = Buffer.byteLength(request.body);\n return new Promise((resolve, reject) => {\n const outgoing = transport({\n hostname,\n port: request.url.port || undefined,\n path: `${request.url.pathname}${request.url.search}`,\n method: request.method,\n headers,\n agent: false,\n lookup: pinnedLookup(addresses),\n signal: AbortSignal.timeout(request.timeoutMs),\n ...(request.url.protocol === \"https:\"\n ? {\n servername: isIP(hostname) === 0 ? hostname : undefined,\n checkServerIdentity: (\n _host: string,\n certificate: Parameters<typeof checkServerIdentity>[1],\n ) => checkServerIdentity(hostname, certificate),\n }\n : undefined),\n });\n outgoing.once(\"response\", resolve);\n outgoing.once(\"error\", reject);\n outgoing.end(request.body);\n });\n};\n\nconst readBody = async (\n response: IncomingMessage,\n maxBodyBytes: number,\n): Promise<string> => {\n const chunks: Array<Uint8Array> = [];\n let length = 0;\n for await (const chunk of response) {\n const value = new Uint8Array(chunk);\n if (length + value.byteLength > maxBodyBytes) {\n response.destroy();\n throw new Error(\"Hosted scanner response exceeded byte limit\");\n }\n chunks.push(value);\n length += value.byteLength;\n }\n const bytes = new Uint8Array(length);\n let offset = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, offset);\n offset += chunk.byteLength;\n }\n const body = new TextDecoder().decode(bytes);\n if (body.trim().length === 0)\n throw new Error(\"Hosted scanner returned an empty body\");\n return body;\n};\n\nconst consumeStream = async (\n response: IncomingMessage,\n maxBodyBytes: number,\n): Promise<void> => {\n let buffer = \"\";\n let length = 0;\n let complete = false;\n const decoder = new TextDecoder();\n try {\n for await (const chunk of response) {\n const value = new Uint8Array(chunk);\n length += value.byteLength;\n if (length > maxBodyBytes)\n throw new Error(\"Hosted scanner stream exceeded byte limit\");\n // Keep decoder state across chunks: SSE payloads may split a UTF-8\n // codepoint at any byte boundary.\n buffer += decoder.decode(value, { stream: true });\n const parsed = parseSseDataFrames(buffer);\n buffer = parsed.rest;\n if (parsed.events.some((event) => event.type === \"error\"))\n throw new Error(\"is-agentic scan failed\");\n if (\n parsed.events.some(\n (event) =>\n event.type === \"scan_complete\" || event.type === \"scan_archived\",\n )\n ) {\n complete = true;\n response.destroy();\n break;\n }\n }\n } catch (cause) {\n if (complete) return;\n throw cause;\n }\n buffer += decoder.decode();\n if (!complete)\n throw new Error(\"is-agentic scan ended before a report was available\");\n};\n\nconst originHeader = (\n origin: string,\n path: string,\n): { readonly origin: string; readonly referer: string } => {\n const base = origin.replace(/\\/$/, \"\");\n return { origin: base, referer: `${base}${path}` };\n};\nconst complete = (\n parsed: Omit<HostedScannerReport, \"requestedUrl\" | \"totalMs\" | \"error\">,\n requestedUrl: string,\n startedAt: number,\n): HostedScannerReport => ({\n ...parsed,\n requestedUrl,\n totalMs: Math.round((performance.now() - startedAt) * 10) / 10,\n error: null,\n});\nconst failed = (\n scanner: HostedScannerReport[\"scanner\"],\n target: URL,\n requestedUrl: string,\n startedAt: number,\n error: unknown,\n): HostedScannerReport => ({\n scanner,\n target: target.href,\n requestedUrl,\n reportUrl: null,\n scannedAt: null,\n score: null,\n scoreLabel: null,\n level: null,\n levelName: null,\n summary: null,\n checks: [],\n findings: [],\n totalMs: Math.round((performance.now() - startedAt) * 10) / 10,\n error: errorMessage(error),\n});\n\nconst parseIsitagentready = (\n payload: unknown,\n target: URL,\n origin: string,\n): Omit<HostedScannerReport, \"requestedUrl\" | \"totalMs\" | \"error\"> => {\n const record = decodeIsitagentready(payload);\n const checks = Object.entries(record.checks ?? {}).flatMap(\n ([category, group]) =>\n Object.entries(group).map(([id, check]) => ({\n id,\n category,\n status: check.status,\n message: check.message ?? null,\n })),\n );\n const passed = checks.filter((check) => check.status === \"pass\").length;\n const failedCount = checks.filter((check) => check.status === \"fail\").length;\n const level = record.level ?? null;\n const levelName = record.levelName ?? record.level_name ?? null;\n const next = record.nextLevel ?? record.next_level;\n const findings = (next?.requirements ?? []).flatMap((requirement) => {\n const name = requirement.check ?? requirement.description;\n return name === undefined\n ? []\n : [\n {\n result: \"missing\",\n tier: next?.name ?? null,\n name,\n details: requirement.description ?? null,\n recommendation: requirement.prompt ?? null,\n },\n ];\n });\n return {\n scanner: \"isitagentready\",\n target: target.href,\n reportUrl: `${origin.replace(/\\/$/, \"\")}/${target.hostname}`,\n scannedAt: record.scannedAt ?? record.scanned_at ?? null,\n score: null,\n scoreLabel: null,\n level,\n levelName,\n summary:\n level === null && levelName === null\n ? `${passed} pass, ${failedCount} fail`\n : `Level ${level ?? \"?\"} ${levelName ?? \"\"}`.trim() +\n `, ${passed} pass, ${failedCount} fail`,\n checks,\n findings,\n };\n};\n\nconst parseIsAgentic = (\n payload: unknown,\n target: URL,\n): Omit<HostedScannerReport, \"requestedUrl\" | \"totalMs\" | \"error\"> => {\n const record = decodeIsAgentic(payload);\n const findings = (record.issues ?? []).map((issue) => ({\n result: issue.result,\n tier: issue.tier ?? null,\n name: issue.name,\n details: issue.details ?? null,\n recommendation: issue.recommendation ?? null,\n }));\n const failedCount = findings.filter(\n (finding) => finding.result === \"failed\",\n ).length;\n const partial = findings.filter(\n (finding) => finding.result === \"partial\",\n ).length;\n const bucket = (\n label: string,\n value: { readonly earned: number; readonly available: number } | undefined,\n ) =>\n value === undefined ? null : `${label} ${value.earned}/${value.available}`;\n return {\n scanner: \"is-agentic\",\n target: target.href,\n reportUrl: record.report_url ?? null,\n scannedAt: record.scanned_at ?? null,\n score: record.score ?? null,\n scoreLabel: record.score_label ?? null,\n level: null,\n levelName: null,\n summary: [\n record.score_label,\n bucket(\"Essential\", record.score_breakdown?.essential),\n bucket(\"Recommended\", record.score_breakdown?.recommended),\n `${failedCount} failed, ${partial} partial`,\n ]\n .filter(\n (part): part is string =>\n part !== null && part !== undefined && part.length > 0,\n )\n .join(\", \"),\n checks: [],\n findings,\n };\n};\n\nconst scanIsAgentic = Effect.fn(\"SeoAudit.scanHostedIsAgentic\")(function* (\n target: URL,\n options: HostedScannerOptions,\n) {\n const requested = new URL(\"/api/scan/stream\", options.origins.isAgentic);\n requested.searchParams.set(\"target\", target.href);\n requested.searchParams.set(\"force\", \"1\");\n const headers = originHeader(\n options.origins.isAgentic,\n `/scan/${target.hostname}`,\n );\n const response = yield* Effect.tryPromise({\n try: () =>\n pinnedResponse({\n method: \"GET\",\n url: requested,\n headers: {\n accept: \"text/event-stream\",\n \"cache-control\": \"no-cache\",\n pragma: \"no-cache\",\n ...headers,\n },\n allowPrivate: options.allowPrivate,\n timeoutMs: options.timeoutMs,\n }),\n catch: (cause) =>\n new HostedScannerError({ message: errorMessage(cause), cause }),\n });\n const status = response.statusCode ?? 0;\n if (status < 200 || status >= 300) {\n const retry = response.headers[\"retry-after\"];\n response.destroy();\n return yield* new HostedScannerError({\n message: `is-agentic.com scan stream returned HTTP ${status}${typeof retry === \"string\" ? `, retry after ${retry}s` : \"\"}`,\n });\n }\n yield* Effect.tryPromise({\n try: () => consumeStream(response, options.maxBodyBytes),\n catch: (cause) =>\n new HostedScannerError({ message: errorMessage(cause), cause }),\n });\n const report = new URL(\"/api/v1/report\", options.origins.isAgentic);\n report.searchParams.set(\"url\", target.href);\n let lastError = new HostedScannerError({\n message: \"is-agentic report is not available yet\",\n });\n for (let attempt = 0; attempt < 5; attempt += 1) {\n const reportResponse = yield* Effect.tryPromise({\n try: () =>\n pinnedResponse({\n method: \"GET\",\n url: report,\n headers: { accept: \"application/json\" },\n allowPrivate: options.allowPrivate,\n timeoutMs: options.timeoutMs,\n }),\n catch: (cause) =>\n new HostedScannerError({ message: errorMessage(cause), cause }),\n });\n const reportStatus = reportResponse.statusCode ?? 0;\n const body = yield* Effect.tryPromise({\n try: () => readBody(reportResponse, options.maxBodyBytes),\n catch: (cause) =>\n new HostedScannerError({ message: errorMessage(cause), cause }),\n });\n if (reportStatus >= 200 && reportStatus < 300) {\n const payload = yield* decodeIsAgenticJson(body).pipe(\n Effect.mapError(\n (cause) =>\n new HostedScannerError({ message: errorMessage(cause), cause }),\n ),\n );\n return { requested, parsed: parseIsAgentic(payload, target) };\n }\n lastError = new HostedScannerError({\n message: `is-agentic report returned HTTP ${reportStatus}`,\n });\n yield* Effect.sleep(`${250 * (attempt + 1)} millis`);\n }\n return yield* lastError;\n});\n\nconst scanIsitagentready = Effect.fn(\"SeoAudit.scanHostedIsitagentready\")(\n function* (target: URL, options: HostedScannerOptions) {\n const requested = new URL(\"/api/scan\", options.origins.isitagentready);\n const headers = originHeader(\n options.origins.isitagentready,\n `/${target.hostname}`,\n );\n const response = yield* Effect.tryPromise({\n try: () =>\n pinnedResponse({\n method: \"POST\",\n url: requested,\n headers: {\n accept: \"application/json\",\n \"content-type\": \"application/json\",\n ...headers,\n },\n body: encodeRequest({\n url: target.href,\n enabledChecks: [...enabledChecks],\n }),\n allowPrivate: options.allowPrivate,\n timeoutMs: options.timeoutMs,\n }),\n catch: (cause) =>\n new HostedScannerError({ message: errorMessage(cause), cause }),\n });\n const status = response.statusCode ?? 0;\n if (status < 200 || status >= 300) {\n response.destroy();\n return yield* new HostedScannerError({\n message: `isitagentready.com returned HTTP ${status}`,\n });\n }\n const body = yield* Effect.tryPromise({\n try: () => readBody(response, options.maxBodyBytes),\n catch: (cause) =>\n new HostedScannerError({ message: errorMessage(cause), cause }),\n });\n const payload = yield* decodeIsitagentreadyJson(body).pipe(\n Effect.mapError(\n (cause) =>\n new HostedScannerError({ message: errorMessage(cause), cause }),\n ),\n );\n return {\n requested,\n parsed: parseIsitagentready(\n payload,\n target,\n options.origins.isitagentready,\n ),\n };\n },\n);\n\n/** Opt-in hosted scanners. Results are attributed failures, never fatal audit failures. */\nexport const scanHosted = async (\n target: URL,\n options: HostedScannerOptions,\n): Promise<ReadonlyArray<HostedScannerReport>> => {\n const output: Array<HostedScannerReport> = [];\n const readyStartedAt = performance.now();\n try {\n const result = await Effect.runPromise(scanIsitagentready(target, options));\n output.push(complete(result.parsed, result.requested.href, readyStartedAt));\n } catch (error) {\n output.push(\n failed(\n \"isitagentready\",\n target,\n new URL(\"/api/scan\", options.origins.isitagentready).href,\n readyStartedAt,\n error,\n ),\n );\n }\n const agenticStartedAt = performance.now();\n try {\n const result = await Effect.runPromise(scanIsAgentic(target, options));\n output.push(\n complete(result.parsed, result.requested.href, agenticStartedAt),\n );\n } catch (error) {\n output.push(\n failed(\n \"is-agentic\",\n target,\n new URL(\"/api/scan/stream\", options.origins.isAgentic).href,\n agenticStartedAt,\n error,\n ),\n );\n }\n return output;\n};\n\nexport const makeHostedScanner = (options: HostedScannerOptions): Scanner => ({\n id: \"hosted\",\n description: \"Opt-in external agent-readiness reports\",\n scan: (input) =>\n Effect.fn(\"SeoAudit.scanHosted\")(function* () {\n const target = new URL(input.target.url);\n if (options.allowPrivateTargets !== true) {\n yield* Effect.tryPromise({\n try: () => resolveTargetUrl(target, false),\n catch: (cause) =>\n new ScannerFailure({\n scanner: \"hosted\",\n target: target.href,\n message: \"Hosted scanners only accept public target URLs.\",\n cause,\n }),\n });\n }\n const evidence = yield* Effect.tryPromise({\n try: () => scanHosted(target, options),\n // Individual hosted service failures are already represented in the\n // report. This boundary only captures an unexpected orchestration error.\n catch: (cause) =>\n new ScannerFailure({\n scanner: \"hosted\",\n target: target.href,\n message: errorMessage(cause),\n cause,\n }),\n });\n if (evidence.every((report) => report.error !== null)) {\n return yield* new ScannerFailure({\n scanner: \"hosted\",\n target: target.href,\n message: evidence.map((report) => report.error).join(\"; \"),\n });\n }\n return { evidence };\n })(),\n});\n"],"mappings":"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"}
|