@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
|
@@ -309,6 +309,7 @@ function _redact(value, depth, maxDepth, marker, parentKey) {
|
|
|
309
309
|
function _resetForTest() {
|
|
310
310
|
sensitiveFieldsSet = new Set(SENSITIVE_FIELDS);
|
|
311
311
|
customDetectors = [];
|
|
312
|
+
outboundInstallCount = 0;
|
|
312
313
|
}
|
|
313
314
|
|
|
314
315
|
// ---- Classifier presets (for outbound DLP) ----
|
|
@@ -625,6 +626,14 @@ function classifyDefaults(opts) {
|
|
|
625
626
|
|
|
626
627
|
var OUTBOUND_INSTALL_REGISTRY = new WeakMap();
|
|
627
628
|
|
|
629
|
+
// Count of primitive instances currently wrapped by an outbound-DLP
|
|
630
|
+
// interceptor. A WeakMap can't be enumerated, so this counter is the
|
|
631
|
+
// cheap "is anything installed?" signal b.compliance.set reads to decide
|
|
632
|
+
// whether to warn that a DLP-floor posture was pinned without wiring.
|
|
633
|
+
// Incremented per primitive on install, decremented on uninstall; never
|
|
634
|
+
// negative.
|
|
635
|
+
var outboundInstallCount = 0;
|
|
636
|
+
|
|
628
637
|
function _emitDlp(action, outcome, metadata) {
|
|
629
638
|
try {
|
|
630
639
|
audit().safeEmit({
|
|
@@ -740,15 +749,15 @@ function installOutboundDlp(opts) {
|
|
|
740
749
|
|
|
741
750
|
if (opts.httpClient) {
|
|
742
751
|
var u1 = _installHttpClient(opts.httpClient, classifier, opts);
|
|
743
|
-
if (u1) { uninstallers.push(u1); installed.httpClient = true; }
|
|
752
|
+
if (u1) { uninstallers.push(u1); installed.httpClient = true; outboundInstallCount += 1; }
|
|
744
753
|
}
|
|
745
754
|
if (opts.mail) {
|
|
746
755
|
var u2 = _installMail(opts.mail, classifier, opts);
|
|
747
|
-
if (u2) { uninstallers.push(u2); installed.mail = true; }
|
|
756
|
+
if (u2) { uninstallers.push(u2); installed.mail = true; outboundInstallCount += 1; }
|
|
748
757
|
}
|
|
749
758
|
if (opts.webhook) {
|
|
750
759
|
var u3 = _installWebhook(opts.webhook, classifier, opts);
|
|
751
|
-
if (u3) { uninstallers.push(u3); installed.webhook = true; }
|
|
760
|
+
if (u3) { uninstallers.push(u3); installed.webhook = true; outboundInstallCount += 1; }
|
|
752
761
|
}
|
|
753
762
|
|
|
754
763
|
_emitDlp("dlp.outbound.installed", "success", {
|
|
@@ -761,12 +770,37 @@ function installOutboundDlp(opts) {
|
|
|
761
770
|
uninstall: function () {
|
|
762
771
|
while (uninstallers.length > 0) {
|
|
763
772
|
var fn = uninstallers.pop();
|
|
764
|
-
try { fn();
|
|
773
|
+
try { fn(); if (outboundInstallCount > 0) outboundInstallCount -= 1; }
|
|
774
|
+
catch (_e) { /* best-effort */ }
|
|
765
775
|
}
|
|
766
776
|
},
|
|
767
777
|
};
|
|
768
778
|
}
|
|
769
779
|
|
|
780
|
+
/**
|
|
781
|
+
* @primitive b.redact.isOutboundDlpInstalled
|
|
782
|
+
* @signature b.redact.isOutboundDlpInstalled()
|
|
783
|
+
* @since 0.14.27
|
|
784
|
+
* @compliance hipaa, pci-dss, gdpr, soc2, fapi2
|
|
785
|
+
* @related b.redact.installForPosture, b.redact.installOutboundDlp
|
|
786
|
+
*
|
|
787
|
+
* Returns `true` when at least one primitive instance (httpClient /
|
|
788
|
+
* mail / webhook) currently carries an outbound-DLP interceptor.
|
|
789
|
+
* `b.compliance.set` reads this to decide whether to emit the one-time
|
|
790
|
+
* `compliance.posture.outbound_dlp_unwired` warning when a posture whose
|
|
791
|
+
* floor implies outbound DLP is pinned without any wiring. Read-only.
|
|
792
|
+
*
|
|
793
|
+
* @example
|
|
794
|
+
* b.redact.isOutboundDlpInstalled(); // → false
|
|
795
|
+
* var dlp = b.redact.installForPosture("hipaa", { httpClient: myHttp });
|
|
796
|
+
* b.redact.isOutboundDlpInstalled(); // → true
|
|
797
|
+
* dlp.uninstall();
|
|
798
|
+
* b.redact.isOutboundDlpInstalled(); // → false
|
|
799
|
+
*/
|
|
800
|
+
function isOutboundDlpInstalled() {
|
|
801
|
+
return outboundInstallCount > 0;
|
|
802
|
+
}
|
|
803
|
+
|
|
770
804
|
function _resolvePosturePatterns(name) {
|
|
771
805
|
var n = String(name).toLowerCase();
|
|
772
806
|
if (n === "pci-dss" || n === "pci") {
|
|
@@ -779,6 +813,15 @@ function _resolvePosturePatterns(name) {
|
|
|
779
813
|
return ["pan", "credit-card", "iban", "pem", "aws-access-key", "jwt", "api-key-shape"];
|
|
780
814
|
}
|
|
781
815
|
if (n === "soc2" || n === "gdpr") {
|
|
816
|
+
// Known fidelity collapse: soc2 and gdpr share one outbound-DLP
|
|
817
|
+
// pattern set here. They are distinct regimes — GDPR's special-
|
|
818
|
+
// category personal data (Art. 9) is broader than the SOC 2 Trust
|
|
819
|
+
// Services criteria this preset targets — but the built-in
|
|
820
|
+
// value-shape detectors don't yet distinguish them, so the same
|
|
821
|
+
// pattern list backs both. Operators needing GDPR-specific shapes
|
|
822
|
+
// pass an explicit classifier (classifyDefaults) rather than the
|
|
823
|
+
// posture preset. This is intentional, not an accidental alias —
|
|
824
|
+
// documented so it isn't mistaken for per-regime handling.
|
|
782
825
|
return ["ssn", "ein", "pem", "ssh-private", "aws-access-key", "api-key-shape"];
|
|
783
826
|
}
|
|
784
827
|
throw new DlpError("redact-dlp/unknown-posture",
|
|
@@ -959,9 +1002,12 @@ function _summarizeHit(h) {
|
|
|
959
1002
|
return { label: h.label, action: h.action, where: h.where };
|
|
960
1003
|
}
|
|
961
1004
|
|
|
962
|
-
// Posture-coordinated install —
|
|
963
|
-
// to wire
|
|
964
|
-
// b.compliance
|
|
1005
|
+
// Posture-coordinated install — the operator passes the primitive
|
|
1006
|
+
// instances to wire (httpClient / mail / webhook); the posture name
|
|
1007
|
+
// selects the default classifier. b.compliance.set does NOT call this:
|
|
1008
|
+
// it holds no httpClient / mail / webhook handles, so it cannot install
|
|
1009
|
+
// outbound interceptors. Operators wire DLP explicitly by calling this
|
|
1010
|
+
// (or installOutboundDlp) with their own primitive instances.
|
|
965
1011
|
/**
|
|
966
1012
|
* @primitive b.redact.installForPosture
|
|
967
1013
|
* @signature b.redact.installForPosture(posture, primitives)
|
|
@@ -970,10 +1016,20 @@ function _summarizeHit(h) {
|
|
|
970
1016
|
* @compliance hipaa, pci-dss, gdpr, soc2, fapi2
|
|
971
1017
|
* @related b.redact.installOutboundDlp, b.redact.classifyDefaults
|
|
972
1018
|
*
|
|
973
|
-
* Posture-coordinated install —
|
|
974
|
-
* `
|
|
975
|
-
*
|
|
976
|
-
*
|
|
1019
|
+
* Posture-coordinated install — picks the default classifier for
|
|
1020
|
+
* `posture` and wraps the operator-supplied `primitives.httpClient` /
|
|
1021
|
+
* `.mail` / `.webhook` so every outbound payload runs through it. A
|
|
1022
|
+
* thin convenience over `installOutboundDlp`; direct callers usually
|
|
1023
|
+
* want `installOutboundDlp` because it accepts the full hook surface.
|
|
1024
|
+
*
|
|
1025
|
+
* The operator MUST call this with the primitive instances — pinning a
|
|
1026
|
+
* posture via `b.compliance.set` does NOT auto-install outbound DLP,
|
|
1027
|
+
* because the compliance coordinator holds no httpClient / mail /
|
|
1028
|
+
* webhook handles. When a posture whose floor implies outbound DLP
|
|
1029
|
+
* (hipaa / pci-dss / gdpr / soc2 / fapi-2.0) is pinned without this
|
|
1030
|
+
* call, `b.compliance.set` emits a one-time
|
|
1031
|
+
* `compliance.posture.outbound_dlp_unwired` audit warning so the gap is
|
|
1032
|
+
* grep-able in the audit chain.
|
|
977
1033
|
*
|
|
978
1034
|
* @example
|
|
979
1035
|
* var dlp = b.redact.installForPosture("hipaa", {
|
|
@@ -999,6 +1055,7 @@ module.exports = {
|
|
|
999
1055
|
classifyDefaults: classifyDefaults,
|
|
1000
1056
|
installOutboundDlp: installOutboundDlp,
|
|
1001
1057
|
installForPosture: installForPosture,
|
|
1058
|
+
isOutboundDlpInstalled: isOutboundDlpInstalled,
|
|
1002
1059
|
CLASSIFIER_PATTERNS: CLASSIFIER_PATTERNS,
|
|
1003
1060
|
MARKER: DEFAULT_MARKER,
|
|
1004
1061
|
SENSITIVE_FIELDS: SENSITIVE_FIELDS,
|
|
@@ -28,7 +28,6 @@ var net = require("node:net");
|
|
|
28
28
|
var nodeTls = require("node:tls");
|
|
29
29
|
var nodeUrl = require("node:url");
|
|
30
30
|
var C = require("./constants");
|
|
31
|
-
var safeAsync = require("./safe-async");
|
|
32
31
|
var validateOpts = require("./validate-opts");
|
|
33
32
|
var ipUtils = require("./ip-utils");
|
|
34
33
|
var { RedisError } = require("./framework-error");
|
|
@@ -215,11 +214,28 @@ function create(opts) {
|
|
|
215
214
|
var connected = false;
|
|
216
215
|
var connecting = false;
|
|
217
216
|
var closing = false;
|
|
217
|
+
// Shared in-flight connect. Every _connect() call returns the SAME
|
|
218
|
+
// promise while a connect is in progress, so concurrent callers all
|
|
219
|
+
// observe the same resolve/reject instead of polling a flag. It is
|
|
220
|
+
// ALWAYS settled (resolve on ready, reject on socket-error / connect-
|
|
221
|
+
// timeout / AUTH-or-SELECT failure) and cleared the moment it settles
|
|
222
|
+
// so the next caller starts a fresh attempt — a connect that fails
|
|
223
|
+
// can never leave a never-settling promise behind for the next
|
|
224
|
+
// awaiter to wedge on.
|
|
225
|
+
var connectPromise = null;
|
|
218
226
|
// Tracked + unref'd reconnect timer. Tracked so close() can cancel a
|
|
219
227
|
// pending backoff (otherwise a reconnect scheduled before close fires
|
|
220
228
|
// after it and opens a fresh socket); unref'd so a backoff window doesn't
|
|
221
229
|
// by itself keep the event loop alive (the process-won't-exit class).
|
|
230
|
+
// Single-flight: a non-null reconnectTimer means a backoff is already
|
|
231
|
+
// pending — socket-error AND socket-close firing for the same failure
|
|
232
|
+
// must not stack two timers (which would burn the reconnect budget at
|
|
233
|
+
// 2x and open redundant sockets).
|
|
222
234
|
var reconnectTimer = null;
|
|
235
|
+
// Set once the reconnect budget is exhausted. Makes the give-up path
|
|
236
|
+
// idempotent (drains pending+backlog exactly once) and stops a stray
|
|
237
|
+
// close/error after give-up from re-draining or racing a later success.
|
|
238
|
+
var gaveUp = false;
|
|
223
239
|
var rxBuffer = Buffer.alloc(0);
|
|
224
240
|
// FIFO of in-flight commands awaiting a response
|
|
225
241
|
var pending = [];
|
|
@@ -239,18 +255,31 @@ function create(opts) {
|
|
|
239
255
|
|
|
240
256
|
function _scheduleReconnect() {
|
|
241
257
|
if (closing) return;
|
|
258
|
+
// Single-flight: a socket failure surfaces as both an `error` and a
|
|
259
|
+
// `close` event. Without this guard each one schedules its own timer,
|
|
260
|
+
// stacking two reconnects for one failure — the budget burns at 2x
|
|
261
|
+
// and two fresh sockets open. A pending backoff already covers the
|
|
262
|
+
// failure, so a second call is a no-op.
|
|
263
|
+
if (reconnectTimer !== null) return;
|
|
242
264
|
if (maxReconnectAttempts >= 0 && reconnectAttempt >= maxReconnectAttempts) {
|
|
243
|
-
// Drain pending
|
|
265
|
+
// Reconnect budget exhausted. Drain pending + backlog exactly once;
|
|
266
|
+
// a later stray close/error must not re-drain or race a future
|
|
267
|
+
// success path.
|
|
268
|
+
if (gaveUp) return;
|
|
269
|
+
gaveUp = true;
|
|
244
270
|
var err = _err("RECONNECT_GAVE_UP",
|
|
245
271
|
"redis: gave up after " + reconnectAttempt + " reconnect attempts");
|
|
246
272
|
_drainPending(err);
|
|
247
273
|
return;
|
|
248
274
|
}
|
|
249
275
|
reconnectAttempt++;
|
|
276
|
+
// Exponential backoff capped at 30s. Base 100ms is the first-retry
|
|
277
|
+
// delay (not a duration unit), so it stays a literal; the cap routes
|
|
278
|
+
// through C.TIME.
|
|
250
279
|
var delay = Math.min(C.TIME.seconds(30), 100 * Math.pow(2, reconnectAttempt - 1));
|
|
251
280
|
reconnectTimer = setTimeout(function () {
|
|
252
281
|
reconnectTimer = null;
|
|
253
|
-
_connect().catch(function () { /*
|
|
282
|
+
_connect().catch(function () { /* failure reschedules via the teardown path */ });
|
|
254
283
|
}, delay);
|
|
255
284
|
if (typeof reconnectTimer.unref === "function") reconnectTimer.unref();
|
|
256
285
|
}
|
|
@@ -261,7 +290,10 @@ function create(opts) {
|
|
|
261
290
|
batch.forEach(function (p) { p.reject(err); });
|
|
262
291
|
var bl = backlog.slice();
|
|
263
292
|
backlog.length = 0;
|
|
264
|
-
bl.forEach(function (p) {
|
|
293
|
+
bl.forEach(function (p) {
|
|
294
|
+
if (p.timer) { clearTimeout(p.timer); p.timer = null; }
|
|
295
|
+
p.reject(err);
|
|
296
|
+
});
|
|
265
297
|
}
|
|
266
298
|
|
|
267
299
|
function _onData(chunk) {
|
|
@@ -312,39 +344,74 @@ function create(opts) {
|
|
|
312
344
|
}
|
|
313
345
|
}
|
|
314
346
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
347
|
+
// Single teardown path for a lost socket. A failure surfaces as an
|
|
348
|
+
// `error` event AND a `close` event (and `error` then destroys the
|
|
349
|
+
// socket, which fires `close` again) — three callbacks for ONE lost
|
|
350
|
+
// connection. Routing all of them here, guarded by a "are we still
|
|
351
|
+
// attached to this socket" check, means pending is drained once and
|
|
352
|
+
// exactly one reconnect is scheduled (the single-flight guard in
|
|
353
|
+
// _scheduleReconnect absorbs the rest). `err` is the diagnostic to
|
|
354
|
+
// reject in-flight commands with.
|
|
355
|
+
function _teardownSocket(err) {
|
|
356
|
+
// Already torn down for this socket (the sibling event already ran).
|
|
357
|
+
if (!connected && socket === null) {
|
|
358
|
+
// Still let a stray event re-arm a reconnect if one isn't pending
|
|
359
|
+
// and we haven't been closed — but never re-drain pending.
|
|
360
|
+
if (!closing) _scheduleReconnect();
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
318
363
|
connected = false;
|
|
319
|
-
|
|
364
|
+
var dead = socket;
|
|
320
365
|
socket = null;
|
|
366
|
+
if (dead) {
|
|
367
|
+
try {
|
|
368
|
+
dead.removeListener("error", _onSocketError);
|
|
369
|
+
dead.removeListener("close", _onSocketClose);
|
|
370
|
+
dead.removeListener("data", _onData);
|
|
371
|
+
dead.destroy();
|
|
372
|
+
} catch (_e) { /* best-effort socket teardown */ }
|
|
373
|
+
}
|
|
374
|
+
_drainPending(err);
|
|
321
375
|
if (!closing) _scheduleReconnect();
|
|
322
376
|
}
|
|
323
377
|
|
|
378
|
+
function _onSocketError(err) {
|
|
379
|
+
_teardownSocket(_err("SOCKET",
|
|
380
|
+
"redis socket error: " + ((err && err.message) || String(err))));
|
|
381
|
+
}
|
|
382
|
+
|
|
324
383
|
function _onSocketClose() {
|
|
325
|
-
|
|
326
|
-
if (!closing) {
|
|
327
|
-
var err = _err("SOCKET_CLOSED", "redis socket closed unexpectedly");
|
|
328
|
-
_drainPending(err);
|
|
329
|
-
socket = null;
|
|
330
|
-
_scheduleReconnect();
|
|
331
|
-
}
|
|
384
|
+
_teardownSocket(_err("SOCKET_CLOSED", "redis socket closed unexpectedly"));
|
|
332
385
|
}
|
|
333
386
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
387
|
+
// _connect() — public entry. Returns a promise that ALWAYS settles.
|
|
388
|
+
// Concurrent callers (and the reconnect timer) share the single
|
|
389
|
+
// in-flight connectPromise rather than each starting a parallel dial,
|
|
390
|
+
// and they all observe the same resolve/reject. A previous version
|
|
391
|
+
// polled a `connecting` flag in a `while (connecting) await sleep(20)`
|
|
392
|
+
// loop; if a failure path failed to clear that flag the waiter spun
|
|
393
|
+
// forever. The shared promise removes that wedge — the promise is
|
|
394
|
+
// cleared the instant it settles, so a failed connect can never leave
|
|
395
|
+
// a never-settling promise behind.
|
|
396
|
+
function _connect() {
|
|
397
|
+
if (closing) return Promise.resolve();
|
|
398
|
+
if (connected) return Promise.resolve();
|
|
399
|
+
if (connectPromise) return connectPromise;
|
|
400
|
+
connectPromise = _doConnect();
|
|
401
|
+
// Clear the shared promise once it settles (either way) so the next
|
|
402
|
+
// _connect() starts a fresh attempt instead of re-awaiting a stale
|
|
403
|
+
// settled promise.
|
|
404
|
+
var clear = function () { connectPromise = null; };
|
|
405
|
+
connectPromise.then(clear, clear);
|
|
406
|
+
return connectPromise;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
async function _doConnect() {
|
|
344
410
|
connecting = true;
|
|
345
411
|
rxBuffer = Buffer.alloc(0);
|
|
412
|
+
var newSocket = null;
|
|
346
413
|
try {
|
|
347
|
-
|
|
414
|
+
newSocket = await new Promise(function (resolve, reject) {
|
|
348
415
|
var sock;
|
|
349
416
|
var timer = setTimeout(function () {
|
|
350
417
|
try { if (sock) sock.destroy(); } catch (_e) { /* best-effort socket teardown */ }
|
|
@@ -371,16 +438,19 @@ function create(opts) {
|
|
|
371
438
|
}
|
|
372
439
|
sock.once("error", onErr);
|
|
373
440
|
});
|
|
441
|
+
socket = newSocket;
|
|
374
442
|
socket.setNoDelay(true);
|
|
375
443
|
socket.on("data", _onData);
|
|
376
444
|
socket.on("error", _onSocketError);
|
|
377
445
|
socket.on("close", _onSocketClose);
|
|
378
446
|
connected = true;
|
|
379
|
-
reconnectAttempt = 0;
|
|
380
447
|
|
|
381
448
|
// Auth + select db on (re)connect — without resetting the
|
|
382
449
|
// backlog of commands queued during disconnect. Send these
|
|
383
450
|
// BEFORE the backlog so the server is ready when backlog flushes.
|
|
451
|
+
// A failure here (wrong password, server SELECT rejection, socket
|
|
452
|
+
// dropped mid-AUTH) must not leave connected=true on a half-open
|
|
453
|
+
// socket — the catch below tears the socket down and rethrows.
|
|
384
454
|
if (password) {
|
|
385
455
|
var authArgs = username ? ["AUTH", username, password] : ["AUTH", password];
|
|
386
456
|
await _sendNoQueue(authArgs);
|
|
@@ -389,15 +459,47 @@ function create(opts) {
|
|
|
389
459
|
await _sendNoQueue(["SELECT", String(db)]);
|
|
390
460
|
}
|
|
391
461
|
|
|
392
|
-
//
|
|
462
|
+
// Connect fully succeeded — only now reset the backoff counter +
|
|
463
|
+
// the give-up latch so a future disconnect gets a fresh budget.
|
|
464
|
+
reconnectAttempt = 0;
|
|
465
|
+
gaveUp = false;
|
|
466
|
+
connecting = false;
|
|
467
|
+
|
|
468
|
+
// Flush backlog. Clear each queued entry's not-connected timeout
|
|
469
|
+
// before it goes on the wire — the in-flight command timeout in
|
|
470
|
+
// _writeAndAwait now owns its lifetime.
|
|
393
471
|
var bl = backlog.slice();
|
|
394
472
|
backlog.length = 0;
|
|
395
|
-
bl.forEach(function (entry) {
|
|
473
|
+
bl.forEach(function (entry) {
|
|
474
|
+
if (entry.timer) { clearTimeout(entry.timer); entry.timer = null; }
|
|
475
|
+
_writeAndAwait(entry.args, entry.resolve, entry.reject);
|
|
476
|
+
});
|
|
396
477
|
} catch (err) {
|
|
397
478
|
connecting = false;
|
|
479
|
+
connected = false;
|
|
480
|
+
// Tear down a half-open socket (came up, then AUTH/SELECT failed)
|
|
481
|
+
// so we never leave connected=false with a live socket whose data/
|
|
482
|
+
// error/close handlers would fire against stale state. If the
|
|
483
|
+
// socket-error handler already ran it set socket=null.
|
|
484
|
+
var dead = socket || newSocket;
|
|
485
|
+
socket = null;
|
|
486
|
+
if (dead) {
|
|
487
|
+
try {
|
|
488
|
+
dead.removeListener("error", _onSocketError);
|
|
489
|
+
dead.removeListener("close", _onSocketClose);
|
|
490
|
+
dead.removeListener("data", _onData);
|
|
491
|
+
dead.destroy();
|
|
492
|
+
} catch (_e) { /* best-effort socket teardown */ }
|
|
493
|
+
}
|
|
494
|
+
// A failed dial (reset before ready) or an AUTH/SELECT failure must keep
|
|
495
|
+
// the reconnect loop alive. The post-ready error/close handlers that
|
|
496
|
+
// normally drive reconnect are not attached yet during the dial, so
|
|
497
|
+
// without scheduling here a connection lost mid-dial rejects the connect
|
|
498
|
+
// promise and the client never reconnects. Single-flight + budget-guarded
|
|
499
|
+
// by _scheduleReconnect; the caller still observes this attempt's rejection.
|
|
500
|
+
if (!closing) _scheduleReconnect();
|
|
398
501
|
throw err;
|
|
399
502
|
}
|
|
400
|
-
connecting = false;
|
|
401
503
|
}
|
|
402
504
|
|
|
403
505
|
// Internal helper that bypasses the connect-pending backlog (used
|
|
@@ -448,7 +550,28 @@ function create(opts) {
|
|
|
448
550
|
return;
|
|
449
551
|
}
|
|
450
552
|
if (!connected) {
|
|
451
|
-
|
|
553
|
+
// Reconnect budget exhausted and no reconnect is in flight — a
|
|
554
|
+
// backlogged command here would never be flushed (nothing will
|
|
555
|
+
// reconnect to drain it) and would wedge the caller forever.
|
|
556
|
+
// Reject immediately instead.
|
|
557
|
+
if (gaveUp && reconnectTimer === null && !connecting) {
|
|
558
|
+
reject(_err("RECONNECT_GAVE_UP",
|
|
559
|
+
"redis: client disconnected and reconnect budget exhausted"));
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
// Queued until the next successful connect flushes the backlog.
|
|
563
|
+
// Bound it with a timeout so a connect that never completes (the
|
|
564
|
+
// backend is down for the whole window) settles the caller with
|
|
565
|
+
// a clear error instead of leaving the await pending forever.
|
|
566
|
+
var entry = { args: args, resolve: resolve, reject: reject, timer: null };
|
|
567
|
+
entry.timer = setTimeout(function () {
|
|
568
|
+
var idx = backlog.indexOf(entry);
|
|
569
|
+
if (idx !== -1) backlog.splice(idx, 1);
|
|
570
|
+
reject(_err("COMMAND_TIMEOUT",
|
|
571
|
+
"redis " + args[0] + " timed out while queued (client not connected)"));
|
|
572
|
+
}, commandTimeoutMs);
|
|
573
|
+
if (typeof entry.timer.unref === "function") entry.timer.unref();
|
|
574
|
+
backlog.push(entry);
|
|
452
575
|
return;
|
|
453
576
|
}
|
|
454
577
|
_writeAndAwait(args, resolve, reject);
|
|
@@ -469,6 +592,9 @@ function create(opts) {
|
|
|
469
592
|
async function close() {
|
|
470
593
|
closing = true;
|
|
471
594
|
if (reconnectTimer) { clearTimeout(reconnectTimer); reconnectTimer = null; }
|
|
595
|
+
// Drop the shared connect promise so a re-create after close (or a
|
|
596
|
+
// late awaiter) doesn't re-await a stale in-flight attempt.
|
|
597
|
+
connectPromise = null;
|
|
472
598
|
var err = _err("CLOSED", "redis client closed");
|
|
473
599
|
_drainPending(err);
|
|
474
600
|
if (socket) {
|
|
@@ -492,8 +618,11 @@ function create(opts) {
|
|
|
492
618
|
_state: function () {
|
|
493
619
|
return {
|
|
494
620
|
connected: connected, closing: closing,
|
|
621
|
+
connecting: connecting,
|
|
495
622
|
pending: pending.length, backlog: backlog.length,
|
|
496
623
|
reconnect: reconnectAttempt,
|
|
624
|
+
reconnectPending: reconnectTimer !== null,
|
|
625
|
+
gaveUp: gaveUp,
|
|
497
626
|
host: host, port: port, db: db, tls: useTls,
|
|
498
627
|
connectTimeoutMs: connectTimeoutMs,
|
|
499
628
|
commandTimeoutMs: commandTimeoutMs,
|
|
@@ -254,6 +254,13 @@ function clientIp(req, opts) {
|
|
|
254
254
|
}
|
|
255
255
|
if (req.socket && typeof req.socket.remoteAddress === "string") return req.socket.remoteAddress;
|
|
256
256
|
if (req.connection && typeof req.connection.remoteAddress === "string") return req.connection.remoteAddress;
|
|
257
|
+
// Express-shaped requests expose the resolved client address as `req.ip`
|
|
258
|
+
// (Express derives it from the socket, honoring its own trust-proxy
|
|
259
|
+
// setting) without a `socket.remoteAddress` surface. Fall back to it so a
|
|
260
|
+
// binding captured from such a request is populated rather than null —
|
|
261
|
+
// callers that pin a grant to the issuing IP otherwise capture null and
|
|
262
|
+
// could only be saved by a fail-closed guard at the consumer.
|
|
263
|
+
if (typeof req.ip === "string" && req.ip.length > 0) return req.ip;
|
|
257
264
|
return null;
|
|
258
265
|
}
|
|
259
266
|
|