@blamejs/blamejs-shop 0.4.56 → 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 +2 -0
- 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/package.json +1 -1
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
var helpers = require("../helpers");
|
|
12
12
|
var b = helpers.b;
|
|
13
13
|
var check = helpers.check;
|
|
14
|
+
var arcSign = require("../../lib/mail-arc-sign");
|
|
14
15
|
|
|
15
16
|
function testSurface() {
|
|
16
17
|
check("mail.spf.verify is a function", typeof b.mail.spf.verify === "function");
|
|
@@ -1376,8 +1377,46 @@ async function testSpfMechanismPtrRemainsDeferred() {
|
|
|
1376
1377
|
rv.result === "permerror" && /5\.5/.test(rv.explanation || ""));
|
|
1377
1378
|
}
|
|
1378
1379
|
|
|
1380
|
+
// ARC canon-source header parser — byte-exact golden lock. The AMS/AS
|
|
1381
|
+
// signatures are computed over the bytes this parser extracts; a sign->verify
|
|
1382
|
+
// round-trip shares the parser and so cannot catch a byte-error (it would only
|
|
1383
|
+
// surface as a rejection at a real ARC verifier). ARC's relaxed-canon parser
|
|
1384
|
+
// STRIPS leading WSP from the value (vs DKIM's simple-canon parser, which
|
|
1385
|
+
// preserves it) and PRESERVES the raw CRLF of a folded continuation.
|
|
1386
|
+
function testArcHeaderParserGolden() {
|
|
1387
|
+
var ph = arcSign._parseHeaderBlockForTest;
|
|
1388
|
+
function eq(label, raw, expected) {
|
|
1389
|
+
check("arc parser: " + label, JSON.stringify(ph(raw)) === JSON.stringify(expected));
|
|
1390
|
+
}
|
|
1391
|
+
eq("relaxed parser STRIPS leading WSP from value",
|
|
1392
|
+
"From: a@b.com",
|
|
1393
|
+
[{ name: "From", value: "a@b.com" }]);
|
|
1394
|
+
eq("leading SP + TAB stripped",
|
|
1395
|
+
"X: \tvalue",
|
|
1396
|
+
[{ name: "X", value: "value" }]);
|
|
1397
|
+
eq("folded continuation keeps raw CRLF + line",
|
|
1398
|
+
"From: a@b.com\r\nSubject: hello\r\n world",
|
|
1399
|
+
[{ name: "From", value: "a@b.com" },
|
|
1400
|
+
{ name: "Subject", value: "hello\r\n world" }]);
|
|
1401
|
+
eq("exact name, order preserved across a colon-less line",
|
|
1402
|
+
"From: a@b.com\r\ngarbage\r\nTo: c@d.com",
|
|
1403
|
+
[{ name: "From", value: "a@b.com" },
|
|
1404
|
+
{ name: "To", value: "c@d.com" }]);
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
function testByteCapMultibyte() {
|
|
1408
|
+
// dmarc.parseForensicReport maxBytes is a BYTE cap; it returns an error
|
|
1409
|
+
// object (does not throw) on refusal.
|
|
1410
|
+
var report = String.fromCharCode(0x4e2d).repeat(20); // 60 UTF-8 bytes; cap 30
|
|
1411
|
+
var r = b.mail.dmarc.parseForensicReport(report, { maxBytes: 30 });
|
|
1412
|
+
check("dmarc-ruf byte-cap: multibyte report over byte cap rejected",
|
|
1413
|
+
r && r.ok === false && r.error && r.error.code === "mail-auth/dmarc-ruf-too-large");
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1379
1416
|
async function run() {
|
|
1417
|
+
testByteCapMultibyte();
|
|
1380
1418
|
testSurface();
|
|
1419
|
+
testArcHeaderParserGolden();
|
|
1381
1420
|
testSpfParse();
|
|
1382
1421
|
testSpfBadRecord();
|
|
1383
1422
|
await testSpfVerifyMockedDns();
|
|
@@ -90,6 +90,41 @@ function testDkimCanonicalization() {
|
|
|
90
90
|
check("simple body: keeps interior WSP", sb("hello world\r\n") === "hello world\r\n");
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
// ---- Header-block parser (the bytes the canonicalizers consume) ----
|
|
94
|
+
//
|
|
95
|
+
// The sign->verify round-trip CANNOT catch a parser byte-error: both sides run
|
|
96
|
+
// this same parser, so a wrong { name, value } extraction is self-consistent
|
|
97
|
+
// and the round-trip still passes — it would only surface as a signature
|
|
98
|
+
// rejection at a real external verifier (Gmail / opendkim) computing from the
|
|
99
|
+
// raw message. So pin the parser's byte-exact output directly. The two
|
|
100
|
+
// signature-critical invariants: the value PRESERVES its leading SP/WSP (simple
|
|
101
|
+
// canon signs those bytes verbatim), and a folded continuation PRESERVES the
|
|
102
|
+
// raw CRLF + continuation line (relaxed canon unfolds it itself; collapsing it
|
|
103
|
+
// in the parser would change the signed bytes).
|
|
104
|
+
function testDkimHeaderParserGolden() {
|
|
105
|
+
var ph = b.mail.dkim._parseHeadersForTest;
|
|
106
|
+
function eq(label, raw, expected) {
|
|
107
|
+
check("parser: " + label, JSON.stringify(ph(raw)) === JSON.stringify(expected));
|
|
108
|
+
}
|
|
109
|
+
eq("simple field preserves leading SP in value",
|
|
110
|
+
"From: a@b.com",
|
|
111
|
+
[{ name: "From", value: " a@b.com" }]);
|
|
112
|
+
eq("value preserves leading SP + TAB verbatim",
|
|
113
|
+
"X: \tvalue",
|
|
114
|
+
[{ name: "X", value: " \tvalue" }]);
|
|
115
|
+
eq("SP-folded continuation keeps raw CRLF + line",
|
|
116
|
+
"From: a@b.com\r\nSubject: hello\r\n world",
|
|
117
|
+
[{ name: "From", value: " a@b.com" },
|
|
118
|
+
{ name: "Subject", value: " hello\r\n world" }]);
|
|
119
|
+
eq("TAB-folded continuation keeps raw CRLF + TAB line",
|
|
120
|
+
"Subject: a\r\n\tb",
|
|
121
|
+
[{ name: "Subject", value: " a\r\n\tb" }]);
|
|
122
|
+
eq("exact field name (no trim), order preserved across a colon-less line",
|
|
123
|
+
"From: a@b.com\r\ngarbage-no-colon\r\nTo: c@d.com",
|
|
124
|
+
[{ name: "From", value: " a@b.com" },
|
|
125
|
+
{ name: "To", value: " c@d.com" }]);
|
|
126
|
+
}
|
|
127
|
+
|
|
93
128
|
// ---- RSA-SHA256 sign + verify round-trip ----
|
|
94
129
|
|
|
95
130
|
function _splitSignedRfc822(signed) {
|
|
@@ -594,6 +629,7 @@ function testDkimStripBTagValueAnchored() {
|
|
|
594
629
|
async function run() {
|
|
595
630
|
testDkimSurfaceAndValidation();
|
|
596
631
|
testDkimCanonicalization();
|
|
632
|
+
testDkimHeaderParserGolden();
|
|
597
633
|
testDkimRsaSignProducesHeader();
|
|
598
634
|
testDkimEd25519Sign();
|
|
599
635
|
testDkimSignerRejectsBadInput();
|
|
@@ -180,6 +180,22 @@ async function testGc() {
|
|
|
180
180
|
check("gc removed at least 1", r.removed >= 1);
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
+
async function testMaxEntriesEvictsOldest() {
|
|
184
|
+
// The in-memory backend caps entry count via boundedMap (evict-oldest). At
|
|
185
|
+
// maxEntries=2, recording a 3rd distinct triplet evicts the 1st — so the 1st
|
|
186
|
+
// is first-seen again on re-check rather than retry-too-soon. Distinct /24
|
|
187
|
+
// subnets so the triplets don't CIDR-aggregate into one fingerprint.
|
|
188
|
+
var gl = b.mail.greylist.create({ maxEntries: 2 });
|
|
189
|
+
await gl.check(_ctx({ ip: "198.51.100.1" })); // entry 1
|
|
190
|
+
await gl.check(_ctx({ ip: "203.0.113.1" })); // entry 2 — at cap
|
|
191
|
+
await gl.check(_ctx({ ip: "192.0.2.1" })); // entry 3 — evicts entry 1
|
|
192
|
+
var v = await gl.check(_ctx({ ip: "198.51.100.1" }));
|
|
193
|
+
check("maxEntries: oldest triplet evicted → first-seen again", v.reason === "first-seen");
|
|
194
|
+
// Entry 3 (most recent) is still present → retry-too-soon, not evicted.
|
|
195
|
+
var v3 = await gl.check(_ctx({ ip: "192.0.2.1" }));
|
|
196
|
+
check("maxEntries: newest triplet retained", v3.reason === "retry-too-soon");
|
|
197
|
+
}
|
|
198
|
+
|
|
183
199
|
async function testFingerprintHashStable() {
|
|
184
200
|
var fp1 = b.mail.greylist._hashFingerprint("203.0.113.0/24", "a@b.com", "c@d.com");
|
|
185
201
|
var fp2 = b.mail.greylist._hashFingerprint("203.0.113.0/24", "a@b.com", "c@d.com");
|
|
@@ -206,6 +222,7 @@ async function run() {
|
|
|
206
222
|
await testCompliancePosture();
|
|
207
223
|
await testProfileResolution();
|
|
208
224
|
await testGc();
|
|
225
|
+
await testMaxEntriesEvictsOldest();
|
|
209
226
|
await testFingerprintHashStable();
|
|
210
227
|
}
|
|
211
228
|
|
|
@@ -28,6 +28,45 @@ async function run() {
|
|
|
28
28
|
var modSurface = b.mail.server.tls;
|
|
29
29
|
check("surface: context is fn", typeof modSurface.context === "function");
|
|
30
30
|
check("surface: MailServerTlsError class", typeof modSurface.MailServerTlsError === "function");
|
|
31
|
+
check("surface: upgradeSocket is fn", typeof modSurface.upgradeSocket === "function");
|
|
32
|
+
check("surface: upgradeLineProtocol is fn", typeof modSurface.upgradeLineProtocol === "function");
|
|
33
|
+
|
|
34
|
+
// ---- upgradeLineProtocol: config-time validation (§8 entry-point) ----
|
|
35
|
+
var ulpBad = [];
|
|
36
|
+
try { modSurface.upgradeLineProtocol(); } catch (e) { ulpBad.push(e); }
|
|
37
|
+
try { modSurface.upgradeLineProtocol({}); } catch (e) { ulpBad.push(e); }
|
|
38
|
+
try { modSurface.upgradeLineProtocol({ state: {} }); } catch (e) { ulpBad.push(e); }
|
|
39
|
+
check("upgradeLineProtocol throws on missing opts", ulpBad[0] && /opts required/.test(ulpBad[0].message));
|
|
40
|
+
check("upgradeLineProtocol throws on missing state", ulpBad[1] && /state/.test(ulpBad[1].message));
|
|
41
|
+
check("upgradeLineProtocol throws on missing drain", ulpBad[2] && /drain/.test(ulpBad[2].message));
|
|
42
|
+
|
|
43
|
+
// ---- upgradeLineProtocol: the STARTTLS-injection drain runs BEFORE the
|
|
44
|
+
// upgrade (CVE-2021-33515 / CVE-2021-38371). With a non-socket the inner
|
|
45
|
+
// upgradeSocket throws, but the pre-handshake state MUST already be wiped.
|
|
46
|
+
var injState = {
|
|
47
|
+
lineBuffer: Buffer.from("A001 LOGIN pipelined-pre-handshake\r\n"),
|
|
48
|
+
pendingLiteral: { bytes: 42 },
|
|
49
|
+
authPending: "half-sasl-token",
|
|
50
|
+
tls: false,
|
|
51
|
+
};
|
|
52
|
+
var injThrew = null;
|
|
53
|
+
try {
|
|
54
|
+
modSurface.upgradeLineProtocol({
|
|
55
|
+
state: injState,
|
|
56
|
+
socket: {}, // not a net.Socket → inner upgradeSocket throws
|
|
57
|
+
secureContext: {},
|
|
58
|
+
idleTimeoutMs: 1000,
|
|
59
|
+
clearFields: ["pendingLiteral", "authPending"],
|
|
60
|
+
drain: function () {},
|
|
61
|
+
onError: function () {},
|
|
62
|
+
});
|
|
63
|
+
} catch (e) { injThrew = e; }
|
|
64
|
+
check("upgradeLineProtocol rejects a non-socket (via upgradeSocket)",
|
|
65
|
+
injThrew && /plainSocket/.test(injThrew.message));
|
|
66
|
+
check("injection drain: lineBuffer emptied even when the upgrade fails",
|
|
67
|
+
injState.lineBuffer.length === 0);
|
|
68
|
+
check("injection drain: clearFields[0] (pendingLiteral) nulled", injState.pendingLiteral === null);
|
|
69
|
+
check("injection drain: clearFields[1] (authPending) nulled", injState.authPending === null);
|
|
31
70
|
|
|
32
71
|
// ---- happy path: plain PEM files load + return a SecureContext ----
|
|
33
72
|
var tmp1 = _mkTmpDir("happy");
|
|
@@ -371,7 +371,24 @@ async function testRefusesBadBackend() {
|
|
|
371
371
|
threw && (threw.code || "").indexOf("mail-store/bad-backend") !== -1);
|
|
372
372
|
}
|
|
373
373
|
|
|
374
|
+
async function testByteCapMultibyte() {
|
|
375
|
+
// maxBodyBytes is a BYTE cap on the decoded body text. A multibyte body
|
|
376
|
+
// under the char count but over the byte cap must be refused.
|
|
377
|
+
var fx = await _setupStore("bytecap");
|
|
378
|
+
try {
|
|
379
|
+
var store = b.mailStore.create({ backend: fx.db, maxBodyBytes: 30 });
|
|
380
|
+
var mb = String.fromCharCode(0x4e2d).repeat(15); // 15 chars / 45 UTF-8 bytes; cap 30
|
|
381
|
+
var msg = _msg(["From: a@example.com", "To: b@example.com", "Subject: x",
|
|
382
|
+
"Date: Wed, 14 May 2026 12:00:00 +0000", "Content-Type: text/plain; charset=utf-8"], mb);
|
|
383
|
+
var threw = null;
|
|
384
|
+
try { store.appendMessage("INBOX", msg); } catch (e) { threw = e; }
|
|
385
|
+
check("mailStore byte-cap: multibyte body over byte cap refused",
|
|
386
|
+
threw && threw.code === "mail-store/oversize-body");
|
|
387
|
+
} finally { _teardown(fx); }
|
|
388
|
+
}
|
|
389
|
+
|
|
374
390
|
async function run() {
|
|
391
|
+
await testByteCapMultibyte();
|
|
375
392
|
testSurface();
|
|
376
393
|
await testBootstrap();
|
|
377
394
|
await testAppendFetchRoundtrip();
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* mime-parse — RFC 5322 / 2045 header-block + MIME structure parsing shared by
|
|
4
|
+
* the mail stack (email, dsn, arf, auth, bounce). Covers the header-block
|
|
5
|
+
* classifier (fields / malformed / folding / header-body boundary), the
|
|
6
|
+
* parseHeaderBlock fields view, header/body bisection, Content-Type parsing,
|
|
7
|
+
* case-insensitive header lookup, and multipart partitioning.
|
|
8
|
+
*
|
|
9
|
+
* classifyHeaderBlock.malformed is the header-injection signal (a header-section
|
|
10
|
+
* line that is neither a `name: value` field nor a folding continuation) that
|
|
11
|
+
* the silent-skip parsers used to drop; guard-email consumes it.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
var helpers = require("../helpers");
|
|
15
|
+
var check = helpers.check;
|
|
16
|
+
var mp = require("../../lib/mime-parse");
|
|
17
|
+
|
|
18
|
+
function _eq(label, actual, expected) {
|
|
19
|
+
check(label, JSON.stringify(actual) === JSON.stringify(expected));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function testClassifyHeaderBlockFields() {
|
|
23
|
+
var r = mp.classifyHeaderBlock("A: 1\r\nB: 2\r\n boldfold\r\n\r\nbody");
|
|
24
|
+
_eq("classify: fields parsed, folding collapsed to single SP",
|
|
25
|
+
r.fields, [{ name: "A", value: "1" }, { name: "B", value: "2 boldfold" }]);
|
|
26
|
+
check("classify: clean block has no malformed lines", r.malformed.length === 0);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function testClassifyHeaderBlockMalformed() {
|
|
30
|
+
var r = mp.classifyHeaderBlock("garbage\r\nTo: x@y.com");
|
|
31
|
+
_eq("classify: a colon-less header-section line is malformed (injection signal)",
|
|
32
|
+
r.malformed, [{ lineIndex: 0, line: "garbage", reason: "no-colon" }]);
|
|
33
|
+
_eq("classify: the valid field after it still parses",
|
|
34
|
+
r.fields, [{ name: "To", value: "x@y.com" }]);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function testClassifyHeaderBlockBoundary() {
|
|
38
|
+
// A non-field line AFTER the blank header/body boundary is BODY — not flagged.
|
|
39
|
+
var r = mp.classifyHeaderBlock("A: 1\r\n\r\nnot-a-header-line");
|
|
40
|
+
check("classify: boundary-aware — body lines are not malformed", r.malformed.length === 0);
|
|
41
|
+
_eq("classify: only the header section is parsed into fields",
|
|
42
|
+
r.fields, [{ name: "A", value: "1" }]);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function testClassifyHeaderBlockBadInput() {
|
|
46
|
+
check("classify: null → empty structure", mp.classifyHeaderBlock(null).fields.length === 0);
|
|
47
|
+
check("classify: undefined → empty structure", mp.classifyHeaderBlock(undefined).malformed.length === 0);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function testParseHeaderBlockIsFieldsView() {
|
|
51
|
+
_eq("parseHeaderBlock returns the classifier's fields",
|
|
52
|
+
mp.parseHeaderBlock("From: a\r\nTo: b"),
|
|
53
|
+
[{ name: "From", value: "a" }, { name: "To", value: "b" }]);
|
|
54
|
+
// Equivalence with classifyHeaderBlock.fields on the same input.
|
|
55
|
+
var raw = "Subject: hi\r\n there\r\nFrom: a@b.com";
|
|
56
|
+
_eq("parseHeaderBlock === classifyHeaderBlock(x).fields",
|
|
57
|
+
mp.parseHeaderBlock(raw), mp.classifyHeaderBlock(raw).fields);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function testSplitHeadersAndBody() {
|
|
61
|
+
var s = mp.splitHeadersAndBody("H: v\r\n\r\nthe body\r\nline2");
|
|
62
|
+
_eq("split: header section parsed", s.headers, [{ name: "H", value: "v" }]);
|
|
63
|
+
check("split: body preserved verbatim after the blank line", s.body === "the body\r\nline2");
|
|
64
|
+
var none = mp.splitHeadersAndBody("H: v\r\nI: w");
|
|
65
|
+
check("split: no blank line → empty body", none.body === "");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function testParseContentType() {
|
|
69
|
+
var ct = mp.parseContentType("text/html; charset=utf-8; boundary=xyz");
|
|
70
|
+
check("parseContentType: type lowercased", ct.type === "text/html");
|
|
71
|
+
check("parseContentType: charset param", ct.params.charset === "utf-8");
|
|
72
|
+
check("parseContentType: boundary param", ct.params.boundary === "xyz");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function testFindHeader() {
|
|
76
|
+
var hs = [{ name: "From", value: "a" }, { name: "to", value: "b" }];
|
|
77
|
+
check("findHeader: case-insensitive match", mp.findHeader(hs, "TO") === "b");
|
|
78
|
+
check("findHeader: missing → null/undefined", !mp.findHeader(hs, "Subject"));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function testSplitMimeParts() {
|
|
82
|
+
_eq("splitMimeParts: partitions on --boundary, drops preamble + close",
|
|
83
|
+
mp.splitMimeParts("preamble\r\n--bnd\r\npart1\r\n--bnd\r\npart2\r\n--bnd--\r\n", "bnd"),
|
|
84
|
+
["part1", "part2"]);
|
|
85
|
+
_eq("splitMimeParts: empty boundary → no parts",
|
|
86
|
+
mp.splitMimeParts("anything", ""), []);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function run() {
|
|
90
|
+
testClassifyHeaderBlockFields();
|
|
91
|
+
testClassifyHeaderBlockMalformed();
|
|
92
|
+
testClassifyHeaderBlockBoundary();
|
|
93
|
+
testClassifyHeaderBlockBadInput();
|
|
94
|
+
testParseHeaderBlockIsFieldsView();
|
|
95
|
+
testSplitHeadersAndBody();
|
|
96
|
+
testParseContentType();
|
|
97
|
+
testFindHeader();
|
|
98
|
+
testSplitMimeParts();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
module.exports = { run: run };
|
|
102
|
+
|
|
103
|
+
if (require.main === module) {
|
|
104
|
+
try { run(); console.log("[mime-parse] OK — " + helpers.getChecks() + " checks passed"); }
|
|
105
|
+
catch (e) { console.error("FAIL:", e.stack || e); process.exit(1); }
|
|
106
|
+
}
|
|
@@ -20,7 +20,24 @@ function run() {
|
|
|
20
20
|
check("b.money.convert function", typeof b.money.convert === "function");
|
|
21
21
|
check("b.money.CURRENCIES exposed", typeof b.money.CURRENCIES === "object");
|
|
22
22
|
check("b.money.MoneyError exposed", typeof b.money.MoneyError === "function");
|
|
23
|
+
check("b.money.roundMinor function", typeof b.money.roundMinor === "function");
|
|
23
24
|
check("b.money.Money class exposed", typeof b.money.Money === "function");
|
|
25
|
+
|
|
26
|
+
// ---- roundMinor: cash-rounding to an increment (BigInt minor units) ----
|
|
27
|
+
check("roundMinor: CHF 12.32 → nearest 0.05 (half-even)", b.money.roundMinor(1232n, 5n) === 1230n);
|
|
28
|
+
check("roundMinor: tie → half-even picks even multiple", b.money.roundMinor(25n, 10n, "half-even") === 20n);
|
|
29
|
+
check("roundMinor: tie → half-up away from zero", b.money.roundMinor(25n, 10n, "half-up") === 30n);
|
|
30
|
+
check("roundMinor: negative tie → half-up away from zero", b.money.roundMinor(-25n, 10n, "half-up") === -30n);
|
|
31
|
+
check("roundMinor: floor toward -inf", b.money.roundMinor(27n, 10n, "floor") === 20n);
|
|
32
|
+
check("roundMinor: ceiling toward +inf", b.money.roundMinor(21n, 10n, "ceiling") === 30n);
|
|
33
|
+
check("roundMinor: exact multiple returns unchanged", b.money.roundMinor(30n, 10n) === 30n);
|
|
34
|
+
check("roundMinor: safe-integer Number coerced to BigInt", b.money.roundMinor(25, 10n, "half-up") === 30n);
|
|
35
|
+
check("roundMinor: bad mode throws money/bad-rounding-mode",
|
|
36
|
+
(function () { try { b.money.roundMinor(10n, 5n, "nope"); return null; } catch (e) { return e.code; } })()
|
|
37
|
+
=== "money/bad-rounding-mode");
|
|
38
|
+
check("roundMinor: non-integer minor throws money/bad-minor-units",
|
|
39
|
+
(function () { try { b.money.roundMinor(1.5, 5n); return null; } catch (e) { return e.code; } })()
|
|
40
|
+
=== "money/bad-minor-units");
|
|
24
41
|
check("b.money.Money is the prototype", b.money.of("1.00", "USD") instanceof b.money.Money);
|
|
25
42
|
check("CURRENCIES is frozen", Object.isFrozen(b.money.CURRENCIES));
|
|
26
43
|
check("CURRENCIES.USD exponent", b.money.CURRENCIES.USD === 2);
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* b.mtlsCa revocation + issuance identity (#322).
|
|
4
|
+
*
|
|
5
|
+
* The require-mtls gate denies by SHA3-512 fingerprint, but revocation used to
|
|
6
|
+
* be keyed only by serial, the registry could only be a plaintext file, and
|
|
7
|
+
* issuance discarded the serial + fingerprint. This proves the three additive
|
|
8
|
+
* fixes: fingerprint-addressable revoke()/isRevoked(), a bring-your-own
|
|
9
|
+
* revocation store, and serial+fingerprint surfaced from issuance.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
var helpers = require("../helpers");
|
|
13
|
+
var b = helpers.b;
|
|
14
|
+
var check = helpers.check;
|
|
15
|
+
var fs = require("fs");
|
|
16
|
+
var os = require("os");
|
|
17
|
+
var path = require("path");
|
|
18
|
+
|
|
19
|
+
async function run() {
|
|
20
|
+
var dir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-mtls-revoke-"));
|
|
21
|
+
var ca = b.mtlsCa.create({ dataDir: dir, caKeySealedMode: "disabled", generation: 1 });
|
|
22
|
+
|
|
23
|
+
// ---- #322 part 3: issuance surfaces serial + fingerprint ----
|
|
24
|
+
var issued = await ca.generateClientCert({ cn: "client-1" });
|
|
25
|
+
check("issuance surfaces a hex serialNumber",
|
|
26
|
+
typeof issued.serialNumber === "string" && /^[0-9a-f]+$/.test(issued.serialNumber));
|
|
27
|
+
check("issuance surfaces a 128-hex SHA3-512 fingerprint",
|
|
28
|
+
typeof issued.fingerprint === "string" && issued.fingerprint.length === 128);
|
|
29
|
+
check("the surfaced fingerprint equals the gate's b.crypto.sha3Hash(cert)",
|
|
30
|
+
issued.fingerprint === b.crypto.sha3Hash(issued.cert));
|
|
31
|
+
|
|
32
|
+
// ---- #322 part 1: revoke + isRevoked by serial (backward-compat) ----
|
|
33
|
+
ca.revoke(issued.serialNumber, { reason: "superseded" });
|
|
34
|
+
check("revoke(serial) then isRevoked(serial) is true", ca.isRevoked(issued.serialNumber) === true);
|
|
35
|
+
check("a serial that was never revoked reads false", ca.isRevoked("00ff") === false);
|
|
36
|
+
var first = ca.revoke(issued.serialNumber);
|
|
37
|
+
var again = ca.revoke(issued.serialNumber);
|
|
38
|
+
check("revoke is idempotent (revokedAt unchanged)", first.revokedAt === again.revokedAt);
|
|
39
|
+
|
|
40
|
+
// ---- #322 part 1: revoke + isRevoked by fingerprint (the gate's key) ----
|
|
41
|
+
var issued2 = await ca.generateClientCert({ cn: "client-2" });
|
|
42
|
+
ca.revoke({ fingerprint: issued2.fingerprint, reason: "keyCompromise" });
|
|
43
|
+
check("revoke({fingerprint}) then isRevoked(fingerprint) is true",
|
|
44
|
+
ca.isRevoked(issued2.fingerprint) === true);
|
|
45
|
+
check("isRevoked tolerates separator/case formatting",
|
|
46
|
+
ca.isRevoked(issued2.fingerprint.toUpperCase()) === true);
|
|
47
|
+
|
|
48
|
+
var threwNoKey = false;
|
|
49
|
+
try { ca.revoke({ reason: "x" }); } catch (e) { threwNoKey = /no-revocation-key/.test(e.code || ""); }
|
|
50
|
+
check("revoke with neither serial nor fingerprint throws", threwNoKey);
|
|
51
|
+
|
|
52
|
+
// ---- #322 part 2: bring-your-own revocation store ----
|
|
53
|
+
var rows = [];
|
|
54
|
+
var store = { list: function () { return rows.slice(); }, add: function (e) { rows.push(e); } };
|
|
55
|
+
var dir2 = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-mtls-byostore-"));
|
|
56
|
+
var ca2 = b.mtlsCa.create({ dataDir: dir2, caKeySealedMode: "disabled", revocationStore: store });
|
|
57
|
+
ca2.revoke("AB:CD:EF", { reason: "cessationOfOperation" });
|
|
58
|
+
check("BYO store: revoke writes through the operator store (normalized serial)",
|
|
59
|
+
rows.length === 1 && rows[0].serialNumber === "abcdef");
|
|
60
|
+
check("BYO store: isRevoked reads through the operator store", ca2.isRevoked("abcdef") === true);
|
|
61
|
+
check("BYO store: the default revocations.json was not written",
|
|
62
|
+
!fs.existsSync(path.join(dir2, "revocations.json")));
|
|
63
|
+
|
|
64
|
+
var threwBadStore = false;
|
|
65
|
+
try {
|
|
66
|
+
b.mtlsCa.create({ dataDir: dir2, caKeySealedMode: "disabled", revocationStore: { list: 1 } });
|
|
67
|
+
} catch (e) { threwBadStore = /bad-revocation-store/.test(e.code || ""); }
|
|
68
|
+
check("a revocationStore missing list()/add() is refused at create()", threwBadStore);
|
|
69
|
+
|
|
70
|
+
// ---- #322 part 3: a custom engine may return a non-X.509 cert shape ----
|
|
71
|
+
// The serial comes from an X.509 parse (best-effort); the fingerprint is a
|
|
72
|
+
// hash of the returned bytes (always available). Optional identity
|
|
73
|
+
// enrichment must never crash issuance.
|
|
74
|
+
var dir3 = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-mtls-stub-"));
|
|
75
|
+
var stubEngine = {
|
|
76
|
+
generateCa: async function () {
|
|
77
|
+
return { caCertPem: "ENGINE-CA", caKeyPem: "ENGINE-KEY", generation: 1 };
|
|
78
|
+
},
|
|
79
|
+
signClientCert: async function (a) {
|
|
80
|
+
return { cert: "-----BEGIN CERTIFICATE-----\nNOT-X509-" + a.cn + "\n-----END CERTIFICATE-----\n", key: "k" };
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
var ca3 = b.mtlsCa.create({ dataDir: dir3, engine: stubEngine, caKeySealedMode: "disabled" });
|
|
84
|
+
var stub = await ca3.generateClientCert({ cn: "stub-client" });
|
|
85
|
+
check("non-X.509 engine cert does not crash issuance", typeof stub.cert === "string");
|
|
86
|
+
check("unparseable cert yields serialNumber null (best-effort)", stub.serialNumber === null);
|
|
87
|
+
check("fingerprint is still surfaced for a non-X.509 cert", stub.fingerprint === b.crypto.sha3Hash(stub.cert));
|
|
88
|
+
ca3.revoke({ fingerprint: stub.fingerprint });
|
|
89
|
+
check("a non-X.509 cert is still revocable by fingerprint", ca3.isRevoked(stub.fingerprint) === true);
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
93
|
+
fs.rmSync(dir2, { recursive: true, force: true });
|
|
94
|
+
fs.rmSync(dir3, { recursive: true, force: true });
|
|
95
|
+
} catch (_e) { /* best-effort */ }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
module.exports = { run: run };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* b.nonceStore.release(nonce) — the rollback half of reserve -> commit ->
|
|
4
|
+
* rollback (#325).
|
|
5
|
+
*
|
|
6
|
+
* An eager checkAndInsert claim with no un-claim inverts the at-least-once
|
|
7
|
+
* contract: when downstream processing fails and the provider redelivers, the
|
|
8
|
+
* already-claimed id reads as a replay and the event is dropped. release()
|
|
9
|
+
* un-claims so the redelivery is reprocessed. The cluster backend's release
|
|
10
|
+
* (DELETE by nonce hash) is exercised in the live-integration suite; here we
|
|
11
|
+
* cover the memory + custom backends.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
var helpers = require("../helpers");
|
|
15
|
+
var b = helpers.b;
|
|
16
|
+
var check = helpers.check;
|
|
17
|
+
|
|
18
|
+
async function run() {
|
|
19
|
+
var exp = Date.now() + 60000;
|
|
20
|
+
|
|
21
|
+
// ---- memory backend: reserve -> replay -> release -> re-reserve ----
|
|
22
|
+
var s = b.nonceStore.create({ backend: "memory" });
|
|
23
|
+
check("#325 first claim wins (reserve)", (await s.checkAndInsert("evt-1", exp)) === true);
|
|
24
|
+
check("#325 a concurrent duplicate reads as replay", (await s.checkAndInsert("evt-1", exp)) === false);
|
|
25
|
+
check("#325 release un-claims a live nonce (returns true)", (await s.release("evt-1")) === true);
|
|
26
|
+
check("#325 a redelivery after release is reprocessed (re-claim wins)",
|
|
27
|
+
(await s.checkAndInsert("evt-1", exp)) === true);
|
|
28
|
+
check("#325 commit path: WITHOUT release the duplicate stays suppressed",
|
|
29
|
+
(await s.checkAndInsert("evt-1", exp)) === false);
|
|
30
|
+
check("#325 release of a never-claimed nonce returns false", (await s.release("never-seen")) === false);
|
|
31
|
+
|
|
32
|
+
var threwBad = false;
|
|
33
|
+
try { await s.release(""); } catch (e) { threwBad = /INVALID_NONCE/.test(e.code || ""); }
|
|
34
|
+
check("#325 release rejects an empty nonce", threwBad);
|
|
35
|
+
s.close();
|
|
36
|
+
|
|
37
|
+
// ---- custom backend: release forwarded when present, loud when absent ----
|
|
38
|
+
var forwarded = null;
|
|
39
|
+
var withRelease = b.nonceStore.create({ backend: {
|
|
40
|
+
checkAndInsert: function () { return Promise.resolve(true); },
|
|
41
|
+
release: function (n) { forwarded = n; return Promise.resolve(true); },
|
|
42
|
+
} });
|
|
43
|
+
await withRelease.release("evt-Z");
|
|
44
|
+
check("#325 a custom backend's release() is forwarded", forwarded === "evt-Z");
|
|
45
|
+
|
|
46
|
+
var withoutRelease = b.nonceStore.create({ backend: {
|
|
47
|
+
checkAndInsert: function () { return Promise.resolve(true); },
|
|
48
|
+
} });
|
|
49
|
+
var threwNoRel = false;
|
|
50
|
+
try { await withoutRelease.release("x"); } catch (e) { threwNoRel = /BACKEND_NO_RELEASE/.test(e.code || ""); }
|
|
51
|
+
check("#325 a custom backend without release() fails loudly (no silent dropped rollback)", threwNoRel);
|
|
52
|
+
|
|
53
|
+
// ---- enforceReplay: first use passes; replay refused; store-throw fails closed ----
|
|
54
|
+
function RErr(code, message) { this.code = code; this.message = message; }
|
|
55
|
+
var ropts = { errorClass: RErr, storeFailedCode: "x/store-failed", replayCode: "x/replay", tokenLabel: "token" };
|
|
56
|
+
var rs = b.nonceStore.create({ backend: "memory" });
|
|
57
|
+
await b.nonceStore.enforceReplay(rs, "jti-A", exp, ropts);
|
|
58
|
+
check("enforceReplay: first use of a jti passes (no throw)", true);
|
|
59
|
+
var replayErr = null;
|
|
60
|
+
try { await b.nonceStore.enforceReplay(rs, "jti-A", exp, ropts); } catch (e) { replayErr = e; }
|
|
61
|
+
check("enforceReplay: a re-used jti is refused with the replay code + message",
|
|
62
|
+
replayErr instanceof RErr && replayErr.code === "x/replay" &&
|
|
63
|
+
replayErr.message === "token jti='jti-A' has been seen before — replay refused");
|
|
64
|
+
rs.close();
|
|
65
|
+
|
|
66
|
+
// A store failure must fail CLOSED (store-failed error), never silently pass.
|
|
67
|
+
var failStore = b.nonceStore.create({ backend: {
|
|
68
|
+
checkAndInsert: function () { return Promise.reject(new Error("db down")); },
|
|
69
|
+
} });
|
|
70
|
+
var storeErr = null;
|
|
71
|
+
try { await b.nonceStore.enforceReplay(failStore, "jti-B", exp, ropts); } catch (e) { storeErr = e; }
|
|
72
|
+
check("enforceReplay: a store failure fails closed (store-failed code, not a pass)",
|
|
73
|
+
storeErr instanceof RErr && storeErr.code === "x/store-failed" &&
|
|
74
|
+
storeErr.message.indexOf("replayStore.checkAndInsert threw: db down") === 0);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = { run: run };
|
|
@@ -201,6 +201,52 @@ function testObservabilitySemconvK8sAttributes() {
|
|
|
201
201
|
check("SEMCONV.K8S_REPLICASET_NAME", S.K8S_REPLICASET_NAME === "k8s.replicaset.name");
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
+
// b.observability.namespaced — the drop-silent prefixed metric emitter every
|
|
205
|
+
// primitive used to hand-roll as a private _emitMetric closure.
|
|
206
|
+
function testObservabilityNamespaced() {
|
|
207
|
+
check("b.observability.namespaced is a function",
|
|
208
|
+
typeof b.observability.namespaced === "function");
|
|
209
|
+
var seen = [];
|
|
210
|
+
var orig = b.observability.safeEvent; // late-bound — the stub is observed
|
|
211
|
+
b.observability.safeEvent = function (name, n, labels) {
|
|
212
|
+
seen.push({ name: name, n: n, labels: labels });
|
|
213
|
+
};
|
|
214
|
+
try {
|
|
215
|
+
var emit = b.observability.namespaced("network.byte_quota");
|
|
216
|
+
emit("exceeded", 5, { key: "k" });
|
|
217
|
+
emit("reset"); // value → 1, labels → {}
|
|
218
|
+
var gated = b.observability.namespaced("middleware.tusUpload", false);
|
|
219
|
+
gated("create.ok"); // gateFlag false → no-op
|
|
220
|
+
} finally {
|
|
221
|
+
b.observability.safeEvent = orig;
|
|
222
|
+
}
|
|
223
|
+
check("namespaced prefixes the name + passes value/labels through",
|
|
224
|
+
seen[0].name === "network.byte_quota.exceeded" && seen[0].n === 5 && seen[0].labels.key === "k");
|
|
225
|
+
check("namespaced defaults value to 1 and labels to {}",
|
|
226
|
+
seen[1].name === "network.byte_quota.reset" && seen[1].n === 1 &&
|
|
227
|
+
JSON.stringify(seen[1].labels) === "{}");
|
|
228
|
+
check("namespaced(prefix, false) is a no-op",
|
|
229
|
+
!seen.some(function (e) { return e.name === "middleware.tusUpload.create.ok"; }));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// b.observability.makeCounterEmitter — the per-instance counter sibling of
|
|
233
|
+
// namespaced, every primitive used to hand-roll as a private _emitObs closure.
|
|
234
|
+
function testObservabilityMakeCounterEmitter() {
|
|
235
|
+
check("b.observability.makeCounterEmitter is a function",
|
|
236
|
+
typeof b.observability.makeCounterEmitter === "function");
|
|
237
|
+
var sinkSeen = [];
|
|
238
|
+
var sink = { event: function (name, value, labels) { sinkSeen.push({ name: name, value: value, labels: labels }); } };
|
|
239
|
+
var emit = b.observability.makeCounterEmitter(sink);
|
|
240
|
+
emit("auth.lockout.tripped", { actor: "alice" });
|
|
241
|
+
check("makeCounterEmitter emits value 1 + name + labels to the sink",
|
|
242
|
+
sinkSeen.length === 1 && sinkSeen[0].name === "auth.lockout.tripped" &&
|
|
243
|
+
sinkSeen[0].value === 1 && sinkSeen[0].labels.actor === "alice");
|
|
244
|
+
var threw = false;
|
|
245
|
+
try { b.observability.makeCounterEmitter({ event: function () { throw new Error("sink down"); } })("x"); }
|
|
246
|
+
catch (_e) { threw = true; }
|
|
247
|
+
check("makeCounterEmitter is drop-silent on a sink throw", threw === false);
|
|
248
|
+
}
|
|
249
|
+
|
|
204
250
|
async function run() {
|
|
205
251
|
testObservabilitySurface();
|
|
206
252
|
testObservabilityTapRunsFnWithoutRegistries();
|
|
@@ -217,6 +263,8 @@ async function run() {
|
|
|
217
263
|
testObservabilityEventDropsBadName();
|
|
218
264
|
testObservabilitySemconvResourceAttributes();
|
|
219
265
|
testObservabilitySemconvK8sAttributes();
|
|
266
|
+
testObservabilityNamespaced();
|
|
267
|
+
testObservabilityMakeCounterEmitter();
|
|
220
268
|
}
|
|
221
269
|
|
|
222
270
|
module.exports = { run: run };
|