@blamejs/blamejs-shop 0.5.12 → 0.5.13
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 +632 -416
- package/lib/vendor/blamejs/.clusterfuzzlite/Dockerfile +21 -10
- package/lib/vendor/blamejs/.clusterfuzzlite/build.sh +30 -9
- package/lib/vendor/blamejs/.github/dependabot.yml +8 -0
- package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +7 -2
- package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +7 -2
- package/lib/vendor/blamejs/.github/workflows/ci.yml +21 -21
- package/lib/vendor/blamejs/.github/workflows/codeql.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +4 -4
- package/lib/vendor/blamejs/.github/workflows/release-container.yml +7 -7
- package/lib/vendor/blamejs/.github/workflows/scorecard.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
- package/lib/vendor/blamejs/.gitignore +2 -0
- package/lib/vendor/blamejs/CHANGELOG.md +122 -0
- package/lib/vendor/blamejs/NOTICE +26 -1
- package/lib/vendor/blamejs/SECURITY.md +1 -1
- package/lib/vendor/blamejs/api-snapshot.json +207 -5
- package/lib/vendor/blamejs/docker/keycloak/realm-blamejs-test.json +29 -0
- package/lib/vendor/blamejs/examples/wiki/DEPLOY.md +1 -0
- package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +31 -0
- package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +109 -0
- package/lib/vendor/blamejs/examples/wiki/nginx.conf +106 -0
- package/lib/vendor/blamejs/examples/wiki/package-lock.json +1 -1
- package/lib/vendor/blamejs/examples/wiki/test/e2e.js +92 -0
- package/lib/vendor/blamejs/fuzz/asn1-der.fuzz.js +28 -0
- package/lib/vendor/blamejs/fuzz/cms-codec.fuzz.js +17 -0
- package/lib/vendor/blamejs/fuzz/link-header.fuzz.js +18 -0
- package/lib/vendor/blamejs/index.js +6 -0
- package/lib/vendor/blamejs/lib/a2a.js +4 -4
- package/lib/vendor/blamejs/lib/agent-idempotency.js +18 -2
- package/lib/vendor/blamejs/lib/agent-saga.js +36 -8
- package/lib/vendor/blamejs/lib/agent-snapshot.js +63 -6
- package/lib/vendor/blamejs/lib/app-shutdown.js +23 -20
- package/lib/vendor/blamejs/lib/archive-read.js +8 -0
- package/lib/vendor/blamejs/lib/archive-tar.js +12 -2
- package/lib/vendor/blamejs/lib/arg-parser.js +49 -5
- package/lib/vendor/blamejs/lib/asn1-der.js +12 -0
- package/lib/vendor/blamejs/lib/audit-sign.js +47 -1
- package/lib/vendor/blamejs/lib/audit.js +71 -8
- package/lib/vendor/blamejs/lib/auth/ciba.js +14 -2
- package/lib/vendor/blamejs/lib/auth/fido-mds3.js +58 -47
- package/lib/vendor/blamejs/lib/auth/jwt.js +34 -0
- package/lib/vendor/blamejs/lib/auth/oauth.js +90 -13
- package/lib/vendor/blamejs/lib/auth/oid4vci.js +20 -17
- package/lib/vendor/blamejs/lib/auth/openid-federation.js +214 -23
- package/lib/vendor/blamejs/lib/auth/saml.js +38 -20
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +10 -4
- package/lib/vendor/blamejs/lib/backup/bundle.js +13 -3
- package/lib/vendor/blamejs/lib/backup/index.js +16 -5
- package/lib/vendor/blamejs/lib/backup/manifest.js +18 -5
- package/lib/vendor/blamejs/lib/base32.js +21 -0
- package/lib/vendor/blamejs/lib/break-glass.js +19 -10
- package/lib/vendor/blamejs/lib/bundler.js +5 -1
- package/lib/vendor/blamejs/lib/cache-status.js +3 -7
- package/lib/vendor/blamejs/lib/calendar.js +21 -1
- package/lib/vendor/blamejs/lib/cbor.js +12 -1
- package/lib/vendor/blamejs/lib/cert.js +29 -11
- package/lib/vendor/blamejs/lib/cli.js +94 -24
- package/lib/vendor/blamejs/lib/cloud-events.js +2 -2
- package/lib/vendor/blamejs/lib/cluster-provider-db.js +13 -3
- package/lib/vendor/blamejs/lib/codepoint-class.js +85 -0
- package/lib/vendor/blamejs/lib/compliance-ai-act-prohibited.js +8 -4
- package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +19 -4
- package/lib/vendor/blamejs/lib/compliance-ai-act.js +6 -8
- package/lib/vendor/blamejs/lib/content-credentials.js +1 -1
- package/lib/vendor/blamejs/lib/content-digest.js +2 -1
- package/lib/vendor/blamejs/lib/cookies.js +13 -3
- package/lib/vendor/blamejs/lib/cose.js +31 -16
- package/lib/vendor/blamejs/lib/crypto-field.js +32 -0
- package/lib/vendor/blamejs/lib/crypto-oprf.js +11 -2
- package/lib/vendor/blamejs/lib/crypto-xwing.js +22 -4
- package/lib/vendor/blamejs/lib/crypto.js +314 -19
- package/lib/vendor/blamejs/lib/csp.js +11 -3
- package/lib/vendor/blamejs/lib/daemon.js +270 -24
- package/lib/vendor/blamejs/lib/dark-patterns.js +5 -2
- package/lib/vendor/blamejs/lib/db-declare-view.js +2 -2
- package/lib/vendor/blamejs/lib/db-query.js +34 -7
- package/lib/vendor/blamejs/lib/db.js +18 -6
- package/lib/vendor/blamejs/lib/dbsc.js +17 -0
- package/lib/vendor/blamejs/lib/dev.js +21 -2
- package/lib/vendor/blamejs/lib/dsr.js +157 -102
- package/lib/vendor/blamejs/lib/external-db.js +41 -2
- package/lib/vendor/blamejs/lib/file-upload.js +25 -7
- package/lib/vendor/blamejs/lib/flag-providers.js +27 -15
- package/lib/vendor/blamejs/lib/forms.js +113 -27
- package/lib/vendor/blamejs/lib/gate-contract.js +23 -10
- package/lib/vendor/blamejs/lib/gdpr-ropa.js +8 -1
- package/lib/vendor/blamejs/lib/guard-agent-registry.js +1 -1
- package/lib/vendor/blamejs/lib/guard-archive.js +2 -2
- package/lib/vendor/blamejs/lib/guard-cidr.js +27 -1
- package/lib/vendor/blamejs/lib/guard-graphql.js +30 -11
- package/lib/vendor/blamejs/lib/guard-html.js +26 -53
- package/lib/vendor/blamejs/lib/guard-image.js +24 -5
- package/lib/vendor/blamejs/lib/guard-imap-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-jmap.js +19 -3
- package/lib/vendor/blamejs/lib/guard-jwt.js +18 -2
- package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -2
- package/lib/vendor/blamejs/lib/guard-managesieve-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-markdown.js +11 -24
- package/lib/vendor/blamejs/lib/guard-pdf.js +18 -2
- package/lib/vendor/blamejs/lib/guard-pop3-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-regex.js +8 -5
- package/lib/vendor/blamejs/lib/guard-svg.js +31 -32
- package/lib/vendor/blamejs/lib/guard-time.js +1 -1
- package/lib/vendor/blamejs/lib/guard-uuid.js +2 -2
- package/lib/vendor/blamejs/lib/html-balance.js +3 -3
- package/lib/vendor/blamejs/lib/http-client-cache.js +82 -4
- package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +16 -1
- package/lib/vendor/blamejs/lib/http-client.js +39 -7
- package/lib/vendor/blamejs/lib/http-message-signature.js +35 -1
- package/lib/vendor/blamejs/lib/i18n-messageformat.js +31 -6
- package/lib/vendor/blamejs/lib/i18n.js +35 -21
- package/lib/vendor/blamejs/lib/incident-report.js +8 -1
- package/lib/vendor/blamejs/lib/ip-utils.js +11 -1
- package/lib/vendor/blamejs/lib/json-path.js +23 -1
- package/lib/vendor/blamejs/lib/jwk.js +20 -3
- package/lib/vendor/blamejs/lib/link-header.js +2 -1
- package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +5 -1
- package/lib/vendor/blamejs/lib/log-stream-otlp.js +5 -1
- package/lib/vendor/blamejs/lib/log-stream.js +8 -3
- package/lib/vendor/blamejs/lib/mail-auth.js +123 -22
- package/lib/vendor/blamejs/lib/mail-bimi.js +1 -1
- package/lib/vendor/blamejs/lib/mail-bounce.js +8 -0
- package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +46 -10
- package/lib/vendor/blamejs/lib/mail-dav.js +22 -3
- package/lib/vendor/blamejs/lib/mail-dkim.js +96 -30
- package/lib/vendor/blamejs/lib/mail-helo.js +6 -1
- package/lib/vendor/blamejs/lib/mail-scan.js +23 -16
- package/lib/vendor/blamejs/lib/mail-send-deliver.js +34 -8
- package/lib/vendor/blamejs/lib/mail-server-imap.js +3 -4
- package/lib/vendor/blamejs/lib/mail-server-managesieve.js +7 -11
- package/lib/vendor/blamejs/lib/mail-server-mx.js +93 -7
- package/lib/vendor/blamejs/lib/mail-server-registry.js +8 -2
- package/lib/vendor/blamejs/lib/mail.js +15 -5
- package/lib/vendor/blamejs/lib/metrics.js +268 -63
- package/lib/vendor/blamejs/lib/middleware/age-gate.js +7 -1
- package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/body-parser.js +19 -4
- package/lib/vendor/blamejs/lib/middleware/bot-guard.js +5 -9
- package/lib/vendor/blamejs/lib/middleware/csp-report.js +40 -8
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +24 -10
- package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -5
- package/lib/vendor/blamejs/lib/middleware/index.js +6 -1
- package/lib/vendor/blamejs/lib/middleware/nel.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +12 -1
- package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/scim-server.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/tus-upload.js +6 -2
- package/lib/vendor/blamejs/lib/mtls-ca.js +18 -2
- package/lib/vendor/blamejs/lib/network-dns-resolver.js +11 -1
- package/lib/vendor/blamejs/lib/network-dns.js +21 -2
- package/lib/vendor/blamejs/lib/network-tls.js +69 -7
- package/lib/vendor/blamejs/lib/nonce-store.js +9 -1
- package/lib/vendor/blamejs/lib/object-store/gcs.js +7 -0
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +31 -0
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +1 -1
- package/lib/vendor/blamejs/lib/outbox.js +1 -1
- package/lib/vendor/blamejs/lib/parsers/safe-ini.js +9 -1
- package/lib/vendor/blamejs/lib/parsers/safe-toml.js +10 -1
- package/lib/vendor/blamejs/lib/permissions.js +6 -3
- package/lib/vendor/blamejs/lib/pid-probe.js +55 -0
- package/lib/vendor/blamejs/lib/pqc-agent.js +8 -1
- package/lib/vendor/blamejs/lib/pqc-software.js +3 -3
- package/lib/vendor/blamejs/lib/pubsub.js +20 -9
- package/lib/vendor/blamejs/lib/queue-local.js +8 -1
- package/lib/vendor/blamejs/lib/queue-redis.js +5 -0
- package/lib/vendor/blamejs/lib/redact.js +54 -0
- package/lib/vendor/blamejs/lib/restore-bundle.js +10 -2
- package/lib/vendor/blamejs/lib/restore.js +19 -0
- package/lib/vendor/blamejs/lib/retention.js +12 -4
- package/lib/vendor/blamejs/lib/router.js +60 -6
- package/lib/vendor/blamejs/lib/safe-buffer.js +69 -0
- package/lib/vendor/blamejs/lib/safe-decompress.js +8 -2
- package/lib/vendor/blamejs/lib/safe-dns.js +25 -20
- package/lib/vendor/blamejs/lib/safe-ical.js +7 -3
- package/lib/vendor/blamejs/lib/safe-mime.js +12 -1
- package/lib/vendor/blamejs/lib/safe-object.js +80 -0
- package/lib/vendor/blamejs/lib/safe-path.js +52 -4
- package/lib/vendor/blamejs/lib/safe-redirect.js +10 -2
- package/lib/vendor/blamejs/lib/safe-schema.js +4 -1
- package/lib/vendor/blamejs/lib/safe-sieve.js +33 -1
- package/lib/vendor/blamejs/lib/safe-sql.js +88 -0
- package/lib/vendor/blamejs/lib/safe-vcard.js +7 -3
- package/lib/vendor/blamejs/lib/scheduler.js +8 -1
- package/lib/vendor/blamejs/lib/security-assert.js +6 -6
- package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +74 -27
- package/lib/vendor/blamejs/lib/self-update.js +517 -87
- package/lib/vendor/blamejs/lib/server-timing.js +2 -4
- package/lib/vendor/blamejs/lib/session.js +34 -12
- package/lib/vendor/blamejs/lib/sql.js +15 -1
- package/lib/vendor/blamejs/lib/ssrf-guard.js +52 -0
- package/lib/vendor/blamejs/lib/static.js +55 -13
- package/lib/vendor/blamejs/lib/storage.js +8 -2
- package/lib/vendor/blamejs/lib/subject.js +6 -1
- package/lib/vendor/blamejs/lib/tenant-quota.js +52 -13
- package/lib/vendor/blamejs/lib/tls-exporter.js +3 -3
- package/lib/vendor/blamejs/lib/tsa.js +34 -13
- package/lib/vendor/blamejs/lib/uri-template.js +8 -1
- package/lib/vendor/blamejs/lib/vault/index.js +13 -0
- package/lib/vendor/blamejs/lib/vc.js +44 -5
- package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +26 -26
- package/lib/vendor/blamejs/lib/vendor/noble-ciphers.cjs +792 -1
- package/lib/vendor/blamejs/lib/vendor/noble-curves.cjs +3443 -1
- package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +2737 -1
- package/lib/vendor/blamejs/lib/vendor/pki.cjs +39550 -13
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +55 -53
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5551 -5554
- package/lib/vendor/blamejs/lib/vendor/simplewebauthn-server.cjs +22459 -32
- package/lib/vendor/blamejs/lib/watcher.js +89 -17
- package/lib/vendor/blamejs/lib/webhook-dispatcher.js +25 -3
- package/lib/vendor/blamejs/lib/webhook.js +12 -2
- package/lib/vendor/blamejs/lib/ws-client.js +32 -1
- package/lib/vendor/blamejs/lib/xml-c14n.js +29 -1
- package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile +1 -1
- package/lib/vendor/blamejs/package-lock.json +2 -2
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.16.x.json +1462 -0
- package/lib/vendor/blamejs/release-notes/v0.17.0.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.1.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.10.json +30 -0
- package/lib/vendor/blamejs/release-notes/v0.17.11.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.17.12.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.13.json +77 -0
- package/lib/vendor/blamejs/release-notes/v0.17.14.json +40 -0
- package/lib/vendor/blamejs/release-notes/v0.17.15.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.16.json +27 -0
- package/lib/vendor/blamejs/release-notes/v0.17.17.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.18.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.19.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.2.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.20.json +43 -0
- package/lib/vendor/blamejs/release-notes/v0.17.21.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.22.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.3.json +43 -0
- package/lib/vendor/blamejs/release-notes/v0.17.4.json +35 -0
- package/lib/vendor/blamejs/release-notes/v0.17.5.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.6.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.7.json +35 -0
- package/lib/vendor/blamejs/release-notes/v0.17.8.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.17.9.json +26 -0
- package/lib/vendor/blamejs/scripts/validate-source-comment-blocks.js +4 -0
- package/lib/vendor/blamejs/scripts/vendor-update.sh +293 -9
- package/lib/vendor/blamejs/socket.yml +94 -0
- package/lib/vendor/blamejs/test/00-primitives.js +605 -0
- package/lib/vendor/blamejs/test/helpers/drivers.js +12 -9
- package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +90 -1
- package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +122 -1
- package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +30 -0
- package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +29 -0
- package/lib/vendor/blamejs/test/integration/dsr-cluster-mysql.test.js +479 -0
- package/lib/vendor/blamejs/test/integration/dsr-cluster-pg.test.js +487 -0
- package/lib/vendor/blamejs/test/integration/federation-auth.test.js +313 -5
- package/lib/vendor/blamejs/test/integration/mail-dkim.test.js +80 -0
- package/lib/vendor/blamejs/test/integration/openid-federation-chain.test.js +275 -0
- package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +96 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +401 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/acme.test.js +1649 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +33 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-saga.test.js +60 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/api-encrypt.test.js +891 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/app-shutdown.test.js +128 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-adapters.test.js +271 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-read.test.js +628 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-tar-read.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-wrap.test.js +227 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/arg-parser.test.js +15 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file.test.js +114 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +141 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-tools.test.js +624 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit.test.js +769 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +436 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth.test.js +1697 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oid4vp.test.js +495 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-password.test.js +500 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml.test.js +1809 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-status-list.test.js +243 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-index.test.js +2226 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +183 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/base32.test.js +105 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +693 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cache.test.js +603 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/calendar.test.js +557 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/case-insensitive-security-token-guard.test.js +214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cbor.test.js +25 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cert.test.js +843 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/ciba-authreqid-binding.test.js +77 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/ciba.test.js +866 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-erase.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli.test.js +2790 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cluster-lease-renewal-ttl.test.js +114 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cluster.test.js +1032 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cms-codec.test.js +575 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +739 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +8 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +194 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-lifecycle-proto-key.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +254 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +613 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/cookies.test.js +140 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cose.test.js +407 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-adversarial.test.js +352 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field.test.js +575 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-files-parallel.test.js +10 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +24 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-oprf.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-spki-pin.test.js +183 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-xwing.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto.test.js +345 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-report.test.js +58 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csv.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +459 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/dark-patterns.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-query.test.js +1019 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db.test.js +1621 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ddl-change-control.test.js +462 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/dnssec.test.js +323 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-verify.test.js +562 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +901 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/dual-control.test.js +249 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +561 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db.test.js +1214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fal.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fedcm-dbsc.test.js +46 -20
- package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +147 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +907 -38
- package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +29 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/file-upload.test.js +1135 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/forms.test.js +747 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract.test.js +1855 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gdpr-ropa.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-archive.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-auth.test.js +117 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-cidr.test.js +151 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-domain.test.js +422 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +424 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{guard-gate-disposition-coverage.test.js → guard-gate-disposition.test.js} +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-graphql.test.js +340 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +29 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-idempotency-key.test.js +28 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +519 -45
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jmap.test.js +51 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jsonpath.test.js +66 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jwt.test.js +436 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +25 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +16 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-mime.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-oauth.test.js +140 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-regex.test.js +99 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-shell.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{guard-sql-coverage.test.js → guard-sql.test.js} +3 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-template.test.js +71 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-time.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-uuid.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/html-balance.test.js +38 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache-authorization.test.js +347 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +908 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client.test.js +2874 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-message-signature.test.js +643 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n-messageformat.test.js +38 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +1153 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +494 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jsdoc-example-execution.test.js +177 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/json-path.test.js +103 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/json-schema.test.js +214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jwk.test.js +41 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +276 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/keychain.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log-stream.test.js +241 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log.test.js +106 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +441 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +2136 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-bimi.test.js +759 -12
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-bounce.test.js +811 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp-experimental.test.js +401 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +751 -8
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +864 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto.test.js +110 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dav.test.js +830 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy.test.js +635 -86
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +818 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-helo.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-scan.test.js +199 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-send-deliver.test.js +686 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +778 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +1438 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-managesieve.test.js +449 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +773 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-pop3.test.js +623 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-rate-limit.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-registry.test.js +13 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-submission.test.js +877 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-sieve.test.js +326 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store-fts.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +242 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail.test.js +1596 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mcp.test.js +440 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics-snapshot.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics.test.js +1230 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-assetlinks.test.js +113 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-body-parser.test.js +1169 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-bot-disclose.test.js +123 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-cookies.test.js +108 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-gpc.test.js +121 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-headers.test.js +163 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-host-allowlist.test.js +154 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-require-content-type.test.js +127 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{middleware-tus-upload-coverage.test.js → middleware-tus-upload.test.js} +45 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-web-app-manifest.test.js +132 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-crl-fingerprint-only.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns-resolver.test.js +65 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +1727 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/network-nts.test.js +699 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy.test.js +1181 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +1876 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/network.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-enforce-replay-nonboolean.test.js +81 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ntp-check.test.js +122 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +378 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/oid4vci.test.js +1016 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/openid-federation.test.js +946 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/outbox.test.js +818 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/own-property-membership-guards.test.js +109 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-safe-toml.test.js +543 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{parsers-safe-yaml-coverage.test.js → parsers-safe-yaml.test.js} +2 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/passkey.test.js +649 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/permissions.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +22 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pubsub.test.js +295 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue-flow-repeat.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-xff-spoofing.test.js +34 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/redact.test.js +1031 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/require-bound-key.test.js +401 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/restore-empty-manifest-wipe.test.js +154 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/retention.test.js +600 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-host-path-injection.test.js +231 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-tls0rtt.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router.test.js +1277 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-async.test.js +133 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +14 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-decompress.test.js +28 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-dns.test.js +245 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-ical.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-ini.test.js +376 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-json.test.js +175 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-mime.test.js +518 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-object.test.js +62 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-schema.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-sql.test.js +142 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-url.test.js +112 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-vcard.test.js +26 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scheduler.test.js +157 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scim-server.test.js +396 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +930 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/security-assert.test.js +755 -82
- package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +1053 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +200 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-strict-binding-missing-failclosed.test.js +110 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +636 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql-offset-without-limit.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +1190 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +850 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/storage-presigned-url.test.js +146 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/storage.test.js +621 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/subject.test.js +47 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/template.test.js +582 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +587 -25
- package/lib/vendor/blamejs/test/layer-0-primitives/time.test.js +11 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tsa.test.js +524 -63
- package/lib/vendor/blamejs/test/layer-0-primitives/uri-template.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault-rotate.test.js +866 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault.test.js +74 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vc.test.js +215 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +550 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +388 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +262 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/websocket.test.js +1294 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +629 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/xml-c14n-attr-normalization.test.js +164 -0
- package/lib/vendor/blamejs/test/smoke.js +2 -0
- package/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.16.0.json +0 -44
- package/lib/vendor/blamejs/release-notes/v0.16.1.json +0 -36
- package/lib/vendor/blamejs/release-notes/v0.16.2.json +0 -71
- package/lib/vendor/blamejs/release-notes/v0.16.3.json +0 -71
- package/lib/vendor/blamejs/test/layer-0-primitives/acme-coverage.test.js +0 -441
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth-coverage.test.js +0 -482
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml-coverage.test.js +0 -671
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-index-coverage.test.js +0 -690
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-coverage.test.js +0 -238
- package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials-coverage.test.js +0 -319
- package/lib/vendor/blamejs/test/layer-0-primitives/keychain-coverage.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth-coverage.test.js +0 -437
- package/lib/vendor/blamejs/test/layer-0-primitives/mcp-coverage.test.js +0 -443
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics-coverage.test.js +0 -395
- package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy-coverage.test.js +0 -565
- package/lib/vendor/blamejs/test/layer-0-primitives/router-coverage.test.js +0 -592
- package/lib/vendor/blamejs/test/layer-0-primitives/sql-coverage.test.js +0 -422
- package/lib/vendor/blamejs/test/layer-0-primitives/test-coverage.test.js +0 -573
|
@@ -0,0 +1,575 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) blamejs contributors
|
|
3
|
+
"use strict";
|
|
4
|
+
/**
|
|
5
|
+
* b.cryptoField — sealed-column accessors + the seal / unseal seam.
|
|
6
|
+
*
|
|
7
|
+
* getSealedFields is the sealed-column accessor storage backends consult to
|
|
8
|
+
* know which columns to wrap in vault.seal on write and vault.unseal on read.
|
|
9
|
+
*
|
|
10
|
+
* The seal/unseal seam tests drive the adversarial + defensive branches an
|
|
11
|
+
* operator's data actually exercises: an empty-string sealed field (the three
|
|
12
|
+
* envelope branches — plain / aad / K_row — must agree, never crash), the
|
|
13
|
+
* type-fidelity codec (Buffer / object / array preserved through a sealed
|
|
14
|
+
* column), the AAD cross-row / cross-column / cross-table copy-protection (a
|
|
15
|
+
* relocated or tampered cell must be refused, not surfaced), and the
|
|
16
|
+
* config-time refusals when the rowId term of the AAD binding is missing.
|
|
17
|
+
*
|
|
18
|
+
* Uses uniquely-named tables (no clearForTest) so the shared per-table schema
|
|
19
|
+
* registry other smoke tests populate is left intact.
|
|
20
|
+
*
|
|
21
|
+
* Run standalone: `node test/layer-0-primitives/crypto-field.test.js`
|
|
22
|
+
* Or via smoke: `node test/smoke.js`
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
var helpers = require("../helpers");
|
|
26
|
+
var b = helpers.b;
|
|
27
|
+
var check = helpers.check;
|
|
28
|
+
var fs = require("fs");
|
|
29
|
+
var os = require("os");
|
|
30
|
+
var path = require("path");
|
|
31
|
+
var { setupTestDb, teardownTestDb } = require("../helpers/db");
|
|
32
|
+
|
|
33
|
+
// Capture-or-value helper: returns { ok:true, value } when fn() returns, or
|
|
34
|
+
// { ok:false, err } when it throws — so a check can assert BOTH "did not throw"
|
|
35
|
+
// and "returned the right value" in one stable expression (a raw throw would
|
|
36
|
+
// otherwise abort the whole run before the assertion counts).
|
|
37
|
+
function _try(fn) {
|
|
38
|
+
try { return { ok: true, value: fn() }; }
|
|
39
|
+
catch (e) { return { ok: false, err: e }; }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ---- getSealedFields accessor ----
|
|
43
|
+
|
|
44
|
+
function testReturnsDeclaredSealedFields() {
|
|
45
|
+
b.cryptoField.registerTable("cf_getsealed_patients", {
|
|
46
|
+
sealedFields: ["ssn", "diagnosis"],
|
|
47
|
+
derivedHashes: {
|
|
48
|
+
ssnHash: { from: "ssn", normalize: function (s) { return String(s).replace(/-/g, ""); } },
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
var fields = b.cryptoField.getSealedFields("cf_getsealed_patients");
|
|
52
|
+
check("getSealedFields returns an array", Array.isArray(fields));
|
|
53
|
+
check("getSealedFields returns exactly the declared sealed columns",
|
|
54
|
+
fields.length === 2 && fields[0] === "ssn" && fields[1] === "diagnosis");
|
|
55
|
+
|
|
56
|
+
// Agrees with the fuller getSchema() record's sealedFields.
|
|
57
|
+
var schema = b.cryptoField.getSchema("cf_getsealed_patients");
|
|
58
|
+
check("getSealedFields agrees with getSchema().sealedFields",
|
|
59
|
+
JSON.stringify(schema.sealedFields) === JSON.stringify(fields));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function testUnregisteredTableIsEmpty() {
|
|
63
|
+
// A table that was never registered → empty array (not null/undefined),
|
|
64
|
+
// so a backend can iterate the result unconditionally.
|
|
65
|
+
var fields = b.cryptoField.getSealedFields("cf_getsealed_never_registered");
|
|
66
|
+
check("getSealedFields returns [] for an unregistered table",
|
|
67
|
+
Array.isArray(fields) && fields.length === 0);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function testTableWithNoSealedColumns() {
|
|
71
|
+
// A registered table that seals nothing → empty array.
|
|
72
|
+
b.cryptoField.registerTable("cf_getsealed_public", { sealedFields: [] });
|
|
73
|
+
var fields = b.cryptoField.getSealedFields("cf_getsealed_public");
|
|
74
|
+
check("getSealedFields returns [] for a table sealing no columns",
|
|
75
|
+
Array.isArray(fields) && fields.length === 0);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function testPreservesDeclarationOrder() {
|
|
79
|
+
// The accessor preserves the operator's declared column order, which the
|
|
80
|
+
// seal/unseal call sites depend on for stable column mapping.
|
|
81
|
+
b.cryptoField.registerTable("cf_getsealed_order", {
|
|
82
|
+
sealedFields: ["zeta", "alpha", "mu"],
|
|
83
|
+
});
|
|
84
|
+
var fields = b.cryptoField.getSealedFields("cf_getsealed_order");
|
|
85
|
+
check("getSealedFields preserves declared column order",
|
|
86
|
+
fields.join(",") === "zeta,alpha,mu");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ---- seal / unseal seam (vault-backed, no db) ----
|
|
90
|
+
|
|
91
|
+
async function testSealUnsealSeams() {
|
|
92
|
+
var tmp = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-cf-seam-"));
|
|
93
|
+
try {
|
|
94
|
+
try { b.vault._resetForTest(); } catch (_e) { /* fresh init below */ }
|
|
95
|
+
await b.vault.init({ dataDir: tmp, mode: "plaintext" });
|
|
96
|
+
b.cryptoField.clearRateCapForTest();
|
|
97
|
+
|
|
98
|
+
// --- empty-string sealed field: sealed as a real envelope, tamper-evident ---
|
|
99
|
+
// vault.aad.seal REFUSES empty plaintext, so a naive skip of "" would store a
|
|
100
|
+
// bare plaintext empty string in the sealed column -- and unsealRow's falsy
|
|
101
|
+
// skip would then accept a ciphertext a DB-write attacker downgraded to "" with
|
|
102
|
+
// no AEAD failure. Instead _encodeTyped("") -> a non-empty typed marker, so a
|
|
103
|
+
// sealed empty string is a real authenticated envelope that round-trips to ""
|
|
104
|
+
// and detects a downgrade to "".
|
|
105
|
+
b.cryptoField.registerTable("cf_seam_aad_empty", {
|
|
106
|
+
aad: true, sealedFields: ["secret"], rowIdField: "id",
|
|
107
|
+
});
|
|
108
|
+
var aadSealedEmpty = b.cryptoField.sealRow("cf_seam_aad_empty", { id: "r1", secret: "" });
|
|
109
|
+
check("aad table: empty-string sealed field is a non-empty envelope (not bare plaintext)",
|
|
110
|
+
typeof aadSealedEmpty.secret === "string" && aadSealedEmpty.secret.length > 0);
|
|
111
|
+
var aadEmpty = _try(function () {
|
|
112
|
+
return b.cryptoField.unsealRow("cf_seam_aad_empty",
|
|
113
|
+
Object.assign({}, aadSealedEmpty), "seam").secret;
|
|
114
|
+
});
|
|
115
|
+
check("aad table: empty-string sealed field round-trips to empty (no throw)",
|
|
116
|
+
aadEmpty.ok === true && aadEmpty.value === "");
|
|
117
|
+
// Downgrade tamper: a DB-write attacker replaces the ciphertext with "".
|
|
118
|
+
// unsealRow must fail closed (null the cell), NOT accept "" as a valid value.
|
|
119
|
+
var aadDowngrade = b.cryptoField.unsealRow("cf_seam_aad_empty",
|
|
120
|
+
Object.assign({}, aadSealedEmpty, { secret: "" }), "seam");
|
|
121
|
+
check("aad table: a ciphertext downgraded to empty fails closed (nulled, not accepted)",
|
|
122
|
+
aadDowngrade.secret === null);
|
|
123
|
+
|
|
124
|
+
// Plain + K_row branches agree on the same empty-string round-trip.
|
|
125
|
+
b.cryptoField.registerTable("cf_seam_plain_empty", { sealedFields: ["secret"] });
|
|
126
|
+
var plainEmpty = _try(function () {
|
|
127
|
+
var sealedEmpty = b.cryptoField.sealRow("cf_seam_plain_empty", { secret: "" });
|
|
128
|
+
return b.cryptoField.unsealRow("cf_seam_plain_empty", sealedEmpty, "seam").secret;
|
|
129
|
+
});
|
|
130
|
+
check("plain table: an empty-string sealed field round-trips to '' (no throw)",
|
|
131
|
+
plainEmpty.ok === true && plainEmpty.value === "");
|
|
132
|
+
|
|
133
|
+
// A null / undefined sealed field is still skipped (pre-existing contract).
|
|
134
|
+
var nullField = b.cryptoField.sealRow("cf_seam_plain_empty", { secret: null });
|
|
135
|
+
check("a null sealed field is left null (skipped, not sealed)", nullField.secret === null);
|
|
136
|
+
|
|
137
|
+
// --- type-fidelity codec: Buffer / object / array / number / boolean ---
|
|
138
|
+
b.cryptoField.registerTable("cf_seam_types", {
|
|
139
|
+
sealedFields: ["blob", "obj", "arr", "num", "flag", "selfesc"],
|
|
140
|
+
});
|
|
141
|
+
var blob = Buffer.from([0, 1, 2, 250, 255]); // non-ASCII bytes, no literals
|
|
142
|
+
var sealedTypes = b.cryptoField.sealRow("cf_seam_types", {
|
|
143
|
+
blob: blob,
|
|
144
|
+
obj: { a: 1, b: [2, 3], s: "x" },
|
|
145
|
+
arr: [1, "two", 3],
|
|
146
|
+
num: 42,
|
|
147
|
+
flag: false,
|
|
148
|
+
selfesc: "\x00bjsv1:evil", // a string that itself begins with the codec sentinel
|
|
149
|
+
});
|
|
150
|
+
check("a Buffer sealed field is stored as a vault: envelope",
|
|
151
|
+
typeof sealedTypes.blob === "string" && sealedTypes.blob.indexOf("vault:") === 0);
|
|
152
|
+
var readTypes = b.cryptoField.unsealRow("cf_seam_types", Object.assign({}, sealedTypes), "seam");
|
|
153
|
+
check("a Buffer round-trips byte-for-byte through a sealed column",
|
|
154
|
+
Buffer.isBuffer(readTypes.blob) && readTypes.blob.equals(blob));
|
|
155
|
+
check("an object round-trips through a sealed column",
|
|
156
|
+
readTypes.obj && JSON.stringify(readTypes.obj) === JSON.stringify({ a: 1, b: [2, 3], s: "x" }));
|
|
157
|
+
check("an array round-trips through a sealed column",
|
|
158
|
+
Array.isArray(readTypes.arr) && JSON.stringify(readTypes.arr) === JSON.stringify([1, "two", 3]));
|
|
159
|
+
check("a number keeps the String() contract through a sealed column", readTypes.num === "42");
|
|
160
|
+
check("a boolean keeps the String() contract through a sealed column", readTypes.flag === "false");
|
|
161
|
+
check("a string that itself begins with the codec sentinel round-trips verbatim (self-escape)",
|
|
162
|
+
readTypes.selfesc === "\x00bjsv1:evil");
|
|
163
|
+
|
|
164
|
+
// --- AAD copy-protection: cross-row / cross-column / cross-table refusal ---
|
|
165
|
+
// The confidentiality guarantee: a cell AEAD-bound to (table,row,column)
|
|
166
|
+
// can NEVER be unsealed under a different context. A seam that surfaced a
|
|
167
|
+
// relocated cell would be a copy-paste confidentiality break.
|
|
168
|
+
b.cryptoField.registerTable("cf_seam_ctx", {
|
|
169
|
+
aad: true, sealedFields: ["c1", "c2"], rowIdField: "id",
|
|
170
|
+
});
|
|
171
|
+
b.cryptoField.registerTable("cf_seam_ctx_other", {
|
|
172
|
+
aad: true, sealedFields: ["c1"], rowIdField: "id",
|
|
173
|
+
});
|
|
174
|
+
var sealed = b.cryptoField.sealRow("cf_seam_ctx", { id: "rowA", c1: "secret-c1", c2: "secret-c2" });
|
|
175
|
+
check("an aad cell is stored as a vault.aad: envelope",
|
|
176
|
+
typeof sealed.c1 === "string" && sealed.c1.indexOf("vault.aad:") === 0);
|
|
177
|
+
|
|
178
|
+
var okRead = b.cryptoField.unsealRow("cf_seam_ctx", Object.assign({}, sealed), "seam");
|
|
179
|
+
check("the correct (table,row,column) context decrypts both cells",
|
|
180
|
+
okRead.c1 === "secret-c1" && okRead.c2 === "secret-c2");
|
|
181
|
+
|
|
182
|
+
// Relocate c1's ciphertext into column c2 (same row): AAD column term differs.
|
|
183
|
+
var wrongCol = b.cryptoField.unsealRow("cf_seam_ctx", { id: "rowA", c2: sealed.c1 }, "seam");
|
|
184
|
+
check("a cell relocated to a DIFFERENT column is refused (nulled, never surfaced)",
|
|
185
|
+
wrongCol.c2 === null);
|
|
186
|
+
|
|
187
|
+
// Relocate c1's ciphertext onto a different rowId: AAD rowId term differs.
|
|
188
|
+
var wrongRow = b.cryptoField.unsealRow("cf_seam_ctx", { id: "rowB", c1: sealed.c1 }, "seam");
|
|
189
|
+
check("a cell relocated to a DIFFERENT row is refused (nulled)", wrongRow.c1 === null);
|
|
190
|
+
|
|
191
|
+
// Read the same cell through a DIFFERENT table: AAD table term differs.
|
|
192
|
+
var wrongTable = b.cryptoField.unsealRow("cf_seam_ctx_other", { id: "rowA", c1: sealed.c1 }, "seam");
|
|
193
|
+
check("a cell read through a DIFFERENT table is refused (nulled)", wrongTable.c1 === null);
|
|
194
|
+
|
|
195
|
+
// --- tamper: a single flipped ciphertext char fails AEAD verification ---
|
|
196
|
+
var tamperedCell = sealed.c1.slice(0, -1) + (sealed.c1.slice(-1) === "A" ? "B" : "A");
|
|
197
|
+
var tampered = b.cryptoField.unsealRow("cf_seam_ctx",
|
|
198
|
+
{ id: "rowA", c1: tamperedCell, c2: sealed.c2 }, "seam");
|
|
199
|
+
check("a tampered aad cell fails verification and is nulled (never surfaces plaintext)",
|
|
200
|
+
tampered.c1 === null);
|
|
201
|
+
check("an untampered sibling cell on the same row still decrypts",
|
|
202
|
+
tampered.c2 === "secret-c2");
|
|
203
|
+
|
|
204
|
+
// --- config-time refusals: the rowId term of the AAD binding is required ---
|
|
205
|
+
var aadNoRowId = _try(function () {
|
|
206
|
+
return b.cryptoField.sealRow("cf_seam_ctx", { c1: "x" }); // no id column
|
|
207
|
+
});
|
|
208
|
+
check("sealRow refuses an aad table when the rowId column is missing",
|
|
209
|
+
aadNoRowId.ok === false && aadNoRowId.err &&
|
|
210
|
+
aadNoRowId.err.code === "crypto-field/seal-row-aad-rowid-missing");
|
|
211
|
+
|
|
212
|
+
var kRowNoRowId = _try(function () {
|
|
213
|
+
// K_row seal with no rowId / _id — cannot build the (table,rowId,column) AAD.
|
|
214
|
+
return b.cryptoField.sealRow("cf_seam_plain_empty", { secret: "v" }, { kRow: Buffer.alloc(32) });
|
|
215
|
+
});
|
|
216
|
+
check("sealRow refuses a K_row seal with no rowId",
|
|
217
|
+
kRowNoRowId.ok === false && kRowNoRowId.err &&
|
|
218
|
+
kRowNoRowId.err.code === "crypto-field/seal-row-krow-rowid-missing");
|
|
219
|
+
|
|
220
|
+
b.cryptoField.clearRateCapForTest();
|
|
221
|
+
} finally {
|
|
222
|
+
try { b.vault._resetForTest(); } catch (_e) { /* leave vault state clean for siblings */ }
|
|
223
|
+
try { fs.rmSync(tmp, { recursive: true, force: true }); } catch (_e) { /* best-effort */ }
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// ---- the REAL consumer path: b.db insert/read across envelope types ----
|
|
228
|
+
|
|
229
|
+
async function testConsumerPathEmptyAndKRow() {
|
|
230
|
+
var dir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-cf-seam-db-"));
|
|
231
|
+
try {
|
|
232
|
+
await setupTestDb(dir, [
|
|
233
|
+
{
|
|
234
|
+
name: "cf_seam_aad_db",
|
|
235
|
+
columns: { _id: "TEXT PRIMARY KEY", secret: "TEXT", note: "TEXT" },
|
|
236
|
+
aad: true,
|
|
237
|
+
sealedFields: ["secret", "note"],
|
|
238
|
+
rowIdField: "_id",
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
name: "cf_seam_krow_db",
|
|
242
|
+
columns: { _id: "TEXT PRIMARY KEY", subjectId: "TEXT", ssn: "TEXT" },
|
|
243
|
+
sealedFields: ["ssn"],
|
|
244
|
+
subjectField: "subjectId",
|
|
245
|
+
},
|
|
246
|
+
]);
|
|
247
|
+
b.cryptoField.clearResidencyForTest();
|
|
248
|
+
b.cryptoField.declarePerRowKey("cf_seam_krow_db", { keySize: 32 });
|
|
249
|
+
|
|
250
|
+
// aad table, real write boundary: an empty-string sealed field must not
|
|
251
|
+
// crash the insert (the pre-fix vault.aad.seal("") throw surfaced here).
|
|
252
|
+
var insAad = _try(function () {
|
|
253
|
+
return b.db.from("cf_seam_aad_db").insertOne({ _id: "a1", secret: "", note: "present" });
|
|
254
|
+
});
|
|
255
|
+
check("b.db.insertOne on an aad table does NOT crash on an empty-string sealed field",
|
|
256
|
+
insAad.ok === true);
|
|
257
|
+
if (insAad.ok) {
|
|
258
|
+
var gotA = b.db.from("cf_seam_aad_db").where({ _id: "a1" }).first();
|
|
259
|
+
check("aad-table insert round-trips the empty sealed field to ''", gotA && gotA.secret === "");
|
|
260
|
+
check("aad-table insert round-trips the non-empty sibling sealed field", gotA && gotA.note === "present");
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// per-row-key table, real write boundary: empty-string field round-trips too.
|
|
264
|
+
var insKRow = _try(function () {
|
|
265
|
+
return b.db.from("cf_seam_krow_db").insertOne({ _id: "k1", subjectId: "s1", ssn: "" });
|
|
266
|
+
});
|
|
267
|
+
check("b.db.insertOne on a per-row-key table does NOT crash on an empty-string sealed field",
|
|
268
|
+
insKRow.ok === true);
|
|
269
|
+
if (insKRow.ok) {
|
|
270
|
+
var gotK = b.db.from("cf_seam_krow_db").where({ _id: "k1" }).first();
|
|
271
|
+
check("per-row-key insert round-trips the empty sealed field to ''", gotK && gotK.ssn === "");
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// control: a non-empty aad value is stored as a vault.aad: envelope on disk
|
|
275
|
+
// and round-trips — the empty-string fix does not weaken real sealing.
|
|
276
|
+
b.db.from("cf_seam_aad_db").insertOne({ _id: "a2", secret: "top-secret", note: "n" });
|
|
277
|
+
var rawA2 = b.db.prepare('SELECT "secret" AS s FROM "cf_seam_aad_db" WHERE _id = ?').get("a2");
|
|
278
|
+
check("a non-empty aad sealed value is stored as a vault.aad: envelope on disk",
|
|
279
|
+
rawA2 && typeof rawA2.s === "string" && rawA2.s.indexOf("vault.aad:") === 0);
|
|
280
|
+
var gotA2 = b.db.from("cf_seam_aad_db").where({ _id: "a2" }).first();
|
|
281
|
+
check("a non-empty aad sealed value round-trips through the real read path",
|
|
282
|
+
gotA2 && gotA2.secret === "top-secret");
|
|
283
|
+
} finally {
|
|
284
|
+
try { b.cryptoField.clearResidencyForTest(); } catch (_e) { /* best-effort */ }
|
|
285
|
+
await teardownTestDb(dir);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// ---- accessor / guard branches (no vault needed) ----
|
|
290
|
+
|
|
291
|
+
function testAccessorAndGuardBranches() {
|
|
292
|
+
// isRowSealed — the K_row-prefix router the read path uses to pick the
|
|
293
|
+
// K_row decrypt over the vault-root unseal. A non-string or a plain
|
|
294
|
+
// vault: cell must NOT be routed as row-keyed.
|
|
295
|
+
check("isRowSealed true for a vault.row: cell", b.cryptoField.isRowSealed("vault.row:AAAA") === true);
|
|
296
|
+
check("isRowSealed false for a plain vault: cell", b.cryptoField.isRowSealed("vault:AAAA") === false);
|
|
297
|
+
check("isRowSealed false for null", b.cryptoField.isRowSealed(null) === false);
|
|
298
|
+
check("isRowSealed false for a number", b.cryptoField.isRowSealed(42) === false);
|
|
299
|
+
|
|
300
|
+
// getSchema returns null (not undefined) for an unregistered table so a
|
|
301
|
+
// backend can branch on it directly.
|
|
302
|
+
check("getSchema returns null for an unregistered table",
|
|
303
|
+
b.cryptoField.getSchema("cf_cov_never_registered_schema") === null);
|
|
304
|
+
|
|
305
|
+
// sealRow / unsealRow are no-ops when the row is falsy or the table was
|
|
306
|
+
// never registered — the storage backend calls them unconditionally.
|
|
307
|
+
check("sealRow(null) returns the falsy row unchanged", b.cryptoField.sealRow("cf_cov_x", null) === null);
|
|
308
|
+
check("unsealRow(null) returns the falsy row unchanged", b.cryptoField.unsealRow("cf_cov_x", null) === null);
|
|
309
|
+
var passthruIn = { a: 1, b: "vault:whatever" };
|
|
310
|
+
var sealedPassthru = b.cryptoField.sealRow("cf_cov_unregistered_table_zzz", passthruIn);
|
|
311
|
+
check("sealRow on an unregistered table returns the row unchanged",
|
|
312
|
+
sealedPassthru === passthruIn);
|
|
313
|
+
var unsealPassthru = b.cryptoField.unsealRow("cf_cov_unregistered_table_zzz", passthruIn);
|
|
314
|
+
check("unsealRow on an unregistered table returns the row unchanged",
|
|
315
|
+
unsealPassthru === passthruIn);
|
|
316
|
+
|
|
317
|
+
// applyPosture is a defensive guard: empty / non-string returns null WITHOUT
|
|
318
|
+
// recording a posture (so it can't accidentally arm the erase-vacuum cascade).
|
|
319
|
+
check("applyPosture('') returns null (no-op)", b.cryptoField.applyPosture("") === null);
|
|
320
|
+
check("applyPosture(non-string) returns null (no-op)", b.cryptoField.applyPosture(42) === null);
|
|
321
|
+
var posture = b.cryptoField.getActivePosture();
|
|
322
|
+
check("getActivePosture is read-only (null or a string)",
|
|
323
|
+
posture === null || typeof posture === "string");
|
|
324
|
+
|
|
325
|
+
// registerTable rejects an unknown derived-hash mode at config time so a
|
|
326
|
+
// typo can't silently index under a malformed digest.
|
|
327
|
+
var badMode = _try(function () {
|
|
328
|
+
return b.cryptoField.registerTable("cf_cov_badmode", { derivedHashMode: "md5" });
|
|
329
|
+
});
|
|
330
|
+
check("registerTable throws on an unknown derivedHashMode",
|
|
331
|
+
badMode.ok === false && badMode.err && badMode.err.code === "crypto-field/bad-derived-hash-mode");
|
|
332
|
+
var badColMode = _try(function () {
|
|
333
|
+
return b.cryptoField.registerTable("cf_cov_badcolmode", {
|
|
334
|
+
derivedHashes: { h: { from: "x", mode: "sha1" } },
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
check("registerTable throws on an unknown per-column derived-hash mode",
|
|
338
|
+
badColMode.ok === false && badColMode.err &&
|
|
339
|
+
badColMode.err.code === "crypto-field/bad-derived-hash-col-mode");
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// ---- column-residency write gate (CWE-178 case-insensitivity) ----
|
|
343
|
+
|
|
344
|
+
function testColumnResidencyGate() {
|
|
345
|
+
b.cryptoField.declareColumnResidency("cf_cov_res", {
|
|
346
|
+
columnResidency: { addressLine1: "eu", name: "global" },
|
|
347
|
+
});
|
|
348
|
+
check("getColumnResidency returns the declared map",
|
|
349
|
+
JSON.stringify(b.cryptoField.getColumnResidency("cf_cov_res")) ===
|
|
350
|
+
JSON.stringify({ addressLine1: "eu", name: "global" }));
|
|
351
|
+
check("getColumnResidency returns null for an undeclared table",
|
|
352
|
+
b.cryptoField.getColumnResidency("cf_cov_res_none") === null);
|
|
353
|
+
|
|
354
|
+
// A region-bound column on a mismatched backend is refused with the full
|
|
355
|
+
// want/got refusal shape the storage backend wraps in its own error.
|
|
356
|
+
var refuse = b.cryptoField.assertColumnResidency("cf_cov_res",
|
|
357
|
+
{ id: 1, addressLine1: "10 Rue de Rivoli" }, { backendTag: "us" });
|
|
358
|
+
check("assertColumnResidency refuses an eu column landing on a us backend",
|
|
359
|
+
refuse && refuse.error === "column-residency-mismatch" && refuse.column === "addressLine1" &&
|
|
360
|
+
refuse.want === "eu" && refuse.got === "us");
|
|
361
|
+
|
|
362
|
+
// The matching backend passes.
|
|
363
|
+
check("assertColumnResidency passes an eu column on an eu backend",
|
|
364
|
+
b.cryptoField.assertColumnResidency("cf_cov_res",
|
|
365
|
+
{ id: 1, addressLine1: "10 Rue de Rivoli" }, { backendTag: "eu" }) === null);
|
|
366
|
+
|
|
367
|
+
// A "global" column and an "unrestricted" backend both pass any backend.
|
|
368
|
+
check("assertColumnResidency passes a global column on any backend",
|
|
369
|
+
b.cryptoField.assertColumnResidency("cf_cov_res",
|
|
370
|
+
{ id: 1, name: "Alice" }, { backendTag: "us" }) === null);
|
|
371
|
+
check("assertColumnResidency passes an eu column on an unrestricted backend",
|
|
372
|
+
b.cryptoField.assertColumnResidency("cf_cov_res",
|
|
373
|
+
{ id: 1, addressLine1: "x" }, { backendTag: "unrestricted" }) === null);
|
|
374
|
+
|
|
375
|
+
// CWE-178: a raw-SQL-parsed row can differ in column case; the gate resolves
|
|
376
|
+
// case-insensitively so a differently-cased column cannot skip the check.
|
|
377
|
+
var refuseCase = b.cryptoField.assertColumnResidency("cf_cov_res",
|
|
378
|
+
{ id: 1, ADDRESSLINE1: "10 Rue de Rivoli" }, { backendTag: "us" });
|
|
379
|
+
check("assertColumnResidency resolves the mapped column case-insensitively (CWE-178)",
|
|
380
|
+
refuseCase && refuseCase.error === "column-residency-mismatch" && refuseCase.column === "addressLine1");
|
|
381
|
+
|
|
382
|
+
// A null / absent cell is skipped (nothing to place).
|
|
383
|
+
check("assertColumnResidency skips a null cell",
|
|
384
|
+
b.cryptoField.assertColumnResidency("cf_cov_res",
|
|
385
|
+
{ id: 1, addressLine1: null }, { backendTag: "us" }) === null);
|
|
386
|
+
check("assertColumnResidency returns null for an undeclared table",
|
|
387
|
+
b.cryptoField.assertColumnResidency("cf_cov_res_none", { addressLine1: "x" }, { backendTag: "us" }) === null);
|
|
388
|
+
|
|
389
|
+
// Config-time fail-loud on malformed declarations.
|
|
390
|
+
check("declareColumnResidency throws on an empty table name",
|
|
391
|
+
_try(function () { return b.cryptoField.declareColumnResidency("", { columnResidency: {} }); })
|
|
392
|
+
.err.code === "crypto-field/residency-table-empty");
|
|
393
|
+
check("declareColumnResidency throws when opts is not an object",
|
|
394
|
+
_try(function () { return b.cryptoField.declareColumnResidency("cf_cov_res2", null); })
|
|
395
|
+
.err.code === "crypto-field/residency-opts-not-object");
|
|
396
|
+
check("declareColumnResidency throws when columnResidency is not an object",
|
|
397
|
+
_try(function () { return b.cryptoField.declareColumnResidency("cf_cov_res2", { columnResidency: 5 }); })
|
|
398
|
+
.err.code === "crypto-field/residency-map-not-object");
|
|
399
|
+
check("declareColumnResidency throws on an empty residency tag",
|
|
400
|
+
_try(function () { return b.cryptoField.declareColumnResidency("cf_cov_res2", { columnResidency: { c: "" } }); })
|
|
401
|
+
.err.code === "crypto-field/residency-tag-empty");
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// ---- per-row residency + per-row-key config guards, eraseRow tombstone ----
|
|
405
|
+
|
|
406
|
+
function testPerRowConfigGuardsAndErase() {
|
|
407
|
+
// Per-row residency: the residency tag column must stay plaintext, so
|
|
408
|
+
// declaring it on top of a sealed column is refused at config time.
|
|
409
|
+
b.cryptoField.registerTable("cf_cov_prr", { sealedFields: ["region", "ssn"] });
|
|
410
|
+
check("declarePerRowResidency refuses a sealed residency column",
|
|
411
|
+
_try(function () {
|
|
412
|
+
return b.cryptoField.declarePerRowResidency("cf_cov_prr", {
|
|
413
|
+
residencyColumn: "region", allowedTags: ["eu", "global"],
|
|
414
|
+
});
|
|
415
|
+
}).err.code === "crypto-field/per-row-residency-sealed-conflict");
|
|
416
|
+
check("declarePerRowResidency refuses an empty allowedTags array",
|
|
417
|
+
_try(function () {
|
|
418
|
+
return b.cryptoField.declarePerRowResidency("cf_cov_prr2", {
|
|
419
|
+
residencyColumn: "dataRegion", allowedTags: [],
|
|
420
|
+
});
|
|
421
|
+
}).err.code === "crypto-field/per-row-residency-tags-invalid");
|
|
422
|
+
|
|
423
|
+
var prrSpec = b.cryptoField.declarePerRowResidency("cf_cov_prr3", {
|
|
424
|
+
residencyColumn: "dataRegion", allowedTags: ["eu-west-1", "global"],
|
|
425
|
+
});
|
|
426
|
+
check("declarePerRowResidency returns the declared spec",
|
|
427
|
+
prrSpec.residencyColumn === "dataRegion" && prrSpec.allowedTags.length === 2);
|
|
428
|
+
check("getPerRowResidency returns a copy of the spec",
|
|
429
|
+
b.cryptoField.getPerRowResidency("cf_cov_prr3").residencyColumn === "dataRegion");
|
|
430
|
+
check("getPerRowResidency returns null for an undeclared table",
|
|
431
|
+
b.cryptoField.getPerRowResidency("cf_cov_prr_none") === null);
|
|
432
|
+
var listed = b.cryptoField.listPerRowResidency();
|
|
433
|
+
check("listPerRowResidency includes the declared table",
|
|
434
|
+
Array.isArray(listed) && listed.some(function (e) {
|
|
435
|
+
return e.table === "cf_cov_prr3" && e.residencyColumn === "dataRegion";
|
|
436
|
+
}));
|
|
437
|
+
|
|
438
|
+
// declarePerRowKey validation — config-time fail-loud on bad sizing.
|
|
439
|
+
check("declarePerRowKey throws on an empty table name",
|
|
440
|
+
_try(function () { return b.cryptoField.declarePerRowKey("", {}); })
|
|
441
|
+
.err.code === "crypto-field/per-row-key-table-empty");
|
|
442
|
+
check("declarePerRowKey throws on a keySize below the 16-byte minimum",
|
|
443
|
+
_try(function () { return b.cryptoField.declarePerRowKey("cf_cov_pk", { keySize: 8 }); })
|
|
444
|
+
.err.code === "crypto-field/per-row-key-bad-size");
|
|
445
|
+
check("declarePerRowKey throws on a non-integer keySize",
|
|
446
|
+
_try(function () { return b.cryptoField.declarePerRowKey("cf_cov_pk", { keySize: 16.5 }); })
|
|
447
|
+
.err.code === "crypto-field/per-row-key-bad-size");
|
|
448
|
+
check("declarePerRowKey throws on a non-numeric keySize",
|
|
449
|
+
_try(function () { return b.cryptoField.declarePerRowKey("cf_cov_pk", { keySize: "32" }); })
|
|
450
|
+
.err.code === "crypto-field/per-row-key-bad-size");
|
|
451
|
+
check("declarePerRowKey throws on a non-string info label",
|
|
452
|
+
_try(function () { return b.cryptoField.declarePerRowKey("cf_cov_pk", { info: 123 }); })
|
|
453
|
+
.err.code === "crypto-field/per-row-key-info-empty");
|
|
454
|
+
|
|
455
|
+
check("hasPerRowKey false before declaration", b.cryptoField.hasPerRowKey("cf_cov_pk_ok") === false);
|
|
456
|
+
var pkSpec = b.cryptoField.declarePerRowKey("cf_cov_pk_ok"); // default keySize 32
|
|
457
|
+
check("declarePerRowKey defaults keySize to 32", pkSpec.keySize === 32);
|
|
458
|
+
check("declarePerRowKey defaults the info label to the table namespace",
|
|
459
|
+
pkSpec.info === "blamejs-per-row-key:cf_cov_pk_ok");
|
|
460
|
+
check("hasPerRowKey true after declaration", b.cryptoField.hasPerRowKey("cf_cov_pk_ok") === true);
|
|
461
|
+
|
|
462
|
+
// materialize / destroy require a db handle — the guard branches throw or
|
|
463
|
+
// no-op WITHOUT touching crypto when the table isn't keyed or no handle is
|
|
464
|
+
// passed.
|
|
465
|
+
check("materializePerRowKey returns null for a non-keyed table",
|
|
466
|
+
b.cryptoField.materializePerRowKey("cf_cov_not_keyed", "r1", {}) === null);
|
|
467
|
+
check("materializePerRowKey throws when no db handle is supplied",
|
|
468
|
+
_try(function () { return b.cryptoField.materializePerRowKey("cf_cov_pk_ok", "r1"); })
|
|
469
|
+
.err.code === "crypto-field/materialize-per-row-key-no-db");
|
|
470
|
+
check("destroyPerRowKey no-ops (destroyed:0) for a non-keyed table",
|
|
471
|
+
b.cryptoField.destroyPerRowKey("cf_cov_not_keyed", "r1", {}).destroyed === 0);
|
|
472
|
+
check("destroyPerRowKey throws when no db handle is supplied",
|
|
473
|
+
_try(function () { return b.cryptoField.destroyPerRowKey("cf_cov_pk_ok", "r1"); })
|
|
474
|
+
.err.code === "crypto-field/destroy-per-row-key-no-db");
|
|
475
|
+
|
|
476
|
+
// eraseRow tombstone: sealed columns + derived-hash mirrors NULLed, a
|
|
477
|
+
// 1-day-bucketed __erasedAt stamped, non-sealed columns preserved.
|
|
478
|
+
b.cryptoField.registerTable("cf_cov_erase", {
|
|
479
|
+
sealedFields: ["ssn"], derivedHashes: { ssnHash: { from: "ssn" } },
|
|
480
|
+
});
|
|
481
|
+
check("eraseRow(null) returns the falsy row", b.cryptoField.eraseRow("cf_cov_erase", null) === null);
|
|
482
|
+
var eraseInput = { id: 7, ssn: "vault:whatever", ssnHash: "deadbeef", keep: "retained" };
|
|
483
|
+
var erased = b.cryptoField.eraseRow("cf_cov_erase", eraseInput);
|
|
484
|
+
check("eraseRow NULLs the sealed column", erased.ssn === null);
|
|
485
|
+
check("eraseRow NULLs the derived-hash mirror", erased.ssnHash === null);
|
|
486
|
+
check("eraseRow preserves non-sealed columns", erased.keep === "retained");
|
|
487
|
+
check("eraseRow stamps a numeric __erasedAt", typeof erased.__erasedAt === "number");
|
|
488
|
+
check("eraseRow buckets __erasedAt to a 1-day floor (UTC ms)", erased.__erasedAt % (24 * 60 * 60 * 1000) === 0);
|
|
489
|
+
check("eraseRow does not mutate the input row", eraseInput.ssn === "vault:whatever");
|
|
490
|
+
check("eraseRow on an unregistered table returns the row unchanged",
|
|
491
|
+
b.cryptoField.eraseRow("cf_cov_erase_none", eraseInput) === eraseInput);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// ---- malformed envelopes + Uint8Array type fidelity (vault-backed) ----
|
|
495
|
+
|
|
496
|
+
async function testMalformedEnvelopesFailClosed() {
|
|
497
|
+
var tmp = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-cf-malformed-"));
|
|
498
|
+
try {
|
|
499
|
+
try { b.vault._resetForTest(); } catch (_e) { /* fresh init below */ }
|
|
500
|
+
await b.vault.init({ dataDir: tmp, mode: "plaintext" });
|
|
501
|
+
b.cryptoField.clearRateCapForTest();
|
|
502
|
+
|
|
503
|
+
// A DB-write attacker forges a garbage vault: payload into a sealed
|
|
504
|
+
// column. unsealRow must fail closed (null the cell), never crash the
|
|
505
|
+
// read and never surface the attacker-crafted string.
|
|
506
|
+
b.cryptoField.registerTable("cf_cov_malformed", { sealedFields: ["x"] });
|
|
507
|
+
var garbage = _try(function () {
|
|
508
|
+
return b.cryptoField.unsealRow("cf_cov_malformed",
|
|
509
|
+
{ id: 1, x: "vault:not-valid-base64-@@@" }, "seam");
|
|
510
|
+
});
|
|
511
|
+
check("unsealRow does not throw on a malformed vault: envelope", garbage.ok === true);
|
|
512
|
+
check("unsealRow nulls a malformed vault: envelope (fail closed, never surfaced)",
|
|
513
|
+
garbage.value.x === null);
|
|
514
|
+
|
|
515
|
+
// A malformed vault.aad: envelope on an aad table likewise fails closed.
|
|
516
|
+
b.cryptoField.registerTable("cf_cov_malformed_aad", {
|
|
517
|
+
aad: true, sealedFields: ["x"], rowIdField: "id",
|
|
518
|
+
});
|
|
519
|
+
var garbageAad = _try(function () {
|
|
520
|
+
return b.cryptoField.unsealRow("cf_cov_malformed_aad",
|
|
521
|
+
{ id: "rowA", x: "vault.aad:garbage-not-a-real-envelope" }, "seam");
|
|
522
|
+
});
|
|
523
|
+
check("unsealRow does not throw on a malformed vault.aad: envelope", garbageAad.ok === true);
|
|
524
|
+
check("unsealRow nulls a malformed vault.aad: envelope (fail closed)", garbageAad.value.x === null);
|
|
525
|
+
|
|
526
|
+
// AAD-downgrade refusal: a plain (unbound) vault: cell on an aad table is a
|
|
527
|
+
// relocatable-seal downgrade — refused (nulled), not surfaced. Build a real
|
|
528
|
+
// plain vault: cell on a separate plain table, then read it through the aad
|
|
529
|
+
// table's context.
|
|
530
|
+
b.cryptoField.registerTable("cf_cov_plainsrc", { sealedFields: ["x"] });
|
|
531
|
+
var plainCell = b.cryptoField.sealRow("cf_cov_plainsrc", { x: "leaked" }).x;
|
|
532
|
+
check("control: the source plain cell is a vault: (unbound) envelope",
|
|
533
|
+
typeof plainCell === "string" && plainCell.indexOf("vault:") === 0);
|
|
534
|
+
var downgrade = b.cryptoField.unsealRow("cf_cov_malformed_aad",
|
|
535
|
+
{ id: "rowA", x: plainCell }, "seam");
|
|
536
|
+
check("unsealRow refuses a plain vault: cell on an aad table (downgrade nulled)",
|
|
537
|
+
downgrade.x === null);
|
|
538
|
+
|
|
539
|
+
// Type fidelity: a plain Uint8Array (not a Buffer) round-trips as bytes —
|
|
540
|
+
// the distinct _encodeTyped Uint8Array branch, separate from Buffer.
|
|
541
|
+
b.cryptoField.registerTable("cf_cov_u8", { sealedFields: ["bytes"] });
|
|
542
|
+
var u8 = new Uint8Array([0, 9, 250, 255, 1]);
|
|
543
|
+
var sealedU8 = b.cryptoField.sealRow("cf_cov_u8", { bytes: u8 });
|
|
544
|
+
check("a Uint8Array sealed field is stored as a vault: envelope",
|
|
545
|
+
typeof sealedU8.bytes === "string" && sealedU8.bytes.indexOf("vault:") === 0);
|
|
546
|
+
var readU8 = b.cryptoField.unsealRow("cf_cov_u8", Object.assign({}, sealedU8), "seam");
|
|
547
|
+
check("a Uint8Array round-trips byte-for-byte (as a Buffer) through a sealed column",
|
|
548
|
+
Buffer.isBuffer(readU8.bytes) && readU8.bytes.equals(Buffer.from(u8)));
|
|
549
|
+
|
|
550
|
+
b.cryptoField.clearRateCapForTest();
|
|
551
|
+
} finally {
|
|
552
|
+
try { b.vault._resetForTest(); } catch (_e) { /* leave vault state clean for siblings */ }
|
|
553
|
+
try { fs.rmSync(tmp, { recursive: true, force: true }); } catch (_e) { /* best-effort */ }
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
async function run() {
|
|
558
|
+
testReturnsDeclaredSealedFields();
|
|
559
|
+
testUnregisteredTableIsEmpty();
|
|
560
|
+
testTableWithNoSealedColumns();
|
|
561
|
+
testPreservesDeclarationOrder();
|
|
562
|
+
testAccessorAndGuardBranches();
|
|
563
|
+
testColumnResidencyGate();
|
|
564
|
+
testPerRowConfigGuardsAndErase();
|
|
565
|
+
await testSealUnsealSeams();
|
|
566
|
+
await testConsumerPathEmptyAndKRow();
|
|
567
|
+
await testMalformedEnvelopesFailClosed();
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
module.exports = { run: run };
|
|
571
|
+
|
|
572
|
+
if (require.main === module) {
|
|
573
|
+
run().then(function () { console.log("[crypto-field] OK"); })
|
|
574
|
+
.catch(function (e) { console.error(e); process.exit(1); });
|
|
575
|
+
}
|
|
@@ -172,6 +172,16 @@ async function testMissingFile() {
|
|
|
172
172
|
try { await b.crypto.hashFilesParallel(["/no-such-file-12345"]); }
|
|
173
173
|
catch (e) { threw = e; }
|
|
174
174
|
check("missing file rejected", threw !== null);
|
|
175
|
+
// The pre-open stat failure must preserve the underlying fs error
|
|
176
|
+
// metadata (code / path) so callers can branch on ENOENT vs EACCES
|
|
177
|
+
// rather than string-matching the wrapped message. The mid-read
|
|
178
|
+
// stream error path already carries .code; the pre-open path must not
|
|
179
|
+
// discard it, or the observable failure shape is nondeterministic by
|
|
180
|
+
// timing.
|
|
181
|
+
check("missing file: err.code preserved as ENOENT",
|
|
182
|
+
threw && threw.code === "ENOENT");
|
|
183
|
+
check("missing file: err.path preserved",
|
|
184
|
+
threw && threw.path === "/no-such-file-12345");
|
|
175
185
|
}
|
|
176
186
|
|
|
177
187
|
async function run() {
|
|
@@ -67,6 +67,30 @@ async function run() {
|
|
|
67
67
|
catch (e) { sha256Err = e; }
|
|
68
68
|
check("hashFile rejects sha256", sha256Err && /unsupported algorithm/.test(sha256Err.message));
|
|
69
69
|
|
|
70
|
+
// ---- Prototype-chain algorithm name: own-property guard ----
|
|
71
|
+
// A truthiness guard on the plain-object STREAM_HASH_ALGORITHMS table
|
|
72
|
+
// (if (!entry)) lets a name that collides with an Object.prototype member
|
|
73
|
+
// ("constructor" → the Object constructor, "__proto__" → Object.prototype)
|
|
74
|
+
// slip past the allowlist check; createHash(entry.algorithm === undefined)
|
|
75
|
+
// then throws SYNCHRONOUSLY from this Promise-returning function, so a caller
|
|
76
|
+
// that only wired a rejection handler gets an unhandled exception instead of
|
|
77
|
+
// the documented Promise.reject(TypeError("unsupported algorithm ...")).
|
|
78
|
+
var protoAlgNames = ["constructor", "__proto__", "hasOwnProperty"];
|
|
79
|
+
for (var pai = 0; pai < protoAlgNames.length; pai += 1) {
|
|
80
|
+
var badAlg = protoAlgNames[pai];
|
|
81
|
+
var protoThrewSync = false;
|
|
82
|
+
var protoPromise = null;
|
|
83
|
+
var protoErr = null;
|
|
84
|
+
try { protoPromise = b.crypto.hashStream(Readable.from([Buffer.from("x")]), badAlg); }
|
|
85
|
+
catch (_sync) { protoThrewSync = true; }
|
|
86
|
+
check("hashStream(" + JSON.stringify(badAlg) + ") does not throw synchronously", protoThrewSync === false);
|
|
87
|
+
if (protoPromise) {
|
|
88
|
+
try { await protoPromise; } catch (e) { protoErr = e; }
|
|
89
|
+
check("hashStream(" + JSON.stringify(badAlg) + ") rejects with unsupported algorithm",
|
|
90
|
+
!!(protoErr && /unsupported algorithm/.test(protoErr.message || "")));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
70
94
|
// ---- Bad arg: empty path ----
|
|
71
95
|
var badPathErr;
|
|
72
96
|
try { await b.crypto.hashFile(""); }
|
|
@@ -43,6 +43,22 @@ function testSurface() {
|
|
|
43
43
|
check("unknown suite throws", code(function () { b.crypto.oprf.suite("x25519-sha256"); }) === "oprf/bad-suite");
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
// A suite name that collides with an Object.prototype member must be refused
|
|
47
|
+
// exactly like any other unknown name. A truthiness guard on the plain-object
|
|
48
|
+
// SUITE_IMPL table (if (!impl)) instead of an own-property check returns
|
|
49
|
+
// Object.prototype (for "__proto__") or the Object constructor (for
|
|
50
|
+
// "constructor") as a truthy "suite" — a broken { oprf: undefined, voprf:
|
|
51
|
+
// undefined } object that passes the guard and later throws an opaque
|
|
52
|
+
// TypeError at s.oprf.blind() instead of the documented
|
|
53
|
+
// OprfError("oprf/bad-suite"). These names are all-lowercase, so the
|
|
54
|
+
// .toLowerCase() normalization does not filter them (unlike "hasOwnProperty").
|
|
55
|
+
function testPrototypeKeySuiteRejected() {
|
|
56
|
+
["__proto__", "constructor", "hasOwnProperty", "toString", "valueOf", "isPrototypeOf"].forEach(function (k) {
|
|
57
|
+
check("suite(" + JSON.stringify(k) + ") throws oprf/bad-suite (own-property guard)",
|
|
58
|
+
code(function () { b.crypto.oprf.suite(k); }) === "oprf/bad-suite");
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
46
62
|
function testRfc9497Vectors() {
|
|
47
63
|
Object.keys(VEC).forEach(function (name) {
|
|
48
64
|
var s = b.crypto.oprf.suite(name);
|
|
@@ -95,6 +111,7 @@ function testVoprfRoundTripAndProof() {
|
|
|
95
111
|
|
|
96
112
|
async function run() {
|
|
97
113
|
testSurface();
|
|
114
|
+
testPrototypeKeySuiteRejected();
|
|
98
115
|
testRfc9497Vectors();
|
|
99
116
|
testOprfRoundTrip();
|
|
100
117
|
testVoprfRoundTripAndProof();
|