@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,1250 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* mail-dkim — DKIM-Signature header generation for outbound mail.
|
|
4
|
+
*
|
|
5
|
+
* RFC 6376 (rsa-sha256) is the default; RFC 8463 (ed25519-sha256) is
|
|
6
|
+
* available as opt-in. The two share the same signer surface so
|
|
7
|
+
* operators flip algorithms by changing the `algorithm` opt and the
|
|
8
|
+
* private key — no code change.
|
|
9
|
+
*
|
|
10
|
+
* Forward-looking: the DKIM-Signature `a=` tag carries an algorithm
|
|
11
|
+
* identifier. When the IETF standardizes a post-quantum DKIM algorithm
|
|
12
|
+
* (an SLH-DSA or ML-DSA variant), this module gains a third allowed
|
|
13
|
+
* value alongside `rsa-sha256` and `ed25519-sha256`. The signer's
|
|
14
|
+
* outer surface stays the same.
|
|
15
|
+
*
|
|
16
|
+
* Public API:
|
|
17
|
+
*
|
|
18
|
+
* var signer = b.mail.dkim.create({
|
|
19
|
+
* domain: "example.com",
|
|
20
|
+
* selector: "s1",
|
|
21
|
+
* privateKey: pemString | crypto.KeyObject,
|
|
22
|
+
* algorithm: "rsa-sha256" (default) | "ed25519-sha256"
|
|
23
|
+
* headersToSign: ["from","to","subject","date","message-id"]
|
|
24
|
+
* (default — order matters in the signed string)
|
|
25
|
+
* canonicalization:"relaxed/relaxed" (default) | "simple/simple"
|
|
26
|
+
* | "relaxed/simple" | "simple/relaxed"
|
|
27
|
+
* bodyLength: number (optional `l=` cap; off by default)
|
|
28
|
+
* audit: false (default true)
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* var signedRfc822 = signer.sign(rfc822String);
|
|
32
|
+
*
|
|
33
|
+
* The signer never mutates the message object — it consumes the final
|
|
34
|
+
* RFC 822 wire format produced by `mail._buildRfc822` and returns a
|
|
35
|
+
* new string with the DKIM-Signature header prepended.
|
|
36
|
+
*
|
|
37
|
+
* Validation surface uses DkimError (FrameworkError subclass) with a
|
|
38
|
+
* permanent flag — every problem here is a configuration / shape
|
|
39
|
+
* problem, not a transient one.
|
|
40
|
+
*/
|
|
41
|
+
var lazyRequire = require("./lazy-require");
|
|
42
|
+
var audit = lazyRequire(function () { return require("./audit"); });
|
|
43
|
+
var nodeCrypto = require("node:crypto");
|
|
44
|
+
var safeBuffer = require("./safe-buffer");
|
|
45
|
+
var validateOpts = require("./validate-opts");
|
|
46
|
+
var C = require("./constants");
|
|
47
|
+
var networkDnsResolver = lazyRequire(function () { return require("./network-dns-resolver"); });
|
|
48
|
+
var { FrameworkError } = require("./framework-error");
|
|
49
|
+
|
|
50
|
+
class DkimError extends FrameworkError {
|
|
51
|
+
constructor(code, message) {
|
|
52
|
+
super(message, code);
|
|
53
|
+
this.name = "DkimError";
|
|
54
|
+
this.permanent = true;
|
|
55
|
+
this.isDkimError = true;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
var ALLOWED_ALGORITHMS = ["rsa-sha256", "ed25519-sha256"];
|
|
60
|
+
var ALLOWED_CANON = [
|
|
61
|
+
"relaxed/relaxed",
|
|
62
|
+
"simple/simple",
|
|
63
|
+
"relaxed/simple",
|
|
64
|
+
"simple/relaxed",
|
|
65
|
+
];
|
|
66
|
+
var DEFAULT_HEADERS = ["from", "to", "subject", "date", "message-id"];
|
|
67
|
+
|
|
68
|
+
// RSA modulus bit-size thresholds per RFC 8301bis (draft-ietf-dmarc-rfc8301bis)
|
|
69
|
+
// + Google + Yahoo February 2024 bulk-sender policy + M³AAWG hardening.
|
|
70
|
+
// RFC 8301 §3.1 historic floor was 1024; bulk-sender enforcement at the
|
|
71
|
+
// two largest mailbox providers raised the operational floor to 2048
|
|
72
|
+
// (messages signed with <2048-bit keys are rejected or quarantined).
|
|
73
|
+
// Anything below MIN must be considered failure on verify; below WEAK
|
|
74
|
+
// emits a warning so operators can quarantine while transitioning.
|
|
75
|
+
// Operators stuck with legacy 1024-bit signers (deprecated; remediate
|
|
76
|
+
// before bulk-sending) opt down via verify({ minRsaBits: 1024 }) per-call
|
|
77
|
+
// — the historical floor stays available for migration but the
|
|
78
|
+
// framework default refuses sub-2048 inbound.
|
|
79
|
+
var RSA_MIN_BITS = 2048; // allow:raw-byte-literal — RFC 8301bis + 2024 bulk-sender floor
|
|
80
|
+
var RSA_WEAK_BITS = 2048; // allow:raw-byte-literal — RFC 8301bis weak threshold (same as floor)
|
|
81
|
+
var RSA_LEGACY_MIN_BITS = 1024; // allow:raw-byte-literal — RFC 8301 historical floor, opt-in only
|
|
82
|
+
|
|
83
|
+
// ---- Canonicalization (RFC 6376 §3.4) ----
|
|
84
|
+
|
|
85
|
+
function _canonHeaderRelaxed(name, value) {
|
|
86
|
+
// Lowercase name, unfold continuations, collapse internal WSP runs to
|
|
87
|
+
// single SP, strip leading/trailing WSP from value.
|
|
88
|
+
var unfolded = String(value).replace(/\r?\n[ \t]+/g, " ");
|
|
89
|
+
var trimmed = unfolded.replace(/[ \t]+/g, " ").replace(/^[ \t]+|[ \t]+$/g, "");
|
|
90
|
+
return name.toLowerCase() + ":" + trimmed + "\r\n";
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function _canonHeaderSimple(name, value) {
|
|
94
|
+
// Preserve as-is. Used rarely in practice but spec-compliant.
|
|
95
|
+
return name + ":" + value + "\r\n";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function _canonBodyRelaxed(body) {
|
|
99
|
+
// 1) Reduce internal WSP runs in each line to a single SP, strip
|
|
100
|
+
// trailing WSP. 2) Strip empty lines at end of body. 3) Ensure
|
|
101
|
+
// a single trailing CRLF. Empty body → just "\r\n".
|
|
102
|
+
if (!body) return "\r\n";
|
|
103
|
+
var normalized = body.replace(/\r?\n/g, "\r\n");
|
|
104
|
+
var lines = normalized.split("\r\n");
|
|
105
|
+
for (var i = 0; i < lines.length; i++) {
|
|
106
|
+
lines[i] = safeBuffer.stripTrailingHspace(lines[i].replace(/[ \t]+/g, " "));
|
|
107
|
+
}
|
|
108
|
+
// Drop trailing empty lines.
|
|
109
|
+
while (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
|
|
110
|
+
if (lines.length === 0) return "\r\n";
|
|
111
|
+
return lines.join("\r\n") + "\r\n";
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function _canonBodySimple(body) {
|
|
115
|
+
// Strip trailing empty lines but otherwise preserve the body. Empty
|
|
116
|
+
// body → "\r\n".
|
|
117
|
+
if (!body) return "\r\n";
|
|
118
|
+
var normalized = body.replace(/\r?\n/g, "\r\n");
|
|
119
|
+
// Strip trailing empty lines.
|
|
120
|
+
while (normalized.endsWith("\r\n\r\n")) {
|
|
121
|
+
normalized = normalized.slice(0, -2);
|
|
122
|
+
}
|
|
123
|
+
if (!normalized.endsWith("\r\n")) normalized += "\r\n";
|
|
124
|
+
return normalized;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ---- RFC 822 split ----
|
|
128
|
+
|
|
129
|
+
function _splitHeadersBody(rfc822) {
|
|
130
|
+
// Headers terminated by the first empty line. Headers may use folded
|
|
131
|
+
// continuation lines (CRLF + WSP); we keep them folded and let the
|
|
132
|
+
// canonicalizer unfold relaxed-mode.
|
|
133
|
+
var sep = rfc822.indexOf("\r\n\r\n");
|
|
134
|
+
if (sep === -1) {
|
|
135
|
+
throw new DkimError("dkim/missing-body-separator",
|
|
136
|
+
"rfc822 input has no header/body separator (CRLF CRLF)");
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
headers: rfc822.slice(0, sep + 2), // include trailing CRLF after last header
|
|
140
|
+
body: rfc822.slice(sep + 4),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function _parseHeaders(rawHeaders) {
|
|
145
|
+
// Parse into [{ name, value }, ...] preserving order. Folded
|
|
146
|
+
// continuation lines (start with WSP) are appended to the prior
|
|
147
|
+
// header's value verbatim.
|
|
148
|
+
var lines = rawHeaders.split("\r\n");
|
|
149
|
+
var out = [];
|
|
150
|
+
for (var i = 0; i < lines.length; i++) {
|
|
151
|
+
var line = lines[i];
|
|
152
|
+
if (!line) continue;
|
|
153
|
+
if (line[0] === " " || line[0] === "\t") {
|
|
154
|
+
if (out.length > 0) out[out.length - 1].value += "\r\n" + line;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
var colon = line.indexOf(":");
|
|
158
|
+
if (colon === -1) continue;
|
|
159
|
+
out.push({
|
|
160
|
+
name: line.slice(0, colon),
|
|
161
|
+
value: line.slice(colon + 1), // preserve leading SP for simple canon
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
return out;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ---- Hashing + signing ----
|
|
168
|
+
|
|
169
|
+
function _bodyHashB64(body, algorithm, canonBody) {
|
|
170
|
+
var canonicalized = canonBody === "simple"
|
|
171
|
+
? _canonBodySimple(body)
|
|
172
|
+
: _canonBodyRelaxed(body);
|
|
173
|
+
var hashName = "sha256"; // both rsa-sha256 and ed25519-sha256 hash with sha256
|
|
174
|
+
return nodeCrypto.createHash(hashName)
|
|
175
|
+
.update(canonicalized).digest("base64");
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function _signString(strToSign, privateKey, algorithm) {
|
|
179
|
+
if (algorithm === "rsa-sha256") {
|
|
180
|
+
return nodeCrypto.createSign("RSA-SHA256")
|
|
181
|
+
.update(strToSign).sign(privateKey).toString("base64");
|
|
182
|
+
}
|
|
183
|
+
if (algorithm === "ed25519-sha256") {
|
|
184
|
+
// Ed25519 in node:crypto signs the raw message (it hashes
|
|
185
|
+
// internally as part of EdDSA). Per RFC 8463 the verifier still
|
|
186
|
+
// sees `a=ed25519-sha256` because the body hash is sha256.
|
|
187
|
+
return nodeCrypto.sign(null, Buffer.from(strToSign, "utf8"), privateKey)
|
|
188
|
+
.toString("base64");
|
|
189
|
+
}
|
|
190
|
+
throw new DkimError("dkim/bad-algorithm",
|
|
191
|
+
"unknown algorithm: " + algorithm);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ---- Signature header construction ----
|
|
195
|
+
|
|
196
|
+
function _foldSignatureHeader(unfolded) {
|
|
197
|
+
// RFC 5322 §2.2.3 line length: 78 preferred, 998 max. The b= value
|
|
198
|
+
// is long enough that folding helps readability and stays well clear
|
|
199
|
+
// of the limit.
|
|
200
|
+
var maxLine = 76;
|
|
201
|
+
var name = "DKIM-Signature: ";
|
|
202
|
+
var rest = unfolded;
|
|
203
|
+
if ((name + rest).length <= maxLine) return name + rest;
|
|
204
|
+
// Fold on tag boundaries (`; tag=value`). Each non-last chunk keeps
|
|
205
|
+
// its trailing `;` (RFC 6376 §3.2 — `;` is the tag-list separator,
|
|
206
|
+
// not a tag-end terminator; receivers' parsers expect it on the
|
|
207
|
+
// PRIOR line at fold points). Earlier shape ("v=1\r\n\ta=...;")
|
|
208
|
+
// missed the first separator and tripped strict parsers.
|
|
209
|
+
var parts = rest.split("; ");
|
|
210
|
+
var lines = [name + parts[0] + (parts.length > 1 ? ";" : "")];
|
|
211
|
+
for (var i = 1; i < parts.length; i++) {
|
|
212
|
+
lines.push("\t" + parts[i] + (i < parts.length - 1 ? ";" : ""));
|
|
213
|
+
}
|
|
214
|
+
return lines.join("\r\n");
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// ---- Public surface ----
|
|
218
|
+
|
|
219
|
+
function create(opts) {
|
|
220
|
+
opts = opts || {};
|
|
221
|
+
validateOpts(opts, [
|
|
222
|
+
"domain", "selector", "privateKey", "algorithm",
|
|
223
|
+
"headersToSign", "canonicalization", "bodyLength", "audit",
|
|
224
|
+
], "mail.dkim.create");
|
|
225
|
+
|
|
226
|
+
if (typeof opts.domain !== "string" || !/^[a-z0-9.-]+\.[a-z]{2,}$/i.test(opts.domain)) {
|
|
227
|
+
throw new DkimError("dkim/bad-domain",
|
|
228
|
+
"domain must be a valid DNS name (e.g. 'example.com')");
|
|
229
|
+
}
|
|
230
|
+
// RFC 6376 §3.1 ABNF: selector = sub-domain *("." sub-domain). Multi-
|
|
231
|
+
// label selectors like "2024.s1" are valid (and common for time-rotated
|
|
232
|
+
// keys). Each label is the LDH set; refuse leading/trailing dots and
|
|
233
|
+
// empty labels.
|
|
234
|
+
if (typeof opts.selector !== "string" ||
|
|
235
|
+
opts.selector.length === 0 || opts.selector.length > 253 || // allow:raw-byte-literal — DNS label length cap (RFC 1035)
|
|
236
|
+
!/^[a-z0-9_-]+(?:\.[a-z0-9_-]+)*$/i.test(opts.selector)) {
|
|
237
|
+
throw new DkimError("dkim/bad-selector",
|
|
238
|
+
"selector must be a non-empty LDH token, optionally dot-separated (e.g. 's1', '2024.s1') (RFC 6376 §3.1)");
|
|
239
|
+
}
|
|
240
|
+
if (!opts.privateKey || (typeof opts.privateKey !== "string" &&
|
|
241
|
+
typeof opts.privateKey !== "object")) {
|
|
242
|
+
throw new DkimError("dkim/missing-private-key",
|
|
243
|
+
"privateKey is required (PEM string or crypto.KeyObject)");
|
|
244
|
+
}
|
|
245
|
+
var algorithm = opts.algorithm || "rsa-sha256";
|
|
246
|
+
if (ALLOWED_ALGORITHMS.indexOf(algorithm) === -1) {
|
|
247
|
+
throw new DkimError("dkim/bad-algorithm",
|
|
248
|
+
"algorithm must be one of: " + ALLOWED_ALGORITHMS.join(", "));
|
|
249
|
+
}
|
|
250
|
+
var canonicalization = opts.canonicalization || "relaxed/relaxed";
|
|
251
|
+
if (ALLOWED_CANON.indexOf(canonicalization) === -1) {
|
|
252
|
+
throw new DkimError("dkim/bad-canonicalization",
|
|
253
|
+
"canonicalization must be one of: " + ALLOWED_CANON.join(", "));
|
|
254
|
+
}
|
|
255
|
+
var canonHeader = canonicalization.split("/")[0];
|
|
256
|
+
var canonBody = canonicalization.split("/")[1];
|
|
257
|
+
|
|
258
|
+
var headersToSign = opts.headersToSign || DEFAULT_HEADERS;
|
|
259
|
+
if (!Array.isArray(headersToSign) || headersToSign.length === 0) {
|
|
260
|
+
throw new DkimError("dkim/bad-headers",
|
|
261
|
+
"headersToSign must be a non-empty array of header names");
|
|
262
|
+
}
|
|
263
|
+
for (var i = 0; i < headersToSign.length; i++) {
|
|
264
|
+
if (typeof headersToSign[i] !== "string" || headersToSign[i].length === 0) {
|
|
265
|
+
throw new DkimError("dkim/bad-headers",
|
|
266
|
+
"headersToSign[" + i + "] must be a non-empty string");
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// The DKIM `l=` body-length tag is intentionally NOT supported.
|
|
270
|
+
// M³AAWG, Gmail, and Microsoft 365 guidance is "never use l=" — it
|
|
271
|
+
// enables append-after-signature attacks where an attacker appends
|
|
272
|
+
// arbitrary content past the signed length and the DKIM signature
|
|
273
|
+
// still validates against the original prefix. Throw at create-time
|
|
274
|
+
// so the misconfiguration surfaces at boot, not at first send().
|
|
275
|
+
if (opts.bodyLength !== undefined) {
|
|
276
|
+
throw new DkimError("dkim/l-tag-forbidden",
|
|
277
|
+
"DKIM `l=` body-length tag is forbidden — append-after-signature " +
|
|
278
|
+
"attack vector. Remove opts.bodyLength.");
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
var auditOn = opts.audit !== false;
|
|
282
|
+
// Try to parse the private key once at create time so misconfigured
|
|
283
|
+
// operators see the failure at boot rather than at first send().
|
|
284
|
+
var keyObject;
|
|
285
|
+
try {
|
|
286
|
+
keyObject = typeof opts.privateKey === "string" || Buffer.isBuffer(opts.privateKey)
|
|
287
|
+
? nodeCrypto.createPrivateKey({ key: opts.privateKey, format: "pem" })
|
|
288
|
+
: opts.privateKey;
|
|
289
|
+
} catch (e) {
|
|
290
|
+
throw new DkimError("dkim/bad-private-key",
|
|
291
|
+
"privateKey could not be parsed: " + ((e && e.message) || String(e)));
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function _emit(action, info) {
|
|
295
|
+
if (!auditOn) return;
|
|
296
|
+
audit().safeEmit({
|
|
297
|
+
action: action,
|
|
298
|
+
outcome: info.outcome || "success",
|
|
299
|
+
actor: info.actor || {},
|
|
300
|
+
metadata: {
|
|
301
|
+
domain: opts.domain,
|
|
302
|
+
selector: opts.selector,
|
|
303
|
+
algorithm: algorithm,
|
|
304
|
+
bodyLength: info.bodyLength,
|
|
305
|
+
durationMs: info.durationMs,
|
|
306
|
+
},
|
|
307
|
+
reason: info.reason || null,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function sign(rfc822) {
|
|
312
|
+
if (typeof rfc822 !== "string" || rfc822.length === 0) {
|
|
313
|
+
throw new DkimError("dkim/bad-input",
|
|
314
|
+
"sign() requires the rfc822 wire format as a non-empty string");
|
|
315
|
+
}
|
|
316
|
+
var t0 = Date.now();
|
|
317
|
+
var split = _splitHeadersBody(rfc822);
|
|
318
|
+
var parsedHeaders = _parseHeaders(split.headers);
|
|
319
|
+
|
|
320
|
+
// Body hash. The `l=` body-length tag is forbidden at create-time
|
|
321
|
+
// (above), so the body is always hashed in full.
|
|
322
|
+
var body = split.body;
|
|
323
|
+
var bh = _bodyHashB64(body, algorithm, canonBody);
|
|
324
|
+
|
|
325
|
+
// Build the unsigned DKIM-Signature header (b= empty).
|
|
326
|
+
// Tag order follows RFC 6376 examples: v, a, c, d, s, h, bh, b.
|
|
327
|
+
var sigTags = [
|
|
328
|
+
"v=1",
|
|
329
|
+
"a=" + algorithm,
|
|
330
|
+
"c=" + canonicalization,
|
|
331
|
+
"d=" + opts.domain,
|
|
332
|
+
"s=" + opts.selector,
|
|
333
|
+
"h=" + headersToSign.join(":"),
|
|
334
|
+
"bh=" + bh,
|
|
335
|
+
];
|
|
336
|
+
sigTags.push("b=");
|
|
337
|
+
var unsignedSigValue = sigTags.join("; ");
|
|
338
|
+
|
|
339
|
+
// Canonicalize the header set: each header in headersToSign (in
|
|
340
|
+
// order, picking the LAST occurrence per RFC 6376 §5.4.2), then
|
|
341
|
+
// the DKIM-Signature header itself with empty b=. The result is
|
|
342
|
+
// what gets signed.
|
|
343
|
+
//
|
|
344
|
+
// Missing-header policy (RFC 6376 §3.4.2 + §5.4): the signer is
|
|
345
|
+
// permitted to list a header in h= that isn't present in the
|
|
346
|
+
// message — the verifier will compute the canonicalized form as
|
|
347
|
+
// empty and the signature still validates IF both sides agree the
|
|
348
|
+
// header is absent. The risk is silent drift: an operator
|
|
349
|
+
// configures `headersToSign: [..., "List-Unsubscribe-Post", ...]`
|
|
350
|
+
// for a campaign mailer, the per-message builder forgets to add
|
|
351
|
+
// the header, and the signature ships without binding to the
|
|
352
|
+
// intended commitment. Emit an audit event so operators see the
|
|
353
|
+
// skip rather than only noticing when a recipient rejects.
|
|
354
|
+
var headerNamesLc = parsedHeaders.map(function (h) { return h.name.toLowerCase(); });
|
|
355
|
+
var missingHeaders = [];
|
|
356
|
+
var canonicalizedHeaders = "";
|
|
357
|
+
for (var j = 0; j < headersToSign.length; j++) {
|
|
358
|
+
var wantLc = headersToSign[j].toLowerCase();
|
|
359
|
+
var idx = -1;
|
|
360
|
+
for (var k = 0; k < headerNamesLc.length; k++) {
|
|
361
|
+
if (headerNamesLc[k] === wantLc) idx = k;
|
|
362
|
+
}
|
|
363
|
+
if (idx === -1) {
|
|
364
|
+
// Operator configured h= entry that isn't in the message —
|
|
365
|
+
// surface via audit; sign continues per RFC 6376 §3.4.2.
|
|
366
|
+
missingHeaders.push(headersToSign[j]);
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
var h = parsedHeaders[idx];
|
|
370
|
+
canonicalizedHeaders += canonHeader === "simple"
|
|
371
|
+
? _canonHeaderSimple(h.name, h.value)
|
|
372
|
+
: _canonHeaderRelaxed(h.name, h.value);
|
|
373
|
+
}
|
|
374
|
+
if (missingHeaders.length > 0 && auditOn) {
|
|
375
|
+
try {
|
|
376
|
+
audit().safeEmit({
|
|
377
|
+
action: "dkim.sign.headers_missing",
|
|
378
|
+
outcome: "success",
|
|
379
|
+
actor: null,
|
|
380
|
+
metadata: {
|
|
381
|
+
domain: opts.domain,
|
|
382
|
+
selector: opts.selector,
|
|
383
|
+
missingHeaders: missingHeaders,
|
|
384
|
+
headersConfigured: headersToSign.length,
|
|
385
|
+
severity: "warning",
|
|
386
|
+
},
|
|
387
|
+
});
|
|
388
|
+
} catch (_e) { /* drop-silent */ }
|
|
389
|
+
}
|
|
390
|
+
// Append the unsigned DKIM-Signature header without trailing CRLF
|
|
391
|
+
// per RFC 6376 §3.7.
|
|
392
|
+
var dkimHeaderForSigning = canonHeader === "simple"
|
|
393
|
+
? _canonHeaderSimple("DKIM-Signature", " " + unsignedSigValue)
|
|
394
|
+
: _canonHeaderRelaxed("DKIM-Signature", unsignedSigValue);
|
|
395
|
+
canonicalizedHeaders += dkimHeaderForSigning.replace(/\r\n$/, "");
|
|
396
|
+
|
|
397
|
+
var signature = _signString(canonicalizedHeaders, keyObject, algorithm);
|
|
398
|
+
// Replace the empty `b=` placeholder with the actual base64 signature.
|
|
399
|
+
var finalSigValue = sigTags.slice(0, -1).concat(["b=" + signature]).join("; ");
|
|
400
|
+
|
|
401
|
+
var dkimHeaderLine = _foldSignatureHeader(finalSigValue) + "\r\n";
|
|
402
|
+
|
|
403
|
+
_emit("dkim.sign.success", {
|
|
404
|
+
bodyLength: body.length,
|
|
405
|
+
durationMs: Date.now() - t0,
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
return dkimHeaderLine + rfc822;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
return {
|
|
412
|
+
sign: sign,
|
|
413
|
+
domain: opts.domain,
|
|
414
|
+
selector: opts.selector,
|
|
415
|
+
algorithm: algorithm,
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// dualSigner — RFC 8463 §3 transition signer. Produces messages with
|
|
420
|
+
// BOTH a legacy RSA-SHA-256 DKIM-Signature AND an Ed25519-SHA-256
|
|
421
|
+
// DKIM-Signature header. Receivers that don't yet support Ed25519
|
|
422
|
+
// validate the RSA signature; receivers that prefer Ed25519 validate
|
|
423
|
+
// the post-quantum-friendlier signature. The transition pattern is
|
|
424
|
+
// the recommended path for moving the operator's domain off RSA-SHA-
|
|
425
|
+
// 256 without breaking older verifiers.
|
|
426
|
+
//
|
|
427
|
+
// var dual = b.mail.dkim.dualSigner({
|
|
428
|
+
// domain: "example.com",
|
|
429
|
+
// rsa: { selector: "rsa1", privateKey: rsaPemKey },
|
|
430
|
+
// eddsa: { selector: "eddsa1", privateKey: ed25519PemKey },
|
|
431
|
+
// // every other create() opt is shared (canonicalization,
|
|
432
|
+
// // headersToSign, audit) but can be overridden per algorithm.
|
|
433
|
+
// });
|
|
434
|
+
// var signed = dual.sign(rfc822Wire);
|
|
435
|
+
// // → wire with two DKIM-Signature: headers (RSA first, Ed25519 second)
|
|
436
|
+
//
|
|
437
|
+
// Both signers are constructed eagerly at create-time (configuration
|
|
438
|
+
// errors surface at boot, not at first send). The combined sign()
|
|
439
|
+
// applies the RSA signer first, then the Ed25519 signer on top.
|
|
440
|
+
// ---- DKIM-Signature verification (RFC 6376 §6) ----
|
|
441
|
+
//
|
|
442
|
+
// Counterpart to the signer. Walks every DKIM-Signature header in
|
|
443
|
+
// the message, parses the tag list, fetches the signing public key
|
|
444
|
+
// from DNS TXT at <selector>._domainkey.<domain>, canonicalizes the
|
|
445
|
+
// body + headers per the c= tag, and runs nodeCrypto.verify.
|
|
446
|
+
//
|
|
447
|
+
// Surface:
|
|
448
|
+
//
|
|
449
|
+
// var rv = await b.mail.dkim.verify(rfc822, {
|
|
450
|
+
// dnsLookup: async function (qname, type) { return [["v=DKIM1; k=rsa; p=BASE64..."]]; },
|
|
451
|
+
// });
|
|
452
|
+
// // → [{ d, s, alg, result, errors }, ...]
|
|
453
|
+
//
|
|
454
|
+
// One result per DKIM-Signature header (operators expect multiple
|
|
455
|
+
// when senders dual-sign with RSA + Ed25519). Each result's `result`
|
|
456
|
+
// is one of: "pass" / "fail" / "permerror" / "temperror" / "neutral".
|
|
457
|
+
//
|
|
458
|
+
// dnsLookup is operator-supplied so verify() composes with the
|
|
459
|
+
// framework's b.network.dns (DoH / DoT / system) without taking a
|
|
460
|
+
// hard dependency on it. When omitted, falls back to node:dns.
|
|
461
|
+
|
|
462
|
+
function _parseDkimTagList(value) {
|
|
463
|
+
// RFC 6376 §3.2 — tags are `key=value` separated by `;`. Whitespace
|
|
464
|
+
// around `=` and `;` is allowed and stripped. The signer folds the
|
|
465
|
+
// DKIM-Signature header across CRLF + WSP; unfold first so tag
|
|
466
|
+
// boundaries land in the right place.
|
|
467
|
+
var unfolded = String(value).replace(/\r?\n[ \t]+/g, " ");
|
|
468
|
+
var tags = {};
|
|
469
|
+
var parts = unfolded.split(";");
|
|
470
|
+
for (var i = 0; i < parts.length; i += 1) {
|
|
471
|
+
var p = parts[i].trim();
|
|
472
|
+
if (p.length === 0) continue;
|
|
473
|
+
var eq = p.indexOf("=");
|
|
474
|
+
if (eq === -1) continue;
|
|
475
|
+
var key = p.slice(0, eq).trim().toLowerCase();
|
|
476
|
+
var val = p.slice(eq + 1).trim();
|
|
477
|
+
// Whitespace inside values is unfolded — RFC 6376 §3.2 says FWS
|
|
478
|
+
// (folding whitespace) is ignored within a tag value. Strip
|
|
479
|
+
// newlines + tabs while preserving the meaningful tokens.
|
|
480
|
+
val = val.replace(/\s+/g, "");
|
|
481
|
+
tags[key] = val;
|
|
482
|
+
}
|
|
483
|
+
return tags;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function _selectorTxtToKeyTags(txtRecords) {
|
|
487
|
+
// DKIM key record is a TXT record at <selector>._domainkey.<domain>.
|
|
488
|
+
// Format: "v=DKIM1; k=rsa; p=<base64>" (chunks may be split across
|
|
489
|
+
// multi-string TXT). Returns { v, k, p, t, h } or throws.
|
|
490
|
+
var joined = "";
|
|
491
|
+
if (Array.isArray(txtRecords)) {
|
|
492
|
+
for (var i = 0; i < txtRecords.length; i += 1) {
|
|
493
|
+
var rec = txtRecords[i];
|
|
494
|
+
joined = Array.isArray(rec) ? rec.join("") : String(rec);
|
|
495
|
+
if (joined.indexOf("v=DKIM1") === 0 || joined.indexOf("p=") !== -1) break;
|
|
496
|
+
}
|
|
497
|
+
} else {
|
|
498
|
+
joined = String(txtRecords || "");
|
|
499
|
+
}
|
|
500
|
+
if (joined.length === 0) {
|
|
501
|
+
throw new DkimError("dkim/key-not-found", "DKIM key record is empty");
|
|
502
|
+
}
|
|
503
|
+
return _parseDkimTagList(joined);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// Process-local cache for fetched DKIM key TXT records. Mailing-list
|
|
507
|
+
// fan-out and bulk-replay scenarios frequently re-fetch the same
|
|
508
|
+
// selector; without a cache the verifier hammers DNS. TTL bounded so
|
|
509
|
+
// rotated keys propagate within minutes, not hours.
|
|
510
|
+
//
|
|
511
|
+
// Eviction is LRU (not FIFO): on hit, the entry is removed and
|
|
512
|
+
// re-inserted so the Map's insertion-order ordering tracks recency.
|
|
513
|
+
// FIFO would evict the most-recently-fetched key of an
|
|
514
|
+
// active-domain mix under cache pressure — exactly the wrong shape
|
|
515
|
+
// for repeated-sender workloads.
|
|
516
|
+
var DKIM_KEY_CACHE = new Map();
|
|
517
|
+
var DKIM_KEY_CACHE_TTL_MS = C.TIME.minutes(5);
|
|
518
|
+
var DKIM_KEY_CACHE_MAX_ENTRIES = 1024;
|
|
519
|
+
|
|
520
|
+
// Per-message signature-count cap (DoS bound). A single message with
|
|
521
|
+
// many DKIM-Signature headers forces the verifier to fetch a key and
|
|
522
|
+
// run cryptographic verify for each — without a cap, an attacker
|
|
523
|
+
// inflates verifier work linearly in header count. RFC 6376 §6.1
|
|
524
|
+
// permits multiple signatures but doesn't bound them; mainstream
|
|
525
|
+
// receivers cap at 5–8. Operators that legitimately accept more
|
|
526
|
+
// override via verify({ maxSignatures }).
|
|
527
|
+
var DKIM_MAX_SIGNATURES_PER_MESSAGE = 8; // allow:raw-byte-literal — receiver-fan-out DoS bound
|
|
528
|
+
// Operator-supplied `maxSignatures` opt is range-checked against this
|
|
529
|
+
// ceiling. RFC 6376 §6.1 sets no upper bound; 16 is generous headroom
|
|
530
|
+
// for legitimate relay chains with hop signatures while keeping the
|
|
531
|
+
// verify-fan-out within a CPU-DoS envelope.
|
|
532
|
+
var DKIM_MAX_SIGNATURES_PER_MESSAGE_CEILING = 16; // allow:raw-byte-literal — operator-opt range ceiling
|
|
533
|
+
|
|
534
|
+
function _cacheGet(qname) {
|
|
535
|
+
var ent = DKIM_KEY_CACHE.get(qname);
|
|
536
|
+
if (!ent) return null;
|
|
537
|
+
if (ent.expires <= Date.now()) {
|
|
538
|
+
DKIM_KEY_CACHE.delete(qname);
|
|
539
|
+
return null;
|
|
540
|
+
}
|
|
541
|
+
// LRU: remove + re-insert so this entry becomes the most-recent in
|
|
542
|
+
// Map insertion order. Evictions below pop the oldest via keys().
|
|
543
|
+
DKIM_KEY_CACHE.delete(qname);
|
|
544
|
+
DKIM_KEY_CACHE.set(qname, ent);
|
|
545
|
+
return ent.tags;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
function _cachePut(qname, tags) {
|
|
549
|
+
if (DKIM_KEY_CACHE.size >= DKIM_KEY_CACHE_MAX_ENTRIES) {
|
|
550
|
+
// Drop oldest by insertion-order (LRU since _cacheGet rotates).
|
|
551
|
+
var oldest = DKIM_KEY_CACHE.keys().next().value;
|
|
552
|
+
if (oldest !== undefined) DKIM_KEY_CACHE.delete(oldest);
|
|
553
|
+
}
|
|
554
|
+
DKIM_KEY_CACHE.set(qname, { tags: tags, expires: Date.now() + DKIM_KEY_CACHE_TTL_MS });
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// Shared safe-DNS TXT lookup. Operator-supplied `dnsLookup` (legacy
|
|
558
|
+
// `[[strings]]` shape) takes precedence; otherwise routes through
|
|
559
|
+
// `b.network.dns.resolver` which uses DoH by default (per v0.7.23),
|
|
560
|
+
// so the framework default never falls back to plaintext node:dns
|
|
561
|
+
// resolution against an operator-untrusted upstream. CVE-2008-1447
|
|
562
|
+
// (Kaminsky) + CVE-2022-3204 (NRDelegationAttack) class — the
|
|
563
|
+
// transport-encrypted DoH path plus `b.safeDns` parse caps defend
|
|
564
|
+
// both transport and parse-side. Operators that need plaintext
|
|
565
|
+
// upstream wire it explicitly via `dnsLookup`.
|
|
566
|
+
var _defaultResolver = null;
|
|
567
|
+
function _getDefaultResolver() {
|
|
568
|
+
if (_defaultResolver) return _defaultResolver;
|
|
569
|
+
_defaultResolver = networkDnsResolver().create();
|
|
570
|
+
return _defaultResolver;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
async function _safeResolveTxt(qname, operatorLookup) {
|
|
574
|
+
if (operatorLookup) return operatorLookup(qname, "TXT");
|
|
575
|
+
var r = await _getDefaultResolver().queryTxt(qname);
|
|
576
|
+
// Resolver returns parsed RRs; reshape to the legacy
|
|
577
|
+
// `[[chunk1, chunk2], ...]` shape so callers downstream don't care
|
|
578
|
+
// which path produced the bytes.
|
|
579
|
+
var out = [];
|
|
580
|
+
for (var i = 0; i < r.rrs.length; i += 1) {
|
|
581
|
+
var rr = r.rrs[i];
|
|
582
|
+
if (rr && rr.type === 16) { // allow:raw-byte-literal — IANA DNS qtype TXT
|
|
583
|
+
out.push(Array.isArray(rr.decoded) ? rr.decoded : [String(rr.decoded)]);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
if (out.length === 0) {
|
|
587
|
+
var err = new Error("no TXT records for " + qname);
|
|
588
|
+
err.code = "ENODATA";
|
|
589
|
+
throw err;
|
|
590
|
+
}
|
|
591
|
+
return out;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
function _resetDkimKeyCacheForTest() { DKIM_KEY_CACHE.clear(); }
|
|
595
|
+
|
|
596
|
+
function _pemFromB64KeyMaterial(b64) {
|
|
597
|
+
// RSA: SubjectPublicKeyInfo DER in base64. Ed25519: raw 32-byte key
|
|
598
|
+
// OR SPKI DER. Wrap in PEM markers so node:crypto.createPublicKey
|
|
599
|
+
// accepts it.
|
|
600
|
+
var pem = "-----BEGIN PUBLIC KEY-----\n";
|
|
601
|
+
// 64-char wrap (PEM convention).
|
|
602
|
+
for (var i = 0; i < b64.length; i += 64) { // allow:raw-byte-literal — PEM wrap width
|
|
603
|
+
pem += b64.slice(i, i + 64) + "\n"; // allow:raw-byte-literal — PEM wrap width
|
|
604
|
+
}
|
|
605
|
+
pem += "-----END PUBLIC KEY-----\n";
|
|
606
|
+
return pem;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
async function _fetchDkimKey(domain, selector, dnsLookup) {
|
|
610
|
+
var qname = selector + "._domainkey." + domain;
|
|
611
|
+
var cached = _cacheGet(qname);
|
|
612
|
+
if (cached) return cached;
|
|
613
|
+
var records;
|
|
614
|
+
try {
|
|
615
|
+
records = await _safeResolveTxt(qname, dnsLookup);
|
|
616
|
+
} catch (e) {
|
|
617
|
+
if (e && (e.code === "ENOTFOUND" || e.code === "ENODATA")) {
|
|
618
|
+
throw new DkimError("dkim/key-not-found",
|
|
619
|
+
"no DKIM TXT record at " + qname);
|
|
620
|
+
}
|
|
621
|
+
throw new DkimError("dkim/key-lookup-temperror",
|
|
622
|
+
"DKIM TXT lookup for " + qname + " failed: " +
|
|
623
|
+
((e && e.message) || String(e)));
|
|
624
|
+
}
|
|
625
|
+
var tags = _selectorTxtToKeyTags(records);
|
|
626
|
+
_cachePut(qname, tags);
|
|
627
|
+
return tags;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
function _findDkimSignatureHeaders(parsedHeaders) {
|
|
631
|
+
var out = [];
|
|
632
|
+
for (var i = 0; i < parsedHeaders.length; i += 1) {
|
|
633
|
+
if (parsedHeaders[i].name.toLowerCase() === "dkim-signature") {
|
|
634
|
+
out.push({ index: i, name: parsedHeaders[i].name, value: parsedHeaders[i].value });
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
return out;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// Strip the value of the `b=` tag from a DKIM-Signature tag list per
|
|
641
|
+
// RFC 6376 §3.7. Walks tag-spec boundaries (`;` separator) and only
|
|
642
|
+
// matches the exact `b` tag name — not any tag whose name happens
|
|
643
|
+
// to end in `b`. Returns the value with the b= tag's content removed
|
|
644
|
+
// (leaving `b=` in place).
|
|
645
|
+
function _stripBTagValue(value) {
|
|
646
|
+
var parts = String(value).split(";");
|
|
647
|
+
var out = [];
|
|
648
|
+
for (var i = 0; i < parts.length; i += 1) {
|
|
649
|
+
var p = parts[i];
|
|
650
|
+
var m = /^(\s*)([A-Za-z][A-Za-z0-9_-]*)(\s*=)/.exec(p);
|
|
651
|
+
if (m && m[2].toLowerCase() === "b") {
|
|
652
|
+
out.push(m[1] + m[2] + m[3]);
|
|
653
|
+
continue;
|
|
654
|
+
}
|
|
655
|
+
out.push(p);
|
|
656
|
+
}
|
|
657
|
+
return out.join(";");
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
function _verifySingleSignature(rfc822, parsedHeaders, sigHeader, keyTags, sigTags, verifyOpts) {
|
|
661
|
+
verifyOpts = verifyOpts || {};
|
|
662
|
+
// Reconstruct what the signer canonicalized, per RFC 6376 §3.7.
|
|
663
|
+
var canonicalization = sigTags.c || "simple/simple";
|
|
664
|
+
var canonHeader = canonicalization.split("/")[0];
|
|
665
|
+
var canonBody = canonicalization.split("/")[1];
|
|
666
|
+
var algorithm = sigTags.a;
|
|
667
|
+
|
|
668
|
+
// RFC 6376 §3.5 — the optional i= tag (Agent or User Identifier),
|
|
669
|
+
// when present, MUST have a domain part identical to or a subdomain
|
|
670
|
+
// of d=. A signature whose i= claims `@evil.example.com` while d=
|
|
671
|
+
// is `example.org` is malformed and binds the signer's claim to a
|
|
672
|
+
// domain the verifier wouldn't otherwise associate. Refuse.
|
|
673
|
+
if (typeof sigTags.i === "string" && sigTags.i.length > 0) {
|
|
674
|
+
var iDomain = sigTags.i.indexOf("@") === -1
|
|
675
|
+
? sigTags.i
|
|
676
|
+
: sigTags.i.slice(sigTags.i.indexOf("@") + 1);
|
|
677
|
+
var d = String(sigTags.d || "").toLowerCase();
|
|
678
|
+
var iDl = iDomain.toLowerCase();
|
|
679
|
+
if (d.length === 0 || (iDl !== d && iDl.slice(-d.length - 1) !== "." + d)) {
|
|
680
|
+
return { result: "permerror",
|
|
681
|
+
errors: ["DKIM-Signature i=" + sigTags.i + " is not d= or a subdomain of d=" + sigTags.d + " (RFC 6376 §3.5)"] };
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// RFC 6376 §3.6.1 — the key record's optional h= tag declares the
|
|
686
|
+
// hash algorithms the key MAY be used with (`sha256` is canonical).
|
|
687
|
+
// The signature's a= names the hash via its suffix (`rsa-sha256`,
|
|
688
|
+
// `ed25519-sha256`). If h= is present on the key, the signature's
|
|
689
|
+
// hash MUST appear in the colon-separated list; otherwise the key
|
|
690
|
+
// owner intends the key for a different hash family and the
|
|
691
|
+
// signature is unauthorized.
|
|
692
|
+
if (typeof keyTags.h === "string" && keyTags.h.length > 0) {
|
|
693
|
+
var sigHash = String(algorithm || "").toLowerCase().split("-").slice(-1)[0];
|
|
694
|
+
var allowedHashes = keyTags.h.toLowerCase().split(":").map(function (s) { return s.trim(); });
|
|
695
|
+
if (sigHash.length === 0 || allowedHashes.indexOf(sigHash) === -1) {
|
|
696
|
+
return { result: "permerror",
|
|
697
|
+
errors: ["DKIM-Signature a=" + algorithm + " hash '" + sigHash +
|
|
698
|
+
"' not in key h=" + keyTags.h + " (RFC 6376 §3.6.1)"] };
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
var split = _splitHeadersBody(rfc822);
|
|
703
|
+
var body = split.body;
|
|
704
|
+
if (sigTags.l !== undefined) {
|
|
705
|
+
// The framework refuses l= at SIGN-time per the M3AAWG / Gmail /
|
|
706
|
+
// Microsoft 365 guidance (v0.7.18). On VERIFY, an `l=` tag on an
|
|
707
|
+
// inbound signature signals append-after-signature exposure —
|
|
708
|
+
// operators decide acceptance. Honor the cap for the body hash so
|
|
709
|
+
// the signature still validates against legitimate senders that
|
|
710
|
+
// use l=, but flag in the result.
|
|
711
|
+
var lcap = parseInt(sigTags.l, 10);
|
|
712
|
+
if (isFinite(lcap) && lcap >= 0) body = body.slice(0, lcap);
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// 1. Body-hash check.
|
|
716
|
+
var expectedBh = sigTags.bh;
|
|
717
|
+
if (typeof expectedBh !== "string") {
|
|
718
|
+
return { result: "permerror", errors: ["DKIM-Signature missing bh="] };
|
|
719
|
+
}
|
|
720
|
+
var actualBh = _bodyHashB64(body, algorithm, canonBody);
|
|
721
|
+
if (actualBh !== expectedBh) {
|
|
722
|
+
return { result: "fail", errors: ["body hash mismatch"] };
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
// 2. Canonicalize the headers in h= order, then the DKIM-Signature
|
|
726
|
+
// header itself with the b= value emptied (per §3.7).
|
|
727
|
+
var headerNames = (sigTags.h || "").split(":").map(function (s) {
|
|
728
|
+
return s.trim().toLowerCase();
|
|
729
|
+
});
|
|
730
|
+
// RFC 6376 §3.5 — "from" MUST be in h=. Without From-coverage the
|
|
731
|
+
// signature does not bind to the visible sender, and the receiver's
|
|
732
|
+
// "this domain signed for that From" claim is meaningless. Cornerstone
|
|
733
|
+
// bypass class — refuse the signature outright.
|
|
734
|
+
if (headerNames.indexOf("from") === -1) {
|
|
735
|
+
return { result: "permerror",
|
|
736
|
+
errors: ["DKIM-Signature h= tag does not include 'from' (RFC 6376 §3.5)"] };
|
|
737
|
+
}
|
|
738
|
+
var lcNames = parsedHeaders.map(function (h) { return h.name.toLowerCase(); });
|
|
739
|
+
var canonicalizedHeaders = "";
|
|
740
|
+
for (var j = 0; j < headerNames.length; j += 1) {
|
|
741
|
+
var want = headerNames[j];
|
|
742
|
+
if (want.length === 0) continue;
|
|
743
|
+
var idx = lcNames.lastIndexOf(want); // last-occurrence per the DKIM spec
|
|
744
|
+
if (idx === -1) continue;
|
|
745
|
+
var h = parsedHeaders[idx];
|
|
746
|
+
canonicalizedHeaders += canonHeader === "simple"
|
|
747
|
+
? _canonHeaderSimple(h.name, h.value)
|
|
748
|
+
: _canonHeaderRelaxed(h.name, h.value);
|
|
749
|
+
}
|
|
750
|
+
// Strip the b= value from the DKIM-Signature header for the canonical
|
|
751
|
+
// form per RFC 6376 §3.7. The strip must locate the `b=` tag within
|
|
752
|
+
// the tag-list grammar (`tag-spec *( ";" tag-spec )` per §3.2) and
|
|
753
|
+
// zero its value through the next `;` OR end-of-string. The earlier
|
|
754
|
+
// shape `/(\bb=)[^;]*/i` matched on the first `b=` substring anywhere
|
|
755
|
+
// in the value — fine for current DKIM tag vocabulary (no tag-name
|
|
756
|
+
// ends in `b`) but brittle against any hypothetical future tag whose
|
|
757
|
+
// name ends in `b` (`ab=`, `pub=`, `cb=` …). Anchor on the tag-list
|
|
758
|
+
// structure instead.
|
|
759
|
+
var unsignedSigValue = _stripBTagValue(sigHeader.value);
|
|
760
|
+
canonicalizedHeaders += canonHeader === "simple"
|
|
761
|
+
? _canonHeaderSimple("DKIM-Signature", " " + unsignedSigValue).replace(/\r\n$/, "")
|
|
762
|
+
: _canonHeaderRelaxed("DKIM-Signature", unsignedSigValue).replace(/\r\n$/, "");
|
|
763
|
+
|
|
764
|
+
// 3. Verify the signature.
|
|
765
|
+
var sigB64 = sigTags.b;
|
|
766
|
+
if (typeof sigB64 !== "string") {
|
|
767
|
+
return { result: "permerror", errors: ["DKIM-Signature missing b="] };
|
|
768
|
+
}
|
|
769
|
+
var sigBuf = Buffer.from(sigB64, "base64");
|
|
770
|
+
var pem = _pemFromB64KeyMaterial(keyTags.p);
|
|
771
|
+
var keyObj;
|
|
772
|
+
try { keyObj = nodeCrypto.createPublicKey(pem); }
|
|
773
|
+
catch (e) {
|
|
774
|
+
return { result: "permerror",
|
|
775
|
+
errors: ["DKIM key parse failed: " + ((e && e.message) || String(e))] };
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
var nodeAlgo = algorithm === "rsa-sha256" ? "sha256" :
|
|
779
|
+
algorithm === "ed25519-sha256" ? null : null;
|
|
780
|
+
if (algorithm !== "rsa-sha256" && algorithm !== "ed25519-sha256") {
|
|
781
|
+
return { result: "permerror",
|
|
782
|
+
errors: ["unsupported DKIM algorithm '" + algorithm + "'"] };
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
// Key-size enforcement (RFC 8301bis §3.1 + Google + Yahoo Feb 2024
|
|
786
|
+
// bulk-sender + M³AAWG hardening):
|
|
787
|
+
// - Default floor: 2048 bits (bulk-sender enforced floor).
|
|
788
|
+
// - Operator opt-down: verify({ minRsaBits: 1024 }) re-enables the
|
|
789
|
+
// historical RFC 8301 floor for legacy migration windows. Sub-
|
|
790
|
+
// 1024 is refused regardless of opt-down — no operator policy
|
|
791
|
+
// can accept genuinely-too-small RSA per §3.1.
|
|
792
|
+
// - Below opt-down-honored floor → fail; below WEAK threshold →
|
|
793
|
+
// warning so operators can quarantine while transitioning.
|
|
794
|
+
var operatorMinBits = (typeof verifyOpts.minRsaBits === "number" &&
|
|
795
|
+
isFinite(verifyOpts.minRsaBits) &&
|
|
796
|
+
verifyOpts.minRsaBits >= RSA_LEGACY_MIN_BITS)
|
|
797
|
+
? Math.floor(verifyOpts.minRsaBits)
|
|
798
|
+
: RSA_MIN_BITS;
|
|
799
|
+
var warnings = [];
|
|
800
|
+
if (algorithm === "rsa-sha256" && keyObj.asymmetricKeyType === "rsa") {
|
|
801
|
+
var modBits = (keyObj.asymmetricKeyDetails && keyObj.asymmetricKeyDetails.modulusLength) || 0;
|
|
802
|
+
if (modBits > 0 && modBits < operatorMinBits) {
|
|
803
|
+
return { result: "fail",
|
|
804
|
+
errors: ["RSA key too small: " + modBits + " bits (minimum " + operatorMinBits +
|
|
805
|
+
" — RFC 8301bis + 2024 bulk-sender)"] };
|
|
806
|
+
}
|
|
807
|
+
if (modBits > 0 && modBits < RSA_WEAK_BITS) {
|
|
808
|
+
warnings.push("rsa-key-weak: " + modBits + " bits (< " + RSA_WEAK_BITS + ")");
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
if (sigTags.l !== undefined) {
|
|
812
|
+
warnings.push("l-tag-present: append-after-signature exposure (RFC 6376 §8.2)");
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
var verified;
|
|
816
|
+
try {
|
|
817
|
+
verified = nodeCrypto.verify(nodeAlgo,
|
|
818
|
+
Buffer.from(canonicalizedHeaders, "utf8"), keyObj, sigBuf);
|
|
819
|
+
} catch (e) {
|
|
820
|
+
return { result: "permerror",
|
|
821
|
+
errors: ["DKIM verify threw: " + ((e && e.message) || String(e))] };
|
|
822
|
+
}
|
|
823
|
+
return verified
|
|
824
|
+
? { result: "pass", errors: [], warnings: warnings }
|
|
825
|
+
: { result: "fail", errors: ["signature verification failed"], warnings: warnings };
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
// RFC 6376 §3.5 — `t=` / `x=` clock-skew bound. Operator-tunable, but
|
|
829
|
+
// must be a finite non-negative number and must NOT exceed the
|
|
830
|
+
// FRAMEWORK absolute ceiling. An unbounded skew lets an attacker
|
|
831
|
+
// re-play a long-expired signed message indefinitely; the ceiling
|
|
832
|
+
// bounds the maximum back-dating tolerance.
|
|
833
|
+
var DKIM_CLOCK_SKEW_MS_MAX = C.TIME.hours(24);
|
|
834
|
+
var DKIM_CLOCK_SKEW_MS_DEFAULT = C.TIME.minutes(5);
|
|
835
|
+
|
|
836
|
+
async function verify(rfc822, opts) {
|
|
837
|
+
if (typeof rfc822 !== "string" || rfc822.length === 0) {
|
|
838
|
+
throw new DkimError("dkim/bad-input",
|
|
839
|
+
"verify(): rfc822 must be a non-empty string");
|
|
840
|
+
}
|
|
841
|
+
opts = opts || {};
|
|
842
|
+
validateOpts(opts, ["dnsLookup", "audit", "clockSkewMs", "maxSignatures",
|
|
843
|
+
"minRsaBits"], "mail.dkim.verify");
|
|
844
|
+
var auditOn = opts.audit !== false;
|
|
845
|
+
|
|
846
|
+
// Bounded clock skew: refuse non-numeric / negative / infinite /
|
|
847
|
+
// beyond-ceiling. Throwing on bad config-time input per the
|
|
848
|
+
// framework's three-tier validation policy.
|
|
849
|
+
var clockSkewMs;
|
|
850
|
+
if (opts.clockSkewMs === undefined || opts.clockSkewMs === null) {
|
|
851
|
+
clockSkewMs = DKIM_CLOCK_SKEW_MS_DEFAULT;
|
|
852
|
+
} else if (typeof opts.clockSkewMs !== "number" || !isFinite(opts.clockSkewMs) ||
|
|
853
|
+
opts.clockSkewMs < 0) {
|
|
854
|
+
throw new DkimError("dkim/bad-clock-skew",
|
|
855
|
+
"verify(): clockSkewMs must be a finite non-negative number");
|
|
856
|
+
} else if (opts.clockSkewMs > DKIM_CLOCK_SKEW_MS_MAX) {
|
|
857
|
+
throw new DkimError("dkim/bad-clock-skew",
|
|
858
|
+
"verify(): clockSkewMs " + opts.clockSkewMs + " exceeds framework ceiling " +
|
|
859
|
+
DKIM_CLOCK_SKEW_MS_MAX + " (RFC 6376 §3.5 — back-dating replay defense)");
|
|
860
|
+
} else {
|
|
861
|
+
clockSkewMs = Math.floor(opts.clockSkewMs);
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
// RFC 6376 §6.1 — verifier MUST handle multiple signatures but the
|
|
865
|
+
// RFC sets no count cap. An unbounded count is a CPU-DoS surface
|
|
866
|
+
// (each sig forces a DNS fetch + cryptographic verify). Range 1-16
|
|
867
|
+
// — mainstream receivers (Gmail/Yahoo/MS 2024 bulk-sender guidance)
|
|
868
|
+
// cite 2-3 valid signatures per message as the operational ceiling;
|
|
869
|
+
// 16 is generous headroom for relay chains with hop signatures. The
|
|
870
|
+
// operator opt is range-checked at config time — values < 1 or > 16
|
|
871
|
+
// throw rather than silently clamp so an over-large config doesn't
|
|
872
|
+
// re-introduce the DoS surface.
|
|
873
|
+
var maxSignatures = DKIM_MAX_SIGNATURES_PER_MESSAGE;
|
|
874
|
+
if (opts.maxSignatures !== undefined) {
|
|
875
|
+
if (typeof opts.maxSignatures !== "number" ||
|
|
876
|
+
!isFinite(opts.maxSignatures) ||
|
|
877
|
+
opts.maxSignatures < 1 ||
|
|
878
|
+
opts.maxSignatures > DKIM_MAX_SIGNATURES_PER_MESSAGE_CEILING) {
|
|
879
|
+
throw new DkimError("dkim/bad-max-signatures",
|
|
880
|
+
"verify: maxSignatures must be an integer in [1, " +
|
|
881
|
+
DKIM_MAX_SIGNATURES_PER_MESSAGE_CEILING + "] (got " + opts.maxSignatures + ")");
|
|
882
|
+
}
|
|
883
|
+
maxSignatures = Math.floor(opts.maxSignatures);
|
|
884
|
+
}
|
|
885
|
+
var verifyOpts = { minRsaBits: opts.minRsaBits };
|
|
886
|
+
|
|
887
|
+
var split = _splitHeadersBody(rfc822);
|
|
888
|
+
var parsedHeaders = _parseHeaders(split.headers);
|
|
889
|
+
var sigHeaders = _findDkimSignatureHeaders(parsedHeaders);
|
|
890
|
+
if (sigHeaders.length === 0) {
|
|
891
|
+
return [{ result: "none", errors: ["no DKIM-Signature headers"] }];
|
|
892
|
+
}
|
|
893
|
+
// When the message carries more signatures than the cap allows,
|
|
894
|
+
// surface a `policy` verdict before any cryptographic work runs.
|
|
895
|
+
// The prior `slice(0, maxSignatures)` shape silently truncated; an
|
|
896
|
+
// operator-visible refusal lets postmasters see DoS attempts in
|
|
897
|
+
// their authentication-results stream.
|
|
898
|
+
if (sigHeaders.length > maxSignatures) {
|
|
899
|
+
if (auditOn) {
|
|
900
|
+
try {
|
|
901
|
+
audit().safeEmit({
|
|
902
|
+
action: "dkim.verify.signature_count_cap",
|
|
903
|
+
outcome: "denied",
|
|
904
|
+
actor: null,
|
|
905
|
+
metadata: {
|
|
906
|
+
sigCount: sigHeaders.length,
|
|
907
|
+
maxSignatures: maxSignatures,
|
|
908
|
+
severity: "warning",
|
|
909
|
+
},
|
|
910
|
+
});
|
|
911
|
+
} catch (_e) { /* drop-silent */ }
|
|
912
|
+
}
|
|
913
|
+
return [{ result: "policy",
|
|
914
|
+
errors: ["DKIM-Signature count " + sigHeaders.length +
|
|
915
|
+
" exceeds maxSignatures=" + maxSignatures +
|
|
916
|
+
" (RFC 6376 §6.1; verifier DoS cap)"] }];
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
var results = [];
|
|
920
|
+
for (var i = 0; i < sigHeaders.length; i += 1) {
|
|
921
|
+
var sigTags = _parseDkimTagList(sigHeaders[i].value);
|
|
922
|
+
var d = sigTags.d;
|
|
923
|
+
var s = sigTags.s;
|
|
924
|
+
var alg = sigTags.a;
|
|
925
|
+
// RFC 6376 §3.5 — v= tag is REQUIRED and MUST be "1". Unrecognized
|
|
926
|
+
// version → permerror per spec; refuse rather than guess at intent.
|
|
927
|
+
if (sigTags.v !== undefined && sigTags.v !== "1") {
|
|
928
|
+
results.push({ d: d || null, s: s || null, alg: alg || null,
|
|
929
|
+
result: "permerror", errors: ["DKIM-Signature v=" + sigTags.v + " unsupported (RFC 6376 §3.5 — only v=1)"] });
|
|
930
|
+
continue;
|
|
931
|
+
}
|
|
932
|
+
// RFC 6376 §3.5 — x= signature expiration, t= signature timestamp.
|
|
933
|
+
// x= MUST be after t= and MUST NOT be in the past. t= sanity:
|
|
934
|
+
// refuse if more than 24h in the future (clock drift between
|
|
935
|
+
// signer + verifier of more than a day is a near-certain bug or
|
|
936
|
+
// attack). Both are in seconds-since-epoch per ABNF.
|
|
937
|
+
var nowSec = Math.floor(Date.now() / C.TIME.seconds(1));
|
|
938
|
+
var clockSkewSec = Math.floor(clockSkewMs / C.TIME.seconds(1));
|
|
939
|
+
if (sigTags.x !== undefined) {
|
|
940
|
+
var expSec = parseInt(sigTags.x, 10);
|
|
941
|
+
if (isFinite(expSec) && expSec + clockSkewSec < nowSec) {
|
|
942
|
+
results.push({ d: d || null, s: s || null, alg: alg || null,
|
|
943
|
+
result: "permerror",
|
|
944
|
+
errors: ["DKIM-Signature x=" + expSec + " has expired (RFC 6376 §3.5)"] });
|
|
945
|
+
continue;
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
if (sigTags.t !== undefined) {
|
|
949
|
+
var tSec = parseInt(sigTags.t, 10);
|
|
950
|
+
// Allow up to 24h future-skew; beyond that, refuse — neither
|
|
951
|
+
// operator clock drift nor delivery latency explains a future-
|
|
952
|
+
// dated signing time of more than a day.
|
|
953
|
+
if (isFinite(tSec) && tSec - (24 * 60 * 60) > nowSec) { // allow:raw-byte-literal — Unix-seconds offset, not bytes / allow:raw-time-literal — 24h future-date sanity ceiling
|
|
954
|
+
results.push({ d: d || null, s: s || null, alg: alg || null,
|
|
955
|
+
result: "permerror",
|
|
956
|
+
errors: ["DKIM-Signature t=" + tSec + " is more than 24h in the future (RFC 6376 §3.5 sanity)"] });
|
|
957
|
+
continue;
|
|
958
|
+
}
|
|
959
|
+
if (sigTags.x !== undefined) {
|
|
960
|
+
var xSec = parseInt(sigTags.x, 10);
|
|
961
|
+
if (isFinite(xSec) && isFinite(tSec) && xSec < tSec) {
|
|
962
|
+
results.push({ d: d || null, s: s || null, alg: alg || null,
|
|
963
|
+
result: "permerror",
|
|
964
|
+
errors: ["DKIM-Signature x= must be after t= (RFC 6376 §3.5)"] });
|
|
965
|
+
continue;
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
if (!d || !s) {
|
|
970
|
+
results.push({ d: d || null, s: s || null, alg: alg || null,
|
|
971
|
+
result: "permerror", errors: ["DKIM-Signature missing d= or s="] });
|
|
972
|
+
continue;
|
|
973
|
+
}
|
|
974
|
+
var keyTags;
|
|
975
|
+
try { keyTags = await _fetchDkimKey(d, s, opts.dnsLookup); }
|
|
976
|
+
catch (e) {
|
|
977
|
+
var verdict = e.code === "dkim/key-lookup-temperror" ? "temperror" : "permerror";
|
|
978
|
+
results.push({ d: d, s: s, alg: alg, result: verdict, errors: [e.message] });
|
|
979
|
+
continue;
|
|
980
|
+
}
|
|
981
|
+
if (keyTags.p === "") {
|
|
982
|
+
// RFC 6376 §3.6.1 — empty p= explicitly revokes the key. Verdict
|
|
983
|
+
// is "fail" (not "permerror") — the signature is well-formed but
|
|
984
|
+
// the key authority intentionally withdrew it.
|
|
985
|
+
results.push({ d: d, s: s, alg: alg, result: "fail",
|
|
986
|
+
errors: ["DKIM key revoked (empty p= per RFC 6376 §3.6.1)"] });
|
|
987
|
+
continue;
|
|
988
|
+
}
|
|
989
|
+
if (!keyTags.p) {
|
|
990
|
+
results.push({ d: d, s: s, alg: alg, result: "permerror",
|
|
991
|
+
errors: ["DKIM key record missing p="] });
|
|
992
|
+
continue;
|
|
993
|
+
}
|
|
994
|
+
// RFC 6376 §3.6.1 — k= tag declares the key's algorithm family.
|
|
995
|
+
// Default is "rsa" when absent. If the key's k= disagrees with the
|
|
996
|
+
// signature's a= family, the operator who published the key intends
|
|
997
|
+
// a different algorithm; refuse rather than guess.
|
|
998
|
+
if (keyTags.k !== undefined) {
|
|
999
|
+
var kFamily = String(keyTags.k).toLowerCase();
|
|
1000
|
+
var sigFamily = String(alg || "").toLowerCase().split("-")[0];
|
|
1001
|
+
if (kFamily !== sigFamily) {
|
|
1002
|
+
results.push({ d: d, s: s, alg: alg, result: "permerror",
|
|
1003
|
+
errors: ["DKIM key k=" + kFamily + " does not match signature a=" + alg + " (RFC 6376 §3.6.1)"] });
|
|
1004
|
+
continue;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
var rv = _verifySingleSignature(rfc822, parsedHeaders, sigHeaders[i], keyTags, sigTags, verifyOpts);
|
|
1008
|
+
results.push(Object.assign({ d: d, s: s, alg: alg }, rv));
|
|
1009
|
+
}
|
|
1010
|
+
return results;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
function dualSigner(opts) {
|
|
1014
|
+
if (!opts || !opts.rsa || !opts.eddsa) {
|
|
1015
|
+
throw new DkimError("dkim/dual-signer-missing",
|
|
1016
|
+
"dualSigner requires both opts.rsa and opts.eddsa");
|
|
1017
|
+
}
|
|
1018
|
+
if (!opts.domain) {
|
|
1019
|
+
throw new DkimError("dkim/dual-signer-missing-domain",
|
|
1020
|
+
"dualSigner requires opts.domain");
|
|
1021
|
+
}
|
|
1022
|
+
function _merge(base, alg, override) {
|
|
1023
|
+
return Object.assign({}, base, { algorithm: alg }, override);
|
|
1024
|
+
}
|
|
1025
|
+
var sharedBase = {};
|
|
1026
|
+
var commonKeys = ["domain", "headersToSign", "canonicalization", "audit"];
|
|
1027
|
+
for (var i = 0; i < commonKeys.length; i += 1) {
|
|
1028
|
+
if (opts[commonKeys[i]] !== undefined) sharedBase[commonKeys[i]] = opts[commonKeys[i]];
|
|
1029
|
+
}
|
|
1030
|
+
var rsaSigner = create(_merge(sharedBase, "rsa-sha256", opts.rsa));
|
|
1031
|
+
var eddsaSigner = create(_merge(sharedBase, "ed25519-sha256", opts.eddsa));
|
|
1032
|
+
return {
|
|
1033
|
+
sign: function (rfc822) {
|
|
1034
|
+
var afterRsa = rsaSigner.sign(rfc822);
|
|
1035
|
+
return eddsaSigner.sign(afterRsa);
|
|
1036
|
+
},
|
|
1037
|
+
rsa: rsaSigner,
|
|
1038
|
+
eddsa: eddsaSigner,
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
// Test-only exports for unit testing the canonicalization primitives
|
|
1043
|
+
// directly without going through a full sign() round.
|
|
1044
|
+
/**
|
|
1045
|
+
* @primitive b.mail.dkim.bootstrap
|
|
1046
|
+
* @signature b.mail.dkim.bootstrap(opts)
|
|
1047
|
+
* @since 0.9.48
|
|
1048
|
+
* @status stable
|
|
1049
|
+
* @related b.vault.sealPemFile
|
|
1050
|
+
*
|
|
1051
|
+
* Bootstrap a DKIM keypair + DNS TXT record + ready-to-use signer.
|
|
1052
|
+
* Operators deploying outbound mail (b.mail.send, b.mail.server.submission)
|
|
1053
|
+
* need three things in place: (1) a private signing key, (2) the matching
|
|
1054
|
+
* public key published as a DNS TXT record under
|
|
1055
|
+
* `<selector>._domainkey.<domain>`, (3) a `b.mail.dkim.create(...)` handle
|
|
1056
|
+
* wired into the outbound agent. Pre-this-primitive every consumer
|
|
1057
|
+
* reinvented the keypair-mint + DNS-record-serialize plumbing; this
|
|
1058
|
+
* primitive owns it.
|
|
1059
|
+
*
|
|
1060
|
+
* Default algorithm is `ed25519-sha256` (RFC 8463): smaller DNS record,
|
|
1061
|
+
* faster signing, modern crypto. Operators with receivers that don't yet
|
|
1062
|
+
* support Ed25519 pass `algorithm: "rsa-sha256"` for RFC 6376 (defaults
|
|
1063
|
+
* to 2048-bit RSA per RFC 8301 §3.1 guidance — opt up with `rsaBits`).
|
|
1064
|
+
* Passing `algorithm: "dual"` mints BOTH keypairs and returns a
|
|
1065
|
+
* `b.mail.dkim.dualSigner`-shaped signer that emits two DKIM-Signature
|
|
1066
|
+
* headers (one per alg) for max receiver compat per RFC 8463 §3 dual-
|
|
1067
|
+
* signing pattern.
|
|
1068
|
+
*
|
|
1069
|
+
* @opts
|
|
1070
|
+
* domain: string, // required — RFC 5321 domain
|
|
1071
|
+
* selector: string, // required — RFC 6376 §3.1 selector (the `s1` in s1._domainkey.example.com)
|
|
1072
|
+
* algorithm: "ed25519-sha256" | "rsa-sha256" | "dual",
|
|
1073
|
+
* // default: "ed25519-sha256"
|
|
1074
|
+
* rsaBits: number, // RSA-only; default 2048; refused below 1024 (RFC 8301 §3.1)
|
|
1075
|
+
* rsaSelector: string, // dual-only; selector for the RSA key (defaults to selector + "-rsa")
|
|
1076
|
+
*
|
|
1077
|
+
* @example
|
|
1078
|
+
* var dkim = b.mail.dkim.bootstrap({ domain: "example.com", selector: "s1" });
|
|
1079
|
+
* // → {
|
|
1080
|
+
* // algorithm: "ed25519-sha256",
|
|
1081
|
+
* // domain: "example.com",
|
|
1082
|
+
* // selector: "s1",
|
|
1083
|
+
* // privateKeyPem,
|
|
1084
|
+
* // publicKeyPem,
|
|
1085
|
+
* // dnsName: "s1._domainkey.example.com",
|
|
1086
|
+
* // dnsTxtValue: "v=DKIM1; k=ed25519; p=MCowBQYDK2Vw...",
|
|
1087
|
+
* // dnsRecord: 's1._domainkey.example.com. IN TXT ("v=DKIM1; k=ed25519; p=MCo...")',
|
|
1088
|
+
* // signer: fn(headersToSign?, canonicalization?) → signer,
|
|
1089
|
+
* // }
|
|
1090
|
+
*
|
|
1091
|
+
* // Operator seals the private key via the vault then wires the signer:
|
|
1092
|
+
* var sealedPath = b.vault.sealPemFile({ source: "/var/lib/blamejs/dkim.key", destination: "/var/lib/blamejs/dkim.key.sealed" });
|
|
1093
|
+
* var signer = dkim.signer(); // uses dkim.privateKeyPem in-memory
|
|
1094
|
+
*
|
|
1095
|
+
* // Dual signing — RSA + Ed25519 for max receiver compatibility:
|
|
1096
|
+
* var dkim2 = b.mail.dkim.bootstrap({ domain: "example.com", selector: "s1", algorithm: "dual" });
|
|
1097
|
+
* // dkim2.signer() returns a dualSigner emitting both DKIM-Signature headers.
|
|
1098
|
+
*/
|
|
1099
|
+
function bootstrap(opts) {
|
|
1100
|
+
validateOpts.requireObject(opts, "b.mail.dkim.bootstrap", DkimError, "dkim/bad-opts");
|
|
1101
|
+
validateOpts.requireNonEmptyString(opts.domain, "b.mail.dkim.bootstrap: opts.domain",
|
|
1102
|
+
DkimError, "dkim/bad-domain");
|
|
1103
|
+
validateOpts.requireNonEmptyString(opts.selector, "b.mail.dkim.bootstrap: opts.selector",
|
|
1104
|
+
DkimError, "dkim/bad-selector");
|
|
1105
|
+
var alg = opts.algorithm || "ed25519-sha256";
|
|
1106
|
+
if (alg !== "ed25519-sha256" && alg !== "rsa-sha256" && alg !== "dual") {
|
|
1107
|
+
throw new DkimError("dkim/bad-algorithm",
|
|
1108
|
+
"b.mail.dkim.bootstrap: opts.algorithm must be 'ed25519-sha256' | 'rsa-sha256' | 'dual'");
|
|
1109
|
+
}
|
|
1110
|
+
// DKIM selector + domain shape: RFC 6376 §3.1 — selector is a
|
|
1111
|
+
// sub-domain label (no leading/trailing dot; no whitespace; no
|
|
1112
|
+
// wildcards). domain is a normal DNS hostname.
|
|
1113
|
+
if (!/^[A-Za-z0-9](?:[A-Za-z0-9._-]{0,62}[A-Za-z0-9])?$/.test(opts.selector)) { // allow:regex-no-length-cap — anchored + bounded repeat
|
|
1114
|
+
throw new DkimError("dkim/bad-selector",
|
|
1115
|
+
"b.mail.dkim.bootstrap: opts.selector must match RFC 6376 §3.1 selector shape");
|
|
1116
|
+
}
|
|
1117
|
+
if (!/^[A-Za-z0-9](?:[A-Za-z0-9.-]{0,253}[A-Za-z0-9])?$/.test(opts.domain)) { // allow:regex-no-length-cap — anchored + bounded repeat
|
|
1118
|
+
throw new DkimError("dkim/bad-domain",
|
|
1119
|
+
"b.mail.dkim.bootstrap: opts.domain must be a DNS-hostname-shaped string");
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
if (alg === "ed25519-sha256") {
|
|
1123
|
+
return _bootstrapSingle("ed25519-sha256", opts.domain, opts.selector);
|
|
1124
|
+
}
|
|
1125
|
+
if (alg === "rsa-sha256") {
|
|
1126
|
+
var bits = opts.rsaBits === undefined ? RSA_MIN_BITS : opts.rsaBits;
|
|
1127
|
+
if (typeof bits !== "number" || !isFinite(bits) || bits < RSA_LEGACY_MIN_BITS || (bits % 1) !== 0) {
|
|
1128
|
+
throw new DkimError("dkim/bad-rsa-bits",
|
|
1129
|
+
"b.mail.dkim.bootstrap: opts.rsaBits must be an integer >= " + RSA_LEGACY_MIN_BITS +
|
|
1130
|
+
" (RFC 8301 §3.1 floor; default " + RSA_MIN_BITS +
|
|
1131
|
+
" per RFC 8301bis + 2024 bulk-sender)");
|
|
1132
|
+
}
|
|
1133
|
+
return _bootstrapSingle("rsa-sha256", opts.domain, opts.selector, bits);
|
|
1134
|
+
}
|
|
1135
|
+
// dual
|
|
1136
|
+
var rsaSelector = opts.rsaSelector || (opts.selector + "-rsa");
|
|
1137
|
+
if (!/^[A-Za-z0-9](?:[A-Za-z0-9._-]{0,62}[A-Za-z0-9])?$/.test(rsaSelector)) { // allow:regex-no-length-cap — anchored + bounded repeat
|
|
1138
|
+
throw new DkimError("dkim/bad-selector",
|
|
1139
|
+
"b.mail.dkim.bootstrap: opts.rsaSelector must match RFC 6376 §3.1 selector shape");
|
|
1140
|
+
}
|
|
1141
|
+
var rsaBits = opts.rsaBits === undefined ? RSA_MIN_BITS : opts.rsaBits;
|
|
1142
|
+
if (typeof rsaBits !== "number" || !isFinite(rsaBits) || rsaBits < RSA_LEGACY_MIN_BITS || (rsaBits % 1) !== 0) {
|
|
1143
|
+
throw new DkimError("dkim/bad-rsa-bits",
|
|
1144
|
+
"b.mail.dkim.bootstrap: opts.rsaBits must be an integer >= " + RSA_LEGACY_MIN_BITS);
|
|
1145
|
+
}
|
|
1146
|
+
var ed = _bootstrapSingle("ed25519-sha256", opts.domain, opts.selector);
|
|
1147
|
+
var rsa = _bootstrapSingle("rsa-sha256", opts.domain, rsaSelector, rsaBits);
|
|
1148
|
+
return {
|
|
1149
|
+
algorithm: "dual",
|
|
1150
|
+
domain: opts.domain,
|
|
1151
|
+
ed25519: ed,
|
|
1152
|
+
rsa: rsa,
|
|
1153
|
+
signer: function (signOpts) {
|
|
1154
|
+
signOpts = signOpts || {};
|
|
1155
|
+
return dualSigner({
|
|
1156
|
+
domain: opts.domain,
|
|
1157
|
+
headersToSign: signOpts.headersToSign,
|
|
1158
|
+
canonicalization: signOpts.canonicalization,
|
|
1159
|
+
eddsa: {
|
|
1160
|
+
selector: opts.selector,
|
|
1161
|
+
privateKey: ed.privateKeyPem,
|
|
1162
|
+
},
|
|
1163
|
+
rsa: {
|
|
1164
|
+
selector: rsaSelector,
|
|
1165
|
+
privateKey: rsa.privateKeyPem,
|
|
1166
|
+
},
|
|
1167
|
+
});
|
|
1168
|
+
},
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
function _bootstrapSingle(algorithm, domain, selector, rsaBits) {
|
|
1173
|
+
var keyPair;
|
|
1174
|
+
var k; // DNS TXT `k=` tag value
|
|
1175
|
+
if (algorithm === "ed25519-sha256") {
|
|
1176
|
+
keyPair = nodeCrypto.generateKeyPairSync("ed25519", {
|
|
1177
|
+
publicKeyEncoding: { type: "spki", format: "der" },
|
|
1178
|
+
privateKeyEncoding: { type: "pkcs8", format: "pem" },
|
|
1179
|
+
});
|
|
1180
|
+
k = "ed25519";
|
|
1181
|
+
} else {
|
|
1182
|
+
keyPair = nodeCrypto.generateKeyPairSync("rsa", {
|
|
1183
|
+
modulusLength: rsaBits,
|
|
1184
|
+
publicKeyEncoding: { type: "spki", format: "der" },
|
|
1185
|
+
privateKeyEncoding: { type: "pkcs8", format: "pem" },
|
|
1186
|
+
});
|
|
1187
|
+
k = "rsa";
|
|
1188
|
+
}
|
|
1189
|
+
var publicKeyPemObj = nodeCrypto.createPublicKey({ key: keyPair.publicKey, type: "spki", format: "der" });
|
|
1190
|
+
var publicKeyPem = publicKeyPemObj.export({ type: "spki", format: "pem" });
|
|
1191
|
+
var pBase64 = Buffer.from(keyPair.publicKey).toString("base64");
|
|
1192
|
+
var dnsName = selector + "._domainkey." + domain;
|
|
1193
|
+
// RFC 6376 §3.6.1 record syntax: v=DKIM1; k=<alg>; p=<base64>
|
|
1194
|
+
// The optional t/s/g/n/h/k tags omitted (operator can re-edit
|
|
1195
|
+
// the dnsTxtValue before publishing if they need policy flags).
|
|
1196
|
+
var dnsTxtValue = "v=DKIM1; k=" + k + "; p=" + pBase64;
|
|
1197
|
+
// BIND/Unbound zone-file shape: name TTL? IN TXT ("...").
|
|
1198
|
+
// TXT values > 255 octets must be split into multiple quoted
|
|
1199
|
+
// strings per RFC 1035 §3.3.14 — long RSA records will trip this.
|
|
1200
|
+
var dnsRecord = dnsName + ". IN TXT (" + _wrapDnsTxt(dnsTxtValue) + ")";
|
|
1201
|
+
|
|
1202
|
+
return {
|
|
1203
|
+
algorithm: algorithm,
|
|
1204
|
+
domain: domain,
|
|
1205
|
+
selector: selector,
|
|
1206
|
+
privateKeyPem: keyPair.privateKey,
|
|
1207
|
+
publicKeyPem: publicKeyPem,
|
|
1208
|
+
dnsName: dnsName,
|
|
1209
|
+
dnsTxtValue: dnsTxtValue,
|
|
1210
|
+
dnsRecord: dnsRecord,
|
|
1211
|
+
signer: function (signOpts) {
|
|
1212
|
+
signOpts = signOpts || {};
|
|
1213
|
+
return create({
|
|
1214
|
+
domain: domain,
|
|
1215
|
+
selector: selector,
|
|
1216
|
+
privateKey: keyPair.privateKey,
|
|
1217
|
+
algorithm: algorithm,
|
|
1218
|
+
headersToSign: signOpts.headersToSign,
|
|
1219
|
+
canonicalization: signOpts.canonicalization,
|
|
1220
|
+
});
|
|
1221
|
+
},
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
// RFC 1035 §3.3.14 — TXT records carry one or more <character-string>s
|
|
1226
|
+
// each capped at 255 octets. Long RSA p= values are split into multiple
|
|
1227
|
+
// quoted strings so the zone file is valid.
|
|
1228
|
+
function _wrapDnsTxt(value) {
|
|
1229
|
+
if (value.length <= 255) return '"' + value + '"'; // allow:raw-byte-literal — RFC 1035 character-string cap
|
|
1230
|
+
var parts = [];
|
|
1231
|
+
for (var i = 0; i < value.length; i += 255) parts.push('"' + value.slice(i, i + 255) + '"'); // allow:raw-byte-literal — RFC 1035 character-string cap
|
|
1232
|
+
return parts.join(" ");
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
module.exports = {
|
|
1236
|
+
create: create,
|
|
1237
|
+
bootstrap: bootstrap,
|
|
1238
|
+
verify: verify,
|
|
1239
|
+
_resetDkimKeyCacheForTest: _resetDkimKeyCacheForTest,
|
|
1240
|
+
dualSigner: dualSigner,
|
|
1241
|
+
DkimError: DkimError,
|
|
1242
|
+
RSA_MIN_BITS: RSA_MIN_BITS,
|
|
1243
|
+
RSA_LEGACY_MIN_BITS: RSA_LEGACY_MIN_BITS,
|
|
1244
|
+
DKIM_MAX_SIGNATURES_PER_MESSAGE: DKIM_MAX_SIGNATURES_PER_MESSAGE,
|
|
1245
|
+
DKIM_CLOCK_SKEW_MS_MAX: DKIM_CLOCK_SKEW_MS_MAX,
|
|
1246
|
+
_canonHeaderRelaxedForTest: _canonHeaderRelaxed,
|
|
1247
|
+
_canonBodyRelaxedForTest: _canonBodyRelaxed,
|
|
1248
|
+
_canonBodySimpleForTest: _canonBodySimple,
|
|
1249
|
+
_stripBTagValueForTest: _stripBTagValue,
|
|
1250
|
+
};
|