@brandlab-digital/conformance 3.3.1 → 3.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -43,6 +43,7 @@ export function inspectStaticRules(context) {
43
43
  inspectRetiredConfiguration(context);
44
44
  inspectWorkflowPins(context);
45
45
  inspectVercelIgnore(context);
46
+ inspectImageRemotePatterns(context);
46
47
  }
47
48
  /** Capabilities declared by brandlab.config.ts, the contact route and the location data. */
48
49
  export function describeCapabilities(root, config) {
@@ -725,6 +726,181 @@ function inspectVercelIgnore(context) {
725
726
  remediation: "Remove the package manifest and lockfile patterns from .vercelignore.",
726
727
  }));
727
728
  }
729
+ // --- runtime: image remote patterns (3.3.3) -----------------------------------
730
+ const NEXT_CONFIG_FILES = ["next.config.ts", "next.config.mts", "next.config.mjs", "next.config.js"];
731
+ /**
732
+ * next.config's images.remotePatterns, as the optimiser will fetch them: from 3.3.3 a
733
+ * production build refuses an http, protocol-less or local source, or a wildcard host that
734
+ * admits a local address (blocker: next build would fail), and any other wildcard host or a
735
+ * pattern for every path of a third-party host is
736
+ * reported as a warning (the optimiser fetches such images for anyone who asks:
737
+ * GHSA-cjq9-62q9-8jv4, usage cost). Spreads and conditional entries are the site's own
738
+ * gating and are left alone; images.developmentRemotePatterns is for next dev only.
739
+ */
740
+ function inspectImageRemotePatterns(context) {
741
+ const path = NEXT_CONFIG_FILES.find((candidate) => context.source.byPath.has(candidate));
742
+ const file = path ? context.source.byPath.get(path) : undefined;
743
+ if (!path || !file)
744
+ return;
745
+ const calls = findImportedCalls(file, SITE_NEXT("next-config"), "defineBrandlabNextConfig");
746
+ if (calls.length === 0)
747
+ return;
748
+ const ruleId = "brandlab-runtime-image-remote-patterns";
749
+ recordEvaluation(context.evaluations, "runtime", ruleId);
750
+ const ownHosts = canonicalHosts(context);
751
+ for (const call of calls) {
752
+ const images = sameFileObject(file, propertyExpression(unwrapExpression(call.arguments[0]), "images"));
753
+ const patterns = sameFileArray(file, propertyExpression(images, "remotePatterns"));
754
+ if (!patterns)
755
+ continue;
756
+ patterns.elements.forEach((element, index) => {
757
+ const pattern = unwrapExpression(element);
758
+ if (!pattern || !ts.isObjectLiteralExpression(pattern))
759
+ return;
760
+ const protocolNode = unwrapExpression(objectPropertyValue(pattern, "protocol"));
761
+ const hostname = stringLiteralValue(unwrapExpression(objectPropertyValue(pattern, "hostname")));
762
+ const pathnameNode = unwrapExpression(objectPropertyValue(pattern, "pathname"));
763
+ const pathname = pathnameNode ? stringLiteralValue(pathnameNode) : undefined;
764
+ // A computed host, protocol or path cannot be judged here; defineBrandlabNextConfig checks it at build time.
765
+ if (hostname === null || (protocolNode && stringLiteralValue(protocolNode) === null) || pathname === null)
766
+ return;
767
+ const protocol = protocolNode ? stringLiteralValue(protocolNode) : undefined;
768
+ const shown = `${protocol ?? "any protocol"}://${hostname}${pathname === undefined ? "/**" : pathname.startsWith("/") ? pathname : `/${pathname}`}`;
769
+ const at = { ruleId, surface: "runtime", path, line: lineOfNode(file, pattern) };
770
+ if (protocol !== "https" || isLocalImageHost(hostname)) {
771
+ context.findings.push(staticFinding({
772
+ ...at,
773
+ expected: "Remote image sources a production build fetches are https on public hosts",
774
+ actual: `images.remotePatterns[${index}] allows ${shown}: from 3.3.3 a production build refuses an image source that uses http, names no protocol, or names or admits a local address, so next build fails.`,
775
+ remediation: "Remove the pattern, name the exact public hosts instead of a wildcard that admits local addresses, or move a development-only source (such as http://localhost) to images.developmentRemotePatterns, which only next dev uses.",
776
+ }));
777
+ return;
778
+ }
779
+ const wildcardHost = hostname.includes("*");
780
+ const everyPath = pathname === undefined || /^\/?\*\*$/.test(pathname);
781
+ if (!wildcardHost && (!everyPath || ownHosts.has(hostname.toLowerCase())))
782
+ return;
783
+ context.findings.push(staticFinding({
784
+ ...at,
785
+ severity: "warning",
786
+ expected: "Remote image patterns name the hosts and paths the site's images come from",
787
+ actual: wildcardHost
788
+ ? `images.remotePatterns[${index}] (${shown}) lets the image optimiser fetch from every host matching ${hostname}, for anyone who asks.`
789
+ : `images.remotePatterns[${index}] (${shown}) lets the image optimiser fetch any path on ${hostname}, for anyone who asks.`,
790
+ remediation: wildcardHost
791
+ ? "List the exact hosts the site's images come from, or serve local copies under public/."
792
+ : "Narrow pathname to the folders the site's images use (for example /vi/** or /images/**), or serve local copies under public/.",
793
+ }));
794
+ });
795
+ }
796
+ }
797
+ /** The site's canonical host and its www twin, from the defineBrandlabSite call in src/config/site.ts. */
798
+ function canonicalHosts(context) {
799
+ const hosts = new Set();
800
+ for (const file of context.source.files) {
801
+ for (const call of findImportedCalls(file, SITE_CORE("site"), "defineBrandlabSite")) {
802
+ const url = stringLiteralValue(unwrapExpression(objectPropertyValue(unwrapExpression(call.arguments[0]), "canonicalUrl")));
803
+ if (!url)
804
+ continue;
805
+ try {
806
+ const host = new URL(url).hostname.toLowerCase();
807
+ hosts.add(host);
808
+ hosts.add(host.startsWith("www.") ? host.slice(4) : `www.${host}`);
809
+ }
810
+ catch {
811
+ // not a URL: nothing to exempt
812
+ }
813
+ }
814
+ }
815
+ return hosts;
816
+ }
817
+ /** Loopback, unspecified, private, shared and link-local hosts in any URL spelling, and wildcard hosts that admit one, as defineBrandlabNextConfig refuses them. */
818
+ export function isLocalImageHost(hostname) {
819
+ const host = hostname.trim().toLowerCase().replace(/^\[(.*)\]$/, "$1").replace(/\.$/, "");
820
+ // Other picomatch syntax (?, braces, classes, extglobs) cannot be judged here, so it is refused.
821
+ if (/[?{}[\]()!@+]/.test(host))
822
+ return true;
823
+ // A wildcard host is local when it admits a local address: Next matches hostnames with picomatch, whose `*` stops
824
+ // only at a slash, so `*` and `**` both admit `localhost`, and `10.*.*.*` admits 10.0.0.1. Any wildcard address
825
+ // (`192.168.1.*`, `fd12:*`) counts as local.
826
+ if (host.includes("*")) {
827
+ if (/^[\d.*]+$/.test(host) || host.includes(":"))
828
+ return true;
829
+ const source = host.split(/(\*\*|\*)/).map((part) => (part === "**" ? ".*" : part === "*" ? "[^/]*" : part.replace(/[.+?^$()|{}[\]\\]/g, "\\$&"))).join("");
830
+ const glob = new RegExp("^" + source + "$");
831
+ return LOCAL_HOST_SAMPLES.some((sample) => glob.test(sample));
832
+ }
833
+ // The address a URL reads it as: 127.1, 0x7f.0.0.1 and [::ffff:127.0.0.1] all name 127.0.0.1.
834
+ let named = host;
835
+ try {
836
+ named = new URL("https://" + (host.includes(":") ? "[" + host + "]" : host)).hostname.replace(/^\[(.*)\]$/, "$1");
837
+ }
838
+ catch {
839
+ // not a host a URL can name: judged as written
840
+ }
841
+ if (named === "localhost" || named.endsWith(".localhost"))
842
+ return true;
843
+ const hex = named.match(/^(?:0{0,4}:){0,5}:?ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/);
844
+ const dotted = hex ? [parseInt(hex[1], 16) >> 8, parseInt(hex[1], 16) & 255, parseInt(hex[2], 16) >> 8, parseInt(hex[2], 16) & 255].join(".") : undefined;
845
+ const mapped = named.match(/^(?:0{0,4}:){0,5}:?ffff:(\d{1,3}(?:\.\d{1,3}){3})$/);
846
+ const ipv4 = (dotted ?? mapped?.[1] ?? named).match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
847
+ if (ipv4) {
848
+ const [a, b] = [Number(ipv4[1]), Number(ipv4[2])];
849
+ return a === 0 || a === 10 || a === 127 || (a === 169 && b === 254) || (a === 172 && b >= 16 && b <= 31) ||
850
+ (a === 192 && b === 168) || (a === 100 && b >= 64 && b <= 127);
851
+ }
852
+ if (!named.includes(":"))
853
+ return false;
854
+ const groups = named.split(":");
855
+ const allZero = (parts) => parts.every((part) => /^0*$/.test(part));
856
+ // :: and ::1 in any spelling (0:0:0:0:0:0:0:1), then the private and link-local prefixes.
857
+ if (allZero(groups) || (allZero(groups.slice(0, -1)) && /^0*1$/.test(groups.at(-1) ?? "")))
858
+ return true;
859
+ return /^f[cd][0-9a-f]{0,2}:/.test(named) || /^fe[89ab][0-9a-f]?:/.test(named);
860
+ }
861
+ /** One address in each local range, to judge a wildcard host by. */
862
+ const LOCAL_HOST_SAMPLES = ["localhost", "a.localhost", "0.0.0.0", "10.0.0.1", "100.64.0.1", "127.0.0.1", "169.254.169.254", "172.16.0.1", "192.168.0.1", "::1", "fc00::1", "fe80::1"];
863
+ function unwrapExpression(node) {
864
+ let current = node;
865
+ while (current && (ts.isAsExpression(current) || ts.isSatisfiesExpression(current) || ts.isParenthesizedExpression(current) || ts.isNonNullExpression(current))) {
866
+ current = current.expression;
867
+ }
868
+ return current;
869
+ }
870
+ /** A property's value, including shorthand (`{ remotePatterns }` gives the identifier). */
871
+ function propertyExpression(node, name) {
872
+ if (!node || !ts.isObjectLiteralExpression(node))
873
+ return undefined;
874
+ for (const property of node.properties) {
875
+ if (ts.isShorthandPropertyAssignment(property) && property.name.text === name)
876
+ return property.name;
877
+ }
878
+ return objectPropertyValue(node, name);
879
+ }
880
+ /** The initializer of a top-level `const name = …` in the same file, unwrapped. */
881
+ function sameFileInitializer(file, name) {
882
+ for (const statement of parseBrandlabSourceFile(file).statements) {
883
+ if (!ts.isVariableStatement(statement))
884
+ continue;
885
+ for (const declaration of statement.declarationList.declarations) {
886
+ if (ts.isIdentifier(declaration.name) && declaration.name.text === name)
887
+ return unwrapExpression(declaration.initializer);
888
+ }
889
+ }
890
+ return undefined;
891
+ }
892
+ /** An array literal, directly or through a top-level `const name = [...]` in the same file. */
893
+ function sameFileArray(file, node) {
894
+ const value = unwrapExpression(node);
895
+ const resolved = value && ts.isIdentifier(value) ? sameFileInitializer(file, value.text) : value;
896
+ return resolved && ts.isArrayLiteralExpression(resolved) ? resolved : undefined;
897
+ }
898
+ /** An object literal, directly or through a top-level `const name = {...}` in the same file. */
899
+ function sameFileObject(file, node) {
900
+ const value = unwrapExpression(node);
901
+ const resolved = value && ts.isIdentifier(value) ? sameFileInitializer(file, value.text) : value;
902
+ return resolved && ts.isObjectLiteralExpression(resolved) ? resolved : undefined;
903
+ }
728
904
  /** Evaluate gitignore-style patterns (last match wins) for a root-level file. */
