@blamejs/blamejs-shop 0.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +87 -0
- package/LICENSE +17 -0
- package/README.md +117 -0
- package/SECURITY.md +139 -0
- package/lib/admin.js +952 -0
- package/lib/analytics.js +267 -0
- package/lib/cart.js +279 -0
- package/lib/catalog-import.js +344 -0
- package/lib/catalog.js +769 -0
- package/lib/checkout.js +320 -0
- package/lib/config.js +151 -0
- package/lib/customers.js +322 -0
- package/lib/email.js +242 -0
- package/lib/externaldb-d1.js +283 -0
- package/lib/index.js +57 -0
- package/lib/inventory-alerts.js +198 -0
- package/lib/newsletter.js +142 -0
- package/lib/order.js +380 -0
- package/lib/payment.js +318 -0
- package/lib/pricing.js +185 -0
- package/lib/r2-bridge.js +169 -0
- package/lib/shipping.js +185 -0
- package/lib/storefront.js +2160 -0
- package/lib/subscriptions.js +410 -0
- package/lib/tax.js +161 -0
- package/lib/theme.js +194 -0
- package/lib/vendor/MANIFEST.json +19 -0
- package/lib/vendor/blamejs/.clusterfuzzlite/Dockerfile +23 -0
- package/lib/vendor/blamejs/.clusterfuzzlite/build.sh +34 -0
- package/lib/vendor/blamejs/.clusterfuzzlite/project.yaml +16 -0
- package/lib/vendor/blamejs/.dockerignore +45 -0
- package/lib/vendor/blamejs/.gitattributes +42 -0
- package/lib/vendor/blamejs/.github/CODEOWNERS +4 -0
- package/lib/vendor/blamejs/.github/FUNDING.yml +2 -0
- package/lib/vendor/blamejs/.github/ISSUE_TEMPLATE/bug_report.md +58 -0
- package/lib/vendor/blamejs/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/lib/vendor/blamejs/.github/ISSUE_TEMPLATE/feature_request.md +99 -0
- package/lib/vendor/blamejs/.github/PULL_REQUEST_TEMPLATE.md +77 -0
- package/lib/vendor/blamejs/.github/dependabot.yml +37 -0
- package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +148 -0
- package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +107 -0
- package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +122 -0
- package/lib/vendor/blamejs/.github/workflows/ci.yml +511 -0
- package/lib/vendor/blamejs/.github/workflows/codeql.yml +50 -0
- package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +655 -0
- package/lib/vendor/blamejs/.github/workflows/release-container.yml +406 -0
- package/lib/vendor/blamejs/.github/workflows/scorecard.yml +101 -0
- package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +134 -0
- package/lib/vendor/blamejs/.gitignore +102 -0
- package/lib/vendor/blamejs/.gitleaks.toml +166 -0
- package/lib/vendor/blamejs/.hadolint.yaml +18 -0
- package/lib/vendor/blamejs/.npmrc +5 -0
- package/lib/vendor/blamejs/.pinact.yaml +17 -0
- package/lib/vendor/blamejs/ARCHITECTURE.md +158 -0
- package/lib/vendor/blamejs/CHANGELOG.md +1351 -0
- package/lib/vendor/blamejs/CODE_OF_CONDUCT.md +86 -0
- package/lib/vendor/blamejs/CONTRIBUTING.md +156 -0
- package/lib/vendor/blamejs/GOVERNANCE.md +201 -0
- package/lib/vendor/blamejs/LICENSE +201 -0
- package/lib/vendor/blamejs/LTS-CALENDAR.md +29 -0
- package/lib/vendor/blamejs/MIGRATING.md +29 -0
- package/lib/vendor/blamejs/NOTICE +81 -0
- package/lib/vendor/blamejs/README.md +304 -0
- package/lib/vendor/blamejs/SECURITY.md +432 -0
- package/lib/vendor/blamejs/api-snapshot.json +48709 -0
- package/lib/vendor/blamejs/assets/BlameJS_Logo.png +0 -0
- package/lib/vendor/blamejs/assets/BlameJS_Logo.svg +129 -0
- package/lib/vendor/blamejs/bench/README.md +77 -0
- package/lib/vendor/blamejs/bench/_helpers.js +70 -0
- package/lib/vendor/blamejs/bench/baseline.json +183 -0
- package/lib/vendor/blamejs/bench/crypto-hash.bench.js +19 -0
- package/lib/vendor/blamejs/bench/crypto-symmetric.bench.js +28 -0
- package/lib/vendor/blamejs/bench/run.js +140 -0
- package/lib/vendor/blamejs/bench/safe-json.bench.js +31 -0
- package/lib/vendor/blamejs/bin/blamejs.js +13 -0
- package/lib/vendor/blamejs/docker/caddy/Caddyfile +46 -0
- package/lib/vendor/blamejs/docker/coredns/Corefile +37 -0
- package/lib/vendor/blamejs/docker/haproxy/haproxy.cfg +52 -0
- package/lib/vendor/blamejs/docker/init/generate-certs.sh +118 -0
- package/lib/vendor/blamejs/docker/keycloak/realm-blamejs-test.json +87 -0
- package/lib/vendor/blamejs/docker/mitmproxy/config.yaml +16 -0
- package/lib/vendor/blamejs/docker/mongo/init-tls.sh +17 -0
- package/lib/vendor/blamejs/docker/mysql/my.cnf +12 -0
- package/lib/vendor/blamejs/docker/nats/nats.conf +33 -0
- package/lib/vendor/blamejs/docker/postgres/init-tls.sh +17 -0
- package/lib/vendor/blamejs/docker/postgres/postgresql.conf +18 -0
- package/lib/vendor/blamejs/docker/rabbitmq/rabbitmq.conf +18 -0
- package/lib/vendor/blamejs/docker/redis/redis.conf +15 -0
- package/lib/vendor/blamejs/docker/squid/squid.conf +24 -0
- package/lib/vendor/blamejs/docker/syslog/syslog-ng.conf +34 -0
- package/lib/vendor/blamejs/docker-compose.test.yml +545 -0
- package/lib/vendor/blamejs/docs/cis-postgres-crosswalk.md +102 -0
- package/lib/vendor/blamejs/docs/cis-sqlite-equivalent.md +92 -0
- package/lib/vendor/blamejs/eslint.config.mjs +204 -0
- package/lib/vendor/blamejs/examples/wiki/Caddyfile +40 -0
- package/lib/vendor/blamejs/examples/wiki/DEPLOY.md +218 -0
- package/lib/vendor/blamejs/examples/wiki/Dockerfile +120 -0
- package/lib/vendor/blamejs/examples/wiki/README.md +157 -0
- package/lib/vendor/blamejs/examples/wiki/cli-snapshot.json +250 -0
- package/lib/vendor/blamejs/examples/wiki/docker-compose.prod.yml +231 -0
- package/lib/vendor/blamejs/examples/wiki/docker-compose.yml +166 -0
- package/lib/vendor/blamejs/examples/wiki/env-snapshot.json +217 -0
- package/lib/vendor/blamejs/examples/wiki/lib/auto-site-entries.js +139 -0
- package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +555 -0
- package/lib/vendor/blamejs/examples/wiki/lib/harvest-cli.js +507 -0
- package/lib/vendor/blamejs/examples/wiki/lib/harvest-env-vars.js +435 -0
- package/lib/vendor/blamejs/examples/wiki/lib/harvest-errors.js +282 -0
- package/lib/vendor/blamejs/examples/wiki/lib/harvest-vendored-deps.js +321 -0
- package/lib/vendor/blamejs/examples/wiki/lib/nav.js +15 -0
- package/lib/vendor/blamejs/examples/wiki/lib/opts-resolver.js +75 -0
- package/lib/vendor/blamejs/examples/wiki/lib/page-generator.js +508 -0
- package/lib/vendor/blamejs/examples/wiki/lib/section.js +276 -0
- package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +587 -0
- package/lib/vendor/blamejs/examples/wiki/lib/source-doc-parser.js +318 -0
- package/lib/vendor/blamejs/examples/wiki/lib/symbol-index.js +122 -0
- package/lib/vendor/blamejs/examples/wiki/migrations/0001-pages-schema.js +74 -0
- package/lib/vendor/blamejs/examples/wiki/package.json +18 -0
- package/lib/vendor/blamejs/examples/wiki/public/img/blamejs-logo.png +0 -0
- package/lib/vendor/blamejs/examples/wiki/public/img/blamejs-logo.svg +129 -0
- package/lib/vendor/blamejs/examples/wiki/public/robots.txt +5 -0
- package/lib/vendor/blamejs/examples/wiki/public/vendor/MANIFEST.json +30 -0
- package/lib/vendor/blamejs/examples/wiki/public/vendor/prism.css +1 -0
- package/lib/vendor/blamejs/examples/wiki/public/vendor/prism.js +15 -0
- package/lib/vendor/blamejs/examples/wiki/public/wiki.css +1250 -0
- package/lib/vendor/blamejs/examples/wiki/routes/admin.js +366 -0
- package/lib/vendor/blamejs/examples/wiki/routes/integration.js +230 -0
- package/lib/vendor/blamejs/examples/wiki/routes/pages.js +266 -0
- package/lib/vendor/blamejs/examples/wiki/scripts/backfill-module-metadata.js +214 -0
- package/lib/vendor/blamejs/examples/wiki/seeders/prod/0001-default-pages.js +35 -0
- package/lib/vendor/blamejs/examples/wiki/seeders/prod/pages/_index.js +34 -0
- package/lib/vendor/blamejs/examples/wiki/seeders/prod/pages/api.js +76 -0
- package/lib/vendor/blamejs/examples/wiki/server.js +129 -0
- package/lib/vendor/blamejs/examples/wiki/site.config.js +197 -0
- package/lib/vendor/blamejs/examples/wiki/snippets/README.md +38 -0
- package/lib/vendor/blamejs/examples/wiki/snippets/auth/password-hash.example.js +15 -0
- package/lib/vendor/blamejs/examples/wiki/src/editor.js +103 -0
- package/lib/vendor/blamejs/examples/wiki/src/wiki.js +349 -0
- package/lib/vendor/blamejs/examples/wiki/test/AUDIT.md +155 -0
- package/lib/vendor/blamejs/examples/wiki/test/codebase-patterns.test.js +594 -0
- package/lib/vendor/blamejs/examples/wiki/test/e2e.js +741 -0
- package/lib/vendor/blamejs/examples/wiki/test/find-missing-pages.js +254 -0
- package/lib/vendor/blamejs/examples/wiki/test/integration.js +391 -0
- package/lib/vendor/blamejs/examples/wiki/test/validate-cli-snapshot.js +379 -0
- package/lib/vendor/blamejs/examples/wiki/test/validate-env-snapshot.js +346 -0
- package/lib/vendor/blamejs/examples/wiki/test/validate-nav-coverage.js +212 -0
- package/lib/vendor/blamejs/examples/wiki/test/validate-site-coverage.js +252 -0
- package/lib/vendor/blamejs/examples/wiki/test/validate-source-comment-blocks.js +107 -0
- package/lib/vendor/blamejs/examples/wiki/views/_layout.html +115 -0
- package/lib/vendor/blamejs/examples/wiki/views/admin/api-keys.html +51 -0
- package/lib/vendor/blamejs/examples/wiki/views/admin/dashboard.html +22 -0
- package/lib/vendor/blamejs/examples/wiki/views/admin/edit.html +17 -0
- package/lib/vendor/blamejs/examples/wiki/views/home.html +85 -0
- package/lib/vendor/blamejs/examples/wiki/views/login.html +18 -0
- package/lib/vendor/blamejs/examples/wiki/views/page.html +5 -0
- package/lib/vendor/blamejs/examples/wiki/views/partials/nav.html +13 -0
- package/lib/vendor/blamejs/examples/wiki/views/search.html +19 -0
- package/lib/vendor/blamejs/examples/wiki/wiki.config.js +15 -0
- package/lib/vendor/blamejs/fuzz/README.md +137 -0
- package/lib/vendor/blamejs/fuzz/_expected.js +35 -0
- package/lib/vendor/blamejs/fuzz/guard-agent-registry.fuzz.js +22 -0
- package/lib/vendor/blamejs/fuzz/guard-csv.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/guard-csv_seed_corpus/01-basic.csv +3 -0
- package/lib/vendor/blamejs/fuzz/guard-csv_seed_corpus/02-formula.csv +1 -0
- package/lib/vendor/blamejs/fuzz/guard-csv_seed_corpus/03-hyperlink.csv +1 -0
- package/lib/vendor/blamejs/fuzz/guard-dsn.fuzz.js +22 -0
- package/lib/vendor/blamejs/fuzz/guard-email.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/guard-email_seed_corpus/01-basic.eml +5 -0
- package/lib/vendor/blamejs/fuzz/guard-envelope.fuzz.js +24 -0
- package/lib/vendor/blamejs/fuzz/guard-event-bus-payload.fuzz.js +24 -0
- package/lib/vendor/blamejs/fuzz/guard-event-bus-topic.fuzz.js +20 -0
- package/lib/vendor/blamejs/fuzz/guard-html.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/guard-html_seed_corpus/01-basic.html +1 -0
- package/lib/vendor/blamejs/fuzz/guard-html_seed_corpus/02-script.html +1 -0
- package/lib/vendor/blamejs/fuzz/guard-html_seed_corpus/03-event.html +1 -0
- package/lib/vendor/blamejs/fuzz/guard-html_seed_corpus/04-jsurl.html +1 -0
- package/lib/vendor/blamejs/fuzz/guard-idempotency-key.fuzz.js +20 -0
- package/lib/vendor/blamejs/fuzz/guard-imap-command.fuzz.js +35 -0
- package/lib/vendor/blamejs/fuzz/guard-jmap.fuzz.js +41 -0
- package/lib/vendor/blamejs/fuzz/guard-json.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/01-basic.json +1 -0
- package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/02-proto.json +1 -0
- package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/03-dupkey.json +1 -0
- package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/04-nan.json +1 -0
- package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/05-bom.json +1 -0
- package/lib/vendor/blamejs/fuzz/guard-list-id.fuzz.js +21 -0
- package/lib/vendor/blamejs/fuzz/guard-list-unsubscribe.fuzz.js +25 -0
- package/lib/vendor/blamejs/fuzz/guard-mail-compose.fuzz.js +22 -0
- package/lib/vendor/blamejs/fuzz/guard-mail-move.fuzz.js +22 -0
- package/lib/vendor/blamejs/fuzz/guard-mail-query.fuzz.js +27 -0
- package/lib/vendor/blamejs/fuzz/guard-mail-reply.fuzz.js +23 -0
- package/lib/vendor/blamejs/fuzz/guard-mail-sieve.fuzz.js +36 -0
- package/lib/vendor/blamejs/fuzz/guard-managesieve-command.fuzz.js +26 -0
- package/lib/vendor/blamejs/fuzz/guard-markdown.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/guard-markdown_seed_corpus/01-basic.md +2 -0
- package/lib/vendor/blamejs/fuzz/guard-markdown_seed_corpus/02-jsurl.md +1 -0
- package/lib/vendor/blamejs/fuzz/guard-markdown_seed_corpus/03-jsimg.md +1 -0
- package/lib/vendor/blamejs/fuzz/guard-message-id.fuzz.js +26 -0
- package/lib/vendor/blamejs/fuzz/guard-pop3-command.fuzz.js +23 -0
- package/lib/vendor/blamejs/fuzz/guard-posture-chain.fuzz.js +22 -0
- package/lib/vendor/blamejs/fuzz/guard-saga-config.fuzz.js +32 -0
- package/lib/vendor/blamejs/fuzz/guard-smtp-command.fuzz.js +27 -0
- package/lib/vendor/blamejs/fuzz/guard-snapshot-envelope.fuzz.js +22 -0
- package/lib/vendor/blamejs/fuzz/guard-stream-args.fuzz.js +22 -0
- package/lib/vendor/blamejs/fuzz/guard-svg.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/guard-svg_seed_corpus/01-basic.svg +1 -0
- package/lib/vendor/blamejs/fuzz/guard-svg_seed_corpus/02-script.svg +1 -0
- package/lib/vendor/blamejs/fuzz/guard-tenant-id.fuzz.js +20 -0
- package/lib/vendor/blamejs/fuzz/guard-trace-context.fuzz.js +30 -0
- package/lib/vendor/blamejs/fuzz/guard-xml.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/guard-xml_seed_corpus/01-basic.xml +1 -0
- package/lib/vendor/blamejs/fuzz/guard-xml_seed_corpus/02-xxe.xml +1 -0
- package/lib/vendor/blamejs/fuzz/guard-yaml.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/guard-yaml_seed_corpus/01-basic.yaml +2 -0
- package/lib/vendor/blamejs/fuzz/guard-yaml_seed_corpus/02-anchor.yaml +2 -0
- package/lib/vendor/blamejs/fuzz/guard-yaml_seed_corpus/03-norway.yaml +1 -0
- package/lib/vendor/blamejs/fuzz/guard-yaml_seed_corpus/04-multidoc.yaml +4 -0
- package/lib/vendor/blamejs/fuzz/parsers__safe-ini.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/parsers__safe-ini_seed_corpus/01-basic.ini +2 -0
- package/lib/vendor/blamejs/fuzz/parsers__safe-toml.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/parsers__safe-toml_seed_corpus/01-basic.toml +4 -0
- package/lib/vendor/blamejs/fuzz/parsers__safe-xml.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/parsers__safe-xml_seed_corpus/01-basic.xml +1 -0
- package/lib/vendor/blamejs/fuzz/parsers__safe-yaml.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/parsers__safe-yaml_seed_corpus/01-basic.yaml +4 -0
- package/lib/vendor/blamejs/fuzz/safe-decompress.fuzz.js +49 -0
- package/lib/vendor/blamejs/fuzz/safe-dns.fuzz.js +29 -0
- package/lib/vendor/blamejs/fuzz/safe-ical.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/safe-icap.fuzz.js +42 -0
- package/lib/vendor/blamejs/fuzz/safe-json.fuzz.js +25 -0
- package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/01-object.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/02-array.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/03-string.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/04-proto.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/05-deep.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-jsonpath.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/safe-jsonpath_seed_corpus/01-basic.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-jsonpath_seed_corpus/02-filter.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-jsonpath_seed_corpus/03-deepscan.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-jsonpath_seed_corpus/04-slice.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-mime.fuzz.js +27 -0
- package/lib/vendor/blamejs/fuzz/safe-mount-info.fuzz.js +33 -0
- package/lib/vendor/blamejs/fuzz/safe-sieve.fuzz.js +28 -0
- package/lib/vendor/blamejs/fuzz/safe-smtp.fuzz.js +64 -0
- package/lib/vendor/blamejs/fuzz/safe-url.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/01-basic.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/02-userinfo.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/03-dangerous.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/04-data.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/05-ipv6.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/06-idn.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-vcard.fuzz.js +16 -0
- package/lib/vendor/blamejs/index.js +678 -0
- package/lib/vendor/blamejs/keys/release-pqc-pub.json +7 -0
- package/lib/vendor/blamejs/lib/_test/crypto-fixtures.js +67 -0
- package/lib/vendor/blamejs/lib/a2a-tasks.js +598 -0
- package/lib/vendor/blamejs/lib/a2a.js +407 -0
- package/lib/vendor/blamejs/lib/acme.js +1448 -0
- package/lib/vendor/blamejs/lib/agent-audit.js +45 -0
- package/lib/vendor/blamejs/lib/agent-event-bus.js +382 -0
- package/lib/vendor/blamejs/lib/agent-idempotency.js +497 -0
- package/lib/vendor/blamejs/lib/agent-orchestrator.js +717 -0
- package/lib/vendor/blamejs/lib/agent-posture-chain.js +366 -0
- package/lib/vendor/blamejs/lib/agent-saga.js +321 -0
- package/lib/vendor/blamejs/lib/agent-snapshot.js +676 -0
- package/lib/vendor/blamejs/lib/agent-stream.js +269 -0
- package/lib/vendor/blamejs/lib/agent-tenant.js +632 -0
- package/lib/vendor/blamejs/lib/agent-trace.js +281 -0
- package/lib/vendor/blamejs/lib/ai-adverse-decision.js +184 -0
- package/lib/vendor/blamejs/lib/ai-content-detect.js +268 -0
- package/lib/vendor/blamejs/lib/ai-input.js +201 -0
- package/lib/vendor/blamejs/lib/ai-model-manifest.js +363 -0
- package/lib/vendor/blamejs/lib/ai-pref.js +340 -0
- package/lib/vendor/blamejs/lib/api-key.js +721 -0
- package/lib/vendor/blamejs/lib/api-snapshot.js +458 -0
- package/lib/vendor/blamejs/lib/app-shutdown.js +557 -0
- package/lib/vendor/blamejs/lib/app.js +365 -0
- package/lib/vendor/blamejs/lib/archive.js +547 -0
- package/lib/vendor/blamejs/lib/arg-parser.js +697 -0
- package/lib/vendor/blamejs/lib/argon2-builtin.js +173 -0
- package/lib/vendor/blamejs/lib/asn1-der.js +424 -0
- package/lib/vendor/blamejs/lib/asyncapi-bindings.js +160 -0
- package/lib/vendor/blamejs/lib/asyncapi-traits.js +143 -0
- package/lib/vendor/blamejs/lib/asyncapi.js +575 -0
- package/lib/vendor/blamejs/lib/atomic-file.js +1023 -0
- package/lib/vendor/blamejs/lib/audit-chain.js +266 -0
- package/lib/vendor/blamejs/lib/audit-daily-review.js +389 -0
- package/lib/vendor/blamejs/lib/audit-sign.js +751 -0
- package/lib/vendor/blamejs/lib/audit-tools.js +1113 -0
- package/lib/vendor/blamejs/lib/audit.js +1671 -0
- package/lib/vendor/blamejs/lib/auth/aal.js +169 -0
- package/lib/vendor/blamejs/lib/auth/access-lock.js +220 -0
- package/lib/vendor/blamejs/lib/auth/acr-vocabulary.js +265 -0
- package/lib/vendor/blamejs/lib/auth/ato-kill-switch.js +112 -0
- package/lib/vendor/blamejs/lib/auth/auth-time-tracker.js +111 -0
- package/lib/vendor/blamejs/lib/auth/bot-challenge.js +573 -0
- package/lib/vendor/blamejs/lib/auth/ciba.js +637 -0
- package/lib/vendor/blamejs/lib/auth/dpop.js +516 -0
- package/lib/vendor/blamejs/lib/auth/elevation-grant.js +306 -0
- package/lib/vendor/blamejs/lib/auth/fal.js +229 -0
- package/lib/vendor/blamejs/lib/auth/fido-mds3.js +681 -0
- package/lib/vendor/blamejs/lib/auth/jwt-external.js +519 -0
- package/lib/vendor/blamejs/lib/auth/jwt.js +430 -0
- package/lib/vendor/blamejs/lib/auth/lockout.js +449 -0
- package/lib/vendor/blamejs/lib/auth/oauth.js +2141 -0
- package/lib/vendor/blamejs/lib/auth/oid4vci.js +657 -0
- package/lib/vendor/blamejs/lib/auth/oid4vp.js +531 -0
- package/lib/vendor/blamejs/lib/auth/openid-federation.js +600 -0
- package/lib/vendor/blamejs/lib/auth/passkey.js +676 -0
- package/lib/vendor/blamejs/lib/auth/password.js +693 -0
- package/lib/vendor/blamejs/lib/auth/saml.js +2109 -0
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-disclosure.js +95 -0
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-holder.js +225 -0
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-issuer.js +197 -0
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +728 -0
- package/lib/vendor/blamejs/lib/auth/status-list.js +272 -0
- package/lib/vendor/blamejs/lib/auth/step-up-policy.js +335 -0
- package/lib/vendor/blamejs/lib/auth/step-up.js +454 -0
- package/lib/vendor/blamejs/lib/auth-bot-challenge.js +505 -0
- package/lib/vendor/blamejs/lib/auth-header.js +148 -0
- package/lib/vendor/blamejs/lib/backup/bundle.js +265 -0
- package/lib/vendor/blamejs/lib/backup/crypto.js +176 -0
- package/lib/vendor/blamejs/lib/backup/index.js +1001 -0
- package/lib/vendor/blamejs/lib/backup/manifest.js +443 -0
- package/lib/vendor/blamejs/lib/boot-gates.js +174 -0
- package/lib/vendor/blamejs/lib/breach-deadline.js +272 -0
- package/lib/vendor/blamejs/lib/break-glass.js +1753 -0
- package/lib/vendor/blamejs/lib/budr.js +205 -0
- package/lib/vendor/blamejs/lib/bundler.js +461 -0
- package/lib/vendor/blamejs/lib/cache-redis.js +256 -0
- package/lib/vendor/blamejs/lib/cache-status.js +288 -0
- package/lib/vendor/blamejs/lib/cache.js +1331 -0
- package/lib/vendor/blamejs/lib/calendar.js +1240 -0
- package/lib/vendor/blamejs/lib/canonical-json.js +143 -0
- package/lib/vendor/blamejs/lib/cdn-cache-control.js +473 -0
- package/lib/vendor/blamejs/lib/cert.js +763 -0
- package/lib/vendor/blamejs/lib/chain-writer.js +259 -0
- package/lib/vendor/blamejs/lib/circuit-breaker.js +101 -0
- package/lib/vendor/blamejs/lib/cli-helpers.js +237 -0
- package/lib/vendor/blamejs/lib/cli.js +2328 -0
- package/lib/vendor/blamejs/lib/client-hints.js +318 -0
- package/lib/vendor/blamejs/lib/cloud-events.js +277 -0
- package/lib/vendor/blamejs/lib/cluster-provider-db.js +317 -0
- package/lib/vendor/blamejs/lib/cluster-storage.js +351 -0
- package/lib/vendor/blamejs/lib/cluster.js +1017 -0
- package/lib/vendor/blamejs/lib/cms-codec.js +826 -0
- package/lib/vendor/blamejs/lib/codepoint-class.js +262 -0
- package/lib/vendor/blamejs/lib/compliance-ai-act-logging.js +190 -0
- package/lib/vendor/blamejs/lib/compliance-ai-act-prohibited.js +205 -0
- package/lib/vendor/blamejs/lib/compliance-ai-act-risk.js +189 -0
- package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +200 -0
- package/lib/vendor/blamejs/lib/compliance-ai-act.js +821 -0
- package/lib/vendor/blamejs/lib/compliance-eaa.js +204 -0
- package/lib/vendor/blamejs/lib/compliance-sanctions-aliases.js +167 -0
- package/lib/vendor/blamejs/lib/compliance-sanctions-fetcher.js +206 -0
- package/lib/vendor/blamejs/lib/compliance-sanctions-fuzzy.js +297 -0
- package/lib/vendor/blamejs/lib/compliance-sanctions.js +569 -0
- package/lib/vendor/blamejs/lib/compliance.js +1558 -0
- package/lib/vendor/blamejs/lib/config-drift.js +426 -0
- package/lib/vendor/blamejs/lib/config.js +446 -0
- package/lib/vendor/blamejs/lib/consent.js +369 -0
- package/lib/vendor/blamejs/lib/constants.js +209 -0
- package/lib/vendor/blamejs/lib/content-credentials.js +704 -0
- package/lib/vendor/blamejs/lib/cookies.js +560 -0
- package/lib/vendor/blamejs/lib/cra-report.js +299 -0
- package/lib/vendor/blamejs/lib/credential-hash.js +394 -0
- package/lib/vendor/blamejs/lib/crypto-field.js +1017 -0
- package/lib/vendor/blamejs/lib/crypto-hpke-pq.js +187 -0
- package/lib/vendor/blamejs/lib/crypto-hpke.js +256 -0
- package/lib/vendor/blamejs/lib/crypto.js +1908 -0
- package/lib/vendor/blamejs/lib/csp.js +271 -0
- package/lib/vendor/blamejs/lib/csv.js +418 -0
- package/lib/vendor/blamejs/lib/daemon.js +481 -0
- package/lib/vendor/blamejs/lib/dark-patterns.js +488 -0
- package/lib/vendor/blamejs/lib/data-act.js +328 -0
- package/lib/vendor/blamejs/lib/db-collection.js +587 -0
- package/lib/vendor/blamejs/lib/db-declare-row-policy.js +267 -0
- package/lib/vendor/blamejs/lib/db-declare-view.js +420 -0
- package/lib/vendor/blamejs/lib/db-file-lifecycle.js +333 -0
- package/lib/vendor/blamejs/lib/db-query.js +802 -0
- package/lib/vendor/blamejs/lib/db-role-context.js +50 -0
- package/lib/vendor/blamejs/lib/db-schema.js +322 -0
- package/lib/vendor/blamejs/lib/db.js +3111 -0
- package/lib/vendor/blamejs/lib/dbsc.js +299 -0
- package/lib/vendor/blamejs/lib/ddl-change-control.js +523 -0
- package/lib/vendor/blamejs/lib/deprecate.js +377 -0
- package/lib/vendor/blamejs/lib/dev.js +405 -0
- package/lib/vendor/blamejs/lib/dora.js +402 -0
- package/lib/vendor/blamejs/lib/dr-runbook.js +368 -0
- package/lib/vendor/blamejs/lib/dsr.js +1188 -0
- package/lib/vendor/blamejs/lib/dual-control.js +526 -0
- package/lib/vendor/blamejs/lib/early-hints.js +212 -0
- package/lib/vendor/blamejs/lib/error-page.js +420 -0
- package/lib/vendor/blamejs/lib/events.js +214 -0
- package/lib/vendor/blamejs/lib/external-db-migrate.js +659 -0
- package/lib/vendor/blamejs/lib/external-db.js +1877 -0
- package/lib/vendor/blamejs/lib/fapi2.js +394 -0
- package/lib/vendor/blamejs/lib/fda-21cfr11.js +395 -0
- package/lib/vendor/blamejs/lib/fdx.js +370 -0
- package/lib/vendor/blamejs/lib/fedcm.js +264 -0
- package/lib/vendor/blamejs/lib/file-type.js +360 -0
- package/lib/vendor/blamejs/lib/file-upload.js +1256 -0
- package/lib/vendor/blamejs/lib/flag-cache.js +136 -0
- package/lib/vendor/blamejs/lib/flag-evaluation-context.js +135 -0
- package/lib/vendor/blamejs/lib/flag-providers.js +279 -0
- package/lib/vendor/blamejs/lib/flag-targeting.js +210 -0
- package/lib/vendor/blamejs/lib/flag.js +346 -0
- package/lib/vendor/blamejs/lib/forms.js +525 -0
- package/lib/vendor/blamejs/lib/framework-error.js +724 -0
- package/lib/vendor/blamejs/lib/framework-schema.js +845 -0
- package/lib/vendor/blamejs/lib/framework-sha1-hibp.js +34 -0
- package/lib/vendor/blamejs/lib/fsm.js +469 -0
- package/lib/vendor/blamejs/lib/gate-contract.js +1661 -0
- package/lib/vendor/blamejs/lib/gdpr-ropa.js +261 -0
- package/lib/vendor/blamejs/lib/graphql-federation.js +234 -0
- package/lib/vendor/blamejs/lib/guard-agent-registry.js +179 -0
- package/lib/vendor/blamejs/lib/guard-all.js +555 -0
- package/lib/vendor/blamejs/lib/guard-archive.js +901 -0
- package/lib/vendor/blamejs/lib/guard-auth.js +451 -0
- package/lib/vendor/blamejs/lib/guard-cidr.js +676 -0
- package/lib/vendor/blamejs/lib/guard-csv.js +1176 -0
- package/lib/vendor/blamejs/lib/guard-domain.js +814 -0
- package/lib/vendor/blamejs/lib/guard-dsn.js +382 -0
- package/lib/vendor/blamejs/lib/guard-email.js +951 -0
- package/lib/vendor/blamejs/lib/guard-envelope.js +294 -0
- package/lib/vendor/blamejs/lib/guard-event-bus-payload.js +217 -0
- package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +150 -0
- package/lib/vendor/blamejs/lib/guard-filename.js +956 -0
- package/lib/vendor/blamejs/lib/guard-graphql.js +731 -0
- package/lib/vendor/blamejs/lib/guard-html-wcag-aria.js +164 -0
- package/lib/vendor/blamejs/lib/guard-html-wcag-forms.js +144 -0
- package/lib/vendor/blamejs/lib/guard-html-wcag-tables.js +154 -0
- package/lib/vendor/blamejs/lib/guard-html-wcag-tagwalk.js +44 -0
- package/lib/vendor/blamejs/lib/guard-html-wcag.js +470 -0
- package/lib/vendor/blamejs/lib/guard-html.js +1209 -0
- package/lib/vendor/blamejs/lib/guard-idempotency-key.js +151 -0
- package/lib/vendor/blamejs/lib/guard-image.js +584 -0
- package/lib/vendor/blamejs/lib/guard-imap-command.js +337 -0
- package/lib/vendor/blamejs/lib/guard-jmap.js +321 -0
- package/lib/vendor/blamejs/lib/guard-json.js +935 -0
- package/lib/vendor/blamejs/lib/guard-jsonpath.js +512 -0
- package/lib/vendor/blamejs/lib/guard-jwt.js +772 -0
- package/lib/vendor/blamejs/lib/guard-list-id.js +318 -0
- package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +412 -0
- package/lib/vendor/blamejs/lib/guard-mail-compose.js +282 -0
- package/lib/vendor/blamejs/lib/guard-mail-move.js +202 -0
- package/lib/vendor/blamejs/lib/guard-mail-query.js +310 -0
- package/lib/vendor/blamejs/lib/guard-mail-reply.js +172 -0
- package/lib/vendor/blamejs/lib/guard-mail-sieve.js +207 -0
- package/lib/vendor/blamejs/lib/guard-managesieve-command.js +566 -0
- package/lib/vendor/blamejs/lib/guard-markdown.js +768 -0
- package/lib/vendor/blamejs/lib/guard-message-id.js +267 -0
- package/lib/vendor/blamejs/lib/guard-mime.js +609 -0
- package/lib/vendor/blamejs/lib/guard-oauth.js +650 -0
- package/lib/vendor/blamejs/lib/guard-pdf.js +569 -0
- package/lib/vendor/blamejs/lib/guard-pop3-command.js +317 -0
- package/lib/vendor/blamejs/lib/guard-posture-chain.js +201 -0
- package/lib/vendor/blamejs/lib/guard-regex.js +632 -0
- package/lib/vendor/blamejs/lib/guard-saga-config.js +157 -0
- package/lib/vendor/blamejs/lib/guard-shell.js +522 -0
- package/lib/vendor/blamejs/lib/guard-smtp-command.js +594 -0
- package/lib/vendor/blamejs/lib/guard-snapshot-envelope.js +168 -0
- package/lib/vendor/blamejs/lib/guard-stream-args.js +166 -0
- package/lib/vendor/blamejs/lib/guard-svg.js +1163 -0
- package/lib/vendor/blamejs/lib/guard-template.js +490 -0
- package/lib/vendor/blamejs/lib/guard-tenant-id.js +138 -0
- package/lib/vendor/blamejs/lib/guard-time.js +586 -0
- package/lib/vendor/blamejs/lib/guard-trace-context.js +172 -0
- package/lib/vendor/blamejs/lib/guard-uuid.js +548 -0
- package/lib/vendor/blamejs/lib/guard-xml.js +666 -0
- package/lib/vendor/blamejs/lib/guard-yaml.js +726 -0
- package/lib/vendor/blamejs/lib/hal.js +125 -0
- package/lib/vendor/blamejs/lib/handlers.js +350 -0
- package/lib/vendor/blamejs/lib/honeytoken.js +168 -0
- package/lib/vendor/blamejs/lib/html-balance.js +347 -0
- package/lib/vendor/blamejs/lib/http-client-cache.js +923 -0
- package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +519 -0
- package/lib/vendor/blamejs/lib/http-client.js +2152 -0
- package/lib/vendor/blamejs/lib/http-message-signature.js +589 -0
- package/lib/vendor/blamejs/lib/http2-teardown.js +34 -0
- package/lib/vendor/blamejs/lib/i18n-messageformat.js +398 -0
- package/lib/vendor/blamejs/lib/i18n.js +931 -0
- package/lib/vendor/blamejs/lib/iab-mspa.js +257 -0
- package/lib/vendor/blamejs/lib/iab-tcf.js +461 -0
- package/lib/vendor/blamejs/lib/importmap-integrity.js +90 -0
- package/lib/vendor/blamejs/lib/inbox.js +435 -0
- package/lib/vendor/blamejs/lib/incident-report.js +314 -0
- package/lib/vendor/blamejs/lib/ip-utils.js +102 -0
- package/lib/vendor/blamejs/lib/jobs.js +185 -0
- package/lib/vendor/blamejs/lib/jose-jwe-experimental.js +228 -0
- package/lib/vendor/blamejs/lib/jsonapi.js +230 -0
- package/lib/vendor/blamejs/lib/keychain.js +865 -0
- package/lib/vendor/blamejs/lib/lazy-require.js +48 -0
- package/lib/vendor/blamejs/lib/legal-hold.js +374 -0
- package/lib/vendor/blamejs/lib/local-db-thin.js +321 -0
- package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +369 -0
- package/lib/vendor/blamejs/lib/log-stream-local.js +146 -0
- package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +410 -0
- package/lib/vendor/blamejs/lib/log-stream-otlp.js +286 -0
- package/lib/vendor/blamejs/lib/log-stream-syslog.js +310 -0
- package/lib/vendor/blamejs/lib/log-stream-webhook.js +199 -0
- package/lib/vendor/blamejs/lib/log-stream.js +584 -0
- package/lib/vendor/blamejs/lib/log.js +625 -0
- package/lib/vendor/blamejs/lib/lro.js +200 -0
- package/lib/vendor/blamejs/lib/mail-agent.js +786 -0
- package/lib/vendor/blamejs/lib/mail-arc-sign.js +417 -0
- package/lib/vendor/blamejs/lib/mail-arf.js +343 -0
- package/lib/vendor/blamejs/lib/mail-auth.js +2144 -0
- package/lib/vendor/blamejs/lib/mail-bimi.js +1047 -0
- package/lib/vendor/blamejs/lib/mail-bounce.js +955 -0
- package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +1286 -0
- package/lib/vendor/blamejs/lib/mail-crypto-smime.js +789 -0
- package/lib/vendor/blamejs/lib/mail-crypto.js +108 -0
- package/lib/vendor/blamejs/lib/mail-dav.js +1224 -0
- package/lib/vendor/blamejs/lib/mail-deploy.js +1119 -0
- package/lib/vendor/blamejs/lib/mail-dkim.js +1250 -0
- package/lib/vendor/blamejs/lib/mail-greylist.js +448 -0
- package/lib/vendor/blamejs/lib/mail-helo.js +473 -0
- package/lib/vendor/blamejs/lib/mail-journal.js +435 -0
- package/lib/vendor/blamejs/lib/mail-mdn.js +424 -0
- package/lib/vendor/blamejs/lib/mail-rbl.js +392 -0
- package/lib/vendor/blamejs/lib/mail-require-tls.js +198 -0
- package/lib/vendor/blamejs/lib/mail-scan.js +502 -0
- package/lib/vendor/blamejs/lib/mail-send-deliver.js +629 -0
- package/lib/vendor/blamejs/lib/mail-server-imap.js +1858 -0
- package/lib/vendor/blamejs/lib/mail-server-jmap.js +1565 -0
- package/lib/vendor/blamejs/lib/mail-server-managesieve.js +908 -0
- package/lib/vendor/blamejs/lib/mail-server-mx.js +969 -0
- package/lib/vendor/blamejs/lib/mail-server-pop3.js +915 -0
- package/lib/vendor/blamejs/lib/mail-server-rate-limit.js +315 -0
- package/lib/vendor/blamejs/lib/mail-server-registry.js +378 -0
- package/lib/vendor/blamejs/lib/mail-server-submission.js +1396 -0
- package/lib/vendor/blamejs/lib/mail-server-tls.js +445 -0
- package/lib/vendor/blamejs/lib/mail-sieve.js +557 -0
- package/lib/vendor/blamejs/lib/mail-spam-score.js +284 -0
- package/lib/vendor/blamejs/lib/mail-srs.js +248 -0
- package/lib/vendor/blamejs/lib/mail-store-fts.js +394 -0
- package/lib/vendor/blamejs/lib/mail-store.js +929 -0
- package/lib/vendor/blamejs/lib/mail-unsubscribe.js +400 -0
- package/lib/vendor/blamejs/lib/mail.js +1971 -0
- package/lib/vendor/blamejs/lib/mcp-tool-registry.js +473 -0
- package/lib/vendor/blamejs/lib/mcp.js +950 -0
- package/lib/vendor/blamejs/lib/metrics.js +1503 -0
- package/lib/vendor/blamejs/lib/middleware/age-gate.js +177 -0
- package/lib/vendor/blamejs/lib/middleware/ai-act-disclosure.js +203 -0
- package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +981 -0
- package/lib/vendor/blamejs/lib/middleware/assetlinks.js +137 -0
- package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +171 -0
- package/lib/vendor/blamejs/lib/middleware/attach-user.js +220 -0
- package/lib/vendor/blamejs/lib/middleware/bearer-auth.js +293 -0
- package/lib/vendor/blamejs/lib/middleware/body-parser.js +1519 -0
- package/lib/vendor/blamejs/lib/middleware/bot-disclose.js +183 -0
- package/lib/vendor/blamejs/lib/middleware/bot-guard.js +217 -0
- package/lib/vendor/blamejs/lib/middleware/clear-site-data.js +122 -0
- package/lib/vendor/blamejs/lib/middleware/compose-pipeline.js +355 -0
- package/lib/vendor/blamejs/lib/middleware/compression.js +489 -0
- package/lib/vendor/blamejs/lib/middleware/cookies.js +130 -0
- package/lib/vendor/blamejs/lib/middleware/cors.js +386 -0
- package/lib/vendor/blamejs/lib/middleware/csp-nonce.js +388 -0
- package/lib/vendor/blamejs/lib/middleware/csp-report.js +167 -0
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +499 -0
- package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +243 -0
- package/lib/vendor/blamejs/lib/middleware/db-role-for.js +304 -0
- package/lib/vendor/blamejs/lib/middleware/dpop.js +402 -0
- package/lib/vendor/blamejs/lib/middleware/error-handler.js +69 -0
- package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +168 -0
- package/lib/vendor/blamejs/lib/middleware/flag-context.js +110 -0
- package/lib/vendor/blamejs/lib/middleware/gpc.js +153 -0
- package/lib/vendor/blamejs/lib/middleware/headers.js +242 -0
- package/lib/vendor/blamejs/lib/middleware/health.js +438 -0
- package/lib/vendor/blamejs/lib/middleware/host-allowlist.js +189 -0
- package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +964 -0
- package/lib/vendor/blamejs/lib/middleware/index.js +183 -0
- package/lib/vendor/blamejs/lib/middleware/nel.js +214 -0
- package/lib/vendor/blamejs/lib/middleware/network-allowlist.js +237 -0
- package/lib/vendor/blamejs/lib/middleware/no-cache.js +106 -0
- package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +177 -0
- package/lib/vendor/blamejs/lib/middleware/protected-resource-metadata.js +277 -0
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +556 -0
- package/lib/vendor/blamejs/lib/middleware/request-id.js +79 -0
- package/lib/vendor/blamejs/lib/middleware/request-log.js +205 -0
- package/lib/vendor/blamejs/lib/middleware/require-aal.js +138 -0
- package/lib/vendor/blamejs/lib/middleware/require-auth.js +144 -0
- package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +290 -0
- package/lib/vendor/blamejs/lib/middleware/require-content-type.js +113 -0
- package/lib/vendor/blamejs/lib/middleware/require-methods.js +97 -0
- package/lib/vendor/blamejs/lib/middleware/require-mtls.js +212 -0
- package/lib/vendor/blamejs/lib/middleware/require-step-up.js +226 -0
- package/lib/vendor/blamejs/lib/middleware/scim-server.js +375 -0
- package/lib/vendor/blamejs/lib/middleware/security-headers.js +285 -0
- package/lib/vendor/blamejs/lib/middleware/security-txt.js +170 -0
- package/lib/vendor/blamejs/lib/middleware/span-http-server.js +280 -0
- package/lib/vendor/blamejs/lib/middleware/speculation-rules.js +323 -0
- package/lib/vendor/blamejs/lib/middleware/sse.js +200 -0
- package/lib/vendor/blamejs/lib/middleware/trace-log-correlation.js +167 -0
- package/lib/vendor/blamejs/lib/middleware/trace-propagate.js +148 -0
- package/lib/vendor/blamejs/lib/middleware/tus-upload.js +749 -0
- package/lib/vendor/blamejs/lib/middleware/web-app-manifest.js +164 -0
- package/lib/vendor/blamejs/lib/migration-files.js +37 -0
- package/lib/vendor/blamejs/lib/migrations.js +385 -0
- package/lib/vendor/blamejs/lib/mime-parse.js +198 -0
- package/lib/vendor/blamejs/lib/money.js +699 -0
- package/lib/vendor/blamejs/lib/mtls-ca.js +572 -0
- package/lib/vendor/blamejs/lib/mtls-engine-default.js +501 -0
- package/lib/vendor/blamejs/lib/network-byte-quota.js +308 -0
- package/lib/vendor/blamejs/lib/network-dns-resolver.js +533 -0
- package/lib/vendor/blamejs/lib/network-dns.js +1930 -0
- package/lib/vendor/blamejs/lib/network-heartbeat.js +425 -0
- package/lib/vendor/blamejs/lib/network-nts.js +574 -0
- package/lib/vendor/blamejs/lib/network-proxy.js +265 -0
- package/lib/vendor/blamejs/lib/network-smtp-policy.js +836 -0
- package/lib/vendor/blamejs/lib/network-tls.js +3126 -0
- package/lib/vendor/blamejs/lib/network.js +346 -0
- package/lib/vendor/blamejs/lib/nis2-report.js +181 -0
- package/lib/vendor/blamejs/lib/nist-crosswalk.js +293 -0
- package/lib/vendor/blamejs/lib/nonce-store.js +177 -0
- package/lib/vendor/blamejs/lib/notify.js +683 -0
- package/lib/vendor/blamejs/lib/ntp-check.js +458 -0
- package/lib/vendor/blamejs/lib/numeric-bounds.js +111 -0
- package/lib/vendor/blamejs/lib/numeric-checks.js +40 -0
- package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +349 -0
- package/lib/vendor/blamejs/lib/object-store/azure-blob.js +488 -0
- package/lib/vendor/blamejs/lib/object-store/gcs-bucket-ops.js +351 -0
- package/lib/vendor/blamejs/lib/object-store/gcs.js +515 -0
- package/lib/vendor/blamejs/lib/object-store/http-put.js +153 -0
- package/lib/vendor/blamejs/lib/object-store/http-request.js +38 -0
- package/lib/vendor/blamejs/lib/object-store/index.js +197 -0
- package/lib/vendor/blamejs/lib/object-store/local.js +163 -0
- package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +1133 -0
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +957 -0
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +420 -0
- package/lib/vendor/blamejs/lib/observability-tracer.js +395 -0
- package/lib/vendor/blamejs/lib/observability.js +720 -0
- package/lib/vendor/blamejs/lib/openapi-paths-builder.js +248 -0
- package/lib/vendor/blamejs/lib/openapi-schema-walk.js +192 -0
- package/lib/vendor/blamejs/lib/openapi-security.js +169 -0
- package/lib/vendor/blamejs/lib/openapi-yaml.js +154 -0
- package/lib/vendor/blamejs/lib/openapi.js +489 -0
- package/lib/vendor/blamejs/lib/otel-export.js +278 -0
- package/lib/vendor/blamejs/lib/outbox.js +547 -0
- package/lib/vendor/blamejs/lib/pagination.js +542 -0
- package/lib/vendor/blamejs/lib/parsers/index.js +91 -0
- package/lib/vendor/blamejs/lib/parsers/safe-env.js +642 -0
- package/lib/vendor/blamejs/lib/parsers/safe-ini.js +293 -0
- package/lib/vendor/blamejs/lib/parsers/safe-toml.js +784 -0
- package/lib/vendor/blamejs/lib/parsers/safe-xml.js +390 -0
- package/lib/vendor/blamejs/lib/parsers/safe-yaml.js +1015 -0
- package/lib/vendor/blamejs/lib/permissions.js +793 -0
- package/lib/vendor/blamejs/lib/pick.js +105 -0
- package/lib/vendor/blamejs/lib/pqc-agent.js +351 -0
- package/lib/vendor/blamejs/lib/pqc-gate.js +279 -0
- package/lib/vendor/blamejs/lib/pqc-software.js +271 -0
- package/lib/vendor/blamejs/lib/problem-details.js +482 -0
- package/lib/vendor/blamejs/lib/process-spawn.js +196 -0
- package/lib/vendor/blamejs/lib/promise-pool.js +162 -0
- package/lib/vendor/blamejs/lib/protobuf-encoder.js +190 -0
- package/lib/vendor/blamejs/lib/protocol-dispatcher.js +161 -0
- package/lib/vendor/blamejs/lib/public-suffix.js +403 -0
- package/lib/vendor/blamejs/lib/pubsub-cluster.js +154 -0
- package/lib/vendor/blamejs/lib/pubsub-redis.js +167 -0
- package/lib/vendor/blamejs/lib/pubsub.js +463 -0
- package/lib/vendor/blamejs/lib/queue-local.js +476 -0
- package/lib/vendor/blamejs/lib/queue-redis.js +745 -0
- package/lib/vendor/blamejs/lib/queue-sqs.js +319 -0
- package/lib/vendor/blamejs/lib/queue.js +1016 -0
- package/lib/vendor/blamejs/lib/redact.js +1007 -0
- package/lib/vendor/blamejs/lib/redis-client.js +520 -0
- package/lib/vendor/blamejs/lib/render.js +285 -0
- package/lib/vendor/blamejs/lib/request-helpers.js +767 -0
- package/lib/vendor/blamejs/lib/resource-access-lock.js +116 -0
- package/lib/vendor/blamejs/lib/restore-bundle.js +340 -0
- package/lib/vendor/blamejs/lib/restore-rollback.js +365 -0
- package/lib/vendor/blamejs/lib/restore.js +409 -0
- package/lib/vendor/blamejs/lib/retention.js +640 -0
- package/lib/vendor/blamejs/lib/retry.js +523 -0
- package/lib/vendor/blamejs/lib/router.js +1289 -0
- package/lib/vendor/blamejs/lib/safe-async.js +1184 -0
- package/lib/vendor/blamejs/lib/safe-buffer.js +562 -0
- package/lib/vendor/blamejs/lib/safe-decompress.js +297 -0
- package/lib/vendor/blamejs/lib/safe-dns.js +665 -0
- package/lib/vendor/blamejs/lib/safe-ical.js +634 -0
- package/lib/vendor/blamejs/lib/safe-icap.js +502 -0
- package/lib/vendor/blamejs/lib/safe-json.js +946 -0
- package/lib/vendor/blamejs/lib/safe-jsonpath.js +285 -0
- package/lib/vendor/blamejs/lib/safe-mime.js +831 -0
- package/lib/vendor/blamejs/lib/safe-mount-info.js +306 -0
- package/lib/vendor/blamejs/lib/safe-path.js +254 -0
- package/lib/vendor/blamejs/lib/safe-redirect.js +106 -0
- package/lib/vendor/blamejs/lib/safe-schema.js +1810 -0
- package/lib/vendor/blamejs/lib/safe-sieve.js +684 -0
- package/lib/vendor/blamejs/lib/safe-smtp.js +185 -0
- package/lib/vendor/blamejs/lib/safe-sql.js +363 -0
- package/lib/vendor/blamejs/lib/safe-url.js +428 -0
- package/lib/vendor/blamejs/lib/safe-vcard.js +473 -0
- package/lib/vendor/blamejs/lib/sandbox-worker.js +135 -0
- package/lib/vendor/blamejs/lib/sandbox.js +358 -0
- package/lib/vendor/blamejs/lib/scheduler.js +827 -0
- package/lib/vendor/blamejs/lib/sd-notify.js +269 -0
- package/lib/vendor/blamejs/lib/sec-cyber.js +214 -0
- package/lib/vendor/blamejs/lib/security-assert.js +395 -0
- package/lib/vendor/blamejs/lib/seeders.js +620 -0
- package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +309 -0
- package/lib/vendor/blamejs/lib/self-update.js +804 -0
- package/lib/vendor/blamejs/lib/server-timing.js +174 -0
- package/lib/vendor/blamejs/lib/session-device-binding.js +431 -0
- package/lib/vendor/blamejs/lib/session-stores.js +138 -0
- package/lib/vendor/blamejs/lib/session.js +1162 -0
- package/lib/vendor/blamejs/lib/slug.js +381 -0
- package/lib/vendor/blamejs/lib/sse.js +349 -0
- package/lib/vendor/blamejs/lib/ssrf-guard.js +792 -0
- package/lib/vendor/blamejs/lib/standard-webhooks.js +183 -0
- package/lib/vendor/blamejs/lib/static.js +1249 -0
- package/lib/vendor/blamejs/lib/storage.js +1272 -0
- package/lib/vendor/blamejs/lib/stream-throttle.js +235 -0
- package/lib/vendor/blamejs/lib/structured-fields.js +244 -0
- package/lib/vendor/blamejs/lib/subject.js +667 -0
- package/lib/vendor/blamejs/lib/tcpa-10dlc.js +175 -0
- package/lib/vendor/blamejs/lib/template.js +931 -0
- package/lib/vendor/blamejs/lib/tenant-quota.js +545 -0
- package/lib/vendor/blamejs/lib/test-harness.js +275 -0
- package/lib/vendor/blamejs/lib/testing.js +1185 -0
- package/lib/vendor/blamejs/lib/time.js +578 -0
- package/lib/vendor/blamejs/lib/tls-exporter.js +239 -0
- package/lib/vendor/blamejs/lib/totp.js +318 -0
- package/lib/vendor/blamejs/lib/tracing.js +546 -0
- package/lib/vendor/blamejs/lib/uuid.js +207 -0
- package/lib/vendor/blamejs/lib/validate-opts.js +381 -0
- package/lib/vendor/blamejs/lib/vault/index.js +638 -0
- package/lib/vendor/blamejs/lib/vault/passphrase-ops.js +311 -0
- package/lib/vendor/blamejs/lib/vault/passphrase-source.js +198 -0
- package/lib/vendor/blamejs/lib/vault/rotate.js +803 -0
- package/lib/vendor/blamejs/lib/vault/seal-pem-file.js +471 -0
- package/lib/vendor/blamejs/lib/vault/wrap.js +296 -0
- package/lib/vendor/blamejs/lib/vault-aad.js +259 -0
- package/lib/vendor/blamejs/lib/vendor/.vendor-data-pubkey +4 -0
- package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +161 -0
- package/lib/vendor/blamejs/lib/vendor/bimi-trust-anchors.data.js +68 -0
- package/lib/vendor/blamejs/lib/vendor/bimi-trust-anchors.pem +33 -0
- package/lib/vendor/blamejs/lib/vendor/common-passwords-top-10000.data.js +1325 -0
- package/lib/vendor/blamejs/lib/vendor/common-passwords-top-10000.txt +10002 -0
- package/lib/vendor/blamejs/lib/vendor/noble-ciphers.cjs +9 -0
- package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +18 -0
- package/lib/vendor/blamejs/lib/vendor/pki.cjs +181 -0
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +16382 -0
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5881 -0
- package/lib/vendor/blamejs/lib/vendor/simplewebauthn-server.cjs +328 -0
- package/lib/vendor/blamejs/lib/vendor/vendor-data-pubkey.js +16 -0
- package/lib/vendor/blamejs/lib/vendor-data.js +520 -0
- package/lib/vendor/blamejs/lib/vex.js +630 -0
- package/lib/vendor/blamejs/lib/watcher.js +608 -0
- package/lib/vendor/blamejs/lib/web-push-vapid.js +322 -0
- package/lib/vendor/blamejs/lib/webhook.js +977 -0
- package/lib/vendor/blamejs/lib/websocket-channels.js +327 -0
- package/lib/vendor/blamejs/lib/websocket.js +1561 -0
- package/lib/vendor/blamejs/lib/wiki-concepts.js +338 -0
- package/lib/vendor/blamejs/lib/worker-pool.js +464 -0
- package/lib/vendor/blamejs/lib/ws-client.js +978 -0
- package/lib/vendor/blamejs/lib/xml-c14n.js +506 -0
- package/lib/vendor/blamejs/memory/specs/node-26-map-getorinsert-migration.md +164 -0
- package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile +19 -0
- package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/README.md +88 -0
- package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/build.sh +26 -0
- package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/project.yaml +28 -0
- package/lib/vendor/blamejs/package.json +81 -0
- package/lib/vendor/blamejs/release-notes/v0.0.x.json +310 -0
- package/lib/vendor/blamejs/release-notes/v0.1.x.json +1798 -0
- package/lib/vendor/blamejs/release-notes/v0.10.x.json +1288 -0
- package/lib/vendor/blamejs/release-notes/v0.11.x.json +2551 -0
- package/lib/vendor/blamejs/release-notes/v0.12.0.json +64 -0
- package/lib/vendor/blamejs/release-notes/v0.12.1.json +32 -0
- package/lib/vendor/blamejs/release-notes/v0.12.2.json +45 -0
- package/lib/vendor/blamejs/release-notes/v0.2.x.json +706 -0
- package/lib/vendor/blamejs/release-notes/v0.3.x.json +786 -0
- package/lib/vendor/blamejs/release-notes/v0.4.x.json +588 -0
- package/lib/vendor/blamejs/release-notes/v0.5.x.json +390 -0
- package/lib/vendor/blamejs/release-notes/v0.6.x.json +1947 -0
- package/lib/vendor/blamejs/release-notes/v0.7.x.json +3811 -0
- package/lib/vendor/blamejs/release-notes/v0.8.x.json +3318 -0
- package/lib/vendor/blamejs/release-notes/v0.9.x.json +2257 -0
- package/lib/vendor/blamejs/scripts/build-vendored-sbom.js +325 -0
- package/lib/vendor/blamejs/scripts/check-api-snapshot.js +62 -0
- package/lib/vendor/blamejs/scripts/check-changelog-extract.js +108 -0
- package/lib/vendor/blamejs/scripts/check-pack-against-gitignore.js +83 -0
- package/lib/vendor/blamejs/scripts/check-services.js +483 -0
- package/lib/vendor/blamejs/scripts/check-vendor-currency.js +349 -0
- package/lib/vendor/blamejs/scripts/consolidate-release-notes.js +216 -0
- package/lib/vendor/blamejs/scripts/gen-migrating.js +275 -0
- package/lib/vendor/blamejs/scripts/generate-changelog-entry.js +577 -0
- package/lib/vendor/blamejs/scripts/generate-release-signing-key.js +79 -0
- package/lib/vendor/blamejs/scripts/publish-dep-confusion-placeholder.sh +101 -0
- package/lib/vendor/blamejs/scripts/refresh-api-snapshot.js +31 -0
- package/lib/vendor/blamejs/scripts/refresh-vendor-manifest.js +132 -0
- package/lib/vendor/blamejs/scripts/release.js +652 -0
- package/lib/vendor/blamejs/scripts/sha3-digest.js +62 -0
- package/lib/vendor/blamejs/scripts/sign-release-artifact.js +92 -0
- package/lib/vendor/blamejs/scripts/test-integration.js +181 -0
- package/lib/vendor/blamejs/scripts/test-wiki-integration.js +126 -0
- package/lib/vendor/blamejs/scripts/validate-source-comment-blocks.js +77 -0
- package/lib/vendor/blamejs/scripts/vendor-data-gen.js +186 -0
- package/lib/vendor/blamejs/scripts/vendor-data-keygen.js +101 -0
- package/lib/vendor/blamejs/scripts/vendor-update.sh +278 -0
- package/lib/vendor/blamejs/test/00-primitives.js +19075 -0
- package/lib/vendor/blamejs/test/10-state.js +622 -0
- package/lib/vendor/blamejs/test/20-db.js +561 -0
- package/lib/vendor/blamejs/test/30-chain.js +2110 -0
- package/lib/vendor/blamejs/test/40-consumers.js +2453 -0
- package/lib/vendor/blamejs/test/50-integration.js +486 -0
- package/lib/vendor/blamejs/test/_helpers.js +10 -0
- package/lib/vendor/blamejs/test/_smoke-worker.js +69 -0
- package/lib/vendor/blamejs/test/fixtures/exploit-corpus/corpus.json +368 -0
- package/lib/vendor/blamejs/test/fixtures/http-client-stream-payload.txt +2 -0
- package/lib/vendor/blamejs/test/fixtures/worker-pool/echo.js +52 -0
- package/lib/vendor/blamejs/test/helpers/_codebase-shingle-worker.js +24 -0
- package/lib/vendor/blamejs/test/helpers/_codebase-shingle.js +203 -0
- package/lib/vendor/blamejs/test/helpers/_shape-match.js +513 -0
- package/lib/vendor/blamejs/test/helpers/check.js +36 -0
- package/lib/vendor/blamejs/test/helpers/cluster.js +70 -0
- package/lib/vendor/blamejs/test/helpers/db.js +143 -0
- package/lib/vendor/blamejs/test/helpers/drivers.js +207 -0
- package/lib/vendor/blamejs/test/helpers/fs-watch.js +101 -0
- package/lib/vendor/blamejs/test/helpers/http.js +14 -0
- package/lib/vendor/blamejs/test/helpers/index.js +93 -0
- package/lib/vendor/blamejs/test/helpers/json-round-trip.js +120 -0
- package/lib/vendor/blamejs/test/helpers/mocks.js +20 -0
- package/lib/vendor/blamejs/test/helpers/otel.js +13 -0
- package/lib/vendor/blamejs/test/helpers/services.js +380 -0
- package/lib/vendor/blamejs/test/helpers/wait.js +206 -0
- package/lib/vendor/blamejs/test/integration/cache.test.js +235 -0
- package/lib/vendor/blamejs/test/integration/cluster-provider-mysql.test.js +174 -0
- package/lib/vendor/blamejs/test/integration/federation-auth.test.js +611 -0
- package/lib/vendor/blamejs/test/integration/http-client.test.js +129 -0
- package/lib/vendor/blamejs/test/integration/log-stream.test.js +219 -0
- package/lib/vendor/blamejs/test/integration/mail-crypto-smime.test.js +181 -0
- package/lib/vendor/blamejs/test/integration/mail-dkim.test.js +152 -0
- package/lib/vendor/blamejs/test/integration/mail-smtp.test.js +161 -0
- package/lib/vendor/blamejs/test/integration/mtls-ca.test.js +289 -0
- package/lib/vendor/blamejs/test/integration/network-dns.test.js +123 -0
- package/lib/vendor/blamejs/test/integration/network-heartbeat.test.js +101 -0
- package/lib/vendor/blamejs/test/integration/ntp-check.test.js +89 -0
- package/lib/vendor/blamejs/test/integration/object-store-sigv4.test.js +403 -0
- package/lib/vendor/blamejs/test/integration/pqc-pkcs8-forward-compat.test.js +271 -0
- package/lib/vendor/blamejs/test/integration/pubsub.test.js +137 -0
- package/lib/vendor/blamejs/test/integration/queue-redis.test.js +352 -0
- package/lib/vendor/blamejs/test/integration/redis-client-tls.test.js +96 -0
- package/lib/vendor/blamejs/test/integration/ssrf-guard.test.js +98 -0
- package/lib/vendor/blamejs/test/integration/websocket-permessage-deflate.test.js +261 -0
- package/lib/vendor/blamejs/test/integration/ws-client-roundtrip.test.js +230 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +211 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/a2a.test.js +59 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/access-lock.test.js +136 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/acme.test.js +219 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +69 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-event-bus.test.js +266 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +262 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-orchestrator.test.js +390 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-posture-chain.test.js +174 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-saga.test.js +279 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +322 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-stream.test.js +227 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-tenant.test.js +302 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-trace.test.js +150 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ai-adverse-decision.test.js +44 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ai-content-detect.test.js +150 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ai-input.test.js +50 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ai-model-manifest.test.js +96 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ai-pref.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/api-encrypt.test.js +1080 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/app-shutdown.test.js +311 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-zip-stream.test.js +291 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive.test.js +140 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/arg-parser.test.js +267 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +108 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/asyncapi.test.js +929 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-conflict-path.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-cve-defensive.test.js +176 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-daily-review.test.js +132 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-export-cadf.test.js +97 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-framework-namespaces.test.js +141 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-segregation.test.js +115 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-ml-dsa-65.test.js +163 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-use-store.test.js +246 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-bot-challenge-verifier.test.js +485 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-bot-challenge.test.js +331 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +352 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-lockout.test.js +572 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-password-audit.test.js +61 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/azure-blob-bucket-ops.test.js +258 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +105 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-worker.test.js +34 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/bearer-auth.test.js +107 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/body-parser-chunked-malformed.test.js +131 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/body-parser-smuggling.test.js +118 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/boot-gates.test.js +85 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/breach-deadline.test.js +38 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +861 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/budr.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/bundler-engine.test.js +209 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cache-status.test.js +129 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cache.test.js +871 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/calendar.test.js +891 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/canonical-json-jcs.test.js +43 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cdn-cache-control.test.js +243 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cert.test.js +550 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +107 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-api-key.test.js +147 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-audit-verify-chain.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-backup.test.js +135 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-config-drift.test.js +67 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-erase.test.js +75 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-file-type.test.js +98 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-helpers.test.js +145 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-mtls.test.js +133 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-password.test.js +97 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-restore.test.js +160 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-retention.test.js +84 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-security.test.js +69 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-vault.test.js +142 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/client-hints.test.js +133 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cms-codec.test.js +237 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +9600 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +575 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-cascade.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-eaa.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +712 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance.test.js +278 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/config-drift.test.js +97 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/config.test.js +424 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cors.test.js +357 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cra-report.test.js +31 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/credential-hash.test.js +226 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-base64url.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-envelope.test.js +85 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-files-parallel.test.js +193 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +98 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hpke-pq.test.js +132 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hpke.test.js +155 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-mlkem768-x25519.test.js +129 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-namespace-hash.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-random-int.test.js +72 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-builder.test.js +96 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-nonce.test.js +401 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-report.test.js +34 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csv.test.js +180 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +210 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/daily-byte-quota.test.js +153 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dark-patterns.test.js +66 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/data-act.test.js +74 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-collection-extensions.test.js +226 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-collection.test.js +136 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-init-extensions.test.js +165 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-query-cross-schema.test.js +150 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-query-extensions.test.js +191 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-role-for.test.js +228 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-vacuum.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-worm.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ddl-change-control.test.js +184 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/declare-row-policy.test.js +203 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/declare-view.test.js +303 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dns-dnssec-algorithm.test.js +163 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dns-null-mx.test.js +39 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dora.test.js +165 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dr-runbook.test.js +59 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dsr-state-rules.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +786 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dual-control.test.js +105 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/early-hints.test.js +147 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/events.test.js +105 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/exploit-replay.test.js +243 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db-hardening.test.js +181 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +190 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db-routing.test.js +531 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fal.test.js +118 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fapi2.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fda-21cfr11.test.js +156 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fdx.test.js +79 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fedcm-dbsc.test.js +216 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +434 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +432 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/file-type.test.js +81 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +887 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/forensic-snapshot.test.js +51 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fsm.test.js +375 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gcs-bucket-ops.test.js +321 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gdpr-ropa.test.js +41 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/graphql-federation.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-agent-registry.test.js +87 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-all.test.js +328 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-archive.test.js +339 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +694 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-dsn.test.js +296 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-email.test.js +234 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-envelope.test.js +192 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-event-bus-payload.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-event-bus-topic.test.js +71 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +386 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-html-wcag.test.js +859 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +357 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-idempotency-key.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jmap.test.js +174 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-json.test.js +317 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-list-id.test.js +199 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-list-unsubscribe.test.js +214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-compose.test.js +111 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-move.test.js +110 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-query.test.js +112 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-reply.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-sieve.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +301 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +265 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-message-id.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +161 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-posture-chain.test.js +100 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-saga-config.test.js +79 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-smtp-command.test.js +269 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-snapshot-envelope.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-stream-args.test.js +78 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +288 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-tenant-id.test.js +69 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-trace-context.test.js +102 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-xml.test.js +202 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-yaml.test.js +203 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/hal.test.js +51 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/honeytoken.test.js +50 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/html-balance.test.js +37 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +692 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-stream.test.js +280 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-message-signature.test.js +225 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n-messageformat.test.js +203 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +991 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/iab-mspa.test.js +63 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/iab-tcf.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +612 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/importmap-integrity.test.js +56 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +166 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/incident-report.test.js +29 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jose-jwe-experimental.test.js +121 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/json-api.test.js +58 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/json-round-trip-helper.test.js +110 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +159 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/keychain.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/legal-hold.test.js +118 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/local-db-thin.test.js +150 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log-stream-cloudwatch.test.js +489 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log-stream-otlp-grpc.test.js +207 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log-stream-otlp.test.js +283 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/lro.test.js +65 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +417 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-arf.test.js +208 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +910 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-bimi.test.js +502 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-bounce.test.js +680 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-canspam.test.js +128 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp-experimental.test.js +149 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +323 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +297 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dav.test.js +514 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy-tlsrpt.test.js +369 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy.test.js +199 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +627 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-feedback-id.test.js +56 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-greylist.test.js +217 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-helo.test.js +283 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-journal.test.js +217 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-mdn.test.js +334 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-rbl.test.js +271 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-require-tls.test.js +128 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-scan.test.js +215 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-send-deliver.test.js +336 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +732 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +840 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-managesieve.test.js +130 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +285 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-pop3.test.js +74 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-rate-limit.test.js +112 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-registry.test.js +229 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-submission.test.js +394 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-tls.test.js +147 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-sieve.test.js +151 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-spam-score.test.js +204 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-srs.test.js +152 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store-fts.test.js +279 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +323 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-unsubscribe.test.js +165 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail.test.js +439 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mcp-tool-registry.test.js +202 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mcp.test.js +155 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics-shadow-registry.test.js +112 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics-snapshot.test.js +224 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-compose-pipeline.test.js +278 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/money.test.js +376 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-paths.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/nel.test.js +200 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-allowlist.test.js +106 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-byte-quota.test.js +133 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns-resolver.test.js +372 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +635 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-heartbeat-passive.test.js +128 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-tls-build-options.test.js +130 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-tls-ct-inclusion.test.js +179 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +447 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network.test.js +369 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/nis2-report.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/nist-crosswalk.test.js +42 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/no-cache.test.js +98 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/notify.test.js +707 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/numeric-bounds.test.js +142 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/oauth-callback.test.js +72 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +597 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +190 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/openapi.test.js +877 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/otel-export.test.js +257 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pagination.test.js +522 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +216 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/passkey.test.js +324 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/permissions.test.js +546 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +153 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pqc-software.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/problem-details.test.js +195 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/process-spawn.test.js +62 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/promise-pool.test.js +93 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/protected-resource-metadata.test.js +68 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/protobuf-encoder.test.js +138 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/protocol-dispatcher.test.js +174 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/public-suffix.test.js +197 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pubsub.test.js +232 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue-dlq-extend-lease.test.js +178 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue-flow-repeat.test.js +322 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue-priority-rate-progress.test.js +266 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue-sqs.test.js +300 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-cluster.test.js +338 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-registry.test.js +75 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/redact-dlp.test.js +246 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/redis-client.test.js +130 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +335 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-log.test.js +170 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/require-auth-cache-control.test.js +93 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/require-mtls.test.js +34 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/resource-access-lock.test.js +52 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/retention-floor.test.js +67 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/retry.test.js +535 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-cross-origin-redirect.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-tls0rtt.test.js +128 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-async-loops.test.js +163 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-async-parallel.test.js +170 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-decompress.test.js +248 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-dns.test.js +451 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-ical.test.js +289 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-icap.test.js +206 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-jsonpath.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-mime.test.js +339 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-mount-info.test.js +180 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +78 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-sieve.test.js +123 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-smtp.test.js +95 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-url-idn-homograph.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-vcard.test.js +257 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/saml-slo.test.js +249 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sandbox.test.js +228 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scheduler-exactly-once.test.js +238 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scim-server.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +700 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sd-notify.test.js +67 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sec-cyber.test.js +85 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/security-assert.test.js +107 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +175 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/seeders.test.js +816 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/self-update-standalone-verifier.test.js +168 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +302 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/server-timing.test.js +93 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +247 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +295 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/shape-match.test.js +142 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +952 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-multipart-sse.test.js +441 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/slug.test.js +330 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/smtp-policy.test.js +233 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/source-comment-blocks.test.js +105 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/speculation-rules.test.js +319 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sse.test.js +148 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +283 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/standard-webhooks.test.js +67 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +266 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/step-up.test.js +487 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/storage-chunk-scratch.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/storage-presigned-url.test.js +773 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/stream-throttle.test.js +173 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/structured-fields.test.js +180 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tcpa-10dlc.test.js +66 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/test-coverage.test.js +571 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/test-harness.test.js +190 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/testing-request.test.js +119 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/testing.test.js +522 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/time.test.js +151 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tls-exporter.test.js +168 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tls-ocsp-ct.test.js +275 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tls-ocsp-verify.test.js +105 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tls-pinset-drift.test.js +35 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tls-preferred-groups.test.js +81 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tracing.test.js +280 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/uuid.test.js +93 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault-aad.test.js +277 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault-seal-pem-file.test.js +252 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vendor-data.test.js +149 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vendor-manifest.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vex.test.js +661 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +308 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/web-push-vapid.test.js +144 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +674 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/websocket-channels.test.js +360 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/worker-pool.test.js +302 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +349 -0
- package/lib/vendor/blamejs/test/layer-1-state/api-key.test.js +717 -0
- package/lib/vendor/blamejs/test/layer-5-integration/bundler-output.test.js +444 -0
- package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +597 -0
- package/lib/vendor/blamejs/test/layer-5-integration/security-chaos.test.js +308 -0
- package/lib/vendor/blamejs/test/smoke.js +431 -0
- package/lib/webhooks.js +305 -0
- package/package.json +43 -0
|
@@ -0,0 +1,1930 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var dns = require("node:dns");
|
|
4
|
+
var net = require("node:net");
|
|
5
|
+
var https = require("node:https");
|
|
6
|
+
var nodeTls = require("node:tls");
|
|
7
|
+
var dnsPromises = dns.promises;
|
|
8
|
+
|
|
9
|
+
var C = require("./constants");
|
|
10
|
+
var bCrypto = require("./crypto");
|
|
11
|
+
var lazyRequire = require("./lazy-require");
|
|
12
|
+
var safeBuffer = require("./safe-buffer");
|
|
13
|
+
var safeUrl = require("./safe-url");
|
|
14
|
+
var validateOpts = require("./validate-opts");
|
|
15
|
+
var { defineClass } = require("./framework-error");
|
|
16
|
+
|
|
17
|
+
var DnsError = defineClass("DnsError", { alwaysPermanent: false });
|
|
18
|
+
|
|
19
|
+
// Protocol-fixed byte counts and radixes — passthrough through C.BYTES
|
|
20
|
+
// keeps every numeric literal routed through one helper.
|
|
21
|
+
var DNS_QTYPE_AAAA = 28; // RFC 3596 — IPv6 record type
|
|
22
|
+
var IPV6_ADDR_BYTES = C.BYTES.bytes(16); // IPv6 address octet length
|
|
23
|
+
var IPV6_HEX_GROUPS = C.BYTES.bytes(8); // IPv6 16-bit hex groups
|
|
24
|
+
var HEX_RADIX = C.BYTES.bytes(16); // parseInt / toString radix-16
|
|
25
|
+
|
|
26
|
+
var observability = lazyRequire(function () { return require("./observability"); });
|
|
27
|
+
var safeEnv = require("./parsers/safe-env");
|
|
28
|
+
|
|
29
|
+
var STATE = {
|
|
30
|
+
servers: null,
|
|
31
|
+
resultOrder: null,
|
|
32
|
+
family: 0,
|
|
33
|
+
lookupTimeoutMs: 0,
|
|
34
|
+
cacheTtlMs: 0,
|
|
35
|
+
cacheNegativeTtlMs: 0,
|
|
36
|
+
doh: null,
|
|
37
|
+
dot: null,
|
|
38
|
+
// Default-on secure DNS (DoH via Cloudflare) when neither doh nor dot
|
|
39
|
+
// is operator-configured AND no opt-out env var is set. Operators
|
|
40
|
+
// who explicitly want the system resolver call useSystemResolver()
|
|
41
|
+
// or set BLAMEJS_DNS_TRANSPORT=system. Default-on per Core Rule §3
|
|
42
|
+
// ("security defaults are not opt-in").
|
|
43
|
+
systemResolver: false,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Default DoH provider when nothing is configured. Cloudflare's
|
|
47
|
+
// 1.1.1.1 service is privacy-respecting, free, and global.
|
|
48
|
+
var DEFAULT_DOH_URL = "https://cloudflare-dns.com/dns-query";
|
|
49
|
+
|
|
50
|
+
// RFC 6761 + RFC 6762 + operator-internal special-form host names that
|
|
51
|
+
// public DoH/DoT providers don't resolve. Local lookups for these names
|
|
52
|
+
// route through node:dns which honours /etc/hosts + LDH locally.
|
|
53
|
+
var LOCAL_SUFFIXES = [".localhost", ".local", ".test", ".invalid",
|
|
54
|
+
".internal", ".intranet", ".lan", ".home", ".corp"];
|
|
55
|
+
function _isLocalFormHost(host) {
|
|
56
|
+
if (typeof host !== "string" || host.length === 0) return true;
|
|
57
|
+
// Strip the trailing root-zone dot BEFORE any reserved-name compare.
|
|
58
|
+
// RFC 1034 §3.1 — `foo.` is the absolute form of `foo` (both resolve
|
|
59
|
+
// to the same target). Without the strip, `localhost.` would slip
|
|
60
|
+
// past the reserved-form check and reach a public DoH/DoT provider
|
|
61
|
+
// that maps it to NXDOMAIN, which downstream consumers might then
|
|
62
|
+
// try to resolve via system fallback.
|
|
63
|
+
while (host.length > 0 && host.charAt(host.length - 1) === ".") {
|
|
64
|
+
host = host.slice(0, -1);
|
|
65
|
+
}
|
|
66
|
+
if (host === "localhost") return true;
|
|
67
|
+
// IP literal — skip DNS resolution entirely (caller passes through).
|
|
68
|
+
if (net.isIP(host)) return true;
|
|
69
|
+
var lc = host.toLowerCase();
|
|
70
|
+
for (var i = 0; i < LOCAL_SUFFIXES.length; i += 1) {
|
|
71
|
+
if (lc.length > LOCAL_SUFFIXES[i].length &&
|
|
72
|
+
lc.slice(-LOCAL_SUFFIXES[i].length) === LOCAL_SUFFIXES[i]) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function _ensureSecureDefault() {
|
|
80
|
+
if (STATE.doh || STATE.dot || STATE.systemResolver) return;
|
|
81
|
+
var override = safeEnv.readVar("BLAMEJS_DNS_TRANSPORT");
|
|
82
|
+
if (override === "system") { STATE.systemResolver = true; return; }
|
|
83
|
+
if (override === "dot") {
|
|
84
|
+
// Cloudflare 1.1.1.1 over TLS, port 853.
|
|
85
|
+
STATE.dot = { host: "1.1.1.1", port: 853, servername: "1.1.1.1", ca: null }; // allow:raw-byte-literal — IANA-assigned DoT port
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// Default: DoH via Cloudflare.
|
|
89
|
+
STATE.doh = { url: DEFAULT_DOH_URL, method: null, ca: null };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
var POSITIVE_CACHE = new Map();
|
|
93
|
+
var NEGATIVE_CACHE = new Map();
|
|
94
|
+
|
|
95
|
+
function _now() { return Date.now(); }
|
|
96
|
+
|
|
97
|
+
function _cacheGet(host, family) {
|
|
98
|
+
var key = host + "/" + family;
|
|
99
|
+
var pos = POSITIVE_CACHE.get(key);
|
|
100
|
+
if (pos && pos.expiresAt > _now()) return { hit: true, value: pos.value };
|
|
101
|
+
if (pos) POSITIVE_CACHE.delete(key);
|
|
102
|
+
var neg = NEGATIVE_CACHE.get(key);
|
|
103
|
+
if (neg && neg.expiresAt > _now()) return { hit: true, error: neg.error };
|
|
104
|
+
if (neg) NEGATIVE_CACHE.delete(key);
|
|
105
|
+
return { hit: false };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function _cachePutPositive(host, family, value) {
|
|
109
|
+
if (STATE.cacheTtlMs <= 0) return;
|
|
110
|
+
POSITIVE_CACHE.set(host + "/" + family, {
|
|
111
|
+
value: value,
|
|
112
|
+
expiresAt: _now() + STATE.cacheTtlMs,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function _cachePutNegative(host, family, error) {
|
|
117
|
+
if (STATE.cacheTtlMs <= 0) return;
|
|
118
|
+
var ttl = STATE.cacheNegativeTtlMs > 0 ? STATE.cacheNegativeTtlMs : Math.min(STATE.cacheTtlMs, C.TIME.seconds(30));
|
|
119
|
+
NEGATIVE_CACHE.set(host + "/" + family, {
|
|
120
|
+
error: error,
|
|
121
|
+
expiresAt: _now() + ttl,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function _clearCache() {
|
|
126
|
+
POSITIVE_CACHE.clear();
|
|
127
|
+
NEGATIVE_CACHE.clear();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function setServers(serverList) {
|
|
131
|
+
if (!Array.isArray(serverList) || serverList.length === 0) {
|
|
132
|
+
throw new DnsError("dns/bad-servers", "dns.setServers: expected non-empty array of resolver IPs");
|
|
133
|
+
}
|
|
134
|
+
for (var i = 0; i < serverList.length; i++) {
|
|
135
|
+
var s = serverList[i];
|
|
136
|
+
if (typeof s !== "string" || s.length === 0) {
|
|
137
|
+
throw new DnsError("dns/bad-server", "dns.setServers[" + i + "]: expected non-empty string, got " + typeof s);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
STATE.servers = serverList.slice();
|
|
141
|
+
try { dns.setServers(serverList); } catch (e) {
|
|
142
|
+
throw new DnsError("dns/setservers-failed", "dns.setServers failed: " + e.message);
|
|
143
|
+
}
|
|
144
|
+
_clearCache();
|
|
145
|
+
_emitObs("network.dns.servers.set", { count: serverList.length });
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function getServers() {
|
|
149
|
+
if (STATE.servers) return STATE.servers.slice();
|
|
150
|
+
try { return dns.getServers(); } catch (_e) { return []; }
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function setResultOrder(order) {
|
|
154
|
+
if (order !== "ipv4first" && order !== "verbatim" && order !== "ipv6first") {
|
|
155
|
+
throw new DnsError("dns/bad-result-order",
|
|
156
|
+
"dns.setResultOrder: expected 'ipv4first' | 'verbatim' | 'ipv6first', got " + JSON.stringify(order));
|
|
157
|
+
}
|
|
158
|
+
STATE.resultOrder = order;
|
|
159
|
+
if (order === "ipv6first") {
|
|
160
|
+
try { dns.setDefaultResultOrder("verbatim"); } catch (_e) { /* node may not support setter on this version — best-effort */ }
|
|
161
|
+
} else {
|
|
162
|
+
try { dns.setDefaultResultOrder(order); } catch (_e) { /* node may not support setter on this version — best-effort */ }
|
|
163
|
+
}
|
|
164
|
+
_clearCache();
|
|
165
|
+
_emitObs("network.dns.result_order.set", { order: order });
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function setFamily(fam) {
|
|
169
|
+
if (fam !== 0 && fam !== 4 && fam !== 6) {
|
|
170
|
+
throw new DnsError("dns/bad-family", "dns.setFamily: expected 0 | 4 | 6, got " + JSON.stringify(fam));
|
|
171
|
+
}
|
|
172
|
+
STATE.family = fam;
|
|
173
|
+
_clearCache();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function setLookupTimeoutMs(ms) {
|
|
177
|
+
if (typeof ms !== "number" || !isFinite(ms) || ms < 0) {
|
|
178
|
+
throw new DnsError("dns/bad-timeout",
|
|
179
|
+
"dns.setLookupTimeoutMs: expected non-negative finite number, got " + JSON.stringify(ms));
|
|
180
|
+
}
|
|
181
|
+
STATE.lookupTimeoutMs = ms;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function setCacheTtlMs(ms, negativeMs) {
|
|
185
|
+
if (typeof ms !== "number" || !isFinite(ms) || ms < 0) {
|
|
186
|
+
throw new DnsError("dns/bad-cache-ttl",
|
|
187
|
+
"dns.setCacheTtlMs: expected non-negative finite number, got " + JSON.stringify(ms));
|
|
188
|
+
}
|
|
189
|
+
STATE.cacheTtlMs = ms;
|
|
190
|
+
if (negativeMs !== undefined) {
|
|
191
|
+
if (typeof negativeMs !== "number" || !isFinite(negativeMs) || negativeMs < 0) {
|
|
192
|
+
throw new DnsError("dns/bad-cache-ttl",
|
|
193
|
+
"dns.setCacheTtlMs negativeMs: expected non-negative finite number, got " + JSON.stringify(negativeMs));
|
|
194
|
+
}
|
|
195
|
+
STATE.cacheNegativeTtlMs = negativeMs;
|
|
196
|
+
}
|
|
197
|
+
if (ms === 0) _clearCache();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Operator opt-out from the default-on secure DNS. After calling this,
|
|
201
|
+
// every lookup routes through node:dns (the OS resolver). Equivalent
|
|
202
|
+
// to setting BLAMEJS_DNS_TRANSPORT=system. Operators on internal-DNS
|
|
203
|
+
// deployments (split-horizon, custom resolver appliances) need this
|
|
204
|
+
// to keep their hostnames resolving locally.
|
|
205
|
+
function useSystemResolver() {
|
|
206
|
+
STATE.doh = null;
|
|
207
|
+
STATE.dot = null;
|
|
208
|
+
STATE.systemResolver = true;
|
|
209
|
+
_resetDotPool();
|
|
210
|
+
_clearCache();
|
|
211
|
+
_emitObs("network.dns.system_resolver.set", {});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function useDnsOverHttps(opts) {
|
|
215
|
+
opts = opts || {};
|
|
216
|
+
validateOpts(opts, ["provider", "url", "method", "ca"], "dns.useDnsOverHttps");
|
|
217
|
+
var url = opts.url;
|
|
218
|
+
if (!url && opts.provider) {
|
|
219
|
+
var p = String(opts.provider).toLowerCase();
|
|
220
|
+
if (p === "cloudflare") url = "https://cloudflare-dns.com/dns-query";
|
|
221
|
+
else if (p === "google") url = "https://dns.google/dns-query";
|
|
222
|
+
else if (p === "quad9") url = "https://dns.quad9.net/dns-query";
|
|
223
|
+
else throw new DnsError("dns/bad-doh-provider", "dns.useDnsOverHttps: unknown provider '" + opts.provider + "'");
|
|
224
|
+
}
|
|
225
|
+
if (typeof url !== "string" || url.indexOf("https://") !== 0) {
|
|
226
|
+
throw new DnsError("dns/bad-doh-url",
|
|
227
|
+
"dns.useDnsOverHttps: url must be an https:// string, got " + JSON.stringify(url));
|
|
228
|
+
}
|
|
229
|
+
var method = opts.method;
|
|
230
|
+
if (method !== undefined && method !== "GET" && method !== "POST") {
|
|
231
|
+
throw new DnsError("dns/bad-doh-method",
|
|
232
|
+
"dns.useDnsOverHttps: method must be 'GET' | 'POST' | undefined (auto), got " +
|
|
233
|
+
JSON.stringify(method));
|
|
234
|
+
}
|
|
235
|
+
if (opts.ca !== undefined && opts.ca !== null &&
|
|
236
|
+
!Buffer.isBuffer(opts.ca) && typeof opts.ca !== "string" && !Array.isArray(opts.ca)) {
|
|
237
|
+
throw new DnsError("dns/bad-doh-ca",
|
|
238
|
+
"dns.useDnsOverHttps: ca must be a PEM string, Buffer, or array of either");
|
|
239
|
+
}
|
|
240
|
+
STATE.doh = { url: url, method: method, ca: opts.ca || null };
|
|
241
|
+
_clearCache();
|
|
242
|
+
_emitObs("network.dns.doh.set", { url: url, method: method || "auto" });
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function useDnsOverTls(opts) {
|
|
246
|
+
opts = opts || {};
|
|
247
|
+
validateOpts(opts, ["host", "port", "servername", "ca"], "dns.useDnsOverTls");
|
|
248
|
+
validateOpts.requireNonEmptyString(opts.host, "dns.useDnsOverTls: host", DnsError, "dns/bad-dot-host");
|
|
249
|
+
if (opts.ca !== undefined && opts.ca !== null &&
|
|
250
|
+
!Buffer.isBuffer(opts.ca) && typeof opts.ca !== "string" && !Array.isArray(opts.ca)) {
|
|
251
|
+
throw new DnsError("dns/bad-dot-ca",
|
|
252
|
+
"dns.useDnsOverTls: ca must be a PEM string, Buffer, or array of either");
|
|
253
|
+
}
|
|
254
|
+
STATE.dot = {
|
|
255
|
+
host: opts.host,
|
|
256
|
+
port: opts.port || 853,
|
|
257
|
+
servername: opts.servername || opts.host,
|
|
258
|
+
ca: opts.ca || null,
|
|
259
|
+
};
|
|
260
|
+
_resetDotPool();
|
|
261
|
+
_clearCache();
|
|
262
|
+
_emitObs("network.dns.dot.set", { host: STATE.dot.host, port: STATE.dot.port });
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function _withTimeout(promise, ms, host) {
|
|
266
|
+
if (ms <= 0) return promise;
|
|
267
|
+
return new Promise(function (resolve, reject) {
|
|
268
|
+
var timer = setTimeout(function () {
|
|
269
|
+
reject(new DnsError("dns/lookup-timeout", "dns lookup of '" + host + "' exceeded " + ms + "ms"));
|
|
270
|
+
}, ms);
|
|
271
|
+
timer.unref && timer.unref();
|
|
272
|
+
promise.then(
|
|
273
|
+
function (v) { clearTimeout(timer); resolve(v); },
|
|
274
|
+
function (e) { clearTimeout(timer); reject(e); }
|
|
275
|
+
);
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function _encodeDnsQuery(host, qtype) {
|
|
280
|
+
var parts = host.split(".").filter(Boolean);
|
|
281
|
+
var nameLen = 1;
|
|
282
|
+
for (var i = 0; i < parts.length; i++) nameLen += 1 + Buffer.byteLength(parts[i], "ascii");
|
|
283
|
+
var buf = Buffer.alloc(12 + nameLen + 4);
|
|
284
|
+
// Cryptographic RNG for the 16-bit DNS query ID — frustrates poisoning
|
|
285
|
+
// attempts that guess the transaction ID. Routes through `b.crypto.randomInt`
|
|
286
|
+
// (which wraps nodeCrypto.randomInt) so every framework random-int draw
|
|
287
|
+
// is greppable through one substrate.
|
|
288
|
+
var id = bCrypto.randomInt(0, 0x10000);
|
|
289
|
+
buf.writeUInt16BE(id, 0);
|
|
290
|
+
buf.writeUInt16BE(0x0100, 2);
|
|
291
|
+
buf.writeUInt16BE(1, 4);
|
|
292
|
+
var off = 12;
|
|
293
|
+
for (var p = 0; p < parts.length; p++) {
|
|
294
|
+
var s = parts[p];
|
|
295
|
+
buf.writeUInt8(Buffer.byteLength(s, "ascii"), off++);
|
|
296
|
+
off += buf.write(s, off, "ascii");
|
|
297
|
+
}
|
|
298
|
+
buf.writeUInt8(0, off++);
|
|
299
|
+
buf.writeUInt16BE(qtype, off); off += 2;
|
|
300
|
+
buf.writeUInt16BE(1, off);
|
|
301
|
+
return { buf: buf, id: id };
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Walk a DNS-message name in-place and advance `state.off`. RFC 1035
|
|
305
|
+
// §3.1 names terminate either with a single 0x00 byte OR with a
|
|
306
|
+
// 2-byte compression pointer (high two bits 11). The pre-0.7.68
|
|
307
|
+
// parser unconditionally executed `if (buf[off] === 0) off++`
|
|
308
|
+
// after the loop, which consumed the high byte of the next field
|
|
309
|
+
// when the loop had exited via the compression pointer — silently
|
|
310
|
+
// breaking every DNS response that used name compression in the
|
|
311
|
+
// answer section (which is most of them).
|
|
312
|
+
function _skipDnsName(buf, state) {
|
|
313
|
+
var endedViaPointer = false;
|
|
314
|
+
while (state.off < buf.length && buf[state.off] !== 0) {
|
|
315
|
+
if ((buf[state.off] & 0xc0) === 0xc0) { // allow:raw-byte-literal — RFC 1035 name-compression pointer mask
|
|
316
|
+
state.off += 2;
|
|
317
|
+
endedViaPointer = true;
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
state.off += buf[state.off] + 1;
|
|
321
|
+
}
|
|
322
|
+
if (!endedViaPointer && state.off < buf.length && buf[state.off] === 0) {
|
|
323
|
+
state.off += 1;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function _decodeDnsAnswer(buf, qtype) {
|
|
328
|
+
if (!Buffer.isBuffer(buf) || buf.length < 12) throw new DnsError("dns/bad-reply", "dns reply truncated");
|
|
329
|
+
var rcode = buf.readUInt8(3) & 0x0f;
|
|
330
|
+
if (rcode !== 0) throw new DnsError("dns/no-result", "dns reply rcode " + rcode);
|
|
331
|
+
var qdcount = buf.readUInt16BE(4);
|
|
332
|
+
var ancount = buf.readUInt16BE(6);
|
|
333
|
+
var state = { off: 12 };
|
|
334
|
+
for (var q = 0; q < qdcount; q++) {
|
|
335
|
+
_skipDnsName(buf, state);
|
|
336
|
+
state.off += 4;
|
|
337
|
+
}
|
|
338
|
+
var addrs = [];
|
|
339
|
+
for (var a = 0; a < ancount; a++) {
|
|
340
|
+
_skipDnsName(buf, state);
|
|
341
|
+
var off = state.off;
|
|
342
|
+
var rtype = buf.readUInt16BE(off); off += 2;
|
|
343
|
+
off += 2;
|
|
344
|
+
off += 4;
|
|
345
|
+
var rdlen = buf.readUInt16BE(off); off += 2;
|
|
346
|
+
if (rtype === qtype && qtype === 1 && rdlen === 4) {
|
|
347
|
+
addrs.push(buf[off] + "." + buf[off + 1] + "." + buf[off + 2] + "." + buf[off + 3]);
|
|
348
|
+
} else if (rtype === qtype && qtype === DNS_QTYPE_AAAA && rdlen === IPV6_ADDR_BYTES) {
|
|
349
|
+
var groups = [];
|
|
350
|
+
for (var g = 0; g < IPV6_HEX_GROUPS; g++) {
|
|
351
|
+
groups.push(buf.readUInt16BE(off + g * 2).toString(HEX_RADIX));
|
|
352
|
+
}
|
|
353
|
+
addrs.push(groups.join(":"));
|
|
354
|
+
}
|
|
355
|
+
off += rdlen;
|
|
356
|
+
state.off = off;
|
|
357
|
+
}
|
|
358
|
+
return addrs;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Read the AD bit (Authenticated Data, RFC 4035) from a DNS reply
|
|
362
|
+
// header. Byte 3 holds RA, Z, AD, CD, and rcode bits; AD is bit 5
|
|
363
|
+
// (mask 0x20). Set when the upstream recursive resolver has validated
|
|
364
|
+
// the chain.
|
|
365
|
+
function _readAdBit(buf) {
|
|
366
|
+
if (!Buffer.isBuffer(buf) || buf.length < 12) return false;
|
|
367
|
+
return (buf.readUInt8(3) & 0x20) !== 0; // allow:raw-byte-literal — RFC 4035 AD-bit mask
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// DoH GET URL length cap. RFC 8484 §4.1 says clients MAY use POST when
|
|
371
|
+
// the GET URL would exceed implementation limits. We pick 2048 bytes
|
|
372
|
+
// (a conservative ceiling well below RFC 7230's recommended 8 KB) so
|
|
373
|
+
// long DNS names (e.g. ESNI / SVCB record queries with operator-side
|
|
374
|
+
// hostname concatenation) fall back cleanly. Operator can force POST
|
|
375
|
+
// always with `useDnsOverHttps({ url, method: "POST" })`.
|
|
376
|
+
var DOH_GET_URL_MAX_BYTES = 2048;
|
|
377
|
+
|
|
378
|
+
async function _dohLookup(host, family) {
|
|
379
|
+
var qtype = family === 6 ? 28 : 1;
|
|
380
|
+
var enc = _encodeDnsQuery(host, qtype);
|
|
381
|
+
var b64 = bCrypto.toBase64Url(enc.buf);
|
|
382
|
+
var getUrl = STATE.doh.url + (STATE.doh.url.indexOf("?") === -1 ? "?" : "&") + "dns=" + b64;
|
|
383
|
+
var forcedMethod = STATE.doh.method;
|
|
384
|
+
var usePost = forcedMethod === "POST" || (!forcedMethod && getUrl.length > DOH_GET_URL_MAX_BYTES);
|
|
385
|
+
// STATE.doh.url is already https-validated in useDnsOverHttps; route the
|
|
386
|
+
// parse through safeUrl so the framework's URL primitive owns every parse.
|
|
387
|
+
var u = safeUrl.parse(STATE.doh.url, { allowedProtocols: safeUrl.ALLOW_HTTP_TLS });
|
|
388
|
+
return new Promise(function (resolve, reject) {
|
|
389
|
+
var reqOpts = {
|
|
390
|
+
hostname: u.hostname,
|
|
391
|
+
port: u.port || 443,
|
|
392
|
+
path: u.pathname + u.search,
|
|
393
|
+
method: usePost ? "POST" : "GET",
|
|
394
|
+
headers: {
|
|
395
|
+
"accept": "application/dns-message",
|
|
396
|
+
},
|
|
397
|
+
minVersion: "TLSv1.3",
|
|
398
|
+
ecdhCurve: C.TLS_GROUP_CURVE_STR,
|
|
399
|
+
};
|
|
400
|
+
if (STATE.doh.ca) reqOpts.ca = STATE.doh.ca;
|
|
401
|
+
if (usePost) {
|
|
402
|
+
reqOpts.headers["content-type"] = "application/dns-message";
|
|
403
|
+
reqOpts.headers["content-length"] = enc.buf.length;
|
|
404
|
+
} else {
|
|
405
|
+
// getUrl was composed from STATE.doh.url + a base64-url DNS query suffix.
|
|
406
|
+
// safeUrl.parse re-validates the composed URL.
|
|
407
|
+
var parsedGet = safeUrl.parse(getUrl, { allowedProtocols: safeUrl.ALLOW_HTTP_TLS });
|
|
408
|
+
reqOpts.path = parsedGet.pathname + parsedGet.search;
|
|
409
|
+
}
|
|
410
|
+
var req = https.request(reqOpts, function (res) {
|
|
411
|
+
// RFC 8484 caps DoH responses at 64 KiB practical max; raise to
|
|
412
|
+
// 256 KiB to leave headroom for upstream resolvers that pad.
|
|
413
|
+
var collector = safeBuffer.boundedChunkCollector({
|
|
414
|
+
maxBytes: C.BYTES.kib(256),
|
|
415
|
+
errorClass: DnsError,
|
|
416
|
+
sizeCode: "dns/doh-too-large",
|
|
417
|
+
sizeMessage: "DoH response exceeds 256 KiB",
|
|
418
|
+
});
|
|
419
|
+
var pushFailed = null;
|
|
420
|
+
res.on("data", function (c) {
|
|
421
|
+
if (pushFailed) return;
|
|
422
|
+
try { collector.push(c); }
|
|
423
|
+
catch (e) { pushFailed = e; }
|
|
424
|
+
});
|
|
425
|
+
res.on("end", function () {
|
|
426
|
+
try {
|
|
427
|
+
if (pushFailed) { reject(pushFailed); return; }
|
|
428
|
+
var body = collector.result();
|
|
429
|
+
if (res.statusCode !== 200) {
|
|
430
|
+
reject(new DnsError("dns/doh-http", "DoH HTTP " + res.statusCode + " for " + host));
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
resolve(_decodeDnsAnswer(body, qtype));
|
|
434
|
+
} catch (e) { reject(e); }
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
req.on("error", function (e) { reject(new DnsError("dns/doh-failed", "DoH request failed: " + e.message)); });
|
|
438
|
+
if (usePost) req.write(enc.buf);
|
|
439
|
+
req.end();
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// _dohLookupSecure — DNSSEC-aware DoH lookup. Returns `{ rrs, ad }`
|
|
444
|
+
// where `ad` is the AD bit (RFC 4035) set by the upstream resolver
|
|
445
|
+
// after chain validation. Internal — operators reach for
|
|
446
|
+
// `resolveSecure` instead.
|
|
447
|
+
async function _dohLookupSecure(host, family) {
|
|
448
|
+
var qtype = family === 6 ? 28 : 1; // allow:raw-byte-literal — DNS QTYPE values for A / AAAA
|
|
449
|
+
var enc = _encodeDnsQuery(host, qtype);
|
|
450
|
+
var b64 = bCrypto.toBase64Url(enc.buf);
|
|
451
|
+
var getUrl = STATE.doh.url + (STATE.doh.url.indexOf("?") === -1 ? "?" : "&") + "dns=" + b64;
|
|
452
|
+
var forcedMethod = STATE.doh.method;
|
|
453
|
+
var usePost = forcedMethod === "POST" || (!forcedMethod && getUrl.length > DOH_GET_URL_MAX_BYTES);
|
|
454
|
+
var u = safeUrl.parse(STATE.doh.url, { allowedProtocols: safeUrl.ALLOW_HTTP_TLS });
|
|
455
|
+
return new Promise(function (resolve, reject) {
|
|
456
|
+
var reqOpts = {
|
|
457
|
+
hostname: u.hostname,
|
|
458
|
+
port: u.port || 443, // allow:raw-byte-literal — HTTPS default port
|
|
459
|
+
path: u.pathname + u.search,
|
|
460
|
+
method: usePost ? "POST" : "GET",
|
|
461
|
+
headers: { "accept": "application/dns-message" },
|
|
462
|
+
minVersion: "TLSv1.3",
|
|
463
|
+
ecdhCurve: C.TLS_GROUP_CURVE_STR,
|
|
464
|
+
};
|
|
465
|
+
if (STATE.doh.ca) reqOpts.ca = STATE.doh.ca;
|
|
466
|
+
if (usePost) {
|
|
467
|
+
reqOpts.headers["content-type"] = "application/dns-message";
|
|
468
|
+
reqOpts.headers["content-length"] = enc.buf.length;
|
|
469
|
+
} else {
|
|
470
|
+
var parsedGet = safeUrl.parse(getUrl, { allowedProtocols: safeUrl.ALLOW_HTTP_TLS });
|
|
471
|
+
reqOpts.path = parsedGet.pathname + parsedGet.search;
|
|
472
|
+
}
|
|
473
|
+
var req = https.request(reqOpts, function (res) {
|
|
474
|
+
var collector = safeBuffer.boundedChunkCollector({
|
|
475
|
+
maxBytes: C.BYTES.kib(256),
|
|
476
|
+
errorClass: DnsError,
|
|
477
|
+
sizeCode: "dns/doh-too-large",
|
|
478
|
+
sizeMessage: "DoH response exceeds 256 KiB",
|
|
479
|
+
});
|
|
480
|
+
var pushFailed = null;
|
|
481
|
+
res.on("data", function (c) {
|
|
482
|
+
if (pushFailed) return;
|
|
483
|
+
try { collector.push(c); }
|
|
484
|
+
catch (e) { pushFailed = e; }
|
|
485
|
+
});
|
|
486
|
+
res.on("end", function () {
|
|
487
|
+
try {
|
|
488
|
+
if (pushFailed) { reject(pushFailed); return; }
|
|
489
|
+
var body = collector.result();
|
|
490
|
+
if (res.statusCode !== 200) { // allow:raw-byte-literal — HTTP 200 OK
|
|
491
|
+
reject(new DnsError("dns/doh-http", "DoH HTTP " + res.statusCode + " for " + host));
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
resolve({ rrs: _decodeDnsAnswer(body, qtype), ad: _readAdBit(body) });
|
|
495
|
+
} catch (e) { reject(e); }
|
|
496
|
+
});
|
|
497
|
+
});
|
|
498
|
+
req.on("error", function (e) { reject(new DnsError("dns/doh-failed", "DoH request failed: " + e.message)); });
|
|
499
|
+
if (usePost) req.write(enc.buf);
|
|
500
|
+
req.end();
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// resolveSecure — DNSSEC-aware resolution. Returns `{ rrs, ad }`
|
|
505
|
+
// where `ad` is the AD bit (RFC 4035) set by the upstream DoH
|
|
506
|
+
// resolver after chain validation, and `rrs` is the answer-record
|
|
507
|
+
// list (IPv4 / IPv6 string addresses for A / AAAA queries).
|
|
508
|
+
//
|
|
509
|
+
// Operators wiring DANE / TLSA validation (RFC 7672 SMTP DANE)
|
|
510
|
+
// require `ad === true` to honor the DANE security claim per RFC
|
|
511
|
+
// 7672 §1.3 — without DNSSEC validation the TLSA records can't be
|
|
512
|
+
// authenticated and the chain check is meaningless.
|
|
513
|
+
//
|
|
514
|
+
// Only available over DoH transport. The system resolver and DoT
|
|
515
|
+
// transports don't surface the AD bit through Node's API today.
|
|
516
|
+
async function resolveSecure(host, type) {
|
|
517
|
+
type = type || "A";
|
|
518
|
+
if (!STATE.doh) {
|
|
519
|
+
throw new DnsError("dns/secure-requires-doh",
|
|
520
|
+
"resolveSecure requires DoH transport (call useDnsOverHttps " +
|
|
521
|
+
"or rely on the default-on DoH posture)");
|
|
522
|
+
}
|
|
523
|
+
if (typeof host !== "string" || host.length === 0 || host.length > 253) { // allow:raw-byte-literal — RFC 1035 hostname octet ceiling
|
|
524
|
+
throw new DnsError("dns/bad-host",
|
|
525
|
+
"resolveSecure host is malformed");
|
|
526
|
+
}
|
|
527
|
+
// RFC 1035 §2.3.4 LDH validation — labels are letters / digits /
|
|
528
|
+
// hyphen, hyphens not at edges, label length 1..63, total length
|
|
529
|
+
// 253. Pre-v0.8.32 the framework only checked total length;
|
|
530
|
+
// operator-supplied hosts containing `_` / `:` / spaces flowed
|
|
531
|
+
// through to the DoH endpoint and surfaced as opaque server
|
|
532
|
+
// errors.
|
|
533
|
+
var labels = host.split(".");
|
|
534
|
+
for (var li = 0; li < labels.length; li += 1) {
|
|
535
|
+
var label = labels[li];
|
|
536
|
+
if (label.length === 0 || label.length > 63) { // allow:raw-byte-literal — RFC 1035 max label length
|
|
537
|
+
throw new DnsError("dns/bad-host",
|
|
538
|
+
"resolveSecure host has invalid label (length 1..63 required, got " + label.length + ")");
|
|
539
|
+
}
|
|
540
|
+
if (!/^[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?$/.test(label)) {
|
|
541
|
+
throw new DnsError("dns/bad-host",
|
|
542
|
+
"resolveSecure host label '" + label + "' violates RFC 1035 LDH rule (letters/digits/hyphen, no leading/trailing hyphen)");
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
var family;
|
|
546
|
+
if (type === "A") family = 4;
|
|
547
|
+
else if (type === "AAAA") family = 6;
|
|
548
|
+
else throw new DnsError("dns/secure-unsupported-type",
|
|
549
|
+
"resolveSecure currently supports A and AAAA; got " + type);
|
|
550
|
+
return _dohLookupSecure(host, family);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// DoT connection pool. Per-(host:port) cached TLS socket so successive
|
|
554
|
+
// lookups amortize the handshake. Sockets idle past the timeout are
|
|
555
|
+
// closed and removed; first lookup after expiry rebuilds. Each socket
|
|
556
|
+
// services one in-flight query at a time (DNS-over-TCP allows pipelining
|
|
557
|
+
// but the framework chooses serialization for simpler back-pressure).
|
|
558
|
+
var DOT_IDLE_TIMEOUT_MS = C.TIME.minutes(2);
|
|
559
|
+
var _dotPool = new Map(); // "host:port" → { sock, lastUsedAt, idle, queue }
|
|
560
|
+
|
|
561
|
+
function _dotPoolKey() {
|
|
562
|
+
return STATE.dot.host + ":" + STATE.dot.port;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
function _dotConnect() {
|
|
566
|
+
var connectOpts = {
|
|
567
|
+
host: STATE.dot.host,
|
|
568
|
+
port: STATE.dot.port,
|
|
569
|
+
servername: STATE.dot.servername,
|
|
570
|
+
minVersion: "TLSv1.3",
|
|
571
|
+
ecdhCurve: C.TLS_GROUP_CURVE_STR,
|
|
572
|
+
};
|
|
573
|
+
if (STATE.dot.ca) connectOpts.ca = STATE.dot.ca;
|
|
574
|
+
var sock = nodeTls.connect(connectOpts);
|
|
575
|
+
// The pool entry is ref()'d while a query is in flight and unref()'d
|
|
576
|
+
// when idle — _dotLookup toggles this around its query. Calling
|
|
577
|
+
// unref() unconditionally here let node exit during a normal lookup
|
|
578
|
+
// when no other I/O kept the event loop alive.
|
|
579
|
+
return sock;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
function _dotEvict(key) {
|
|
583
|
+
var entry = _dotPool.get(key);
|
|
584
|
+
if (!entry) return;
|
|
585
|
+
try { entry.sock.destroy(); } catch (_e) { /* best-effort socket teardown */ }
|
|
586
|
+
_dotPool.delete(key);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
async function _dotLookup(host, family) {
|
|
590
|
+
var qtype = family === 6 ? 28 : 1;
|
|
591
|
+
var enc = _encodeDnsQuery(host, qtype);
|
|
592
|
+
var key = _dotPoolKey();
|
|
593
|
+
var entry = _dotPool.get(key);
|
|
594
|
+
if (entry && (Date.now() - entry.lastUsedAt > DOT_IDLE_TIMEOUT_MS)) {
|
|
595
|
+
_dotEvict(key);
|
|
596
|
+
entry = null;
|
|
597
|
+
}
|
|
598
|
+
if (!entry) {
|
|
599
|
+
var sock = _dotConnect();
|
|
600
|
+
entry = {
|
|
601
|
+
sock: sock,
|
|
602
|
+
lastUsedAt: Date.now(),
|
|
603
|
+
idle: true,
|
|
604
|
+
ready: new Promise(function (res, rej) {
|
|
605
|
+
sock.once("secureConnect", function () { res(); });
|
|
606
|
+
sock.once("error", function (e) {
|
|
607
|
+
rej(new DnsError("dns/dot-handshake-failed",
|
|
608
|
+
"DoT TLS handshake to " + STATE.dot.host + ":" + STATE.dot.port +
|
|
609
|
+
" failed: " + ((e && e.message) || String(e))));
|
|
610
|
+
});
|
|
611
|
+
}),
|
|
612
|
+
};
|
|
613
|
+
// Pre-attach a no-op observer so a handshake failure isn't reported
|
|
614
|
+
// as an unhandledRejection in the window between this assignment
|
|
615
|
+
// and the first lookup awaiting entry.ready. The real reject path
|
|
616
|
+
// routes through _dotLookup's then(_, onErr) handler below.
|
|
617
|
+
entry.ready.catch(function () { /* observed; routed via per-lookup handler */ });
|
|
618
|
+
_dotPool.set(key, entry);
|
|
619
|
+
sock.on("error", function () { _dotEvict(key); });
|
|
620
|
+
sock.on("close", function () { if (_dotPool.get(key) === entry) _dotPool.delete(key); });
|
|
621
|
+
}
|
|
622
|
+
// Serialize: each socket handles one query at a time. If another
|
|
623
|
+
// query is in flight, queue behind it.
|
|
624
|
+
var waitTicket = entry._tail || Promise.resolve();
|
|
625
|
+
entry._tail = waitTicket.then(function () {
|
|
626
|
+
return new Promise(function (resolve, reject) {
|
|
627
|
+
entry.idle = false;
|
|
628
|
+
// Hold the event loop open while a query is in flight.
|
|
629
|
+
try { entry.sock.ref(); } catch (_e) { /* best-effort event-loop hold */ }
|
|
630
|
+
Promise.resolve(entry.ready).then(function () {
|
|
631
|
+
var lenBuf = Buffer.alloc(2);
|
|
632
|
+
lenBuf.writeUInt16BE(enc.buf.length, 0);
|
|
633
|
+
var got = [];
|
|
634
|
+
var expectLen = -1;
|
|
635
|
+
var done = false;
|
|
636
|
+
function settle(err, val) {
|
|
637
|
+
if (done) return;
|
|
638
|
+
done = true;
|
|
639
|
+
entry.sock.removeListener("data", onData);
|
|
640
|
+
entry.sock.removeListener("error", onErr);
|
|
641
|
+
entry.idle = true;
|
|
642
|
+
entry.lastUsedAt = Date.now();
|
|
643
|
+
// Release the event-loop hold so an idle pool socket doesn't
|
|
644
|
+
// keep node alive between queries.
|
|
645
|
+
try { entry.sock.unref(); } catch (_e) { /* best-effort event-loop release */ }
|
|
646
|
+
if (err) reject(err); else resolve(val);
|
|
647
|
+
}
|
|
648
|
+
function onData(chunk) {
|
|
649
|
+
got.push(chunk);
|
|
650
|
+
var all = Buffer.concat(got);
|
|
651
|
+
if (expectLen === -1 && all.length >= 2) expectLen = all.readUInt16BE(0);
|
|
652
|
+
if (expectLen >= 0 && all.length >= expectLen + 2) {
|
|
653
|
+
try {
|
|
654
|
+
settle(null, _decodeDnsAnswer(all.slice(2, 2 + expectLen), qtype));
|
|
655
|
+
} catch (e) { settle(e); }
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
function onErr(e) {
|
|
659
|
+
_dotEvict(key);
|
|
660
|
+
settle(new DnsError("dns/dot-failed", "DoT failed: " + e.message));
|
|
661
|
+
}
|
|
662
|
+
entry.sock.on("data", onData);
|
|
663
|
+
entry.sock.on("error", onErr);
|
|
664
|
+
entry.sock.write(lenBuf);
|
|
665
|
+
entry.sock.write(enc.buf);
|
|
666
|
+
}, function (handshakeErr) {
|
|
667
|
+
// entry.ready rejected (TLS handshake / cert verification failure).
|
|
668
|
+
// Route as the lookup's reject so callers see a real DnsError
|
|
669
|
+
// instead of an unhandledRejection from the TLSSocket event.
|
|
670
|
+
entry.idle = true;
|
|
671
|
+
try { entry.sock.unref(); } catch (_e) { /* best-effort event-loop release */ }
|
|
672
|
+
reject(handshakeErr);
|
|
673
|
+
});
|
|
674
|
+
});
|
|
675
|
+
});
|
|
676
|
+
return entry._tail;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
function _resetDotPool() {
|
|
680
|
+
var keys = Array.from(_dotPool.keys());
|
|
681
|
+
for (var i = 0; i < keys.length; i++) _dotEvict(keys[i]);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// ---- Generic DNS query (arbitrary QTYPE) -----------------------------
|
|
685
|
+
//
|
|
686
|
+
// The pre-v0.8.53 DNS module only handled A (1) and AAAA (28) lookups.
|
|
687
|
+
// SVCB (64) / HTTPS (65) and the DDR / DNR discovery primitives need a
|
|
688
|
+
// path that sends an arbitrary QTYPE and returns the raw rdata buffers
|
|
689
|
+
// for downstream parsing. These helpers reuse the existing encode +
|
|
690
|
+
// transport infrastructure (DoH / DoT / system) and add a small
|
|
691
|
+
// rdata-aware decoder that walks the answer section preserving the
|
|
692
|
+
// rdata bytes and answer offsets (needed because SVCB rdata contains
|
|
693
|
+
// compressed names that point back into the message).
|
|
694
|
+
//
|
|
695
|
+
// NOT IN SCOPE — DoQ (DNS-over-QUIC, RFC 9250). Node's QUIC support is
|
|
696
|
+
// experimental as of Node 24.x (tracking issue
|
|
697
|
+
// https://github.com/nodejs/node/issues/38478) and the framework's
|
|
698
|
+
// "no flag-gated experimental APIs in defaults" policy keeps it
|
|
699
|
+
// deferred. Operators wanting DoQ today wire it in their own agent
|
|
700
|
+
// and feed the returned IP set back through the existing transport
|
|
701
|
+
// abstractions (DDR-discovered DoH / DoT). Re-evaluate when Node
|
|
702
|
+
// flips QUIC stable.
|
|
703
|
+
|
|
704
|
+
// RFC 1035 §4.1.4 name compression — read a possibly-compressed name
|
|
705
|
+
// starting at `start`. Returns { name, nextOff } where nextOff is the
|
|
706
|
+
// byte immediately after the name's length-prefixed encoding (NOT
|
|
707
|
+
// chasing the pointer). `name` is a dot-joined string (without the
|
|
708
|
+
// trailing root label). Hardened against pointer loops with an
|
|
709
|
+
// iteration cap.
|
|
710
|
+
function _readDnsName(buf, start) {
|
|
711
|
+
var labels = [];
|
|
712
|
+
var off = start;
|
|
713
|
+
var nextOff = -1;
|
|
714
|
+
var iterations = 0;
|
|
715
|
+
var ITER_CAP = 256; // allow:raw-byte-literal — DNS name pointer-loop safeguard
|
|
716
|
+
while (off < buf.length && iterations < ITER_CAP) {
|
|
717
|
+
iterations += 1;
|
|
718
|
+
var len = buf[off];
|
|
719
|
+
if (len === 0) {
|
|
720
|
+
if (nextOff === -1) nextOff = off + 1;
|
|
721
|
+
break;
|
|
722
|
+
}
|
|
723
|
+
if ((len & 0xc0) === 0xc0) { // allow:raw-byte-literal — RFC 1035 name-compression pointer mask
|
|
724
|
+
if (off + 1 >= buf.length) {
|
|
725
|
+
throw new DnsError("dns/svcb-malformed",
|
|
726
|
+
"DNS name truncated at compression pointer");
|
|
727
|
+
}
|
|
728
|
+
if (nextOff === -1) nextOff = off + 2;
|
|
729
|
+
var ptr = ((len & 0x3f) << 8) | buf[off + 1]; // allow:raw-byte-literal — RFC 1035 pointer offset mask
|
|
730
|
+
if (ptr >= buf.length || ptr === off) {
|
|
731
|
+
throw new DnsError("dns/svcb-malformed",
|
|
732
|
+
"DNS name pointer out of bounds or self-referential");
|
|
733
|
+
}
|
|
734
|
+
off = ptr;
|
|
735
|
+
continue;
|
|
736
|
+
}
|
|
737
|
+
if ((len & 0xc0) !== 0) { // allow:raw-byte-literal — RFC 1035 reserved label-type bits
|
|
738
|
+
throw new DnsError("dns/svcb-malformed",
|
|
739
|
+
"DNS name has reserved label type 0x" + len.toString(HEX_RADIX));
|
|
740
|
+
}
|
|
741
|
+
if (off + 1 + len > buf.length) {
|
|
742
|
+
throw new DnsError("dns/svcb-malformed",
|
|
743
|
+
"DNS name label exceeds message length");
|
|
744
|
+
}
|
|
745
|
+
labels.push(buf.toString("ascii", off + 1, off + 1 + len));
|
|
746
|
+
off += 1 + len;
|
|
747
|
+
}
|
|
748
|
+
if (iterations >= ITER_CAP) {
|
|
749
|
+
throw new DnsError("dns/svcb-malformed",
|
|
750
|
+
"DNS name compression loop (>" + ITER_CAP + " hops)");
|
|
751
|
+
}
|
|
752
|
+
if (nextOff === -1) {
|
|
753
|
+
throw new DnsError("dns/svcb-malformed",
|
|
754
|
+
"DNS name not terminated");
|
|
755
|
+
}
|
|
756
|
+
return { name: labels.join("."), nextOff: nextOff };
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// Walk the answer section preserving rdata offsets so SVCB rdata can
|
|
760
|
+
// resolve compressed names against the full message buffer.
|
|
761
|
+
function _decodeDnsAnswerRaw(buf) {
|
|
762
|
+
if (!Buffer.isBuffer(buf) || buf.length < 12) {
|
|
763
|
+
throw new DnsError("dns/bad-reply", "dns reply truncated");
|
|
764
|
+
}
|
|
765
|
+
var rcode = buf.readUInt8(3) & 0x0f; // allow:raw-byte-literal — RFC 1035 RCODE nibble mask
|
|
766
|
+
if (rcode !== 0) {
|
|
767
|
+
throw new DnsError("dns/no-result", "dns reply rcode " + rcode);
|
|
768
|
+
}
|
|
769
|
+
var qdcount = buf.readUInt16BE(4);
|
|
770
|
+
var ancount = buf.readUInt16BE(6);
|
|
771
|
+
var state = { off: 12 };
|
|
772
|
+
for (var q = 0; q < qdcount; q++) {
|
|
773
|
+
_skipDnsName(buf, state);
|
|
774
|
+
state.off += 4;
|
|
775
|
+
}
|
|
776
|
+
var answers = [];
|
|
777
|
+
for (var a = 0; a < ancount; a++) {
|
|
778
|
+
_skipDnsName(buf, state);
|
|
779
|
+
var off = state.off;
|
|
780
|
+
if (off + 10 > buf.length) {
|
|
781
|
+
throw new DnsError("dns/bad-reply", "answer record truncated");
|
|
782
|
+
}
|
|
783
|
+
var rtype = buf.readUInt16BE(off); off += 2;
|
|
784
|
+
var rclass = buf.readUInt16BE(off); off += 2;
|
|
785
|
+
var ttl = buf.readUInt32BE(off); off += 4;
|
|
786
|
+
var rdlen = buf.readUInt16BE(off); off += 2;
|
|
787
|
+
if (off + rdlen > buf.length) {
|
|
788
|
+
throw new DnsError("dns/bad-reply", "answer rdata truncated");
|
|
789
|
+
}
|
|
790
|
+
answers.push({
|
|
791
|
+
rtype: rtype,
|
|
792
|
+
rclass: rclass,
|
|
793
|
+
ttl: ttl,
|
|
794
|
+
rdataOff: off,
|
|
795
|
+
rdlen: rdlen,
|
|
796
|
+
});
|
|
797
|
+
off += rdlen;
|
|
798
|
+
state.off = off;
|
|
799
|
+
}
|
|
800
|
+
return { msg: buf, answers: answers, ad: _readAdBit(buf) };
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
async function _dohRawQuery(host, qtype) {
|
|
804
|
+
var enc = _encodeDnsQuery(host, qtype);
|
|
805
|
+
var b64 = bCrypto.toBase64Url(enc.buf);
|
|
806
|
+
var getUrl = STATE.doh.url + (STATE.doh.url.indexOf("?") === -1 ? "?" : "&") + "dns=" + b64;
|
|
807
|
+
var forcedMethod = STATE.doh.method;
|
|
808
|
+
var usePost = forcedMethod === "POST" || (!forcedMethod && getUrl.length > DOH_GET_URL_MAX_BYTES);
|
|
809
|
+
var u = safeUrl.parse(STATE.doh.url, { allowedProtocols: safeUrl.ALLOW_HTTP_TLS });
|
|
810
|
+
return new Promise(function (resolve, reject) {
|
|
811
|
+
var reqOpts = {
|
|
812
|
+
hostname: u.hostname,
|
|
813
|
+
port: u.port || 443, // allow:raw-byte-literal — HTTPS default port
|
|
814
|
+
path: u.pathname + u.search,
|
|
815
|
+
method: usePost ? "POST" : "GET",
|
|
816
|
+
headers: { "accept": "application/dns-message" },
|
|
817
|
+
minVersion: "TLSv1.3",
|
|
818
|
+
ecdhCurve: C.TLS_GROUP_CURVE_STR,
|
|
819
|
+
};
|
|
820
|
+
if (STATE.doh.ca) reqOpts.ca = STATE.doh.ca;
|
|
821
|
+
if (usePost) {
|
|
822
|
+
reqOpts.headers["content-type"] = "application/dns-message";
|
|
823
|
+
reqOpts.headers["content-length"] = enc.buf.length;
|
|
824
|
+
} else {
|
|
825
|
+
var parsedGet = safeUrl.parse(getUrl, { allowedProtocols: safeUrl.ALLOW_HTTP_TLS });
|
|
826
|
+
reqOpts.path = parsedGet.pathname + parsedGet.search;
|
|
827
|
+
}
|
|
828
|
+
var req = https.request(reqOpts, function (res) {
|
|
829
|
+
var collector = safeBuffer.boundedChunkCollector({
|
|
830
|
+
maxBytes: C.BYTES.kib(256),
|
|
831
|
+
errorClass: DnsError,
|
|
832
|
+
sizeCode: "dns/doh-too-large",
|
|
833
|
+
sizeMessage: "DoH response exceeds 256 KiB",
|
|
834
|
+
});
|
|
835
|
+
var pushFailed = null;
|
|
836
|
+
res.on("data", function (c) {
|
|
837
|
+
if (pushFailed) return;
|
|
838
|
+
try { collector.push(c); }
|
|
839
|
+
catch (e) { pushFailed = e; }
|
|
840
|
+
});
|
|
841
|
+
res.on("end", function () {
|
|
842
|
+
try {
|
|
843
|
+
if (pushFailed) { reject(pushFailed); return; }
|
|
844
|
+
if (res.statusCode !== 200) { // allow:raw-byte-literal — HTTP 200 OK
|
|
845
|
+
reject(new DnsError("dns/doh-http", "DoH HTTP " + res.statusCode + " for " + host));
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
resolve(collector.result());
|
|
849
|
+
} catch (e) { reject(e); }
|
|
850
|
+
});
|
|
851
|
+
});
|
|
852
|
+
req.on("error", function (e) { reject(new DnsError("dns/doh-failed", "DoH request failed: " + e.message)); });
|
|
853
|
+
if (usePost) req.write(enc.buf);
|
|
854
|
+
req.end();
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
async function _dotRawQuery(host, qtype) {
|
|
859
|
+
var enc = _encodeDnsQuery(host, qtype);
|
|
860
|
+
var key = _dotPoolKey();
|
|
861
|
+
var entry = _dotPool.get(key);
|
|
862
|
+
if (entry && (Date.now() - entry.lastUsedAt > DOT_IDLE_TIMEOUT_MS)) {
|
|
863
|
+
_dotEvict(key);
|
|
864
|
+
entry = null;
|
|
865
|
+
}
|
|
866
|
+
if (!entry) {
|
|
867
|
+
var sock = _dotConnect();
|
|
868
|
+
entry = {
|
|
869
|
+
sock: sock,
|
|
870
|
+
lastUsedAt: Date.now(),
|
|
871
|
+
idle: true,
|
|
872
|
+
ready: new Promise(function (res, rej) {
|
|
873
|
+
sock.once("secureConnect", function () { res(); });
|
|
874
|
+
sock.once("error", function (e) {
|
|
875
|
+
rej(new DnsError("dns/dot-handshake-failed",
|
|
876
|
+
"DoT TLS handshake to " + STATE.dot.host + ":" + STATE.dot.port +
|
|
877
|
+
" failed: " + ((e && e.message) || String(e))));
|
|
878
|
+
});
|
|
879
|
+
}),
|
|
880
|
+
};
|
|
881
|
+
entry.ready.catch(function () { /* observed via per-lookup handler below */ });
|
|
882
|
+
_dotPool.set(key, entry);
|
|
883
|
+
sock.on("error", function () { _dotEvict(key); });
|
|
884
|
+
sock.on("close", function () { if (_dotPool.get(key) === entry) _dotPool.delete(key); });
|
|
885
|
+
}
|
|
886
|
+
var waitTicket = entry._tail || Promise.resolve();
|
|
887
|
+
entry._tail = waitTicket.then(function () {
|
|
888
|
+
return new Promise(function (resolve, reject) {
|
|
889
|
+
entry.idle = false;
|
|
890
|
+
try { entry.sock.ref(); } catch (_e) { /* best-effort event-loop hold */ }
|
|
891
|
+
Promise.resolve(entry.ready).then(function () {
|
|
892
|
+
var lenBuf = Buffer.alloc(2);
|
|
893
|
+
lenBuf.writeUInt16BE(enc.buf.length, 0);
|
|
894
|
+
var got = [];
|
|
895
|
+
var expectLen = -1;
|
|
896
|
+
var done = false;
|
|
897
|
+
function settle(err, val) {
|
|
898
|
+
if (done) return;
|
|
899
|
+
done = true;
|
|
900
|
+
entry.sock.removeListener("data", onData);
|
|
901
|
+
entry.sock.removeListener("error", onErr);
|
|
902
|
+
entry.idle = true;
|
|
903
|
+
entry.lastUsedAt = Date.now();
|
|
904
|
+
try { entry.sock.unref(); } catch (_e) { /* best-effort event-loop release */ }
|
|
905
|
+
if (err) reject(err); else resolve(val);
|
|
906
|
+
}
|
|
907
|
+
function onData(chunk) {
|
|
908
|
+
got.push(chunk);
|
|
909
|
+
var all = Buffer.concat(got);
|
|
910
|
+
if (expectLen === -1 && all.length >= 2) expectLen = all.readUInt16BE(0);
|
|
911
|
+
if (expectLen >= 0 && all.length >= expectLen + 2) {
|
|
912
|
+
settle(null, all.slice(2, 2 + expectLen));
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
function onErr(e) {
|
|
916
|
+
_dotEvict(key);
|
|
917
|
+
settle(new DnsError("dns/dot-failed", "DoT failed: " + e.message));
|
|
918
|
+
}
|
|
919
|
+
entry.sock.on("data", onData);
|
|
920
|
+
entry.sock.on("error", onErr);
|
|
921
|
+
entry.sock.write(lenBuf);
|
|
922
|
+
entry.sock.write(enc.buf);
|
|
923
|
+
}, function (handshakeErr) {
|
|
924
|
+
entry.idle = true;
|
|
925
|
+
try { entry.sock.unref(); } catch (_e) { /* best-effort event-loop release */ }
|
|
926
|
+
reject(handshakeErr);
|
|
927
|
+
});
|
|
928
|
+
});
|
|
929
|
+
});
|
|
930
|
+
return entry._tail;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
async function _systemRawQuery(host, qtype) {
|
|
934
|
+
// node:dns doesn't expose arbitrary-QTYPE wire-format queries; fall
|
|
935
|
+
// back to TCP framed query against the configured system resolvers
|
|
936
|
+
// (port 53). Used only when the operator has explicitly opted out
|
|
937
|
+
// of DoH/DoT via useSystemResolver().
|
|
938
|
+
var servers = getServers();
|
|
939
|
+
if (servers.length === 0) {
|
|
940
|
+
throw new DnsError("dns/no-system-resolvers",
|
|
941
|
+
"system resolver has no configured servers; cannot send raw QTYPE query");
|
|
942
|
+
}
|
|
943
|
+
var serverEntry = servers[0];
|
|
944
|
+
var serverHost = serverEntry;
|
|
945
|
+
var serverPort = 53; // allow:raw-byte-literal — IANA-assigned DNS port
|
|
946
|
+
var bracketEnd = serverEntry.lastIndexOf("]:");
|
|
947
|
+
if (bracketEnd !== -1) {
|
|
948
|
+
serverHost = serverEntry.slice(1, bracketEnd);
|
|
949
|
+
serverPort = parseInt(serverEntry.slice(bracketEnd + 2), 10) || 53; // allow:raw-byte-literal — IANA-assigned DNS port
|
|
950
|
+
} else if (serverEntry.indexOf(":") !== -1 && net.isIP(serverEntry) === 0) {
|
|
951
|
+
var colonIdx = serverEntry.lastIndexOf(":");
|
|
952
|
+
serverHost = serverEntry.slice(0, colonIdx);
|
|
953
|
+
serverPort = parseInt(serverEntry.slice(colonIdx + 1), 10) || 53; // allow:raw-byte-literal — IANA-assigned DNS port
|
|
954
|
+
}
|
|
955
|
+
var enc = _encodeDnsQuery(host, qtype);
|
|
956
|
+
return new Promise(function (resolve, reject) {
|
|
957
|
+
var sock = net.connect({ host: serverHost, port: serverPort });
|
|
958
|
+
var got = [];
|
|
959
|
+
var expectLen = -1;
|
|
960
|
+
var done = false;
|
|
961
|
+
function settle(err, val) {
|
|
962
|
+
if (done) return;
|
|
963
|
+
done = true;
|
|
964
|
+
try { sock.destroy(); } catch (_e) { /* best-effort socket teardown */ }
|
|
965
|
+
if (err) reject(err); else resolve(val);
|
|
966
|
+
}
|
|
967
|
+
sock.on("connect", function () {
|
|
968
|
+
var lenBuf = Buffer.alloc(2);
|
|
969
|
+
lenBuf.writeUInt16BE(enc.buf.length, 0);
|
|
970
|
+
sock.write(lenBuf);
|
|
971
|
+
sock.write(enc.buf);
|
|
972
|
+
});
|
|
973
|
+
sock.on("data", function (chunk) {
|
|
974
|
+
got.push(chunk);
|
|
975
|
+
var all = Buffer.concat(got);
|
|
976
|
+
if (expectLen === -1 && all.length >= 2) expectLen = all.readUInt16BE(0);
|
|
977
|
+
if (expectLen >= 0 && all.length >= expectLen + 2) {
|
|
978
|
+
settle(null, all.slice(2, 2 + expectLen));
|
|
979
|
+
}
|
|
980
|
+
});
|
|
981
|
+
sock.on("error", function (e) {
|
|
982
|
+
settle(new DnsError("dns/system-failed", "system DNS TCP query failed: " + e.message));
|
|
983
|
+
});
|
|
984
|
+
sock.on("close", function () {
|
|
985
|
+
if (!done) settle(new DnsError("dns/system-failed", "system DNS TCP closed before reply"));
|
|
986
|
+
});
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
// Pick a transport for raw-QTYPE queries based on operator config.
|
|
991
|
+
// `forceTransport` (used by DDR) overrides; "system" routes through
|
|
992
|
+
// the OS resolver.
|
|
993
|
+
async function _rawQuery(host, qtype, forceTransport) {
|
|
994
|
+
_ensureSecureDefault();
|
|
995
|
+
var transport = forceTransport;
|
|
996
|
+
if (!transport) {
|
|
997
|
+
if (STATE.doh) transport = "doh";
|
|
998
|
+
else if (STATE.dot) transport = "dot";
|
|
999
|
+
else transport = "system";
|
|
1000
|
+
}
|
|
1001
|
+
if (transport === "doh") {
|
|
1002
|
+
if (!STATE.doh) {
|
|
1003
|
+
throw new DnsError("dns/transport-unavailable",
|
|
1004
|
+
"raw query requested DoH transport but useDnsOverHttps() not configured");
|
|
1005
|
+
}
|
|
1006
|
+
return _withTimeout(_dohRawQuery(host, qtype), STATE.lookupTimeoutMs, host);
|
|
1007
|
+
}
|
|
1008
|
+
if (transport === "dot") {
|
|
1009
|
+
if (!STATE.dot) {
|
|
1010
|
+
throw new DnsError("dns/transport-unavailable",
|
|
1011
|
+
"raw query requested DoT transport but useDnsOverTls() not configured");
|
|
1012
|
+
}
|
|
1013
|
+
return _withTimeout(_dotRawQuery(host, qtype), STATE.lookupTimeoutMs, host);
|
|
1014
|
+
}
|
|
1015
|
+
if (transport === "system") {
|
|
1016
|
+
return _withTimeout(_systemRawQuery(host, qtype), STATE.lookupTimeoutMs, host);
|
|
1017
|
+
}
|
|
1018
|
+
throw new DnsError("dns/bad-transport",
|
|
1019
|
+
"raw query: unknown transport '" + transport + "' (expected 'doh' | 'dot' | 'system')");
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
// ---- SVCB / HTTPS RR (RFC 9460) --------------------------------------
|
|
1023
|
+
|
|
1024
|
+
var DNS_QTYPE_SVCB = 64; // allow:raw-byte-literal — RFC 9460 §14.1 SVCB record type code
|
|
1025
|
+
var DNS_QTYPE_HTTPS = 65; // allow:raw-byte-literal — RFC 9460 §14.1 HTTPS record type code
|
|
1026
|
+
|
|
1027
|
+
// SvcParamKey assignments (RFC 9460 §14.3.2 + IANA registry). Keys
|
|
1028
|
+
// past 7 are operator-extensible; we recognize the IETF-blessed set
|
|
1029
|
+
// and surface the rest as opaque buffers under params.unknown[<key>].
|
|
1030
|
+
var SVCB_KEY_MANDATORY = 0;
|
|
1031
|
+
var SVCB_KEY_ALPN = 1;
|
|
1032
|
+
var SVCB_KEY_NO_DEF_ALPN = 2;
|
|
1033
|
+
var SVCB_KEY_PORT = 3;
|
|
1034
|
+
var SVCB_KEY_IPV4HINT = 4;
|
|
1035
|
+
var SVCB_KEY_ECH = 5;
|
|
1036
|
+
var SVCB_KEY_IPV6HINT = 6;
|
|
1037
|
+
var SVCB_KEY_DOHPATH = 7; // allow:raw-byte-literal — RFC 9461 SvcParamKey
|
|
1038
|
+
|
|
1039
|
+
function _readCharString(buf, off, end) {
|
|
1040
|
+
if (off >= end) {
|
|
1041
|
+
throw new DnsError("dns/svcb-malformed", "alpn list truncated at char-string length");
|
|
1042
|
+
}
|
|
1043
|
+
var len = buf[off];
|
|
1044
|
+
if (off + 1 + len > end) {
|
|
1045
|
+
throw new DnsError("dns/svcb-malformed", "alpn char-string overflows alpn value");
|
|
1046
|
+
}
|
|
1047
|
+
return { value: buf.toString("utf8", off + 1, off + 1 + len), nextOff: off + 1 + len };
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
function _parseSvcbRdata(msg, rdataOff, rdlen) {
|
|
1051
|
+
var end = rdataOff + rdlen;
|
|
1052
|
+
if (rdataOff + 2 > end) {
|
|
1053
|
+
throw new DnsError("dns/svcb-malformed", "SVCB rdata truncated before priority");
|
|
1054
|
+
}
|
|
1055
|
+
var priority = msg.readUInt16BE(rdataOff);
|
|
1056
|
+
var nameRes = _readDnsName(msg, rdataOff + 2);
|
|
1057
|
+
var target = nameRes.name === "" ? "." : nameRes.name;
|
|
1058
|
+
var off = nameRes.nextOff;
|
|
1059
|
+
var params = {};
|
|
1060
|
+
var prevKey = -1;
|
|
1061
|
+
while (off < end) {
|
|
1062
|
+
if (off + 4 > end) {
|
|
1063
|
+
throw new DnsError("dns/svcb-malformed", "SvcParam header truncated");
|
|
1064
|
+
}
|
|
1065
|
+
var key = msg.readUInt16BE(off); off += 2;
|
|
1066
|
+
var paramLen = msg.readUInt16BE(off); off += 2;
|
|
1067
|
+
if (off + paramLen > end) {
|
|
1068
|
+
throw new DnsError("dns/svcb-malformed", "SvcParam value overflows rdata");
|
|
1069
|
+
}
|
|
1070
|
+
if (key <= prevKey) {
|
|
1071
|
+
throw new DnsError("dns/svcb-malformed",
|
|
1072
|
+
"SvcParams not in ascending key order (key " + key + " after " + prevKey + ")");
|
|
1073
|
+
}
|
|
1074
|
+
prevKey = key;
|
|
1075
|
+
var paramEnd = off + paramLen;
|
|
1076
|
+
if (key === SVCB_KEY_MANDATORY) {
|
|
1077
|
+
if (paramLen % 2 !== 0) {
|
|
1078
|
+
throw new DnsError("dns/svcb-malformed", "mandatory SvcParam length not multiple of 2");
|
|
1079
|
+
}
|
|
1080
|
+
var mand = [];
|
|
1081
|
+
for (var mo = off; mo < paramEnd; mo += 2) {
|
|
1082
|
+
mand.push(msg.readUInt16BE(mo));
|
|
1083
|
+
}
|
|
1084
|
+
params.mandatory = mand;
|
|
1085
|
+
} else if (key === SVCB_KEY_ALPN) {
|
|
1086
|
+
var alpns = [];
|
|
1087
|
+
var ao = off;
|
|
1088
|
+
while (ao < paramEnd) {
|
|
1089
|
+
var cs = _readCharString(msg, ao, paramEnd);
|
|
1090
|
+
alpns.push(cs.value);
|
|
1091
|
+
ao = cs.nextOff;
|
|
1092
|
+
}
|
|
1093
|
+
params.alpn = alpns;
|
|
1094
|
+
} else if (key === SVCB_KEY_NO_DEF_ALPN) {
|
|
1095
|
+
if (paramLen !== 0) {
|
|
1096
|
+
throw new DnsError("dns/svcb-malformed", "no-default-alpn must have zero-length value");
|
|
1097
|
+
}
|
|
1098
|
+
params.noDefaultAlpn = true;
|
|
1099
|
+
} else if (key === SVCB_KEY_PORT) {
|
|
1100
|
+
if (paramLen !== 2) {
|
|
1101
|
+
throw new DnsError("dns/svcb-malformed", "port SvcParam must be 2 bytes");
|
|
1102
|
+
}
|
|
1103
|
+
params.port = msg.readUInt16BE(off);
|
|
1104
|
+
} else if (key === SVCB_KEY_IPV4HINT) {
|
|
1105
|
+
if (paramLen % 4 !== 0) {
|
|
1106
|
+
throw new DnsError("dns/svcb-malformed", "ipv4hint length not multiple of 4");
|
|
1107
|
+
}
|
|
1108
|
+
var v4 = [];
|
|
1109
|
+
for (var v4o = off; v4o < paramEnd; v4o += 4) {
|
|
1110
|
+
v4.push(msg[v4o] + "." + msg[v4o + 1] + "." + msg[v4o + 2] + "." + msg[v4o + 3]);
|
|
1111
|
+
}
|
|
1112
|
+
params.ipv4hint = v4;
|
|
1113
|
+
} else if (key === SVCB_KEY_ECH) {
|
|
1114
|
+
// ECHConfigList — opaque to the caller; surface as raw buffer.
|
|
1115
|
+
params.ech = Buffer.from(msg.slice(off, paramEnd));
|
|
1116
|
+
} else if (key === SVCB_KEY_IPV6HINT) {
|
|
1117
|
+
if (paramLen % IPV6_ADDR_BYTES !== 0) {
|
|
1118
|
+
throw new DnsError("dns/svcb-malformed", "ipv6hint length not multiple of 16");
|
|
1119
|
+
}
|
|
1120
|
+
var v6 = [];
|
|
1121
|
+
for (var v6o = off; v6o < paramEnd; v6o += IPV6_ADDR_BYTES) {
|
|
1122
|
+
var groups = [];
|
|
1123
|
+
for (var g = 0; g < IPV6_HEX_GROUPS; g++) {
|
|
1124
|
+
groups.push(msg.readUInt16BE(v6o + g * 2).toString(HEX_RADIX));
|
|
1125
|
+
}
|
|
1126
|
+
v6.push(groups.join(":"));
|
|
1127
|
+
}
|
|
1128
|
+
params.ipv6hint = v6;
|
|
1129
|
+
} else if (key === SVCB_KEY_DOHPATH) {
|
|
1130
|
+
params.dohpath = msg.toString("utf8", off, paramEnd);
|
|
1131
|
+
} else {
|
|
1132
|
+
// Unknown / future SvcParamKey — surface as opaque bytes so the
|
|
1133
|
+
// operator can still read it without us silently dropping the
|
|
1134
|
+
// record.
|
|
1135
|
+
if (!params.unknown) params.unknown = {};
|
|
1136
|
+
params.unknown[key] = Buffer.from(msg.slice(off, paramEnd));
|
|
1137
|
+
}
|
|
1138
|
+
off = paramEnd;
|
|
1139
|
+
}
|
|
1140
|
+
return { priority: priority, target: target, params: params };
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
function _validateLdh(host, primitive) {
|
|
1144
|
+
if (typeof host !== "string" || host.length === 0 || host.length > 253) { // allow:raw-byte-literal — RFC 1035 hostname octet ceiling
|
|
1145
|
+
throw new DnsError("dns/bad-host",
|
|
1146
|
+
primitive + ": host must be a non-empty RFC 1035 LDH name (length 1..253)");
|
|
1147
|
+
}
|
|
1148
|
+
// Allow leading underscore on labels (SVCB / HTTPS query targets like
|
|
1149
|
+
// "_dns.resolver.arpa" require it).
|
|
1150
|
+
var labels = host.split(".");
|
|
1151
|
+
for (var li = 0; li < labels.length; li += 1) {
|
|
1152
|
+
var label = labels[li];
|
|
1153
|
+
if (label.length === 0 || label.length > 63) { // allow:raw-byte-literal — RFC 1035 max label length
|
|
1154
|
+
throw new DnsError("dns/bad-host",
|
|
1155
|
+
primitive + ": host label length must be 1..63");
|
|
1156
|
+
}
|
|
1157
|
+
if (!/^[A-Za-z0-9_](?:[A-Za-z0-9_-]*[A-Za-z0-9_])?$/.test(label)) {
|
|
1158
|
+
throw new DnsError("dns/bad-host",
|
|
1159
|
+
primitive + ": host label '" + label + "' violates LDH (allowed: letters/digits/underscore/hyphen, no leading/trailing hyphen)");
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
async function _querySvcbLike(host, qtype, opts) {
|
|
1165
|
+
opts = opts || {};
|
|
1166
|
+
validateOpts(opts, ["transport"], "dns.querySvcb");
|
|
1167
|
+
_validateLdh(host, "dns.querySvcb");
|
|
1168
|
+
if (opts.transport !== undefined && opts.transport !== "doh" &&
|
|
1169
|
+
opts.transport !== "dot" && opts.transport !== "system") {
|
|
1170
|
+
throw new DnsError("dns/bad-transport",
|
|
1171
|
+
"dns.querySvcb: transport must be 'doh' | 'dot' | 'system' | undefined");
|
|
1172
|
+
}
|
|
1173
|
+
_emitObs("network.dns.svcb.requested", { qtype: qtype, transport: opts.transport || "auto" });
|
|
1174
|
+
var startMs = _now();
|
|
1175
|
+
var reply;
|
|
1176
|
+
try {
|
|
1177
|
+
reply = await _rawQuery(host, qtype, opts.transport);
|
|
1178
|
+
} catch (e) {
|
|
1179
|
+
_emitObs("network.dns.svcb.failure", {
|
|
1180
|
+
latencyMs: _now() - startMs,
|
|
1181
|
+
code: e.code || "unknown",
|
|
1182
|
+
});
|
|
1183
|
+
throw e;
|
|
1184
|
+
}
|
|
1185
|
+
var decoded = _decodeDnsAnswerRaw(reply);
|
|
1186
|
+
var records = [];
|
|
1187
|
+
for (var i = 0; i < decoded.answers.length; i++) {
|
|
1188
|
+
var ans = decoded.answers[i];
|
|
1189
|
+
if (ans.rtype !== qtype) continue;
|
|
1190
|
+
records.push(_parseSvcbRdata(decoded.msg, ans.rdataOff, ans.rdlen));
|
|
1191
|
+
}
|
|
1192
|
+
records.sort(function (a, b) { return a.priority - b.priority; });
|
|
1193
|
+
_emitObs("network.dns.svcb.success", {
|
|
1194
|
+
latencyMs: _now() - startMs,
|
|
1195
|
+
count: records.length,
|
|
1196
|
+
qtype: qtype,
|
|
1197
|
+
});
|
|
1198
|
+
return records;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
/**
|
|
1202
|
+
* @primitive b.network.dns.querySvcb
|
|
1203
|
+
* @signature b.network.dns.querySvcb(name, opts?)
|
|
1204
|
+
* @since 0.8.53
|
|
1205
|
+
* @status stable
|
|
1206
|
+
* @related b.network.dns.queryHttps, b.network.dns.discoverEncrypted
|
|
1207
|
+
*
|
|
1208
|
+
* Query SVCB records (RFC 9460 §2) for `name`. Returns an array of
|
|
1209
|
+
* `{ priority, target, params }` records sorted by priority. AliasMode
|
|
1210
|
+
* records (priority === 0) carry a `target` and empty `params` —
|
|
1211
|
+
* the caller chases the alias by re-querying the target. ServiceMode
|
|
1212
|
+
* records (priority > 0) carry SvcParams: `alpn` / `port` / `ipv4hint` /
|
|
1213
|
+
* `ipv6hint` / `ech` / `mandatory` / `dohpath`. Unknown SvcParamKeys
|
|
1214
|
+
* surface under `params.unknown[key]` as raw bytes — operators
|
|
1215
|
+
* implementing forward-compat can still read them. Malformed rdata
|
|
1216
|
+
* throws `DnsError` with code `dns/svcb-malformed`.
|
|
1217
|
+
*
|
|
1218
|
+
* @opts
|
|
1219
|
+
* {
|
|
1220
|
+
* transport: "doh" | "dot" | "system",
|
|
1221
|
+
* }
|
|
1222
|
+
*
|
|
1223
|
+
* @example
|
|
1224
|
+
* var b = require("@blamejs/core");
|
|
1225
|
+
* var rrs = await b.network.dns.querySvcb("_443._wss.example.com");
|
|
1226
|
+
*/
|
|
1227
|
+
async function querySvcb(name, opts) {
|
|
1228
|
+
return _querySvcbLike(name, DNS_QTYPE_SVCB, opts);
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
/**
|
|
1232
|
+
* @primitive b.network.dns.queryHttps
|
|
1233
|
+
* @signature b.network.dns.queryHttps(name, opts?)
|
|
1234
|
+
* @since 0.8.53
|
|
1235
|
+
* @status stable
|
|
1236
|
+
* @related b.network.dns.querySvcb
|
|
1237
|
+
*
|
|
1238
|
+
* Query HTTPS records (RFC 9460 §9). Identical to `querySvcb` except
|
|
1239
|
+
* the QTYPE is HTTPS (65) — the user-agent-facing variant of SVCB
|
|
1240
|
+
* for `https://` origins. Browsers query this for ECH discovery and
|
|
1241
|
+
* h3 advertisement; servers can call it to validate their own
|
|
1242
|
+
* published HTTPS RRset. Returns the same shape as `querySvcb`.
|
|
1243
|
+
*
|
|
1244
|
+
* @opts
|
|
1245
|
+
* {
|
|
1246
|
+
* transport: "doh" | "dot" | "system",
|
|
1247
|
+
* }
|
|
1248
|
+
*
|
|
1249
|
+
* @example
|
|
1250
|
+
* var b = require("@blamejs/core");
|
|
1251
|
+
* var rrs = await b.network.dns.queryHttps("example.com");
|
|
1252
|
+
*/
|
|
1253
|
+
async function queryHttps(name, opts) {
|
|
1254
|
+
return _querySvcbLike(name, DNS_QTYPE_HTTPS, opts);
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
// ---- DDR / DNR (RFC 9462 + RFC 9463) ---------------------------------
|
|
1258
|
+
|
|
1259
|
+
// Default DDR query target — RFC 9462 §3.
|
|
1260
|
+
var DDR_QUERY_NAME = "_dns.resolver.arpa";
|
|
1261
|
+
|
|
1262
|
+
// Operator-supplied designated resolver list. When set, the framework
|
|
1263
|
+
// prefers these over its own configured transport (subject to
|
|
1264
|
+
// `useDesignatedResolvers` having been called explicitly — never
|
|
1265
|
+
// silently overriding operator config).
|
|
1266
|
+
var _designatedResolvers = null;
|
|
1267
|
+
|
|
1268
|
+
/**
|
|
1269
|
+
* @primitive b.network.dns.discoverEncrypted
|
|
1270
|
+
* @signature b.network.dns.discoverEncrypted(opts?)
|
|
1271
|
+
* @since 0.8.53
|
|
1272
|
+
* @status stable
|
|
1273
|
+
* @related b.network.dns.useDesignatedResolvers, b.network.dns.querySvcb
|
|
1274
|
+
*
|
|
1275
|
+
* RFC 9462 Discovery of Designated Resolvers. Queries
|
|
1276
|
+
* `_dns.resolver.arpa` for SVCB records that advertise encrypted DNS
|
|
1277
|
+
* alternatives (DoH / DoT) hosted by the network's currently-configured
|
|
1278
|
+
* Do53 resolver. Returns a list of resolver descriptors with
|
|
1279
|
+
* `{ transport, alpn, target, port, dohpath, ipv4hint, ipv6hint, priority }`.
|
|
1280
|
+
*
|
|
1281
|
+
* The discovery query goes through the system resolver by default
|
|
1282
|
+
* (RFC 9462 §4 — DDR validation requires the response to come from
|
|
1283
|
+
* the Do53 resolver whose IP we compare). Callers that already have
|
|
1284
|
+
* a trusted DoH / DoT transport configured can pass
|
|
1285
|
+
* `{ insecureSystemResolverOnly: false }` to allow DDR via the
|
|
1286
|
+
* encrypted transport too.
|
|
1287
|
+
*
|
|
1288
|
+
* Throws `DnsError` with code `dns/ddr-not-discovered` when the
|
|
1289
|
+
* resolver does not publish DDR records.
|
|
1290
|
+
*
|
|
1291
|
+
* @opts
|
|
1292
|
+
* {
|
|
1293
|
+
* name: string,
|
|
1294
|
+
* insecureSystemResolverOnly: boolean,
|
|
1295
|
+
* }
|
|
1296
|
+
*
|
|
1297
|
+
* @example
|
|
1298
|
+
* var b = require("@blamejs/core");
|
|
1299
|
+
* var resolvers = await b.network.dns.discoverEncrypted();
|
|
1300
|
+
*/
|
|
1301
|
+
async function discoverEncrypted(opts) {
|
|
1302
|
+
opts = opts || {};
|
|
1303
|
+
validateOpts(opts, ["name", "insecureSystemResolverOnly"], "dns.discoverEncrypted");
|
|
1304
|
+
var name = opts.name || DDR_QUERY_NAME;
|
|
1305
|
+
if (typeof name !== "string" || name.length === 0) {
|
|
1306
|
+
throw new DnsError("dns/bad-host",
|
|
1307
|
+
"dns.discoverEncrypted: name must be a non-empty string");
|
|
1308
|
+
}
|
|
1309
|
+
var insecureOnly = opts.insecureSystemResolverOnly !== false;
|
|
1310
|
+
var transport = insecureOnly ? "system" : undefined;
|
|
1311
|
+
_validateLdh(name, "dns.discoverEncrypted");
|
|
1312
|
+
var startMs = _now();
|
|
1313
|
+
var records;
|
|
1314
|
+
try {
|
|
1315
|
+
records = await _querySvcbLike(name, DNS_QTYPE_SVCB, { transport: transport });
|
|
1316
|
+
} catch (e) {
|
|
1317
|
+
_emitObs("network.dns.ddr.failure", {
|
|
1318
|
+
latencyMs: _now() - startMs,
|
|
1319
|
+
code: e.code || "unknown",
|
|
1320
|
+
});
|
|
1321
|
+
if (e.code === "dns/no-result") {
|
|
1322
|
+
throw new DnsError("dns/ddr-not-discovered",
|
|
1323
|
+
"dns.discoverEncrypted: resolver did not publish DDR records at " + name);
|
|
1324
|
+
}
|
|
1325
|
+
throw e;
|
|
1326
|
+
}
|
|
1327
|
+
if (records.length === 0) {
|
|
1328
|
+
_emitObs("network.dns.ddr.empty", { latencyMs: _now() - startMs });
|
|
1329
|
+
throw new DnsError("dns/ddr-not-discovered",
|
|
1330
|
+
"dns.discoverEncrypted: resolver returned empty DDR record set at " + name);
|
|
1331
|
+
}
|
|
1332
|
+
var resolvers = [];
|
|
1333
|
+
for (var i = 0; i < records.length; i++) {
|
|
1334
|
+
var rec = records[i];
|
|
1335
|
+
if (rec.priority === 0) continue; // AliasMode — caller chases
|
|
1336
|
+
var alpn = (rec.params && rec.params.alpn) || [];
|
|
1337
|
+
var isDot = alpn.indexOf("dot") !== -1;
|
|
1338
|
+
var isDoh = alpn.indexOf("h2") !== -1 || alpn.indexOf("h3") !== -1 ||
|
|
1339
|
+
(rec.params && typeof rec.params.dohpath === "string");
|
|
1340
|
+
var transportKind = isDot ? "dot" : (isDoh ? "doh" : null);
|
|
1341
|
+
if (!transportKind) continue;
|
|
1342
|
+
resolvers.push({
|
|
1343
|
+
transport: transportKind,
|
|
1344
|
+
alpn: alpn,
|
|
1345
|
+
target: rec.target,
|
|
1346
|
+
port: (rec.params && rec.params.port) ||
|
|
1347
|
+
(transportKind === "dot" ? 853 : 443), // allow:raw-byte-literal — IANA-assigned DoT/HTTPS ports
|
|
1348
|
+
dohpath: (rec.params && rec.params.dohpath) || null,
|
|
1349
|
+
ipv4hint: (rec.params && rec.params.ipv4hint) || [],
|
|
1350
|
+
ipv6hint: (rec.params && rec.params.ipv6hint) || [],
|
|
1351
|
+
priority: rec.priority,
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
resolvers.sort(function (a, b) { return a.priority - b.priority; });
|
|
1355
|
+
if (resolvers.length === 0) {
|
|
1356
|
+
throw new DnsError("dns/ddr-not-discovered",
|
|
1357
|
+
"dns.discoverEncrypted: DDR records present but none advertised a recognized transport (alpn=dot/h2/h3)");
|
|
1358
|
+
}
|
|
1359
|
+
_emitObs("network.dns.ddr.success", {
|
|
1360
|
+
latencyMs: _now() - startMs,
|
|
1361
|
+
count: resolvers.length,
|
|
1362
|
+
});
|
|
1363
|
+
return resolvers;
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
/**
|
|
1367
|
+
* @primitive b.network.dns.useDesignatedResolvers
|
|
1368
|
+
* @signature b.network.dns.useDesignatedResolvers(list)
|
|
1369
|
+
* @since 0.8.53
|
|
1370
|
+
* @status stable
|
|
1371
|
+
* @related b.network.dns.discoverEncrypted, b.network.dns.querySvcb
|
|
1372
|
+
*
|
|
1373
|
+
* RFC 9463 Discovery of Network-designated Resolvers. The framework
|
|
1374
|
+
* doesn't run a DHCP / IPv6 RA client itself; an operator-side agent
|
|
1375
|
+
* (or the output of `discoverEncrypted()`) supplies the resolver list
|
|
1376
|
+
* and the framework swaps its transport over to the lowest-priority
|
|
1377
|
+
* entry. Items are tried in order: the first one that successfully
|
|
1378
|
+
* configures (DoH `useDnsOverHttps`, DoT `useDnsOverTls`) wins.
|
|
1379
|
+
*
|
|
1380
|
+
* Each entry shape:
|
|
1381
|
+
*
|
|
1382
|
+
* {
|
|
1383
|
+
* transport: "doh" | "dot",
|
|
1384
|
+
* url: string,
|
|
1385
|
+
* host: string,
|
|
1386
|
+
* port: number,
|
|
1387
|
+
* servername: string,
|
|
1388
|
+
* alpn: Array<string>,
|
|
1389
|
+
* ca: string|Buffer|Array,
|
|
1390
|
+
* }
|
|
1391
|
+
*
|
|
1392
|
+
* Throws `DnsError` with code `dns/dnr-no-resolvers` if `list` is
|
|
1393
|
+
* empty, and `dns/dnr-malformed` if an entry is missing its required
|
|
1394
|
+
* transport-specific fields.
|
|
1395
|
+
*
|
|
1396
|
+
* @example
|
|
1397
|
+
* var b = require("@blamejs/core");
|
|
1398
|
+
* var found = await b.network.dns.discoverEncrypted();
|
|
1399
|
+
* b.network.dns.useDesignatedResolvers(found.map(function (r) {
|
|
1400
|
+
* return r.transport === "doh"
|
|
1401
|
+
* ? { transport: "doh", url: "https://" + r.target + (r.dohpath || "/dns-query") }
|
|
1402
|
+
* : { transport: "dot", host: r.target, port: r.port, servername: r.target };
|
|
1403
|
+
* }));
|
|
1404
|
+
*/
|
|
1405
|
+
function useDesignatedResolvers(list) {
|
|
1406
|
+
if (!Array.isArray(list) || list.length === 0) {
|
|
1407
|
+
throw new DnsError("dns/dnr-no-resolvers",
|
|
1408
|
+
"dns.useDesignatedResolvers: expected non-empty array of resolver descriptors");
|
|
1409
|
+
}
|
|
1410
|
+
var validated = [];
|
|
1411
|
+
for (var i = 0; i < list.length; i++) {
|
|
1412
|
+
var entry = list[i];
|
|
1413
|
+
if (!entry || typeof entry !== "object") {
|
|
1414
|
+
throw new DnsError("dns/dnr-malformed",
|
|
1415
|
+
"dns.useDesignatedResolvers[" + i + "]: entry must be an object");
|
|
1416
|
+
}
|
|
1417
|
+
if (entry.transport !== "doh" && entry.transport !== "dot") {
|
|
1418
|
+
throw new DnsError("dns/dnr-malformed",
|
|
1419
|
+
"dns.useDesignatedResolvers[" + i + "]: transport must be 'doh' or 'dot'");
|
|
1420
|
+
}
|
|
1421
|
+
if (entry.transport === "doh") {
|
|
1422
|
+
if (typeof entry.url !== "string" || entry.url.indexOf("https://") !== 0) {
|
|
1423
|
+
throw new DnsError("dns/dnr-malformed",
|
|
1424
|
+
"dns.useDesignatedResolvers[" + i + "]: doh entry requires url starting with https://");
|
|
1425
|
+
}
|
|
1426
|
+
} else {
|
|
1427
|
+
if (typeof entry.host !== "string" || entry.host.length === 0) {
|
|
1428
|
+
throw new DnsError("dns/dnr-malformed",
|
|
1429
|
+
"dns.useDesignatedResolvers[" + i + "]: dot entry requires host");
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
validated.push(entry);
|
|
1433
|
+
}
|
|
1434
|
+
var lastErr = null;
|
|
1435
|
+
for (var j = 0; j < validated.length; j++) {
|
|
1436
|
+
var v = validated[j];
|
|
1437
|
+
try {
|
|
1438
|
+
if (v.transport === "doh") {
|
|
1439
|
+
useDnsOverHttps({ url: v.url, ca: v.ca || null, method: v.method });
|
|
1440
|
+
} else {
|
|
1441
|
+
useDnsOverTls({
|
|
1442
|
+
host: v.host,
|
|
1443
|
+
port: v.port || 853, // allow:raw-byte-literal — IANA-assigned DoT port
|
|
1444
|
+
servername: v.servername || v.host,
|
|
1445
|
+
ca: v.ca || null,
|
|
1446
|
+
});
|
|
1447
|
+
}
|
|
1448
|
+
_designatedResolvers = validated.slice();
|
|
1449
|
+
_emitObs("network.dns.dnr.set", {
|
|
1450
|
+
count: validated.length,
|
|
1451
|
+
active: j,
|
|
1452
|
+
transport: v.transport,
|
|
1453
|
+
});
|
|
1454
|
+
return { active: j, count: validated.length };
|
|
1455
|
+
} catch (e) {
|
|
1456
|
+
lastErr = e;
|
|
1457
|
+
_emitObs("network.dns.dnr.entry_failed", {
|
|
1458
|
+
index: j,
|
|
1459
|
+
transport: v.transport,
|
|
1460
|
+
code: e.code || "unknown",
|
|
1461
|
+
});
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
throw new DnsError("dns/dnr-no-resolvers",
|
|
1465
|
+
"dns.useDesignatedResolvers: no entry could be configured. Last error: " +
|
|
1466
|
+
((lastErr && lastErr.message) || "unknown"));
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
function _designatedResolversForTest() { return _designatedResolvers; }
|
|
1470
|
+
|
|
1471
|
+
function _orderAddrs(addrs) {
|
|
1472
|
+
if (STATE.resultOrder === "ipv6first") {
|
|
1473
|
+
addrs.sort(function (a, b) { return (b.family || 0) - (a.family || 0); });
|
|
1474
|
+
} else if (STATE.resultOrder === "ipv4first") {
|
|
1475
|
+
addrs.sort(function (a, b) { return (a.family || 0) - (b.family || 0); });
|
|
1476
|
+
}
|
|
1477
|
+
return addrs;
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
async function _dualStack(queryFn, host, family) {
|
|
1481
|
+
if (family === 4 || family === 6) {
|
|
1482
|
+
return _withTimeout(queryFn(host, family), STATE.lookupTimeoutMs, host);
|
|
1483
|
+
}
|
|
1484
|
+
var first = STATE.resultOrder === "ipv6first" ? 6 : 4;
|
|
1485
|
+
var second = first === 4 ? 6 : 4;
|
|
1486
|
+
var firstResult = await _withTimeout(queryFn(host, first), STATE.lookupTimeoutMs, host).catch(function () { return []; });
|
|
1487
|
+
var secondResult = await _withTimeout(queryFn(host, second), STATE.lookupTimeoutMs, host).catch(function () { return []; });
|
|
1488
|
+
return (firstResult || []).concat(secondResult || []);
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
async function lookup(host, opts) {
|
|
1492
|
+
opts = opts || {};
|
|
1493
|
+
validateOpts(opts, ["family", "all"], "dns.lookup");
|
|
1494
|
+
var family = opts.family !== undefined ? opts.family : STATE.family;
|
|
1495
|
+
if (net.isIP(host)) {
|
|
1496
|
+
var fam = net.isIP(host);
|
|
1497
|
+
var literal = { address: host, family: fam };
|
|
1498
|
+
return opts.all ? [literal] : literal;
|
|
1499
|
+
}
|
|
1500
|
+
var cacheKey = family || 0;
|
|
1501
|
+
var cached = _cacheGet(host, cacheKey);
|
|
1502
|
+
if (cached.hit) {
|
|
1503
|
+
if (cached.error) throw cached.error;
|
|
1504
|
+
return opts.all ? cached.value : cached.value[0];
|
|
1505
|
+
}
|
|
1506
|
+
_emitObs("network.dns.lookup.requested", { family: cacheKey });
|
|
1507
|
+
var startMs = _now();
|
|
1508
|
+
// Resolve secure-DNS default on first use. Idempotent.
|
|
1509
|
+
_ensureSecureDefault();
|
|
1510
|
+
|
|
1511
|
+
// Special-form hostnames per RFC 6761 (localhost / .test / .invalid /
|
|
1512
|
+
// .localhost) and operator-internal suffixes never hit DoH/DoT —
|
|
1513
|
+
// public DoH providers don't resolve these. Route through node:dns
|
|
1514
|
+
// (which checks /etc/hosts and the OS resolver). This keeps tests +
|
|
1515
|
+
// dev workflows working while public-internet resolution still goes
|
|
1516
|
+
// through the secure transport.
|
|
1517
|
+
var isLocalForm = _isLocalFormHost(host);
|
|
1518
|
+
|
|
1519
|
+
try {
|
|
1520
|
+
var addrs;
|
|
1521
|
+
if (STATE.doh && !isLocalForm) {
|
|
1522
|
+
addrs = await _dualStack(_dohLookup, host, family);
|
|
1523
|
+
} else if (STATE.dot && !isLocalForm) {
|
|
1524
|
+
addrs = await _dualStack(_dotLookup, host, family);
|
|
1525
|
+
} else {
|
|
1526
|
+
// System resolver (operator explicit opt-out via useSystemResolver).
|
|
1527
|
+
var nodeOpts = { all: true };
|
|
1528
|
+
if (family === 4 || family === 6) nodeOpts.family = family; // allow:raw-byte-literal — IPv4/IPv6 family literals
|
|
1529
|
+
addrs = await _withTimeout(dnsPromises.lookup(host, nodeOpts), STATE.lookupTimeoutMs, host);
|
|
1530
|
+
if (!Array.isArray(addrs)) addrs = [addrs];
|
|
1531
|
+
}
|
|
1532
|
+
var normalized = (addrs || []).map(function (a) {
|
|
1533
|
+
if (typeof a === "string") return { address: a, family: net.isIP(a) || 4 };
|
|
1534
|
+
return { address: a.address || a, family: a.family || net.isIP(a.address || a) || 4 };
|
|
1535
|
+
});
|
|
1536
|
+
_orderAddrs(normalized);
|
|
1537
|
+
if (normalized.length === 0) {
|
|
1538
|
+
throw new DnsError("dns/no-result", "dns lookup of '" + host + "' returned no addresses");
|
|
1539
|
+
}
|
|
1540
|
+
_cachePutPositive(host, cacheKey, normalized);
|
|
1541
|
+
_emitObs("network.dns.lookup.success", { latencyMs: _now() - startMs, count: normalized.length });
|
|
1542
|
+
return opts.all ? normalized : normalized[0];
|
|
1543
|
+
} catch (e) {
|
|
1544
|
+
_cachePutNegative(host, cacheKey, e);
|
|
1545
|
+
_emitObs("network.dns.lookup.failure", { latencyMs: _now() - startMs, code: e.code || "unknown" });
|
|
1546
|
+
throw e;
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
async function _resolveProtocol(host, family, opts) {
|
|
1551
|
+
opts = opts || {};
|
|
1552
|
+
if (typeof host !== "string" || host.length === 0) {
|
|
1553
|
+
throw new DnsError("dns/bad-host", "dns.resolve" + family + ": host required");
|
|
1554
|
+
}
|
|
1555
|
+
if (net.isIP(host)) {
|
|
1556
|
+
if (net.isIP(host) !== family) {
|
|
1557
|
+
throw new DnsError("dns/wrong-family", "dns.resolve" + family + ": IP literal '" + host + "' is not family " + family);
|
|
1558
|
+
}
|
|
1559
|
+
return [host];
|
|
1560
|
+
}
|
|
1561
|
+
if (opts.transport !== undefined && opts.transport !== "doh" &&
|
|
1562
|
+
opts.transport !== "dot" && opts.transport !== "system") {
|
|
1563
|
+
throw new DnsError("dns/bad-transport",
|
|
1564
|
+
"dns.resolve" + family + ": transport must be 'doh' | 'dot' | 'system' | undefined");
|
|
1565
|
+
}
|
|
1566
|
+
_emitObs("network.dns.resolve.requested", { family: family, transport: opts.transport || "auto" });
|
|
1567
|
+
var startMs = _now();
|
|
1568
|
+
try {
|
|
1569
|
+
var addrs;
|
|
1570
|
+
var forced = opts.transport;
|
|
1571
|
+
if (forced === "doh" || (!forced && STATE.doh)) {
|
|
1572
|
+
if (!STATE.doh) {
|
|
1573
|
+
throw new DnsError("dns/transport-unavailable",
|
|
1574
|
+
"dns.resolve" + family + ": transport 'doh' requested but useDnsOverHttps() not configured");
|
|
1575
|
+
}
|
|
1576
|
+
addrs = await _withTimeout(_dohLookup(host, family), STATE.lookupTimeoutMs, host);
|
|
1577
|
+
} else if (forced === "dot" || (!forced && STATE.dot)) {
|
|
1578
|
+
if (!STATE.dot) {
|
|
1579
|
+
throw new DnsError("dns/transport-unavailable",
|
|
1580
|
+
"dns.resolve" + family + ": transport 'dot' requested but useDnsOverTls() not configured");
|
|
1581
|
+
}
|
|
1582
|
+
addrs = await _withTimeout(_dotLookup(host, family), STATE.lookupTimeoutMs, host);
|
|
1583
|
+
} else {
|
|
1584
|
+
var resolver = family === 6 ? dnsPromises.resolve6 : dnsPromises.resolve4;
|
|
1585
|
+
addrs = await _withTimeout(resolver(host), STATE.lookupTimeoutMs, host);
|
|
1586
|
+
}
|
|
1587
|
+
if (!Array.isArray(addrs)) addrs = [addrs];
|
|
1588
|
+
var normalized = addrs.map(function (a) { return typeof a === "string" ? a : (a.address || a); });
|
|
1589
|
+
if (normalized.length === 0) {
|
|
1590
|
+
throw new DnsError("dns/no-result", "dns.resolve" + family + " of '" + host + "' returned no addresses");
|
|
1591
|
+
}
|
|
1592
|
+
_emitObs("network.dns.resolve.success", { family: family, latencyMs: _now() - startMs, count: normalized.length });
|
|
1593
|
+
return normalized;
|
|
1594
|
+
} catch (e) {
|
|
1595
|
+
_emitObs("network.dns.resolve.failure", { family: family, latencyMs: _now() - startMs, code: e.code || "unknown" });
|
|
1596
|
+
if (e instanceof DnsError) throw e;
|
|
1597
|
+
throw new DnsError("dns/resolve-failed",
|
|
1598
|
+
"dns.resolve" + family + " of '" + host + "' failed: " + (e.message || String(e)));
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
async function resolve4(host, opts) { return _resolveProtocol(host, 4, opts); }
|
|
1603
|
+
async function resolve6(host, opts) { return _resolveProtocol(host, 6, opts); }
|
|
1604
|
+
async function resolveAaaa(host, opts) { return _resolveProtocol(host, 6, opts); }
|
|
1605
|
+
|
|
1606
|
+
// Generic resolve API surfacing the transport opt + record type.
|
|
1607
|
+
// `type` defaults to "A"; "AAAA" routes through resolve6; SVCB / HTTPS
|
|
1608
|
+
// types route through the new querySvcb / queryHttps primitives.
|
|
1609
|
+
async function resolve(host, type, opts) {
|
|
1610
|
+
type = (type || "A").toUpperCase();
|
|
1611
|
+
if (type === "A") return _resolveProtocol(host, 4, opts);
|
|
1612
|
+
if (type === "AAAA") return _resolveProtocol(host, 6, opts);
|
|
1613
|
+
if (type === "SVCB") return querySvcb(host, opts);
|
|
1614
|
+
if (type === "HTTPS") return queryHttps(host, opts);
|
|
1615
|
+
throw new DnsError("dns/unsupported-type",
|
|
1616
|
+
"dns.resolve: type must be 'A' | 'AAAA' | 'SVCB' | 'HTTPS' (got " + JSON.stringify(type) + ")");
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
// PTR lookup — given a v4 or v6 IP literal, return the list of names
|
|
1620
|
+
// the in-addr.arpa / ip6.arpa zones map back to. Building block for
|
|
1621
|
+
// FCrDNS (forward-confirmed reverse DNS, RFC 8601 §3 lite) callers
|
|
1622
|
+
// and the outbound-mail iprev surface — the PTR query plus the
|
|
1623
|
+
// matching forward A/AAAA query share this DnsError class.
|
|
1624
|
+
//
|
|
1625
|
+
// dnsPromises.reverse() doesn't honor the DoH/DoT transports (those
|
|
1626
|
+
// transports query A/AAAA/TXT via wire format; PTR queries take a
|
|
1627
|
+
// separate code path). For now this routes through the system
|
|
1628
|
+
// resolver — operators who require ALL DNS over secure transport
|
|
1629
|
+
// wrap the surface with their own resolver.
|
|
1630
|
+
async function reverse(ip) {
|
|
1631
|
+
if (typeof ip !== "string" || ip.length === 0) {
|
|
1632
|
+
throw new DnsError("dns/bad-ip", "dns.reverse: ip must be a non-empty string");
|
|
1633
|
+
}
|
|
1634
|
+
if (!net.isIP(ip)) {
|
|
1635
|
+
throw new DnsError("dns/bad-ip",
|
|
1636
|
+
"dns.reverse: '" + ip + "' is not a valid IPv4 or IPv6 address");
|
|
1637
|
+
}
|
|
1638
|
+
_emitObs("network.dns.reverse.requested", { family: net.isIPv6(ip) ? 6 : 4 });
|
|
1639
|
+
var startMs = _now();
|
|
1640
|
+
try {
|
|
1641
|
+
var ptrs = await _withTimeout(dnsPromises.reverse(ip), STATE.lookupTimeoutMs, ip);
|
|
1642
|
+
_emitObs("network.dns.reverse.success", {
|
|
1643
|
+
latencyMs: _now() - startMs, count: Array.isArray(ptrs) ? ptrs.length : 0,
|
|
1644
|
+
});
|
|
1645
|
+
return Array.isArray(ptrs) ? ptrs : [];
|
|
1646
|
+
} catch (e) {
|
|
1647
|
+
_emitObs("network.dns.reverse.failure", {
|
|
1648
|
+
latencyMs: _now() - startMs, code: e.code || "unknown",
|
|
1649
|
+
});
|
|
1650
|
+
if (e instanceof DnsError) throw e;
|
|
1651
|
+
throw new DnsError("dns/reverse-failed",
|
|
1652
|
+
"dns.reverse of '" + ip + "' failed: " + (e.message || String(e)));
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
function nodeLookup(host, options, callback) {
|
|
1657
|
+
if (typeof options === "function") { callback = options; options = {}; }
|
|
1658
|
+
options = options || {};
|
|
1659
|
+
var fam = options.family !== undefined ? options.family : 0;
|
|
1660
|
+
lookup(host, { family: fam, all: !!options.all }).then(
|
|
1661
|
+
function (res) {
|
|
1662
|
+
if (options.all) callback(null, res);
|
|
1663
|
+
else callback(null, res.address, res.family);
|
|
1664
|
+
},
|
|
1665
|
+
function (err) { callback(err); }
|
|
1666
|
+
);
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
function _emitObs(name, fields) {
|
|
1670
|
+
try { observability().emit(name, fields || {}); } catch (_e) { /* obs best-effort */ }
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
function _stateForTest() { return STATE; }
|
|
1674
|
+
function _resetForTest() {
|
|
1675
|
+
STATE.servers = null; STATE.resultOrder = null; STATE.family = 0;
|
|
1676
|
+
STATE.lookupTimeoutMs = 0; STATE.cacheTtlMs = 0; STATE.cacheNegativeTtlMs = 0;
|
|
1677
|
+
STATE.doh = null; STATE.dot = null; STATE.systemResolver = false;
|
|
1678
|
+
_designatedResolvers = null;
|
|
1679
|
+
_clearCache();
|
|
1680
|
+
_resetDotPool();
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
/**
|
|
1684
|
+
* @primitive b.network.dns.isNullMx
|
|
1685
|
+
* @signature b.network.dns.isNullMx(mxRecords)
|
|
1686
|
+
* @since 0.8.87
|
|
1687
|
+
* @status stable
|
|
1688
|
+
*
|
|
1689
|
+
* RFC 7505 Null-MX check — returns `true` when the supplied MX
|
|
1690
|
+
* records signal "this domain does not accept email" (a single MX
|
|
1691
|
+
* record with priority 0 and exchange `.`). Operators sending mail
|
|
1692
|
+
* call this before delivery to skip domains that have explicitly
|
|
1693
|
+
* opted out of email. Returns `false` for any other shape (zero
|
|
1694
|
+
* records, multiple records, non-zero priority, non-`.` exchange).
|
|
1695
|
+
*
|
|
1696
|
+
* MX records are expected in the `{ priority, exchange }` shape
|
|
1697
|
+
* returned by `node:dns.resolveMx` (or `b.network.dns.resolve(host,
|
|
1698
|
+
* "MX")`). Operator supplies the records; this is a pure
|
|
1699
|
+
* classifier, no network call.
|
|
1700
|
+
*
|
|
1701
|
+
* @example
|
|
1702
|
+
* var node = require("node:dns/promises");
|
|
1703
|
+
* var mx;
|
|
1704
|
+
* try { mx = await node.resolveMx("example.com"); }
|
|
1705
|
+
* catch (e) { mx = []; }
|
|
1706
|
+
* if (b.network.dns.isNullMx(mx)) {
|
|
1707
|
+
* throw new Error("example.com publishes Null-MX (RFC 7505) — does not accept email");
|
|
1708
|
+
* }
|
|
1709
|
+
*/
|
|
1710
|
+
function isNullMx(mxRecords) {
|
|
1711
|
+
if (!Array.isArray(mxRecords) || mxRecords.length !== 1) return false;
|
|
1712
|
+
var only = mxRecords[0];
|
|
1713
|
+
if (!only || typeof only !== "object") return false;
|
|
1714
|
+
if (only.priority !== 0) return false;
|
|
1715
|
+
// node's resolveMx returns the exchange as "" (empty) when the
|
|
1716
|
+
// RDATA is "." (root); other resolvers may keep "." literal. Accept
|
|
1717
|
+
// both.
|
|
1718
|
+
return only.exchange === "" || only.exchange === ".";
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
// RFC 9905 — Deprecating DNSSEC SHA-1 Usage. The IANA DNSSEC Algorithm
|
|
1722
|
+
// Numbers registry classifies SHA-1-based DNSKEY algorithms (5
|
|
1723
|
+
// RSASHA1, 7 RSASHA1-NSEC3-SHA1, 10 RSASHA512-using-SHA1-NSEC3) and
|
|
1724
|
+
// SHA-1 DS digest type 1 as "MUST NOT be used" / "MUST NOT be
|
|
1725
|
+
// supported". Operators auditing inbound DNSSEC chain-of-trust data
|
|
1726
|
+
// classify a record's algorithm number to decide whether to refuse
|
|
1727
|
+
// the validation as deprecated.
|
|
1728
|
+
//
|
|
1729
|
+
// Returns the classification verdict object:
|
|
1730
|
+
// {
|
|
1731
|
+
// deprecated: boolean, // true when SHA-1 family per RFC 9905 §3-§4
|
|
1732
|
+
// algorithm: number, // echo of input
|
|
1733
|
+
// name: string, // human-readable label
|
|
1734
|
+
// reason: string, // citation
|
|
1735
|
+
// }
|
|
1736
|
+
// for any IANA DNSKEY algorithm number, or null for unknown / non-
|
|
1737
|
+
// numeric input. Defensive request-shape reader — never throws.
|
|
1738
|
+
|
|
1739
|
+
/**
|
|
1740
|
+
* @primitive b.network.dns.classifyDnskeyAlgorithm
|
|
1741
|
+
* @signature b.network.dns.classifyDnskeyAlgorithm(algorithm)
|
|
1742
|
+
* @since 0.8.91
|
|
1743
|
+
* @status stable
|
|
1744
|
+
* @related b.network.dns.classifyDsDigestType, b.network.dns.isNullMx
|
|
1745
|
+
*
|
|
1746
|
+
* Classify a DNSKEY / RRSIG algorithm number against the IANA DNS
|
|
1747
|
+
* Security Algorithm Numbers registry, flagging SHA-1-based and
|
|
1748
|
+
* other deprecated algorithms per RFC 9905 (Deprecating DNSSEC
|
|
1749
|
+
* SHA-1 Usage), RFC 8624 (Algorithm Implementation Requirements),
|
|
1750
|
+
* and RFC 6944 / RFC 6725 (RSAMD5 deprecation).
|
|
1751
|
+
*
|
|
1752
|
+
* Returns `{ algorithm, name, deprecated, reason, known }` for any
|
|
1753
|
+
* IANA-assigned number; `known: false` for unassigned numbers
|
|
1754
|
+
* (operators decide whether unassigned == deprecated for their
|
|
1755
|
+
* threat model). Returns `null` for non-integer / non-finite input.
|
|
1756
|
+
*
|
|
1757
|
+
* Operators auditing inbound DNSSEC chain-of-trust evidence call
|
|
1758
|
+
* this on each link's algorithm number and refuse the validation
|
|
1759
|
+
* when `deprecated === true`. Defensive request-shape reader —
|
|
1760
|
+
* never throws.
|
|
1761
|
+
*
|
|
1762
|
+
* @example
|
|
1763
|
+
* var v = b.network.dns.classifyDnskeyAlgorithm(5);
|
|
1764
|
+
* // → { algorithm: 5, name: "RSASHA1", deprecated: true,
|
|
1765
|
+
* // reason: "SHA-1 deprecated (RFC 9905 §3)", known: true }
|
|
1766
|
+
* if (v && v.deprecated) throw new Error("refuse DNSSEC algo " + v.name);
|
|
1767
|
+
*
|
|
1768
|
+
* b.network.dns.classifyDnskeyAlgorithm(13);
|
|
1769
|
+
* // → { algorithm: 13, name: "ECDSAP256SHA256", deprecated: false, ... }
|
|
1770
|
+
*/
|
|
1771
|
+
|
|
1772
|
+
// Canonical DNSKEY algorithm vocabulary (IANA DNS Security Algorithm
|
|
1773
|
+
// Numbers registry — https://www.iana.org/assignments/dns-sec-alg-numbers).
|
|
1774
|
+
// Operators looking up the human-readable label or computing whether
|
|
1775
|
+
// the framework's own DNSSEC paths use a deprecated algorithm walk
|
|
1776
|
+
// this table. Every IANA-assigned number gets an entry (including
|
|
1777
|
+
// Reserved / Private-use values) so `classifyDnskeyAlgorithm()`
|
|
1778
|
+
// returns `known: true` for the full assigned space; the "Unassigned"
|
|
1779
|
+
// range (17-122, 124-251) is the only set that surfaces as
|
|
1780
|
+
// `known: false`. Marked-deprecated entries cite the controlling
|
|
1781
|
+
// RFC; Reserved / Private-use entries are flagged so operators
|
|
1782
|
+
// auditing DNSSEC chain-of-trust evidence know they cannot validate
|
|
1783
|
+
// the entry against a public algorithm registry.
|
|
1784
|
+
var DNSKEY_ALGORITHMS = Object.freeze({
|
|
1785
|
+
1: { name: "RSAMD5", deprecated: true, reason: "MD5 broken (RFC 6944 §2.1, RFC 6725)" },
|
|
1786
|
+
2: { name: "DH", deprecated: true, reason: "Diffie-Hellman key (RFC 2539) — never widely deployed; superseded by signature algorithms" },
|
|
1787
|
+
3: { name: "DSA", deprecated: true, reason: "DSA deprecated (RFC 8624 §3.1)" },
|
|
1788
|
+
4: { name: "Reserved", deprecated: true, reason: "Reserved (RFC 4034 §A.1) — not for production use" },
|
|
1789
|
+
5: { name: "RSASHA1", deprecated: true, reason: "SHA-1 deprecated (RFC 9905 §3)" },
|
|
1790
|
+
6: { name: "DSA-NSEC3-SHA1", deprecated: true, reason: "SHA-1 deprecated (RFC 9905 §3); DSA deprecated (RFC 8624 §3.1)" },
|
|
1791
|
+
7: { name: "RSASHA1-NSEC3-SHA1", deprecated: true, reason: "SHA-1 deprecated (RFC 9905 §3)" },
|
|
1792
|
+
8: { name: "RSASHA256", deprecated: false, reason: "current — RFC 5702" }, // allow:raw-byte-literal — IANA DNSKEY algorithm number
|
|
1793
|
+
9: { name: "Reserved", deprecated: true, reason: "Reserved (RFC 5155) — not for production use" },
|
|
1794
|
+
10: { name: "RSASHA512", deprecated: false, reason: "current — RFC 5702" },
|
|
1795
|
+
11: { name: "Reserved", deprecated: true, reason: "Reserved (RFC 5155) — not for production use" },
|
|
1796
|
+
12: { name: "ECC-GOST", deprecated: true, reason: "deprecated (RFC 8624 §3.1)" },
|
|
1797
|
+
13: { name: "ECDSAP256SHA256", deprecated: false, reason: "current — RFC 6605" },
|
|
1798
|
+
14: { name: "ECDSAP384SHA384", deprecated: false, reason: "current — RFC 6605" },
|
|
1799
|
+
15: { name: "ED25519", deprecated: false, reason: "current — RFC 8080" },
|
|
1800
|
+
16: { name: "ED448", deprecated: false, reason: "current — RFC 8080" }, // allow:raw-byte-literal — IANA DNSKEY algorithm number
|
|
1801
|
+
// 17-122: Unassigned per IANA. Operators that see one of these
|
|
1802
|
+
// get known: false from classifyDnskeyAlgorithm() — the entry
|
|
1803
|
+
// is not a typo against the framework table, it's a value the
|
|
1804
|
+
// registry hasn't allocated yet.
|
|
1805
|
+
// 123-251: Reserved per IANA.
|
|
1806
|
+
252: { name: "INDIRECT", deprecated: true, reason: "Reserved indirect-keys placeholder (RFC 4034 §A.1) — not usable for signing/verification" }, // allow:raw-byte-literal — IANA DNSKEY algorithm number
|
|
1807
|
+
253: { name: "PRIVATEDNS", deprecated: false, reason: "Private algorithm identified by domain name (RFC 4034 §A.1.1) — operators using this assume the private algorithm itself is acceptable" },
|
|
1808
|
+
254: { name: "PRIVATEOID", deprecated: false, reason: "Private algorithm identified by OID (RFC 4034 §A.1.2) — operators using this assume the private algorithm itself is acceptable" },
|
|
1809
|
+
255: { name: "Reserved", deprecated: true, reason: "Reserved (RFC 4034 §A.1) — not for production use" },
|
|
1810
|
+
});
|
|
1811
|
+
|
|
1812
|
+
/**
|
|
1813
|
+
* @primitive b.network.dns.classifyDsDigestType
|
|
1814
|
+
* @signature b.network.dns.classifyDsDigestType(digestType)
|
|
1815
|
+
* @since 0.8.91
|
|
1816
|
+
* @status stable
|
|
1817
|
+
* @related b.network.dns.classifyDnskeyAlgorithm, b.network.dns.isNullMx
|
|
1818
|
+
*
|
|
1819
|
+
* Classify a DS-record digest type against the IANA DNSSEC Delegation
|
|
1820
|
+
* Signer (DS) Resource Record (RR) Type Digest Algorithms registry,
|
|
1821
|
+
* flagging SHA-1 (digest type 1) as deprecated per RFC 9905 §4.
|
|
1822
|
+
*
|
|
1823
|
+
* Returns `{ digestType, name, deprecated, reason, known }` for any
|
|
1824
|
+
* IANA-assigned number; `null` for non-integer input.
|
|
1825
|
+
*
|
|
1826
|
+
* @example
|
|
1827
|
+
* var v = b.network.dns.classifyDsDigestType(1);
|
|
1828
|
+
* // → { digestType: 1, name: "SHA-1", deprecated: true,
|
|
1829
|
+
* // reason: "SHA-1 deprecated (RFC 9905 §4)", known: true }
|
|
1830
|
+
*
|
|
1831
|
+
* b.network.dns.classifyDsDigestType(2);
|
|
1832
|
+
* // → { digestType: 2, name: "SHA-256", deprecated: false, ... }
|
|
1833
|
+
*/
|
|
1834
|
+
|
|
1835
|
+
// DS digest-type vocabulary (RFC 4034 §5.1 + RFC 6605 §6 + RFC 8624
|
|
1836
|
+
// §3.2 + RFC 9558). Digest type 1 = SHA-1 is deprecated per RFC 9905
|
|
1837
|
+
// §4. Digest types 5 (GOST R 34.11-2012) and 6 (SM3) added by RFC
|
|
1838
|
+
// 9558. Reserved value 0 surfaced for completeness.
|
|
1839
|
+
var DS_DIGEST_TYPES = Object.freeze({
|
|
1840
|
+
0: { name: "Reserved", deprecated: true, reason: "Reserved (RFC 3658) — not for production use" },
|
|
1841
|
+
1: { name: "SHA-1", deprecated: true, reason: "SHA-1 deprecated (RFC 9905 §4)" },
|
|
1842
|
+
2: { name: "SHA-256", deprecated: false, reason: "current — RFC 4509" },
|
|
1843
|
+
3: { name: "GOST R 34.11-94", deprecated: true, reason: "deprecated (RFC 8624 §3.2; superseded by GOST 2012 in RFC 9558)" },
|
|
1844
|
+
4: { name: "SHA-384", deprecated: false, reason: "current — RFC 6605 §6" },
|
|
1845
|
+
5: { name: "GOST R 34.11-2012", deprecated: false, reason: "current — RFC 9558 §3" },
|
|
1846
|
+
6: { name: "SM3", deprecated: false, reason: "current — RFC 9558 §3 (Chinese national standard)" },
|
|
1847
|
+
});
|
|
1848
|
+
|
|
1849
|
+
function classifyDnskeyAlgorithm(algorithm) {
|
|
1850
|
+
if (typeof algorithm !== "number" || !isFinite(algorithm) || Math.floor(algorithm) !== algorithm) {
|
|
1851
|
+
return null;
|
|
1852
|
+
}
|
|
1853
|
+
var row = DNSKEY_ALGORITHMS[algorithm];
|
|
1854
|
+
if (!row) {
|
|
1855
|
+
return {
|
|
1856
|
+
algorithm: algorithm,
|
|
1857
|
+
name: "unassigned",
|
|
1858
|
+
deprecated: false,
|
|
1859
|
+
reason: "no IANA assignment for algorithm " + algorithm,
|
|
1860
|
+
known: false,
|
|
1861
|
+
};
|
|
1862
|
+
}
|
|
1863
|
+
return {
|
|
1864
|
+
algorithm: algorithm,
|
|
1865
|
+
name: row.name,
|
|
1866
|
+
deprecated: row.deprecated,
|
|
1867
|
+
reason: row.reason,
|
|
1868
|
+
known: true,
|
|
1869
|
+
};
|
|
1870
|
+
}
|
|
1871
|
+
|
|
1872
|
+
function classifyDsDigestType(digestType) {
|
|
1873
|
+
if (typeof digestType !== "number" || !isFinite(digestType) || Math.floor(digestType) !== digestType) {
|
|
1874
|
+
return null;
|
|
1875
|
+
}
|
|
1876
|
+
var row = DS_DIGEST_TYPES[digestType];
|
|
1877
|
+
if (!row) {
|
|
1878
|
+
return {
|
|
1879
|
+
digestType: digestType,
|
|
1880
|
+
name: "unassigned",
|
|
1881
|
+
deprecated: false,
|
|
1882
|
+
reason: "no IANA assignment for digest type " + digestType,
|
|
1883
|
+
known: false,
|
|
1884
|
+
};
|
|
1885
|
+
}
|
|
1886
|
+
return {
|
|
1887
|
+
digestType: digestType,
|
|
1888
|
+
name: row.name,
|
|
1889
|
+
deprecated: row.deprecated,
|
|
1890
|
+
reason: row.reason,
|
|
1891
|
+
known: true,
|
|
1892
|
+
};
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
module.exports = {
|
|
1896
|
+
setServers: setServers,
|
|
1897
|
+
isNullMx: isNullMx,
|
|
1898
|
+
classifyDnskeyAlgorithm: classifyDnskeyAlgorithm,
|
|
1899
|
+
classifyDsDigestType: classifyDsDigestType,
|
|
1900
|
+
DNSKEY_ALGORITHMS: DNSKEY_ALGORITHMS,
|
|
1901
|
+
DS_DIGEST_TYPES: DS_DIGEST_TYPES,
|
|
1902
|
+
getServers: getServers,
|
|
1903
|
+
setResultOrder: setResultOrder,
|
|
1904
|
+
setFamily: setFamily,
|
|
1905
|
+
setLookupTimeoutMs: setLookupTimeoutMs,
|
|
1906
|
+
setCacheTtlMs: setCacheTtlMs,
|
|
1907
|
+
useDnsOverHttps: useDnsOverHttps,
|
|
1908
|
+
useDnsOverTls: useDnsOverTls,
|
|
1909
|
+
useSystemResolver: useSystemResolver,
|
|
1910
|
+
useDesignatedResolvers: useDesignatedResolvers,
|
|
1911
|
+
discoverEncrypted: discoverEncrypted,
|
|
1912
|
+
lookup: lookup,
|
|
1913
|
+
resolve: resolve,
|
|
1914
|
+
resolve4: resolve4,
|
|
1915
|
+
resolve6: resolve6,
|
|
1916
|
+
resolveAaaa: resolveAaaa,
|
|
1917
|
+
resolveSecure: resolveSecure,
|
|
1918
|
+
reverse: reverse,
|
|
1919
|
+
querySvcb: querySvcb,
|
|
1920
|
+
queryHttps: queryHttps,
|
|
1921
|
+
nodeLookup: nodeLookup,
|
|
1922
|
+
clearCache: _clearCache,
|
|
1923
|
+
DnsError: DnsError,
|
|
1924
|
+
_parseSvcbRdata: _parseSvcbRdata,
|
|
1925
|
+
_decodeDnsAnswerRaw: _decodeDnsAnswerRaw,
|
|
1926
|
+
_readDnsName: _readDnsName,
|
|
1927
|
+
_stateForTest: _stateForTest,
|
|
1928
|
+
_resetForTest: _resetForTest,
|
|
1929
|
+
_designatedResolversForTest: _designatedResolversForTest,
|
|
1930
|
+
};
|