@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,1503 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @module b.metrics
|
|
4
|
+
* @nav Observability
|
|
5
|
+
* @title Metrics
|
|
6
|
+
*
|
|
7
|
+
* @intro
|
|
8
|
+
* Counter / gauge / histogram primitives in Prometheus 0.0.4 text
|
|
9
|
+
* format with OTLP-friendly labels, plus framework auto-instrumentation
|
|
10
|
+
* wired into audit / vault / queue hot paths.
|
|
11
|
+
*
|
|
12
|
+
* `b.metrics.create()` returns a registry — call `counter(name)` /
|
|
13
|
+
* `gauge(name)` / `histogram(name)` to register typed metrics, then
|
|
14
|
+
* `requestMiddleware()` for per-request counter+latency, and
|
|
15
|
+
* `expositionHandler()` for the `/metrics` scrape route. Every metric
|
|
16
|
+
* carries a per-instance `labelCardinalityCap` (default 10,000) — when
|
|
17
|
+
* the next label combination would push past the cap the increment
|
|
18
|
+
* drops and a single warning logs, so a runaway label (request-id,
|
|
19
|
+
* raw URL with query string, per-user dimension) can't OOM the
|
|
20
|
+
* process.
|
|
21
|
+
*
|
|
22
|
+
* Framework modules call `metrics.tap("audit.record", value, labels)`
|
|
23
|
+
* at hot paths. Until a registry is active the call is a zero-cost
|
|
24
|
+
* no-op; once `create()` runs, taps flow into pre-registered
|
|
25
|
+
* counters / gauges (`framework_audit_events_total`,
|
|
26
|
+
* `framework_vault_seal_total`, `framework_queue_depth`,
|
|
27
|
+
* `framework_jobs_inflight`, `framework_errors_total`,
|
|
28
|
+
* `framework_http_requests_total`,
|
|
29
|
+
* `framework_http_request_duration_seconds`).
|
|
30
|
+
*
|
|
31
|
+
* Best-practice route labels are the route TEMPLATE
|
|
32
|
+
* (`/users/:id`), not the actual path — `requestMiddleware` reads
|
|
33
|
+
* `req.routePattern` when the matcher set one and falls back to the
|
|
34
|
+
* query-stripped URL otherwise.
|
|
35
|
+
*
|
|
36
|
+
* @card
|
|
37
|
+
* Counter / gauge / histogram primitives in Prometheus 0.0.4 text format with OTLP-friendly labels, plus framework auto-instrumentation wired into audit / vault / queue hot paths.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
var C = require("./constants");
|
|
41
|
+
var canonicalJson = require("./canonical-json");
|
|
42
|
+
var nodeFs = require("node:fs");
|
|
43
|
+
var atomicFile = require("./atomic-file");
|
|
44
|
+
var safeJson = require("./safe-json");
|
|
45
|
+
var { defineClass } = require("./framework-error");
|
|
46
|
+
var { boot } = require("./log");
|
|
47
|
+
var numericBounds = require("./numeric-bounds");
|
|
48
|
+
var { resolveRoute, captureResponseStatus, HTTP_STATUS } = require("./request-helpers");
|
|
49
|
+
var validateOpts = require("./validate-opts");
|
|
50
|
+
|
|
51
|
+
var MetricsError = defineClass("MetricsError", { alwaysPermanent: true });
|
|
52
|
+
var log = boot("metrics");
|
|
53
|
+
|
|
54
|
+
// Default histogram buckets for HTTP latency in seconds.
|
|
55
|
+
var DEFAULT_HTTP_BUCKETS = Object.freeze([
|
|
56
|
+
0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10,
|
|
57
|
+
]);
|
|
58
|
+
|
|
59
|
+
var DEFAULT_CARDINALITY_CAP = C.BYTES.bytes(10000);
|
|
60
|
+
// Bound metric / label names before regex test — DoS shape if an
|
|
61
|
+
// operator passed a multi-megabyte string. Prometheus exposition
|
|
62
|
+
// recommends short ascii names; 200 is a generous ceiling.
|
|
63
|
+
var MAX_METRIC_NAME_LEN = 200;
|
|
64
|
+
var METRIC_NAME_RE = /^[a-zA-Z_:][a-zA-Z0-9_:]*$/;
|
|
65
|
+
var LABEL_NAME_RE = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
66
|
+
|
|
67
|
+
// ---- tap (global no-op stub for framework module taps) ----
|
|
68
|
+
//
|
|
69
|
+
// Framework modules call metrics.tap("name", value, labels) at hot
|
|
70
|
+
// paths. Until a registry is active, calls are no-ops (zero cost).
|
|
71
|
+
// metrics.create() replaces _activeTap with the registry-driven path,
|
|
72
|
+
// flowing taps into pre-registered counters / gauges / histograms.
|
|
73
|
+
//
|
|
74
|
+
// Drop-silent by design: the wrapping try/catch is intentional. tap is
|
|
75
|
+
// called from request hot paths where throwing on a misnamed metric
|
|
76
|
+
// (or a label whose value coerced unexpectedly) would crash the
|
|
77
|
+
// request that triggered it. The metric-registration path (counter /
|
|
78
|
+
// gauge / histogram) DOES throw on bad name/label-name regex — that's
|
|
79
|
+
// a config-time call where operators want fast failure; the runtime
|
|
80
|
+
// tap() is the drop-silent boundary.
|
|
81
|
+
|
|
82
|
+
var _activeTap = null;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @primitive b.metrics.tap
|
|
86
|
+
* @signature b.metrics.tap(name, value, labels)
|
|
87
|
+
* @since 0.4.0
|
|
88
|
+
* @related b.metrics.create, b.observability.event
|
|
89
|
+
*
|
|
90
|
+
* Framework hot-path tap. Modules call `tap("audit.record", 1,
|
|
91
|
+
* { action, outcome })` without importing a registry. Until
|
|
92
|
+
* `b.metrics.create()` runs the call is a zero-cost no-op; afterwards
|
|
93
|
+
* the active registry routes the tap into pre-registered counters and
|
|
94
|
+
* gauges. Drop-silent on internal throws so a misconfigured metric
|
|
95
|
+
* cannot crash the request that triggered the tap.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* // Module-level — no registry yet, no-op:
|
|
99
|
+
* b.metrics.tap("audit.record", 1, { action: "auth.login", outcome: "success" });
|
|
100
|
+
*
|
|
101
|
+
* // After registry creation, the same tap call increments
|
|
102
|
+
* // framework_audit_events_total{action="auth.login", outcome="success"}.
|
|
103
|
+
* var registry = b.metrics.create({ namespace: "myapp" });
|
|
104
|
+
* b.metrics.tap("audit.record", 1, { action: "auth.login", outcome: "success" });
|
|
105
|
+
*/
|
|
106
|
+
function tap(name, value, labels) {
|
|
107
|
+
if (_activeTap === null) return;
|
|
108
|
+
try { _activeTap(name, value, labels); }
|
|
109
|
+
catch (_e) { /* tap path errors must not break callers */ }
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ---- helpers ----
|
|
113
|
+
|
|
114
|
+
function _validateMetricName(name) {
|
|
115
|
+
if (typeof name !== "string" || name.length > MAX_METRIC_NAME_LEN ||
|
|
116
|
+
!METRIC_NAME_RE.test(name)) {
|
|
117
|
+
throw new MetricsError("metrics/bad-name",
|
|
118
|
+
"metric name '" + name + "' must match " + METRIC_NAME_RE +
|
|
119
|
+
" (max " + MAX_METRIC_NAME_LEN + " chars)");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function _validateLabelName(name) {
|
|
123
|
+
if (typeof name !== "string" || name.length > MAX_METRIC_NAME_LEN ||
|
|
124
|
+
!LABEL_NAME_RE.test(name)) {
|
|
125
|
+
throw new MetricsError("metrics/bad-label",
|
|
126
|
+
"label name '" + name + "' must match " + LABEL_NAME_RE +
|
|
127
|
+
" (max " + MAX_METRIC_NAME_LEN + " chars)");
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Counter / gauge / histogram methods all accept (callLabels, value) but
|
|
131
|
+
// degrade to (value) when no labels are passed. Centralized here so we
|
|
132
|
+
// don't repeat the swap-and-coerce dance four times.
|
|
133
|
+
//
|
|
134
|
+
// _normalizeLabelArg(arg1, arg2, defaultValue) → { labels, value }
|
|
135
|
+
function _normalizeLabelArg(callLabels, value, defaultValue) {
|
|
136
|
+
if (typeof callLabels === "number") {
|
|
137
|
+
return { labels: null, value: callLabels };
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
labels: callLabels,
|
|
141
|
+
value: typeof value === "number" ? value : defaultValue,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// CRYPTO-18 — credential-shape detector. Operators routinely tap their
|
|
146
|
+
// own observability with `{ token: req.headers.authorization }` or
|
|
147
|
+
// `{ apiKey: req.headers["x-api-key"] }`, which then leak through the
|
|
148
|
+
// /metrics scrape surface to any reader of the metrics endpoint. The
|
|
149
|
+
// detector refuses (replaces with `[REDACTED-CREDENTIAL]`) any value
|
|
150
|
+
// matching well-known credential shapes:
|
|
151
|
+
//
|
|
152
|
+
// - "Bearer <token>" / "Basic <base64>" / "Negotiate <token>" — RFC
|
|
153
|
+
// 6750 / 7617 / 4559 wire forms
|
|
154
|
+
// - "Token <opaque>" — common GitLab / Trello convention
|
|
155
|
+
// - "sk-" / "pk-" / "rk-" prefixes — Stripe, OpenAI, modern issuers
|
|
156
|
+
// - "ghp_" / "ghs_" / "github_pat_" — GitHub
|
|
157
|
+
// - JWT shape: header.payload.signature (each segment base64url with
|
|
158
|
+
// length >= 8)
|
|
159
|
+
// - High-entropy long strings (>= 40 chars, hex / base64-shape) are
|
|
160
|
+
// a heuristic fallback so unknown-issuer tokens still get caught
|
|
161
|
+
var _CRED_PREFIX_RE = /^(?:Bearer|Basic|Negotiate|Token|Digest)\s+\S/i;
|
|
162
|
+
var _CRED_ISSUER_RE = /^(?:sk-|pk-|rk-|ghp_|ghs_|gho_|github_pat_|xoxb-|xoxa-|xoxp-|xoxr-|xapp-)/;
|
|
163
|
+
var _CRED_JWT_RE = /^[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}$/; // allow:raw-byte-literal — JWT segment min length
|
|
164
|
+
var _CRED_ENTROPY_RE = /^[A-Za-z0-9_+/=-]{40,}$/; // allow:raw-byte-literal — high-entropy length floor
|
|
165
|
+
|
|
166
|
+
// CRED_MAX_SCAN — upper bound on the byte slice the credential
|
|
167
|
+
// detector inspects. Operator-supplied label values longer than this
|
|
168
|
+
// are still REDACTED (a 4 KiB token that opens with a Bearer prefix is
|
|
169
|
+
// still a credential), but the regex tests run on the prefix slice so
|
|
170
|
+
// a 1 GB string can't ReDoS the scanner. Counter cardinality stays
|
|
171
|
+
// stable: the same long string always maps to the same prefix slice.
|
|
172
|
+
var CRED_MAX_SCAN = 256; // allow:raw-byte-literal — prefix-scan length cap
|
|
173
|
+
|
|
174
|
+
function _looksLikeCredential(str) {
|
|
175
|
+
if (typeof str !== "string") return false;
|
|
176
|
+
if (str.length < 8) return false; // allow:raw-byte-literal — minimum credential length floor
|
|
177
|
+
// Clamp to the prefix slice so a hostile label value can't push the
|
|
178
|
+
// regex into superlinear time. All four credential shapes have
|
|
179
|
+
// signature in the first ~256 bytes; Stripe / GitHub / OpenAI tokens
|
|
180
|
+
// are <64 bytes, JWTs are typically <2 KiB but the header + first
|
|
181
|
+
// payload segment fit in the prefix.
|
|
182
|
+
var clamped = str.length > CRED_MAX_SCAN ? str.slice(0, CRED_MAX_SCAN) : str;
|
|
183
|
+
// CRED_MIN_LEN — credential shapes shorter than 8 chars don't carry
|
|
184
|
+
// enough entropy to be real tokens; hoisted to a named constant so
|
|
185
|
+
// every test() has its length floor visible at the call site
|
|
186
|
+
// (testFormatValidatorLengthCap convention).
|
|
187
|
+
var CRED_MIN_LEN = 8; // allow:raw-byte-literal — minimum credential length floor
|
|
188
|
+
if (clamped.length >= CRED_MIN_LEN && _CRED_PREFIX_RE.test(clamped)) return true;
|
|
189
|
+
if (clamped.length >= CRED_MIN_LEN && _CRED_ISSUER_RE.test(clamped)) return true;
|
|
190
|
+
if (clamped.length >= CRED_MIN_LEN && _CRED_JWT_RE.test(clamped)) return true;
|
|
191
|
+
if (clamped.length >= CRED_MIN_LEN && _CRED_ENTROPY_RE.test(clamped)) return true;
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function _validateLabelValue(value) {
|
|
196
|
+
// Prometheus exposition: label values are quoted strings; backslash,
|
|
197
|
+
// newline, double-quote get escaped at serialize time. Coerce here so
|
|
198
|
+
// counters indexed by various input types still work.
|
|
199
|
+
if (value === null || value === undefined) return "";
|
|
200
|
+
var coerced = String(value);
|
|
201
|
+
// CRYPTO-18 — credential-shape detector. Operators who tap their
|
|
202
|
+
// observability with raw header values leak bearer tokens / API
|
|
203
|
+
// keys through /metrics to every scrape reader. Refuse the value
|
|
204
|
+
// and surface a redaction marker so the metric still labels (so
|
|
205
|
+
// counter cardinality doesn't collapse to a single empty-string
|
|
206
|
+
// bucket) but the bytes themselves never reach the scrape stream.
|
|
207
|
+
if (_looksLikeCredential(coerced)) return "[REDACTED-CREDENTIAL]";
|
|
208
|
+
return coerced;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Serialize a labels object to a canonical Map key. Routed through
|
|
212
|
+
// canonical-json so the framework has one canonical-sort source of
|
|
213
|
+
// truth for sorted-keys serialization (avoiding the silent-data-loss
|
|
214
|
+
// class on Date / Buffer / Map / Set / BigInt values).
|
|
215
|
+
function _labelsKey(labels) {
|
|
216
|
+
if (!labels) return "";
|
|
217
|
+
// Coerce values to strings first so canonical-json's primitive
|
|
218
|
+
// serialization matches the Prometheus wire format.
|
|
219
|
+
var coerced = {};
|
|
220
|
+
var keys = Object.keys(labels);
|
|
221
|
+
for (var i = 0; i < keys.length; i++) {
|
|
222
|
+
coerced[keys[i]] = _validateLabelValue(labels[keys[i]]);
|
|
223
|
+
}
|
|
224
|
+
return canonicalJson.stringify(coerced);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Escape a label value per the Prometheus exposition format.
|
|
228
|
+
function _escapeLabelValue(v) {
|
|
229
|
+
return String(v).replace(/\\/g, "\\\\").replace(/\n/g, "\\n").replace(/"/g, "\\\"");
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Wire-format renderer for Prometheus exposition. Determinism is
|
|
233
|
+
// shared with _labelsKey: both walk keys in lexicographic order via
|
|
234
|
+
// the same _sortedLabelKeys helper, so the canonical-sort source of
|
|
235
|
+
// truth is one helper instead of two duplicated walks.
|
|
236
|
+
function _renderLabels(labelObj) {
|
|
237
|
+
if (!labelObj) return "";
|
|
238
|
+
var sortedKeys = _sortedLabelKeys(labelObj);
|
|
239
|
+
if (sortedKeys.length === 0) return "";
|
|
240
|
+
var parts = [];
|
|
241
|
+
for (var k = 0; k < sortedKeys.length; k++) {
|
|
242
|
+
parts.push(sortedKeys[k] + '="' + _escapeLabelValue(labelObj[sortedKeys[k]]) + '"');
|
|
243
|
+
}
|
|
244
|
+
return "{" + parts.join(",") + "}";
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Single canonical-sort source of truth for label keys. Both
|
|
248
|
+
// _labelsKey (Map key) and _renderLabels (Prometheus exposition)
|
|
249
|
+
// route through here so the framework has one walk shape.
|
|
250
|
+
function _sortedLabelKeys(labelObj) {
|
|
251
|
+
var keys = Object.keys(labelObj);
|
|
252
|
+
keys.sort();
|
|
253
|
+
return keys;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Combine default + per-call labels, validating against the metric's
|
|
257
|
+
// declared labelNames. Throws if a label name isn't declared.
|
|
258
|
+
function _resolveLabels(defaultLabels, declaredNames, callLabels) {
|
|
259
|
+
var out = {};
|
|
260
|
+
if (defaultLabels) {
|
|
261
|
+
var dk = Object.keys(defaultLabels);
|
|
262
|
+
for (var i = 0; i < dk.length; i++) out[dk[i]] = defaultLabels[dk[i]];
|
|
263
|
+
}
|
|
264
|
+
if (callLabels) {
|
|
265
|
+
var ck = Object.keys(callLabels);
|
|
266
|
+
for (var j = 0; j < ck.length; j++) {
|
|
267
|
+
var k = ck[j];
|
|
268
|
+
if (declaredNames.indexOf(k) === -1 && !(defaultLabels && Object.prototype.hasOwnProperty.call(defaultLabels, k))) {
|
|
269
|
+
throw new MetricsError("metrics/undeclared-label",
|
|
270
|
+
"label '" + k + "' not declared in labelNames " + JSON.stringify(declaredNames));
|
|
271
|
+
}
|
|
272
|
+
out[k] = callLabels[k];
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
// Verify all declared labels are present.
|
|
276
|
+
for (var n = 0; n < declaredNames.length; n++) {
|
|
277
|
+
if (!Object.prototype.hasOwnProperty.call(out, declaredNames[n])) {
|
|
278
|
+
throw new MetricsError("metrics/missing-label",
|
|
279
|
+
"label '" + declaredNames[n] + "' is required (declared in labelNames)");
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return out;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// ---- registry factory ----
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* @primitive b.metrics.create
|
|
289
|
+
* @signature b.metrics.create(opts)
|
|
290
|
+
* @since 0.4.0
|
|
291
|
+
* @status stable
|
|
292
|
+
* @related b.metrics.tap, b.observability.event, b.tracing.create
|
|
293
|
+
*
|
|
294
|
+
* Build a Prometheus-format metrics registry. The returned registry
|
|
295
|
+
* exposes `counter` / `gauge` / `histogram` factories,
|
|
296
|
+
* `requestMiddleware()` for per-route auto-instrumentation,
|
|
297
|
+
* `expositionHandler()` for the `/metrics` scrape route, and
|
|
298
|
+
* `exposition()` for direct rendering. Activates the framework
|
|
299
|
+
* auto-tap so audit / vault / queue / error events feed
|
|
300
|
+
* pre-registered framework counters.
|
|
301
|
+
*
|
|
302
|
+
* @opts
|
|
303
|
+
* namespace: string, // prepended to every metric name
|
|
304
|
+
* defaultLabels: object, // attached to every sample
|
|
305
|
+
* labelCardinalityCap: number, // per-metric distinct-label-set cap; default 10000
|
|
306
|
+
*
|
|
307
|
+
* @example
|
|
308
|
+
* var m = b.metrics.create({
|
|
309
|
+
* namespace: "myapp",
|
|
310
|
+
* defaultLabels: { service: "api", version: "1.2.3" },
|
|
311
|
+
* });
|
|
312
|
+
*
|
|
313
|
+
* var requests = m.counter("http_requests_total", {
|
|
314
|
+
* help: "Total HTTP requests",
|
|
315
|
+
* labelNames: ["method", "route", "status"],
|
|
316
|
+
* });
|
|
317
|
+
* requests.inc({ method: "GET", route: "/users", status: "200" });
|
|
318
|
+
*
|
|
319
|
+
* var latency = m.histogram("http_request_duration_seconds", {
|
|
320
|
+
* help: "HTTP request latency",
|
|
321
|
+
* labelNames: ["method", "route"],
|
|
322
|
+
* buckets: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],
|
|
323
|
+
* });
|
|
324
|
+
* latency.observe({ method: "GET", route: "/users" }, 0.123);
|
|
325
|
+
*
|
|
326
|
+
* var depth = m.gauge("queue_depth", { labelNames: ["queueName"] });
|
|
327
|
+
* depth.set({ queueName: "default" }, 42);
|
|
328
|
+
*
|
|
329
|
+
* // Wire into an HTTP server.
|
|
330
|
+
* router.use(m.requestMiddleware());
|
|
331
|
+
* router.get("/metrics", m.expositionHandler());
|
|
332
|
+
*/
|
|
333
|
+
function create(opts) {
|
|
334
|
+
opts = opts || {};
|
|
335
|
+
validateOpts(opts, [
|
|
336
|
+
"namespace", "defaultLabels", "labelCardinalityCap",
|
|
337
|
+
], "b.metrics");
|
|
338
|
+
var namespace = opts.namespace || "";
|
|
339
|
+
var defaultLabels = opts.defaultLabels || {};
|
|
340
|
+
numericBounds.requirePositiveFiniteIntIfPresent(opts.labelCardinalityCap,
|
|
341
|
+
"labelCardinalityCap", MetricsError, "metrics/bad-opt");
|
|
342
|
+
var cardinalityCap = opts.labelCardinalityCap || DEFAULT_CARDINALITY_CAP;
|
|
343
|
+
|
|
344
|
+
// Validate defaultLabels names.
|
|
345
|
+
var dlk = Object.keys(defaultLabels);
|
|
346
|
+
for (var i = 0; i < dlk.length; i++) _validateLabelName(dlk[i]);
|
|
347
|
+
|
|
348
|
+
var metrics = new Map(); // fullName → metric instance
|
|
349
|
+
|
|
350
|
+
function _qualifyName(name) {
|
|
351
|
+
return namespace ? namespace + "_" + name : name;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function _registerMetric(metric) {
|
|
355
|
+
if (metrics.has(metric.name)) {
|
|
356
|
+
throw new MetricsError("metrics/duplicate",
|
|
357
|
+
"metric '" + metric.name + "' already registered");
|
|
358
|
+
}
|
|
359
|
+
metrics.set(metric.name, metric);
|
|
360
|
+
return metric;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// ---- counter ----
|
|
364
|
+
|
|
365
|
+
function counter(name, copts) {
|
|
366
|
+
copts = copts || {};
|
|
367
|
+
var fullName = _qualifyName(name);
|
|
368
|
+
_validateMetricName(fullName);
|
|
369
|
+
var labelNames = (copts.labelNames || []).slice();
|
|
370
|
+
for (var i = 0; i < labelNames.length; i++) _validateLabelName(labelNames[i]);
|
|
371
|
+
var help = copts.help || "";
|
|
372
|
+
var values = new Map(); // labelsKey → { labels, value }
|
|
373
|
+
var capWarned = false;
|
|
374
|
+
|
|
375
|
+
var instance = {
|
|
376
|
+
type: "counter",
|
|
377
|
+
name: fullName,
|
|
378
|
+
help: help,
|
|
379
|
+
unit: copts.unit || null,
|
|
380
|
+
labelNames: labelNames,
|
|
381
|
+
values: values,
|
|
382
|
+
inc: function (callLabels, n) {
|
|
383
|
+
var arg = _normalizeLabelArg(callLabels, n, 1);
|
|
384
|
+
if (arg.value < 0) {
|
|
385
|
+
throw new MetricsError("metrics/counter-decrement",
|
|
386
|
+
"counter.inc value must be >= 0 (got " + arg.value + ") — counters never decrease");
|
|
387
|
+
}
|
|
388
|
+
var resolved = _resolveLabels(defaultLabels, labelNames, arg.labels);
|
|
389
|
+
var key = _labelsKey(resolved);
|
|
390
|
+
var entry = values.get(key);
|
|
391
|
+
if (!entry) {
|
|
392
|
+
if (values.size >= cardinalityCap) {
|
|
393
|
+
if (!capWarned) {
|
|
394
|
+
log("metric '" + fullName + "' hit labelCardinalityCap (" + cardinalityCap +
|
|
395
|
+
") — dropping new label combinations. Reduce label cardinality or raise the cap.");
|
|
396
|
+
capWarned = true;
|
|
397
|
+
}
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
entry = { labels: resolved, value: 0 };
|
|
401
|
+
values.set(key, entry);
|
|
402
|
+
}
|
|
403
|
+
entry.value += arg.value;
|
|
404
|
+
},
|
|
405
|
+
reset: function () { values.clear(); capWarned = false; },
|
|
406
|
+
get: function (callLabels) {
|
|
407
|
+
var resolved = _resolveLabels(defaultLabels, labelNames, callLabels);
|
|
408
|
+
var entry = values.get(_labelsKey(resolved));
|
|
409
|
+
return entry ? entry.value : 0;
|
|
410
|
+
},
|
|
411
|
+
};
|
|
412
|
+
return _registerMetric(instance);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// ---- gauge ----
|
|
416
|
+
|
|
417
|
+
function gauge(name, copts) {
|
|
418
|
+
copts = copts || {};
|
|
419
|
+
var fullName = _qualifyName(name);
|
|
420
|
+
_validateMetricName(fullName);
|
|
421
|
+
var labelNames = (copts.labelNames || []).slice();
|
|
422
|
+
for (var i = 0; i < labelNames.length; i++) _validateLabelName(labelNames[i]);
|
|
423
|
+
var help = copts.help || "";
|
|
424
|
+
var values = new Map();
|
|
425
|
+
var capWarned = false;
|
|
426
|
+
|
|
427
|
+
function _ensure(callLabels) {
|
|
428
|
+
var resolved = _resolveLabels(defaultLabels, labelNames, callLabels);
|
|
429
|
+
var key = _labelsKey(resolved);
|
|
430
|
+
var entry = values.get(key);
|
|
431
|
+
if (!entry) {
|
|
432
|
+
if (values.size >= cardinalityCap) {
|
|
433
|
+
if (!capWarned) {
|
|
434
|
+
log("metric '" + fullName + "' hit labelCardinalityCap (" + cardinalityCap + ")");
|
|
435
|
+
capWarned = true;
|
|
436
|
+
}
|
|
437
|
+
return null;
|
|
438
|
+
}
|
|
439
|
+
entry = { labels: resolved, value: 0 };
|
|
440
|
+
values.set(key, entry);
|
|
441
|
+
}
|
|
442
|
+
return entry;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
var instance = {
|
|
446
|
+
type: "gauge",
|
|
447
|
+
name: fullName,
|
|
448
|
+
help: help,
|
|
449
|
+
unit: copts.unit || null,
|
|
450
|
+
labelNames: labelNames,
|
|
451
|
+
values: values,
|
|
452
|
+
set: function (callLabels, v) {
|
|
453
|
+
var arg = _normalizeLabelArg(callLabels, v, NaN);
|
|
454
|
+
if (typeof arg.value !== "number" || isNaN(arg.value)) {
|
|
455
|
+
throw new MetricsError("metrics/gauge-bad-value",
|
|
456
|
+
"gauge.set value must be a finite number");
|
|
457
|
+
}
|
|
458
|
+
var entry = _ensure(arg.labels);
|
|
459
|
+
if (entry) entry.value = arg.value;
|
|
460
|
+
},
|
|
461
|
+
inc: function (callLabels, n) {
|
|
462
|
+
var arg = _normalizeLabelArg(callLabels, n, 1);
|
|
463
|
+
var entry = _ensure(arg.labels);
|
|
464
|
+
if (entry) entry.value += arg.value;
|
|
465
|
+
},
|
|
466
|
+
dec: function (callLabels, n) {
|
|
467
|
+
var arg = _normalizeLabelArg(callLabels, n, 1);
|
|
468
|
+
var entry = _ensure(arg.labels);
|
|
469
|
+
if (entry) entry.value -= arg.value;
|
|
470
|
+
},
|
|
471
|
+
reset: function () { values.clear(); capWarned = false; },
|
|
472
|
+
get: function (callLabels) {
|
|
473
|
+
var resolved = _resolveLabels(defaultLabels, labelNames, callLabels);
|
|
474
|
+
var entry = values.get(_labelsKey(resolved));
|
|
475
|
+
return entry ? entry.value : 0;
|
|
476
|
+
},
|
|
477
|
+
};
|
|
478
|
+
return _registerMetric(instance);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// ---- histogram ----
|
|
482
|
+
|
|
483
|
+
function histogram(name, copts) {
|
|
484
|
+
copts = copts || {};
|
|
485
|
+
var fullName = _qualifyName(name);
|
|
486
|
+
_validateMetricName(fullName);
|
|
487
|
+
var labelNames = (copts.labelNames || []).slice();
|
|
488
|
+
for (var i = 0; i < labelNames.length; i++) _validateLabelName(labelNames[i]);
|
|
489
|
+
var help = copts.help || "";
|
|
490
|
+
var rawBuckets = copts.buckets || DEFAULT_HTTP_BUCKETS;
|
|
491
|
+
if (!Array.isArray(rawBuckets) || rawBuckets.length === 0) {
|
|
492
|
+
throw new MetricsError("metrics/bad-buckets",
|
|
493
|
+
"histogram buckets must be a non-empty array of ascending numbers");
|
|
494
|
+
}
|
|
495
|
+
// Verify ascending + numeric.
|
|
496
|
+
for (var b = 0; b < rawBuckets.length; b++) {
|
|
497
|
+
if (typeof rawBuckets[b] !== "number" || isNaN(rawBuckets[b])) {
|
|
498
|
+
throw new MetricsError("metrics/bad-buckets",
|
|
499
|
+
"histogram bucket boundary " + b + " is not a number");
|
|
500
|
+
}
|
|
501
|
+
if (b > 0 && rawBuckets[b] <= rawBuckets[b - 1]) {
|
|
502
|
+
throw new MetricsError("metrics/bad-buckets",
|
|
503
|
+
"histogram buckets must be strictly ascending");
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
var buckets = rawBuckets.slice();
|
|
507
|
+
var values = new Map();
|
|
508
|
+
var capWarned = false;
|
|
509
|
+
|
|
510
|
+
var instance = {
|
|
511
|
+
type: "histogram",
|
|
512
|
+
name: fullName,
|
|
513
|
+
help: help,
|
|
514
|
+
unit: copts.unit || null,
|
|
515
|
+
labelNames: labelNames,
|
|
516
|
+
buckets: buckets,
|
|
517
|
+
values: values,
|
|
518
|
+
observe: function (callLabels, v, exemplar) {
|
|
519
|
+
var arg = _normalizeLabelArg(callLabels, v, NaN);
|
|
520
|
+
if (typeof arg.value !== "number" || isNaN(arg.value)) {
|
|
521
|
+
throw new MetricsError("metrics/histogram-bad-value",
|
|
522
|
+
"histogram.observe value must be a finite number");
|
|
523
|
+
}
|
|
524
|
+
var resolved = _resolveLabels(defaultLabels, labelNames, arg.labels);
|
|
525
|
+
var key = _labelsKey(resolved);
|
|
526
|
+
var entry = values.get(key);
|
|
527
|
+
if (!entry) {
|
|
528
|
+
if (values.size >= cardinalityCap) {
|
|
529
|
+
if (!capWarned) {
|
|
530
|
+
log("metric '" + fullName + "' hit labelCardinalityCap (" + cardinalityCap + ")");
|
|
531
|
+
capWarned = true;
|
|
532
|
+
}
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
// counts[i] is the count for the [<=buckets[i]] bucket; counts[buckets.length] is +Inf.
|
|
536
|
+
entry = {
|
|
537
|
+
labels: resolved,
|
|
538
|
+
counts: new Array(buckets.length + 1).fill(0),
|
|
539
|
+
sum: 0,
|
|
540
|
+
count: 0,
|
|
541
|
+
exemplars: new Array(buckets.length + 1).fill(null),
|
|
542
|
+
};
|
|
543
|
+
values.set(key, entry);
|
|
544
|
+
}
|
|
545
|
+
for (var i = 0; i < buckets.length; i++) {
|
|
546
|
+
if (arg.value <= buckets[i]) {
|
|
547
|
+
entry.counts[i]++;
|
|
548
|
+
// OpenMetrics §6.2 — store the most-recent exemplar per
|
|
549
|
+
// bucket. Operators wire trace_id / span_id via `exemplar`
|
|
550
|
+
// arg; the registry only records what's passed in.
|
|
551
|
+
if (exemplar && typeof exemplar === "object") {
|
|
552
|
+
entry.exemplars[i] = {
|
|
553
|
+
labels: exemplar.labels || {},
|
|
554
|
+
value: exemplar.value !== undefined ? exemplar.value : arg.value,
|
|
555
|
+
timestamp: exemplar.timestamp || null,
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
entry.counts[buckets.length]++; // +Inf bucket is everything
|
|
561
|
+
entry.sum += arg.value;
|
|
562
|
+
entry.count += 1;
|
|
563
|
+
},
|
|
564
|
+
reset: function () { values.clear(); capWarned = false; },
|
|
565
|
+
};
|
|
566
|
+
return _registerMetric(instance);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// ---- exposition ----
|
|
570
|
+
|
|
571
|
+
function exposition(opts) {
|
|
572
|
+
opts = opts || {};
|
|
573
|
+
// v0.10.16 — `format: "openmetrics"` emits OpenMetrics 1.0 wire
|
|
574
|
+
// format (RFC TBD; project at https://openmetrics.io). Differences
|
|
575
|
+
// from Prometheus 0.0.4: `# UNIT <metric> <unit>` lines, `_total`
|
|
576
|
+
// suffix MUST on counters, `# EOF` terminator. v0.10.16 ships
|
|
577
|
+
// the EOF terminator + UNIT lines when opts.format === "openmetrics".
|
|
578
|
+
var openMetrics = opts.format === "openmetrics";
|
|
579
|
+
var lines = [];
|
|
580
|
+
var sortedNames = Array.from(metrics.keys()).sort();
|
|
581
|
+
for (var i = 0; i < sortedNames.length; i++) {
|
|
582
|
+
var m = metrics.get(sortedNames[i]);
|
|
583
|
+
// OpenMetrics §5.1.2 — counter sample lines MUST suffix with
|
|
584
|
+
// `_total`. The metadata `# HELP / # TYPE / # UNIT` lines MUST
|
|
585
|
+
// name the SAME family identifier the samples use, otherwise
|
|
586
|
+
// strict OpenMetrics parsers reject the family. Derive the
|
|
587
|
+
// exposition name once at the top of the loop so both the
|
|
588
|
+
// metadata lines and the sample lines agree.
|
|
589
|
+
var exposedName = m.name;
|
|
590
|
+
if (openMetrics && m.type === "counter" && !/_total$/.test(m.name)) {
|
|
591
|
+
exposedName = m.name + "_total";
|
|
592
|
+
}
|
|
593
|
+
if (m.help) lines.push("# HELP " + exposedName + " " + m.help);
|
|
594
|
+
lines.push("# TYPE " + exposedName + " " + m.type);
|
|
595
|
+
if (openMetrics && m.unit) lines.push("# UNIT " + exposedName + " " + m.unit);
|
|
596
|
+
var keys = Array.from(m.values.keys()).sort();
|
|
597
|
+
if (m.type === "histogram") {
|
|
598
|
+
for (var k = 0; k < keys.length; k++) {
|
|
599
|
+
var entry = m.values.get(keys[k]);
|
|
600
|
+
for (var bi = 0; bi < m.buckets.length; bi++) {
|
|
601
|
+
var bLabels = Object.assign({}, entry.labels, { le: String(m.buckets[bi]) });
|
|
602
|
+
var bucketLine = m.name + "_bucket" + _renderLabels(bLabels) + " " + entry.counts[bi];
|
|
603
|
+
// OpenMetrics 1.0 §6.2 — exemplar trace + span IDs appended
|
|
604
|
+
// as `# {trace_id="...",span_id="..."} <value> <timestamp>`.
|
|
605
|
+
if (openMetrics && entry.exemplars && entry.exemplars[bi]) {
|
|
606
|
+
var ex = entry.exemplars[bi];
|
|
607
|
+
bucketLine += " # " + _renderLabels(ex.labels || {}) + " " + ex.value;
|
|
608
|
+
if (ex.timestamp) bucketLine += " " + ex.timestamp;
|
|
609
|
+
}
|
|
610
|
+
lines.push(bucketLine);
|
|
611
|
+
}
|
|
612
|
+
var infLabels = Object.assign({}, entry.labels, { le: "+Inf" });
|
|
613
|
+
lines.push(m.name + "_bucket" + _renderLabels(infLabels) + " " + entry.counts[m.buckets.length]);
|
|
614
|
+
lines.push(m.name + "_sum" + _renderLabels(entry.labels) + " " + entry.sum);
|
|
615
|
+
lines.push(m.name + "_count" + _renderLabels(entry.labels) + " " + entry.count);
|
|
616
|
+
}
|
|
617
|
+
} else if (m.type === "counter" && openMetrics) {
|
|
618
|
+
// exposedName already carries the `_total` suffix when needed
|
|
619
|
+
// (derived at the top of the loop so metadata + samples agree).
|
|
620
|
+
for (var v = 0; v < keys.length; v++) {
|
|
621
|
+
var ent = m.values.get(keys[v]);
|
|
622
|
+
lines.push(exposedName + _renderLabels(ent.labels) + " " + ent.value);
|
|
623
|
+
}
|
|
624
|
+
} else {
|
|
625
|
+
for (var v2 = 0; v2 < keys.length; v2++) {
|
|
626
|
+
var ent2 = m.values.get(keys[v2]);
|
|
627
|
+
lines.push(m.name + _renderLabels(ent2.labels) + " " + ent2.value);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
lines.push("");
|
|
631
|
+
}
|
|
632
|
+
if (openMetrics) lines.push("# EOF");
|
|
633
|
+
return lines.join("\n") + (lines.length ? "" : "\n");
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
function expositionHandler() {
|
|
637
|
+
return function metricsHandler(req, res) {
|
|
638
|
+
var body = exposition();
|
|
639
|
+
res.writeHead(HTTP_STATUS.OK, {
|
|
640
|
+
"Content-Type": "text/plain; version=0.0.4; charset=utf-8",
|
|
641
|
+
"Content-Length": Buffer.byteLength(body),
|
|
642
|
+
"Cache-Control": "no-store",
|
|
643
|
+
});
|
|
644
|
+
res.end(body);
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
// ---- request middleware (auto-time + auto-count) ----
|
|
649
|
+
|
|
650
|
+
// Built-in metrics created on first requestMiddleware call so apps
|
|
651
|
+
// that don't use the middleware don't pay the registration cost.
|
|
652
|
+
var requestsTotal = null;
|
|
653
|
+
var requestDuration = null;
|
|
654
|
+
function _ensureRequestMetrics() {
|
|
655
|
+
if (requestsTotal && requestDuration) return;
|
|
656
|
+
requestsTotal = counter("framework_http_requests_total", {
|
|
657
|
+
help: "Total HTTP requests handled by the framework",
|
|
658
|
+
labelNames: ["method", "route", "status"],
|
|
659
|
+
});
|
|
660
|
+
requestDuration = histogram("framework_http_request_duration_seconds", {
|
|
661
|
+
help: "HTTP request latency in seconds",
|
|
662
|
+
labelNames: ["method", "route"],
|
|
663
|
+
buckets: DEFAULT_HTTP_BUCKETS,
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
function requestMiddleware() {
|
|
668
|
+
_ensureRequestMetrics();
|
|
669
|
+
return function metricsRequest(req, res, next) {
|
|
670
|
+
var start = process.hrtime.bigint();
|
|
671
|
+
captureResponseStatus(res, function (status) {
|
|
672
|
+
var elapsedSec = Number(process.hrtime.bigint() - start) / 1e9;
|
|
673
|
+
var route = resolveRoute(req);
|
|
674
|
+
var labels = { method: req.method || "GET", route: route, status: String(status) };
|
|
675
|
+
var durLabels = { method: labels.method, route: route };
|
|
676
|
+
// Best-effort tap path — a label coercion or registry race
|
|
677
|
+
// must not crash the request that triggered it. Log so
|
|
678
|
+
// the operator sees the failure in the same channel as
|
|
679
|
+
// the rest of the framework's diagnostics.
|
|
680
|
+
try { requestsTotal.inc(labels); }
|
|
681
|
+
catch (e) { log.warn("metrics/request-counter-failed: " + e.message); }
|
|
682
|
+
try { requestDuration.observe(durLabels, elapsedSec); }
|
|
683
|
+
catch (e) { log.warn("metrics/request-duration-failed: " + e.message); }
|
|
684
|
+
});
|
|
685
|
+
return next();
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// ---- framework auto-instrumentation taps ----
|
|
690
|
+
//
|
|
691
|
+
// tap() calls in audit / vault / queue route through here when this
|
|
692
|
+
// registry is active. Pre-register the counters so we don't create
|
|
693
|
+
// them lazily inside the tap path (which would bind allocator cost
|
|
694
|
+
// to per-event hot paths).
|
|
695
|
+
|
|
696
|
+
var auditEventsTotal = counter("framework_audit_events_total", {
|
|
697
|
+
help: "Audit events recorded by the framework",
|
|
698
|
+
labelNames: ["action", "outcome"],
|
|
699
|
+
});
|
|
700
|
+
var vaultSealTotal = counter("framework_vault_seal_total", {
|
|
701
|
+
help: "Vault seal calls",
|
|
702
|
+
});
|
|
703
|
+
var vaultUnsealTotal = counter("framework_vault_unseal_total", {
|
|
704
|
+
help: "Vault unseal calls",
|
|
705
|
+
});
|
|
706
|
+
var queueEnqueueTotal = counter("framework_queue_enqueue_total", {
|
|
707
|
+
help: "Queue enqueue operations",
|
|
708
|
+
labelNames: ["queueName"],
|
|
709
|
+
});
|
|
710
|
+
var queueCompleteTotal = counter("framework_queue_complete_total", {
|
|
711
|
+
help: "Queue job completions",
|
|
712
|
+
labelNames: ["queueName"],
|
|
713
|
+
});
|
|
714
|
+
var queueFailTotal = counter("framework_queue_fail_total", {
|
|
715
|
+
help: "Queue job failures",
|
|
716
|
+
labelNames: ["queueName"],
|
|
717
|
+
});
|
|
718
|
+
var queueDepthGauge = gauge("framework_queue_depth", {
|
|
719
|
+
help: "Queue depth — pending + inflight jobs",
|
|
720
|
+
labelNames: ["queueName"],
|
|
721
|
+
});
|
|
722
|
+
var jobsInflightGauge = gauge("framework_jobs_inflight", {
|
|
723
|
+
help: "Jobs currently leased to a consumer",
|
|
724
|
+
labelNames: ["queueName"],
|
|
725
|
+
});
|
|
726
|
+
var errorsTotal = counter("framework_errors_total", {
|
|
727
|
+
help: "Framework-error class constructions",
|
|
728
|
+
labelNames: ["class"],
|
|
729
|
+
});
|
|
730
|
+
|
|
731
|
+
function _tapHandler(name, value, labels) {
|
|
732
|
+
var qn = (labels && labels.queueName) || "default";
|
|
733
|
+
if (name === "audit.record") {
|
|
734
|
+
auditEventsTotal.inc({
|
|
735
|
+
action: (labels && labels.action) || "unknown",
|
|
736
|
+
outcome: (labels && labels.outcome) || "unknown",
|
|
737
|
+
}, value || 1);
|
|
738
|
+
} else if (name === "vault.seal") { vaultSealTotal.inc(value || 1); }
|
|
739
|
+
else if (name === "vault.unseal") { vaultUnsealTotal.inc(value || 1); }
|
|
740
|
+
else if (name === "queue.enqueue") {
|
|
741
|
+
queueEnqueueTotal.inc({ queueName: qn }, value || 1);
|
|
742
|
+
queueDepthGauge.inc({ queueName: qn }, value || 1);
|
|
743
|
+
}
|
|
744
|
+
else if (name === "queue.lease") {
|
|
745
|
+
jobsInflightGauge.inc({ queueName: qn }, value || 1);
|
|
746
|
+
}
|
|
747
|
+
else if (name === "queue.complete") {
|
|
748
|
+
queueCompleteTotal.inc({ queueName: qn }, value || 1);
|
|
749
|
+
queueDepthGauge.dec({ queueName: qn }, value || 1);
|
|
750
|
+
jobsInflightGauge.dec({ queueName: qn }, value || 1);
|
|
751
|
+
}
|
|
752
|
+
else if (name === "queue.fail") {
|
|
753
|
+
queueFailTotal.inc({ queueName: qn }, value || 1);
|
|
754
|
+
jobsInflightGauge.dec({ queueName: qn }, value || 1);
|
|
755
|
+
// Depth = pending + inflight. Retry transitions inflight→pending
|
|
756
|
+
// (depth unchanged); terminal failure exits both buckets.
|
|
757
|
+
if (labels && labels.willRetry === false) {
|
|
758
|
+
queueDepthGauge.dec({ queueName: qn }, value || 1);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
else if (name === "error.construct") {
|
|
762
|
+
errorsTotal.inc({ class: (labels && labels.class) || "unknown" }, value || 1);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
_activeTap = _tapHandler;
|
|
766
|
+
|
|
767
|
+
// ---- registry surface ----
|
|
768
|
+
|
|
769
|
+
var registry = {
|
|
770
|
+
counter: counter,
|
|
771
|
+
gauge: gauge,
|
|
772
|
+
histogram: histogram,
|
|
773
|
+
requestMiddleware: requestMiddleware,
|
|
774
|
+
expositionHandler: expositionHandler,
|
|
775
|
+
exposition: exposition,
|
|
776
|
+
metrics: metrics, // diagnostic; operators rarely need it
|
|
777
|
+
namespace: namespace,
|
|
778
|
+
defaultLabels: defaultLabels,
|
|
779
|
+
cardinalityCap: cardinalityCap,
|
|
780
|
+
deactivate: function () {
|
|
781
|
+
// Release the global tap handler. Operator-driven test reset.
|
|
782
|
+
if (_activeTap === _tapHandler) _activeTap = null;
|
|
783
|
+
},
|
|
784
|
+
};
|
|
785
|
+
return registry;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
function _resetForTest() {
|
|
789
|
+
_activeTap = null;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// ---- Snapshot writer/reader ----
|
|
793
|
+
//
|
|
794
|
+
// Out-of-process metrics export pattern for long-running daemons:
|
|
795
|
+
// the daemon writes a JSON snapshot atomically every N seconds; a
|
|
796
|
+
// separate CLI process reads + renders. Bypasses the HTTP-port +
|
|
797
|
+
// Unix-socket coupling that the regular Prometheus exposition
|
|
798
|
+
// handler requires. Useful for systemd daemons that don't want to
|
|
799
|
+
// bind a stats port at all (operator runs `daemon stats` and the
|
|
800
|
+
// CLI just reads the file).
|
|
801
|
+
//
|
|
802
|
+
// The writer is atomic — every write goes through atomic-file's
|
|
803
|
+
// writeSync (temp-file + rename + fsync) so a reader that lands
|
|
804
|
+
// between rename and fsync sees the previous complete snapshot
|
|
805
|
+
// rather than a partially-written one.
|
|
806
|
+
//
|
|
807
|
+
// Surface:
|
|
808
|
+
//
|
|
809
|
+
// var stop = b.metrics.snapshot.startWriter({
|
|
810
|
+
// path: "/run/blamejs-daemon/metrics.json",
|
|
811
|
+
// intervalMs: 5000,
|
|
812
|
+
// fields: function () { return { uptimeMs: ..., counters: {...} }; },
|
|
813
|
+
// });
|
|
814
|
+
// // ...later:
|
|
815
|
+
// stop(); // clears timer; runs one final fields() flush before returning
|
|
816
|
+
//
|
|
817
|
+
// var snap = b.metrics.snapshot.read("/run/blamejs-daemon/metrics.json");
|
|
818
|
+
// process.stdout.write(b.metrics.snapshot.render(snap, { format: "text" }));
|
|
819
|
+
|
|
820
|
+
/**
|
|
821
|
+
* @primitive b.metrics.snapshot.startWriter
|
|
822
|
+
* @signature b.metrics.snapshot.startWriter(opts)
|
|
823
|
+
* @since 0.9.13
|
|
824
|
+
* @status stable
|
|
825
|
+
* @related b.metrics.snapshot.read, b.metrics.snapshot.render
|
|
826
|
+
*
|
|
827
|
+
* Start a periodic writer that calls `opts.fields()` every
|
|
828
|
+
* `opts.intervalMs` and writes the returned object as JSON to
|
|
829
|
+
* `opts.path` atomically. Returns a `stop()` function that clears
|
|
830
|
+
* the timer + performs one final flush before resolving.
|
|
831
|
+
*
|
|
832
|
+
* @opts
|
|
833
|
+
* path: string, // absolute path to write the snapshot
|
|
834
|
+
* intervalMs: number, // milliseconds between flushes (>=100)
|
|
835
|
+
* fields: Function, // returns an object — written as JSON
|
|
836
|
+
* registry: object, // optional `b.metrics.create()` handle — adds a
|
|
837
|
+
* // structured `metrics` field carrying every
|
|
838
|
+
* // registered counter / gauge / histogram (incl.
|
|
839
|
+
* // bucket counts) so sidecar readers compose
|
|
840
|
+
* // histogram_quantile() against the snapshot
|
|
841
|
+
* fileMode: number, // POSIX mode (default 0o640 — owner rw, group r)
|
|
842
|
+
*
|
|
843
|
+
* @example
|
|
844
|
+
* var registry = b.metrics.create();
|
|
845
|
+
* var latency = registry.histogram("op_latency_seconds", { buckets: [0.01, 0.1, 1] });
|
|
846
|
+
* var stop = b.metrics.snapshot.startWriter({
|
|
847
|
+
* path: "/run/blamejs/metrics.json",
|
|
848
|
+
* intervalMs: 5000,
|
|
849
|
+
* registry: registry,
|
|
850
|
+
* fields: function () { return { uptimeMs: process.uptime() * 1000 }; },
|
|
851
|
+
* });
|
|
852
|
+
* // Snapshot file: { writtenAt, fields, metrics: { op_latency_seconds: { type, buckets, observations: [{ labels, counts, sum, count }] } } }
|
|
853
|
+
* stop();
|
|
854
|
+
*/
|
|
855
|
+
function _serializeRegistry(registry) {
|
|
856
|
+
// Walk every registered metric in the registry.metrics Map and emit
|
|
857
|
+
// a JSON-friendly structured shape. Histograms get full buckets +
|
|
858
|
+
// bucket counts so downstream consumers compose
|
|
859
|
+
// `histogram_quantile()` against the snapshot without a separate
|
|
860
|
+
// exposition endpoint (issue #100).
|
|
861
|
+
var out = {};
|
|
862
|
+
var names = registry.metrics instanceof Map
|
|
863
|
+
? Array.from(registry.metrics.keys()).sort()
|
|
864
|
+
: Object.keys(registry.metrics).sort();
|
|
865
|
+
for (var i = 0; i < names.length; i += 1) {
|
|
866
|
+
var name = names[i];
|
|
867
|
+
var m = registry.metrics instanceof Map ? registry.metrics.get(name) : registry.metrics[name];
|
|
868
|
+
if (!m) continue;
|
|
869
|
+
var entry = { type: m.type, help: m.help || "", labelNames: m.labelNames || [] };
|
|
870
|
+
if (m.type === "histogram") {
|
|
871
|
+
entry.buckets = m.buckets.slice();
|
|
872
|
+
entry.observations = [];
|
|
873
|
+
var hKeys = m.values instanceof Map ? Array.from(m.values.keys()).sort() : Object.keys(m.values).sort();
|
|
874
|
+
for (var hi = 0; hi < hKeys.length; hi += 1) {
|
|
875
|
+
var hv = m.values instanceof Map ? m.values.get(hKeys[hi]) : m.values[hKeys[hi]];
|
|
876
|
+
entry.observations.push({
|
|
877
|
+
labels: hv.labels,
|
|
878
|
+
counts: hv.counts.slice(),
|
|
879
|
+
sum: hv.sum,
|
|
880
|
+
count: hv.count,
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
} else {
|
|
884
|
+
entry.observations = [];
|
|
885
|
+
var vKeys = m.values instanceof Map ? Array.from(m.values.keys()).sort() : Object.keys(m.values).sort();
|
|
886
|
+
for (var vi = 0; vi < vKeys.length; vi += 1) {
|
|
887
|
+
var vv = m.values instanceof Map ? m.values.get(vKeys[vi]) : m.values[vKeys[vi]];
|
|
888
|
+
entry.observations.push({ labels: vv.labels, value: vv.value });
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
out[name] = entry;
|
|
892
|
+
}
|
|
893
|
+
return out;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
function snapshotStartWriter(opts) {
|
|
897
|
+
opts = opts || {};
|
|
898
|
+
validateOpts.requireNonEmptyString(opts.path,
|
|
899
|
+
"metrics.snapshot.startWriter: opts.path",
|
|
900
|
+
MetricsError, "metrics-snapshot/bad-path");
|
|
901
|
+
if (typeof opts.intervalMs !== "number" || !isFinite(opts.intervalMs) || opts.intervalMs < 100) {
|
|
902
|
+
throw new MetricsError("metrics-snapshot/bad-interval",
|
|
903
|
+
"metrics.snapshot.startWriter: opts.intervalMs must be a finite number >= 100, got " + opts.intervalMs);
|
|
904
|
+
}
|
|
905
|
+
if (typeof opts.fields !== "function") {
|
|
906
|
+
throw new MetricsError("metrics-snapshot/bad-fields",
|
|
907
|
+
"metrics.snapshot.startWriter: opts.fields must be a function returning the snapshot object");
|
|
908
|
+
}
|
|
909
|
+
// Issue #100 — optional `registry` handle pulls every registered
|
|
910
|
+
// metric into a structured `metrics` field in the JSON snapshot:
|
|
911
|
+
// counters / gauges as `{ value }` per label set, histograms as
|
|
912
|
+
// `{ buckets, observations }` with bucket counts + sum + count.
|
|
913
|
+
// Sidecar readers compose `histogram_quantile()` against the
|
|
914
|
+
// snapshot file without running a separate /metrics endpoint.
|
|
915
|
+
if (opts.registry !== undefined && opts.registry !== null &&
|
|
916
|
+
(typeof opts.registry !== "object" || typeof opts.registry.metrics !== "object")) {
|
|
917
|
+
throw new MetricsError("metrics-snapshot/bad-registry",
|
|
918
|
+
"metrics.snapshot.startWriter: opts.registry must be a metrics registry " +
|
|
919
|
+
"(from b.metrics.create()) or omitted");
|
|
920
|
+
}
|
|
921
|
+
var p = opts.path;
|
|
922
|
+
var fieldsFn = opts.fields;
|
|
923
|
+
var registry = opts.registry || null;
|
|
924
|
+
var intervalMs = opts.intervalMs;
|
|
925
|
+
// CRYPTO-6 — file mode for the atomic write. Default 0o640
|
|
926
|
+
// (owner rw, group r, world none). Operators with a sidecar
|
|
927
|
+
// reader in a different group override to 0o644; multi-tenant
|
|
928
|
+
// hosts may even tighten to 0o600.
|
|
929
|
+
var fileMode = opts.fileMode !== undefined ? opts.fileMode : 0o640; // allow:raw-byte-literal — POSIX file mode octal
|
|
930
|
+
if (typeof fileMode !== "number" || !isFinite(fileMode) ||
|
|
931
|
+
fileMode < 0 || fileMode > 0o777 || Math.floor(fileMode) !== fileMode) {
|
|
932
|
+
throw new MetricsError("metrics-snapshot/bad-file-mode",
|
|
933
|
+
"metrics.snapshot.startWriter: opts.fileMode must be a POSIX file-mode integer in [0, 0o777], got " +
|
|
934
|
+
fileMode);
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
var doFlush = function () {
|
|
938
|
+
var snap;
|
|
939
|
+
try {
|
|
940
|
+
snap = fieldsFn();
|
|
941
|
+
} catch (e) {
|
|
942
|
+
log("snapshot.fields() threw: " + (e && e.message ? e.message : String(e)));
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
945
|
+
if (!snap || typeof snap !== "object") {
|
|
946
|
+
log("snapshot.fields() returned non-object; skipping flush");
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
var payload = {
|
|
950
|
+
writtenAt: new Date().toISOString(),
|
|
951
|
+
fields: snap,
|
|
952
|
+
};
|
|
953
|
+
if (registry) {
|
|
954
|
+
try { payload.metrics = _serializeRegistry(registry); }
|
|
955
|
+
catch (e2) { log("snapshot.metrics serialize failed: " + ((e2 && e2.message) || String(e2))); }
|
|
956
|
+
}
|
|
957
|
+
try {
|
|
958
|
+
// CRYPTO-6 — default 0o640 (owner rw, group r, world none) so
|
|
959
|
+
// operator-supplied snapshot fields aren't world-readable on a
|
|
960
|
+
// multi-tenant host. Operators with a sidecar reader running as
|
|
961
|
+
// a different group override via opts.fileMode at startWriter
|
|
962
|
+
// construction.
|
|
963
|
+
atomicFile.writeSync(p, JSON.stringify(payload) + "\n", { fileMode: fileMode });
|
|
964
|
+
} catch (e) {
|
|
965
|
+
log("snapshot.writeSync failed: " + (e && e.message ? e.message : String(e)));
|
|
966
|
+
}
|
|
967
|
+
};
|
|
968
|
+
|
|
969
|
+
// First flush is synchronous so the file exists by the time
|
|
970
|
+
// startWriter returns. Subsequent flushes run on the interval.
|
|
971
|
+
doFlush();
|
|
972
|
+
var timer = setInterval(doFlush, intervalMs);
|
|
973
|
+
if (typeof timer.unref === "function") timer.unref();
|
|
974
|
+
|
|
975
|
+
return function stop() {
|
|
976
|
+
clearInterval(timer);
|
|
977
|
+
doFlush(); // final flush captures last state before the daemon exits
|
|
978
|
+
};
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
/**
|
|
982
|
+
* @primitive b.metrics.snapshot.read
|
|
983
|
+
* @signature b.metrics.snapshot.read(path)
|
|
984
|
+
* @since 0.9.13
|
|
985
|
+
* @status stable
|
|
986
|
+
* @related b.metrics.snapshot.startWriter, b.metrics.snapshot.render
|
|
987
|
+
*
|
|
988
|
+
* Read + parse a snapshot file written by `startWriter`. Returns
|
|
989
|
+
* `{ writtenAt, fields }`. Throws `MetricsError` with code
|
|
990
|
+
* `metrics-snapshot/...` on missing file, parse failure, or
|
|
991
|
+
* shape mismatch.
|
|
992
|
+
*
|
|
993
|
+
* @example
|
|
994
|
+
* var snap = b.metrics.snapshot.read("/run/blamejs/metrics.json");
|
|
995
|
+
* console.log("uptime:", snap.fields.uptimeMs);
|
|
996
|
+
* console.log("written at:", snap.writtenAt);
|
|
997
|
+
*/
|
|
998
|
+
function snapshotRead(p) {
|
|
999
|
+
validateOpts.requireNonEmptyString(p,
|
|
1000
|
+
"metrics.snapshot.read: path",
|
|
1001
|
+
MetricsError, "metrics-snapshot/bad-path");
|
|
1002
|
+
var raw;
|
|
1003
|
+
try {
|
|
1004
|
+
raw = nodeFs.readFileSync(p, "utf8");
|
|
1005
|
+
} catch (e) {
|
|
1006
|
+
throw new MetricsError("metrics-snapshot/not-found",
|
|
1007
|
+
"metrics.snapshot.read: " + p + " — " + (e && e.message ? e.message : String(e)));
|
|
1008
|
+
}
|
|
1009
|
+
var parsed;
|
|
1010
|
+
// safeJson.parse with bounded maxBytes — the snapshot file is read
|
|
1011
|
+
// by a separate CLI / sidecar process from where it's written, and a
|
|
1012
|
+
// hostile actor with write access to the snapshot path could replace
|
|
1013
|
+
// it with a multi-GB file that would OOM the reader. 4 MiB ceiling
|
|
1014
|
+
// is well above the framework's expected snapshot size (~5-50 KiB)
|
|
1015
|
+
// and the safeJson absolute cap stays within reach.
|
|
1016
|
+
try {
|
|
1017
|
+
// CRYPTO-21 — route through C.BYTES.mib(4); the raw byte literal
|
|
1018
|
+
// was a drift smell flagged by codebase-patterns.
|
|
1019
|
+
parsed = safeJson.parse(raw, { maxBytes: C.BYTES.mib(4) });
|
|
1020
|
+
} catch (e) {
|
|
1021
|
+
throw new MetricsError("metrics-snapshot/bad-json",
|
|
1022
|
+
"metrics.snapshot.read: " + p + " contains invalid JSON: " + (e && e.message ? e.message : String(e)));
|
|
1023
|
+
}
|
|
1024
|
+
if (!parsed || typeof parsed !== "object" ||
|
|
1025
|
+
typeof parsed.writtenAt !== "string" || !parsed.fields ||
|
|
1026
|
+
typeof parsed.fields !== "object") {
|
|
1027
|
+
throw new MetricsError("metrics-snapshot/bad-shape",
|
|
1028
|
+
"metrics.snapshot.read: " + p + " is not a startWriter-produced snapshot (missing writtenAt or fields)");
|
|
1029
|
+
}
|
|
1030
|
+
return parsed;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
/**
|
|
1034
|
+
* @primitive b.metrics.snapshot.render
|
|
1035
|
+
* @signature b.metrics.snapshot.render(snap, opts)
|
|
1036
|
+
* @since 0.9.13
|
|
1037
|
+
* @status stable
|
|
1038
|
+
* @related b.metrics.snapshot.read
|
|
1039
|
+
*
|
|
1040
|
+
* Format a snapshot object for human or machine consumption.
|
|
1041
|
+
*
|
|
1042
|
+
* format: "text" — operator-readable lines, one field per row (default)
|
|
1043
|
+
* format: "prometheus" — Prometheus 0.0.4 text format
|
|
1044
|
+
*
|
|
1045
|
+
* ## Type detection (`prometheus` format only)
|
|
1046
|
+
*
|
|
1047
|
+
* Per Prometheus naming convention + OpenMetrics 1.0.0 §6.2, counter
|
|
1048
|
+
* metric families MUST carry the `_total` suffix; every other numeric
|
|
1049
|
+
* field renders as a gauge. The renderer auto-detects by suffix:
|
|
1050
|
+
*
|
|
1051
|
+
* - field name ends in `_total` → `# TYPE <name> counter`
|
|
1052
|
+
* - everything else → `# TYPE <name> gauge`
|
|
1053
|
+
*
|
|
1054
|
+
* Operators with metrics that don't fit the convention (e.g. a counter
|
|
1055
|
+
* named `bytes_sent` without the `_total` suffix, or a gauge that
|
|
1056
|
+
* happens to end in `_total`) opt the right type via `opts.fieldTypes`:
|
|
1057
|
+
*
|
|
1058
|
+
* render(snap, { format: "prometheus", fieldTypes: {
|
|
1059
|
+
* bytes_sent: "counter", // override default gauge
|
|
1060
|
+
* ratio_total: "gauge", // override default counter
|
|
1061
|
+
* }});
|
|
1062
|
+
*
|
|
1063
|
+
* Pre-v0.9.47 every field rendered as gauge regardless of name, which
|
|
1064
|
+
* broke `rate()` queries against counter-shaped series. Operators
|
|
1065
|
+
* scraping a long-running deployment will see `rate(*_total[5m])`
|
|
1066
|
+
* queries start returning the right answer once the new types reach
|
|
1067
|
+
* the scrape target.
|
|
1068
|
+
*
|
|
1069
|
+
* @opts
|
|
1070
|
+
* format: "text" | "prometheus", // default: "text"
|
|
1071
|
+
* prefix: string, // prometheus-only; default: "blamejs"
|
|
1072
|
+
* fieldTypes: Object, // prometheus-only; per-field type override
|
|
1073
|
+
* // map. Values: "counter" | "gauge".
|
|
1074
|
+
*
|
|
1075
|
+
* @example
|
|
1076
|
+
* var snap = b.metrics.snapshot.read("/run/blamejs/metrics.json");
|
|
1077
|
+
* process.stdout.write(b.metrics.snapshot.render(snap));
|
|
1078
|
+
* // or for Prometheus scraping (auto-detects http_requests_total
|
|
1079
|
+
* // as a counter via the _total suffix):
|
|
1080
|
+
* res.setHeader("Content-Type", "text/plain; version=0.0.4");
|
|
1081
|
+
* res.end(b.metrics.snapshot.render(snap, { format: "prometheus", prefix: "myapp" }));
|
|
1082
|
+
*/
|
|
1083
|
+
var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/; // allow:duplicate-regex — ISO-8601 instant shape ships in three primitives (metrics text-render, content-credentials, mail-server-imap APPEND); each is bounded by its own caller and the regex itself is 50 bytes — extracting into a cross-module dep wouldn't carry its weight
|
|
1084
|
+
|
|
1085
|
+
// Formats a single field value for the text renderer. ISO-date-shaped
|
|
1086
|
+
// strings render verbatim (with millisecond precision) so the human
|
|
1087
|
+
// operator reads them as timestamps; everything else degrades to the
|
|
1088
|
+
// existing number / string / boolean / JSON formatting.
|
|
1089
|
+
function _formatTextValue(v) {
|
|
1090
|
+
if (typeof v === "number") return String(v);
|
|
1091
|
+
if (typeof v === "boolean") return v ? "true" : "false";
|
|
1092
|
+
if (typeof v === "string") {
|
|
1093
|
+
if (ISO_DATE_RE.test(v) && isFinite(Date.parse(v))) return v; // allow:regex-no-length-cap — ISO-date shape, length-bounded by the anchored pattern
|
|
1094
|
+
return v;
|
|
1095
|
+
}
|
|
1096
|
+
return JSON.stringify(v);
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
// Internal text-format renderer extracted from snapshotRender so the
|
|
1100
|
+
// E.grouped-text + H.iso-date paths share one code path.
|
|
1101
|
+
function _renderText(fields, snap, opts) {
|
|
1102
|
+
var lines = ["snapshot written-at: " + snap.writtenAt];
|
|
1103
|
+
// E. operator-supplied group map. Group ordering follows the
|
|
1104
|
+
// insertion order of the `opts.groups` object; fields not named in
|
|
1105
|
+
// any group fall to the bottom under `== Other ==`.
|
|
1106
|
+
if (opts.groups && typeof opts.groups === "object" && !Array.isArray(opts.groups)) {
|
|
1107
|
+
var groupNames = Object.keys(opts.groups);
|
|
1108
|
+
var named = Object.create(null);
|
|
1109
|
+
for (var gi = 0; gi < groupNames.length; gi += 1) {
|
|
1110
|
+
var gName = groupNames[gi];
|
|
1111
|
+
var fieldNames = opts.groups[gName];
|
|
1112
|
+
if (!Array.isArray(fieldNames)) continue;
|
|
1113
|
+
lines.push("");
|
|
1114
|
+
lines.push("== " + gName + " ==");
|
|
1115
|
+
for (var fi = 0; fi < fieldNames.length; fi += 1) {
|
|
1116
|
+
var fn = fieldNames[fi];
|
|
1117
|
+
named[fn] = true;
|
|
1118
|
+
if (Object.prototype.hasOwnProperty.call(fields, fn)) {
|
|
1119
|
+
lines.push(" " + fn + ": " + _formatTextValue(fields[fn]));
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
// Stable order for the unnamed remainder.
|
|
1124
|
+
// allow:bare-canonicalize-walk — operator-facing display ordering
|
|
1125
|
+
var remainder = Object.keys(fields).sort().filter(function (k) { return !named[k]; });
|
|
1126
|
+
if (remainder.length > 0) {
|
|
1127
|
+
lines.push("");
|
|
1128
|
+
lines.push("== Other ==");
|
|
1129
|
+
for (var ri = 0; ri < remainder.length; ri += 1) {
|
|
1130
|
+
lines.push(" " + remainder[ri] + ": " + _formatTextValue(fields[remainder[ri]]));
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
return lines.join("\n") + "\n";
|
|
1134
|
+
}
|
|
1135
|
+
// Default flat rendering.
|
|
1136
|
+
// allow:bare-canonicalize-walk — operator-facing display ordering
|
|
1137
|
+
var keys = Object.keys(fields).sort();
|
|
1138
|
+
for (var i = 0; i < keys.length; i += 1) {
|
|
1139
|
+
var k = keys[i];
|
|
1140
|
+
lines.push(" " + k + ": " + _formatTextValue(fields[k]));
|
|
1141
|
+
}
|
|
1142
|
+
return lines.join("\n") + "\n";
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
function snapshotRender(snap, opts) {
|
|
1146
|
+
opts = opts || {};
|
|
1147
|
+
var format = opts.format || "text";
|
|
1148
|
+
if (!snap || typeof snap !== "object" || !snap.fields) {
|
|
1149
|
+
throw new MetricsError("metrics-snapshot/bad-snap",
|
|
1150
|
+
"metrics.snapshot.render: snap must be a startWriter-produced object (got " + typeof snap + ")");
|
|
1151
|
+
}
|
|
1152
|
+
var fields = snap.fields;
|
|
1153
|
+
if (format === "text") {
|
|
1154
|
+
return _renderText(fields, snap, opts);
|
|
1155
|
+
}
|
|
1156
|
+
if (format === "prometheus") {
|
|
1157
|
+
var prefix = opts.prefix || "blamejs";
|
|
1158
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(prefix)) {
|
|
1159
|
+
throw new MetricsError("metrics-snapshot/bad-prefix",
|
|
1160
|
+
"metrics.snapshot.render: prometheus prefix must match [a-zA-Z_][a-zA-Z0-9_]*, got '" + prefix + "'");
|
|
1161
|
+
}
|
|
1162
|
+
var fieldTypes = opts.fieldTypes || {};
|
|
1163
|
+
if (typeof fieldTypes !== "object" || fieldTypes === null || Array.isArray(fieldTypes)) {
|
|
1164
|
+
throw new MetricsError("metrics-snapshot/bad-field-types",
|
|
1165
|
+
"metrics.snapshot.render: opts.fieldTypes must be an object mapping field-name → 'counter' | 'gauge'");
|
|
1166
|
+
}
|
|
1167
|
+
var out = [];
|
|
1168
|
+
// allow:bare-canonicalize-walk — sort is for stable Prometheus
|
|
1169
|
+
// exposition output ordering, not canonicalize-for-hashing
|
|
1170
|
+
var keys2 = Object.keys(fields).sort();
|
|
1171
|
+
for (var j = 0; j < keys2.length; j++) {
|
|
1172
|
+
var k2 = keys2[j];
|
|
1173
|
+
var v2 = fields[k2];
|
|
1174
|
+
if (typeof v2 !== "number" || !isFinite(v2)) continue; // only numeric scalars
|
|
1175
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(k2)) continue; // skip prom-incompatible names
|
|
1176
|
+
var metric = prefix + "_" + k2;
|
|
1177
|
+
var declared = fieldTypes[k2];
|
|
1178
|
+
var fieldType;
|
|
1179
|
+
if (declared !== undefined) {
|
|
1180
|
+
if (declared !== "counter" && declared !== "gauge") {
|
|
1181
|
+
throw new MetricsError("metrics-snapshot/bad-field-type",
|
|
1182
|
+
"metrics.snapshot.render: opts.fieldTypes." + k2 + " must be 'counter' or 'gauge', got '" + declared + "'");
|
|
1183
|
+
}
|
|
1184
|
+
fieldType = declared;
|
|
1185
|
+
} else {
|
|
1186
|
+
// Prometheus naming convention + OpenMetrics 1.0.0 §6.2:
|
|
1187
|
+
// counter family names carry the _total suffix.
|
|
1188
|
+
fieldType = /_total$/.test(k2) ? "counter" : "gauge";
|
|
1189
|
+
}
|
|
1190
|
+
out.push("# TYPE " + metric + " " + fieldType);
|
|
1191
|
+
out.push(metric + " " + v2);
|
|
1192
|
+
}
|
|
1193
|
+
// ISO-date string fields → parallel `<name>_epoch_ms` gauge per
|
|
1194
|
+
// OpenMetrics 1.0 §3.4 (Timestamps MUST be float64 Unix-epoch). The
|
|
1195
|
+
// operator-facing text format renders the ISO string verbatim; the
|
|
1196
|
+
// Prometheus / OpenMetrics format gets the epoch-ms equivalent so
|
|
1197
|
+
// downstream alerting can compute durations.
|
|
1198
|
+
for (var jd = 0; jd < keys2.length; jd += 1) {
|
|
1199
|
+
var kd = keys2[jd];
|
|
1200
|
+
var vd = fields[kd];
|
|
1201
|
+
if (typeof vd !== "string") continue;
|
|
1202
|
+
if (vd.length > 64) continue; // allow:raw-byte-literal — ISO 8601 max length cap, not bytes
|
|
1203
|
+
if (!ISO_DATE_RE.test(vd)) continue; // allow:regex-no-length-cap — length-bounded immediately above
|
|
1204
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(kd)) continue; // allow:regex-no-length-cap — field-name shape, length-bounded by snap field naming
|
|
1205
|
+
var ms = Date.parse(vd);
|
|
1206
|
+
if (!isFinite(ms)) continue;
|
|
1207
|
+
var emName = prefix + "_" + kd + "_epoch_ms";
|
|
1208
|
+
out.push("# TYPE " + emName + " gauge");
|
|
1209
|
+
out.push(emName + " " + ms);
|
|
1210
|
+
}
|
|
1211
|
+
return out.join("\n") + "\n";
|
|
1212
|
+
}
|
|
1213
|
+
throw new MetricsError("metrics-snapshot/bad-format",
|
|
1214
|
+
"metrics.snapshot.render: format must be 'text' or 'prometheus', got '" + format + "'");
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
/**
|
|
1218
|
+
* @primitive b.metrics.snapshot.shadowRegistry
|
|
1219
|
+
* @signature b.metrics.snapshot.shadowRegistry(opts)
|
|
1220
|
+
* @since 0.10.9
|
|
1221
|
+
* @status stable
|
|
1222
|
+
* @related b.metrics.snapshot.render, b.metrics.create
|
|
1223
|
+
*
|
|
1224
|
+
* Build a namespaced shadow metrics registry that mirrors a subset of
|
|
1225
|
+
* a primary registry's counters / gauges / info for export to systems
|
|
1226
|
+
* needing isolated views (sidecar / per-tenant scrape endpoint /
|
|
1227
|
+
* compliance-tagged subset). Cardinality cap closes the
|
|
1228
|
+
* [client_golang CVE-2022-21698](https://nvd.nist.gov/vuln/detail/CVE-2022-21698)
|
|
1229
|
+
* unbounded-cardinality DoS class. Returns
|
|
1230
|
+
* `{ inc, set, setInfo, snapshot, render, reset }`.
|
|
1231
|
+
*
|
|
1232
|
+
* @opts
|
|
1233
|
+
* namespace: string, // identifier prefix; required
|
|
1234
|
+
* counters: string[], // counter names to mirror
|
|
1235
|
+
* gauges: string[], // gauge names to mirror
|
|
1236
|
+
* info: string[], // info names to mirror
|
|
1237
|
+
* cardinalityCap: number, // default 10000 per metric name
|
|
1238
|
+
* onCardinalityExceeded: "drop" | "audit-only" | "refuse", // default "drop"
|
|
1239
|
+
*
|
|
1240
|
+
* @example
|
|
1241
|
+
* var shadow = b.metrics.snapshot.shadowRegistry({
|
|
1242
|
+
* namespace: "tenant_a",
|
|
1243
|
+
* counters: ["requests_total", "errors_total"],
|
|
1244
|
+
* gauges: ["queue_depth"],
|
|
1245
|
+
* });
|
|
1246
|
+
* shadow.inc("requests_total");
|
|
1247
|
+
* shadow.set("queue_depth", 42);
|
|
1248
|
+
* shadow.snapshot();
|
|
1249
|
+
*/
|
|
1250
|
+
var SHADOW_DEFAULT_CARDINALITY = 10000; // allow:raw-byte-literal — cardinality cap, not bytes
|
|
1251
|
+
function shadowRegistry(opts) {
|
|
1252
|
+
if (!opts || typeof opts !== "object") {
|
|
1253
|
+
throw new MetricsError("metrics-shadow/bad-opts",
|
|
1254
|
+
"shadowRegistry: opts object required");
|
|
1255
|
+
}
|
|
1256
|
+
validateOpts.requireNonEmptyString(opts.namespace,
|
|
1257
|
+
"shadowRegistry: opts.namespace", MetricsError, "metrics-shadow/bad-namespace");
|
|
1258
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(opts.namespace)) { // allow:regex-no-length-cap — OpenMetrics name-shape, length-bounded by namespace
|
|
1259
|
+
throw new MetricsError("metrics-shadow/bad-namespace",
|
|
1260
|
+
"shadowRegistry: namespace must match [a-zA-Z_][a-zA-Z0-9_]*");
|
|
1261
|
+
}
|
|
1262
|
+
var counterSet = _shadowSetOf(opts.counters, "counters");
|
|
1263
|
+
var gaugeSet = _shadowSetOf(opts.gauges, "gauges");
|
|
1264
|
+
var infoSet = _shadowSetOf(opts.info, "info");
|
|
1265
|
+
var cap = opts.cardinalityCap === undefined ? SHADOW_DEFAULT_CARDINALITY : opts.cardinalityCap;
|
|
1266
|
+
if (typeof cap !== "number" || !isFinite(cap) || cap < 1 || Math.floor(cap) !== cap) {
|
|
1267
|
+
throw new MetricsError("metrics-shadow/bad-cap",
|
|
1268
|
+
"shadowRegistry: cardinalityCap must be a positive integer");
|
|
1269
|
+
}
|
|
1270
|
+
var policy = opts.onCardinalityExceeded || "drop";
|
|
1271
|
+
if (policy !== "drop" && policy !== "audit-only" && policy !== "refuse") {
|
|
1272
|
+
throw new MetricsError("metrics-shadow/bad-policy",
|
|
1273
|
+
"shadowRegistry: onCardinalityExceeded must be 'drop', 'audit-only', or 'refuse'");
|
|
1274
|
+
}
|
|
1275
|
+
var counters = Object.create(null);
|
|
1276
|
+
var gauges = Object.create(null);
|
|
1277
|
+
var info = Object.create(null);
|
|
1278
|
+
var lastCardinalityAuditMs = 0;
|
|
1279
|
+
|
|
1280
|
+
function _cardinalityHit(metric) {
|
|
1281
|
+
var now = Date.now();
|
|
1282
|
+
// Rate-limit cardinality audit emissions to once per second per
|
|
1283
|
+
// shadow registry so a hostile label flood doesn't fan out into
|
|
1284
|
+
// the audit log.
|
|
1285
|
+
if (now - lastCardinalityAuditMs >= C.TIME.seconds(1)) {
|
|
1286
|
+
lastCardinalityAuditMs = now;
|
|
1287
|
+
try {
|
|
1288
|
+
require("./audit").safeEmit({
|
|
1289
|
+
action: "metrics.shadow.cardinality_dropped",
|
|
1290
|
+
outcome: policy === "refuse" ? "denied" : "denied",
|
|
1291
|
+
metadata: { namespace: opts.namespace, metric: metric, cap: cap, policy: policy },
|
|
1292
|
+
});
|
|
1293
|
+
} catch (_e) { /* drop-silent */ }
|
|
1294
|
+
}
|
|
1295
|
+
if (policy === "refuse") {
|
|
1296
|
+
throw new MetricsError("metrics-shadow/cardinality-exceeded",
|
|
1297
|
+
"shadowRegistry.inc/set: '" + metric + "' cardinality exceeds cap=" + cap);
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
function _labelKey(labels) {
|
|
1302
|
+
if (!labels || typeof labels !== "object") return "";
|
|
1303
|
+
var keys = Object.keys(labels).sort(); // allow:bare-canonicalize-walk — label-set canonicalization for cardinality keying
|
|
1304
|
+
var parts = [];
|
|
1305
|
+
for (var i = 0; i < keys.length; i += 1) {
|
|
1306
|
+
parts.push(keys[i] + "=" + String(labels[keys[i]]));
|
|
1307
|
+
}
|
|
1308
|
+
return parts.join(",");
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
function inc(name, labels) {
|
|
1312
|
+
if (!counterSet[name]) return;
|
|
1313
|
+
var lk = _labelKey(labels);
|
|
1314
|
+
if (!counters[name]) counters[name] = Object.create(null);
|
|
1315
|
+
var current = counters[name][lk];
|
|
1316
|
+
if (current === undefined) {
|
|
1317
|
+
if (Object.keys(counters[name]).length >= cap) {
|
|
1318
|
+
_cardinalityHit(name);
|
|
1319
|
+
return;
|
|
1320
|
+
}
|
|
1321
|
+
counters[name][lk] = 1;
|
|
1322
|
+
} else {
|
|
1323
|
+
counters[name][lk] = current + 1;
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
function set(name, value, labels) {
|
|
1328
|
+
if (!gaugeSet[name]) return;
|
|
1329
|
+
if (typeof value !== "number" || !isFinite(value)) {
|
|
1330
|
+
throw new MetricsError("metrics-shadow/bad-gauge-value",
|
|
1331
|
+
"shadowRegistry.set: '" + name + "' value must be a finite number");
|
|
1332
|
+
}
|
|
1333
|
+
var lk = _labelKey(labels);
|
|
1334
|
+
if (!gauges[name]) gauges[name] = Object.create(null);
|
|
1335
|
+
if (gauges[name][lk] === undefined && Object.keys(gauges[name]).length >= cap) {
|
|
1336
|
+
_cardinalityHit(name);
|
|
1337
|
+
return;
|
|
1338
|
+
}
|
|
1339
|
+
gauges[name][lk] = value;
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
function setInfo(name, value) {
|
|
1343
|
+
if (!infoSet[name]) return;
|
|
1344
|
+
info[name] = value;
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
function snapshotShadow() {
|
|
1348
|
+
return Object.freeze({
|
|
1349
|
+
namespace: opts.namespace,
|
|
1350
|
+
counters: _shallowClone(counters),
|
|
1351
|
+
gauges: _shallowClone(gauges),
|
|
1352
|
+
info: Object.assign({}, info),
|
|
1353
|
+
});
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
function renderShadow(renderOpts) {
|
|
1357
|
+
renderOpts = renderOpts || {};
|
|
1358
|
+
var format = renderOpts.format || "text";
|
|
1359
|
+
// Prometheus / OpenMetrics — emit labeled metric lines directly so
|
|
1360
|
+
// counters / gauges with label sets survive the export. Routing
|
|
1361
|
+
// through `snapshotRender` would have filtered synthetic
|
|
1362
|
+
// `name{labelKey=value}` field names against the Prometheus
|
|
1363
|
+
// metric-name shape `[a-zA-Z_][a-zA-Z0-9_]*` and dropped them all.
|
|
1364
|
+
if (format === "prometheus" || format === "openmetrics") {
|
|
1365
|
+
var out = [];
|
|
1366
|
+
var prefix = opts.namespace;
|
|
1367
|
+
function _emitLabeled(name, labelMap, kind) {
|
|
1368
|
+
var metric = prefix + "_" + name;
|
|
1369
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(metric)) return; // allow:regex-no-length-cap — Prometheus name-shape; metric length bounded by namespace + name caps
|
|
1370
|
+
out.push("# TYPE " + metric + " " + kind);
|
|
1371
|
+
var lks = Object.keys(labelMap);
|
|
1372
|
+
for (var li = 0; li < lks.length; li += 1) {
|
|
1373
|
+
var lk = lks[li];
|
|
1374
|
+
if (lk === "") { out.push(metric + " " + labelMap[lk]); continue; }
|
|
1375
|
+
// The label-key string was assembled by `_labelKey` from a
|
|
1376
|
+
// single shadow-registry call's `labels` object — values
|
|
1377
|
+
// are framework-internal (operator code that supplied them
|
|
1378
|
+
// is bounded by guards upstream); split on `,` is safe.
|
|
1379
|
+
// Not a header-value parse (which would need a quoted-
|
|
1380
|
+
// string aware split per RFC 9110).
|
|
1381
|
+
var lpairs = lk.split(","); // allow:bare-split-on-quoted-header — framework-internal label-key (assembled by _labelKey), not an HTTP header parse
|
|
1382
|
+
var formatted = [];
|
|
1383
|
+
for (var pi = 0; pi < lpairs.length; pi += 1) {
|
|
1384
|
+
var eqIdx = lpairs[pi].indexOf("=");
|
|
1385
|
+
if (eqIdx === -1) continue;
|
|
1386
|
+
var lname = lpairs[pi].slice(0, eqIdx);
|
|
1387
|
+
var lvalue = lpairs[pi].slice(eqIdx + 1);
|
|
1388
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(lname)) continue; // allow:regex-no-length-cap — Prometheus label-name shape
|
|
1389
|
+
// Prometheus exposition: escape `\`, `"`, `\n` in label values.
|
|
1390
|
+
lvalue = String(lvalue).replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n"); // allow:regex-no-length-cap — fixed-char-set escape // allow:duplicate-regex — Prometheus value escape shape
|
|
1391
|
+
formatted.push(lname + '="' + lvalue + '"');
|
|
1392
|
+
}
|
|
1393
|
+
out.push(metric + "{" + formatted.join(",") + "} " + labelMap[lk]);
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
var cn2 = Object.keys(counters);
|
|
1397
|
+
for (var ci = 0; ci < cn2.length; ci += 1) {
|
|
1398
|
+
_emitLabeled(cn2[ci], counters[cn2[ci]], /_total$/.test(cn2[ci]) ? "counter" : "gauge"); // allow:regex-no-length-cap — name-suffix check
|
|
1399
|
+
}
|
|
1400
|
+
var gn2 = Object.keys(gauges);
|
|
1401
|
+
for (var ggi = 0; ggi < gn2.length; ggi += 1) {
|
|
1402
|
+
_emitLabeled(gn2[ggi], gauges[gn2[ggi]], "gauge");
|
|
1403
|
+
}
|
|
1404
|
+
return out.join("\n") + (out.length ? "\n" : "");
|
|
1405
|
+
}
|
|
1406
|
+
// Text format — route through snapshotRender via synthetic field
|
|
1407
|
+
// names. The text-format renderer accepts arbitrary field names so
|
|
1408
|
+
// labeled series survive here.
|
|
1409
|
+
var snap = { writtenAt: new Date().toISOString(), fields: {} };
|
|
1410
|
+
var cn = Object.keys(counters);
|
|
1411
|
+
for (var i = 0; i < cn.length; i += 1) {
|
|
1412
|
+
var labels = counters[cn[i]];
|
|
1413
|
+
var labelKeys = Object.keys(labels);
|
|
1414
|
+
if (labelKeys.length === 1 && labelKeys[0] === "") {
|
|
1415
|
+
snap.fields[cn[i]] = labels[""];
|
|
1416
|
+
} else {
|
|
1417
|
+
for (var j = 0; j < labelKeys.length; j += 1) {
|
|
1418
|
+
var key = labelKeys[j] === "" ? cn[i] : cn[i] + "{" + labelKeys[j] + "}";
|
|
1419
|
+
snap.fields[key] = labels[labelKeys[j]];
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
var gn = Object.keys(gauges);
|
|
1424
|
+
for (var gi = 0; gi < gn.length; gi += 1) {
|
|
1425
|
+
var glabels = gauges[gn[gi]];
|
|
1426
|
+
var glk = Object.keys(glabels);
|
|
1427
|
+
if (glk.length === 1 && glk[0] === "") {
|
|
1428
|
+
snap.fields[gn[gi]] = glabels[""];
|
|
1429
|
+
} else {
|
|
1430
|
+
for (var gj = 0; gj < glk.length; gj += 1) {
|
|
1431
|
+
var gkey = glk[gj] === "" ? gn[gi] : gn[gi] + "{" + glk[gj] + "}";
|
|
1432
|
+
snap.fields[gkey] = glabels[glk[gj]];
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
var inames = Object.keys(info);
|
|
1437
|
+
for (var ii = 0; ii < inames.length; ii += 1) snap.fields[inames[ii]] = info[inames[ii]];
|
|
1438
|
+
return snapshotRender(snap, Object.assign({ prefix: opts.namespace }, renderOpts));
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
function reset() {
|
|
1442
|
+
counters = Object.create(null);
|
|
1443
|
+
gauges = Object.create(null);
|
|
1444
|
+
info = Object.create(null);
|
|
1445
|
+
lastCardinalityAuditMs = 0;
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
return {
|
|
1449
|
+
inc: inc,
|
|
1450
|
+
set: set,
|
|
1451
|
+
setInfo: setInfo,
|
|
1452
|
+
snapshot: snapshotShadow,
|
|
1453
|
+
render: renderShadow,
|
|
1454
|
+
reset: reset,
|
|
1455
|
+
};
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
function _shadowSetOf(arr, label) {
|
|
1459
|
+
if (arr === undefined) return Object.create(null);
|
|
1460
|
+
if (!Array.isArray(arr)) {
|
|
1461
|
+
throw new MetricsError("metrics-shadow/bad-" + label,
|
|
1462
|
+
"shadowRegistry: opts." + label + " must be an array of metric names");
|
|
1463
|
+
}
|
|
1464
|
+
var set = Object.create(null);
|
|
1465
|
+
for (var i = 0; i < arr.length; i += 1) {
|
|
1466
|
+
if (typeof arr[i] !== "string" || arr[i].length === 0) {
|
|
1467
|
+
throw new MetricsError("metrics-shadow/bad-" + label,
|
|
1468
|
+
"shadowRegistry: opts." + label + "[" + i + "] must be a non-empty string");
|
|
1469
|
+
}
|
|
1470
|
+
set[arr[i]] = true;
|
|
1471
|
+
}
|
|
1472
|
+
return set;
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
function _shallowClone(obj) {
|
|
1476
|
+
var out = Object.create(null);
|
|
1477
|
+
var keys = Object.keys(obj);
|
|
1478
|
+
for (var i = 0; i < keys.length; i += 1) {
|
|
1479
|
+
out[keys[i]] = Object.assign(Object.create(null), obj[keys[i]]);
|
|
1480
|
+
}
|
|
1481
|
+
return out;
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
var snapshot = {
|
|
1485
|
+
startWriter: snapshotStartWriter,
|
|
1486
|
+
read: snapshotRead,
|
|
1487
|
+
render: snapshotRender,
|
|
1488
|
+
shadowRegistry: shadowRegistry,
|
|
1489
|
+
};
|
|
1490
|
+
|
|
1491
|
+
module.exports = {
|
|
1492
|
+
create: create,
|
|
1493
|
+
tap: tap,
|
|
1494
|
+
snapshot: snapshot,
|
|
1495
|
+
MetricsError: MetricsError,
|
|
1496
|
+
DEFAULT_HTTP_BUCKETS: DEFAULT_HTTP_BUCKETS,
|
|
1497
|
+
DEFAULT_CARDINALITY_CAP: DEFAULT_CARDINALITY_CAP,
|
|
1498
|
+
_resetForTest: _resetForTest,
|
|
1499
|
+
// Internal helpers for tests
|
|
1500
|
+
_labelsKey: _labelsKey,
|
|
1501
|
+
_renderLabels: _renderLabels,
|
|
1502
|
+
_escapeLabelValue: _escapeLabelValue,
|
|
1503
|
+
};
|