@blamejs/blamejs-shop 0.4.55 → 0.4.57
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 +4 -0
- package/lib/admin.js +385 -2
- package/lib/asset-manifest.json +1 -1
- package/lib/vendor/MANIFEST.json +426 -366
- package/lib/vendor/blamejs/.github/codeql/codeql-config.yml +25 -0
- package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +1 -1
- package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +1 -1
- package/lib/vendor/blamejs/.github/workflows/ci.yml +13 -13
- package/lib/vendor/blamejs/.github/workflows/codeql.yml +8 -7
- package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +2 -2
- package/lib/vendor/blamejs/.github/workflows/release-container.yml +4 -4
- package/lib/vendor/blamejs/.github/workflows/scorecard.yml +1 -1
- package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
- package/lib/vendor/blamejs/CHANGELOG.md +2 -0
- package/lib/vendor/blamejs/api-snapshot.json +1381 -4
- package/lib/vendor/blamejs/eslint.config.mjs +1 -0
- package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +4 -1
- package/lib/vendor/blamejs/examples/wiki/lib/symbol-index.js +5 -2
- package/lib/vendor/blamejs/examples/wiki/routes/pages.js +4 -1
- package/lib/vendor/blamejs/fuzz/guard-text.fuzz.js +20 -0
- package/lib/vendor/blamejs/index.js +2 -0
- package/lib/vendor/blamejs/lib/a2a-tasks.js +7 -23
- package/lib/vendor/blamejs/lib/acme.js +6 -5
- package/lib/vendor/blamejs/lib/agent-event-bus.js +5 -4
- package/lib/vendor/blamejs/lib/agent-idempotency.js +2 -5
- package/lib/vendor/blamejs/lib/agent-orchestrator.js +2 -5
- package/lib/vendor/blamejs/lib/agent-saga.js +3 -5
- package/lib/vendor/blamejs/lib/agent-tenant.js +2 -5
- package/lib/vendor/blamejs/lib/ai-adverse-decision.js +2 -15
- package/lib/vendor/blamejs/lib/ai-capability.js +1 -6
- package/lib/vendor/blamejs/lib/ai-dp.js +1 -5
- package/lib/vendor/blamejs/lib/ai-input.js +2 -2
- package/lib/vendor/blamejs/lib/ai-pref.js +3 -8
- package/lib/vendor/blamejs/lib/ai-quota.js +3 -14
- package/lib/vendor/blamejs/lib/api-key.js +37 -28
- package/lib/vendor/blamejs/lib/archive-adapters.js +2 -4
- package/lib/vendor/blamejs/lib/archive-entry-policy.js +32 -0
- package/lib/vendor/blamejs/lib/archive-read.js +5 -17
- package/lib/vendor/blamejs/lib/archive-tar-read.js +5 -16
- package/lib/vendor/blamejs/lib/archive.js +2 -10
- package/lib/vendor/blamejs/lib/arg-parser.js +7 -6
- package/lib/vendor/blamejs/lib/asyncapi-traits.js +2 -6
- package/lib/vendor/blamejs/lib/atomic-file.js +108 -31
- package/lib/vendor/blamejs/lib/audit-chain.js +133 -53
- package/lib/vendor/blamejs/lib/audit-daily-review.js +24 -14
- package/lib/vendor/blamejs/lib/audit-emit.js +82 -0
- package/lib/vendor/blamejs/lib/audit-sign.js +257 -0
- package/lib/vendor/blamejs/lib/audit.js +84 -0
- package/lib/vendor/blamejs/lib/auth/access-lock.js +5 -27
- package/lib/vendor/blamejs/lib/auth/dpop.js +23 -35
- package/lib/vendor/blamejs/lib/auth/fido-mds3.js +9 -15
- package/lib/vendor/blamejs/lib/auth/jwt-external.js +26 -8
- package/lib/vendor/blamejs/lib/auth/jwt.js +13 -15
- package/lib/vendor/blamejs/lib/auth/lockout.js +6 -25
- package/lib/vendor/blamejs/lib/auth/oauth.js +67 -45
- package/lib/vendor/blamejs/lib/auth/oid4vci.js +55 -32
- package/lib/vendor/blamejs/lib/auth/oid4vp.js +3 -2
- package/lib/vendor/blamejs/lib/auth/openid-federation.js +6 -6
- package/lib/vendor/blamejs/lib/auth/passkey.js +3 -3
- package/lib/vendor/blamejs/lib/auth/password.js +7 -1
- package/lib/vendor/blamejs/lib/auth/saml.js +37 -27
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-holder.js +2 -14
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-issuer.js +2 -14
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +1 -1
- package/lib/vendor/blamejs/lib/auth/status-list.js +7 -7
- package/lib/vendor/blamejs/lib/auth/step-up.js +6 -12
- package/lib/vendor/blamejs/lib/auth-bot-challenge.js +6 -37
- package/lib/vendor/blamejs/lib/backup/bundle.js +11 -18
- package/lib/vendor/blamejs/lib/backup/index.js +14 -47
- package/lib/vendor/blamejs/lib/bounded-map.js +112 -1
- package/lib/vendor/blamejs/lib/breach-deadline.js +1 -11
- package/lib/vendor/blamejs/lib/cache.js +7 -18
- package/lib/vendor/blamejs/lib/cbor.js +2 -1
- package/lib/vendor/blamejs/lib/cdn-cache-control.js +8 -9
- package/lib/vendor/blamejs/lib/cert.js +3 -10
- package/lib/vendor/blamejs/lib/chain-writer.js +162 -47
- package/lib/vendor/blamejs/lib/cli.js +5 -1
- package/lib/vendor/blamejs/lib/client-hints.js +7 -9
- package/lib/vendor/blamejs/lib/cloud-events.js +40 -31
- package/lib/vendor/blamejs/lib/cluster-storage.js +2 -38
- package/lib/vendor/blamejs/lib/cms-codec.js +2 -1
- package/lib/vendor/blamejs/lib/codepoint-class.js +67 -1
- package/lib/vendor/blamejs/lib/compliance-ai-act-logging.js +1 -6
- package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +2 -4
- package/lib/vendor/blamejs/lib/compliance-eaa.js +1 -11
- package/lib/vendor/blamejs/lib/compliance-sanctions-fetcher.js +21 -28
- package/lib/vendor/blamejs/lib/compliance-sanctions.js +2 -14
- package/lib/vendor/blamejs/lib/compliance.js +2 -9
- package/lib/vendor/blamejs/lib/config-drift.js +2 -12
- package/lib/vendor/blamejs/lib/content-digest.js +10 -8
- package/lib/vendor/blamejs/lib/cookies.js +5 -11
- package/lib/vendor/blamejs/lib/cose.js +19 -11
- package/lib/vendor/blamejs/lib/cra-report.js +1 -11
- package/lib/vendor/blamejs/lib/crypto-field.js +5 -10
- package/lib/vendor/blamejs/lib/crypto.js +120 -3
- package/lib/vendor/blamejs/lib/csp.js +235 -3
- package/lib/vendor/blamejs/lib/daemon.js +42 -41
- package/lib/vendor/blamejs/lib/data-act.js +19 -9
- package/lib/vendor/blamejs/lib/db-query.js +6 -40
- package/lib/vendor/blamejs/lib/db.js +34 -12
- package/lib/vendor/blamejs/lib/dbsc.js +5 -6
- package/lib/vendor/blamejs/lib/ddl-change-control.js +18 -14
- package/lib/vendor/blamejs/lib/deprecate.js +4 -5
- package/lib/vendor/blamejs/lib/did.js +6 -2
- package/lib/vendor/blamejs/lib/dsr.js +8 -12
- package/lib/vendor/blamejs/lib/external-db-migrate.js +21 -22
- package/lib/vendor/blamejs/lib/external-db.js +14 -26
- package/lib/vendor/blamejs/lib/fda-21cfr11.js +12 -8
- package/lib/vendor/blamejs/lib/fdx.js +22 -18
- package/lib/vendor/blamejs/lib/file-upload.js +80 -66
- package/lib/vendor/blamejs/lib/flag-evaluation-context.js +5 -8
- package/lib/vendor/blamejs/lib/framework-error.js +12 -0
- package/lib/vendor/blamejs/lib/framework-schema.js +19 -0
- package/lib/vendor/blamejs/lib/fsm.js +7 -12
- package/lib/vendor/blamejs/lib/gate-contract.js +869 -38
- package/lib/vendor/blamejs/lib/gdpr-ropa.js +4 -13
- package/lib/vendor/blamejs/lib/graphql-federation.js +1 -1
- package/lib/vendor/blamejs/lib/guard-agent-registry.js +2 -1
- package/lib/vendor/blamejs/lib/guard-all.js +1 -0
- package/lib/vendor/blamejs/lib/guard-archive.js +9 -30
- package/lib/vendor/blamejs/lib/guard-auth.js +23 -80
- package/lib/vendor/blamejs/lib/guard-cidr.js +20 -96
- package/lib/vendor/blamejs/lib/guard-csv.js +135 -196
- package/lib/vendor/blamejs/lib/guard-domain.js +23 -106
- package/lib/vendor/blamejs/lib/guard-dsn.js +16 -13
- package/lib/vendor/blamejs/lib/guard-email.js +46 -53
- package/lib/vendor/blamejs/lib/guard-envelope.js +1 -1
- package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +2 -1
- package/lib/vendor/blamejs/lib/guard-filename.js +12 -60
- package/lib/vendor/blamejs/lib/guard-graphql.js +28 -75
- package/lib/vendor/blamejs/lib/guard-html-wcag.js +15 -2
- package/lib/vendor/blamejs/lib/guard-html.js +65 -117
- package/lib/vendor/blamejs/lib/guard-idempotency-key.js +2 -1
- package/lib/vendor/blamejs/lib/guard-image.js +280 -77
- package/lib/vendor/blamejs/lib/guard-imap-command.js +8 -9
- package/lib/vendor/blamejs/lib/guard-json.js +87 -103
- package/lib/vendor/blamejs/lib/guard-jsonpath.js +20 -88
- package/lib/vendor/blamejs/lib/guard-jwt.js +32 -114
- package/lib/vendor/blamejs/lib/guard-list-id.js +2 -7
- package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -7
- package/lib/vendor/blamejs/lib/guard-mail-compose.js +5 -6
- package/lib/vendor/blamejs/lib/guard-mail-move.js +2 -1
- package/lib/vendor/blamejs/lib/guard-mail-query.js +5 -3
- package/lib/vendor/blamejs/lib/guard-mail-sieve.js +6 -7
- package/lib/vendor/blamejs/lib/guard-managesieve-command.js +5 -4
- package/lib/vendor/blamejs/lib/guard-markdown.js +76 -110
- package/lib/vendor/blamejs/lib/guard-message-id.js +5 -6
- package/lib/vendor/blamejs/lib/guard-mime.js +20 -99
- package/lib/vendor/blamejs/lib/guard-oauth.js +19 -73
- package/lib/vendor/blamejs/lib/guard-pdf.js +65 -72
- package/lib/vendor/blamejs/lib/guard-pop3-command.js +12 -13
- package/lib/vendor/blamejs/lib/guard-posture-chain.js +2 -1
- package/lib/vendor/blamejs/lib/guard-regex.js +24 -99
- package/lib/vendor/blamejs/lib/guard-saga-config.js +2 -1
- package/lib/vendor/blamejs/lib/guard-shell.js +22 -87
- package/lib/vendor/blamejs/lib/guard-smtp-command.js +8 -11
- package/lib/vendor/blamejs/lib/guard-sql.js +15 -13
- package/lib/vendor/blamejs/lib/guard-stream-args.js +2 -1
- package/lib/vendor/blamejs/lib/guard-svg.js +95 -140
- package/lib/vendor/blamejs/lib/guard-template.js +23 -80
- package/lib/vendor/blamejs/lib/guard-tenant-id.js +2 -1
- package/lib/vendor/blamejs/lib/guard-text.js +592 -0
- package/lib/vendor/blamejs/lib/guard-time.js +27 -95
- package/lib/vendor/blamejs/lib/guard-uuid.js +21 -93
- package/lib/vendor/blamejs/lib/guard-xml.js +76 -106
- package/lib/vendor/blamejs/lib/guard-yaml.js +24 -60
- package/lib/vendor/blamejs/lib/http-client-cache.js +5 -12
- package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +2 -4
- package/lib/vendor/blamejs/lib/http-client.js +8 -21
- package/lib/vendor/blamejs/lib/http-message-signature.js +3 -2
- package/lib/vendor/blamejs/lib/i18n-messageformat.js +5 -7
- package/lib/vendor/blamejs/lib/i18n.js +83 -26
- package/lib/vendor/blamejs/lib/inbox.js +8 -8
- package/lib/vendor/blamejs/lib/incident-report.js +3 -21
- package/lib/vendor/blamejs/lib/ip-utils.js +49 -6
- package/lib/vendor/blamejs/lib/jobs.js +3 -2
- package/lib/vendor/blamejs/lib/keychain.js +6 -18
- package/lib/vendor/blamejs/lib/legal-hold.js +6 -15
- package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +44 -112
- package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +17 -14
- package/lib/vendor/blamejs/lib/log-stream-otlp.js +16 -80
- package/lib/vendor/blamejs/lib/log-stream-webhook.js +20 -92
- package/lib/vendor/blamejs/lib/mail-arc-sign.js +8 -3
- package/lib/vendor/blamejs/lib/mail-arf.js +3 -2
- package/lib/vendor/blamejs/lib/mail-auth.js +40 -66
- package/lib/vendor/blamejs/lib/mail-bimi.js +19 -39
- package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +3 -2
- package/lib/vendor/blamejs/lib/mail-dav.js +8 -35
- package/lib/vendor/blamejs/lib/mail-deploy.js +6 -9
- package/lib/vendor/blamejs/lib/mail-dkim.js +19 -38
- package/lib/vendor/blamejs/lib/mail-greylist.js +15 -26
- package/lib/vendor/blamejs/lib/mail-helo.js +2 -3
- package/lib/vendor/blamejs/lib/mail-journal.js +2 -1
- package/lib/vendor/blamejs/lib/mail-mdn.js +4 -3
- package/lib/vendor/blamejs/lib/mail-rbl.js +5 -8
- package/lib/vendor/blamejs/lib/mail-scan.js +2 -2
- package/lib/vendor/blamejs/lib/mail-send-deliver.js +33 -20
- package/lib/vendor/blamejs/lib/mail-server-imap.js +32 -87
- package/lib/vendor/blamejs/lib/mail-server-jmap.js +35 -51
- package/lib/vendor/blamejs/lib/mail-server-managesieve.js +29 -83
- package/lib/vendor/blamejs/lib/mail-server-mx.js +33 -74
- package/lib/vendor/blamejs/lib/mail-server-net.js +177 -0
- package/lib/vendor/blamejs/lib/mail-server-pop3.js +30 -83
- package/lib/vendor/blamejs/lib/mail-server-rate-limit.js +30 -6
- package/lib/vendor/blamejs/lib/mail-server-submission.js +34 -73
- package/lib/vendor/blamejs/lib/mail-server-tls.js +89 -0
- package/lib/vendor/blamejs/lib/mail-spam-score.js +7 -8
- package/lib/vendor/blamejs/lib/mail-store.js +3 -2
- package/lib/vendor/blamejs/lib/mail.js +6 -11
- package/lib/vendor/blamejs/lib/markup-escape.js +31 -0
- package/lib/vendor/blamejs/lib/markup-tokenizer.js +54 -0
- package/lib/vendor/blamejs/lib/mcp-tool-registry.js +26 -23
- package/lib/vendor/blamejs/lib/mcp.js +1 -1
- package/lib/vendor/blamejs/lib/mdoc.js +11 -12
- package/lib/vendor/blamejs/lib/metrics.js +32 -30
- package/lib/vendor/blamejs/lib/middleware/age-gate.js +3 -23
- package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +11 -22
- package/lib/vendor/blamejs/lib/middleware/assetlinks.js +2 -7
- package/lib/vendor/blamejs/lib/middleware/bearer-auth.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/body-parser.js +31 -48
- package/lib/vendor/blamejs/lib/middleware/bot-disclose.js +7 -10
- package/lib/vendor/blamejs/lib/middleware/bot-guard.js +2 -10
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +13 -2
- package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +6 -26
- package/lib/vendor/blamejs/lib/middleware/deny-response.js +19 -1
- package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +7 -0
- package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +4 -20
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +20 -28
- package/lib/vendor/blamejs/lib/middleware/scim-server.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/security-headers.js +9 -1
- package/lib/vendor/blamejs/lib/middleware/security-txt.js +2 -6
- package/lib/vendor/blamejs/lib/middleware/tus-upload.js +12 -27
- package/lib/vendor/blamejs/lib/middleware/web-app-manifest.js +2 -7
- package/lib/vendor/blamejs/lib/migrations.js +4 -13
- package/lib/vendor/blamejs/lib/mime-parse.js +34 -17
- package/lib/vendor/blamejs/lib/module-loader.js +44 -0
- package/lib/vendor/blamejs/lib/money.js +105 -0
- package/lib/vendor/blamejs/lib/mtls-ca.js +116 -36
- package/lib/vendor/blamejs/lib/network-byte-quota.js +4 -18
- package/lib/vendor/blamejs/lib/network-dane.js +8 -6
- package/lib/vendor/blamejs/lib/network-dns-resolver.js +97 -6
- package/lib/vendor/blamejs/lib/network-dnssec.js +16 -16
- package/lib/vendor/blamejs/lib/network-heartbeat.js +3 -2
- package/lib/vendor/blamejs/lib/network-smtp-policy.js +29 -41
- package/lib/vendor/blamejs/lib/network-tls.js +40 -42
- package/lib/vendor/blamejs/lib/nis2-report.js +1 -11
- package/lib/vendor/blamejs/lib/nonce-store.js +81 -3
- package/lib/vendor/blamejs/lib/numeric-bounds.js +22 -8
- package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +2 -6
- package/lib/vendor/blamejs/lib/object-store/azure-blob.js +5 -45
- package/lib/vendor/blamejs/lib/object-store/gcs.js +8 -71
- package/lib/vendor/blamejs/lib/object-store/http-put.js +1 -5
- package/lib/vendor/blamejs/lib/object-store/http-request.js +128 -0
- package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +2 -1
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +9 -77
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +9 -25
- package/lib/vendor/blamejs/lib/observability.js +95 -0
- package/lib/vendor/blamejs/lib/openapi-paths-builder.js +7 -3
- package/lib/vendor/blamejs/lib/otel-export.js +7 -10
- package/lib/vendor/blamejs/lib/outbox.js +43 -37
- package/lib/vendor/blamejs/lib/pagination.js +11 -15
- package/lib/vendor/blamejs/lib/parsers/safe-env.js +5 -4
- package/lib/vendor/blamejs/lib/parsers/safe-ini.js +10 -4
- package/lib/vendor/blamejs/lib/parsers/safe-toml.js +11 -9
- package/lib/vendor/blamejs/lib/parsers/safe-xml.js +2 -2
- package/lib/vendor/blamejs/lib/parsers/safe-yaml.js +7 -6
- package/lib/vendor/blamejs/lib/pick.js +63 -5
- package/lib/vendor/blamejs/lib/pipl-cn.js +69 -59
- package/lib/vendor/blamejs/lib/privacy-pass.js +8 -6
- package/lib/vendor/blamejs/lib/problem-details.js +2 -5
- package/lib/vendor/blamejs/lib/pubsub.js +4 -8
- package/lib/vendor/blamejs/lib/redact.js +2 -1
- package/lib/vendor/blamejs/lib/render.js +4 -2
- package/lib/vendor/blamejs/lib/request-helpers.js +133 -6
- package/lib/vendor/blamejs/lib/restore.js +5 -22
- package/lib/vendor/blamejs/lib/retention.js +3 -5
- package/lib/vendor/blamejs/lib/safe-async.js +457 -0
- package/lib/vendor/blamejs/lib/safe-buffer.js +137 -6
- package/lib/vendor/blamejs/lib/safe-decompress.js +2 -1
- package/lib/vendor/blamejs/lib/safe-dns.js +2 -1
- package/lib/vendor/blamejs/lib/safe-ical.js +12 -26
- package/lib/vendor/blamejs/lib/safe-json.js +7 -8
- package/lib/vendor/blamejs/lib/safe-jsonpath.js +6 -5
- package/lib/vendor/blamejs/lib/safe-mime.js +25 -29
- package/lib/vendor/blamejs/lib/safe-redirect.js +2 -5
- package/lib/vendor/blamejs/lib/safe-schema.js +7 -6
- package/lib/vendor/blamejs/lib/safe-sql.js +126 -0
- package/lib/vendor/blamejs/lib/safe-vcard.js +12 -26
- package/lib/vendor/blamejs/lib/sandbox-worker.js +9 -2
- package/lib/vendor/blamejs/lib/sandbox.js +3 -2
- package/lib/vendor/blamejs/lib/scheduler.js +5 -12
- package/lib/vendor/blamejs/lib/sec-cyber.js +82 -37
- package/lib/vendor/blamejs/lib/seeders.js +4 -11
- package/lib/vendor/blamejs/lib/self-update.js +92 -69
- package/lib/vendor/blamejs/lib/session-device-binding.js +112 -66
- package/lib/vendor/blamejs/lib/session.js +194 -6
- package/lib/vendor/blamejs/lib/sql.js +225 -78
- package/lib/vendor/blamejs/lib/sse.js +6 -10
- package/lib/vendor/blamejs/lib/static.js +136 -98
- package/lib/vendor/blamejs/lib/storage.js +4 -2
- package/lib/vendor/blamejs/lib/structured-fields.js +275 -16
- package/lib/vendor/blamejs/lib/tenant-quota.js +2 -20
- package/lib/vendor/blamejs/lib/tsa.js +11 -15
- package/lib/vendor/blamejs/lib/validate-opts.js +154 -8
- package/lib/vendor/blamejs/lib/vault/seal-pem-file.js +30 -48
- package/lib/vendor/blamejs/lib/vault-aad.js +3 -2
- package/lib/vendor/blamejs/lib/vc.js +2 -7
- package/lib/vendor/blamejs/lib/vex.js +35 -13
- package/lib/vendor/blamejs/lib/web-push-vapid.js +23 -20
- package/lib/vendor/blamejs/lib/webhook-dispatcher.js +706 -0
- package/lib/vendor/blamejs/lib/webhook.js +43 -18
- package/lib/vendor/blamejs/lib/websocket-channels.js +9 -7
- package/lib/vendor/blamejs/lib/websocket.js +7 -3
- package/lib/vendor/blamejs/lib/worm.js +2 -3
- package/lib/vendor/blamejs/lib/ws-client.js +8 -10
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.15.13.json +81 -0
- package/lib/vendor/blamejs/scripts/check-changelog-extract.js +1 -1
- package/lib/vendor/blamejs/test/00-primitives.js +136 -7
- package/lib/vendor/blamejs/test/10-state.js +9 -3
- package/lib/vendor/blamejs/test/30-chain.js +40 -0
- package/lib/vendor/blamejs/test/helpers/check.js +18 -0
- package/lib/vendor/blamejs/test/helpers/db.js +4 -0
- package/lib/vendor/blamejs/test/helpers/index.js +1 -0
- package/lib/vendor/blamejs/test/integration/audit-chain-external-db.test.js +2 -1
- package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +2 -1
- package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +8 -1
- package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +1 -1
- package/lib/vendor/blamejs/test/integration/framework-schema-mysql.test.js +2 -1
- package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +269 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-fd-read.test.js +149 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-framework-namespaces.test.js +51 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +88 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-use-store.test.js +55 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-object-store-adapter.test.js +2 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/bot-guard.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/bounded-map.test.js +129 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/chain-writer-multichain.test.js +107 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-api-key.test.js +12 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +2788 -3214
- package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +78 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-base64url.test.js +63 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +2 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-builder.test.js +50 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-nonce.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +2 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/defineguard-resolve-opts.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +9 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract-content-gate.test.js +290 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +84 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-email.test.js +78 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +23 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-gate-disposition-coverage.test.js +93 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +60 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +184 -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-json.test.js +54 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +10 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +45 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +101 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-text.test.js +365 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-xml.test.js +35 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-yaml.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +20 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +15 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-arf.test.js +10 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +39 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-greylist.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-tls.test.js +39 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mime-parse.test.js +106 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/money.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-revocation.test.js +98 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-release.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-memory-getorinsert.test.js +100 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +88 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-async-loops.test.js +278 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +37 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-jsonpath.test.js +14 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sandbox.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +2 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/session-valid-from.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +100 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/structured-fields.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/validate-opts-shape.test.js +235 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +374 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +75 -8
- package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +3 -3
- package/lib/winback-campaigns.js +202 -42
- package/package.json +1 -1
|
@@ -277,6 +277,32 @@ Money.prototype.multiply = function (factor, opts) {
|
|
|
277
277
|
return new Money(quotient, this.currency);
|
|
278
278
|
};
|
|
279
279
|
|
|
280
|
+
/**
|
|
281
|
+
* @primitive b.money.Money.roundToIncrement
|
|
282
|
+
* @signature b.money.Money.roundToIncrement(step, opts?)
|
|
283
|
+
* @since 0.15.13
|
|
284
|
+
* @status stable
|
|
285
|
+
* @related b.money.roundMinor, b.money.Money
|
|
286
|
+
*
|
|
287
|
+
* Snap this amount to the nearest multiple of `step` minor units, returning a
|
|
288
|
+
* new `Money` in the same currency — the cash-rounding step a coarser
|
|
289
|
+
* denomination needs (CHF to the nearest 0.05, SEK to the nearest 0.10, a
|
|
290
|
+
* 100-unit price step) without leaving the type. Integer-only; immutable;
|
|
291
|
+
* negative amounts (refund previews) round on the correct side of the tie. See
|
|
292
|
+
* `b.money.roundMinor` for the raw-integer form and the mode semantics.
|
|
293
|
+
*
|
|
294
|
+
* @opts
|
|
295
|
+
* mode: "half-even" | "half-up" | "half-down" | "ceiling" | "floor", // default: half-even
|
|
296
|
+
*
|
|
297
|
+
* @example
|
|
298
|
+
* b.money.of("12.32", "CHF").roundToIncrement(5, { mode: "half-up" }); // → CHF 12.30
|
|
299
|
+
* b.money.of("19.97", "SEK").roundToIncrement(10); // → SEK 20.00
|
|
300
|
+
*/
|
|
301
|
+
Money.prototype.roundToIncrement = function (step, opts) {
|
|
302
|
+
opts = opts || {};
|
|
303
|
+
return new Money(roundMinor(this._minor, step, opts.mode || "half-even"), this.currency);
|
|
304
|
+
};
|
|
305
|
+
|
|
280
306
|
// _rationalFromDecimalString -- `"1.085"` -> { num: 1085n, den: 1000n }.
|
|
281
307
|
// Strict shape; same refusals as _parseDecimalString.
|
|
282
308
|
function _rationalFromDecimalString(s) {
|
|
@@ -333,6 +359,84 @@ function _divRound(n, d, rounding) {
|
|
|
333
359
|
return r < 0n ? q - 1n : q + 1n;
|
|
334
360
|
}
|
|
335
361
|
|
|
362
|
+
// Cash-rounding modes for roundMinor / Money.roundToIncrement. half-even
|
|
363
|
+
// (banker's) is the default and matches the rest of the module; half-up rounds
|
|
364
|
+
// a tie away from zero, half-down toward zero; ceiling/floor are directional
|
|
365
|
+
// (toward +inf / -inf) regardless of distance.
|
|
366
|
+
var INCREMENT_MODES = {
|
|
367
|
+
"half-even": true, "half-up": true, "half-down": true, "ceiling": true, "floor": true,
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
function _toIncrementBigInt(step) {
|
|
371
|
+
if (typeof step === "bigint") {
|
|
372
|
+
if (step <= 0n) throw new MoneyError("money/bad-increment",
|
|
373
|
+
"step must be a positive integer of minor units");
|
|
374
|
+
return step;
|
|
375
|
+
}
|
|
376
|
+
if (typeof step === "number" && Number.isInteger(step) && step > 0) return BigInt(step);
|
|
377
|
+
throw new MoneyError("money/bad-increment",
|
|
378
|
+
"step must be a positive integer (BigInt or safe integer Number) of minor units; got " +
|
|
379
|
+
(typeof step === "number" ? String(step) : typeof step));
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* @primitive b.money.roundMinor
|
|
384
|
+
* @signature b.money.roundMinor(minor, step, mode?)
|
|
385
|
+
* @since 0.15.13
|
|
386
|
+
* @status stable
|
|
387
|
+
* @related b.money.Money, b.money.fromMinorUnits
|
|
388
|
+
*
|
|
389
|
+
* Snap a raw minor-unit integer to the nearest multiple of `step` minor units —
|
|
390
|
+
* the cash-rounding step a coarser cash denomination needs even though the
|
|
391
|
+
* currency's ISO 4217 minor unit is finer (a CHF total to the nearest 5 rappen
|
|
392
|
+
* after the 1/2-rappen coins were retired, a SEK total to the nearest 10 öre, a
|
|
393
|
+
* JPY total to a 100-unit psychological-pricing step). Pure BigInt math — no
|
|
394
|
+
* `Number` in the value path — and the remainder sign is handled so a negative
|
|
395
|
+
* amount (a refund preview) rounds on the correct side of the tie.
|
|
396
|
+
*
|
|
397
|
+
* `minor` accepts a BigInt or a safe integer `Number`; the return is a BigInt.
|
|
398
|
+
*
|
|
399
|
+
* @opts
|
|
400
|
+
* mode: "half-even" | "half-up" | "half-down" | "ceiling" | "floor", // default: half-even
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* b.money.roundMinor(1232n, 5n); // CHF 12.32 → nearest 0.05 → 1230n (12.30)
|
|
404
|
+
* b.money.roundMinor(25n, 10n, "half-even"); // tie → even multiple → 20n
|
|
405
|
+
* b.money.roundMinor(25n, 10n, "half-up"); // tie away from zero → 30n
|
|
406
|
+
* b.money.roundMinor(-25n, 10n, "half-up"); // refund tie away from zero → -30n
|
|
407
|
+
*/
|
|
408
|
+
function roundMinor(minor, step, mode) {
|
|
409
|
+
mode = mode || "half-even";
|
|
410
|
+
if (typeof minor === "number" && Number.isInteger(minor)) minor = BigInt(minor);
|
|
411
|
+
if (typeof minor !== "bigint") {
|
|
412
|
+
throw new MoneyError("money/bad-minor-units",
|
|
413
|
+
"minor must be an integer (BigInt or safe integer Number); got " + (typeof minor));
|
|
414
|
+
}
|
|
415
|
+
if (!INCREMENT_MODES[mode]) {
|
|
416
|
+
throw new MoneyError("money/bad-rounding-mode",
|
|
417
|
+
"mode must be one of half-even | half-up | half-down | ceiling | floor; got " + String(mode));
|
|
418
|
+
}
|
|
419
|
+
var stepBig = _toIncrementBigInt(step);
|
|
420
|
+
var q = minor / stepBig;
|
|
421
|
+
var r = minor - q * stepBig;
|
|
422
|
+
if (r === 0n) return minor;
|
|
423
|
+
// lower = the multiple toward -inf, upper = toward +inf. BigInt division
|
|
424
|
+
// truncates toward zero, so the bracket flips by sign of `minor`.
|
|
425
|
+
var lower, upper;
|
|
426
|
+
if (minor >= 0n) { lower = q * stepBig; upper = lower + stepBig; }
|
|
427
|
+
else { upper = q * stepBig; lower = upper - stepBig; }
|
|
428
|
+
if (mode === "floor") return lower;
|
|
429
|
+
if (mode === "ceiling") return upper;
|
|
430
|
+
var distLow = minor - lower; // >= 0
|
|
431
|
+
var distHigh = upper - minor; // >= 0
|
|
432
|
+
if (distLow < distHigh) return lower;
|
|
433
|
+
if (distHigh < distLow) return upper;
|
|
434
|
+
// Exactly on the tie.
|
|
435
|
+
if (mode === "half-up") return (minor >= 0n) ? upper : lower; // away from zero
|
|
436
|
+
if (mode === "half-down") return (minor >= 0n) ? lower : upper; // toward zero
|
|
437
|
+
return ((lower / stepBig) % 2n === 0n) ? lower : upper; // half-even
|
|
438
|
+
}
|
|
439
|
+
|
|
336
440
|
// allocate -- split `this` into `weights.length` parts proportional to
|
|
337
441
|
// the weights, distributing every minor unit. Largest-remainder
|
|
338
442
|
// method: floor each share, then hand out the leftover units to the
|
|
@@ -693,6 +797,7 @@ module.exports = {
|
|
|
693
797
|
parse: parse,
|
|
694
798
|
zero: zero,
|
|
695
799
|
convert: convert,
|
|
800
|
+
roundMinor: roundMinor,
|
|
696
801
|
CURRENCIES: CURRENCIES,
|
|
697
802
|
Money: Money,
|
|
698
803
|
MoneyError: MoneyError,
|
|
@@ -58,6 +58,9 @@ var nodeCrypto = require("node:crypto");
|
|
|
58
58
|
var atomicFile = require("./atomic-file");
|
|
59
59
|
var C = require("./constants");
|
|
60
60
|
var lazyRequire = require("./lazy-require");
|
|
61
|
+
// Lazy — the SHA3-512 fingerprint surfaced from issuance must match the one
|
|
62
|
+
// the require-mtls gate pins (b.crypto.sha3Hash(certPem)).
|
|
63
|
+
var bCrypto = lazyRequire(function () { return require("./crypto"); });
|
|
61
64
|
var { boot } = require("./log");
|
|
62
65
|
var safeBuffer = require("./safe-buffer");
|
|
63
66
|
var safeJson = require("./safe-json");
|
|
@@ -193,7 +196,7 @@ function create(opts) {
|
|
|
193
196
|
opts = opts || {};
|
|
194
197
|
validateOpts(opts, [
|
|
195
198
|
"dataDir", "paths", "vault",
|
|
196
|
-
"caKeySealedMode", "generation", "engine",
|
|
199
|
+
"caKeySealedMode", "generation", "engine", "revocationStore",
|
|
197
200
|
], "b.mtlsCa");
|
|
198
201
|
validateOpts.requireNonEmptyString(opts.dataDir, "mtlsCa.create: opts.dataDir", MtlsCaError, "mtls-ca/no-datadir");
|
|
199
202
|
// Auto-create the dataDir with restrictive perms (CA keys live here).
|
|
@@ -370,6 +373,29 @@ function create(opts) {
|
|
|
370
373
|
return fresh;
|
|
371
374
|
}
|
|
372
375
|
|
|
376
|
+
// Recover the issued certificate's identity from its PEM so issuance and
|
|
377
|
+
// any later revocation/indexing share identifiers without a round-trip back
|
|
378
|
+
// through an X.509 parser. serialNumber is normalized to the same hex form
|
|
379
|
+
// revoke() stores; fingerprint is the SHA3-512 the require-mtls gate pins.
|
|
380
|
+
function _certIdentity(certPem) {
|
|
381
|
+
// serialNumber comes from an X.509 parse, which is best-effort: a custom
|
|
382
|
+
// engine (or a test double) may return a cert in a shape this Node build
|
|
383
|
+
// cannot parse as X.509. The fingerprint is a hash of the returned bytes,
|
|
384
|
+
// so it is always available and is what the require-mtls gate pins —
|
|
385
|
+
// revoke()/isRevoked() by fingerprint keep working even when the serial
|
|
386
|
+
// can't be recovered. Never let optional identity enrichment crash issuance.
|
|
387
|
+
var serialNumber = null;
|
|
388
|
+
try {
|
|
389
|
+
serialNumber = _normalizeSerial(new nodeCrypto.X509Certificate(certPem).serialNumber);
|
|
390
|
+
} catch (_e) {
|
|
391
|
+
serialNumber = null;
|
|
392
|
+
}
|
|
393
|
+
return {
|
|
394
|
+
serialNumber: serialNumber,
|
|
395
|
+
fingerprint: bCrypto().sha3Hash(certPem),
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
|
|
373
399
|
async function generateClientCert(opts2) {
|
|
374
400
|
opts2 = opts2 || {};
|
|
375
401
|
var ca = await initCA();
|
|
@@ -379,7 +405,10 @@ function create(opts) {
|
|
|
379
405
|
throw new MtlsCaError("mtls-ca/bad-engine-output",
|
|
380
406
|
"engine.signClientCert must return { cert, key, ca?, issuedAt?, expiresAt? }");
|
|
381
407
|
}
|
|
382
|
-
|
|
408
|
+
// Surface the issued serial + fingerprint so the caller can track/revoke
|
|
409
|
+
// the cert by the same identifiers without re-parsing the PEM.
|
|
410
|
+
var id = _certIdentity(result.cert);
|
|
411
|
+
return Object.assign({}, result, { serialNumber: id.serialNumber, fingerprint: id.fingerprint });
|
|
383
412
|
}
|
|
384
413
|
|
|
385
414
|
async function generateClientP12(opts2) {
|
|
@@ -395,32 +424,63 @@ function create(opts) {
|
|
|
395
424
|
throw new MtlsCaError("mtls-ca/bad-engine-output",
|
|
396
425
|
"engine.packageP12 must return { p12: Buffer, certPem, issuedAt, expiresAt }");
|
|
397
426
|
}
|
|
427
|
+
if (typeof result.certPem === "string") {
|
|
428
|
+
var id12 = _certIdentity(result.certPem);
|
|
429
|
+
return Object.assign({}, result, { serialNumber: id12.serialNumber, fingerprint: id12.fingerprint });
|
|
430
|
+
}
|
|
398
431
|
return result;
|
|
399
432
|
}
|
|
400
433
|
|
|
401
434
|
// ---- Revocation registry + CRL ----
|
|
402
435
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
436
|
+
// Revocation entries are read + written through a store so the registry can
|
|
437
|
+
// live somewhere other than the default plaintext revocations.json — e.g. an
|
|
438
|
+
// operator-supplied encrypted / clustered store (the bring-your-own-store
|
|
439
|
+
// precedent b.queue's config.db set). Contract (sync):
|
|
440
|
+
// list() -> array of revocation entries
|
|
441
|
+
// add(entry) -> append one entry (the caller has already deduped)
|
|
442
|
+
function _defaultFileStore() {
|
|
443
|
+
function _list() {
|
|
444
|
+
if (!nodeFs.existsSync(paths.revocations)) return [];
|
|
445
|
+
try {
|
|
446
|
+
// safeJson.parse caps depth + size + protects against
|
|
447
|
+
// proto-pollution; a tampered or truncated file shouldn't be able to
|
|
448
|
+
// corrupt the rotator process.
|
|
449
|
+
var json = safeJson.parse(nodeFs.readFileSync(paths.revocations, "utf8"),
|
|
450
|
+
{ maxBytes: C.BYTES.mib(16) });
|
|
451
|
+
return (json && Array.isArray(json.revocations)) ? json.revocations : [];
|
|
452
|
+
} catch (e) {
|
|
453
|
+
throw new MtlsCaError("mtls-ca/revocation-corrupt",
|
|
454
|
+
"could not parse " + paths.revocations + ": " + ((e && e.message) || String(e)));
|
|
455
|
+
}
|
|
418
456
|
}
|
|
457
|
+
return {
|
|
458
|
+
list: _list,
|
|
459
|
+
add: function (entry) {
|
|
460
|
+
var entries = _list();
|
|
461
|
+
entries.push(entry);
|
|
462
|
+
atomicFile.writeSync(paths.revocations,
|
|
463
|
+
JSON.stringify({ revocations: entries }, null, 2) + "\n", { mode: 0o600 });
|
|
464
|
+
},
|
|
465
|
+
};
|
|
419
466
|
}
|
|
467
|
+
var revocationStore = opts.revocationStore || _defaultFileStore();
|
|
468
|
+
validateOpts.requireMethods(revocationStore, ["list", "add"],
|
|
469
|
+
"opts.revocationStore", MtlsCaError, "mtls-ca/bad-revocation-store");
|
|
420
470
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
471
|
+
// A fingerprint is the SHA3-512 hex the require-mtls gate pins. Normalize it
|
|
472
|
+
// like a serial (strip 0x / separators / whitespace, lowercase, hex-validate)
|
|
473
|
+
// so a consumer can revoke by the same value the gate compares against.
|
|
474
|
+
function _normalizeFingerprint(fp) {
|
|
475
|
+
if (!fp || typeof fp !== "string") {
|
|
476
|
+
throw new MtlsCaError("mtls-ca/bad-fingerprint", "fingerprint must be a non-empty string");
|
|
477
|
+
}
|
|
478
|
+
var stripped = fp.replace(/^0x/i, "").replace(/[:\-\s]/g, "");
|
|
479
|
+
if (!safeBuffer.isHex(stripped)) {
|
|
480
|
+
throw new MtlsCaError("mtls-ca/bad-fingerprint",
|
|
481
|
+
"fingerprint contains non-hex characters: " + JSON.stringify(fp));
|
|
482
|
+
}
|
|
483
|
+
return stripped.toLowerCase();
|
|
424
484
|
}
|
|
425
485
|
|
|
426
486
|
function _normalizeSerial(s) {
|
|
@@ -466,46 +526,66 @@ function create(opts) {
|
|
|
466
526
|
"aACompromise": 10,
|
|
467
527
|
};
|
|
468
528
|
|
|
469
|
-
function revoke(
|
|
470
|
-
|
|
529
|
+
function revoke(idOrOpts, opts3) {
|
|
530
|
+
// Accept either revoke(serialString, { reason, fingerprint }) — the
|
|
531
|
+
// backward-compatible serial-keyed form — or revoke({ serial?,
|
|
532
|
+
// fingerprint?, reason? }). The require-mtls gate denies by fingerprint,
|
|
533
|
+
// so a fingerprint-indexed consumer can revoke by the same value it pins
|
|
534
|
+
// on; serial-keyed behavior stays the default. At least one key required.
|
|
535
|
+
var spec = (idOrOpts && typeof idOrOpts === "object") ? idOrOpts : null;
|
|
471
536
|
opts3 = opts3 || {};
|
|
472
|
-
var
|
|
537
|
+
var serialIn = spec ? spec.serial : idOrOpts;
|
|
538
|
+
var fingerprintIn = spec ? spec.fingerprint : opts3.fingerprint;
|
|
539
|
+
var reasonName = (spec ? spec.reason : opts3.reason) || "unspecified";
|
|
540
|
+
|
|
541
|
+
var serial = (serialIn !== undefined && serialIn !== null) ? _normalizeSerial(serialIn) : null;
|
|
542
|
+
var fingerprint = (fingerprintIn !== undefined && fingerprintIn !== null)
|
|
543
|
+
? _normalizeFingerprint(fingerprintIn) : null;
|
|
544
|
+
if (!serial && !fingerprint) {
|
|
545
|
+
throw new MtlsCaError("mtls-ca/no-revocation-key",
|
|
546
|
+
"revoke requires a serial number or a fingerprint " +
|
|
547
|
+
"(revoke(serial, opts) or revoke({ serial, fingerprint }))");
|
|
548
|
+
}
|
|
473
549
|
var reasonCode = CRL_REASON_BY_NAME[reasonName];
|
|
474
550
|
if (reasonCode === undefined) {
|
|
475
551
|
throw new MtlsCaError("mtls-ca/bad-reason",
|
|
476
552
|
"revoke: unknown reason '" + reasonName + "' (valid: " +
|
|
477
553
|
Object.keys(CRL_REASON_BY_NAME).join(", ") + ")");
|
|
478
554
|
}
|
|
479
|
-
var
|
|
480
|
-
|
|
481
|
-
return r.serialNumber === serial;
|
|
555
|
+
var existing = revocationStore.list().find(function (r) {
|
|
556
|
+
return (serial && r.serialNumber === serial) || (fingerprint && r.fingerprint === fingerprint);
|
|
482
557
|
});
|
|
483
558
|
if (existing) {
|
|
484
|
-
// Idempotent — repeated revoke() of the same serial doesn't
|
|
559
|
+
// Idempotent — repeated revoke() of the same serial/fingerprint doesn't
|
|
485
560
|
// shift the revokedAt timestamp.
|
|
486
561
|
return existing;
|
|
487
562
|
}
|
|
488
563
|
var entry = {
|
|
489
564
|
serialNumber: serial,
|
|
565
|
+
fingerprint: fingerprint,
|
|
490
566
|
reason: reasonName,
|
|
491
567
|
reasonCode: reasonCode,
|
|
492
568
|
revokedAt: Date.now(),
|
|
493
569
|
};
|
|
494
|
-
|
|
495
|
-
_saveRevocations(state);
|
|
570
|
+
revocationStore.add(entry);
|
|
496
571
|
return entry;
|
|
497
572
|
}
|
|
498
573
|
|
|
499
|
-
function isRevoked(
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
574
|
+
function isRevoked(serialOrFingerprint) {
|
|
575
|
+
// Accept a serial number OR a SHA3-512 fingerprint — both are hex, so one
|
|
576
|
+
// normalized form is matched against either key each entry carries.
|
|
577
|
+
if (!serialOrFingerprint || typeof serialOrFingerprint !== "string") {
|
|
578
|
+
throw new MtlsCaError("mtls-ca/bad-revocation-key",
|
|
579
|
+
"isRevoked requires a serial number or a fingerprint (hex string)");
|
|
580
|
+
}
|
|
581
|
+
var norm = _normalizeFingerprint(serialOrFingerprint);
|
|
582
|
+
return revocationStore.list().some(function (r) {
|
|
583
|
+
return r.serialNumber === norm || r.fingerprint === norm;
|
|
504
584
|
});
|
|
505
585
|
}
|
|
506
586
|
|
|
507
587
|
function getRevocations() {
|
|
508
|
-
return
|
|
588
|
+
return revocationStore.list().slice();
|
|
509
589
|
}
|
|
510
590
|
|
|
511
591
|
// Generate a signed X.509 CRL covering every entry in the registry.
|
|
@@ -521,7 +601,7 @@ function create(opts) {
|
|
|
521
601
|
"framework's bundled CA engine, which supports it");
|
|
522
602
|
}
|
|
523
603
|
var ca = await initCA();
|
|
524
|
-
var revocations =
|
|
604
|
+
var revocations = revocationStore.list();
|
|
525
605
|
var nowMs = Date.now();
|
|
526
606
|
var thisUpdate = opts3.thisUpdate || new Date(nowMs);
|
|
527
607
|
var nextUpdate = opts3.nextUpdate ||
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
*/
|
|
40
40
|
|
|
41
41
|
var C = require("./constants");
|
|
42
|
+
var boundedMap = require("./bounded-map");
|
|
42
43
|
var defineClass = require("./framework-error").defineClass;
|
|
43
44
|
var lazyRequire = require("./lazy-require");
|
|
44
45
|
var validateOpts = require("./validate-opts");
|
|
@@ -79,9 +80,7 @@ function _slideAndSum(entry, nowHour) {
|
|
|
79
80
|
function _memoryBackend() {
|
|
80
81
|
var store = new Map();
|
|
81
82
|
function _get(key) {
|
|
82
|
-
|
|
83
|
-
if (!entry) { entry = _newEntry(); store.set(key, entry); }
|
|
84
|
-
return entry;
|
|
83
|
+
return boundedMap.getOrInsert(store, key, function () { return _newEntry(); });
|
|
85
84
|
}
|
|
86
85
|
return {
|
|
87
86
|
async total(key, nowMs) {
|
|
@@ -172,27 +171,14 @@ function create(opts) {
|
|
|
172
171
|
validateOpts(opts, ["bytesPerDay", "cache", "audit", "now"], "network.byteQuota");
|
|
173
172
|
_requirePositiveBytes("bytesPerDay", opts.bytesPerDay);
|
|
174
173
|
var bytesPerDay = opts.bytesPerDay;
|
|
175
|
-
var auditOn = opts.audit !== false;
|
|
176
174
|
var now = typeof opts.now === "function" ? opts.now : function () { return Date.now(); };
|
|
177
175
|
var backend = opts.cache && typeof opts.cache.get === "function"
|
|
178
176
|
? _cacheBackend(opts.cache)
|
|
179
177
|
: _memoryBackend();
|
|
180
178
|
|
|
181
|
-
|
|
182
|
-
if (!auditOn) return;
|
|
183
|
-
try {
|
|
184
|
-
audit().safeEmit({
|
|
185
|
-
action: "network.byte_quota." + action,
|
|
186
|
-
outcome: outcome,
|
|
187
|
-
metadata: metadata || {},
|
|
188
|
-
});
|
|
189
|
-
} catch (_e) { /* drop-silent — audit is best-effort */ }
|
|
190
|
-
}
|
|
179
|
+
var _emitAudit = audit().namespaced("network.byte_quota", opts.audit);
|
|
191
180
|
|
|
192
|
-
|
|
193
|
-
try { observability().safeEvent("network.byte_quota." + verb, n || 1, labels || {}); }
|
|
194
|
-
catch (_e) { /* drop-silent */ }
|
|
195
|
-
}
|
|
181
|
+
var _emitMetric = observability().namespaced("network.byte_quota");
|
|
196
182
|
|
|
197
183
|
// check(key, bytes) — preflight without mutation. Returns
|
|
198
184
|
// { allowed, total, remaining, quota, retryAfterSec, degraded }
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
|
|
32
32
|
var nodeCrypto = require("node:crypto");
|
|
33
33
|
var bCrypto = require("./crypto");
|
|
34
|
+
var safeBuffer = require("./safe-buffer");
|
|
34
35
|
var validateOpts = require("./validate-opts");
|
|
35
36
|
var { defineClass } = require("./framework-error");
|
|
36
37
|
|
|
@@ -44,12 +45,13 @@ var SELECTORS = { 0: "Cert", 1: "SPKI" };
|
|
|
44
45
|
// refused rather than guessed.
|
|
45
46
|
var MATCHING = { 0: null, 1: "sha256", 2: "sha512" };
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
var _bytes = safeBuffer.makeByteCoercer({
|
|
49
|
+
errorClass: DaneError,
|
|
50
|
+
typeCode: "dane/bad-bytes",
|
|
51
|
+
messagePrefix: "dane: ",
|
|
52
|
+
messageSuffix: " must be a Buffer / Uint8Array / hex string",
|
|
53
|
+
encoding: "hex",
|
|
54
|
+
});
|
|
53
55
|
|
|
54
56
|
function _selectedData(x509, selector) {
|
|
55
57
|
if (selector === 0) return Buffer.from(x509.raw); // full certificate DER
|
|
@@ -188,7 +188,9 @@ function create(opts) {
|
|
|
188
188
|
var serveStale = opts.serveStale === false ? 0 :
|
|
189
189
|
typeof opts.serveStale === "number" ? opts.serveStale : DEFAULT_STALE_WINDOW;
|
|
190
190
|
var transport = opts.transport || _defaultTransport();
|
|
191
|
-
|
|
191
|
+
// Audit goes to the operator-supplied sink (opts.audit) when present, else the
|
|
192
|
+
// framework chain — b.audit.namespaced no-ops if the sink has no safeEmit.
|
|
193
|
+
var _baseAudit = audit().namespaced("network.dns.resolver", { sink: opts.audit });
|
|
192
194
|
|
|
193
195
|
if (typeof transport.lookup !== "function") {
|
|
194
196
|
throw new ResolverError("resolver/bad-transport",
|
|
@@ -238,11 +240,7 @@ function create(opts) {
|
|
|
238
240
|
}
|
|
239
241
|
|
|
240
242
|
function _safeEmit(action, metadata) {
|
|
241
|
-
|
|
242
|
-
if (auditImpl && typeof auditImpl.safeEmit === "function") {
|
|
243
|
-
auditImpl.safeEmit({ action: "network.dns.resolver." + action, outcome: "success", metadata: metadata });
|
|
244
|
-
}
|
|
245
|
-
} catch (_e) { /* audit drop-silent per validation tier policy */ }
|
|
243
|
+
_baseAudit(action, "success", metadata);
|
|
246
244
|
}
|
|
247
245
|
|
|
248
246
|
async function query(name, type, qopts) {
|
|
@@ -526,8 +524,101 @@ function _minTtl(rrs) {
|
|
|
526
524
|
return min === Infinity ? 0 : min;
|
|
527
525
|
}
|
|
528
526
|
|
|
527
|
+
// _sharedTxtResolver — one process-wide validating resolver (with its TTL
|
|
528
|
+
// cache) shared by every email-auth policy TXT lookup, instead of each module
|
|
529
|
+
// constructing its own (or reaching for plaintext system DNS).
|
|
530
|
+
var _sharedResolver = null;
|
|
531
|
+
function _sharedTxtResolver() {
|
|
532
|
+
if (!_sharedResolver) _sharedResolver = create();
|
|
533
|
+
return _sharedResolver;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* @primitive b.network.dns.resolver.resolveTxt
|
|
538
|
+
* @signature b.network.dns.resolver.resolveTxt(qname, dnsLookup?, resolver?)
|
|
539
|
+
* @since 0.15.13
|
|
540
|
+
* @status stable
|
|
541
|
+
* @related b.network.dns.resolver.safeResolveTxt, b.network.dns.resolver.create
|
|
542
|
+
*
|
|
543
|
+
* Resolve TXT records for `qname` via the operator's `dnsLookup(qname, "TXT")`
|
|
544
|
+
* override when supplied, otherwise the framework's shared validating
|
|
545
|
+
* (DoH / DoT / system, DNSSEC-checked) resolver — normalized to the
|
|
546
|
+
* `string[][]` shape `dnsPromises.resolveTxt` returns. Throws an `ENODATA`
|
|
547
|
+
* Error when no TXT records exist.
|
|
548
|
+
*
|
|
549
|
+
* This is the secure DNS path for every email-auth policy lookup (DMARC / DKIM /
|
|
550
|
+
* ARC / BIMI / MTA-STS / TLS-RPT). Plaintext system DNS (`dnsPromises.resolveTxt`)
|
|
551
|
+
* is spoofable — DNS cache-poisoning / Kaminsky-class — and must NOT be used for
|
|
552
|
+
* records a downgrade or redirect would exploit.
|
|
553
|
+
*
|
|
554
|
+
* Pass `resolver` (a `b.network.dns.resolver.create()` instance) to reshape TXT
|
|
555
|
+
* records off a caller-owned resolver instead of the shared one — the mail-auth
|
|
556
|
+
* and mail-dkim modules use this so their TXT lookups share the same resolver
|
|
557
|
+
* (and cache) they use for A / MX / PTR, instead of each re-rolling the reshape.
|
|
558
|
+
*
|
|
559
|
+
* @example
|
|
560
|
+
* var rrs = await b.network.dns.resolver.resolveTxt("_dmarc.example.com");
|
|
561
|
+
* // → [ ["v=DMARC1; p=reject"] ]
|
|
562
|
+
*/
|
|
563
|
+
async function resolveTxt(qname, dnsLookup, resolver) {
|
|
564
|
+
if (dnsLookup) return dnsLookup(qname, "TXT");
|
|
565
|
+
var r = await (resolver || _sharedTxtResolver()).queryTxt(qname);
|
|
566
|
+
var out = [];
|
|
567
|
+
for (var i = 0; i < r.rrs.length; i += 1) {
|
|
568
|
+
var rr = r.rrs[i];
|
|
569
|
+
if (rr && rr.type === 16) { // IANA DNS qtype TXT
|
|
570
|
+
out.push(Array.isArray(rr.decoded) ? rr.decoded : [String(rr.decoded)]);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
if (out.length === 0) {
|
|
574
|
+
var err = new Error("no TXT records for " + qname);
|
|
575
|
+
err.code = "ENODATA";
|
|
576
|
+
throw err;
|
|
577
|
+
}
|
|
578
|
+
return out;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* @primitive b.network.dns.resolver.safeResolveTxt
|
|
583
|
+
* @signature b.network.dns.resolver.safeResolveTxt(qname, opts?)
|
|
584
|
+
* @since 0.15.13
|
|
585
|
+
* @status stable
|
|
586
|
+
* @related b.network.dns.resolver.resolveTxt
|
|
587
|
+
*
|
|
588
|
+
* `resolveTxt` wrapped with the email-auth policy-fetch convention: a domain
|
|
589
|
+
* with no record (ENOTFOUND / ENODATA) returns `null` (absence is not an
|
|
590
|
+
* error); any other failure throws the caller's typed error via
|
|
591
|
+
* `errorFactory(code, message)` so each protocol keeps its own error class.
|
|
592
|
+
* The same secure resolver path as `resolveTxt` — never plaintext system DNS.
|
|
593
|
+
*
|
|
594
|
+
* @opts
|
|
595
|
+
* dnsLookup: function, // operator override (qname, "TXT") => string[][]
|
|
596
|
+
* errorFactory: function, // (code, message) => Error, thrown on non-absence failures
|
|
597
|
+
* code: string, // error code passed to errorFactory
|
|
598
|
+
*
|
|
599
|
+
* @example
|
|
600
|
+
* var rrs = await b.network.dns.resolver.safeResolveTxt("_mta-sts.example.com", {
|
|
601
|
+
* errorFactory: function (code, msg) { return new SmtpPolicyError(code, msg); },
|
|
602
|
+
* code: "smtp/mta-sts-txt-lookup-failed",
|
|
603
|
+
* });
|
|
604
|
+
* if (rrs === null) return null; // no MTA-STS record published
|
|
605
|
+
*/
|
|
606
|
+
async function safeResolveTxt(qname, opts) {
|
|
607
|
+
opts = opts || {};
|
|
608
|
+
try {
|
|
609
|
+
return await resolveTxt(qname, opts.dnsLookup);
|
|
610
|
+
} catch (e) {
|
|
611
|
+
if (e && (e.code === "ENOTFOUND" || e.code === "ENODATA")) return null;
|
|
612
|
+
var msg = "TXT lookup for " + qname + " failed: " + ((e && e.message) || String(e));
|
|
613
|
+
if (typeof opts.errorFactory === "function") throw opts.errorFactory(opts.code, msg);
|
|
614
|
+
throw e;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
529
618
|
module.exports = {
|
|
530
619
|
create: create,
|
|
620
|
+
resolveTxt: resolveTxt,
|
|
621
|
+
safeResolveTxt: safeResolveTxt,
|
|
531
622
|
ResolverError: ResolverError,
|
|
532
623
|
QTYPE_BY_NAME: QTYPE_BY_NAME,
|
|
533
624
|
};
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
|
|
47
47
|
var nodeCrypto = require("node:crypto");
|
|
48
48
|
var bCrypto = require("./crypto");
|
|
49
|
+
var safeBuffer = require("./safe-buffer");
|
|
49
50
|
var validateOpts = require("./validate-opts");
|
|
50
51
|
var { defineClass } = require("./framework-error");
|
|
51
52
|
|
|
@@ -79,11 +80,14 @@ var TYPE_NUM = {
|
|
|
79
80
|
SMIMEA: 53, CDS: 59, CDNSKEY: 60, OPENPGPKEY: 61, CAA: 257, HINFO: 13,
|
|
80
81
|
};
|
|
81
82
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
// DNSSEC wire data is bytes, never text (allowString:false).
|
|
84
|
+
var _bytes = safeBuffer.makeByteCoercer({
|
|
85
|
+
errorClass: DnssecError,
|
|
86
|
+
typeCode: "dnssec/bad-bytes",
|
|
87
|
+
messagePrefix: "dnssec: ",
|
|
88
|
+
messageSuffix: " must be a Buffer",
|
|
89
|
+
allowString: false,
|
|
90
|
+
});
|
|
87
91
|
|
|
88
92
|
// Canonical wire form of a domain name (RFC 4034 §6.2): each label
|
|
89
93
|
// length-prefixed, ASCII lowercased, terminated by the root label.
|
|
@@ -157,8 +161,11 @@ function _dnskeyToKey(algId, publicKey) {
|
|
|
157
161
|
return _jwkKey({ kty: "OKP", crv: "Ed25519", x: pk.toString("base64url") });
|
|
158
162
|
}
|
|
159
163
|
function _jwkKey(jwk) {
|
|
160
|
-
|
|
161
|
-
|
|
164
|
+
return bCrypto.importPublicJwk(jwk, {
|
|
165
|
+
errorClass: DnssecError,
|
|
166
|
+
code: "dnssec/bad-key",
|
|
167
|
+
messagePrefix: "dnssec: could not import DNSKEY: ",
|
|
168
|
+
});
|
|
162
169
|
}
|
|
163
170
|
|
|
164
171
|
/**
|
|
@@ -284,15 +291,8 @@ function verifyRrset(opts) {
|
|
|
284
291
|
}
|
|
285
292
|
|
|
286
293
|
// Validity window (fail closed on a bad opts.at).
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
if (!(opts.at instanceof Date) || !isFinite(opts.at.getTime())) {
|
|
290
|
-
throw new DnssecError("dnssec/bad-at", "dnssec.verifyRrset: opts.at must be a valid Date");
|
|
291
|
-
}
|
|
292
|
-
atMs = opts.at.getTime();
|
|
293
|
-
} else {
|
|
294
|
-
atMs = Date.now();
|
|
295
|
-
}
|
|
294
|
+
validateOpts.optionalDate(opts.at, "dnssec.verifyRrset: opts.at", DnssecError, "dnssec/bad-at");
|
|
295
|
+
var atMs = (opts.at !== undefined && opts.at !== null) ? opts.at.getTime() : Date.now();
|
|
296
296
|
var nowSec = Math.floor(atMs / 1000);
|
|
297
297
|
if (nowSec < (rrsig.inception >>> 0)) throw new DnssecError("dnssec/not-yet-valid", "dnssec.verifyRrset: RRSIG inception is in the future");
|
|
298
298
|
if (nowSec > (rrsig.expiration >>> 0)) throw new DnssecError("dnssec/expired", "dnssec.verifyRrset: RRSIG has expired");
|
|
@@ -5,6 +5,7 @@ var net = require("node:net");
|
|
|
5
5
|
var C = require("./constants");
|
|
6
6
|
var validateOpts = require("./validate-opts");
|
|
7
7
|
var lazyRequire = require("./lazy-require");
|
|
8
|
+
var boundedMap = require("./bounded-map");
|
|
8
9
|
var { defineClass } = require("./framework-error");
|
|
9
10
|
|
|
10
11
|
var HeartbeatError = defineClass("HeartbeatError", { alwaysPermanent: true });
|
|
@@ -198,9 +199,9 @@ function start(opts) {
|
|
|
198
199
|
var started = [];
|
|
199
200
|
for (var j = 0; j < opts.targets.length; j++) {
|
|
200
201
|
var t = opts.targets[j];
|
|
201
|
-
|
|
202
|
+
boundedMap.requireAbsent(TARGETS, t.name, function () {
|
|
202
203
|
throw new HeartbeatError("heartbeat/duplicate", "heartbeat target '" + t.name + "' already started");
|
|
203
|
-
}
|
|
204
|
+
});
|
|
204
205
|
var entry = {
|
|
205
206
|
target: t,
|
|
206
207
|
intervalMs: t.intervalMs || DEFAULT_INTERVAL_MS,
|