@blamejs/blamejs-shop 0.4.31 → 0.4.33
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/README.md +1 -1
- package/lib/asset-manifest.json +1 -1
- package/lib/vendor/MANIFEST.json +400 -282
- package/lib/vendor/blamejs/.github/workflows/ci.yml +34 -3
- package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +21 -4
- package/lib/vendor/blamejs/.gitignore +6 -0
- package/lib/vendor/blamejs/CHANGELOG.md +28 -0
- package/lib/vendor/blamejs/MIGRATING.md +55 -0
- package/lib/vendor/blamejs/README.md +8 -6
- package/lib/vendor/blamejs/SECURITY.md +19 -3
- package/lib/vendor/blamejs/api-snapshot.json +2190 -664
- package/lib/vendor/blamejs/docker/caddy/localstack.Caddyfile +19 -0
- package/lib/vendor/blamejs/docker/init/generate-certs.sh +1 -1
- package/lib/vendor/blamejs/docker/otel/config.yaml +42 -0
- package/lib/vendor/blamejs/docker/otel/export/.gitkeep +0 -0
- package/lib/vendor/blamejs/docker/postgres/initdb/10-replication.sh +15 -0
- package/lib/vendor/blamejs/docker/postgres/replica-entrypoint.sh +38 -0
- package/lib/vendor/blamejs/docker/toxiproxy/toxiproxy.json +14 -0
- package/lib/vendor/blamejs/docker-compose.test.yml +209 -0
- package/lib/vendor/blamejs/examples/wiki/lib/page-generator.js +132 -0
- package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +221 -61
- package/lib/vendor/blamejs/examples/wiki/lib/source-doc-parser.js +144 -9
- package/lib/vendor/blamejs/examples/wiki/test/e2e.js +99 -0
- package/lib/vendor/blamejs/fuzz/guard-sql.fuzz.js +36 -0
- package/lib/vendor/blamejs/index.js +4 -0
- package/lib/vendor/blamejs/lib/agent-envelope-mac.js +104 -0
- package/lib/vendor/blamejs/lib/agent-event-bus.js +105 -4
- package/lib/vendor/blamejs/lib/agent-posture-chain.js +8 -42
- package/lib/vendor/blamejs/lib/ai-content-detect.js +9 -10
- package/lib/vendor/blamejs/lib/api-key.js +158 -77
- package/lib/vendor/blamejs/lib/atomic-file.js +62 -4
- package/lib/vendor/blamejs/lib/audit-chain.js +47 -11
- package/lib/vendor/blamejs/lib/audit-sign.js +77 -2
- package/lib/vendor/blamejs/lib/audit-tools.js +79 -51
- package/lib/vendor/blamejs/lib/audit.js +259 -123
- package/lib/vendor/blamejs/lib/auth/elevation-grant.js +6 -2
- package/lib/vendor/blamejs/lib/auth/oauth.js +66 -9
- package/lib/vendor/blamejs/lib/auth/openid-federation.js +108 -47
- package/lib/vendor/blamejs/lib/auth/saml.js +6 -8
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +36 -7
- package/lib/vendor/blamejs/lib/backup/index.js +45 -10
- package/lib/vendor/blamejs/lib/break-glass.js +355 -147
- package/lib/vendor/blamejs/lib/cache.js +174 -105
- package/lib/vendor/blamejs/lib/chain-writer.js +38 -16
- package/lib/vendor/blamejs/lib/cli.js +19 -14
- package/lib/vendor/blamejs/lib/cluster-provider-db.js +130 -104
- package/lib/vendor/blamejs/lib/cluster-storage.js +119 -22
- package/lib/vendor/blamejs/lib/cluster.js +119 -71
- package/lib/vendor/blamejs/lib/codepoint-class.js +23 -0
- package/lib/vendor/blamejs/lib/compliance.js +210 -4
- package/lib/vendor/blamejs/lib/consent.js +82 -29
- package/lib/vendor/blamejs/lib/constants.js +27 -11
- package/lib/vendor/blamejs/lib/credential-hash.js +9 -0
- package/lib/vendor/blamejs/lib/crypto-field.js +916 -156
- package/lib/vendor/blamejs/lib/db-declare-row-policy.js +35 -22
- package/lib/vendor/blamejs/lib/db-file-lifecycle.js +3 -2
- package/lib/vendor/blamejs/lib/db-query.js +882 -260
- package/lib/vendor/blamejs/lib/db-schema.js +228 -44
- package/lib/vendor/blamejs/lib/db.js +249 -99
- package/lib/vendor/blamejs/lib/dsr.js +385 -55
- package/lib/vendor/blamejs/lib/error-page.js +14 -1
- package/lib/vendor/blamejs/lib/external-db-migrate.js +239 -137
- package/lib/vendor/blamejs/lib/external-db.js +549 -34
- package/lib/vendor/blamejs/lib/file-upload.js +52 -7
- package/lib/vendor/blamejs/lib/framework-error.js +20 -1
- package/lib/vendor/blamejs/lib/framework-files.js +73 -0
- package/lib/vendor/blamejs/lib/framework-schema.js +695 -394
- package/lib/vendor/blamejs/lib/gate-contract.js +659 -1
- package/lib/vendor/blamejs/lib/guard-agent-registry.js +26 -44
- package/lib/vendor/blamejs/lib/guard-all.js +1 -0
- package/lib/vendor/blamejs/lib/guard-auth.js +42 -112
- package/lib/vendor/blamejs/lib/guard-cidr.js +33 -154
- package/lib/vendor/blamejs/lib/guard-csv.js +46 -113
- package/lib/vendor/blamejs/lib/guard-domain.js +34 -157
- package/lib/vendor/blamejs/lib/guard-dsn.js +27 -43
- package/lib/vendor/blamejs/lib/guard-email.js +47 -69
- package/lib/vendor/blamejs/lib/guard-envelope.js +19 -32
- package/lib/vendor/blamejs/lib/guard-event-bus-payload.js +24 -42
- package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +25 -43
- package/lib/vendor/blamejs/lib/guard-filename.js +42 -106
- package/lib/vendor/blamejs/lib/guard-graphql.js +42 -123
- package/lib/vendor/blamejs/lib/guard-html.js +53 -108
- package/lib/vendor/blamejs/lib/guard-idempotency-key.js +24 -42
- package/lib/vendor/blamejs/lib/guard-image.js +46 -103
- package/lib/vendor/blamejs/lib/guard-imap-command.js +18 -32
- package/lib/vendor/blamejs/lib/guard-jmap.js +16 -30
- package/lib/vendor/blamejs/lib/guard-json.js +38 -108
- package/lib/vendor/blamejs/lib/guard-jsonpath.js +38 -171
- package/lib/vendor/blamejs/lib/guard-jwt.js +49 -179
- package/lib/vendor/blamejs/lib/guard-list-id.js +25 -41
- package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +27 -43
- package/lib/vendor/blamejs/lib/guard-mail-compose.js +24 -42
- package/lib/vendor/blamejs/lib/guard-mail-move.js +26 -44
- package/lib/vendor/blamejs/lib/guard-mail-query.js +28 -46
- package/lib/vendor/blamejs/lib/guard-mail-reply.js +24 -42
- package/lib/vendor/blamejs/lib/guard-mail-sieve.js +24 -42
- package/lib/vendor/blamejs/lib/guard-managesieve-command.js +17 -31
- package/lib/vendor/blamejs/lib/guard-markdown.js +37 -104
- package/lib/vendor/blamejs/lib/guard-message-id.js +26 -45
- package/lib/vendor/blamejs/lib/guard-mime.js +39 -151
- package/lib/vendor/blamejs/lib/guard-oauth.js +54 -135
- package/lib/vendor/blamejs/lib/guard-pdf.js +45 -101
- package/lib/vendor/blamejs/lib/guard-pop3-command.js +21 -31
- package/lib/vendor/blamejs/lib/guard-posture-chain.js +24 -42
- package/lib/vendor/blamejs/lib/guard-regex.js +33 -107
- package/lib/vendor/blamejs/lib/guard-saga-config.js +24 -42
- package/lib/vendor/blamejs/lib/guard-shell.js +42 -172
- package/lib/vendor/blamejs/lib/guard-smtp-command.js +48 -54
- package/lib/vendor/blamejs/lib/guard-snapshot-envelope.js +24 -42
- package/lib/vendor/blamejs/lib/guard-sql.js +1491 -0
- package/lib/vendor/blamejs/lib/guard-stream-args.js +24 -43
- package/lib/vendor/blamejs/lib/guard-svg.js +47 -65
- package/lib/vendor/blamejs/lib/guard-template.js +35 -172
- package/lib/vendor/blamejs/lib/guard-tenant-id.js +26 -45
- package/lib/vendor/blamejs/lib/guard-time.js +32 -154
- package/lib/vendor/blamejs/lib/guard-trace-context.js +25 -44
- package/lib/vendor/blamejs/lib/guard-uuid.js +32 -153
- package/lib/vendor/blamejs/lib/guard-xml.js +38 -113
- package/lib/vendor/blamejs/lib/guard-yaml.js +51 -163
- package/lib/vendor/blamejs/lib/http-client.js +37 -9
- package/lib/vendor/blamejs/lib/inbox.js +120 -107
- package/lib/vendor/blamejs/lib/legal-hold.js +121 -50
- package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +47 -31
- package/lib/vendor/blamejs/lib/log-stream-otlp.js +32 -18
- package/lib/vendor/blamejs/lib/mail-auth.js +236 -0
- package/lib/vendor/blamejs/lib/mail-crypto-smime.js +2 -6
- package/lib/vendor/blamejs/lib/mail-dkim.js +1 -0
- package/lib/vendor/blamejs/lib/mail-greylist.js +2 -6
- package/lib/vendor/blamejs/lib/mail-helo.js +2 -6
- package/lib/vendor/blamejs/lib/mail-journal.js +85 -64
- package/lib/vendor/blamejs/lib/mail-rbl.js +2 -6
- package/lib/vendor/blamejs/lib/mail-scan.js +2 -6
- package/lib/vendor/blamejs/lib/mail-server-jmap.js +117 -12
- package/lib/vendor/blamejs/lib/mail-server-mx.js +276 -7
- package/lib/vendor/blamejs/lib/mail-spam-score.js +2 -6
- package/lib/vendor/blamejs/lib/mail-store.js +293 -154
- package/lib/vendor/blamejs/lib/mail.js +8 -4
- package/lib/vendor/blamejs/lib/middleware/body-parser.js +71 -25
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +19 -8
- package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -1
- package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +17 -7
- package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +75 -51
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +102 -32
- package/lib/vendor/blamejs/lib/middleware/security-headers.js +21 -5
- package/lib/vendor/blamejs/lib/migrations.js +108 -66
- package/lib/vendor/blamejs/lib/network-heartbeat.js +7 -0
- package/lib/vendor/blamejs/lib/network-proxy.js +24 -1
- package/lib/vendor/blamejs/lib/nonce-store.js +31 -9
- package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +9 -4
- package/lib/vendor/blamejs/lib/object-store/azure-blob.js +57 -3
- package/lib/vendor/blamejs/lib/object-store/gcs.js +4 -1
- package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +5 -2
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +38 -6
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +9 -1
- package/lib/vendor/blamejs/lib/observability.js +124 -0
- package/lib/vendor/blamejs/lib/otel-export.js +12 -3
- package/lib/vendor/blamejs/lib/outbox.js +184 -83
- package/lib/vendor/blamejs/lib/parsers/safe-xml.js +47 -7
- package/lib/vendor/blamejs/lib/pqc-agent.js +44 -0
- package/lib/vendor/blamejs/lib/pubsub-cluster.js +42 -20
- package/lib/vendor/blamejs/lib/queue-local.js +225 -140
- package/lib/vendor/blamejs/lib/queue-redis.js +9 -1
- package/lib/vendor/blamejs/lib/queue-sqs.js +6 -0
- package/lib/vendor/blamejs/lib/queue.js +7 -0
- package/lib/vendor/blamejs/lib/redact.js +68 -11
- package/lib/vendor/blamejs/lib/redis-client.js +160 -31
- package/lib/vendor/blamejs/lib/request-helpers.js +7 -0
- package/lib/vendor/blamejs/lib/retention.js +117 -42
- package/lib/vendor/blamejs/lib/router.js +212 -5
- package/lib/vendor/blamejs/lib/safe-dns.js +29 -45
- package/lib/vendor/blamejs/lib/safe-ical.js +18 -33
- package/lib/vendor/blamejs/lib/safe-icap.js +27 -43
- package/lib/vendor/blamejs/lib/safe-sieve.js +21 -40
- package/lib/vendor/blamejs/lib/safe-sql.js +212 -3
- package/lib/vendor/blamejs/lib/safe-url.js +170 -3
- package/lib/vendor/blamejs/lib/safe-vcard.js +18 -33
- package/lib/vendor/blamejs/lib/scheduler.js +47 -12
- package/lib/vendor/blamejs/lib/seeders.js +122 -74
- package/lib/vendor/blamejs/lib/session-stores.js +42 -14
- package/lib/vendor/blamejs/lib/session.js +175 -77
- package/lib/vendor/blamejs/lib/sql.js +3842 -0
- package/lib/vendor/blamejs/lib/sse.js +26 -0
- package/lib/vendor/blamejs/lib/ssrf-guard.js +169 -4
- package/lib/vendor/blamejs/lib/static.js +177 -34
- package/lib/vendor/blamejs/lib/subject.js +96 -49
- package/lib/vendor/blamejs/lib/vault/index.js +3 -2
- package/lib/vendor/blamejs/lib/vault/passphrase-ops.js +3 -2
- package/lib/vendor/blamejs/lib/vault/rotate.js +168 -108
- package/lib/vendor/blamejs/lib/vault-aad.js +6 -0
- package/lib/vendor/blamejs/lib/vendor-data.js +2 -0
- package/lib/vendor/blamejs/lib/websocket.js +35 -5
- package/lib/vendor/blamejs/lib/worker-pool.js +11 -0
- package/lib/vendor/blamejs/package.json +2 -2
- package/lib/vendor/blamejs/release-notes/v0.14.x.json +1503 -0
- package/lib/vendor/blamejs/release-notes/v0.15.0.json +77 -0
- package/lib/vendor/blamejs/release-notes/v0.15.1.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.15.2.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.15.3.json +39 -0
- package/lib/vendor/blamejs/release-notes/v0.15.4.json +39 -0
- package/lib/vendor/blamejs/release-notes/v0.15.5.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.15.6.json +59 -0
- package/lib/vendor/blamejs/release-notes/v0.15.7.json +43 -0
- package/lib/vendor/blamejs/scripts/check-services.js +21 -0
- package/lib/vendor/blamejs/scripts/gen-migrating.js +67 -0
- package/lib/vendor/blamejs/scripts/release.js +398 -38
- package/lib/vendor/blamejs/test/00-primitives.js +168 -0
- package/lib/vendor/blamejs/test/10-state.js +140 -14
- package/lib/vendor/blamejs/test/20-db.js +65 -2
- package/lib/vendor/blamejs/test/helpers/db.js +9 -0
- package/lib/vendor/blamejs/test/helpers/drivers.js +27 -15
- package/lib/vendor/blamejs/test/helpers/services.js +21 -0
- package/lib/vendor/blamejs/test/integration/audit-actor-binding-pg.test.js +246 -0
- package/lib/vendor/blamejs/test/integration/audit-chain-external-db.test.js +517 -0
- package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +639 -0
- package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +832 -0
- package/lib/vendor/blamejs/test/integration/backup-restore-objectstore.test.js +453 -0
- package/lib/vendor/blamejs/test/integration/data-layer-cluster-mysql.test.js +649 -0
- package/lib/vendor/blamejs/test/integration/data-layer-cluster-pg.test.js +770 -0
- package/lib/vendor/blamejs/test/integration/data-layer-mysql-privacy.test.js +630 -0
- package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +610 -0
- package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +577 -0
- package/lib/vendor/blamejs/test/integration/data-layer-postgres.test.js +771 -0
- package/lib/vendor/blamejs/test/integration/db-layer-mysql.test.js +549 -0
- package/lib/vendor/blamejs/test/integration/db-layer-postgres.test.js +598 -0
- package/lib/vendor/blamejs/test/integration/distributed-scheduler-fencing-pg.test.js +602 -0
- package/lib/vendor/blamejs/test/integration/external-db-postgres.test.js +576 -0
- package/lib/vendor/blamejs/test/integration/framework-schema-mysql.test.js +353 -0
- package/lib/vendor/blamejs/test/integration/log-stream-cloudwatch.test.js +224 -0
- package/lib/vendor/blamejs/test/integration/mail-crypto-smime.test.js +142 -17
- package/lib/vendor/blamejs/test/integration/network-heartbeat.test.js +25 -10
- package/lib/vendor/blamejs/test/integration/object-store-azure.test.js +101 -0
- package/lib/vendor/blamejs/test/integration/object-store-gcs.test.js +239 -0
- package/lib/vendor/blamejs/test/integration/object-store-sigv4.test.js +35 -16
- package/lib/vendor/blamejs/test/integration/object-store-worm-lock.test.js +291 -0
- package/lib/vendor/blamejs/test/integration/pubsub.test.js +14 -0
- package/lib/vendor/blamejs/test/integration/queue-sqs.test.js +322 -0
- package/lib/vendor/blamejs/test/integration/redis-reconnect-toxiproxy.test.js +300 -0
- package/lib/vendor/blamejs/test/integration/sql-fts5-catalog-sqlite.test.js +154 -0
- package/lib/vendor/blamejs/test/integration/tls-classical-downgrade-audit.test.js +71 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-event-bus.test.js +175 -12
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-exclusive-temp.test.js +216 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-checkpoint-false-rollback.test.js +203 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-query-self-log.test.js +126 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-safeemit-redacts-secrets.test.js +196 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-signing-key-rotation.test.js +197 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-verifybundle-tamper.test.js +209 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/azure-blob-key-encoding.test.js +121 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-residency-posture.test.js +168 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-scheduletest-drill.test.js +318 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +233 -7
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +1196 -14
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance.test.js +229 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/credential-hash.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +24 -7
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-dual-read-migrate.test.js +165 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-per-row-key.test.js +350 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-unseal-rate-cap.test.js +27 -9
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-upgrade-dialect.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-interop-oracles.test.js +392 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csrf-protect.test.js +159 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-column-gate.test.js +180 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/db-query-cross-schema.test.js +5 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/db-query-sealed-field-in.test.js +101 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +128 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-schema-drift.test.js +38 -5
- package/lib/vendor/blamejs/test/layer-0-primitives/db-schema-reconcile-emittable.test.js +127 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-stream-and-payload-shape.test.js +267 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-worm.test.js +150 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/defineguard-default-gate-posture-caps.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-replaystore-required.test.js +46 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +218 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/erase-posture-vacuum.test.js +210 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db-hardening.test.js +4 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +48 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +237 -5
- package/lib/vendor/blamejs/test/layer-0-primitives/fetch-metadata.test.js +20 -9
- package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +193 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +90 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-stream.test.js +85 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +10 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +15 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/legal-hold.test.js +146 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +189 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-journal.test.js +3 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +123 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +207 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +74 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/oauth-callback.test.js +43 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/otel-export.test.js +133 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/otlp-attr-redaction.test.js +101 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/outbox-inflight-reaper.test.js +136 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/passkey-real-vectors.test.js +429 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +21 -11
- package/lib/vendor/blamejs/test/layer-0-primitives/queue-byo-db.test.js +40 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/redact-dlp.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/redis-client.test.js +113 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/retention-dryrun-no-vacuum.test.js +99 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/retention-floor.test.js +59 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-use-path-scope.test.js +255 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-url-canonicalize.test.js +362 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-xml.test.js +143 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/saml-subjectconfirmation-notonorafter.test.js +287 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scheduler-watchdog-stale-settle.test.js +71 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc-ecdsa-p1363.test.js +79 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +50 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +31 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +45 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +49 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +595 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sse-backpressure.test.js +91 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +69 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +194 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/websocket-extension-header.test.js +88 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/worker-pool-recycle-race.test.js +66 -0
- package/lib/vendor/blamejs/test/layer-1-state/api-key.test.js +84 -0
- package/lib/vendor/blamejs/test/layer-5-integration/external-db-residency.test.js +638 -0
- package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +21 -0
- package/lib/vendor/blamejs/test/smoke.js +79 -21
- package/package.json +2 -2
- package/lib/vendor/blamejs/release-notes/v0.14.0.json +0 -43
- package/lib/vendor/blamejs/release-notes/v0.14.1.json +0 -60
- package/lib/vendor/blamejs/release-notes/v0.14.10.json +0 -54
- package/lib/vendor/blamejs/release-notes/v0.14.11.json +0 -72
- package/lib/vendor/blamejs/release-notes/v0.14.12.json +0 -95
- package/lib/vendor/blamejs/release-notes/v0.14.13.json +0 -52
- package/lib/vendor/blamejs/release-notes/v0.14.14.json +0 -31
- package/lib/vendor/blamejs/release-notes/v0.14.16.json +0 -45
- package/lib/vendor/blamejs/release-notes/v0.14.17.json +0 -57
- package/lib/vendor/blamejs/release-notes/v0.14.18.json +0 -127
- package/lib/vendor/blamejs/release-notes/v0.14.19.json +0 -61
- package/lib/vendor/blamejs/release-notes/v0.14.2.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.14.20.json +0 -73
- package/lib/vendor/blamejs/release-notes/v0.14.21.json +0 -98
- package/lib/vendor/blamejs/release-notes/v0.14.22.json +0 -91
- package/lib/vendor/blamejs/release-notes/v0.14.3.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.14.4.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.14.5.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.14.6.json +0 -60
- package/lib/vendor/blamejs/release-notes/v0.14.7.json +0 -77
- package/lib/vendor/blamejs/release-notes/v0.14.8.json +0 -27
- package/lib/vendor/blamejs/release-notes/v0.14.9.json +0 -40
|
@@ -2090,6 +2090,239 @@ function authResultsEmit(opts) {
|
|
|
2090
2090
|
return "Authentication-Results: " + head + ";\r\n " + clauses.join(sep);
|
|
2091
2091
|
}
|
|
2092
2092
|
|
|
2093
|
+
// ---- Inbound message-authentication pipeline (RFC 7489 §6.6) ----
|
|
2094
|
+
//
|
|
2095
|
+
// One call runs the receiver-side authentication set on a message as it
|
|
2096
|
+
// arrives: SPF (RFC 7208) on the envelope identity, DKIM (RFC 6376) on
|
|
2097
|
+
// the message bytes, DMARC (RFC 7489 / DMARCbis) policy + alignment on
|
|
2098
|
+
// the From-header domain, and — when an authserv-id is supplied — the
|
|
2099
|
+
// RFC 8601 Authentication-Results header the receiver prepends before
|
|
2100
|
+
// delivery. b.mail.server.mx composes this at DATA time via its
|
|
2101
|
+
// guardEnvelope opt; operators running their own listeners (or doing
|
|
2102
|
+
// post-delivery verification in an agent) call it directly:
|
|
2103
|
+
//
|
|
2104
|
+
// var v = await b.mail.inbound.verify({
|
|
2105
|
+
// ip: "203.0.113.5",
|
|
2106
|
+
// helo: "mail.sender.example",
|
|
2107
|
+
// mailFrom: "bounce@sender.example",
|
|
2108
|
+
// message: rfc5322Bytes, // string or Buffer
|
|
2109
|
+
// authservId: "mx.example.com",
|
|
2110
|
+
// });
|
|
2111
|
+
// // → { spf, dkim, from, dmarc, authResults }
|
|
2112
|
+
// if (v.dmarc.recommendedAction === "reject") { /* refuse 550 5.7.1 */ }
|
|
2113
|
+
//
|
|
2114
|
+
// From-header discipline (RFC 7489 §6.6.1): DMARC evaluates exactly one
|
|
2115
|
+
// author domain. A message with zero From fields, several From fields,
|
|
2116
|
+
// or several author addresses in one field is the header-duplication
|
|
2117
|
+
// spoofing shape — an attacker pairs an aligned-but-hidden From with the
|
|
2118
|
+
// one the mail client displays (the CVE-2024-7208 / CVE-2024-7209
|
|
2119
|
+
// hosted-relay spoofing class rides on exactly this ambiguity). Those
|
|
2120
|
+
// messages return `dmarc.result: "permerror"` with
|
|
2121
|
+
// `recommendedAction: "reject"` instead of picking one of the Froms.
|
|
2122
|
+
|
|
2123
|
+
// RFC 5322 §2.1 — the header block ends at the first empty line. SMTP
|
|
2124
|
+
// wire format is CRLF; bare-LF input is accepted defensively for
|
|
2125
|
+
// operator-fed strings that lost CRs in their own tooling.
|
|
2126
|
+
function _splitHeaderBlock(message) {
|
|
2127
|
+
var idx = message.indexOf("\r\n\r\n");
|
|
2128
|
+
if (idx !== -1) return { headers: message.slice(0, idx), body: message.slice(idx + 4) };
|
|
2129
|
+
idx = message.indexOf("\n\n");
|
|
2130
|
+
if (idx !== -1) return { headers: message.slice(0, idx), body: message.slice(idx + 2) };
|
|
2131
|
+
return { headers: message, body: "" };
|
|
2132
|
+
}
|
|
2133
|
+
|
|
2134
|
+
// Quote-aware single pass over a From field value (RFC 5322 phrase
|
|
2135
|
+
// quoting): counts angle-addr pairs that contain an `@` (a `<` inside
|
|
2136
|
+
// a quoted-string is display-name text — `"John <Jr.> Smith" <u@d>`
|
|
2137
|
+
// is one author, not two) and top-level commas (address-list
|
|
2138
|
+
// separators; a comma inside a quoted display-name like
|
|
2139
|
+
// `"Doe, John" <j@d>` does not count). Records the content of the
|
|
2140
|
+
// last @-bearing angle-addr for extraction.
|
|
2141
|
+
function _countFromAuthors(value) {
|
|
2142
|
+
var inQuote = false, inAngle = false, escaped = false;
|
|
2143
|
+
var angleAddrs = 0, topCommas = 0, angleStart = -1;
|
|
2144
|
+
var lastAddr = null;
|
|
2145
|
+
for (var i = 0; i < value.length; i += 1) {
|
|
2146
|
+
var ch = value.charAt(i);
|
|
2147
|
+
if (escaped) { escaped = false; continue; }
|
|
2148
|
+
if (ch === "\\") { escaped = true; continue; }
|
|
2149
|
+
if (ch === "\"" && !inAngle) { inQuote = !inQuote; continue; }
|
|
2150
|
+
if (inQuote) continue;
|
|
2151
|
+
if (ch === "<" && !inAngle) { inAngle = true; angleStart = i; continue; }
|
|
2152
|
+
if (ch === ">" && inAngle) {
|
|
2153
|
+
inAngle = false;
|
|
2154
|
+
var inner = value.slice(angleStart + 1, i).trim();
|
|
2155
|
+
if (inner.indexOf("@") !== -1) { angleAddrs += 1; lastAddr = inner; }
|
|
2156
|
+
continue;
|
|
2157
|
+
}
|
|
2158
|
+
if (ch === "," && !inAngle) topCommas += 1;
|
|
2159
|
+
}
|
|
2160
|
+
return { angleAddrs: angleAddrs, topCommas: topCommas, lastAddr: lastAddr };
|
|
2161
|
+
}
|
|
2162
|
+
|
|
2163
|
+
// Unfold (RFC 5322 §2.2.3), collect every From: field, and extract the
|
|
2164
|
+
// author address. `count` is the number of From fields, widened by
|
|
2165
|
+
// multiple-author detection inside a single field: several @-bearing
|
|
2166
|
+
// angle-addrs, or a bare address-list separated by top-level commas
|
|
2167
|
+
// (RFC 7489 §6.6.1 — a multi-author From is the header-duplication
|
|
2168
|
+
// spoofing shape and must not have "one" author picked from it).
|
|
2169
|
+
function _extractFromHeaders(headerBlock) {
|
|
2170
|
+
var unfolded = headerBlock.replace(/\r?\n[ \t]+/g, " ");
|
|
2171
|
+
var lines = unfolded.split(/\r?\n/);
|
|
2172
|
+
var fromValues = [];
|
|
2173
|
+
for (var i = 0; i < lines.length; i += 1) {
|
|
2174
|
+
var m = /^From[ \t]*:(.*)$/i.exec(lines[i]);
|
|
2175
|
+
if (m) fromValues.push(m[1].trim());
|
|
2176
|
+
}
|
|
2177
|
+
if (fromValues.length === 0) return { count: 0, address: null, domain: null };
|
|
2178
|
+
var count = fromValues.length;
|
|
2179
|
+
var value = fromValues[0];
|
|
2180
|
+
var authors = _countFromAuthors(value);
|
|
2181
|
+
if (count === 1) {
|
|
2182
|
+
if (authors.angleAddrs > 1) count = authors.angleAddrs;
|
|
2183
|
+
else if (authors.topCommas > 0) count = authors.topCommas + 1;
|
|
2184
|
+
}
|
|
2185
|
+
var address;
|
|
2186
|
+
if (authors.angleAddrs >= 1) {
|
|
2187
|
+
// count > 1 is refused by the caller before the address is used;
|
|
2188
|
+
// for the single-author case this is that author's angle-addr.
|
|
2189
|
+
address = authors.lastAddr;
|
|
2190
|
+
} else {
|
|
2191
|
+
// Bare addr-spec form. An RFC 5322 addr-spec cannot contain
|
|
2192
|
+
// whitespace or commas — their presence means an address list or
|
|
2193
|
+
// display-name soup; extracting "the" domain from it would pick
|
|
2194
|
+
// one of several authors (the §6.6.1 forbidden move), so the
|
|
2195
|
+
// field is treated as unparsable instead.
|
|
2196
|
+
address = value.trim();
|
|
2197
|
+
if (/[\s,]/.test(address)) address = null;
|
|
2198
|
+
}
|
|
2199
|
+
var at = address ? address.lastIndexOf("@") : -1;
|
|
2200
|
+
var domain = (at > 0 && address && at < address.length - 1)
|
|
2201
|
+
? address.slice(at + 1).toLowerCase()
|
|
2202
|
+
: null;
|
|
2203
|
+
return { count: count, address: address || null, domain: domain };
|
|
2204
|
+
}
|
|
2205
|
+
|
|
2206
|
+
async function inboundVerify(opts) {
|
|
2207
|
+
validateOpts.requireObject(opts, "inbound.verify", MailAuthError, "mail-auth/inbound-bad-input");
|
|
2208
|
+
validateOpts(opts, ["ip", "helo", "mailFrom", "message", "dnsLookup", "domainExists",
|
|
2209
|
+
"maxSignatures", "clockSkewMs", "minRsaBits", "authservId"],
|
|
2210
|
+
"mail.inbound.verify");
|
|
2211
|
+
validateOpts.requireNonEmptyString(opts.ip, "inbound.verify: ip",
|
|
2212
|
+
MailAuthError, "mail-auth/inbound-bad-ip");
|
|
2213
|
+
if (opts.authservId !== undefined && opts.authservId !== null) {
|
|
2214
|
+
validateOpts.requireNonEmptyString(opts.authservId, "inbound.verify: authservId",
|
|
2215
|
+
MailAuthError, "mail-auth/inbound-bad-authserv-id");
|
|
2216
|
+
}
|
|
2217
|
+
var message = opts.message;
|
|
2218
|
+
if (Buffer.isBuffer(message)) {
|
|
2219
|
+
// DKIM canonicalization re-encodes the string form as UTF-8
|
|
2220
|
+
// (lib/mail-dkim.js hashes Buffer.from(canonicalized, "utf8")), so
|
|
2221
|
+
// the byte→string decode must be utf8 for valid-UTF-8 content to
|
|
2222
|
+
// round-trip exactly. Non-UTF-8 8-bit content cannot survive any
|
|
2223
|
+
// decode + utf8 re-encode; such messages verify as DKIM fail and
|
|
2224
|
+
// DMARC falls back to the SPF identity (RFC 7489 §4.2 — one
|
|
2225
|
+
// aligned authenticator is sufficient to pass).
|
|
2226
|
+
message = message.toString("utf8");
|
|
2227
|
+
}
|
|
2228
|
+
if (typeof message !== "string" || message.length === 0) {
|
|
2229
|
+
throw new MailAuthError("mail-auth/inbound-bad-message",
|
|
2230
|
+
"inbound.verify: message must be a non-empty string or Buffer (the full RFC 5322 message)");
|
|
2231
|
+
}
|
|
2232
|
+
var mailFrom = (typeof opts.mailFrom === "string" && opts.mailFrom.length > 0) ? opts.mailFrom : null;
|
|
2233
|
+
var helo = (typeof opts.helo === "string" && opts.helo.length > 0) ? opts.helo : null;
|
|
2234
|
+
|
|
2235
|
+
// SPF — envelope identity: MAIL FROM, falling back to HELO for the
|
|
2236
|
+
// null reverse-path (RFC 7208 §2.4). DNS failures surface as the
|
|
2237
|
+
// RFC's temperror result, not as throws.
|
|
2238
|
+
var spf;
|
|
2239
|
+
if (mailFrom || helo) {
|
|
2240
|
+
spf = await spfVerify({
|
|
2241
|
+
ip: opts.ip,
|
|
2242
|
+
mailFrom: mailFrom || undefined,
|
|
2243
|
+
helo: helo || undefined,
|
|
2244
|
+
dnsLookup: opts.dnsLookup,
|
|
2245
|
+
});
|
|
2246
|
+
} else {
|
|
2247
|
+
spf = { result: "none", domain: null,
|
|
2248
|
+
explanation: "no MAIL FROM or HELO identity supplied", lookupCount: 0 };
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
// DKIM — every signature on the message (bounded by maxSignatures;
|
|
2252
|
+
// a signature-less message verifies as a single `none` entry).
|
|
2253
|
+
var dkimVerifyOpts = { dnsLookup: opts.dnsLookup };
|
|
2254
|
+
if (opts.clockSkewMs !== undefined) dkimVerifyOpts.clockSkewMs = opts.clockSkewMs;
|
|
2255
|
+
if (opts.maxSignatures !== undefined) dkimVerifyOpts.maxSignatures = opts.maxSignatures;
|
|
2256
|
+
if (opts.minRsaBits !== undefined) dkimVerifyOpts.minRsaBits = opts.minRsaBits;
|
|
2257
|
+
var dkimResults = await dkim.verify(message, dkimVerifyOpts);
|
|
2258
|
+
|
|
2259
|
+
// From header + DMARC policy/alignment.
|
|
2260
|
+
var from = _extractFromHeaders(_splitHeaderBlock(message).headers);
|
|
2261
|
+
var dmarc;
|
|
2262
|
+
if (from.count === 1 && from.address && from.domain) {
|
|
2263
|
+
dmarc = await dmarcEvaluate({
|
|
2264
|
+
from: from.address,
|
|
2265
|
+
spf: spf,
|
|
2266
|
+
dkim: dkimResults,
|
|
2267
|
+
dnsLookup: opts.dnsLookup,
|
|
2268
|
+
domainExists: opts.domainExists,
|
|
2269
|
+
});
|
|
2270
|
+
// RFC 7489 §6.6.2 — a fail verdict computed while an authenticator
|
|
2271
|
+
// returned temperror is not final: the very lookup that failed
|
|
2272
|
+
// transiently could have produced the aligned pass. Surface
|
|
2273
|
+
// temperror so the caller defers (the sender retries) instead of
|
|
2274
|
+
// permanently refusing a legitimate sender during a DNS blip. A
|
|
2275
|
+
// pass verdict stands — one aligned authenticator is sufficient
|
|
2276
|
+
// regardless of the other's transient failure.
|
|
2277
|
+
if (dmarc.result === "fail" &&
|
|
2278
|
+
(spf.result === "temperror" ||
|
|
2279
|
+
dkimResults.some(function (d) { return d.result === "temperror"; }))) {
|
|
2280
|
+
dmarc.result = "temperror";
|
|
2281
|
+
dmarc.recommendedAction = null;
|
|
2282
|
+
dmarc.explanation = (dmarc.explanation ? dmarc.explanation + "; " : "") +
|
|
2283
|
+
"fail computed while an authenticator returned temperror — transient, retry";
|
|
2284
|
+
}
|
|
2285
|
+
} else {
|
|
2286
|
+
dmarc = {
|
|
2287
|
+
result: "permerror",
|
|
2288
|
+
recommendedAction: "reject",
|
|
2289
|
+
policy: null,
|
|
2290
|
+
alignment: { spf: false, dkim: false },
|
|
2291
|
+
orgDomain: null,
|
|
2292
|
+
explanation: from.count === 0
|
|
2293
|
+
? "message has no From header (RFC 7489 §6.6.1)"
|
|
2294
|
+
: (from.count > 1
|
|
2295
|
+
? "message carries " + from.count + " From authors (RFC 7489 §6.6.1 — multi-From spoofing shape)"
|
|
2296
|
+
: "From header has no parsable author domain"),
|
|
2297
|
+
};
|
|
2298
|
+
}
|
|
2299
|
+
|
|
2300
|
+
// RFC 8601 Authentication-Results — only when the caller identifies
|
|
2301
|
+
// itself (the authserv-id is the receiver's own name; there is no
|
|
2302
|
+
// sensible default the framework could invent).
|
|
2303
|
+
var authResults = null;
|
|
2304
|
+
if (opts.authservId) {
|
|
2305
|
+
var arResults = [];
|
|
2306
|
+
var spfEntry = { method: "spf", result: spf.result };
|
|
2307
|
+
if (mailFrom) spfEntry.smtpMailfrom = mailFrom;
|
|
2308
|
+
else if (helo) spfEntry.smtpHelo = helo;
|
|
2309
|
+
arResults.push(spfEntry);
|
|
2310
|
+
for (var di = 0; di < dkimResults.length; di += 1) {
|
|
2311
|
+
var d = dkimResults[di];
|
|
2312
|
+
var dkimEntry = { method: "dkim", result: d.result };
|
|
2313
|
+
if (typeof d.d === "string" && d.d.length > 0) dkimEntry.domain = d.d;
|
|
2314
|
+
if (typeof d.s === "string" && d.s.length > 0) dkimEntry.selector = d.s;
|
|
2315
|
+
arResults.push(dkimEntry);
|
|
2316
|
+
}
|
|
2317
|
+
var dmarcEntry = { method: "dmarc", result: dmarc.result };
|
|
2318
|
+
if (from.address) dmarcEntry.from = from.address;
|
|
2319
|
+
arResults.push(dmarcEntry);
|
|
2320
|
+
authResults = authResultsEmit({ authservId: opts.authservId, results: arResults });
|
|
2321
|
+
}
|
|
2322
|
+
|
|
2323
|
+
return { spf: spf, dkim: dkimResults, from: from, dmarc: dmarc, authResults: authResults };
|
|
2324
|
+
}
|
|
2325
|
+
|
|
2093
2326
|
// ---- DMARC aggregate (RUA) report parser (RFC 7489 §7.2 / draft-ietf-dmarc-aggregate-reporting) ----
|
|
2094
2327
|
//
|
|
2095
2328
|
// MTAs that publish a DMARC `rua=` policy receive aggregate reports
|
|
@@ -2971,6 +3204,9 @@ module.exports = {
|
|
|
2971
3204
|
authResults: Object.freeze({
|
|
2972
3205
|
emit: authResultsEmit,
|
|
2973
3206
|
}),
|
|
3207
|
+
inbound: Object.freeze({
|
|
3208
|
+
verify: inboundVerify,
|
|
3209
|
+
}),
|
|
2974
3210
|
MailAuthError: MailAuthError,
|
|
2975
3211
|
SPF_DNS_LOOKUP_LIMIT: SPF_DNS_LOOKUP_LIMIT,
|
|
2976
3212
|
};
|
|
@@ -102,6 +102,7 @@ var cms = require("./cms-codec");
|
|
|
102
102
|
var asn1 = require("./asn1-der");
|
|
103
103
|
var pqcSoftware = require("./pqc-software");
|
|
104
104
|
var bCrypto = require("./crypto");
|
|
105
|
+
var gateContract = require("./gate-contract");
|
|
105
106
|
var { defineClass } = require("./framework-error");
|
|
106
107
|
|
|
107
108
|
var MailCryptoError = defineClass("MailCryptoError", { alwaysPermanent: true });
|
|
@@ -121,12 +122,7 @@ var REFUSED_HASHES = ["md5", "sha1"];
|
|
|
121
122
|
// encryption is added, it composes the same set with the @intro EFAIL
|
|
122
123
|
// defenses applied.
|
|
123
124
|
var PROFILES = ["strict", "balanced", "permissive"];
|
|
124
|
-
var COMPLIANCE_POSTURES =
|
|
125
|
-
hipaa: "strict",
|
|
126
|
-
"pci-dss": "strict",
|
|
127
|
-
gdpr: "strict",
|
|
128
|
-
soc2: "strict",
|
|
129
|
-
};
|
|
125
|
+
var COMPLIANCE_POSTURES = gateContract.ALL_STRICT_POSTURES;
|
|
130
126
|
|
|
131
127
|
// ---- Public surface (v0.10.16 lights up — composes b.cms) ----
|
|
132
128
|
|
|
@@ -1242,6 +1242,7 @@ module.exports = {
|
|
|
1242
1242
|
RSA_MIN_BITS: RSA_MIN_BITS,
|
|
1243
1243
|
RSA_LEGACY_MIN_BITS: RSA_LEGACY_MIN_BITS,
|
|
1244
1244
|
DKIM_MAX_SIGNATURES_PER_MESSAGE: DKIM_MAX_SIGNATURES_PER_MESSAGE,
|
|
1245
|
+
DKIM_MAX_SIGNATURES_PER_MESSAGE_CEILING: DKIM_MAX_SIGNATURES_PER_MESSAGE_CEILING,
|
|
1245
1246
|
DKIM_CLOCK_SKEW_MS_MAX: DKIM_CLOCK_SKEW_MS_MAX,
|
|
1246
1247
|
_canonHeaderRelaxedForTest: _canonHeaderRelaxed,
|
|
1247
1248
|
_canonBodyRelaxedForTest: _canonBodyRelaxed,
|
|
@@ -102,6 +102,7 @@ var { defineClass } = require("./framework-error");
|
|
|
102
102
|
var bCrypto = require("./crypto");
|
|
103
103
|
var lazyRequire = require("./lazy-require");
|
|
104
104
|
var ipUtils = require("./ip-utils");
|
|
105
|
+
var gateContract = require("./gate-contract");
|
|
105
106
|
|
|
106
107
|
var audit = lazyRequire(function () { return require("./audit"); });
|
|
107
108
|
|
|
@@ -126,12 +127,7 @@ var PROFILES = Object.freeze({
|
|
|
126
127
|
permissive: { minDelayMs: C.TIME.seconds(30), whitelistTtlMs: C.TIME.days(30), ipv4Prefix: 32, ipv6Prefix: 128 }, // RFC 6647 §4.4 prefixes
|
|
127
128
|
});
|
|
128
129
|
|
|
129
|
-
var COMPLIANCE_POSTURES =
|
|
130
|
-
hipaa: "strict",
|
|
131
|
-
"pci-dss": "strict",
|
|
132
|
-
gdpr: "strict",
|
|
133
|
-
soc2: "strict",
|
|
134
|
-
});
|
|
130
|
+
var COMPLIANCE_POSTURES = gateContract.ALL_STRICT_POSTURES;
|
|
135
131
|
|
|
136
132
|
var IPV4_RE = /^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}$/; // allow:regex-no-length-cap — anchored + per-octet repeat-cap
|
|
137
133
|
var IPV6_RE = /^[0-9a-fA-F:]+$/; // allow:regex-no-length-cap — length-checked separately
|
|
@@ -104,6 +104,7 @@
|
|
|
104
104
|
var { defineClass } = require("./framework-error");
|
|
105
105
|
var lazyRequire = require("./lazy-require");
|
|
106
106
|
var ipUtils = require("./ip-utils");
|
|
107
|
+
var gateContract = require("./gate-contract");
|
|
107
108
|
|
|
108
109
|
var audit = lazyRequire(function () { return require("./audit"); });
|
|
109
110
|
|
|
@@ -145,12 +146,7 @@ var PROFILES = Object.freeze({
|
|
|
145
146
|
},
|
|
146
147
|
});
|
|
147
148
|
|
|
148
|
-
var COMPLIANCE_POSTURES =
|
|
149
|
-
hipaa: "strict",
|
|
150
|
-
"pci-dss": "strict",
|
|
151
|
-
gdpr: "strict",
|
|
152
|
-
soc2: "strict",
|
|
153
|
-
});
|
|
149
|
+
var COMPLIANCE_POSTURES = gateContract.ALL_STRICT_POSTURES;
|
|
154
150
|
|
|
155
151
|
// Operator-extensible default list of generic-rDNS patterns the
|
|
156
152
|
// framework ships. Each is a RegExp — case-insensitive — designed
|
|
@@ -72,7 +72,7 @@ var C = require("./constants");
|
|
|
72
72
|
var validateOpts = require("./validate-opts");
|
|
73
73
|
var numericBounds = require("./numeric-bounds");
|
|
74
74
|
var safeJson = require("./safe-json");
|
|
75
|
-
var
|
|
75
|
+
var sql = require("./sql");
|
|
76
76
|
var { defineClass } = require("./framework-error");
|
|
77
77
|
var lazyRequire = require("./lazy-require");
|
|
78
78
|
|
|
@@ -213,33 +213,40 @@ function create(opts) {
|
|
|
213
213
|
// / `messageId` / `archivedAt` / `sizeBytes` / `regimes` / `legalHold`
|
|
214
214
|
// queryable without unsealing the payload. The payload (headers +
|
|
215
215
|
// body) lives in the WORM bucket sealed via b.cryptoField.sealRow.
|
|
216
|
-
//
|
|
217
|
-
//
|
|
218
|
-
//
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
// `
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
var
|
|
225
|
-
var
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
216
|
+
//
|
|
217
|
+
// The journal table is an operator-namespaced local table (NOT a
|
|
218
|
+
// framework `_blamejs_` table that clusterStorage rewrites), so every
|
|
219
|
+
// statement composes b.sql with quoteName:true — b.sql validates the
|
|
220
|
+
// identifier through b.safeSql and emits the dialect-quoted form,
|
|
221
|
+
// running against opts.db (the local sqlite handle) directly. `_t()`
|
|
222
|
+
// opens each verb builder pre-bound to this table so the name resolves
|
|
223
|
+
// in exactly one place.
|
|
224
|
+
var rawTable = "_mail_journal_" + namespace.replace(/-/g, "_");
|
|
225
|
+
var TBL_OPTS = { dialect: "sqlite", quoteName: true };
|
|
226
|
+
function _t(verb) { return sql[verb](rawTable, TBL_OPTS); }
|
|
227
|
+
|
|
228
|
+
// Bootstrap DDL — CREATE TABLE + the archived_at / message_id indexes.
|
|
229
|
+
// runSql is a multi-statement helper, so the three b.sql DDL strings
|
|
230
|
+
// join with `;` into one call (each b.sql build is a single validated
|
|
231
|
+
// statement; the join is the multi-statement boundary runSql expects).
|
|
232
|
+
var ddl = [
|
|
233
|
+
sql.createTable(rawTable, [
|
|
234
|
+
{ name: "journal_id", type: "text", primaryKey: true },
|
|
235
|
+
{ name: "direction", type: "text", notNull: true },
|
|
236
|
+
{ name: "actor_id", type: "text" },
|
|
237
|
+
{ name: "message_id", type: "text" },
|
|
238
|
+
{ name: "archived_at", type: "int", notNull: true },
|
|
239
|
+
{ name: "size_bytes", type: "int", notNull: true },
|
|
240
|
+
{ name: "regimes", type: "text", notNull: true },
|
|
241
|
+
{ name: "floor_until", type: "int", notNull: true },
|
|
242
|
+
{ name: "legal_hold", type: "int", notNull: true, default: 0 },
|
|
243
|
+
{ name: "storage_key", type: "text", notNull: true, unique: true },
|
|
244
|
+
{ name: "sealed_payload", type: "blob", notNull: true },
|
|
245
|
+
], TBL_OPTS).sql,
|
|
246
|
+
sql.createIndex(rawTable + "_archived_at_idx", rawTable, ["archived_at"], TBL_OPTS).sql,
|
|
247
|
+
sql.createIndex(rawTable + "_message_id_idx", rawTable, ["message_id"], TBL_OPTS).sql,
|
|
248
|
+
].join(";");
|
|
249
|
+
opts.db.runSql(ddl);
|
|
243
250
|
|
|
244
251
|
async function record(req) {
|
|
245
252
|
validateOpts.requireObject(req, "mail.journal.record",
|
|
@@ -292,13 +299,24 @@ function create(opts) {
|
|
|
292
299
|
|
|
293
300
|
var regimesJson = JSON.stringify(opts.regimes);
|
|
294
301
|
var floorUntil = archivedAt + floorMs;
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
+
// legal_hold is omitted from the INSERT so the column's
|
|
303
|
+
// `NOT NULL DEFAULT 0` applies (the prior inline `0` SQL literal) — b.sql
|
|
304
|
+
// binds every value it is given, so leaving the column out keeps the row
|
|
305
|
+
// unsealed-at-rest default without binding a redundant constant. b.sql
|
|
306
|
+
// quotes every column + binds every remaining value as a placeholder.
|
|
307
|
+
var insBuilt = _t("insert").values({
|
|
308
|
+
journal_id: journalId,
|
|
309
|
+
direction: req.direction,
|
|
310
|
+
actor_id: req.actorId,
|
|
311
|
+
message_id: req.messageId,
|
|
312
|
+
archived_at: archivedAt,
|
|
313
|
+
size_bytes: sizeBytes,
|
|
314
|
+
regimes: regimesJson,
|
|
315
|
+
floor_until: floorUntil,
|
|
316
|
+
storage_key: storageKey,
|
|
317
|
+
sealed_payload: sealedBlob,
|
|
318
|
+
}).toSql();
|
|
319
|
+
opts.db.runSql(insBuilt.sql, insBuilt.params);
|
|
302
320
|
|
|
303
321
|
_emit("mail.journal.record", "success", {
|
|
304
322
|
journalId: journalId,
|
|
@@ -317,11 +335,12 @@ function create(opts) {
|
|
|
317
335
|
throw new MailJournalError("mail-journal/bad-id",
|
|
318
336
|
"mail.journal.getById: journalId must be a non-empty string");
|
|
319
337
|
}
|
|
320
|
-
var
|
|
321
|
-
"
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
338
|
+
var gbBuilt = _t("select")
|
|
339
|
+
.columns(["direction", "message_id", "archived_at", "size_bytes", "regimes",
|
|
340
|
+
"floor_until", "legal_hold", "storage_key", "sealed_payload"])
|
|
341
|
+
.where("journal_id", journalId)
|
|
342
|
+
.toSql();
|
|
343
|
+
var rows = opts.db.runSql(gbBuilt.sql, gbBuilt.params);
|
|
325
344
|
if (!rows || rows.length === 0) return null;
|
|
326
345
|
var r = rows[0];
|
|
327
346
|
var unsealed = safeJson.parse(opts.vault.unseal(r.sealed_payload));
|
|
@@ -344,30 +363,27 @@ function create(opts) {
|
|
|
344
363
|
|
|
345
364
|
function list(filter) {
|
|
346
365
|
filter = filter || {};
|
|
366
|
+
var limit = numericBounds.isPositiveFiniteInt(filter.limit) ? Math.min(filter.limit, 1000) : 100; // list page cap
|
|
367
|
+
// Each filter term is an optional .where() leaf (AND-composed); b.sql
|
|
368
|
+
// quotes the columns + binds the values. A diagnostic clause list is
|
|
369
|
+
// kept for the audit metadata (the prior `filter: clauses` field).
|
|
347
370
|
var clauses = [];
|
|
348
|
-
var
|
|
371
|
+
var qb = _t("select").columns(["journal_id", "direction", "actor_id", "message_id",
|
|
372
|
+
"archived_at", "size_bytes", "regimes", "floor_until", "legal_hold", "storage_key"]);
|
|
349
373
|
if (filter.direction && ALLOWED_DIRECTIONS[filter.direction]) {
|
|
350
|
-
clauses.push("direction = ?");
|
|
351
|
-
args.push(filter.direction);
|
|
374
|
+
qb.where("direction", filter.direction); clauses.push("direction = ?");
|
|
352
375
|
}
|
|
353
376
|
if (typeof filter.since === "number" && numericBounds.isPositiveFiniteInt(filter.since)) {
|
|
354
|
-
clauses.push("archived_at >= ?");
|
|
355
|
-
args.push(filter.since);
|
|
377
|
+
qb.whereOp("archived_at", ">=", filter.since); clauses.push("archived_at >= ?");
|
|
356
378
|
}
|
|
357
379
|
if (typeof filter.until === "number" && numericBounds.isPositiveFiniteInt(filter.until)) {
|
|
358
|
-
clauses.push("archived_at < ?");
|
|
359
|
-
args.push(filter.until);
|
|
380
|
+
qb.whereOp("archived_at", "<", filter.until); clauses.push("archived_at < ?");
|
|
360
381
|
}
|
|
361
382
|
if (filter.actorId && typeof filter.actorId === "string") {
|
|
362
|
-
clauses.push("actor_id = ?");
|
|
363
|
-
args.push(filter.actorId);
|
|
383
|
+
qb.where("actor_id", filter.actorId); clauses.push("actor_id = ?");
|
|
364
384
|
}
|
|
365
|
-
var
|
|
366
|
-
var
|
|
367
|
-
var sql = "SELECT journal_id, direction, actor_id, message_id, archived_at, " +
|
|
368
|
-
"size_bytes, regimes, floor_until, legal_hold, storage_key FROM " +
|
|
369
|
-
qTable + where + " ORDER BY archived_at DESC LIMIT " + limit + ";";
|
|
370
|
-
var rows = opts.db.runSql(sql, args);
|
|
385
|
+
var listBuilt = qb.orderBy("archived_at", "desc").limit(limit).toSql();
|
|
386
|
+
var rows = opts.db.runSql(listBuilt.sql, listBuilt.params);
|
|
371
387
|
_emit("mail.journal.list", "success", { count: rows ? rows.length : 0, filter: clauses });
|
|
372
388
|
return (rows || []).map(function (r) {
|
|
373
389
|
return {
|
|
@@ -387,11 +403,15 @@ function create(opts) {
|
|
|
387
403
|
|
|
388
404
|
function expireSurface(now) {
|
|
389
405
|
if (now === undefined) now = Date.now();
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
406
|
+
// legal_hold = 0 binds as a value (the prior inline `0` literal).
|
|
407
|
+
var esBuilt = _t("select")
|
|
408
|
+
.columns(["journal_id", "archived_at", "floor_until", "message_id", "regimes"])
|
|
409
|
+
.whereOp("floor_until", "<", now)
|
|
410
|
+
.where("legal_hold", 0)
|
|
411
|
+
.orderBy("archived_at", "asc")
|
|
412
|
+
.limit(1000) // expiry-surface cap
|
|
413
|
+
.toSql();
|
|
414
|
+
var rows = opts.db.runSql(esBuilt.sql, esBuilt.params);
|
|
395
415
|
_emit("mail.journal.expire_surface", "success", { count: rows ? rows.length : 0, now: now });
|
|
396
416
|
return (rows || []).map(function (r) {
|
|
397
417
|
return {
|
|
@@ -409,10 +429,11 @@ function create(opts) {
|
|
|
409
429
|
throw new MailJournalError("mail-journal/bad-id",
|
|
410
430
|
"mail.journal.setLegalHold: journalId required");
|
|
411
431
|
}
|
|
412
|
-
|
|
413
|
-
"
|
|
414
|
-
|
|
415
|
-
|
|
432
|
+
var lhBuilt = _t("update")
|
|
433
|
+
.set("legal_hold", onHold ? 1 : 0)
|
|
434
|
+
.where("journal_id", journalId)
|
|
435
|
+
.toSql();
|
|
436
|
+
opts.db.runSql(lhBuilt.sql, lhBuilt.params);
|
|
416
437
|
_emit("mail.journal.legal_hold_change", "success", { journalId: journalId, onHold: !!onHold });
|
|
417
438
|
}
|
|
418
439
|
|
|
@@ -86,6 +86,7 @@ var C = require("./constants");
|
|
|
86
86
|
var { defineClass } = require("./framework-error");
|
|
87
87
|
var lazyRequire = require("./lazy-require");
|
|
88
88
|
var ipUtils = require("./ip-utils");
|
|
89
|
+
var gateContract = require("./gate-contract");
|
|
89
90
|
|
|
90
91
|
var audit = lazyRequire(function () { return require("./audit"); });
|
|
91
92
|
|
|
@@ -105,12 +106,7 @@ var PROFILES = Object.freeze({
|
|
|
105
106
|
permissive: { maxConcurrent: 32, perListTimeoutMs: C.TIME.seconds(20), maxListsPerQuery: 64 }, // list-count cap
|
|
106
107
|
});
|
|
107
108
|
|
|
108
|
-
var COMPLIANCE_POSTURES =
|
|
109
|
-
hipaa: "strict",
|
|
110
|
-
"pci-dss": "strict",
|
|
111
|
-
gdpr: "strict",
|
|
112
|
-
soc2: "strict",
|
|
113
|
-
});
|
|
109
|
+
var COMPLIANCE_POSTURES = gateContract.ALL_STRICT_POSTURES;
|
|
114
110
|
|
|
115
111
|
/**
|
|
116
112
|
* @primitive b.mail.rbl.create
|
|
@@ -85,6 +85,7 @@ var lazyRequire = require("./lazy-require");
|
|
|
85
85
|
var validateOpts = require("./validate-opts");
|
|
86
86
|
var numericBounds = require("./numeric-bounds");
|
|
87
87
|
var safeIcap = require("./safe-icap");
|
|
88
|
+
var gateContract = require("./gate-contract");
|
|
88
89
|
|
|
89
90
|
var audit = lazyRequire(function () { return require("./audit"); });
|
|
90
91
|
var guardArchive = lazyRequire(function () { return require("./guard-archive"); });
|
|
@@ -107,12 +108,7 @@ var PROFILES = Object.freeze({
|
|
|
107
108
|
permissive: { timeoutMs: C.TIME.seconds(120), maxMessageBytes: C.BYTES.mib(150), maxResponseBytes: C.BYTES.mib(300) }, // operator-facing default mailbox cap
|
|
108
109
|
});
|
|
109
110
|
|
|
110
|
-
var COMPLIANCE_POSTURES =
|
|
111
|
-
hipaa: "strict",
|
|
112
|
-
"pci-dss": "strict",
|
|
113
|
-
gdpr: "strict",
|
|
114
|
-
soc2: "strict",
|
|
115
|
-
});
|
|
111
|
+
var COMPLIANCE_POSTURES = gateContract.ALL_STRICT_POSTURES;
|
|
116
112
|
|
|
117
113
|
var ALLOWED_PROTOCOLS = Object.freeze({
|
|
118
114
|
"icap": true,
|