{"_id":"@arachnodex/job-nfa-report","_rev":"6-64f6d84dcbadc983436aefc805ae404b","name":"@arachnodex/job-nfa-report","dist-tags":{"latest":"1.0.5"},"versions":{"1.0.0":{"name":"@arachnodex/job-nfa-report","version":"1.0.0","keywords":["arachnodex","crawler","assets","cache busting","fingerprint"],"author":{"name":"Rick Kukiela","email":"rick@belniakmedia.com"},"license":"Apache-2.0","_id":"@arachnodex/job-nfa-report@1.0.0","maintainers":[{"name":"rickkukiela","email":"rick@belniakmedia.com"}],"homepage":"https://github.com/Arachnodex/arachnodex#readme","bugs":{"url":"https://github.com/Arachnodex/arachnodex/issues"},"dist":{"shasum":"3254514e1707303e24917387dc97e409c5799ce4","tarball":"https://registry.npmjs.org/@arachnodex/job-nfa-report/-/job-nfa-report-1.0.0.tgz","fileCount":9,"integrity":"sha512-Nn+kRN8ulPBbzy1ryXO1g+Ri3kLIQZ2P/RcT3vwb+r/REfTR1oXufoe3zHXKl2eIbKeDOpocLg4/Fh0hKiES+g==","signatures":[{"sig":"MEQCIH4yN/ZuzItUYeRW08buirtWuWFL5FZEmKc5hAdA9QUPAiBAkNfN4hQ9YCDqe1IezrzFcSgKNApri3OaZ4qShjKLSw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":92293},"main":"bin/index.js","type":"module","types":"types/index.d.ts","engines":{"node":">=22.13.0 <25"},"exports":{".":{"types":"./types/index.d.ts","default":"./bin/index.js","development":"./src/index.ts"},"./config/nfa-report.example.json":"./config/nfa-report.example.json"},"gitHead":"d58d41f13c38355d2bb3c35d1b8c6612d1506fa2","scripts":{"test":"node --conditions=development --import tsx test/*.test.ts","build":"npm run clean:bin && npm run clean:types && esbuild src/index.ts --bundle --platform=node --format=esm --target=node22 --minify --packages=external --outfile=bin/index.js && npm run build:types","clean:bin":"node -e \"const fs=require('node:fs'); fs.rmSync('bin',{recursive:true,force:true}); fs.mkdirSync('bin',{recursive:true});\"","build:types":"tsc -p tsconfig.types.json","clean:types":"node -e \"const fs=require('node:fs'); fs.rmSync('types',{recursive:true,force:true});\""},"_npmUser":{"name":"rickkukiela","email":"rick@belniakmedia.com"},"repository":{"url":"git+https://github.com/Arachnodex/arachnodex.git","type":"git","directory":"packages/job-nfa-report"},"_npmVersion":"11.13.0","description":"Arachnodex job for reporting non-fingerprinted asset references.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"axios":"^1.12.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0","typescript":"^5.6.3","@types/node":"^22","@arachnodex/core":"^1.0.7"},"peerDependencies":{"@arachnodex/core":"^1.0.7"},"_npmOperationalInternal":{"tmp":"tmp/job-nfa-report_1.0.0_1781300441071_0.45445391490928433","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@arachnodex/job-nfa-report","version":"1.0.1","keywords":["arachnodex","crawler","assets","cache busting","fingerprint"],"author":{"name":"Rick Kukiela","email":"rick@belniakmedia.com"},"license":"Apache-2.0","_id":"@arachnodex/job-nfa-report@1.0.1","maintainers":[{"name":"rickkukiela","email":"rick@belniakmedia.com"}],"homepage":"https://github.com/Arachnodex/arachnodex#readme","bugs":{"url":"https://github.com/Arachnodex/arachnodex/issues"},"dist":{"shasum":"c3fc1f80c51417cce50aa907f0c681f43d171177","tarball":"https://registry.npmjs.org/@arachnodex/job-nfa-report/-/job-nfa-report-1.0.1.tgz","fileCount":9,"integrity":"sha512-wCDjrtEBIiu57aprDmDGbmOYebE/Lfy8S1U87HDUjDN/6ZamWmzJWjlt7ebxj9ZTK/AVP2hAOeFnKUT4l936ew==","signatures":[{"sig":"MEUCIAEEGvyP5Nxw/bZBbHzdPeqWA24MaEP/tuS4bHvYwsorAiEA1gUQeC+rFF8nLCrwhjvJO9qRssR3Q9FjduD0AzOjrS0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":92384},"main":"bin/index.js","type":"module","types":"types/index.d.ts","engines":{"node":">=22.13.0 <25"},"exports":{".":{"types":"./types/index.d.ts","default":"./bin/index.js","development":"./src/index.ts"},"./config/nfa-report.example.json":"./config/nfa-report.example.json"},"gitHead":"fb0e633df50ceb88d27341e5ac8818e103375213","scripts":{"test":"node --conditions=development --import tsx test/*.test.ts","build":"npm run clean:bin && npm run clean:types && esbuild src/index.ts --bundle --platform=node --format=esm --target=node22 --minify --packages=external --outfile=bin/index.js && npm run build:types","clean:bin":"node -e \"const fs=require('node:fs'); fs.rmSync('bin',{recursive:true,force:true}); fs.mkdirSync('bin',{recursive:true});\"","build:types":"tsc -p tsconfig.types.json","clean:types":"node -e \"const fs=require('node:fs'); fs.rmSync('types',{recursive:true,force:true});\""},"_npmUser":{"name":"rickkukiela","email":"rick@belniakmedia.com"},"repository":{"url":"git+https://github.com/Arachnodex/arachnodex.git","type":"git","directory":"packages/job-nfa-report"},"_npmVersion":"11.13.0","description":"Arachnodex job for reporting non-fingerprinted asset references.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"axios":"^1.12.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0","typescript":"^5.6.3","@types/node":"^22","@arachnodex/core":"^1.0.7"},"peerDependencies":{"@arachnodex/core":"^1.0.7"},"_npmOperationalInternal":{"tmp":"tmp/job-nfa-report_1.0.1_1781636266441_0.3336985100768126","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@arachnodex/job-nfa-report","version":"1.0.3","keywords":["arachnodex","crawler","assets","cache busting","fingerprint"],"author":{"name":"Rick Kukiela","email":"rick@belniakmedia.com"},"license":"Apache-2.0","_id":"@arachnodex/job-nfa-report@1.0.3","maintainers":[{"name":"rickkukiela","email":"rick@belniakmedia.com"}],"homepage":"https://github.com/Arachnodex/arachnodex#readme","bugs":{"url":"https://github.com/Arachnodex/arachnodex/issues"},"dist":{"shasum":"bdc2af1b22105683c2e71e33742f7cb394fe1b81","tarball":"https://registry.npmjs.org/@arachnodex/job-nfa-report/-/job-nfa-report-1.0.3.tgz","fileCount":9,"integrity":"sha512-CV4Xb7HERRe9TpB1lMGQzXHtxk2yQIIpesBTjaJw0U3MyPM/90AgT5/Ye9RXws2ytLqYZpOd3+zJNf1UEsRXaA==","signatures":[{"sig":"MEUCIEESVqEhmkeQyBvrZ2N47CiT/udKcgmUu8jqW/big3FYAiEAn1DE4gZTYonO3VcBmziMN7+sNOqjv0KJ6A8cCVptuTM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":95555},"main":"bin/index.js","type":"module","types":"types/index.d.ts","engines":{"node":">=22.13.0 <25"},"exports":{".":{"types":"./types/index.d.ts","default":"./bin/index.js","development":"./src/index.ts"},"./config/nfa-report.example.json":"./config/nfa-report.example.json"},"gitHead":"53c650ccf0a97f825b0c84bad88e15d023e850ad","scripts":{"test":"node --conditions=development --import tsx test/*.test.ts","build":"npm run clean:bin && npm run clean:types && esbuild src/index.ts --bundle --platform=node --format=esm --target=node22 --minify --packages=external --outfile=bin/index.js && npm run build:types","clean:bin":"node -e \"const fs=require('node:fs'); fs.rmSync('bin',{recursive:true,force:true}); fs.mkdirSync('bin',{recursive:true});\"","build:types":"tsc -p tsconfig.types.json","clean:types":"node -e \"const fs=require('node:fs'); fs.rmSync('types',{recursive:true,force:true});\""},"_npmUser":{"name":"rickkukiela","email":"rick@belniakmedia.com"},"deprecated":"Published with outdated docs and incomplete Vite/Rollup fingerprint compatibility. Use 1.0.4 or newer.","repository":{"url":"git+https://github.com/Arachnodex/arachnodex.git","type":"git","directory":"packages/job-nfa-report"},"_npmVersion":"11.13.0","description":"Arachnodex job for reporting non-fingerprinted asset references.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"axios":"^1.12.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0","typescript":"^5.6.3","@types/node":"^22","@arachnodex/core":"^1.0.7"},"peerDependencies":{"@arachnodex/core":"^1.0.7"},"_npmOperationalInternal":{"tmp":"tmp/job-nfa-report_1.0.3_1781641217691_0.30877033439141544","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@arachnodex/job-nfa-report","version":"1.0.4","keywords":["arachnodex","crawler","assets","cache busting","fingerprint"],"author":{"name":"Rick Kukiela","email":"rick@belniakmedia.com"},"license":"Apache-2.0","_id":"@arachnodex/job-nfa-report@1.0.4","maintainers":[{"name":"rickkukiela","email":"rick@belniakmedia.com"}],"homepage":"https://github.com/Arachnodex/arachnodex#readme","bugs":{"url":"https://github.com/Arachnodex/arachnodex/issues"},"dist":{"shasum":"935054b935552e6a4902b5ce0c4a05a1a9feab27","tarball":"https://registry.npmjs.org/@arachnodex/job-nfa-report/-/job-nfa-report-1.0.4.tgz","fileCount":9,"integrity":"sha512-8cbgzrvET3OQyBpKswOlJ2cyhOB7CHxNcQLbE5lKXaMmD/CXBDnl7WRj6fgCpoggXP1ZbM8Drt3gDblLwyB72g==","signatures":[{"sig":"MEUCIF6ET+Z7GWCr1/7RnllsdjodeDpfidrtPEpKs69MJ8wcAiEAvR0JKp1AFqwwqyDC/ZRHEhm9CsqBKPRe1m7w9ZlDkeo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":99716},"main":"bin/index.js","type":"module","types":"types/index.d.ts","engines":{"node":">=22.13.0 <25"},"exports":{".":{"types":"./types/index.d.ts","default":"./bin/index.js","development":"./src/index.ts"},"./config/nfa-report.example.json":"./config/nfa-report.example.json"},"gitHead":"bfe94d450ed52306dd60bc38cd7cad7947a763bc","scripts":{"test":"node --conditions=development --import tsx test/*.test.ts","build":"npm run clean:bin && npm run clean:types && esbuild src/index.ts --bundle --platform=node --format=esm --target=node22 --minify --packages=external --outfile=bin/index.js && npm run build:types","clean:bin":"node -e \"const fs=require('node:fs'); fs.rmSync('bin',{recursive:true,force:true}); fs.mkdirSync('bin',{recursive:true});\"","build:types":"tsc -p tsconfig.types.json","clean:types":"node -e \"const fs=require('node:fs'); fs.rmSync('types',{recursive:true,force:true});\""},"_npmUser":{"name":"rickkukiela","email":"rick@belniakmedia.com"},"repository":{"url":"git+https://github.com/Arachnodex/arachnodex.git","type":"git","directory":"packages/job-nfa-report"},"_npmVersion":"11.13.0","description":"Arachnodex job for reporting non-fingerprinted asset references.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"axios":"^1.12.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.25.0","typescript":"^5.6.3","@types/node":"^22","@arachnodex/core":"^1.0.7"},"peerDependencies":{"@arachnodex/core":"^1.0.7"},"_npmOperationalInternal":{"tmp":"tmp/job-nfa-report_1.0.4_1781645634335_0.07143329294438838","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"@arachnodex/job-nfa-report","version":"1.0.5","description":"Arachnodex job for reporting non-fingerprinted asset references.","type":"module","main":"bin/index.js","types":"types/index.d.ts","exports":{".":{"types":"./types/index.d.ts","development":"./src/index.ts","default":"./bin/index.js"},"./config/nfa-report.example.json":"./config/nfa-report.example.json"},"repository":{"type":"git","url":"git+https://github.com/Arachnodex/arachnodex.git","directory":"packages/job-nfa-report"},"keywords":["arachnodex","crawler","assets","cache busting","fingerprint"],"author":{"name":"Rick Kukiela","email":"rick@belniakmedia.com"},"license":"Apache-2.0","bugs":{"url":"https://github.com/Arachnodex/arachnodex/issues"},"homepage":"https://github.com/Arachnodex/arachnodex#readme","publishConfig":{"access":"public"},"scripts":{"clean:bin":"node -e \"const fs=require('node:fs'); fs.rmSync('bin',{recursive:true,force:true}); fs.mkdirSync('bin',{recursive:true});\"","clean:types":"node -e \"const fs=require('node:fs'); fs.rmSync('types',{recursive:true,force:true});\"","build:types":"tsc -p tsconfig.types.json","test":"node --conditions=development --import tsx test/*.test.ts","build":"npm run clean:bin && npm run clean:types && esbuild src/index.ts --bundle --platform=node --format=esm --target=node22 --minify --packages=external --outfile=bin/index.js && npm run build:types"},"dependencies":{"axios":"^1.20.0"},"peerDependencies":{"@arachnodex/core":"^1.0.7"},"devDependencies":{"@arachnodex/core":"^1.0.7","@types/node":"^22","esbuild":"^0.25.0","typescript":"^5.6.3"},"engines":{"node":">=22.13.0 <25"},"gitHead":"56d075dd0cd42082f51c6aa5a85d4ebbe373178c","_id":"@arachnodex/job-nfa-report@1.0.5","_nodeVersion":"24.16.0","_npmVersion":"11.19.1","dist":{"integrity":"sha512-0Ue9e/IVLTkLPjEd8he68o5SjusvbVE/QOayw9sI9ppIMrsfFpw8X/oQoLxqJ8pVNuXV3YY2G7fhfnwgVd0DYg==","shasum":"9e10f3cfbcab089bd5c7b6df9b18647771898866","tarball":"https://registry.npmjs.org/@arachnodex/job-nfa-report/-/job-nfa-report-1.0.5.tgz","fileCount":9,"unpackedSize":99716,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@arachnodex%2fjob-nfa-report@1.0.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIHOiMc5R3A/guUB3PRSQiXisQvxVRRsodUWXiX+9p2F9AiEAn+ktijoSzCkrEWtFoLZNKgG6Olx3UZUXVpIDKPCxy64="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:60756932-a4d3-44f2-a0ea-c49fa52acde0"}},"directories":{},"maintainers":[{"name":"rickkukiela","email":"rick@belniakmedia.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/job-nfa-report_1.0.5_1788284421801_0.9718975362494209"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-12T21:40:40.957Z","modified":"2026-09-01T17:40:22.375Z","1.0.0":"2026-06-12T21:40:41.203Z","1.0.1":"2026-06-16T18:57:46.566Z","1.0.3":"2026-06-16T20:20:17.818Z","1.0.4":"2026-06-16T21:33:54.488Z","1.0.5":"2026-09-01T17:40:21.919Z"},"bugs":{"url":"https://github.com/Arachnodex/arachnodex/issues"},"author":{"name":"Rick Kukiela","email":"rick@belniakmedia.com"},"license":"Apache-2.0","homepage":"https://github.com/Arachnodex/arachnodex#readme","keywords":["arachnodex","crawler","assets","cache busting","fingerprint"],"repository":{"type":"git","url":"git+https://github.com/Arachnodex/arachnodex.git","directory":"packages/job-nfa-report"},"description":"Arachnodex job for reporting non-fingerprinted asset references.","maintainers":[{"name":"rickkukiela","email":"rick@belniakmedia.com"}],"readme":"# @arachnodex/job-nfa-report\n\nThe NFA Report job reports non-fingerprinted asset, media, and document references found during an Arachnodex crawl.\n\nNFA is short for \"non-fingerprinted assets.\" The job is intended for cache-busting audits where long-lived public files should include a build/content fingerprint in the filename or an approved query-string cache-bust value.\n\n## Install\n\nProjects created with `npm create @arachnodex` include this job by default. For a manual install, add it beside `@arachnodex/core`:\n\n```sh\nnpm install @arachnodex/job-nfa-report\n```\n\nThe package uses `@arachnodex/core` as a peer dependency, so it should be installed in the same project as the crawler.\n\n## Usage\n\nRun the job with the default crawler config:\n\n```sh\nnpm exec -- arachnodex -c default -j nfa-report\n```\n\nPrint findings as they are discovered:\n\n```sh\nnpm exec -- arachnodex -c default -j nfa-report -v\n```\n\nAlso scan same-site CSS and JavaScript bodies for nested asset references:\n\n```sh\nnpm exec -- arachnodex -c default -j nfa-report -n\n```\n\nUse both real-time output and nested scanning:\n\n```sh\nnpm exec -- arachnodex -c default -j nfa-report -v -n\n```\n\nRun it with copy/paste prompt output:\n\n```sh\nnpm exec -- arachnodex -c default -j nfa-report -p\n```\n\nUse a job-specific config by placing `-c` after the job name:\n\n```sh\nnpm exec -- arachnodex -c default -j nfa-report -c nfa-report\n```\n\nThat loads the crawler config from `config/default.json` and the NFA Report job config from `config/nfa-report.json`.\n\n## Config File\n\nThe package example config is available at:\n\n```text\nconfig/nfa-report.example.json\n```\n\nA generated Arachnodex project copies this to:\n\n```text\nconfig/nfa-report.json\n```\n\nFor a manual install, copy the example into your Arachnodex project's `config/` directory as `nfa-report.json` when you want to customize the job settings. The job can run with built-in defaults if no job config file exists.\n\nDefault config:\n\n```json\n{\n  \"emailReportEnabled\": true,\n  \"limitMail\": true,\n  \"verbose\": false,\n  \"nested\": false,\n  \"viteRollupFingerprintCompatibility\": true,\n  \"fingerprintPattern\": \"[A-Za-z0-9]{8,}\",\n  \"fingerprintSeparatorPattern\": \"\\\\.\",\n  \"ignorePatterns\": [],\n  \"qsProps\": {\n    \"cb\": \"^\\\\d{10,}$\",\n    \"t\": \"^\\\\d{10,}$\",\n    \"ts\": \"^\\\\d{10,}$\",\n    \"v\": \"^(?:\\\\d{8,}|[A-Za-z0-9._-]{8,})$\",\n    \"ver\": \"^(?:\\\\d{8,}|[A-Za-z0-9._-]{8,})$\",\n    \"version\": \"^(?:\\\\d{8,}|[A-Za-z0-9._-]{8,})$\"\n  },\n  \"assetExtensions\": [\n    \"css\",\n    \"js\",\n    \"mjs\",\n    \"woff\",\n    \"woff2\",\n    \"ttf\",\n    \"otf\",\n    \"eot\",\n    \"ico\",\n    \"png\",\n    \"jpg\",\n    \"jpeg\",\n    \"gif\",\n    \"webp\",\n    \"avif\",\n    \"svg\",\n    \"webmanifest\",\n    \"map\"\n  ],\n  \"mediaExtensions\": [\n    \"mp4\",\n    \"webm\",\n    \"mov\",\n    \"m4v\",\n    \"mp3\",\n    \"wav\",\n    \"ogg\",\n    \"vtt\"\n  ],\n  \"documentExtensions\": [\n    \"pdf\",\n    \"doc\",\n    \"docx\",\n    \"xls\",\n    \"xlsx\",\n    \"ppt\",\n    \"pptx\",\n    \"csv\",\n    \"zip\"\n  ]\n}\n```\n\n## Settings\n\n| Setting | Type | Default | Description |\n| --- | --- | --- | --- |\n| `emailReportEnabled` | boolean | `true` | Include the NFA Report job in Arachnodex report emails. |\n| `limitMail` | boolean | `true` | Suppress this job's regular email report when no non-fingerprinted references were found. |\n| `verbose` | boolean | `false` | Print each unique finding as it is discovered. Can be enabled for one run with `-v` / `--verbose`. Core quiet mode still suppresses this output. |\n| `nested` | boolean | `false` | Scan same-site CSS and JavaScript bodies for nested asset references. Can be enabled for one run with `-n` / `--nested`. |\n| `viteRollupFingerprintCompatibility` | boolean | `true` | Accept Vite/Rollup default eight-character URL-safe hashes for asset and media references when the segment looks hash-like. Disable this for strict separator-only fingerprint detection. |\n| `fingerprintPattern` | string | `\"[A-Za-z0-9]{8,}\"` | Regular expression used to identify a valid hash segment inside a filename stem. The job anchors this pattern to the full segment. |\n| `fingerprintSeparatorPattern` | string | `\"\\\\.\"` | Regular expression used to identify the separator before the filename hash segment. Defaults to a literal dot. Use a character class such as `\"[._-]\"` to accept multiple custom separator characters. |\n| `ignorePatterns` | string[] | `[]` | URL regular expressions to suppress findings that would otherwise be reported. |\n| `qsProps` | object | common cache-bust params | Map of query-string property names to regular expressions. When a URL has a matching property and value, the URL is treated as fingerprinted. |\n| `assetExtensions` | string[] | CSS, JS, fonts, images, manifest, map | File extensions treated as normal asset references. Extensions may be written with or without a leading dot. |\n| `mediaExtensions` | string[] | common audio/video/caption files | File extensions treated as media references. |\n| `documentExtensions` | string[] | common office/document/archive files | File extensions treated as document references. |\n\n## Fingerprint Rules\n\nA URL is accepted as fingerprinted when either the filename or query string proves cache busting.\n\nFilename fingerprints must be the final separated segment before the extension: `name<separator><hash>.<ext>`. By default the configured separator is a literal dot, so the configured shape is `name.<hash>.<ext>`. The default `fingerprintPattern` accepts alphanumeric hash segments of eight or more characters. This avoids treating ordinary words in one-dot filenames like `Products` in `catalog-products-tds_60882.pdf` as fingerprints because they are not in the configured hash-separator position.\n\n### Vite/Rollup Compatibility\n\n`viteRollupFingerprintCompatibility` is an additive compatibility layer for common Vite/Rollup build output. It does not replace `fingerprintPattern`, and it does not change query-string matching.\n\nAs of Vite 8.0.16 with Rollup 4.62.0, Vite's default non-library build output uses Rollup `[hash]` placeholders in patterns like `assets/[name]-[hash].js` and `assets/[name]-[hash].[ext]`. Rollup's default `[hash]` is base64, so generated hashes can contain letters, numbers, `_`, and `-`. Vite's default emitted hashes are commonly eight characters long, such as `DBLn09_S`.\n\nWith the default NFA settings:\n\n- `fingerprintPattern` is still checked first for the configured separator position. The default pattern, `[A-Za-z0-9]{8,}`, accepts normal dot-separated alphanumeric hashes such as `app.2f4a9c0e.css`.\n- When `viteRollupFingerprintCompatibility` is enabled, asset and media references also accept exactly eight URL-safe Rollup/Vite hash characters in the configured separator position, so `pc-bundle.DBLn09_S.js` is accepted even though `_` is not part of the default `fingerprintPattern`.\n- The compatibility layer also accepts default dash-form bundler assets, such as `app-2f4a9c0e.css` and `admin-panel-Ab-cdE1F.css`, when the final dash segment is exactly eight URL-safe hash characters and looks hash-like.\n- A compatibility hash segment looks hash-like when it contains a digit, or when it has mixed-case entropy with at least two uppercase and two lowercase letters. `_` or `-` alone is not enough, so ordinary names such as `customers.help_doc.css` and `product-selector.css` are still reported.\n- The compatibility layer applies only to asset and media references. Document references still require `fingerprintPattern` or `qsProps` to prove fingerprinting.\n\nIf your Vite/Rollup build customizes `rollupOptions.output.hashCharacters`, uses a non-default hash length, or uses a different filename separator, configure `fingerprintPattern` and `fingerprintSeparatorPattern` explicitly. The compatibility setting intentionally targets the default Vite/Rollup hash style instead of trying to recognize every possible custom build format.\n\nDefault behavior comparison:\n\n| URL | Compat enabled | Compat disabled | Why |\n| --- | --- | --- | --- |\n| `/assets/app.2f4a9c0e.css` | accepted | accepted | Dot-separated alphanumeric hash matches the default `fingerprintPattern`. |\n| `/assets/runtime.9A7b6C5d.js` | accepted | accepted | Dot-separated alphanumeric hash matches the default `fingerprintPattern`. |\n| `/assets/pc-bundle.DBLn09_S.js` | accepted | reported | `_` is valid for default Rollup/Vite hashes, but not for the default `fingerprintPattern`. |\n| `/assets/app-2f4a9c0e.css` | accepted | reported | Dash-form `name-[hash].ext` is accepted only by the compatibility layer. |\n| `/assets/admin-panel-Ab-cdE1F.css` | accepted | reported | Dash-form mixed-case/digit hash is accepted only by the compatibility layer. |\n| `/assets/runtime_9A7b6C5d.js` | reported | reported | `_` is not the default configured separator; use `fingerprintSeparatorPattern` for this style. |\n| `/assets/customers.help_doc.css` | reported | reported | `_` alone is not enough to make an ordinary word segment hash-like. |\n| `/documents/manual.DBLn09_S.pdf` | reported | reported | Vite/Rollup compatibility does not apply to document references. |\n\nAccepted examples:\n\n```text\n/assets/app.2f4a9c0e.css\n/assets/runtime.9A7b6C5d.js\n/assets/runtime.AqTz_LpQ.js\n/assets/pc-bundle.DBLn09_S.js\n/assets/app-2f4a9c0e.css\n/assets/admin-panel-Ab-cdE1F.css\n```\n\nTo also accept broader custom dash or underscore hash separators, configure:\n\n```json\n{\n  \"fingerprintSeparatorPattern\": \"[._-]\"\n}\n```\n\nWith that setting, `/assets/app-2f4a9c0e.css` and `/assets/runtime_9A7b6C5d.js` are treated as fingerprinted.\n\nRejected by default examples:\n\n```text\n/assets/app.css\n/assets/2f4a9c0e.css\n/assets/app2f4a9c0e.css\n/assets/runtime_9A7b6C5d.js\n/assets/customers.help_doc.css\n/documents/customers.help_doc.pdf\n/documents/manual.DBLn09_S.pdf\n```\n\nThe second rejected example is only a hash plus extension. The job requires at least one other filename segment before the configured hash separator so reports stay focused on real named assets with build fingerprints.\n\nQuery-string cache busting is controlled by `qsProps`. For example, the default config treats these as valid:\n\n```text\n/assets/app.css?cb=1718048501\n/assets/app.css?v=1718048501\n/assets/app.css?v=20240610\n/assets/app.css?version=2f4a9c0e\n```\n\nUse tighter project-specific patterns if your site has query parameters that look like versions but are not actually cache-bust values.\n\n## Scan Coverage\n\nThe job scans references found in crawled page markup, including:\n\n- Scripts, stylesheets, preloads, icons, manifests, and regular `<link>` references.\n- Images, `srcset` candidates, SVG image/use references, inline styles, and `<style>` blocks.\n- Video, audio, sources, posters, tracks, iframes, embeds, and objects.\n- Open Graph, Twitter, and Microsoft tile image/video metadata.\n- Anchor links to configured asset, media, or document file extensions.\n\nThe job validates only URLs whose extension appears in `assetExtensions`, `mediaExtensions`, or `documentExtensions`. Other URLs are ignored.\n\n## Nested CSS And JavaScript\n\nNested scanning is disabled by default. Enable it with config `nested: true` or the job switch:\n\n```sh\nnpm exec -- arachnodex -c default -j nfa-report -n\n```\n\nWhen enabled, the job downloads same-site CSS, JS, and MJS files already referenced by crawled pages or nested files. It then scans:\n\n- CSS `url(...)`\n- CSS `@import`\n- CSS and JS `sourceMappingURL` comments\n- Conservative JavaScript asset string literals\n\nJavaScript scanning intentionally avoids ordinary relative `.js` / `.mjs` module specifiers, template strings with interpolation, string concatenation, JSON-like broad parsing, and arbitrary library internals. The goal is to catch asset URLs, not every import path or runtime string.\n\nNested fetches are private to this job. They do not add URLs to the shared crawler queue and they do not perform availability reporting.\n\n## Ignore Patterns\n\nUse `ignorePatterns` for references that are expected to remain unfingerprinted, such as third-party URLs, CMS-managed files, or endpoint-style document downloads.\n\n```json\n{\n  \"ignorePatterns\": [\n    \"^https://cdn\\\\.example\\\\.com/vendor/\",\n    \"^/downloads/dynamic-report\\\\.pdf(?:[?#].*)?$\"\n  ]\n}\n```\n\nPatterns are tested against the raw value, absolute URL, path plus query string, path only, and decoded path variants.\n\n## Output\n\nThe console report groups findings by asset, media, and document references. Each entry includes the normalized URL, occurrence count, reference kinds, and sample source URLs.\n\nVerbose mode prints each unique finding as it is discovered:\n\n```sh\nnpm exec -- arachnodex -c default -j nfa-report -v\n```\n\nReport emails include summary counts and grouped finding details. When `limitMail` is `true`, the job suppresses its regular email report if there are no findings.\n\n## Switches\n\n| Switch | Description |\n| --- | --- |\n| `-V`, `--version` | Print the NFA Report job version and exit without crawling. |\n| `-v`, `--verbose` | Print unique findings in real time. Core quiet mode suppresses this output. |\n| `-n`, `--nested` | Scan same-site CSS and JavaScript bodies for nested asset references. |\n| `-p`, `--prompt` | Output grouped findings as copy/paste prompts for another coding agent. |\n","readmeFilename":"README.md"}