@blamejs/blamejs-shop 0.4.31 → 0.4.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/lib/asset-manifest.json +1 -1
- package/lib/vendor/MANIFEST.json +392 -278
- 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 +26 -0
- package/lib/vendor/blamejs/MIGRATING.md +43 -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/oauth.js +53 -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 +31 -5
- 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 +206 -4
- package/lib/vendor/blamejs/lib/consent.js +82 -29
- package/lib/vendor/blamejs/lib/constants.js +27 -11
- 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 +101 -40
- 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 +35 -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 +151 -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/scripts/check-services.js +21 -0
- package/lib/vendor/blamejs/scripts/gen-migrating.js +51 -0
- package/lib/vendor/blamejs/scripts/release.js +398 -38
- package/lib/vendor/blamejs/test/00-primitives.js +117 -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 +1120 -14
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance.test.js +229 -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/router-use-path-scope.test.js +255 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-url-canonicalize.test.js +309 -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/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 +1 -1
- 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
|
@@ -63,17 +63,69 @@ var auditSign = lazyRequire(function () { return require("./audit-sign"); });
|
|
|
63
63
|
var ExternalDbMigrateError = defineClass("ExternalDbMigrateError", { alwaysPermanent: true });
|
|
64
64
|
|
|
65
65
|
// Lazy require — external-db imports back into this module via its
|
|
66
|
-
// public `migrate` namespace; load-order would cycle without lazy.
|
|
66
|
+
// public `migrate` namespace; load-order would cycle without lazy. The
|
|
67
|
+
// same cycle (external-db -> external-db-migrate -> cluster-storage ->
|
|
68
|
+
// cluster -> cluster-provider-db -> external-db) means clusterStorage +
|
|
69
|
+
// frameworkSchema must be lazy here too, and the table-name constants
|
|
70
|
+
// resolved on first use rather than at module load (frameworkSchema's
|
|
71
|
+
// tableName export is not yet bound while this module evaluates).
|
|
67
72
|
var externalDb = lazyRequire(function () { return require("./external-db"); });
|
|
73
|
+
var clusterStorage = lazyRequire(function () { return require("./cluster-storage"); });
|
|
74
|
+
var frameworkSchema = lazyRequire(function () { return require("./framework-schema"); });
|
|
75
|
+
var sql = lazyRequire(function () { return require("./sql"); });
|
|
76
|
+
|
|
77
|
+
// The migration runner's own bookkeeping tables, resolved through
|
|
78
|
+
// frameworkSchema so the configurable framework-table prefix is honored
|
|
79
|
+
// (these names are not in the LOCAL_TO_EXTERNAL map, so the resolve only
|
|
80
|
+
// swaps the leading prefix; default prefix is a no-op). b.sql quotes
|
|
81
|
+
// every identifier by construction in the backend's own dialect
|
|
82
|
+
// (double-quote on Postgres / SQLite, backtick on MySQL), with the
|
|
83
|
+
// placeholder form (`$N` on Postgres, `?` on SQLite / MySQL) selected by
|
|
84
|
+
// the resolved backend dialect — see _backendDialect / _bind below.
|
|
85
|
+
function _trackingTable() { return frameworkSchema().tableName("_blamejs_externaldb_migrations"); } // allow:hand-rolled-sql — single canonical logical-name reference
|
|
86
|
+
function _lockTable() { return frameworkSchema().tableName("_blamejs_externaldb_migrations_lock"); } // allow:hand-rolled-sql — single canonical logical-name reference
|
|
87
|
+
function _historyTable() { return frameworkSchema().tableName("_blamejs_schema_version_history"); } // allow:hand-rolled-sql — single canonical logical-name reference
|
|
88
|
+
|
|
89
|
+
// Resolve the SQL dialect of the backend this migration wave targets.
|
|
90
|
+
// The runner emits Postgres / SQLite / MySQL — they diverge on identifier
|
|
91
|
+
// quoting (double-quote vs backtick), the ON CONFLICT / ON DUPLICATE KEY
|
|
92
|
+
// upsert idiom, and placeholder syntax (`$N` vs `?`). Reading the dialect
|
|
93
|
+
// off the backend itself (set at b.externalDb.init) is what keeps the
|
|
94
|
+
// bookkeeping DDL + tracking statements valid on each. Falls back to
|
|
95
|
+
// "postgres" when the backend can't be resolved (uninitialized externalDb
|
|
96
|
+
// surfaces a clearer error upstream at _resolveBackendName); the bare
|
|
97
|
+
// fallback never reaches a real query.
|
|
98
|
+
function _backendDialect(backendName) {
|
|
99
|
+
var listed;
|
|
100
|
+
try { listed = externalDb().listBackends(); }
|
|
101
|
+
catch (_e) { return "postgres"; }
|
|
102
|
+
for (var i = 0; i < listed.length; i++) {
|
|
103
|
+
if (listed[i].name === backendName) {
|
|
104
|
+
return (listed[i].dialect || "postgres").toLowerCase();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return "postgres";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// b.sql emits `?` placeholders; the externalDb driver receives SQL
|
|
111
|
+
// verbatim, so translate to the Postgres `$N` form on a Postgres backend
|
|
112
|
+
// (placeholderize is a passthrough for SQLite / MySQL, which keep `?`).
|
|
113
|
+
// dialect is the resolved backend dialect so the placeholder form matches
|
|
114
|
+
// the backend the SQL dispatches to.
|
|
115
|
+
function _bind(builder, dialect) {
|
|
116
|
+
var built = builder.toSql();
|
|
117
|
+
return { sql: clusterStorage().placeholderize(built.sql, dialect), params: built.params };
|
|
118
|
+
}
|
|
68
119
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
//
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
120
|
+
// The migration tracking / history / lock tables hold framework
|
|
121
|
+
// bookkeeping ("migration X ran at time T"), not region-bound personal
|
|
122
|
+
// data, so their writes carry the residency-neutral "unrestricted" tag
|
|
123
|
+
// — the per-row residency write gate (b.externalDb.query) refuses DML
|
|
124
|
+
// to a residency-tagged backend under a cross-border regulated posture
|
|
125
|
+
// unless a compatible rowResidencyTag is supplied. Operator migration
|
|
126
|
+
// DML (mod.up) stays subject to the gate; only these internal writes
|
|
127
|
+
// are exempt. Passed as the per-statement opts override on the txClient.
|
|
128
|
+
var FRAMEWORK_METADATA_OPTS = Object.freeze({ rowResidencyTag: "unrestricted" });
|
|
77
129
|
|
|
78
130
|
// Bytes that get signed for one history row. Stable forever — changing
|
|
79
131
|
// it invalidates every prior signature.
|
|
@@ -100,12 +152,11 @@ function _historyPayload(row) {
|
|
|
100
152
|
// default introspect just returns the migration name list as a JSON
|
|
101
153
|
// array, which is enough to detect "someone manually altered the
|
|
102
154
|
// migrations table."
|
|
103
|
-
async function _defaultSchemaIntrospect(xdb) {
|
|
104
|
-
var
|
|
105
|
-
"
|
|
106
|
-
"
|
|
107
|
-
|
|
108
|
-
);
|
|
155
|
+
async function _defaultSchemaIntrospect(xdb, dialect) {
|
|
156
|
+
var q = _bind(sql().select(_trackingTable(), { dialect: dialect })
|
|
157
|
+
.columns(["name", "appliedAt"])
|
|
158
|
+
.orderBy("appliedAt", "asc").orderBy("name", "asc"), dialect);
|
|
159
|
+
var res = await xdb.query(q.sql, q.params);
|
|
109
160
|
var rows = (res && res.rows) || [];
|
|
110
161
|
return sha3Hash(Buffer.from(canonicalJson.stringify(rows), "utf8"));
|
|
111
162
|
}
|
|
@@ -139,74 +190,73 @@ function _lockHolderId() {
|
|
|
139
190
|
(require("node:os").hostname() || "unknown") + "@" + _BOOT_TOKEN;
|
|
140
191
|
}
|
|
141
192
|
|
|
142
|
-
async function _ensureTrackingTable(xdb) {
|
|
193
|
+
async function _ensureTrackingTable(xdb, dialect) {
|
|
143
194
|
// Tracking table holds the migration history. ISO-8601 timestamp
|
|
144
|
-
// strings
|
|
145
|
-
// Postgres/SQLite without dialect-specific type juggling —
|
|
146
|
-
// who want strict TIMESTAMPTZ for their own ad-hoc queries
|
|
147
|
-
// the table ALTER it post-creation.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
")",
|
|
154
|
-
|
|
155
|
-
|
|
195
|
+
// strings keep the framework's tracking table portable across
|
|
196
|
+
// Postgres/SQLite/MySQL without dialect-specific type juggling —
|
|
197
|
+
// operators who want strict TIMESTAMPTZ for their own ad-hoc queries
|
|
198
|
+
// against the table ALTER it post-creation. The `name` PK is a bounded
|
|
199
|
+
// VARCHAR, not TEXT: MySQL refuses an unbounded TEXT/BLOB in a key
|
|
200
|
+
// (ER 1170), and a migration filename is length-capped at FILE_NAME_MAX
|
|
201
|
+
// so 255 covers every valid value. Postgres / SQLite treat VARCHAR(255)
|
|
202
|
+
// identically to TEXT for storage.
|
|
203
|
+
await xdb.query(sql().createTable(_trackingTable(), [
|
|
204
|
+
{ name: "name", type: "VARCHAR(255)", primaryKey: true },
|
|
205
|
+
{ name: "description", type: "TEXT" },
|
|
206
|
+
{ name: "appliedAt", type: "TEXT", notNull: true },
|
|
207
|
+
], { dialect: dialect }).sql, []);
|
|
156
208
|
}
|
|
157
209
|
|
|
158
|
-
async function _ensureHistoryTable(xdb) {
|
|
210
|
+
async function _ensureHistoryTable(xdb, dialect) {
|
|
159
211
|
// Schema-version history table: append-only record of every migrate.up
|
|
160
212
|
// wave + signature over (version, ranAt, ranBy, schemaIntrospectionHash).
|
|
161
213
|
// Signature uses ML-DSA-87 / SLH-DSA-SHAKE-256f via b.auditSign — an
|
|
162
214
|
// attacker tampering with rows after-the-fact cannot forge a matching
|
|
163
|
-
// signature without the audit-signing private key.
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
"
|
|
170
|
-
"
|
|
171
|
-
"
|
|
172
|
-
|
|
173
|
-
"
|
|
174
|
-
|
|
175
|
-
);
|
|
215
|
+
// signature without the audit-signing private key. version + ranAt form
|
|
216
|
+
// the composite PK, so both are bounded VARCHARs (MySQL refuses an
|
|
217
|
+
// unbounded TEXT/BLOB in a key, ER 1170); version is a filename
|
|
218
|
+
// (length-capped) and ranAt an ISO-8601 string, both within bound.
|
|
219
|
+
await xdb.query(sql().createTable(_historyTable(), [
|
|
220
|
+
{ name: "version", type: "VARCHAR(255)", notNull: true },
|
|
221
|
+
{ name: "ranAt", type: "VARCHAR(64)", notNull: true },
|
|
222
|
+
{ name: "ranBy", type: "TEXT", notNull: true },
|
|
223
|
+
{ name: "schemaIntrospectionHash", type: "TEXT", notNull: true },
|
|
224
|
+
{ name: "signature", type: "TEXT" },
|
|
225
|
+
{ name: "publicKeyFingerprint", type: "TEXT" },
|
|
226
|
+
], { dialect: dialect, primaryKey: ["version", "ranAt"] }).sql, []);
|
|
176
227
|
}
|
|
177
228
|
|
|
178
|
-
async function _writeHistoryRow(xdb, row) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
row.signature,
|
|
189
|
-
row.publicKeyFingerprint,
|
|
190
|
-
]
|
|
191
|
-
);
|
|
229
|
+
async function _writeHistoryRow(xdb, row, dialect) {
|
|
230
|
+
var q = _bind(sql().insert(_historyTable(), { dialect: dialect }).values({
|
|
231
|
+
version: row.version,
|
|
232
|
+
ranAt: row.ranAt,
|
|
233
|
+
ranBy: row.ranBy,
|
|
234
|
+
schemaIntrospectionHash: row.schemaIntrospectionHash,
|
|
235
|
+
signature: row.signature,
|
|
236
|
+
publicKeyFingerprint: row.publicKeyFingerprint,
|
|
237
|
+
}), dialect);
|
|
238
|
+
await xdb.query(q.sql, q.params, FRAMEWORK_METADATA_OPTS);
|
|
192
239
|
}
|
|
193
240
|
|
|
194
|
-
async function _ensureLockTable(xdb) {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
241
|
+
async function _ensureLockTable(xdb, dialect) {
|
|
242
|
+
// The scope CHECK is a static operator-controlled literal, carried as
|
|
243
|
+
// the last column's verbatim constraint (b.sql guards it via
|
|
244
|
+
// allowLiterals). lockedAt holds a ms-epoch value, so the framework INT
|
|
245
|
+
// type (BIGINT on Postgres/MySQL) is required — a 32-bit INTEGER
|
|
246
|
+
// overflows. The scope PK is a bounded VARCHAR (only ever 'lock'): MySQL
|
|
247
|
+
// refuses an unbounded TEXT/BLOB in a key (ER 1170).
|
|
248
|
+
await xdb.query(sql().createTable(_lockTable(), [
|
|
249
|
+
{ name: "scope", type: "VARCHAR(64)", primaryKey: true },
|
|
250
|
+
{ name: "lockedAt", type: "INTEGER", notNull: true },
|
|
251
|
+
{ name: "lockedBy", type: "TEXT", notNull: true,
|
|
252
|
+
constraints: ", CHECK (scope = 'lock')" }, // allow:hand-rolled-sql — static DDL CHECK literal
|
|
253
|
+
], { dialect: dialect }).sql, []);
|
|
204
254
|
}
|
|
205
255
|
|
|
206
256
|
// ---- Lock acquire / release ----
|
|
207
257
|
|
|
208
|
-
async function _acquireLock(xdb, opts) {
|
|
209
|
-
await _ensureLockTable(xdb);
|
|
258
|
+
async function _acquireLock(xdb, opts, dialect) {
|
|
259
|
+
await _ensureLockTable(xdb, dialect);
|
|
210
260
|
var holder = _lockHolderId();
|
|
211
261
|
var nowMs = Date.now();
|
|
212
262
|
// See migrations.acquireLock for the same fix — Infinity was
|
|
@@ -218,27 +268,67 @@ async function _acquireLock(xdb, opts) {
|
|
|
218
268
|
ExternalDbMigrateError, "externalDb-migrate/bad-opt");
|
|
219
269
|
if (opts.staleAfterMs !== undefined) staleAfterMs = opts.staleAfterMs;
|
|
220
270
|
}
|
|
271
|
+
// Conflict-safe lock acquire. The INSERT runs inside
|
|
272
|
+
// externalDb.transaction(_acquireLock); on Postgres a plain INSERT that
|
|
273
|
+
// hits the PRIMARY KEY conflict raises SQLSTATE 23505 which ABORTS the
|
|
274
|
+
// surrounding transaction (every later statement then fails with 25P02,
|
|
275
|
+
// "current transaction is aborted"), so the holder-naming SELECT could
|
|
276
|
+
// not run and the operator got a raw aborted-transaction error instead of
|
|
277
|
+
// the documented "migration lock is held by <holder>" message. Emitting
|
|
278
|
+
// `INSERT ... ON CONFLICT (scope) DO NOTHING` (Postgres/SQLite) /
|
|
279
|
+
// `INSERT ... ON DUPLICATE KEY UPDATE scope=scope` (MySQL — a no-op)
|
|
280
|
+
// turns the conflict into a 0-row result rather than a transaction-
|
|
281
|
+
// aborting error, so the inspect SELECT below runs cleanly and names the
|
|
282
|
+
// holder. rowCount === 1 means we won the lock; 0 means it is held.
|
|
283
|
+
function _insertLock() {
|
|
284
|
+
return _bind(sql().upsert(_lockTable(), { dialect: dialect })
|
|
285
|
+
.values({ scope: "lock", lockedAt: nowMs, lockedBy: holder })
|
|
286
|
+
.onConflict(["scope"]).doNothing(), dialect);
|
|
287
|
+
}
|
|
288
|
+
var insRes;
|
|
221
289
|
try {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
290
|
+
var ins = _insertLock();
|
|
291
|
+
insRes = await xdb.query(ins.sql, ins.params, FRAMEWORK_METADATA_OPTS);
|
|
292
|
+
} catch (e0) {
|
|
293
|
+
// A genuine driver/connection fault (not a conflict — the conflict is now
|
|
294
|
+
// a 0-row no-op, never a throw). Surface as lock-busy.
|
|
295
|
+
throw _err("externaldb-migrate/lock-busy",
|
|
296
|
+
"could not acquire migration lock: " + ((e0 && e0.message) || String(e0)));
|
|
297
|
+
}
|
|
298
|
+
if (insRes && insRes.rowCount >= 1) {
|
|
226
299
|
return { holder: holder, takeoverFrom: null, takeoverAgeMs: 0 };
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
)
|
|
300
|
+
}
|
|
301
|
+
{
|
|
302
|
+
// 0 rows inserted → the lock IS held. Inspect it to name the holder. The
|
|
303
|
+
// conflict was a clean no-op (DO NOTHING), so the transaction is NOT
|
|
304
|
+
// aborted and this SELECT runs.
|
|
305
|
+
var selExisting = _bind(sql().select(_lockTable(), { dialect: dialect })
|
|
306
|
+
.columns(["lockedAt", "lockedBy"]).where("scope", "lock"), dialect);
|
|
307
|
+
var existingRes;
|
|
308
|
+
try {
|
|
309
|
+
existingRes = await xdb.query(selExisting.sql, selExisting.params);
|
|
310
|
+
} catch (_inspectErr) {
|
|
311
|
+
throw _err("externaldb-migrate/lock-held",
|
|
312
|
+
"migration lock is held — another process is running migrations " +
|
|
313
|
+
"(the lock row could not be inspected). Wait for it to finish, or " +
|
|
314
|
+
"pass staleAfterMs to force-replace stale locks.");
|
|
315
|
+
}
|
|
233
316
|
var existing = existingRes && existingRes.rows && existingRes.rows[0];
|
|
234
317
|
if (!existing) {
|
|
318
|
+
// Lock row vanished between the no-op insert and the inspect (the
|
|
319
|
+
// holder released concurrently). Retry the acquire once.
|
|
235
320
|
try {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
321
|
+
var insRetry = _insertLock();
|
|
322
|
+
var retryRes = await xdb.query(insRetry.sql, insRetry.params, FRAMEWORK_METADATA_OPTS);
|
|
323
|
+
if (retryRes && retryRes.rowCount >= 1) {
|
|
324
|
+
return { holder: holder, takeoverFrom: null, takeoverAgeMs: 0 };
|
|
325
|
+
}
|
|
326
|
+
throw _err("externaldb-migrate/lock-held",
|
|
327
|
+
"migration lock is held — another process re-acquired it during " +
|
|
328
|
+
"the acquire race. Wait for it to finish, or pass staleAfterMs to " +
|
|
329
|
+
"force-replace stale locks.");
|
|
241
330
|
} catch (e2) {
|
|
331
|
+
if (e2 && e2.isExternalDbMigrateError) throw e2;
|
|
242
332
|
throw _err("externaldb-migrate/lock-busy",
|
|
243
333
|
"could not acquire migration lock: " + ((e2 && e2.message) || String(e2)));
|
|
244
334
|
}
|
|
@@ -248,14 +338,19 @@ async function _acquireLock(xdb, opts) {
|
|
|
248
338
|
// Force-replace the stale lock atomically. Stale-takeover is a
|
|
249
339
|
// SOC2 evidence event — caller emits an audit row.
|
|
250
340
|
var prevHolder = existing.lockedby || existing.lockedBy;
|
|
251
|
-
|
|
252
|
-
"
|
|
253
|
-
|
|
254
|
-
);
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
341
|
+
var delStale = _bind(sql().delete(_lockTable(), { dialect: dialect })
|
|
342
|
+
.where("scope", "lock")
|
|
343
|
+
.where("lockedAt", Number(existing.lockedat || existing.lockedAt)), dialect);
|
|
344
|
+
await xdb.query(delStale.sql, delStale.params, FRAMEWORK_METADATA_OPTS);
|
|
345
|
+
var insTakeover = _insertLock();
|
|
346
|
+
var takeoverRes = await xdb.query(insTakeover.sql, insTakeover.params, FRAMEWORK_METADATA_OPTS);
|
|
347
|
+
if (!takeoverRes || takeoverRes.rowCount < 1) {
|
|
348
|
+
// Another process slipped a fresh lock in between our DELETE and
|
|
349
|
+
// INSERT (the conflict is a DO NOTHING no-op, so 0 rows = lost race).
|
|
350
|
+
throw _err("externaldb-migrate/lock-held",
|
|
351
|
+
"migration lock was re-acquired by another process during the " +
|
|
352
|
+
"stale-lock takeover. Wait for it to finish, or retry.");
|
|
353
|
+
}
|
|
259
354
|
return { holder: holder, takeoverFrom: prevHolder, takeoverAgeMs: ageMs };
|
|
260
355
|
}
|
|
261
356
|
throw _err("externaldb-migrate/lock-held",
|
|
@@ -265,12 +360,11 @@ async function _acquireLock(xdb, opts) {
|
|
|
265
360
|
}
|
|
266
361
|
}
|
|
267
362
|
|
|
268
|
-
async function _releaseLock(xdb, holder) {
|
|
363
|
+
async function _releaseLock(xdb, holder, dialect) {
|
|
269
364
|
try {
|
|
270
|
-
|
|
271
|
-
"
|
|
272
|
-
|
|
273
|
-
);
|
|
365
|
+
var del = _bind(sql().delete(_lockTable(), { dialect: dialect })
|
|
366
|
+
.where("scope", "lock").where("lockedBy", holder), dialect);
|
|
367
|
+
await xdb.query(del.sql, del.params, FRAMEWORK_METADATA_OPTS);
|
|
274
368
|
} catch (_e) {
|
|
275
369
|
// best-effort release; operator can DELETE manually.
|
|
276
370
|
}
|
|
@@ -370,13 +464,13 @@ function create(opts) {
|
|
|
370
464
|
|
|
371
465
|
async function status() {
|
|
372
466
|
var backendName = _resolveBackendName(opts);
|
|
467
|
+
var dialect = _backendDialect(backendName);
|
|
373
468
|
return await externalDb().transaction(async function (xdb) {
|
|
374
|
-
await _ensureTrackingTable(xdb);
|
|
375
|
-
var
|
|
376
|
-
"
|
|
377
|
-
"
|
|
378
|
-
|
|
379
|
-
);
|
|
469
|
+
await _ensureTrackingTable(xdb, dialect);
|
|
470
|
+
var q = _bind(sql().select(_trackingTable(), { dialect: dialect })
|
|
471
|
+
.columns(["name", "description", "appliedAt"])
|
|
472
|
+
.orderBy("appliedAt", "asc").orderBy("name", "asc"), dialect);
|
|
473
|
+
var res = await xdb.query(q.sql, q.params);
|
|
380
474
|
var applied = (res && res.rows) || [];
|
|
381
475
|
var appliedNames = new Set(applied.map(function (r) { return r.name; }));
|
|
382
476
|
var files = _list(dir);
|
|
@@ -392,12 +486,13 @@ function create(opts) {
|
|
|
392
486
|
|
|
393
487
|
async function up() {
|
|
394
488
|
var backendName = _resolveBackendName(opts);
|
|
489
|
+
var dialect = _backendDialect(backendName);
|
|
395
490
|
var ctx = _ctx(backendName);
|
|
396
491
|
|
|
397
492
|
return await externalDb().transaction(async function (xdb) {
|
|
398
|
-
await _ensureTrackingTable(xdb);
|
|
399
|
-
await _ensureLockTable(xdb);
|
|
400
|
-
await _ensureHistoryTable(xdb);
|
|
493
|
+
await _ensureTrackingTable(xdb, dialect);
|
|
494
|
+
await _ensureLockTable(xdb, dialect);
|
|
495
|
+
await _ensureHistoryTable(xdb, dialect);
|
|
401
496
|
}, { backend: backendName }).then(async function () {
|
|
402
497
|
// Acquire the lock OUTSIDE the per-migration transaction so the
|
|
403
498
|
// lock survives across migration boundaries. We use a separate
|
|
@@ -405,7 +500,7 @@ function create(opts) {
|
|
|
405
500
|
// serializes apply order, so this single-connection lock is
|
|
406
501
|
// sufficient.
|
|
407
502
|
var lockResult = await externalDb().transaction(async function (xdb) {
|
|
408
|
-
return await _acquireLock(xdb, opts);
|
|
503
|
+
return await _acquireLock(xdb, opts, dialect);
|
|
409
504
|
}, { backend: backendName });
|
|
410
505
|
var lockHolder = lockResult.holder;
|
|
411
506
|
|
|
@@ -421,9 +516,9 @@ function create(opts) {
|
|
|
421
516
|
}
|
|
422
517
|
|
|
423
518
|
try {
|
|
424
|
-
var
|
|
425
|
-
"
|
|
426
|
-
);
|
|
519
|
+
var appliedQ = _bind(sql().select(_trackingTable(), { dialect: dialect })
|
|
520
|
+
.columns(["name"]), dialect);
|
|
521
|
+
var appliedRes = await externalDb().query(appliedQ.sql, appliedQ.params, { backend: backendName });
|
|
427
522
|
var appliedSet = new Set(((appliedRes && appliedRes.rows) || []).map(function (r) { return r.name; }));
|
|
428
523
|
var files = _list(dir);
|
|
429
524
|
var applied = [];
|
|
@@ -438,11 +533,9 @@ function create(opts) {
|
|
|
438
533
|
await externalDb().transaction(async function (xdb) {
|
|
439
534
|
await mod.up(xdb, ctx);
|
|
440
535
|
var ranAt = new Date().toISOString();
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
[file, mod.description || "", ranAt]
|
|
445
|
-
);
|
|
536
|
+
var insTrack = _bind(sql().insert(_trackingTable(), { dialect: dialect })
|
|
537
|
+
.values({ name: file, description: mod.description || "", appliedAt: ranAt }), dialect);
|
|
538
|
+
await xdb.query(insTrack.sql, insTrack.params, FRAMEWORK_METADATA_OPTS);
|
|
446
539
|
// Schema-version history with signature. Sign post-INSERT
|
|
447
540
|
// so the introspection hash reflects the row that just
|
|
448
541
|
// landed. Sign-failure is non-fatal for the migration but
|
|
@@ -451,7 +544,7 @@ function create(opts) {
|
|
|
451
544
|
version: file,
|
|
452
545
|
ranAt: ranAt,
|
|
453
546
|
ranBy: ranBy,
|
|
454
|
-
schemaIntrospectionHash: await schemaIntrospect(xdb),
|
|
547
|
+
schemaIntrospectionHash: await schemaIntrospect(xdb, dialect),
|
|
455
548
|
signature: null,
|
|
456
549
|
publicKeyFingerprint: null,
|
|
457
550
|
};
|
|
@@ -467,7 +560,7 @@ function create(opts) {
|
|
|
467
560
|
(sigErr && sigErr.message) || String(sigErr));
|
|
468
561
|
}
|
|
469
562
|
}
|
|
470
|
-
await _writeHistoryRow(xdb, historyRow);
|
|
563
|
+
await _writeHistoryRow(xdb, historyRow, dialect);
|
|
471
564
|
_emit(audit, "migrations.history.appended", "success", {
|
|
472
565
|
migration: file,
|
|
473
566
|
schemaIntrospectionHash: historyRow.schemaIntrospectionHash,
|
|
@@ -490,7 +583,7 @@ function create(opts) {
|
|
|
490
583
|
} finally {
|
|
491
584
|
try {
|
|
492
585
|
await externalDb().transaction(async function (xdb) {
|
|
493
|
-
await _releaseLock(xdb, lockHolder);
|
|
586
|
+
await _releaseLock(xdb, lockHolder, dialect);
|
|
494
587
|
}, { backend: backendName });
|
|
495
588
|
_emit(audit, "externaldb.migrate.lock.released", "success",
|
|
496
589
|
{ holder: lockHolder, backend: backendName }, null);
|
|
@@ -507,15 +600,16 @@ function create(opts) {
|
|
|
507
600
|
var steps = (typeof downOpts.steps === "number" && downOpts.steps > 0)
|
|
508
601
|
? Math.floor(downOpts.steps) : 1;
|
|
509
602
|
var backendName = _resolveBackendName(opts);
|
|
603
|
+
var dialect = _backendDialect(backendName);
|
|
510
604
|
var ctx = _ctx(backendName);
|
|
511
605
|
|
|
512
606
|
await externalDb().transaction(async function (xdb) {
|
|
513
|
-
await _ensureTrackingTable(xdb);
|
|
514
|
-
await _ensureLockTable(xdb);
|
|
607
|
+
await _ensureTrackingTable(xdb, dialect);
|
|
608
|
+
await _ensureLockTable(xdb, dialect);
|
|
515
609
|
}, { backend: backendName });
|
|
516
610
|
|
|
517
611
|
var lockResultDown = await externalDb().transaction(async function (xdb) {
|
|
518
|
-
return await _acquireLock(xdb, opts);
|
|
612
|
+
return await _acquireLock(xdb, opts, dialect);
|
|
519
613
|
}, { backend: backendName });
|
|
520
614
|
var lockHolder = lockResultDown.holder;
|
|
521
615
|
|
|
@@ -528,10 +622,10 @@ function create(opts) {
|
|
|
528
622
|
}
|
|
529
623
|
|
|
530
624
|
try {
|
|
531
|
-
var
|
|
532
|
-
"
|
|
533
|
-
|
|
534
|
-
);
|
|
625
|
+
var downQ = _bind(sql().select(_trackingTable(), { dialect: dialect })
|
|
626
|
+
.columns(["name"])
|
|
627
|
+
.orderBy("appliedAt", "desc").orderBy("name", "desc").limit(steps), dialect);
|
|
628
|
+
var appliedRes = await externalDb().query(downQ.sql, downQ.params, { backend: backendName });
|
|
535
629
|
var rows = (appliedRes && appliedRes.rows) || [];
|
|
536
630
|
var reverted = [];
|
|
537
631
|
for (var i = 0; i < rows.length; i++) {
|
|
@@ -545,10 +639,9 @@ function create(opts) {
|
|
|
545
639
|
try {
|
|
546
640
|
await externalDb().transaction(async function (xdb) {
|
|
547
641
|
await mod.down(xdb, ctx);
|
|
548
|
-
|
|
549
|
-
"
|
|
550
|
-
|
|
551
|
-
);
|
|
642
|
+
var delTrack = _bind(sql().delete(_trackingTable(), { dialect: dialect })
|
|
643
|
+
.where("name", file), dialect);
|
|
644
|
+
await xdb.query(delTrack.sql, delTrack.params);
|
|
552
645
|
}, { backend: backendName });
|
|
553
646
|
_emit(audit, "externaldb.migrate.down", "success",
|
|
554
647
|
{ migration: file, durationMs: Date.now() - t0, backend: backendName }, null);
|
|
@@ -565,7 +658,7 @@ function create(opts) {
|
|
|
565
658
|
} finally {
|
|
566
659
|
try {
|
|
567
660
|
await externalDb().transaction(async function (xdb) {
|
|
568
|
-
await _releaseLock(xdb, lockHolder);
|
|
661
|
+
await _releaseLock(xdb, lockHolder, dialect);
|
|
569
662
|
}, { backend: backendName });
|
|
570
663
|
_emit(audit, "externaldb.migrate.lock.released", "success",
|
|
571
664
|
{ holder: lockHolder, backend: backendName }, null);
|
|
@@ -588,13 +681,13 @@ function create(opts) {
|
|
|
588
681
|
async function history(historyOpts) {
|
|
589
682
|
historyOpts = historyOpts || {};
|
|
590
683
|
var backendName = _resolveBackendName(opts);
|
|
684
|
+
var dialect = _backendDialect(backendName);
|
|
591
685
|
return await externalDb().transaction(async function (xdb) {
|
|
592
|
-
await _ensureHistoryTable(xdb);
|
|
593
|
-
var
|
|
594
|
-
"
|
|
595
|
-
"
|
|
596
|
-
|
|
597
|
-
);
|
|
686
|
+
await _ensureHistoryTable(xdb, dialect);
|
|
687
|
+
var histQ = _bind(sql().select(_historyTable(), { dialect: dialect })
|
|
688
|
+
.columns(["version", "ranAt", "ranBy", "schemaIntrospectionHash", "signature", "publicKeyFingerprint"])
|
|
689
|
+
.orderBy("ranAt", "asc").orderBy("version", "asc"), dialect);
|
|
690
|
+
var res = await xdb.query(histQ.sql, histQ.params);
|
|
598
691
|
var out = [];
|
|
599
692
|
var rows = (res && res.rows) || [];
|
|
600
693
|
for (var i = 0; i < rows.length; i++) {
|
|
@@ -653,7 +746,16 @@ function create(opts) {
|
|
|
653
746
|
module.exports = {
|
|
654
747
|
create: create,
|
|
655
748
|
ExternalDbMigrateError: ExternalDbMigrateError,
|
|
656
|
-
TRACKING_TABLE: TRACKING_TABLE,
|
|
657
|
-
HISTORY_TABLE: HISTORY_TABLE,
|
|
658
749
|
HISTORY_SIGNATURE_FORMAT: HISTORY_SIGNATURE_FORMAT,
|
|
659
750
|
};
|
|
751
|
+
|
|
752
|
+
// The resolved table names are exposed as lazy getters: frameworkSchema's
|
|
753
|
+
// tableName export is not bound while this module evaluates (the
|
|
754
|
+
// external-db require cycle), so resolving at access time gives the
|
|
755
|
+
// configurable-prefix-aware concrete name without a load-order trap.
|
|
756
|
+
Object.defineProperty(module.exports, "TRACKING_TABLE", {
|
|
757
|
+
enumerable: true, get: function () { return _trackingTable(); },
|
|
758
|
+
});
|
|
759
|
+
Object.defineProperty(module.exports, "HISTORY_TABLE", {
|
|
760
|
+
enumerable: true, get: function () { return _historyTable(); },
|
|
761
|
+
});
|