@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
|
@@ -127,8 +127,9 @@
|
|
|
127
127
|
*/
|
|
128
128
|
|
|
129
129
|
var net = require("node:net");
|
|
130
|
+
var safeBuffer = require("./safe-buffer");
|
|
130
131
|
var mailServerTls = require("./mail-server-tls");
|
|
131
|
-
var
|
|
132
|
+
var mailServerNet = require("./mail-server-net");
|
|
132
133
|
var C = require("./constants");
|
|
133
134
|
var bCrypto = require("./crypto");
|
|
134
135
|
var numericBounds = require("./numeric-bounds");
|
|
@@ -139,7 +140,7 @@ var mailServerRateLimit = require("./mail-server-rate-limit");
|
|
|
139
140
|
var mailServerRegistry = require("./mail-server-registry");
|
|
140
141
|
var { defineClass } = require("./framework-error");
|
|
141
142
|
|
|
142
|
-
var
|
|
143
|
+
var auditEmit = require("./audit-emit");
|
|
143
144
|
|
|
144
145
|
var MailServerManageSieveError = defineClass("MailServerManageSieveError",
|
|
145
146
|
{ alwaysPermanent: true });
|
|
@@ -226,40 +227,18 @@ function create(opts) {
|
|
|
226
227
|
// the actual script bytes — same cap on both sides).
|
|
227
228
|
var safeSieveProfile = profile;
|
|
228
229
|
|
|
229
|
-
var rateLimit;
|
|
230
|
-
if (opts.rateLimit === false) {
|
|
231
|
-
rateLimit = mailServerRateLimit.create({ disabled: true });
|
|
232
|
-
} else if (opts.rateLimit && typeof opts.rateLimit.admitConnection === "function") {
|
|
233
|
-
rateLimit = opts.rateLimit;
|
|
234
|
-
} else {
|
|
235
|
-
rateLimit = mailServerRateLimit.create(opts.rateLimit || {});
|
|
236
|
-
}
|
|
230
|
+
var rateLimit = mailServerRateLimit.resolve(opts.rateLimit);
|
|
237
231
|
|
|
238
|
-
var tcpServer = null;
|
|
239
|
-
var listening = false;
|
|
240
232
|
var connections = new Set();
|
|
241
233
|
|
|
242
|
-
|
|
243
|
-
try {
|
|
244
|
-
audit().safeEmit({
|
|
245
|
-
action: action,
|
|
246
|
-
outcome: outcome || "success",
|
|
247
|
-
metadata: metadata || {},
|
|
248
|
-
});
|
|
249
|
-
} catch (_e) { /* drop-silent — audit best-effort */ }
|
|
250
|
-
}
|
|
234
|
+
var _emit = auditEmit.emit;
|
|
251
235
|
|
|
252
236
|
function _handleConnection(rawSocket) {
|
|
253
|
-
var remoteAddress = rawSocket
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
try { rawSocket.write('NO "Too many connections from your IP"\r\n'); }
|
|
259
|
-
catch (_e) { /* socket may be down */ }
|
|
260
|
-
try { rawSocket.destroy(); } catch (_e2) { /* idempotent */ }
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
237
|
+
var remoteAddress = mailServerNet.admitConnection(rawSocket, rateLimit, _emit, {
|
|
238
|
+
refusedEvent: "mail.server.managesieve.rate_limit_refused",
|
|
239
|
+
refusalLine: 'NO "Too many connections from your IP"\r\n',
|
|
240
|
+
});
|
|
241
|
+
if (remoteAddress === null) return;
|
|
263
242
|
var connectionId = "msvconn-" + bCrypto.generateToken(8); // connection-id length
|
|
264
243
|
var socket = rawSocket;
|
|
265
244
|
connections.add(socket);
|
|
@@ -354,7 +333,7 @@ function create(opts) {
|
|
|
354
333
|
}
|
|
355
334
|
var crlf = state.lineBuffer.indexOf("\r\n");
|
|
356
335
|
if (crlf === -1) {
|
|
357
|
-
if (state.lineBuffer
|
|
336
|
+
if (safeBuffer.byteLengthOf(state.lineBuffer) > maxLineBytes) {
|
|
358
337
|
_writeNo(socket, "Line too long (cap " + maxLineBytes + ")");
|
|
359
338
|
_close(socket);
|
|
360
339
|
}
|
|
@@ -525,19 +504,18 @@ function create(opts) {
|
|
|
525
504
|
}
|
|
526
505
|
_writeOk(socket, "Begin TLS negotiation now");
|
|
527
506
|
// RFC 5804 §2.2 — discard any bytes the client queued before the
|
|
528
|
-
// upgrade
|
|
529
|
-
//
|
|
530
|
-
//
|
|
531
|
-
//
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
mailServerTls.upgradeSocket({
|
|
536
|
-
plainSocket: socket,
|
|
507
|
+
// upgrade (lineBuffer + pendingLiteral + pendingAuth) so pre-
|
|
508
|
+
// handshake injection can't survive into the post-TLS session.
|
|
509
|
+
// The shared upgradeLineProtocol helper owns that drain plus the
|
|
510
|
+
// CVE-2021-33515 / CVE-2021-38371 listener-strip + pause + read-pump.
|
|
511
|
+
mailServerTls.upgradeLineProtocol({
|
|
512
|
+
state: state,
|
|
513
|
+
socket: socket,
|
|
537
514
|
secureContext: tlsContext,
|
|
538
515
|
idleTimeoutMs: idleTimeoutMs,
|
|
516
|
+
clearFields: ["pendingLiteral", "pendingAuth"],
|
|
517
|
+
drain: _drainBuffer,
|
|
539
518
|
onSecure: function (tlsSocket) {
|
|
540
|
-
state.tls = true;
|
|
541
519
|
_emit("mail.server.managesieve.starttls_upgraded",
|
|
542
520
|
{ connectionId: state.id });
|
|
543
521
|
// RFC 5804 §2.2 — server MUST re-emit capabilities on the
|
|
@@ -546,10 +524,6 @@ function create(opts) {
|
|
|
546
524
|
_emitCapabilityBanner(state, tlsSocket);
|
|
547
525
|
_writeOk(tlsSocket, "TLS negotiation successful");
|
|
548
526
|
},
|
|
549
|
-
onData: function (tlsSocket, chunk) {
|
|
550
|
-
state.lineBuffer = Buffer.concat([state.lineBuffer, chunk]);
|
|
551
|
-
_drainBuffer(state, tlsSocket);
|
|
552
|
-
},
|
|
553
527
|
onError: function (err) {
|
|
554
528
|
_emit("mail.server.managesieve.starttls_handshake_failed",
|
|
555
529
|
{ connectionId: state.id, error: (err && err.message) || String(err) }, "failure");
|
|
@@ -863,43 +837,15 @@ function create(opts) {
|
|
|
863
837
|
}
|
|
864
838
|
|
|
865
839
|
// ---- Lifecycle ----------------------------------------------------------
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
return new Promise(function (resolve, reject) {
|
|
876
|
-
tcpServer.once("error", reject);
|
|
877
|
-
tcpServer.listen(port, address, function () {
|
|
878
|
-
listening = true;
|
|
879
|
-
tcpServer.removeListener("error", reject);
|
|
880
|
-
_emit("mail.server.managesieve.listening", { port: port, address: address });
|
|
881
|
-
resolve({ port: tcpServer.address().port, address: address });
|
|
882
|
-
});
|
|
883
|
-
});
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
async function close() {
|
|
887
|
-
if (!listening) return;
|
|
888
|
-
listening = false;
|
|
889
|
-
for (var s of connections) { try { s.destroy(); } catch (_e) { /* idempotent */ } }
|
|
890
|
-
connections.clear();
|
|
891
|
-
return new Promise(function (resolve) {
|
|
892
|
-
tcpServer.close(function () {
|
|
893
|
-
_emit("mail.server.managesieve.closed", {});
|
|
894
|
-
resolve();
|
|
895
|
-
});
|
|
896
|
-
});
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
return {
|
|
900
|
-
listen: listen,
|
|
901
|
-
close: close,
|
|
902
|
-
};
|
|
840
|
+
return mailServerNet.createStoreServer(net, {
|
|
841
|
+
defaultPort: DEFAULT_PORT,
|
|
842
|
+
handleConnection: _handleConnection,
|
|
843
|
+
errorClass: MailServerManageSieveError,
|
|
844
|
+
errorCodePrefix: "mail-server-managesieve/",
|
|
845
|
+
emit: _emit,
|
|
846
|
+
connections: connections,
|
|
847
|
+
eventBase: "mail.server.managesieve",
|
|
848
|
+
});
|
|
903
849
|
}
|
|
904
850
|
|
|
905
851
|
module.exports = {
|
|
@@ -150,9 +150,10 @@ var guardSmtpCommand = require("./guard-smtp-command");
|
|
|
150
150
|
var guardDomain = require("./guard-domain");
|
|
151
151
|
var mailServerRateLimit = require("./mail-server-rate-limit");
|
|
152
152
|
var mailServerTls = require("./mail-server-tls");
|
|
153
|
+
var mailServerNet = require("./mail-server-net");
|
|
153
154
|
var { defineClass } = require("./framework-error");
|
|
154
155
|
|
|
155
|
-
var
|
|
156
|
+
var auditEmit = require("./audit-emit");
|
|
156
157
|
// Lazy like the sibling host primitives' guard loads — the inbound
|
|
157
158
|
// authentication pipeline (and the DKIM verifier whose range
|
|
158
159
|
// constants the boot validation mirrors) only loads when an operator
|
|
@@ -338,14 +339,7 @@ function create(opts) {
|
|
|
338
339
|
// handle from b.mail.server.rateLimit.create({...}) to share one
|
|
339
340
|
// budget across multiple listeners, or pass an opts object to
|
|
340
341
|
// override defaults.
|
|
341
|
-
var rateLimit;
|
|
342
|
-
if (opts.rateLimit === false) {
|
|
343
|
-
rateLimit = mailServerRateLimit.create({ disabled: true });
|
|
344
|
-
} else if (opts.rateLimit && typeof opts.rateLimit.admitConnection === "function") {
|
|
345
|
-
rateLimit = opts.rateLimit;
|
|
346
|
-
} else {
|
|
347
|
-
rateLimit = mailServerRateLimit.create(opts.rateLimit || {});
|
|
348
|
-
}
|
|
342
|
+
var rateLimit = mailServerRateLimit.resolve(opts.rateLimit);
|
|
349
343
|
|
|
350
344
|
// DATA-phase message-authentication gate. `guardEnvelope: true`
|
|
351
345
|
// gates with defaults; an object tunes it. Like the sibling gates
|
|
@@ -451,16 +445,12 @@ function create(opts) {
|
|
|
451
445
|
});
|
|
452
446
|
}
|
|
453
447
|
function _validateDomainHardened(d, label) {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
_emit
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
label: label,
|
|
461
|
-
}, "denied");
|
|
462
|
-
}
|
|
463
|
-
return verdict;
|
|
448
|
+
return mailServerNet.validateDomainHardened(d, label, {
|
|
449
|
+
guardDomainProfile: guardDomainProfile,
|
|
450
|
+
guardDomain: guardDomain,
|
|
451
|
+
emit: _emit,
|
|
452
|
+
refusedEvent: "mail.server.mx.domain_refused",
|
|
453
|
+
});
|
|
464
454
|
}
|
|
465
455
|
|
|
466
456
|
// Pre-validate operator-supplied localDomains at boot — the same
|
|
@@ -479,35 +469,19 @@ function create(opts) {
|
|
|
479
469
|
}
|
|
480
470
|
}
|
|
481
471
|
|
|
482
|
-
var tcpServer = null;
|
|
483
|
-
var listening = false;
|
|
484
472
|
var connections = new Set();
|
|
485
473
|
|
|
486
|
-
|
|
487
|
-
try {
|
|
488
|
-
audit().safeEmit({
|
|
489
|
-
action: action,
|
|
490
|
-
outcome: outcome || "success",
|
|
491
|
-
metadata: metadata || {},
|
|
492
|
-
});
|
|
493
|
-
} catch (_e) { /* drop-silent — audit best-effort */ }
|
|
494
|
-
}
|
|
474
|
+
var _emit = auditEmit.emit;
|
|
495
475
|
|
|
496
476
|
// ---- Per-connection state machine ---------------------------------------
|
|
497
477
|
function _handleConnection(socket) {
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
try {
|
|
506
|
-
socket.write("421 4.7.0 Too many connections from your IP\r\n");
|
|
507
|
-
} catch (_e) { /* socket may already be torn down */ }
|
|
508
|
-
try { socket.destroy(); } catch (_e2) { /* idempotent */ }
|
|
509
|
-
return;
|
|
510
|
-
}
|
|
478
|
+
// 421 4.7.0 — transient refusal; sender retries elsewhere or later.
|
|
479
|
+
// RFC 5321 §3.8 + §4.5.4.2 (transient negative completion).
|
|
480
|
+
var remoteAddress = mailServerNet.admitConnection(socket, rateLimit, _emit, {
|
|
481
|
+
refusedEvent: "mail.server.mx.rate_limit_refused",
|
|
482
|
+
refusalLine: "421 4.7.0 Too many connections from your IP\r\n",
|
|
483
|
+
});
|
|
484
|
+
if (remoteAddress === null) return;
|
|
511
485
|
socket.once("close", function () { rateLimit.releaseConnection(remoteAddress); });
|
|
512
486
|
|
|
513
487
|
var connectionId = "mxconn-" + bCrypto.generateToken(8); // connection-id length
|
|
@@ -653,7 +627,7 @@ function create(opts) {
|
|
|
653
627
|
|
|
654
628
|
// Command phase — byte-buffered (8BITMIME-safe).
|
|
655
629
|
lineBuffer = lineBuffer.length === 0 ? chunk : Buffer.concat([lineBuffer, chunk]);
|
|
656
|
-
if (lineBuffer
|
|
630
|
+
if (safeBuffer.byteLengthOf(lineBuffer) > maxLineBytes * 4) {
|
|
657
631
|
_writeReply(socket, REPLY_500_SYNTAX,
|
|
658
632
|
"5.5.6 Line too long (>" + maxLineBytes + " bytes)");
|
|
659
633
|
_closeConnection(socket);
|
|
@@ -1229,38 +1203,23 @@ function create(opts) {
|
|
|
1229
1203
|
}
|
|
1230
1204
|
|
|
1231
1205
|
// ---- Lifecycle ----------------------------------------------------------
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
tcpServer = net.createServer(function (socket) {
|
|
1243
|
-
_handleConnection(socket);
|
|
1244
|
-
});
|
|
1245
|
-
return new Promise(function (resolve, reject) {
|
|
1246
|
-
tcpServer.once("error", reject);
|
|
1247
|
-
tcpServer.listen(port, address, function () {
|
|
1248
|
-
listening = true;
|
|
1249
|
-
tcpServer.removeListener("error", reject);
|
|
1250
|
-
_emit("mail.server.mx.listening", {
|
|
1251
|
-
port: port, address: address,
|
|
1252
|
-
});
|
|
1253
|
-
resolve({ port: tcpServer.address().port, address: address });
|
|
1254
|
-
});
|
|
1255
|
-
});
|
|
1256
|
-
}
|
|
1206
|
+
// Port 0 (ephemeral, test mode) must NOT fall back to 25 — the `|| 25`
|
|
1207
|
+
// short-circuit was a footgun on the test path; createTcpListener honors an
|
|
1208
|
+
// explicit 0 (only an OMITTED port falls back to the default).
|
|
1209
|
+
var _tcpListener = mailServerNet.createTcpListener(net, {
|
|
1210
|
+
defaultPort: 25, // SMTP MX port (IANA)
|
|
1211
|
+
handleConnection: _handleConnection,
|
|
1212
|
+
errorFactory: function (code, message) { return new MailServerMxError("mail-server-mx/" + code, message); },
|
|
1213
|
+
emit: _emit,
|
|
1214
|
+
listeningEvent: "mail.server.mx.listening",
|
|
1215
|
+
});
|
|
1257
1216
|
|
|
1258
1217
|
async function close(closeOpts) {
|
|
1259
1218
|
closeOpts = closeOpts || {};
|
|
1260
|
-
if (!
|
|
1219
|
+
if (!_tcpListener.isListening()) return;
|
|
1261
1220
|
var timeoutMs = closeOpts.timeoutMs || C.TIME.seconds(30);
|
|
1262
|
-
|
|
1263
|
-
|
|
1221
|
+
_tcpListener.markClosed();
|
|
1222
|
+
_tcpListener.getServer().close();
|
|
1264
1223
|
connections.forEach(function (sock) {
|
|
1265
1224
|
try { _writeReply(sock, REPLY_421_SERVICE_NOT_AVAIL, "4.3.0 Server shutting down"); }
|
|
1266
1225
|
catch (_e) { /* socket already gone */ }
|
|
@@ -1279,10 +1238,10 @@ function create(opts) {
|
|
|
1279
1238
|
function connectionCount() { return connections.size; }
|
|
1280
1239
|
|
|
1281
1240
|
return {
|
|
1282
|
-
listen: listen,
|
|
1241
|
+
listen: _tcpListener.listen,
|
|
1283
1242
|
close: close,
|
|
1284
1243
|
connectionCount: connectionCount,
|
|
1285
|
-
_portForTest: function () { return
|
|
1244
|
+
_portForTest: function () { var s = _tcpListener.getServer(); return s ? s.address().port : null; },
|
|
1286
1245
|
};
|
|
1287
1246
|
}
|
|
1288
1247
|
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// mail-server-net — the TCP-listener lifecycle shared by the mailbox / transfer
|
|
4
|
+
// servers (b.mail.server.imap / pop3 / mx / managesieve / submission). Each of
|
|
5
|
+
// those keeps its OWN connection set and close() drain because those diverge:
|
|
6
|
+
// the store servers (IMAP/POP3/ManageSieve) await a Promise-wrapped
|
|
7
|
+
// tcpServer.close(), while the transfer servers (MX/Submission) send an SMTP
|
|
8
|
+
// 421 to every live socket and drain with a timeout. What every server shares
|
|
9
|
+
// verbatim is the bind: refuse a double-listen, resolve the default port (never
|
|
10
|
+
// falling back off an explicit port 0 — the ephemeral test-bind path), create
|
|
11
|
+
// the listener, and arm a one-shot "error"→reject so a bind failure (EADDRINUSE,
|
|
12
|
+
// EACCES) rejects the listen promise instead of crashing the process. That, plus
|
|
13
|
+
// the listening/server state, is what createTcpListener owns.
|
|
14
|
+
|
|
15
|
+
// createTcpListener(net, cfg) — build a listener lifecycle.
|
|
16
|
+
// cfg.defaultPort port used when listenOpts.port is omitted (an explicit
|
|
17
|
+
// 0 is honored, for an ephemeral test bind).
|
|
18
|
+
// cfg.handleConnection (socket) => void — the server's per-connection handler.
|
|
19
|
+
// cfg.errorFactory (code, message) => Error — builds the typed
|
|
20
|
+
// "<prefix>/already-listening" double-listen error.
|
|
21
|
+
// cfg.emit (action, metadata) => void — the server's audit emitter.
|
|
22
|
+
// cfg.listeningEvent the "...listening" audit action.
|
|
23
|
+
// cfg.listeningExtra optional () => object merged onto the listening event
|
|
24
|
+
// payload (Submission reports implicitTls).
|
|
25
|
+
// Returns { listen, getServer, isListening, markClosed } — the server wires its
|
|
26
|
+
// own close() through getServer()/isListening()/markClosed().
|
|
27
|
+
function createTcpListener(net, cfg) {
|
|
28
|
+
var server = null;
|
|
29
|
+
var listening = false;
|
|
30
|
+
|
|
31
|
+
function listen(listenOpts) {
|
|
32
|
+
listenOpts = listenOpts || {};
|
|
33
|
+
if (listening) {
|
|
34
|
+
throw cfg.errorFactory("already-listening", "listen: already listening");
|
|
35
|
+
}
|
|
36
|
+
var port = listenOpts.port === undefined ? cfg.defaultPort : listenOpts.port;
|
|
37
|
+
var address = listenOpts.address || "0.0.0.0";
|
|
38
|
+
server = net.createServer(function (socket) { cfg.handleConnection(socket); });
|
|
39
|
+
return new Promise(function (resolve, reject) {
|
|
40
|
+
server.once("error", reject);
|
|
41
|
+
server.listen(port, address, function () {
|
|
42
|
+
listening = true;
|
|
43
|
+
server.removeListener("error", reject);
|
|
44
|
+
var payload = { port: port, address: address };
|
|
45
|
+
if (cfg.listeningExtra) {
|
|
46
|
+
var extra = cfg.listeningExtra();
|
|
47
|
+
for (var k in extra) {
|
|
48
|
+
if (Object.prototype.hasOwnProperty.call(extra, k)) payload[k] = extra[k];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
cfg.emit(cfg.listeningEvent, payload);
|
|
52
|
+
resolve({ port: server.address().port, address: address });
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// closeSimple(closeCfg) — the store-server shutdown (IMAP / POP3 / ManageSieve):
|
|
58
|
+
// mark closed, destroy every live socket immediately, then await the listener's
|
|
59
|
+
// own close before emitting the "...closed" audit. The transfer servers
|
|
60
|
+
// (MX / Submission) do NOT use this — they run a graceful SMTP-421 drain with a
|
|
61
|
+
// timeout, so they own their close() and drive it through markClosed()/getServer().
|
|
62
|
+
// closeCfg.connections the server's live-socket Set (destroyed + cleared).
|
|
63
|
+
// closeCfg.emit the server's audit emitter.
|
|
64
|
+
// closeCfg.closedEvent the "...closed" audit action.
|
|
65
|
+
function closeSimple(closeCfg) {
|
|
66
|
+
if (!listening) return Promise.resolve();
|
|
67
|
+
listening = false;
|
|
68
|
+
for (var s of closeCfg.connections) { try { s.destroy(); } catch (_e) { /* idempotent */ } }
|
|
69
|
+
closeCfg.connections.clear();
|
|
70
|
+
return new Promise(function (resolve) {
|
|
71
|
+
server.close(function () {
|
|
72
|
+
closeCfg.emit(closeCfg.closedEvent, {});
|
|
73
|
+
resolve();
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
listen: listen,
|
|
80
|
+
closeSimple: closeSimple,
|
|
81
|
+
getServer: function () { return server; },
|
|
82
|
+
isListening: function () { return listening; },
|
|
83
|
+
markClosed: function () { listening = false; },
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// createStoreServer(net, cfg) — the COMPLETE lifecycle of a mailbox store server
|
|
88
|
+
// (b.mail.server.imap / pop3 / managesieve): compose createTcpListener with the
|
|
89
|
+
// destroy-then-await closeSimple shutdown and return the { listen, close } a
|
|
90
|
+
// store server exposes. The three store servers are byte-identical here, varying
|
|
91
|
+
// only in port, error class, error-code prefix, and audit-event base — so the
|
|
92
|
+
// wiring lives here once. The transfer servers (MX / Submission) do NOT use this:
|
|
93
|
+
// they run a graceful SMTP-421 drain close + a richer return ({ connectionCount,
|
|
94
|
+
// _portForTest, ... }), so they call createTcpListener directly.
|
|
95
|
+
// cfg.defaultPort port used when listen() omits one (explicit 0 honored).
|
|
96
|
+
// cfg.handleConnection (socket) => void — the per-connection handler.
|
|
97
|
+
// cfg.errorClass the server's typed error constructor (code, message).
|
|
98
|
+
// cfg.errorCodePrefix prepended to the double-listen error code
|
|
99
|
+
// (e.g. "mail-server-imap/").
|
|
100
|
+
// cfg.emit (action, metadata) => void — the server's audit emitter.
|
|
101
|
+
// cfg.connections the live-socket Set (destroyed + cleared on close).
|
|
102
|
+
// cfg.eventBase the audit-action base; listeningEvent = eventBase +
|
|
103
|
+
// ".listening", closedEvent = eventBase + ".closed".
|
|
104
|
+
// Returns { listen, close }.
|
|
105
|
+
function createStoreServer(net, cfg) {
|
|
106
|
+
var ErrorClass = cfg.errorClass;
|
|
107
|
+
var listener = createTcpListener(net, {
|
|
108
|
+
defaultPort: cfg.defaultPort,
|
|
109
|
+
handleConnection: cfg.handleConnection,
|
|
110
|
+
errorFactory: function (code, message) { return new ErrorClass(cfg.errorCodePrefix + code, message); },
|
|
111
|
+
emit: cfg.emit,
|
|
112
|
+
listeningEvent: cfg.eventBase + ".listening",
|
|
113
|
+
});
|
|
114
|
+
function close() {
|
|
115
|
+
return listener.closeSimple({
|
|
116
|
+
connections: cfg.connections,
|
|
117
|
+
emit: cfg.emit,
|
|
118
|
+
closedEvent: cfg.eventBase + ".closed",
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return { listen: listener.listen, close: close };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// admitConnection(socket, rateLimit, emit, cfg) — the per-connection rate-limit
|
|
125
|
+
// gate every mail listener's _handleConnection opens with: resolve the remote
|
|
126
|
+
// IP, admit it via the shared b.mail.server.rateLimit, or refuse it with a
|
|
127
|
+
// protocol-specific line + a "<...>.rate_limit_refused" audit (outcome "denied")
|
|
128
|
+
// and tear the socket down. Returns the remote address on admit, or null when
|
|
129
|
+
// refused — the caller does `if (addr === null) return;` then runs its own
|
|
130
|
+
// (protocol-specific) close handler, connection-id, tracking-set insert, and
|
|
131
|
+
// state machine, none of which this touches.
|
|
132
|
+
// cfg.refusedEvent the "<...>.rate_limit_refused" audit action.
|
|
133
|
+
// cfg.refusalLine the wire bytes written before destroy (IMAP "* BAD …",
|
|
134
|
+
// POP3 "-ERR …", SMTP "421 4.7.0 …", ManageSieve 'NO "…"').
|
|
135
|
+
function admitConnection(socket, rateLimit, emit, cfg) {
|
|
136
|
+
var remoteAddress = socket.remoteAddress || "0.0.0.0";
|
|
137
|
+
var admit = rateLimit.admitConnection(remoteAddress);
|
|
138
|
+
if (!admit.ok) {
|
|
139
|
+
emit(cfg.refusedEvent, { remoteAddress: remoteAddress, reason: admit.reason }, "denied");
|
|
140
|
+
try { socket.write(cfg.refusalLine); } catch (_e) { /* socket may be down */ }
|
|
141
|
+
try { socket.destroy(); } catch (_e2) { /* idempotent */ }
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
return remoteAddress;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// validateDomainHardened(d, label, cfg) — the hardened-domain check the MX and
|
|
148
|
+
// Submission transfer servers run on every HELO / MAIL FROM / RCPT TO domain.
|
|
149
|
+
// When a guardDomain profile is configured it validates the domain and, on
|
|
150
|
+
// refusal, emits a "<refusedEvent>" audit (the only per-server difference — MX
|
|
151
|
+
// vs Submission) before returning the verdict; with no profile it passes
|
|
152
|
+
// through { ok: true }. Sharing it keeps the two servers' domain-validation
|
|
153
|
+
// posture identical (a divergence would be a silent spoofing / IDN-homograph
|
|
154
|
+
// gap on one server).
|
|
155
|
+
// cfg.guardDomainProfile the b.guardDomain profile (falsy = validation off).
|
|
156
|
+
// cfg.guardDomain the b.guardDomain module (its validate(d, profile)).
|
|
157
|
+
// cfg.emit (action, metadata, outcome) => void audit emitter.
|
|
158
|
+
// cfg.refusedEvent the "<...>.domain_refused" audit action.
|
|
159
|
+
function validateDomainHardened(d, label, cfg) {
|
|
160
|
+
if (!cfg.guardDomainProfile) return { ok: true };
|
|
161
|
+
var verdict = cfg.guardDomain.validate(d, cfg.guardDomainProfile);
|
|
162
|
+
if (!verdict.ok) {
|
|
163
|
+
cfg.emit(cfg.refusedEvent, {
|
|
164
|
+
reason: verdict.issues && verdict.issues[0] && verdict.issues[0].kind,
|
|
165
|
+
domain: d,
|
|
166
|
+
label: label,
|
|
167
|
+
}, "denied");
|
|
168
|
+
}
|
|
169
|
+
return verdict;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
module.exports = {
|
|
173
|
+
createTcpListener: createTcpListener,
|
|
174
|
+
createStoreServer: createStoreServer,
|
|
175
|
+
admitConnection: admitConnection,
|
|
176
|
+
validateDomainHardened: validateDomainHardened,
|
|
177
|
+
};
|