729
905
  export function isIgnored(patterns, file) {
730
906
  let ignored = false;
@@ -1 +1 @@
1
- {"version":3,"file":"static-rules.js","sourceRoot":"","sources":["../src/static-rules.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { join, posix } from \"node:path\";\nimport ts from \"typescript\";\nimport { globMatch } from \"./glob.js\";\nimport type { BrandlabFinding } from \"./project.js\";\nimport {\n findWordingInMarkdown,\n findWordingInSource,\n isPublicDocumentPath,\n isPublicModulePath,\n parseJsonSource,\n type PublicCopyFinding,\n} from \"./public-copy.js\";\nimport {\n BRANDLAB_SOURCE_ROOT_DIRECTORIES,\n createBrandlabModuleResolver,\n findImportedCalls,\n importedLocalNames,\n isDirectory,\n lineAt,\n stripCommentsPreservingLayout,\n lineOfNode,\n listModuleReferences,\n objectPropertyValue,\n parseBrandlabSourceFile,\n stringLiteralValue,\n type BrandlabModuleResolver,\n type BrandlabSourceFile,\n type BrandlabSourceIndex,\n walkProjectFiles,\n} from \"./source-files.js\";\nimport type { BrandlabRuleEvaluation } from \"./verification-policy.js\";\n\nconst SITE_CORE = (module: string) => new RegExp(`^@brandlab-digital/site-core/${module}$`);\nconst SITE_NEXT = (module: string) => new RegExp(`^@brandlab-digital/site-next/${module}$`);\nconst SITE_NEXT_ANY = /^@brandlab-digital\\/site-next(?:\\/|$)/;\nconst SOURCE_EXTENSIONS = [\"ts\", \"tsx\", \"js\", \"jsx\", \"mjs\"];\n\nexport interface StaticRuleContext {\n root: string;\n source: BrandlabSourceIndex;\n /** brandlab.config.ts text, or null when it is missing. */\n config: string | null;\n findings: BrandlabFinding[];\n evaluations: BrandlabRuleEvaluation[];\n}\n\nexport function staticFinding(options: {\n ruleId: string;\n surface: string;\n expected: string;\n actual: string;\n remediation: string;\n path?: string;\n line?: number;\n severity?: BrandlabFinding[\"severity\"];\n}): BrandlabFinding {\n return {\n ruleId: options.ruleId,\n surface: options.surface,\n severity: options.severity ?? \"blocker\",\n contract: { name: \"project\", version: \"current-only-v2\" },\n evidenceKind: \"static\",\n ...(options.path ? { path: options.path } : {}),\n ...(options.line ? { line: options.line } : {}),\n expected: options.expected,\n actual: options.actual,\n remediation: options.remediation,\n };\n}\n\nexport function recordEvaluation(\n evaluations: BrandlabRuleEvaluation[],\n surface: string,\n ...ruleIds: string[]\n) {\n for (const ruleId of ruleIds) evaluations.push({ ruleId, surface });\n}\n\n/** The minimal static rules behind the checks that previously passed without evidence. */\nexport function inspectStaticRules(context: StaticRuleContext) {\n const project = describeProject(context);\n inspectContactProviderRoute(context, project);\n inspectAnalyticsPrivacy(context);\n inspectGoogleTagOwner(context);\n inspectGoogleTagConsent(context);\n inspectSearchRouting(context, project);\n inspectBusinessFacts(context);\n inspectSharedBindings(context);\n inspectRouteCatalogue(context, project);\n inspectLocationEstate(context, project);\n inspectImplementationWording(context);\n inspectPlatformReimplementation(context);\n inspectRetiredConfiguration(context);\n inspectWorkflowPins(context);\n inspectVercelIgnore(context);\n}\n\nexport interface BrandlabProjectCapabilities {\n contactEnabled: boolean;\n reviewsEnabled: boolean;\n locationsDeclared: boolean;\n sitemapMode: \"single\" | \"split\" | null;\n}\n\n/** Capabilities declared by brandlab.config.ts, the contact route and the location data. */\nexport function describeCapabilities(root: string, config: string | null): BrandlabProjectCapabilities {\n const text = config ?? \"\";\n const families = text.match(/\\bfamilies\\s*:\\s*\\[([^\\]]*)\\]/)?.[1] ?? \"\";\n const strategy = text.match(/\\blocations\\s*:\\s*\\{[^{}]*\\bstrategy\\s*:\\s*['\"]([a-z-]+)['\"]/)?.[1];\n return {\n contactEnabled:\n /\\bcontact\\s*:\\s*\\{/.test(text) ||\n routeCandidates(\"api/contact/route\").some((path) => existsSync(join(root, path))),\n reviewsEnabled: /\\breviews\\s*:\\s*\\{/.test(text),\n locationsDeclared:\n /['\"](?:locations|service-locations)['\"]/.test(families) ||\n (strategy !== undefined && strategy !== \"none\") ||\n isDirectory(join(root, \"src/data/locations\")),\n sitemapMode: (text.match(/\\bsitemap\\s*:\\s*\\{[^{}]*\\bmode\\s*:\\s*['\"](single|split)['\"]/)?.[1] ??\n null) as BrandlabProjectCapabilities[\"sitemapMode\"],\n };\n}\n\ninterface ProjectShape extends BrandlabProjectCapabilities {\n resolver: BrandlabModuleResolver;\n catalogueFiles: string[];\n}\n\nfunction describeProject(context: StaticRuleContext): ProjectShape {\n const capabilities = describeCapabilities(context.root, context.config);\n return {\n ...capabilities,\n contactEnabled: capabilities.contactEnabled || findContactContractRecipients(context.source).length > 0,\n resolver: createBrandlabModuleResolver(context.root, new Set(context.source.byPath.keys())),\n catalogueFiles: context.source.files\n .filter((file) => findImportedCalls(file, SITE_CORE(\"routes\"), \"defineRouteCatalog\").length > 0)\n .map((file) => file.path),\n };\n}\n\n// --- contact-provider-errors -------------------------------------------------\n\nfunction inspectContactProviderRoute(context: StaticRuleContext, project: ProjectShape) {\n if (!project.contactEnabled) return;\n const ruleId = \"brandlab-contact-provider-route\";\n recordEvaluation(context.evaluations, \"contact\", ruleId);\n const expected =\n \"POST /api/contact produced by the shared handler (createBrandlabContactRouteHandler, or createBrandlabContactRuntime during transition)\";\n const remediation =\n \"Export POST = createBrandlabContactRouteHandler({ contract, runtime }) from @brandlab-digital/site-next/contact/server.\";\n const route = firstExisting(context, routeCandidates(\"api/contact/route\"));\n if (!route) {\n context.findings.push(staticFinding({\n ruleId, surface: \"contact\", path: \"src/app/api/contact/route.ts\", expected, remediation,\n actual: \"The contact capability is enabled but src/app/api/contact/route.ts is missing.\",\n }));\n return;\n }\n const file = context.source.byPath.get(route);\n if (!file || !exportedNames(file).has(\"POST\")) {\n context.findings.push(staticFinding({\n ruleId, surface: \"contact\", path: route, expected, remediation,\n actual: \"The contact route does not export a POST handler.\",\n }));\n return;\n }\n const contactServer = SITE_NEXT(\"contact/server\");\n const direct = findImportedCalls(file, contactServer, \"createBrandlabContactRouteHandler\").length > 0;\n const runtimeModules = [file, ...localImports(context, project.resolver, file)];\n const transitional =\n /\\.contactRouteHandler\\b/.test(file.executable) &&\n runtimeModules.some((candidate) =>\n findImportedCalls(candidate, contactServer, \"createBrandlabContactRuntime\").length > 0);\n if (!direct && !transitional) {\n context.findings.push(staticFinding({\n ruleId, surface: \"contact\", path: route, expected, remediation,\n actual: \"The POST handler is not created by the shared contact runtime, so provider errors are project-owned.\",\n }));\n }\n}\n\n// --- analytics-privacy -------------------------------------------------------\n\nconst ANALYTICS_SINKS = new Set([\n \"gtag\", \"window.gtag\", \"globalThis.gtag\",\n \"dataLayer.push\", \"window.dataLayer.push\", \"globalThis.dataLayer.push\",\n \"sendGAEvent\", \"sendGTMEvent\", \"trackBrandlabBrowserEvent\", \"trackBrandlabEvent\", \"ReactGA.event\",\n]);\n\nconst PII_TOKENS = new Set([\n \"attachment\", \"attachment_name\", \"contact_email\", \"contact_name\", \"customer_name\", \"email\",\n \"email_address\", \"enquiry_message\", \"file_name\", \"filename\", \"first_name\", \"form_message\",\n \"full_name\", \"last_name\", \"message\", \"mobile\", \"mobile_number\", \"phone\", \"phone_number\",\n \"residential_address\", \"street_address\", \"user_email\", \"user_phone\",\n]);\n\nfunction inspectAnalyticsPrivacy(context: StaticRuleContext) {\n if (context.source.files.length === 0) return;\n const ruleId = \"brandlab-analytics-pii-payload\";\n recordEvaluation(context.evaluations, \"analytics\", ruleId);\n for (const file of context.source.files) {\n const visit = (node: ts.Node) => {\n if (ts.isCallExpression(node) && ANALYTICS_SINKS.has(memberPath(node.expression) ?? \"\")) {\n const userData = stringLiteralValue(node.arguments[0]) === \"set\" &&\n stringLiteralValue(node.arguments[1]) === \"user_data\" &&\n node.arguments[2] && !(ts.isObjectLiteralExpression(node.arguments[2]) && node.arguments[2].properties.length === 0);\n const piiNode = userData ? node.arguments[2] : node.arguments.map(findPiiNode).find(Boolean);\n if (piiNode) {\n context.findings.push(staticFinding({\n ruleId,\n surface: \"analytics\",\n path: file.path,\n line: lineOfNode(file, piiNode),\n expected: \"Analytics payloads carry only the shared allowlisted, non-identifying parameters\",\n actual: userData\n ? \"Project code sets Google user_data; enhanced conversion data is owned by the shared runtime.\"\n : \"A lead contact field, message or attachment detail reaches an analytics payload.\",\n remediation: \"Send events through the shared Brandlab analytics runtime without lead details.\",\n }));\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(parseBrandlabSourceFile(file));\n }\n}\n\nfunction findPiiNode(node: ts.Node | undefined): ts.Node | undefined {\n if (!node) return undefined;\n if (ts.isObjectLiteralExpression(node)) {\n for (const property of node.properties) {\n if (ts.isShorthandPropertyAssignment(property) && isPiiToken(property.name.text)) return property;\n if (ts.isSpreadAssignment(property) && isPiiReference(property.expression)) return property;\n if (!ts.isPropertyAssignment(property)) continue;\n const key = ts.isIdentifier(property.name) || ts.isStringLiteralLike(property.name) ? property.name.text : null;\n if ((key && isPiiToken(key)) || isPiiReference(property.initializer)) return property;\n const nested = findPiiNode(property.initializer);\n if (nested) return nested;\n }\n return undefined;\n }\n if (ts.isArrayLiteralExpression(node)) return node.elements.map(findPiiNode).find(Boolean);\n return isPiiReference(node) ? node : undefined;\n}\n\nfunction isPiiReference(node: ts.Node): boolean {\n if (ts.isIdentifier(node)) return isPiiToken(node.text);\n if (ts.isPropertyAccessExpression(node)) return isPiiToken(node.name.text);\n if (ts.isTemplateExpression(node)) return node.templateSpans.some((span) => isPiiReference(span.expression));\n return false;\n}\n\nfunction isPiiToken(value: string): boolean {\n return PII_TOKENS.has(value.replace(/([a-z0-9])([A-Z])/g, \"$1_$2\").toLowerCase().replace(/[^a-z0-9]+/g, \"_\"));\n}\n\nfunction memberPath(node: ts.Expression): string | null {\n if (ts.isIdentifier(node)) return node.text;\n if (ts.isPropertyAccessExpression(node)) {\n const object = memberPath(node.expression);\n return object ? `${object}.${node.name.text}` : null;\n }\n return null;\n}\n\n// --- analytics-conversion: one Google tag owner ------------------------------\n\nfunction inspectGoogleTagOwner(context: StaticRuleContext) {\n if (context.source.files.length === 0) return;\n const ruleId = \"brandlab-analytics-google-tag-owner\";\n recordEvaluation(context.evaluations, \"analytics\", ruleId);\n const usages = context.source.files.flatMap((file) => {\n const locals = new Set(importedLocalNames(file, SITE_NEXT_ANY, \"BrandlabGoogleTag\"));\n if (locals.size === 0) return [];\n const found: { path: string; line: number }[] = [];\n const visit = (node: ts.Node) => {\n if (\n (ts.isJsxSelfClosingElement(node) || ts.isJsxOpeningElement(node)) &&\n ts.isIdentifier(node.tagName) &&\n locals.has(node.tagName.text)\n ) {\n found.push({ path: file.path, line: lineOfNode(file, node) });\n }\n ts.forEachChild(node, visit);\n };\n visit(parseBrandlabSourceFile(file));\n return found;\n });\n const rootLayouts = new Set(routeCandidates(\"layout\").filter((path) => context.source.byPath.has(path)));\n const expected = \"Exactly one <BrandlabGoogleTag /> rendered from the root layout (src/app/layout.tsx)\";\n const remediation = \"Render BrandlabGoogleTag once, directly in src/app/layout.tsx, and remove wrappers or duplicates.\";\n if (usages.length === 1 && rootLayouts.has(usages[0]!.path)) return;\n context.findings.push(staticFinding({\n ruleId,\n surface: \"analytics\",\n ...(usages[0] ? { path: usages[0].path, line: usages[0].line } : { path: \"src/app/layout.tsx\" }),\n expected,\n actual: usages.length === 0\n ? \"No BrandlabGoogleTag is rendered, so the shared tag and its events are absent.\"\n : usages.length > 1\n ? `BrandlabGoogleTag is rendered ${usages.length} times (${usages.map(({ path, line }) => `${path}:${line}`).join(\", \")}).`\n : \"BrandlabGoogleTag is rendered outside the root layout.\",\n remediation,\n }));\n}\n\n// --- analytics-privacy: the Google tag's consent default follows the contract --\n\nfunction inspectGoogleTagConsent(context: StaticRuleContext) {\n if (context.source.files.length === 0) return;\n const ruleId = \"brandlab-analytics-google-tag-consent\";\n recordEvaluation(context.evaluations, \"analytics\", ruleId);\n for (const file of context.source.files) {\n const locals = new Set(importedLocalNames(file, SITE_NEXT_ANY, \"BrandlabGoogleTag\"));\n if (locals.size === 0) continue;\n const visit = (node: ts.Node) => {\n if (\n (ts.isJsxSelfClosingElement(node) || ts.isJsxOpeningElement(node)) &&\n ts.isIdentifier(node.tagName) &&\n locals.has(node.tagName.text)\n ) {\n for (const attribute of node.attributes.properties) {\n if (!ts.isJsxAttribute(attribute) || !ts.isIdentifier(attribute.name) || attribute.name.text !== \"adUserData\") continue;\n context.findings.push(staticFinding({\n ruleId,\n surface: \"analytics\",\n path: file.path,\n line: lineOfNode(file, attribute),\n expected: \"BrandlabGoogleTag takes its ad_user_data consent default from the analytics binding ({...analytics.googleTag})\",\n actual: \"BrandlabGoogleTag sets adUserData itself, so the Google tag's ad_user_data default no longer follows the analytics contract.\",\n remediation:\n \"Remove the adUserData attribute. Only googleAds.enhancedConversions: { mode: 'disclosed' } in the analytics contract grants it by default, once the privacy policy discloses it.\",\n }));\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(parseBrandlabSourceFile(file));\n }\n}\n\n// --- search-routing ----------------------------------------------------------\n\nfunction inspectSearchRouting(context: StaticRuleContext, project: ProjectShape) {\n if (context.source.directoryRoots.length === 0) return;\n inspectPackageRoute(context, project, {\n ruleId: \"brandlab-robots-package-route\",\n surface: \"robots\",\n candidates: routeCandidates(\"robots\"),\n staticFile: \"public/robots.txt\",\n modules: [SITE_NEXT(\"robots\")],\n packageLabel: \"@brandlab-digital/site-next/robots\",\n needsCatalogue: false,\n });\n inspectPackageRoute(context, project, {\n ruleId: \"brandlab-sitemap-package-route\",\n surface: \"sitemap\",\n candidates: [...routeCandidates(\"sitemap.xml/route\"), ...routeCandidates(\"sitemap\")],\n staticFile: \"public/sitemap.xml\",\n modules: [SITE_NEXT(\"sitemaps\"), SITE_CORE(\"sitemaps\")],\n packageLabel: \"@brandlab-digital/site-next/sitemaps\",\n needsCatalogue: true,\n });\n inspectSitemapMode(context, project);\n inspectMetadataBuilder(context, project);\n}\n\nfunction inspectPackageRoute(\n context: StaticRuleContext,\n project: ProjectShape,\n rule: {\n ruleId: string;\n surface: string;\n candidates: string[];\n staticFile: string;\n modules: RegExp[];\n packageLabel: string;\n needsCatalogue: boolean;\n },\n) {\n recordEvaluation(context.evaluations, rule.surface, rule.ruleId);\n const expected = `The ${rule.surface} route is a thin binding of ${rule.packageLabel}${rule.needsCatalogue ? \" over the route catalogue\" : \"\"}`;\n const remediation = `Serve ${rule.surface} from ${rule.candidates[0]} using ${rule.packageLabel}${rule.needsCatalogue ? \" and the routes from src/data/routes.ts\" : \"\"}.`;\n const report = (actual: string, path: string) => context.findings.push(staticFinding({\n ruleId: rule.ruleId, surface: rule.surface, path, expected, actual, remediation,\n }));\n if (existsSync(join(context.root, rule.staticFile))) {\n report(`${rule.staticFile} bypasses the environment-aware shared ${rule.surface} output.`, rule.staticFile);\n }\n const route = firstExisting(context, rule.candidates);\n const file = route ? context.source.byPath.get(route) : undefined;\n if (!route || !file) {\n report(`No ${rule.surface} route was found.`, rule.candidates[0]!);\n return;\n }\n const references = listModuleReferences(file);\n if (!references.some((reference) => rule.modules.some((module) => module.test(reference.specifier)))) {\n report(`${route} does not use ${rule.packageLabel}.`, route);\n return;\n }\n if (rule.needsCatalogue && project.catalogueFiles.length > 0 && !reachesCatalogue(context, project, file)) {\n report(`${route} does not read the route catalogue.`, route);\n }\n}\n\nfunction inspectSitemapMode(context: StaticRuleContext, project: ProjectShape) {\n if (!project.sitemapMode) return;\n const ruleId = \"brandlab-sitemap-split-mode\";\n recordEvaluation(context.evaluations, \"sitemap\", ruleId);\n const chunkRoute = [\"src/app/sitemaps\", \"app/sitemaps\"].find((path) => isDirectory(join(context.root, path)));\n if (project.sitemapMode === \"split\" ? chunkRoute : !chunkRoute) return;\n context.findings.push(staticFinding({\n ruleId,\n surface: \"sitemap\",\n path: chunkRoute ?? \"brandlab.config.ts\",\n expected: \"/sitemaps/[chunk] exists only when brandlab.config sets sitemap.mode: 'split'\",\n actual: project.sitemapMode === \"split\"\n ? \"sitemap.mode is 'split' but no /sitemaps/[chunk] route exists.\"\n : `sitemap.mode is 'single' but ${chunkRoute} still serves sitemap chunks.`,\n remediation: \"Keep the sitemap routes and brandlab.config sitemap.mode in agreement.\",\n }));\n}\n\nfunction inspectMetadataBuilder(context: StaticRuleContext, project: ProjectShape) {\n const ruleId = \"brandlab-metadata-route-builder\";\n recordEvaluation(context.evaluations, \"metadata\", ruleId);\n const builders = context.source.files.filter((file) =>\n findImportedCalls(file, SITE_NEXT(\"metadata\"), \"createRouteMetadataBuilder\").length > 0);\n const expected = \"Page metadata built by createRouteMetadataBuilder(site, routes) from @brandlab-digital/site-next/metadata\";\n const remediation = \"Bind pageMetadata = createRouteMetadataBuilder(site, routes) in src/lib/seo/metadata.ts.\";\n if (builders.length === 0) {\n context.findings.push(staticFinding({\n ruleId, surface: \"metadata\", path: \"src/lib/seo/metadata.ts\", expected, remediation,\n actual: \"No module builds page metadata with createRouteMetadataBuilder.\",\n }));\n return;\n }\n if (project.catalogueFiles.length === 0) return;\n for (const builder of builders.filter((file) => !reachesCatalogue(context, project, file))) {\n context.findings.push(staticFinding({\n ruleId, surface: \"metadata\", path: builder.path, expected, remediation,\n actual: \"The metadata builder does not read the route catalogue.\",\n }));\n }\n}\n\nfunction reachesCatalogue(context: StaticRuleContext, project: ProjectShape, file: BrandlabSourceFile): boolean {\n const catalogues = new Set(project.catalogueFiles);\n const seen = new Set<string>([file.path]);\n let frontier = [file];\n for (let depth = 0; depth < 4 && frontier.length > 0; depth += 1) {\n const next: BrandlabSourceFile[] = [];\n for (const current of frontier) {\n for (const imported of localImports(context, project.resolver, current)) {\n if (catalogues.has(imported.path)) return true;\n if (seen.has(imported.path)) continue;\n seen.add(imported.path);\n next.push(imported);\n }\n }\n frontier = next;\n }\n return false;\n}\n\n// --- business-identity and route-identity ------------------------------------\n\nfunction inspectBusinessFacts(context: StaticRuleContext) {\n if (context.source.files.length === 0) return;\n exactlyOneDefinition(context, {\n ruleId: \"brandlab-business-facts\",\n surface: \"business\",\n module: SITE_CORE(\"business\"),\n name: \"defineBrandlabBusiness\",\n expectedPath: \"src/data/businessEvidence.ts\",\n subject: \"Business facts\",\n });\n}\n\n/** The one-owner 3.0 bindings: site identity, redirects, analytics, next.config and instrumentation. */\nfunction inspectSharedBindings(context: StaticRuleContext) {\n if (context.source.files.length === 0) return;\n exactlyOneDefinition(context, {\n ruleId: \"brandlab-site-identity\",\n surface: \"metadata\",\n module: SITE_CORE(\"site\"),\n name: \"defineBrandlabSite\",\n expectedPath: \"src/config/site.ts\",\n subject: \"The site identity\",\n });\n exactlyOneDefinition(context, {\n ruleId: \"brandlab-redirects-table\",\n surface: \"routes\",\n module: SITE_CORE(\"redirects\"),\n name: \"defineRedirects\",\n expectedPath: \"src/data/redirects.ts\",\n subject: \"The redirect table\",\n });\n exactlyOneDefinition(context, {\n ruleId: \"brandlab-analytics-contract\",\n surface: \"analytics\",\n module: SITE_NEXT(\"analytics\"),\n name: \"defineBrandlabAnalytics\",\n expectedPath: \"src/config/analytics.ts\",\n subject: \"The analytics contract\",\n });\n requireBindingCall(context, {\n ruleId: \"brandlab-runtime-next-config\",\n surface: \"runtime\",\n candidates: [\"next.config.ts\", \"next.config.mts\", \"next.config.mjs\", \"next.config.js\"],\n module: SITE_NEXT(\"next-config\"),\n name: \"defineBrandlabNextConfig\",\n expected: \"next.config exports defineBrandlabNextConfig({ site, redirects, ... }) from @brandlab-digital/site-next/next-config\",\n consequence: \"headers, image formats and Preview noindex are then project-owned\",\n });\n requireBindingCall(context, {\n ruleId: \"brandlab-analytics-instrumentation\",\n surface: \"analytics\",\n candidates: [\"src/instrumentation-client.ts\", \"src/instrumentation-client.js\", \"instrumentation-client.ts\", \"instrumentation-client.js\"],\n module: SITE_NEXT(\"instrumentation-client\"),\n name: \"installBrandlabInstrumentation\",\n expected: \"src/instrumentation-client.ts calls installBrandlabInstrumentation(analytics)\",\n consequence: \"telephone taps and the initial landing are not reported by the shared runtime\",\n });\n}\n\nfunction requireBindingCall(\n context: StaticRuleContext,\n rule: {\n ruleId: string;\n surface: string;\n candidates: readonly string[];\n module: RegExp;\n name: string;\n expected: string;\n consequence: string;\n },\n) {\n recordEvaluation(context.evaluations, rule.surface, rule.ruleId);\n const path = rule.candidates.find((candidate) => context.source.byPath.has(candidate));\n const file = path ? context.source.byPath.get(path) : undefined;\n if (file && findImportedCalls(file, rule.module, rule.name).length > 0) return;\n context.findings.push(staticFinding({\n ruleId: rule.ruleId,\n surface: rule.surface,\n path: path ?? rule.candidates[0]!,\n expected: rule.expected,\n actual: file\n ? `${path} does not call ${rule.name}, so ${rule.consequence}.`\n : `${rule.candidates[0]} is missing, so ${rule.consequence}.`,\n remediation: `Call ${rule.name} from the shared package in ${rule.candidates[0]}.`,\n }));\n}\n\nfunction inspectRouteCatalogue(context: StaticRuleContext, project: ProjectShape) {\n if (context.source.files.length === 0) return;\n exactlyOneDefinition(context, {\n ruleId: \"brandlab-routes-catalogue\",\n surface: \"routes\",\n module: SITE_CORE(\"routes\"),\n name: \"defineRouteCatalog\",\n expectedPath: \"src/data/routes.ts\",\n subject: \"The route catalogue\",\n known: project.catalogueFiles,\n });\n}\n\nfunction exactlyOneDefinition(\n context: StaticRuleContext,\n rule: {\n ruleId: string;\n surface: string;\n module: RegExp;\n name: string;\n expectedPath: string;\n subject: string;\n known?: string[];\n },\n) {\n recordEvaluation(context.evaluations, rule.surface, rule.ruleId);\n const owners = rule.known ?? context.source.files\n .filter((file) => findImportedCalls(file, rule.module, rule.name).length > 0)\n .map((file) => file.path);\n if (owners.length === 1) return;\n context.findings.push(staticFinding({\n ruleId: rule.ruleId,\n surface: rule.surface,\n path: owners[0] ?? rule.expectedPath,\n expected: `${rule.subject} declared once with ${rule.name}`,\n actual: owners.length === 0\n ? `No module calls ${rule.name}.`\n : `${rule.name} is called in ${owners.length} modules: ${owners.join(\", \")}.`,\n remediation: `Keep one ${rule.name} owner in ${rule.expectedPath} and import it everywhere else.`,\n }));\n}\n\nfunction inspectLocationEstate(context: StaticRuleContext, project: ProjectShape) {\n if (!project.locationsDeclared) return;\n const ruleId = \"brandlab-routes-location-estate\";\n recordEvaluation(context.evaluations, \"routes\", ruleId);\n const estate = firstExisting(context, SOURCE_EXTENSIONS.slice(0, 2).map((extension) => `src/data/locations/estate.${extension}`));\n const file = estate ? context.source.byPath.get(estate) : undefined;\n if (file && findImportedCalls(file, SITE_CORE(\"locations\"), \"defineLocationEstate\").length > 0) return;\n context.findings.push(staticFinding({\n ruleId,\n surface: \"routes\",\n path: estate ?? \"src/data/locations/estate.ts\",\n expected: \"The published location list declared once in src/data/locations/estate.ts with defineLocationEstate\",\n actual: file\n ? \"src/data/locations/estate.ts does not declare the estate with defineLocationEstate.\"\n : \"The project publishes locations but has no src/data/locations/estate.ts.\",\n remediation: \"Declare the published locations, retained exclusions and any site-owned locations with defineLocationEstate as literal data.\",\n }));\n}\n\n// --- public-output-safety ----------------------------------------------------\n\n/** Directories that can hold public content documents (MDX, Markdown and JSON data). */\nconst DOCUMENT_ROOTS = [...BRANDLAB_SOURCE_ROOT_DIRECTORIES, \"content\", \"posts\"];\n\n/**\n * Implementation wording in anything that can render publicly: JSX text, rendered\n * attributes (alt, title, aria-label and component copy props), copy-bearing string\n * literals in pages, components, metadata, schema, configuration and data, MDX and\n * Markdown content with its frontmatter, and JSON data. Class lists, styles, import\n * paths, keys, types, comparisons, errors and console output are code, not copy.\n */\nfunction inspectImplementationWording(context: StaticRuleContext) {\n const modules = context.source.files.filter((file) => isPublicModulePath(file.path));\n const documents = [...new Set(DOCUMENT_ROOTS)]\n .flatMap((directory) => walkProjectFiles(context.root, directory))\n .filter(isPublicDocumentPath);\n if (modules.length === 0 && documents.length === 0) return;\n const ruleId = \"brandlab-content-implementation-wording\";\n recordEvaluation(context.evaluations, \"content\", ruleId);\n const report = (path: string, finding: PublicCopyFinding) => {\n context.findings.push(staticFinding({\n ruleId,\n surface: \"content\",\n path,\n line: finding.line,\n expected: \"Publicly rendered copy is finished customer copy, not implementation wording\",\n actual: `Implementation-facing wording (${finding.pattern.source}) appears in ${finding.where}.`,\n remediation: \"Replace the wording with the finished customer copy before it can render publicly.\",\n }));\n };\n for (const file of modules) {\n for (const finding of findWordingInSource(parseBrandlabSourceFile(file))) report(file.path, finding);\n }\n for (const path of documents) {\n const text = readFileSync(join(context.root, path), \"utf8\");\n const findings = path.endsWith(\".json\")\n ? findWordingInSource(parseJsonSource(path, text))\n : findWordingInMarkdown(text);\n for (const finding of findings) report(path, finding);\n }\n}\n\n// --- source-safety -----------------------------------------------------------\n\n/** Shared platform surfaces a project must import rather than declare. */\nconst PROTECTED_PLATFORM_NAMES = new Set([\n \"BrandlabBreadcrumbs\", \"BrandlabGoogleTag\", \"ContactFormEmail\", \"SafeRichText\", \"SchemaScript\",\n \"buildBrandlabMetadata\", \"buildLocalBusinessSchema\", \"buildNextMetadata\", \"buildRobotsMetadata\",\n \"buildSchemaGraph\", \"buildSitemapEntries\", \"createBrandlabContactRouteHandler\",\n \"createBrandlabContactRuntime\", \"createBrandlabRobots\", \"createBrandlabSitemapRoute\",\n \"createNextMetadataBuilder\", \"createRouteAwareMdxBlogAdapter\", \"createRouteAwareStructuredBlogAdapter\",\n \"createRouteMetadataBuilder\", \"defineAnalyticsContract\", \"defineBrandlabAnalytics\",\n \"defineBrandlabBusiness\", \"defineBrandlabContact\", \"defineBrandlabNextConfig\", \"defineBrandlabProject\",\n \"defineBrandlabSite\", \"defineBreadcrumbTrail\", \"defineContactContract\", \"defineLocationEstate\",\n \"defineRedirects\", \"defineRouteCatalog\", \"installBrandlabInstrumentation\", \"installPhoneClickListener\",\n \"renderContactEmail\", \"sitemapIndexXmlResponse\", \"sitemapXmlResponse\", \"trackBrandlabBrowserEvent\",\n \"useBrandlabContactForm\",\n]);\n\n/** Package exports removed in 3.0.0 (web-vitals APIs are reported by the analytics rule). */\nconst RETIRED_PACKAGE_EXPORTS = [\n \"TrackedTelephoneLink\", \"shouldIndexSite\", \"buildRobotsMetadata\", \"buildSeoMetadata\", \"buildNextMetadata\",\n \"buildBrandlabNextMetadata\", \"createNextMetadataBuilder\", \"createBrandlabNextMetadataBuilder\",\n \"isBrandlabProductionDeployment\", \"resolveBrowserAnalyticsConfig\", \"resolveBrandlabGoogleTagConfig\",\n \"BRANDLAB_NEXT_HEADER_PROFILES\", \"createContactHttpSubmissionController\", \"trackDeliveredContactResult\",\n \"trackDeliveredContactWithEnhancedConversions\", \"trackDeliveredContact\", \"shouldTrackContactResult\",\n \"isTrackableContactActionResult\",\n];\n\n/** APIs, options and paths removed in 3.0.0; their presence means an unfinished migration. */\nconst RETIRED_SOURCE_APIS: readonly { pattern: RegExp; label: string }[] = [\n ...RETIRED_PACKAGE_EXPORTS.map((name) => ({ pattern: new RegExp(`\\\\b${name}\\\\b`), label: name })),\n { pattern: /\\bALLOW_INDEXING\\b/, label: \"the ALLOW_INDEXING override\" },\n { pattern: /\\bNEXT_PUBLIC_SITE_URL\\b/, label: \"NEXT_PUBLIC_SITE_URL\" },\n {\n pattern: /\\bbuildBrandlabHeaderRules\\s*\\(\\s*\\{[^}]*\\b(?:isProduction|profile)\\b/,\n label: \"buildBrandlabHeaderRules({ isProduction, profile }) (pass the deployment instead)\",\n },\n { pattern: /\\b(?:xRobotsTag|contentSecurityPolicyMode)\\s*:/, label: \"the xRobotsTag or contentSecurityPolicyMode header option\" },\n { pattern: /\\bleadDiagnostics\\s*:/, label: \"the leadDiagnostics flag (lead diagnostics are always sent)\" },\n];\n\nfunction inspectPlatformReimplementation(context: StaticRuleContext) {\n if (context.source.files.length === 0) return;\n const reimplementation = \"brandlab-source-platform-reimplementation\";\n const retired = \"brandlab-source-retired-api\";\n recordEvaluation(context.evaluations, \"source\", reimplementation, retired);\n for (const file of context.source.files) {\n const declared = declaredProtectedNames(file);\n if (declared) {\n context.findings.push(staticFinding({\n ruleId: reimplementation,\n surface: \"source\",\n path: file.path,\n line: declared.line,\n expected: \"Protected Brandlab platform surfaces are imported from the shared packages\",\n actual: `${declared.name} is declared locally instead of imported from the shared packages.`,\n remediation: `Import ${declared.name} from @brandlab-digital/site-core or site-next and remove the local copy.`,\n }));\n }\n for (const api of RETIRED_SOURCE_APIS) {\n const match = file.executable.match(api.pattern);\n if (!match || match.index === undefined) continue;\n context.findings.push(staticFinding({\n ruleId: retired,\n surface: \"source\",\n path: file.path,\n line: lineAt(file.text, match.index),\n expected: \"Only current 3.0 platform APIs\",\n actual: `The project still uses ${api.label}, which 3.0 removed.`,\n remediation: \"Migrate the caller to the current shared API and delete the retired path.\",\n }));\n }\n }\n}\n\nfunction declaredProtectedNames(file: BrandlabSourceFile): { name: string; line: number } | null {\n const source = parseBrandlabSourceFile(file);\n for (const statement of source.statements) {\n const names: { name: string; node: ts.Node }[] = [];\n if ((ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement)) && statement.name) {\n names.push({ name: statement.name.text, node: statement.name });\n } else if (ts.isVariableStatement(statement)) {\n for (const declaration of statement.declarationList.declarations) {\n if (ts.isIdentifier(declaration.name)) names.push({ name: declaration.name.text, node: declaration.name });\n }\n }\n const protectedName = names.find(({ name }) => PROTECTED_PLATFORM_NAMES.has(name));\n if (protectedName) return { name: protectedName.name, line: lineOfNode(file, protectedName.node) };\n }\n return null;\n}\n\n/** Project configuration keys removed in 3.0.0. */\nconst RETIRED_CONFIG_KEYS: readonly { pattern: RegExp; key: string; label: string; remediation: string }[] = [\n {\n pattern: /\\broutes\\s*:\\s*\\{[^{}]*\\baliases\\s*:/,\n key: \"aliases\",\n label: \"routes.aliases\",\n remediation: \"Move each alias into the redirect table in src/data/redirects.ts.\",\n },\n {\n pattern: /\\bprofile\\s*:/,\n key: \"profile\",\n label: \"the profile field\",\n remediation: \"Delete the profile field; defineBrandlabProject rejects unknown keys.\",\n },\n];\n\nfunction inspectRetiredConfiguration(context: StaticRuleContext) {\n if (!context.config) return;\n const ruleId = \"brandlab-source-retired-api\";\n recordEvaluation(context.evaluations, \"source\", ruleId);\n const config = stripCommentsPreservingLayout(context.config);\n for (const retired of RETIRED_CONFIG_KEYS) {\n const match = config.match(retired.pattern);\n if (!match || match.index === undefined) continue;\n context.findings.push(staticFinding({\n ruleId,\n surface: \"source\",\n path: \"brandlab.config.ts\",\n line: lineAt(context.config, match.index + match[0].lastIndexOf(retired.key)),\n expected: \"Only current 3.0 platform APIs\",\n actual: `brandlab.config.ts still declares ${retired.label}, which 3.0 removed.`,\n remediation: retired.remediation,\n }));\n }\n}\n\n// --- structural: CI and deployment -------------------------------------------\n\nfunction inspectWorkflowPins(context: StaticRuleContext) {\n const directory = join(context.root, \".github/workflows\");\n if (!isDirectory(directory)) return;\n const workflows = readdirSync(directory).filter((name) => /\\.ya?ml$/.test(name)).sort();\n if (workflows.length === 0) return;\n const ruleId = \"brandlab-ci-workflow-pinned\";\n recordEvaluation(context.evaluations, \"project-verification\", ruleId);\n for (const name of workflows) {\n const path = `.github/workflows/${name}`;\n const text = readFileSync(join(context.root, path), \"utf8\");\n for (const match of text.matchAll(/^[ \\t]*-?[ \\t]*uses[ \\t]*:[ \\t]*['\"]?([^'\"\\s#]+)/gm)) {\n const reference = match[1]!;\n if (reference.startsWith(\"./\") || reference.startsWith(\"docker://\")) continue;\n if (/@[0-9a-f]{40}$/.test(reference)) continue;\n context.findings.push(staticFinding({\n ruleId,\n surface: \"project-verification\",\n path,\n line: lineAt(text, match.index ?? 0),\n expected: \"Every reused workflow and action pinned to a full 40-character commit SHA\",\n actual: `${reference} is not pinned to an immutable commit.`,\n remediation: \"Pin the reference to the fleet workflow SHA recorded in the control repo.\",\n }));\n }\n }\n}\n\nfunction inspectVercelIgnore(context: StaticRuleContext) {\n const text = readOptionalFile(join(context.root, \".vercelignore\"));\n if (text === null) return;\n const ruleId = \"brandlab-deployment-vercelignore-lockfile\";\n recordEvaluation(context.evaluations, \"deployment\", ruleId);\n const excluded = [\"package.json\", \"package-lock.json\"].filter((file) => isIgnored(text, file));\n if (excluded.length === 0) return;\n context.findings.push(staticFinding({\n ruleId,\n surface: \"deployment\",\n path: \".vercelignore\",\n expected: \".vercelignore never excludes package.json or package-lock.json\",\n actual: `.vercelignore excludes ${excluded.join(\" and \")}, so Vercel cannot install the exact locked release.`,\n remediation: \"Remove the package manifest and lockfile patterns from .vercelignore.\",\n }));\n}\n\n/** Evaluate gitignore-style patterns (last match wins) for a root-level file. */\nexport function isIgnored(patterns: string, file: string): boolean {\n let ignored = false;\n for (const rawLine of patterns.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (!line || line.startsWith(\"#\")) continue;\n const negated = line.startsWith(\"!\");\n let pattern = negated ? line.slice(1) : line;\n if (pattern.endsWith(\"/\")) continue;\n pattern = pattern.replace(/^\\//, \"\").replace(/^\\*\\*\\//, \"\");\n if (pattern.includes(\"/\")) continue;\n if (globMatch(pattern, file)) ignored = !negated;\n }\n return ignored;\n}\n\n// --- shared helpers ----------------------------------------------------------\n\nexport interface ContactContractRecipient {\n path: string;\n line: number;\n /** The literal delivery.recipientEnv key, or null when it is not statically declared. */\n recipientEnv: string | null;\n}\n\n/** Every defineContactContract call and the recipient environment key it declares. */\nexport function findContactContractRecipients(\n source: BrandlabSourceIndex,\n): ContactContractRecipient[] {\n return source.files.flatMap((file) =>\n findImportedCalls(file, SITE_CORE(\"contact\"), \"defineContactContract\").map((call) => ({\n path: file.path,\n line: lineOfNode(file, call),\n recipientEnv: stringLiteralValue(\n objectPropertyValue(objectPropertyValue(call.arguments[0], \"delivery\"), \"recipientEnv\"),\n ),\n })),\n );\n}\n\n/** Framework route file candidates under src/app, then a legacy root app/. */\nfunction routeCandidates(name: string): string[] {\n return [\"src/app\", \"app\"].flatMap((directory) =>\n SOURCE_EXTENSIONS.map((extension) => posix.join(directory, `${name}.${extension}`)));\n}\n\nfunction firstExisting(context: StaticRuleContext, candidates: readonly string[]): string | null {\n return candidates.find((path) => context.source.byPath.has(path) || existsSync(join(context.root, path))) ?? null;\n}\n\nfunction localImports(\n context: StaticRuleContext,\n resolver: BrandlabModuleResolver,\n file: BrandlabSourceFile,\n): BrandlabSourceFile[] {\n return listModuleReferences(file)\n .filter((reference) => !reference.typeOnly)\n .flatMap((reference) => {\n const resolved = resolver(file.path, reference.specifier);\n const target = resolved ? context.source.byPath.get(resolved) : undefined;\n return target ? [target] : [];\n });\n}\n\n/** Names a module exports, including `export { local as POST }` forms. */\nexport function exportedNames(file: BrandlabSourceFile): Set<string> {\n const names = new Set<string>();\n for (const statement of parseBrandlabSourceFile(file).statements) {\n const exported = ts.canHaveModifiers(statement) &&\n ts.getModifiers(statement)?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);\n if (exported && (ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement)) && statement.name) {\n names.add(statement.name.text);\n } else if (exported && ts.isVariableStatement(statement)) {\n for (const declaration of statement.declarationList.declarations) {\n if (ts.isIdentifier(declaration.name)) names.add(declaration.name.text);\n }\n } else if (ts.isExportDeclaration(statement) && statement.exportClause && ts.isNamedExports(statement.exportClause)) {\n for (const element of statement.exportClause.elements) names.add(element.name.text);\n }\n }\n return names;\n}\n\nfunction readOptionalFile(path: string): string | null {\n return existsSync(path) ? readFileSync(path, \"utf8\") : null;\n}\n"]}
1
+ {"version":3,"file":"static-rules.js","sourceRoot":"","sources":["../src/static-rules.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { join, posix } from \"node:path\";\nimport ts from \"typescript\";\nimport { globMatch } from \"./glob.js\";\nimport type { BrandlabFinding } from \"./project.js\";\nimport {\n findWordingInMarkdown,\n findWordingInSource,\n isPublicDocumentPath,\n isPublicModulePath,\n parseJsonSource,\n type PublicCopyFinding,\n} from \"./public-copy.js\";\nimport {\n BRANDLAB_SOURCE_ROOT_DIRECTORIES,\n createBrandlabModuleResolver,\n findImportedCalls,\n importedLocalNames,\n isDirectory,\n lineAt,\n stripCommentsPreservingLayout,\n lineOfNode,\n listModuleReferences,\n objectPropertyValue,\n parseBrandlabSourceFile,\n stringLiteralValue,\n type BrandlabModuleResolver,\n type BrandlabSourceFile,\n type BrandlabSourceIndex,\n walkProjectFiles,\n} from \"./source-files.js\";\nimport type { BrandlabRuleEvaluation } from \"./verification-policy.js\";\n\nconst SITE_CORE = (module: string) => new RegExp(`^@brandlab-digital/site-core/${module}$`);\nconst SITE_NEXT = (module: string) => new RegExp(`^@brandlab-digital/site-next/${module}$`);\nconst SITE_NEXT_ANY = /^@brandlab-digital\\/site-next(?:\\/|$)/;\nconst SOURCE_EXTENSIONS = [\"ts\", \"tsx\", \"js\", \"jsx\", \"mjs\"];\n\nexport interface StaticRuleContext {\n root: string;\n source: BrandlabSourceIndex;\n /** brandlab.config.ts text, or null when it is missing. */\n config: string | null;\n findings: BrandlabFinding[];\n evaluations: BrandlabRuleEvaluation[];\n}\n\nexport function staticFinding(options: {\n ruleId: string;\n surface: string;\n expected: string;\n actual: string;\n remediation: string;\n path?: string;\n line?: number;\n severity?: BrandlabFinding[\"severity\"];\n}): BrandlabFinding {\n return {\n ruleId: options.ruleId,\n surface: options.surface,\n severity: options.severity ?? \"blocker\",\n contract: { name: \"project\", version: \"current-only-v2\" },\n evidenceKind: \"static\",\n ...(options.path ? { path: options.path } : {}),\n ...(options.line ? { line: options.line } : {}),\n expected: options.expected,\n actual: options.actual,\n remediation: options.remediation,\n };\n}\n\nexport function recordEvaluation(\n evaluations: BrandlabRuleEvaluation[],\n surface: string,\n ...ruleIds: string[]\n) {\n for (const ruleId of ruleIds) evaluations.push({ ruleId, surface });\n}\n\n/** The minimal static rules behind the checks that previously passed without evidence. */\nexport function inspectStaticRules(context: StaticRuleContext) {\n const project = describeProject(context);\n inspectContactProviderRoute(context, project);\n inspectAnalyticsPrivacy(context);\n inspectGoogleTagOwner(context);\n inspectGoogleTagConsent(context);\n inspectSearchRouting(context, project);\n inspectBusinessFacts(context);\n inspectSharedBindings(context);\n inspectRouteCatalogue(context, project);\n inspectLocationEstate(context, project);\n inspectImplementationWording(context);\n inspectPlatformReimplementation(context);\n inspectRetiredConfiguration(context);\n inspectWorkflowPins(context);\n inspectVercelIgnore(context);\n inspectImageRemotePatterns(context);\n}\n\nexport interface BrandlabProjectCapabilities {\n contactEnabled: boolean;\n reviewsEnabled: boolean;\n locationsDeclared: boolean;\n sitemapMode: \"single\" | \"split\" | null;\n}\n\n/** Capabilities declared by brandlab.config.ts, the contact route and the location data. */\nexport function describeCapabilities(root: string, config: string | null): BrandlabProjectCapabilities {\n const text = config ?? \"\";\n const families = text.match(/\\bfamilies\\s*:\\s*\\[([^\\]]*)\\]/)?.[1] ?? \"\";\n const strategy = text.match(/\\blocations\\s*:\\s*\\{[^{}]*\\bstrategy\\s*:\\s*['\"]([a-z-]+)['\"]/)?.[1];\n return {\n contactEnabled:\n /\\bcontact\\s*:\\s*\\{/.test(text) ||\n routeCandidates(\"api/contact/route\").some((path) => existsSync(join(root, path))),\n reviewsEnabled: /\\breviews\\s*:\\s*\\{/.test(text),\n locationsDeclared:\n /['\"](?:locations|service-locations)['\"]/.test(families) ||\n (strategy !== undefined && strategy !== \"none\") ||\n isDirectory(join(root, \"src/data/locations\")),\n sitemapMode: (text.match(/\\bsitemap\\s*:\\s*\\{[^{}]*\\bmode\\s*:\\s*['\"](single|split)['\"]/)?.[1] ??\n null) as BrandlabProjectCapabilities[\"sitemapMode\"],\n };\n}\n\ninterface ProjectShape extends BrandlabProjectCapabilities {\n resolver: BrandlabModuleResolver;\n catalogueFiles: string[];\n}\n\nfunction describeProject(context: StaticRuleContext): ProjectShape {\n const capabilities = describeCapabilities(context.root, context.config);\n return {\n ...capabilities,\n contactEnabled: capabilities.contactEnabled || findContactContractRecipients(context.source).length > 0,\n resolver: createBrandlabModuleResolver(context.root, new Set(context.source.byPath.keys())),\n catalogueFiles: context.source.files\n .filter((file) => findImportedCalls(file, SITE_CORE(\"routes\"), \"defineRouteCatalog\").length > 0)\n .map((file) => file.path),\n };\n}\n\n// --- contact-provider-errors -------------------------------------------------\n\nfunction inspectContactProviderRoute(context: StaticRuleContext, project: ProjectShape) {\n if (!project.contactEnabled) return;\n const ruleId = \"brandlab-contact-provider-route\";\n recordEvaluation(context.evaluations, \"contact\", ruleId);\n const expected =\n \"POST /api/contact produced by the shared handler (createBrandlabContactRouteHandler, or createBrandlabContactRuntime during transition)\";\n const remediation =\n \"Export POST = createBrandlabContactRouteHandler({ contract, runtime }) from @brandlab-digital/site-next/contact/server.\";\n const route = firstExisting(context, routeCandidates(\"api/contact/route\"));\n if (!route) {\n context.findings.push(staticFinding({\n ruleId, surface: \"contact\", path: \"src/app/api/contact/route.ts\", expected, remediation,\n actual: \"The contact capability is enabled but src/app/api/contact/route.ts is missing.\",\n }));\n return;\n }\n const file = context.source.byPath.get(route);\n if (!file || !exportedNames(file).has(\"POST\")) {\n context.findings.push(staticFinding({\n ruleId, surface: \"contact\", path: route, expected, remediation,\n actual: \"The contact route does not export a POST handler.\",\n }));\n return;\n }\n const contactServer = SITE_NEXT(\"contact/server\");\n const direct = findImportedCalls(file, contactServer, \"createBrandlabContactRouteHandler\").length > 0;\n const runtimeModules = [file, ...localImports(context, project.resolver, file)];\n const transitional =\n /\\.contactRouteHandler\\b/.test(file.executable) &&\n runtimeModules.some((candidate) =>\n findImportedCalls(candidate, contactServer, \"createBrandlabContactRuntime\").length > 0);\n if (!direct && !transitional) {\n context.findings.push(staticFinding({\n ruleId, surface: \"contact\", path: route, expected, remediation,\n actual: \"The POST handler is not created by the shared contact runtime, so provider errors are project-owned.\",\n }));\n }\n}\n\n// --- analytics-privacy -------------------------------------------------------\n\nconst ANALYTICS_SINKS = new Set([\n \"gtag\", \"window.gtag\", \"globalThis.gtag\",\n \"dataLayer.push\", \"window.dataLayer.push\", \"globalThis.dataLayer.push\",\n \"sendGAEvent\", \"sendGTMEvent\", \"trackBrandlabBrowserEvent\", \"trackBrandlabEvent\", \"ReactGA.event\",\n]);\n\nconst PII_TOKENS = new Set([\n \"attachment\", \"attachment_name\", \"contact_email\", \"contact_name\", \"customer_name\", \"email\",\n \"email_address\", \"enquiry_message\", \"file_name\", \"filename\", \"first_name\", \"form_message\",\n \"full_name\", \"last_name\", \"message\", \"mobile\", \"mobile_number\", \"phone\", \"phone_number\",\n \"residential_address\", \"street_address\", \"user_email\", \"user_phone\",\n]);\n\nfunction inspectAnalyticsPrivacy(context: StaticRuleContext) {\n if (context.source.files.length === 0) return;\n const ruleId = \"brandlab-analytics-pii-payload\";\n recordEvaluation(context.evaluations, \"analytics\", ruleId);\n for (const file of context.source.files) {\n const visit = (node: ts.Node) => {\n if (ts.isCallExpression(node) && ANALYTICS_SINKS.has(memberPath(node.expression) ?? \"\")) {\n const userData = stringLiteralValue(node.arguments[0]) === \"set\" &&\n stringLiteralValue(node.arguments[1]) === \"user_data\" &&\n node.arguments[2] && !(ts.isObjectLiteralExpression(node.arguments[2]) && node.arguments[2].properties.length === 0);\n const piiNode = userData ? node.arguments[2] : node.arguments.map(findPiiNode).find(Boolean);\n if (piiNode) {\n context.findings.push(staticFinding({\n ruleId,\n surface: \"analytics\",\n path: file.path,\n line: lineOfNode(file, piiNode),\n expected: \"Analytics payloads carry only the shared allowlisted, non-identifying parameters\",\n actual: userData\n ? \"Project code sets Google user_data; enhanced conversion data is owned by the shared runtime.\"\n : \"A lead contact field, message or attachment detail reaches an analytics payload.\",\n remediation: \"Send events through the shared Brandlab analytics runtime without lead details.\",\n }));\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(parseBrandlabSourceFile(file));\n }\n}\n\nfunction findPiiNode(node: ts.Node | undefined): ts.Node | undefined {\n if (!node) return undefined;\n if (ts.isObjectLiteralExpression(node)) {\n for (const property of node.properties) {\n if (ts.isShorthandPropertyAssignment(property) && isPiiToken(property.name.text)) return property;\n if (ts.isSpreadAssignment(property) && isPiiReference(property.expression)) return property;\n if (!ts.isPropertyAssignment(property)) continue;\n const key = ts.isIdentifier(property.name) || ts.isStringLiteralLike(property.name) ? property.name.text : null;\n if ((key && isPiiToken(key)) || isPiiReference(property.initializer)) return property;\n const nested = findPiiNode(property.initializer);\n if (nested) return nested;\n }\n return undefined;\n }\n if (ts.isArrayLiteralExpression(node)) return node.elements.map(findPiiNode).find(Boolean);\n return isPiiReference(node) ? node : undefined;\n}\n\nfunction isPiiReference(node: ts.Node): boolean {\n if (ts.isIdentifier(node)) return isPiiToken(node.text);\n if (ts.isPropertyAccessExpression(node)) return isPiiToken(node.name.text);\n if (ts.isTemplateExpression(node)) return node.templateSpans.some((span) => isPiiReference(span.expression));\n return false;\n}\n\nfunction isPiiToken(value: string): boolean {\n return PII_TOKENS.has(value.replace(/([a-z0-9])([A-Z])/g, \"$1_$2\").toLowerCase().replace(/[^a-z0-9]+/g, \"_\"));\n}\n\nfunction memberPath(node: ts.Expression): string | null {\n if (ts.isIdentifier(node)) return node.text;\n if (ts.isPropertyAccessExpression(node)) {\n const object = memberPath(node.expression);\n return object ? `${object}.${node.name.text}` : null;\n }\n return null;\n}\n\n// --- analytics-conversion: one Google tag owner ------------------------------\n\nfunction inspectGoogleTagOwner(context: StaticRuleContext) {\n if (context.source.files.length === 0) return;\n const ruleId = \"brandlab-analytics-google-tag-owner\";\n recordEvaluation(context.evaluations, \"analytics\", ruleId);\n const usages = context.source.files.flatMap((file) => {\n const locals = new Set(importedLocalNames(file, SITE_NEXT_ANY, \"BrandlabGoogleTag\"));\n if (locals.size === 0) return [];\n const found: { path: string; line: number }[] = [];\n const visit = (node: ts.Node) => {\n if (\n (ts.isJsxSelfClosingElement(node) || ts.isJsxOpeningElement(node)) &&\n ts.isIdentifier(node.tagName) &&\n locals.has(node.tagName.text)\n ) {\n found.push({ path: file.path, line: lineOfNode(file, node) });\n }\n ts.forEachChild(node, visit);\n };\n visit(parseBrandlabSourceFile(file));\n return found;\n });\n const rootLayouts = new Set(routeCandidates(\"layout\").filter((path) => context.source.byPath.has(path)));\n const expected = \"Exactly one <BrandlabGoogleTag /> rendered from the root layout (src/app/layout.tsx)\";\n const remediation = \"Render BrandlabGoogleTag once, directly in src/app/layout.tsx, and remove wrappers or duplicates.\";\n if (usages.length === 1 && rootLayouts.has(usages[0]!.path)) return;\n context.findings.push(staticFinding({\n ruleId,\n surface: \"analytics\",\n ...(usages[0] ? { path: usages[0].path, line: usages[0].line } : { path: \"src/app/layout.tsx\" }),\n expected,\n actual: usages.length === 0\n ? \"No BrandlabGoogleTag is rendered, so the shared tag and its events are absent.\"\n : usages.length > 1\n ? `BrandlabGoogleTag is rendered ${usages.length} times (${usages.map(({ path, line }) => `${path}:${line}`).join(\", \")}).`\n : \"BrandlabGoogleTag is rendered outside the root layout.\",\n remediation,\n }));\n}\n\n// --- analytics-privacy: the Google tag's consent default follows the contract --\n\nfunction inspectGoogleTagConsent(context: StaticRuleContext) {\n if (context.source.files.length === 0) return;\n const ruleId = \"brandlab-analytics-google-tag-consent\";\n recordEvaluation(context.evaluations, \"analytics\", ruleId);\n for (const file of context.source.files) {\n const locals = new Set(importedLocalNames(file, SITE_NEXT_ANY, \"BrandlabGoogleTag\"));\n if (locals.size === 0) continue;\n const visit = (node: ts.Node) => {\n if (\n (ts.isJsxSelfClosingElement(node) || ts.isJsxOpeningElement(node)) &&\n ts.isIdentifier(node.tagName) &&\n locals.has(node.tagName.text)\n ) {\n for (const attribute of node.attributes.properties) {\n if (!ts.isJsxAttribute(attribute) || !ts.isIdentifier(attribute.name) || attribute.name.text !== \"adUserData\") continue;\n context.findings.push(staticFinding({\n ruleId,\n surface: \"analytics\",\n path: file.path,\n line: lineOfNode(file, attribute),\n expected: \"BrandlabGoogleTag takes its ad_user_data consent default from the analytics binding ({...analytics.googleTag})\",\n actual: \"BrandlabGoogleTag sets adUserData itself, so the Google tag's ad_user_data default no longer follows the analytics contract.\",\n remediation:\n \"Remove the adUserData attribute. Only googleAds.enhancedConversions: { mode: 'disclosed' } in the analytics contract grants it by default, once the privacy policy discloses it.\",\n }));\n }\n }\n ts.forEachChild(node, visit);\n };\n visit(parseBrandlabSourceFile(file));\n }\n}\n\n// --- search-routing ----------------------------------------------------------\n\nfunction inspectSearchRouting(context: StaticRuleContext, project: ProjectShape) {\n if (context.source.directoryRoots.length === 0) return;\n inspectPackageRoute(context, project, {\n ruleId: \"brandlab-robots-package-route\",\n surface: \"robots\",\n candidates: routeCandidates(\"robots\"),\n staticFile: \"public/robots.txt\",\n modules: [SITE_NEXT(\"robots\")],\n packageLabel: \"@brandlab-digital/site-next/robots\",\n needsCatalogue: false,\n });\n inspectPackageRoute(context, project, {\n ruleId: \"brandlab-sitemap-package-route\",\n surface: \"sitemap\",\n candidates: [...routeCandidates(\"sitemap.xml/route\"), ...routeCandidates(\"sitemap\")],\n staticFile: \"public/sitemap.xml\",\n modules: [SITE_NEXT(\"sitemaps\"), SITE_CORE(\"sitemaps\")],\n packageLabel: \"@brandlab-digital/site-next/sitemaps\",\n needsCatalogue: true,\n });\n inspectSitemapMode(context, project);\n inspectMetadataBuilder(context, project);\n}\n\nfunction inspectPackageRoute(\n context: StaticRuleContext,\n project: ProjectShape,\n rule: {\n ruleId: string;\n surface: string;\n candidates: string[];\n staticFile: string;\n modules: RegExp[];\n packageLabel: string;\n needsCatalogue: boolean;\n },\n) {\n recordEvaluation(context.evaluations, rule.surface, rule.ruleId);\n const expected = `The ${rule.surface} route is a thin binding of ${rule.packageLabel}${rule.needsCatalogue ? \" over the route catalogue\" : \"\"}`;\n const remediation = `Serve ${rule.surface} from ${rule.candidates[0]} using ${rule.packageLabel}${rule.needsCatalogue ? \" and the routes from src/data/routes.ts\" : \"\"}.`;\n const report = (actual: string, path: string) => context.findings.push(staticFinding({\n ruleId: rule.ruleId, surface: rule.surface, path, expected, actual, remediation,\n }));\n if (existsSync(join(context.root, rule.staticFile))) {\n report(`${rule.staticFile} bypasses the environment-aware shared ${rule.surface} output.`, rule.staticFile);\n }\n const route = firstExisting(context, rule.candidates);\n const file = route ? context.source.byPath.get(route) : undefined;\n if (!route || !file) {\n report(`No ${rule.surface} route was found.`, rule.candidates[0]!);\n return;\n }\n const references = listModuleReferences(file);\n if (!references.some((reference) => rule.modules.some((module) => module.test(reference.specifier)))) {\n report(`${route} does not use ${rule.packageLabel}.`, route);\n return;\n }\n if (rule.needsCatalogue && project.catalogueFiles.length > 0 && !reachesCatalogue(context, project, file)) {\n report(`${route} does not read the route catalogue.`, route);\n }\n}\n\nfunction inspectSitemapMode(context: StaticRuleContext, project: ProjectShape) {\n if (!project.sitemapMode) return;\n const ruleId = \"brandlab-sitemap-split-mode\";\n recordEvaluation(context.evaluations, \"sitemap\", ruleId);\n const chunkRoute = [\"src/app/sitemaps\", \"app/sitemaps\"].find((path) => isDirectory(join(context.root, path)));\n if (project.sitemapMode === \"split\" ? chunkRoute : !chunkRoute) return;\n context.findings.push(staticFinding({\n ruleId,\n surface: \"sitemap\",\n path: chunkRoute ?? \"brandlab.config.ts\",\n expected: \"/sitemaps/[chunk] exists only when brandlab.config sets sitemap.mode: 'split'\",\n actual: project.sitemapMode === \"split\"\n ? \"sitemap.mode is 'split' but no /sitemaps/[chunk] route exists.\"\n : `sitemap.mode is 'single' but ${chunkRoute} still serves sitemap chunks.`,\n remediation: \"Keep the sitemap routes and brandlab.config sitemap.mode in agreement.\",\n }));\n}\n\nfunction inspectMetadataBuilder(context: StaticRuleContext, project: ProjectShape) {\n const ruleId = \"brandlab-metadata-route-builder\";\n recordEvaluation(context.evaluations, \"metadata\", ruleId);\n const builders = context.source.files.filter((file) =>\n findImportedCalls(file, SITE_NEXT(\"metadata\"), \"createRouteMetadataBuilder\").length > 0);\n const expected = \"Page metadata built by createRouteMetadataBuilder(site, routes) from @brandlab-digital/site-next/metadata\";\n const remediation = \"Bind pageMetadata = createRouteMetadataBuilder(site, routes) in src/lib/seo/metadata.ts.\";\n if (builders.length === 0) {\n context.findings.push(staticFinding({\n ruleId, surface: \"metadata\", path: \"src/lib/seo/metadata.ts\", expected, remediation,\n actual: \"No module builds page metadata with createRouteMetadataBuilder.\",\n }));\n return;\n }\n if (project.catalogueFiles.length === 0) return;\n for (const builder of builders.filter((file) => !reachesCatalogue(context, project, file))) {\n context.findings.push(staticFinding({\n ruleId, surface: \"metadata\", path: builder.path, expected, remediation,\n actual: \"The metadata builder does not read the route catalogue.\",\n }));\n }\n}\n\nfunction reachesCatalogue(context: StaticRuleContext, project: ProjectShape, file: BrandlabSourceFile): boolean {\n const catalogues = new Set(project.catalogueFiles);\n const seen = new Set<string>([file.path]);\n let frontier = [file];\n for (let depth = 0; depth < 4 && frontier.length > 0; depth += 1) {\n const next: BrandlabSourceFile[] = [];\n for (const current of frontier) {\n for (const imported of localImports(context, project.resolver, current)) {\n if (catalogues.has(imported.path)) return true;\n if (seen.has(imported.path)) continue;\n seen.add(imported.path);\n next.push(imported);\n }\n }\n frontier = next;\n }\n return false;\n}\n\n// --- business-identity and route-identity ------------------------------------\n\nfunction inspectBusinessFacts(context: StaticRuleContext) {\n if (context.source.files.length === 0) return;\n exactlyOneDefinition(context, {\n ruleId: \"brandlab-business-facts\",\n surface: \"business\",\n module: SITE_CORE(\"business\"),\n name: \"defineBrandlabBusiness\",\n expectedPath: \"src/data/businessEvidence.ts\",\n subject: \"Business facts\",\n });\n}\n\n/** The one-owner 3.0 bindings: site identity, redirects, analytics, next.config and instrumentation. */\nfunction inspectSharedBindings(context: StaticRuleContext) {\n if (context.source.files.length === 0) return;\n exactlyOneDefinition(context, {\n ruleId: \"brandlab-site-identity\",\n surface: \"metadata\",\n module: SITE_CORE(\"site\"),\n name: \"defineBrandlabSite\",\n expectedPath: \"src/config/site.ts\",\n subject: \"The site identity\",\n });\n exactlyOneDefinition(context, {\n ruleId: \"brandlab-redirects-table\",\n surface: \"routes\",\n module: SITE_CORE(\"redirects\"),\n name: \"defineRedirects\",\n expectedPath: \"src/data/redirects.ts\",\n subject: \"The redirect table\",\n });\n exactlyOneDefinition(context, {\n ruleId: \"brandlab-analytics-contract\",\n surface: \"analytics\",\n module: SITE_NEXT(\"analytics\"),\n name: \"defineBrandlabAnalytics\",\n expectedPath: \"src/config/analytics.ts\",\n subject: \"The analytics contract\",\n });\n requireBindingCall(context, {\n ruleId: \"brandlab-runtime-next-config\",\n surface: \"runtime\",\n candidates: [\"next.config.ts\", \"next.config.mts\", \"next.config.mjs\", \"next.config.js\"],\n module: SITE_NEXT(\"next-config\"),\n name: \"defineBrandlabNextConfig\",\n expected: \"next.config exports defineBrandlabNextConfig({ site, redirects, ... }) from @brandlab-digital/site-next/next-config\",\n consequence: \"headers, image formats and Preview noindex are then project-owned\",\n });\n requireBindingCall(context, {\n ruleId: \"brandlab-analytics-instrumentation\",\n surface: \"analytics\",\n candidates: [\"src/instrumentation-client.ts\", \"src/instrumentation-client.js\", \"instrumentation-client.ts\", \"instrumentation-client.js\"],\n module: SITE_NEXT(\"instrumentation-client\"),\n name: \"installBrandlabInstrumentation\",\n expected: \"src/instrumentation-client.ts calls installBrandlabInstrumentation(analytics)\",\n consequence: \"telephone taps and the initial landing are not reported by the shared runtime\",\n });\n}\n\nfunction requireBindingCall(\n context: StaticRuleContext,\n rule: {\n ruleId: string;\n surface: string;\n candidates: readonly string[];\n module: RegExp;\n name: string;\n expected: string;\n consequence: string;\n },\n) {\n recordEvaluation(context.evaluations, rule.surface, rule.ruleId);\n const path = rule.candidates.find((candidate) => context.source.byPath.has(candidate));\n const file = path ? context.source.byPath.get(path) : undefined;\n if (file && findImportedCalls(file, rule.module, rule.name).length > 0) return;\n context.findings.push(staticFinding({\n ruleId: rule.ruleId,\n surface: rule.surface,\n path: path ?? rule.candidates[0]!,\n expected: rule.expected,\n actual: file\n ? `${path} does not call ${rule.name}, so ${rule.consequence}.`\n : `${rule.candidates[0]} is missing, so ${rule.consequence}.`,\n remediation: `Call ${rule.name} from the shared package in ${rule.candidates[0]}.`,\n }));\n}\n\nfunction inspectRouteCatalogue(context: StaticRuleContext, project: ProjectShape) {\n if (context.source.files.length === 0) return;\n exactlyOneDefinition(context, {\n ruleId: \"brandlab-routes-catalogue\",\n surface: \"routes\",\n module: SITE_CORE(\"routes\"),\n name: \"defineRouteCatalog\",\n expectedPath: \"src/data/routes.ts\",\n subject: \"The route catalogue\",\n known: project.catalogueFiles,\n });\n}\n\nfunction exactlyOneDefinition(\n context: StaticRuleContext,\n rule: {\n ruleId: string;\n surface: string;\n module: RegExp;\n name: string;\n expectedPath: string;\n subject: string;\n known?: string[];\n },\n) {\n recordEvaluation(context.evaluations, rule.surface, rule.ruleId);\n const owners = rule.known ?? context.source.files\n .filter((file) => findImportedCalls(file, rule.module, rule.name).length > 0)\n .map((file) => file.path);\n if (owners.length === 1) return;\n context.findings.push(staticFinding({\n ruleId: rule.ruleId,\n surface: rule.surface,\n path: owners[0] ?? rule.expectedPath,\n expected: `${rule.subject} declared once with ${rule.name}`,\n actual: owners.length === 0\n ? `No module calls ${rule.name}.`\n : `${rule.name} is called in ${owners.length} modules: ${owners.join(\", \")}.`,\n remediation: `Keep one ${rule.name} owner in ${rule.expectedPath} and import it everywhere else.`,\n }));\n}\n\nfunction inspectLocationEstate(context: StaticRuleContext, project: ProjectShape) {\n if (!project.locationsDeclared) return;\n const ruleId = \"brandlab-routes-location-estate\";\n recordEvaluation(context.evaluations, \"routes\", ruleId);\n const estate = firstExisting(context, SOURCE_EXTENSIONS.slice(0, 2).map((extension) => `src/data/locations/estate.${extension}`));\n const file = estate ? context.source.byPath.get(estate) : undefined;\n if (file && findImportedCalls(file, SITE_CORE(\"locations\"), \"defineLocationEstate\").length > 0) return;\n context.findings.push(staticFinding({\n ruleId,\n surface: \"routes\",\n path: estate ?? \"src/data/locations/estate.ts\",\n expected: \"The published location list declared once in src/data/locations/estate.ts with defineLocationEstate\",\n actual: file\n ? \"src/data/locations/estate.ts does not declare the estate with defineLocationEstate.\"\n : \"The project publishes locations but has no src/data/locations/estate.ts.\",\n remediation: \"Declare the published locations, retained exclusions and any site-owned locations with defineLocationEstate as literal data.\",\n }));\n}\n\n// --- public-output-safety ----------------------------------------------------\n\n/** Directories that can hold public content documents (MDX, Markdown and JSON data). */\nconst DOCUMENT_ROOTS = [...BRANDLAB_SOURCE_ROOT_DIRECTORIES, \"content\", \"posts\"];\n\n/**\n * Implementation wording in anything that can render publicly: JSX text, rendered\n * attributes (alt, title, aria-label and component copy props), copy-bearing string\n * literals in pages, components, metadata, schema, configuration and data, MDX and\n * Markdown content with its frontmatter, and JSON data. Class lists, styles, import\n * paths, keys, types, comparisons, errors and console output are code, not copy.\n */\nfunction inspectImplementationWording(context: StaticRuleContext) {\n const modules = context.source.files.filter((file) => isPublicModulePath(file.path));\n const documents = [...new Set(DOCUMENT_ROOTS)]\n .flatMap((directory) => walkProjectFiles(context.root, directory))\n .filter(isPublicDocumentPath);\n if (modules.length === 0 && documents.length === 0) return;\n const ruleId = \"brandlab-content-implementation-wording\";\n recordEvaluation(context.evaluations, \"content\", ruleId);\n const report = (path: string, finding: PublicCopyFinding) => {\n context.findings.push(staticFinding({\n ruleId,\n surface: \"content\",\n path,\n line: finding.line,\n expected: \"Publicly rendered copy is finished customer copy, not implementation wording\",\n actual: `Implementation-facing wording (${finding.pattern.source}) appears in ${finding.where}.`,\n remediation: \"Replace the wording with the finished customer copy before it can render publicly.\",\n }));\n };\n for (const file of modules) {\n for (const finding of findWordingInSource(parseBrandlabSourceFile(file))) report(file.path, finding);\n }\n for (const path of documents) {\n const text = readFileSync(join(context.root, path), \"utf8\");\n const findings = path.endsWith(\".json\")\n ? findWordingInSource(parseJsonSource(path, text))\n : findWordingInMarkdown(text);\n for (const finding of findings) report(path, finding);\n }\n}\n\n// --- source-safety -----------------------------------------------------------\n\n/** Shared platform surfaces a project must import rather than declare. */\nconst PROTECTED_PLATFORM_NAMES = new Set([\n \"BrandlabBreadcrumbs\", \"BrandlabGoogleTag\", \"ContactFormEmail\", \"SafeRichText\", \"SchemaScript\",\n \"buildBrandlabMetadata\", \"buildLocalBusinessSchema\", \"buildNextMetadata\", \"buildRobotsMetadata\",\n \"buildSchemaGraph\", \"buildSitemapEntries\", \"createBrandlabContactRouteHandler\",\n \"createBrandlabContactRuntime\", \"createBrandlabRobots\", \"createBrandlabSitemapRoute\",\n \"createNextMetadataBuilder\", \"createRouteAwareMdxBlogAdapter\", \"createRouteAwareStructuredBlogAdapter\",\n \"createRouteMetadataBuilder\", \"defineAnalyticsContract\", \"defineBrandlabAnalytics\",\n \"defineBrandlabBusiness\", \"defineBrandlabContact\", \"defineBrandlabNextConfig\", \"defineBrandlabProject\",\n \"defineBrandlabSite\", \"defineBreadcrumbTrail\", \"defineContactContract\", \"defineLocationEstate\",\n \"defineRedirects\", \"defineRouteCatalog\", \"installBrandlabInstrumentation\", \"installPhoneClickListener\",\n \"renderContactEmail\", \"sitemapIndexXmlResponse\", \"sitemapXmlResponse\", \"trackBrandlabBrowserEvent\",\n \"useBrandlabContactForm\",\n]);\n\n/** Package exports removed in 3.0.0 (web-vitals APIs are reported by the analytics rule). */\nconst RETIRED_PACKAGE_EXPORTS = [\n \"TrackedTelephoneLink\", \"shouldIndexSite\", \"buildRobotsMetadata\", \"buildSeoMetadata\", \"buildNextMetadata\",\n \"buildBrandlabNextMetadata\", \"createNextMetadataBuilder\", \"createBrandlabNextMetadataBuilder\",\n \"isBrandlabProductionDeployment\", \"resolveBrowserAnalyticsConfig\", \"resolveBrandlabGoogleTagConfig\",\n \"BRANDLAB_NEXT_HEADER_PROFILES\", \"createContactHttpSubmissionController\", \"trackDeliveredContactResult\",\n \"trackDeliveredContactWithEnhancedConversions\", \"trackDeliveredContact\", \"shouldTrackContactResult\",\n \"isTrackableContactActionResult\",\n];\n\n/** APIs, options and paths removed in 3.0.0; their presence means an unfinished migration. */\nconst RETIRED_SOURCE_APIS: readonly { pattern: RegExp; label: string }[] = [\n ...RETIRED_PACKAGE_EXPORTS.map((name) => ({ pattern: new RegExp(`\\\\b${name}\\\\b`), label: name })),\n { pattern: /\\bALLOW_INDEXING\\b/, label: \"the ALLOW_INDEXING override\" },\n { pattern: /\\bNEXT_PUBLIC_SITE_URL\\b/, label: \"NEXT_PUBLIC_SITE_URL\" },\n {\n pattern: /\\bbuildBrandlabHeaderRules\\s*\\(\\s*\\{[^}]*\\b(?:isProduction|profile)\\b/,\n label: \"buildBrandlabHeaderRules({ isProduction, profile }) (pass the deployment instead)\",\n },\n { pattern: /\\b(?:xRobotsTag|contentSecurityPolicyMode)\\s*:/, label: \"the xRobotsTag or contentSecurityPolicyMode header option\" },\n { pattern: /\\bleadDiagnostics\\s*:/, label: \"the leadDiagnostics flag (lead diagnostics are always sent)\" },\n];\n\nfunction inspectPlatformReimplementation(context: StaticRuleContext) {\n if (context.source.files.length === 0) return;\n const reimplementation = \"brandlab-source-platform-reimplementation\";\n const retired = \"brandlab-source-retired-api\";\n recordEvaluation(context.evaluations, \"source\", reimplementation, retired);\n for (const file of context.source.files) {\n const declared = declaredProtectedNames(file);\n if (declared) {\n context.findings.push(staticFinding({\n ruleId: reimplementation,\n surface: \"source\",\n path: file.path,\n line: declared.line,\n expected: \"Protected Brandlab platform surfaces are imported from the shared packages\",\n actual: `${declared.name} is declared locally instead of imported from the shared packages.`,\n remediation: `Import ${declared.name} from @brandlab-digital/site-core or site-next and remove the local copy.`,\n }));\n }\n for (const api of RETIRED_SOURCE_APIS) {\n const match = file.executable.match(api.pattern);\n if (!match || match.index === undefined) continue;\n context.findings.push(staticFinding({\n ruleId: retired,\n surface: \"source\",\n path: file.path,\n line: lineAt(file.text, match.index),\n expected: \"Only current 3.0 platform APIs\",\n actual: `The project still uses ${api.label}, which 3.0 removed.`,\n remediation: \"Migrate the caller to the current shared API and delete the retired path.\",\n }));\n }\n }\n}\n\nfunction declaredProtectedNames(file: BrandlabSourceFile): { name: string; line: number } | null {\n const source = parseBrandlabSourceFile(file);\n for (const statement of source.statements) {\n const names: { name: string; node: ts.Node }[] = [];\n if ((ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement)) && statement.name) {\n names.push({ name: statement.name.text, node: statement.name });\n } else if (ts.isVariableStatement(statement)) {\n for (const declaration of statement.declarationList.declarations) {\n if (ts.isIdentifier(declaration.name)) names.push({ name: declaration.name.text, node: declaration.name });\n }\n }\n const protectedName = names.find(({ name }) => PROTECTED_PLATFORM_NAMES.has(name));\n if (protectedName) return { name: protectedName.name, line: lineOfNode(file, protectedName.node) };\n }\n return null;\n}\n\n/** Project configuration keys removed in 3.0.0. */\nconst RETIRED_CONFIG_KEYS: readonly { pattern: RegExp; key: string; label: string; remediation: string }[] = [\n {\n pattern: /\\broutes\\s*:\\s*\\{[^{}]*\\baliases\\s*:/,\n key: \"aliases\",\n label: \"routes.aliases\",\n remediation: \"Move each alias into the redirect table in src/data/redirects.ts.\",\n },\n {\n pattern: /\\bprofile\\s*:/,\n key: \"profile\",\n label: \"the profile field\",\n remediation: \"Delete the profile field; defineBrandlabProject rejects unknown keys.\",\n },\n];\n\nfunction inspectRetiredConfiguration(context: StaticRuleContext) {\n if (!context.config) return;\n const ruleId = \"brandlab-source-retired-api\";\n recordEvaluation(context.evaluations, \"source\", ruleId);\n const config = stripCommentsPreservingLayout(context.config);\n for (const retired of RETIRED_CONFIG_KEYS) {\n const match = config.match(retired.pattern);\n if (!match || match.index === undefined) continue;\n context.findings.push(staticFinding({\n ruleId,\n surface: \"source\",\n path: \"brandlab.config.ts\",\n line: lineAt(context.config, match.index + match[0].lastIndexOf(retired.key)),\n expected: \"Only current 3.0 platform APIs\",\n actual: `brandlab.config.ts still declares ${retired.label}, which 3.0 removed.`,\n remediation: retired.remediation,\n }));\n }\n}\n\n// --- structural: CI and deployment -------------------------------------------\n\nfunction inspectWorkflowPins(context: StaticRuleContext) {\n const directory = join(context.root, \".github/workflows\");\n if (!isDirectory(directory)) return;\n const workflows = readdirSync(directory).filter((name) => /\\.ya?ml$/.test(name)).sort();\n if (workflows.length === 0) return;\n const ruleId = \"brandlab-ci-workflow-pinned\";\n recordEvaluation(context.evaluations, \"project-verification\", ruleId);\n for (const name of workflows) {\n const path = `.github/workflows/${name}`;\n const text = readFileSync(join(context.root, path), \"utf8\");\n for (const match of text.matchAll(/^[ \\t]*-?[ \\t]*uses[ \\t]*:[ \\t]*['\"]?([^'\"\\s#]+)/gm)) {\n const reference = match[1]!;\n if (reference.startsWith(\"./\") || reference.startsWith(\"docker://\")) continue;\n if (/@[0-9a-f]{40}$/.test(reference)) continue;\n context.findings.push(staticFinding({\n ruleId,\n surface: \"project-verification\",\n path,\n line: lineAt(text, match.index ?? 0),\n expected: \"Every reused workflow and action pinned to a full 40-character commit SHA\",\n actual: `${reference} is not pinned to an immutable commit.`,\n remediation: \"Pin the reference to the fleet workflow SHA recorded in the control repo.\",\n }));\n }\n }\n}\n\nfunction inspectVercelIgnore(context: StaticRuleContext) {\n const text = readOptionalFile(join(context.root, \".vercelignore\"));\n if (text === null) return;\n const ruleId = \"brandlab-deployment-vercelignore-lockfile\";\n recordEvaluation(context.evaluations, \"deployment\", ruleId);\n const excluded = [\"package.json\", \"package-lock.json\"].filter((file) => isIgnored(text, file));\n if (excluded.length === 0) return;\n context.findings.push(staticFinding({\n ruleId,\n surface: \"deployment\",\n path: \".vercelignore\",\n expected: \".vercelignore never excludes package.json or package-lock.json\",\n actual: `.vercelignore excludes ${excluded.join(\" and \")}, so Vercel cannot install the exact locked release.`,\n remediation: \"Remove the package manifest and lockfile patterns from .vercelignore.\",\n }));\n}\n\n// --- runtime: image remote patterns (3.3.3) -----------------------------------\n\nconst NEXT_CONFIG_FILES = [\"next.config.ts\", \"next.config.mts\", \"next.config.mjs\", \"next.config.js\"];\n\n/**\n * next.config's images.remotePatterns, as the optimiser will fetch them: from 3.3.3 a\n * production build refuses an http, protocol-less or local source, or a wildcard host that\n * admits a local address (blocker: next build would fail), and any other wildcard host or a\n * pattern for every path of a third-party host is\n * reported as a warning (the optimiser fetches such images for anyone who asks:\n * GHSA-cjq9-62q9-8jv4, usage cost). Spreads and conditional entries are the site's own\n * gating and are left alone; images.developmentRemotePatterns is for next dev only.\n */\nfunction inspectImageRemotePatterns(context: StaticRuleContext) {\n const path = NEXT_CONFIG_FILES.find((candidate) => context.source.byPath.has(candidate));\n const file = path ? context.source.byPath.get(path) : undefined;\n if (!path || !file) return;\n const calls = findImportedCalls(file, SITE_NEXT(\"next-config\"), \"defineBrandlabNextConfig\");\n if (calls.length === 0) return;\n const ruleId = \"brandlab-runtime-image-remote-patterns\";\n recordEvaluation(context.evaluations, \"runtime\", ruleId);\n const ownHosts = canonicalHosts(context);\n for (const call of calls) {\n const images = sameFileObject(file, propertyExpression(unwrapExpression(call.arguments[0]), \"images\"));\n const patterns = sameFileArray(file, propertyExpression(images, \"remotePatterns\"));\n if (!patterns) continue;\n patterns.elements.forEach((element, index) => {\n const pattern = unwrapExpression(element);\n if (!pattern || !ts.isObjectLiteralExpression(pattern)) return;\n const protocolNode = unwrapExpression(objectPropertyValue(pattern, \"protocol\"));\n const hostname = stringLiteralValue(unwrapExpression(objectPropertyValue(pattern, \"hostname\")));\n const pathnameNode = unwrapExpression(objectPropertyValue(pattern, \"pathname\"));\n const pathname = pathnameNode ? stringLiteralValue(pathnameNode) : undefined;\n // A computed host, protocol or path cannot be judged here; defineBrandlabNextConfig checks it at build time.\n if (hostname === null || (protocolNode && stringLiteralValue(protocolNode) === null) || pathname === null) return;\n const protocol = protocolNode ? stringLiteralValue(protocolNode) : undefined;\n const shown = `${protocol ?? \"any protocol\"}://${hostname}${pathname === undefined ? \"/**\" : pathname.startsWith(\"/\") ? pathname : `/${pathname}`}`;\n const at = { ruleId, surface: \"runtime\", path, line: lineOfNode(file, pattern) };\n if (protocol !== \"https\" || isLocalImageHost(hostname)) {\n context.findings.push(staticFinding({\n ...at,\n expected: \"Remote image sources a production build fetches are https on public hosts\",\n actual: `images.remotePatterns[${index}] allows ${shown}: from 3.3.3 a production build refuses an image source that uses http, names no protocol, or names or admits a local address, so next build fails.`,\n remediation: \"Remove the pattern, name the exact public hosts instead of a wildcard that admits local addresses, or move a development-only source (such as http://localhost) to images.developmentRemotePatterns, which only next dev uses.\",\n }));\n return;\n }\n const wildcardHost = hostname.includes(\"*\");\n const everyPath = pathname === undefined || /^\\/?\\*\\*$/.test(pathname);\n if (!wildcardHost && (!everyPath || ownHosts.has(hostname.toLowerCase()))) return;\n context.findings.push(staticFinding({\n ...at,\n severity: \"warning\",\n expected: \"Remote image patterns name the hosts and paths the site's images come from\",\n actual: wildcardHost\n ? `images.remotePatterns[${index}] (${shown}) lets the image optimiser fetch from every host matching ${hostname}, for anyone who asks.`\n : `images.remotePatterns[${index}] (${shown}) lets the image optimiser fetch any path on ${hostname}, for anyone who asks.`,\n remediation: wildcardHost\n ? \"List the exact hosts the site's images come from, or serve local copies under public/.\"\n : \"Narrow pathname to the folders the site's images use (for example /vi/** or /images/**), or serve local copies under public/.\",\n }));\n });\n }\n}\n\n/** The site's canonical host and its www twin, from the defineBrandlabSite call in src/config/site.ts. */\nfunction canonicalHosts(context: StaticRuleContext): Set<string> {\n const hosts = new Set<string>();\n for (const file of context.source.files) {\n for (const call of findImportedCalls(file, SITE_CORE(\"site\"), \"defineBrandlabSite\")) {\n const url = stringLiteralValue(unwrapExpression(objectPropertyValue(unwrapExpression(call.arguments[0]), \"canonicalUrl\")));\n if (!url) continue;\n try {\n const host = new URL(url).hostname.toLowerCase();\n hosts.add(host);\n hosts.add(host.startsWith(\"www.\") ? host.slice(4) : `www.${host}`);\n } catch {\n // not a URL: nothing to exempt\n }\n }\n }\n return hosts;\n}\n\n/** Loopback, unspecified, private, shared and link-local hosts in any URL spelling, and wildcard hosts that admit one, as defineBrandlabNextConfig refuses them. */\nexport function isLocalImageHost(hostname: string): boolean {\n const host = hostname.trim().toLowerCase().replace(/^\\[(.*)\\]$/, \"$1\").replace(/\\.$/, \"\");\n // Other picomatch syntax (?, braces, classes, extglobs) cannot be judged here, so it is refused.\n if (/[?{}[\\]()!@+]/.test(host)) return true;\n // A wildcard host is local when it admits a local address: Next matches hostnames with picomatch, whose `*` stops\n // only at a slash, so `*` and `**` both admit `localhost`, and `10.*.*.*` admits 10.0.0.1. Any wildcard address\n // (`192.168.1.*`, `fd12:*`) counts as local.\n if (host.includes(\"*\")) {\n if (/^[\\d.*]+$/.test(host) || host.includes(\":\")) return true;\n const source = host.split(/(\\*\\*|\\*)/).map((part) => (part === \"**\" ? \".*\" : part === \"*\" ? \"[^/]*\" : part.replace(/[.+?^$()|{}[\\]\\\\]/g, \"\\\\$&\"))).join(\"\");\n const glob = new RegExp(\"^\" + source + \"$\");\n return LOCAL_HOST_SAMPLES.some((sample) => glob.test(sample));\n }\n // The address a URL reads it as: 127.1, 0x7f.0.0.1 and [::ffff:127.0.0.1] all name 127.0.0.1.\n let named = host;\n try {\n named = new URL(\"https://\" + (host.includes(\":\") ? \"[\" + host + \"]\" : host)).hostname.replace(/^\\[(.*)\\]$/, \"$1\");\n } catch {\n // not a host a URL can name: judged as written\n }\n if (named === \"localhost\" || named.endsWith(\".localhost\")) return true;\n const hex = named.match(/^(?:0{0,4}:){0,5}:?ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/);\n const dotted = hex ? [parseInt(hex[1]!, 16) >> 8, parseInt(hex[1]!, 16) & 255, parseInt(hex[2]!, 16) >> 8, parseInt(hex[2]!, 16) & 255].join(\".\") : undefined;\n const mapped = named.match(/^(?:0{0,4}:){0,5}:?ffff:(\\d{1,3}(?:\\.\\d{1,3}){3})$/);\n const ipv4 = (dotted ?? mapped?.[1] ?? named).match(/^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/);\n if (ipv4) {\n const [a, b] = [Number(ipv4[1]), Number(ipv4[2])];\n return a === 0 || a === 10 || a === 127 || (a === 169 && b === 254) || (a === 172 && b >= 16 && b <= 31) ||\n (a === 192 && b === 168) || (a === 100 && b >= 64 && b <= 127);\n }\n if (!named.includes(\":\")) return false;\n const groups = named.split(\":\");\n const allZero = (parts: string[]) => parts.every((part) => /^0*$/.test(part));\n // :: and ::1 in any spelling (0:0:0:0:0:0:0:1), then the private and link-local prefixes.\n if (allZero(groups) || (allZero(groups.slice(0, -1)) && /^0*1$/.test(groups.at(-1) ?? \"\"))) return true;\n return /^f[cd][0-9a-f]{0,2}:/.test(named) || /^fe[89ab][0-9a-f]?:/.test(named);\n}\n\n/** One address in each local range, to judge a wildcard host by. */\nconst LOCAL_HOST_SAMPLES = [\"localhost\", \"a.localhost\", \"0.0.0.0\", \"10.0.0.1\", \"100.64.0.1\", \"127.0.0.1\", \"169.254.169.254\", \"172.16.0.1\", \"192.168.0.1\", \"::1\", \"fc00::1\", \"fe80::1\"];\n\nfunction unwrapExpression(node: ts.Node | undefined): ts.Expression | undefined {\n let current = node as ts.Expression | undefined;\n while (current && (ts.isAsExpression(current) || ts.isSatisfiesExpression(current) || ts.isParenthesizedExpression(current) || ts.isNonNullExpression(current))) {\n current = current.expression;\n }\n return current;\n}\n\n/** A property's value, including shorthand (`{ remotePatterns }` gives the identifier). */\nfunction propertyExpression(node: ts.Node | undefined, name: string): ts.Expression | undefined {\n if (!node || !ts.isObjectLiteralExpression(node)) return undefined;\n for (const property of node.properties) {\n if (ts.isShorthandPropertyAssignment(property) && property.name.text === name) return property.name;\n }\n return objectPropertyValue(node, name);\n}\n\n/** The initializer of a top-level `const name = …` in the same file, unwrapped. */\nfunction sameFileInitializer(file: BrandlabSourceFile, name: string): ts.Expression | undefined {\n for (const statement of parseBrandlabSourceFile(file).statements) {\n if (!ts.isVariableStatement(statement)) continue;\n for (const declaration of statement.declarationList.declarations) {\n if (ts.isIdentifier(declaration.name) && declaration.name.text === name) return unwrapExpression(declaration.initializer);\n }\n }\n return undefined;\n}\n\n/** An array literal, directly or through a top-level `const name = [...]` in the same file. */\nfunction sameFileArray(file: BrandlabSourceFile, node: ts.Expression | undefined): ts.ArrayLiteralExpression | undefined {\n const value = unwrapExpression(node);\n const resolved = value && ts.isIdentifier(value) ? sameFileInitializer(file, value.text) : value;\n return resolved && ts.isArrayLiteralExpression(resolved) ? resolved : undefined;\n}\n\n/** An object literal, directly or through a top-level `const name = {...}` in the same file. */\nfunction sameFileObject(file: BrandlabSourceFile, node: ts.Expression | undefined): ts.ObjectLiteralExpression | undefined {\n const value = unwrapExpression(node);\n const resolved = value && ts.isIdentifier(value) ? sameFileInitializer(file, value.text) : value;\n return resolved && ts.isObjectLiteralExpression(resolved) ? resolved : undefined;\n}\n\n/** Evaluate gitignore-style patterns (last match wins) for a root-level file. */\nexport function isIgnored(patterns: string, file: string): boolean {\n let ignored = false;\n for (const rawLine of patterns.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (!line || line.startsWith(\"#\")) continue;\n const negated = line.startsWith(\"!\");\n let pattern = negated ? line.slice(1) : line;\n if (pattern.endsWith(\"/\")) continue;\n pattern = pattern.replace(/^\\//, \"\").replace(/^\\*\\*\\//, \"\");\n if (pattern.includes(\"/\")) continue;\n if (globMatch(pattern, file)) ignored = !negated;\n }\n return ignored;\n}\n\n// --- shared helpers ----------------------------------------------------------\n\nexport interface ContactContractRecipient {\n path: string;\n line: number;\n /** The literal delivery.recipientEnv key, or null when it is not statically declared. */\n recipientEnv: string | null;\n}\n\n/** Every defineContactContract call and the recipient environment key it declares. */\nexport function findContactContractRecipients(\n source: BrandlabSourceIndex,\n): ContactContractRecipient[] {\n return source.files.flatMap((file) =>\n findImportedCalls(file, SITE_CORE(\"contact\"), \"defineContactContract\").map((call) => ({\n path: file.path,\n line: lineOfNode(file, call),\n recipientEnv: stringLiteralValue(\n objectPropertyValue(objectPropertyValue(call.arguments[0], \"delivery\"), \"recipientEnv\"),\n ),\n })),\n );\n}\n\n/** Framework route file candidates under src/app, then a legacy root app/. */\nfunction routeCandidates(name: string): string[] {\n return [\"src/app\", \"app\"].flatMap((directory) =>\n SOURCE_EXTENSIONS.map((extension) => posix.join(directory, `${name}.${extension}`)));\n}\n\nfunction firstExisting(context: StaticRuleContext, candidates: readonly string[]): string | null {\n return candidates.find((path) => context.source.byPath.has(path) || existsSync(join(context.root, path))) ?? null;\n}\n\nfunction localImports(\n context: StaticRuleContext,\n resolver: BrandlabModuleResolver,\n file: BrandlabSourceFile,\n): BrandlabSourceFile[] {\n return listModuleReferences(file)\n .filter((reference) => !reference.typeOnly)\n .flatMap((reference) => {\n const resolved = resolver(file.path, reference.specifier);\n const target = resolved ? context.source.byPath.get(resolved) : undefined;\n return target ? [target] : [];\n });\n}\n\n/** Names a module exports, including `export { local as POST }` forms. */\nexport function exportedNames(file: BrandlabSourceFile): Set<string> {\n const names = new Set<string>();\n for (const statement of parseBrandlabSourceFile(file).statements) {\n const exported = ts.canHaveModifiers(statement) &&\n ts.getModifiers(statement)?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);\n if (exported && (ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement)) && statement.name) {\n names.add(statement.name.text);\n } else if (exported && ts.isVariableStatement(statement)) {\n for (const declaration of statement.declarationList.declarations) {\n if (ts.isIdentifier(declaration.name)) names.add(declaration.name.text);\n }\n } else if (ts.isExportDeclaration(statement) && statement.exportClause && ts.isNamedExports(statement.exportClause)) {\n for (const element of statement.exportClause.elements) names.add(element.name.text);\n }\n }\n return names;\n}\n\nfunction readOptionalFile(path: string): string | null {\n return existsSync(path) ? readFileSync(path, \"utf8\") : null;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brandlab-digital/conformance",
3
- "version": "3.3.1",
3
+ "version": "3.3.3",
4
4
  "license": "UNLICENSED",
5
5
  "repository": {
6
6
  "type": "git",