@blamejs/blamejs-shop 0.4.56 → 0.4.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/lib/asset-manifest.json +1 -1
- package/lib/vendor/MANIFEST.json +426 -366
- package/lib/vendor/blamejs/.github/codeql/codeql-config.yml +25 -0
- package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +1 -1
- package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +1 -1
- package/lib/vendor/blamejs/.github/workflows/ci.yml +13 -13
- package/lib/vendor/blamejs/.github/workflows/codeql.yml +8 -7
- package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +2 -2
- package/lib/vendor/blamejs/.github/workflows/release-container.yml +4 -4
- package/lib/vendor/blamejs/.github/workflows/scorecard.yml +1 -1
- package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
- package/lib/vendor/blamejs/CHANGELOG.md +2 -0
- package/lib/vendor/blamejs/api-snapshot.json +1381 -4
- package/lib/vendor/blamejs/eslint.config.mjs +1 -0
- package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +4 -1
- package/lib/vendor/blamejs/examples/wiki/lib/symbol-index.js +5 -2
- package/lib/vendor/blamejs/examples/wiki/routes/pages.js +4 -1
- package/lib/vendor/blamejs/fuzz/guard-text.fuzz.js +20 -0
- package/lib/vendor/blamejs/index.js +2 -0
- package/lib/vendor/blamejs/lib/a2a-tasks.js +7 -23
- package/lib/vendor/blamejs/lib/acme.js +6 -5
- package/lib/vendor/blamejs/lib/agent-event-bus.js +5 -4
- package/lib/vendor/blamejs/lib/agent-idempotency.js +2 -5
- package/lib/vendor/blamejs/lib/agent-orchestrator.js +2 -5
- package/lib/vendor/blamejs/lib/agent-saga.js +3 -5
- package/lib/vendor/blamejs/lib/agent-tenant.js +2 -5
- package/lib/vendor/blamejs/lib/ai-adverse-decision.js +2 -15
- package/lib/vendor/blamejs/lib/ai-capability.js +1 -6
- package/lib/vendor/blamejs/lib/ai-dp.js +1 -5
- package/lib/vendor/blamejs/lib/ai-input.js +2 -2
- package/lib/vendor/blamejs/lib/ai-pref.js +3 -8
- package/lib/vendor/blamejs/lib/ai-quota.js +3 -14
- package/lib/vendor/blamejs/lib/api-key.js +37 -28
- package/lib/vendor/blamejs/lib/archive-adapters.js +2 -4
- package/lib/vendor/blamejs/lib/archive-entry-policy.js +32 -0
- package/lib/vendor/blamejs/lib/archive-read.js +5 -17
- package/lib/vendor/blamejs/lib/archive-tar-read.js +5 -16
- package/lib/vendor/blamejs/lib/archive.js +2 -10
- package/lib/vendor/blamejs/lib/arg-parser.js +7 -6
- package/lib/vendor/blamejs/lib/asyncapi-traits.js +2 -6
- package/lib/vendor/blamejs/lib/atomic-file.js +108 -31
- package/lib/vendor/blamejs/lib/audit-chain.js +133 -53
- package/lib/vendor/blamejs/lib/audit-daily-review.js +24 -14
- package/lib/vendor/blamejs/lib/audit-emit.js +82 -0
- package/lib/vendor/blamejs/lib/audit-sign.js +257 -0
- package/lib/vendor/blamejs/lib/audit.js +84 -0
- package/lib/vendor/blamejs/lib/auth/access-lock.js +5 -27
- package/lib/vendor/blamejs/lib/auth/dpop.js +23 -35
- package/lib/vendor/blamejs/lib/auth/fido-mds3.js +9 -15
- package/lib/vendor/blamejs/lib/auth/jwt-external.js +26 -8
- package/lib/vendor/blamejs/lib/auth/jwt.js +13 -15
- package/lib/vendor/blamejs/lib/auth/lockout.js +6 -25
- package/lib/vendor/blamejs/lib/auth/oauth.js +67 -45
- package/lib/vendor/blamejs/lib/auth/oid4vci.js +55 -32
- package/lib/vendor/blamejs/lib/auth/oid4vp.js +3 -2
- package/lib/vendor/blamejs/lib/auth/openid-federation.js +6 -6
- package/lib/vendor/blamejs/lib/auth/passkey.js +3 -3
- package/lib/vendor/blamejs/lib/auth/password.js +7 -1
- package/lib/vendor/blamejs/lib/auth/saml.js +37 -27
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-holder.js +2 -14
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-issuer.js +2 -14
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +1 -1
- package/lib/vendor/blamejs/lib/auth/status-list.js +7 -7
- package/lib/vendor/blamejs/lib/auth/step-up.js +6 -12
- package/lib/vendor/blamejs/lib/auth-bot-challenge.js +6 -37
- package/lib/vendor/blamejs/lib/backup/bundle.js +11 -18
- package/lib/vendor/blamejs/lib/backup/index.js +14 -47
- package/lib/vendor/blamejs/lib/bounded-map.js +112 -1
- package/lib/vendor/blamejs/lib/breach-deadline.js +1 -11
- package/lib/vendor/blamejs/lib/cache.js +7 -18
- package/lib/vendor/blamejs/lib/cbor.js +2 -1
- package/lib/vendor/blamejs/lib/cdn-cache-control.js +8 -9
- package/lib/vendor/blamejs/lib/cert.js +3 -10
- package/lib/vendor/blamejs/lib/chain-writer.js +162 -47
- package/lib/vendor/blamejs/lib/cli.js +5 -1
- package/lib/vendor/blamejs/lib/client-hints.js +7 -9
- package/lib/vendor/blamejs/lib/cloud-events.js +40 -31
- package/lib/vendor/blamejs/lib/cluster-storage.js +2 -38
- package/lib/vendor/blamejs/lib/cms-codec.js +2 -1
- package/lib/vendor/blamejs/lib/codepoint-class.js +67 -1
- package/lib/vendor/blamejs/lib/compliance-ai-act-logging.js +1 -6
- package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +2 -4
- package/lib/vendor/blamejs/lib/compliance-eaa.js +1 -11
- package/lib/vendor/blamejs/lib/compliance-sanctions-fetcher.js +21 -28
- package/lib/vendor/blamejs/lib/compliance-sanctions.js +2 -14
- package/lib/vendor/blamejs/lib/compliance.js +2 -9
- package/lib/vendor/blamejs/lib/config-drift.js +2 -12
- package/lib/vendor/blamejs/lib/content-digest.js +10 -8
- package/lib/vendor/blamejs/lib/cookies.js +5 -11
- package/lib/vendor/blamejs/lib/cose.js +19 -11
- package/lib/vendor/blamejs/lib/cra-report.js +1 -11
- package/lib/vendor/blamejs/lib/crypto-field.js +5 -10
- package/lib/vendor/blamejs/lib/crypto.js +120 -3
- package/lib/vendor/blamejs/lib/csp.js +235 -3
- package/lib/vendor/blamejs/lib/daemon.js +42 -41
- package/lib/vendor/blamejs/lib/data-act.js +19 -9
- package/lib/vendor/blamejs/lib/db-query.js +6 -40
- package/lib/vendor/blamejs/lib/db.js +34 -12
- package/lib/vendor/blamejs/lib/dbsc.js +5 -6
- package/lib/vendor/blamejs/lib/ddl-change-control.js +18 -14
- package/lib/vendor/blamejs/lib/deprecate.js +4 -5
- package/lib/vendor/blamejs/lib/did.js +6 -2
- package/lib/vendor/blamejs/lib/dsr.js +8 -12
- package/lib/vendor/blamejs/lib/external-db-migrate.js +21 -22
- package/lib/vendor/blamejs/lib/external-db.js +14 -26
- package/lib/vendor/blamejs/lib/fda-21cfr11.js +12 -8
- package/lib/vendor/blamejs/lib/fdx.js +22 -18
- package/lib/vendor/blamejs/lib/file-upload.js +80 -66
- package/lib/vendor/blamejs/lib/flag-evaluation-context.js +5 -8
- package/lib/vendor/blamejs/lib/framework-error.js +12 -0
- package/lib/vendor/blamejs/lib/framework-schema.js +19 -0
- package/lib/vendor/blamejs/lib/fsm.js +7 -12
- package/lib/vendor/blamejs/lib/gate-contract.js +869 -38
- package/lib/vendor/blamejs/lib/gdpr-ropa.js +4 -13
- package/lib/vendor/blamejs/lib/graphql-federation.js +1 -1
- package/lib/vendor/blamejs/lib/guard-agent-registry.js +2 -1
- package/lib/vendor/blamejs/lib/guard-all.js +1 -0
- package/lib/vendor/blamejs/lib/guard-archive.js +9 -30
- package/lib/vendor/blamejs/lib/guard-auth.js +23 -80
- package/lib/vendor/blamejs/lib/guard-cidr.js +20 -96
- package/lib/vendor/blamejs/lib/guard-csv.js +135 -196
- package/lib/vendor/blamejs/lib/guard-domain.js +23 -106
- package/lib/vendor/blamejs/lib/guard-dsn.js +16 -13
- package/lib/vendor/blamejs/lib/guard-email.js +46 -53
- package/lib/vendor/blamejs/lib/guard-envelope.js +1 -1
- package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +2 -1
- package/lib/vendor/blamejs/lib/guard-filename.js +12 -60
- package/lib/vendor/blamejs/lib/guard-graphql.js +28 -75
- package/lib/vendor/blamejs/lib/guard-html-wcag.js +15 -2
- package/lib/vendor/blamejs/lib/guard-html.js +65 -117
- package/lib/vendor/blamejs/lib/guard-idempotency-key.js +2 -1
- package/lib/vendor/blamejs/lib/guard-image.js +280 -77
- package/lib/vendor/blamejs/lib/guard-imap-command.js +8 -9
- package/lib/vendor/blamejs/lib/guard-json.js +87 -103
- package/lib/vendor/blamejs/lib/guard-jsonpath.js +20 -88
- package/lib/vendor/blamejs/lib/guard-jwt.js +32 -114
- package/lib/vendor/blamejs/lib/guard-list-id.js +2 -7
- package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -7
- package/lib/vendor/blamejs/lib/guard-mail-compose.js +5 -6
- package/lib/vendor/blamejs/lib/guard-mail-move.js +2 -1
- package/lib/vendor/blamejs/lib/guard-mail-query.js +5 -3
- package/lib/vendor/blamejs/lib/guard-mail-sieve.js +6 -7
- package/lib/vendor/blamejs/lib/guard-managesieve-command.js +5 -4
- package/lib/vendor/blamejs/lib/guard-markdown.js +76 -110
- package/lib/vendor/blamejs/lib/guard-message-id.js +5 -6
- package/lib/vendor/blamejs/lib/guard-mime.js +20 -99
- package/lib/vendor/blamejs/lib/guard-oauth.js +19 -73
- package/lib/vendor/blamejs/lib/guard-pdf.js +65 -72
- package/lib/vendor/blamejs/lib/guard-pop3-command.js +12 -13
- package/lib/vendor/blamejs/lib/guard-posture-chain.js +2 -1
- package/lib/vendor/blamejs/lib/guard-regex.js +24 -99
- package/lib/vendor/blamejs/lib/guard-saga-config.js +2 -1
- package/lib/vendor/blamejs/lib/guard-shell.js +22 -87
- package/lib/vendor/blamejs/lib/guard-smtp-command.js +8 -11
- package/lib/vendor/blamejs/lib/guard-sql.js +15 -13
- package/lib/vendor/blamejs/lib/guard-stream-args.js +2 -1
- package/lib/vendor/blamejs/lib/guard-svg.js +95 -140
- package/lib/vendor/blamejs/lib/guard-template.js +23 -80
- package/lib/vendor/blamejs/lib/guard-tenant-id.js +2 -1
- package/lib/vendor/blamejs/lib/guard-text.js +592 -0
- package/lib/vendor/blamejs/lib/guard-time.js +27 -95
- package/lib/vendor/blamejs/lib/guard-uuid.js +21 -93
- package/lib/vendor/blamejs/lib/guard-xml.js +76 -106
- package/lib/vendor/blamejs/lib/guard-yaml.js +24 -60
- package/lib/vendor/blamejs/lib/http-client-cache.js +5 -12
- package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +2 -4
- package/lib/vendor/blamejs/lib/http-client.js +8 -21
- package/lib/vendor/blamejs/lib/http-message-signature.js +3 -2
- package/lib/vendor/blamejs/lib/i18n-messageformat.js +5 -7
- package/lib/vendor/blamejs/lib/i18n.js +83 -26
- package/lib/vendor/blamejs/lib/inbox.js +8 -8
- package/lib/vendor/blamejs/lib/incident-report.js +3 -21
- package/lib/vendor/blamejs/lib/ip-utils.js +49 -6
- package/lib/vendor/blamejs/lib/jobs.js +3 -2
- package/lib/vendor/blamejs/lib/keychain.js +6 -18
- package/lib/vendor/blamejs/lib/legal-hold.js +6 -15
- package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +44 -112
- package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +17 -14
- package/lib/vendor/blamejs/lib/log-stream-otlp.js +16 -80
- package/lib/vendor/blamejs/lib/log-stream-webhook.js +20 -92
- package/lib/vendor/blamejs/lib/mail-arc-sign.js +8 -3
- package/lib/vendor/blamejs/lib/mail-arf.js +3 -2
- package/lib/vendor/blamejs/lib/mail-auth.js +40 -66
- package/lib/vendor/blamejs/lib/mail-bimi.js +19 -39
- package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +3 -2
- package/lib/vendor/blamejs/lib/mail-dav.js +8 -35
- package/lib/vendor/blamejs/lib/mail-deploy.js +6 -9
- package/lib/vendor/blamejs/lib/mail-dkim.js +19 -38
- package/lib/vendor/blamejs/lib/mail-greylist.js +15 -26
- package/lib/vendor/blamejs/lib/mail-helo.js +2 -3
- package/lib/vendor/blamejs/lib/mail-journal.js +2 -1
- package/lib/vendor/blamejs/lib/mail-mdn.js +4 -3
- package/lib/vendor/blamejs/lib/mail-rbl.js +5 -8
- package/lib/vendor/blamejs/lib/mail-scan.js +2 -2
- package/lib/vendor/blamejs/lib/mail-send-deliver.js +33 -20
- package/lib/vendor/blamejs/lib/mail-server-imap.js +32 -87
- package/lib/vendor/blamejs/lib/mail-server-jmap.js +35 -51
- package/lib/vendor/blamejs/lib/mail-server-managesieve.js +29 -83
- package/lib/vendor/blamejs/lib/mail-server-mx.js +33 -74
- package/lib/vendor/blamejs/lib/mail-server-net.js +177 -0
- package/lib/vendor/blamejs/lib/mail-server-pop3.js +30 -83
- package/lib/vendor/blamejs/lib/mail-server-rate-limit.js +30 -6
- package/lib/vendor/blamejs/lib/mail-server-submission.js +34 -73
- package/lib/vendor/blamejs/lib/mail-server-tls.js +89 -0
- package/lib/vendor/blamejs/lib/mail-spam-score.js +7 -8
- package/lib/vendor/blamejs/lib/mail-store.js +3 -2
- package/lib/vendor/blamejs/lib/mail.js +6 -11
- package/lib/vendor/blamejs/lib/markup-escape.js +31 -0
- package/lib/vendor/blamejs/lib/markup-tokenizer.js +54 -0
- package/lib/vendor/blamejs/lib/mcp-tool-registry.js +26 -23
- package/lib/vendor/blamejs/lib/mcp.js +1 -1
- package/lib/vendor/blamejs/lib/mdoc.js +11 -12
- package/lib/vendor/blamejs/lib/metrics.js +32 -30
- package/lib/vendor/blamejs/lib/middleware/age-gate.js +3 -23
- package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +11 -22
- package/lib/vendor/blamejs/lib/middleware/assetlinks.js +2 -7
- package/lib/vendor/blamejs/lib/middleware/bearer-auth.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/body-parser.js +31 -48
- package/lib/vendor/blamejs/lib/middleware/bot-disclose.js +7 -10
- package/lib/vendor/blamejs/lib/middleware/bot-guard.js +2 -10
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +13 -2
- package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +6 -26
- package/lib/vendor/blamejs/lib/middleware/deny-response.js +19 -1
- package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +7 -0
- package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +4 -20
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +20 -28
- package/lib/vendor/blamejs/lib/middleware/scim-server.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/security-headers.js +9 -1
- package/lib/vendor/blamejs/lib/middleware/security-txt.js +2 -6
- package/lib/vendor/blamejs/lib/middleware/tus-upload.js +12 -27
- package/lib/vendor/blamejs/lib/middleware/web-app-manifest.js +2 -7
- package/lib/vendor/blamejs/lib/migrations.js +4 -13
- package/lib/vendor/blamejs/lib/mime-parse.js +34 -17
- package/lib/vendor/blamejs/lib/module-loader.js +44 -0
- package/lib/vendor/blamejs/lib/money.js +105 -0
- package/lib/vendor/blamejs/lib/mtls-ca.js +116 -36
- package/lib/vendor/blamejs/lib/network-byte-quota.js +4 -18
- package/lib/vendor/blamejs/lib/network-dane.js +8 -6
- package/lib/vendor/blamejs/lib/network-dns-resolver.js +97 -6
- package/lib/vendor/blamejs/lib/network-dnssec.js +16 -16
- package/lib/vendor/blamejs/lib/network-heartbeat.js +3 -2
- package/lib/vendor/blamejs/lib/network-smtp-policy.js +29 -41
- package/lib/vendor/blamejs/lib/network-tls.js +40 -42
- package/lib/vendor/blamejs/lib/nis2-report.js +1 -11
- package/lib/vendor/blamejs/lib/nonce-store.js +81 -3
- package/lib/vendor/blamejs/lib/numeric-bounds.js +22 -8
- package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +2 -6
- package/lib/vendor/blamejs/lib/object-store/azure-blob.js +5 -45
- package/lib/vendor/blamejs/lib/object-store/gcs.js +8 -71
- package/lib/vendor/blamejs/lib/object-store/http-put.js +1 -5
- package/lib/vendor/blamejs/lib/object-store/http-request.js +128 -0
- package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +2 -1
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +9 -77
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +9 -25
- package/lib/vendor/blamejs/lib/observability.js +95 -0
- package/lib/vendor/blamejs/lib/openapi-paths-builder.js +7 -3
- package/lib/vendor/blamejs/lib/otel-export.js +7 -10
- package/lib/vendor/blamejs/lib/outbox.js +43 -37
- package/lib/vendor/blamejs/lib/pagination.js +11 -15
- package/lib/vendor/blamejs/lib/parsers/safe-env.js +5 -4
- package/lib/vendor/blamejs/lib/parsers/safe-ini.js +10 -4
- package/lib/vendor/blamejs/lib/parsers/safe-toml.js +11 -9
- package/lib/vendor/blamejs/lib/parsers/safe-xml.js +2 -2
- package/lib/vendor/blamejs/lib/parsers/safe-yaml.js +7 -6
- package/lib/vendor/blamejs/lib/pick.js +63 -5
- package/lib/vendor/blamejs/lib/pipl-cn.js +69 -59
- package/lib/vendor/blamejs/lib/privacy-pass.js +8 -6
- package/lib/vendor/blamejs/lib/problem-details.js +2 -5
- package/lib/vendor/blamejs/lib/pubsub.js +4 -8
- package/lib/vendor/blamejs/lib/redact.js +2 -1
- package/lib/vendor/blamejs/lib/render.js +4 -2
- package/lib/vendor/blamejs/lib/request-helpers.js +133 -6
- package/lib/vendor/blamejs/lib/restore.js +5 -22
- package/lib/vendor/blamejs/lib/retention.js +3 -5
- package/lib/vendor/blamejs/lib/safe-async.js +457 -0
- package/lib/vendor/blamejs/lib/safe-buffer.js +137 -6
- package/lib/vendor/blamejs/lib/safe-decompress.js +2 -1
- package/lib/vendor/blamejs/lib/safe-dns.js +2 -1
- package/lib/vendor/blamejs/lib/safe-ical.js +12 -26
- package/lib/vendor/blamejs/lib/safe-json.js +7 -8
- package/lib/vendor/blamejs/lib/safe-jsonpath.js +6 -5
- package/lib/vendor/blamejs/lib/safe-mime.js +25 -29
- package/lib/vendor/blamejs/lib/safe-redirect.js +2 -5
- package/lib/vendor/blamejs/lib/safe-schema.js +7 -6
- package/lib/vendor/blamejs/lib/safe-sql.js +126 -0
- package/lib/vendor/blamejs/lib/safe-vcard.js +12 -26
- package/lib/vendor/blamejs/lib/sandbox-worker.js +9 -2
- package/lib/vendor/blamejs/lib/sandbox.js +3 -2
- package/lib/vendor/blamejs/lib/scheduler.js +5 -12
- package/lib/vendor/blamejs/lib/sec-cyber.js +82 -37
- package/lib/vendor/blamejs/lib/seeders.js +4 -11
- package/lib/vendor/blamejs/lib/self-update.js +92 -69
- package/lib/vendor/blamejs/lib/session-device-binding.js +112 -66
- package/lib/vendor/blamejs/lib/session.js +194 -6
- package/lib/vendor/blamejs/lib/sql.js +225 -78
- package/lib/vendor/blamejs/lib/sse.js +6 -10
- package/lib/vendor/blamejs/lib/static.js +136 -98
- package/lib/vendor/blamejs/lib/storage.js +4 -2
- package/lib/vendor/blamejs/lib/structured-fields.js +275 -16
- package/lib/vendor/blamejs/lib/tenant-quota.js +2 -20
- package/lib/vendor/blamejs/lib/tsa.js +11 -15
- package/lib/vendor/blamejs/lib/validate-opts.js +154 -8
- package/lib/vendor/blamejs/lib/vault/seal-pem-file.js +30 -48
- package/lib/vendor/blamejs/lib/vault-aad.js +3 -2
- package/lib/vendor/blamejs/lib/vc.js +2 -7
- package/lib/vendor/blamejs/lib/vex.js +35 -13
- package/lib/vendor/blamejs/lib/web-push-vapid.js +23 -20
- package/lib/vendor/blamejs/lib/webhook-dispatcher.js +706 -0
- package/lib/vendor/blamejs/lib/webhook.js +43 -18
- package/lib/vendor/blamejs/lib/websocket-channels.js +9 -7
- package/lib/vendor/blamejs/lib/websocket.js +7 -3
- package/lib/vendor/blamejs/lib/worm.js +2 -3
- package/lib/vendor/blamejs/lib/ws-client.js +8 -10
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.15.13.json +81 -0
- package/lib/vendor/blamejs/scripts/check-changelog-extract.js +1 -1
- package/lib/vendor/blamejs/test/00-primitives.js +136 -7
- package/lib/vendor/blamejs/test/10-state.js +9 -3
- package/lib/vendor/blamejs/test/30-chain.js +40 -0
- package/lib/vendor/blamejs/test/helpers/check.js +18 -0
- package/lib/vendor/blamejs/test/helpers/db.js +4 -0
- package/lib/vendor/blamejs/test/helpers/index.js +1 -0
- package/lib/vendor/blamejs/test/integration/audit-chain-external-db.test.js +2 -1
- package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +2 -1
- package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +8 -1
- package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +1 -1
- package/lib/vendor/blamejs/test/integration/framework-schema-mysql.test.js +2 -1
- package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +269 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-fd-read.test.js +149 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-framework-namespaces.test.js +51 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +88 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-use-store.test.js +55 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-object-store-adapter.test.js +2 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/bot-guard.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/bounded-map.test.js +129 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/chain-writer-multichain.test.js +107 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-api-key.test.js +12 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +2788 -3214
- package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +78 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-base64url.test.js +63 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +2 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-builder.test.js +50 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-nonce.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +2 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/defineguard-resolve-opts.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +9 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract-content-gate.test.js +290 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +84 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-email.test.js +78 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +23 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-gate-disposition-coverage.test.js +93 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +60 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +184 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-json.test.js +54 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +10 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +45 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +101 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-text.test.js +365 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-xml.test.js +35 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-yaml.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +20 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +15 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-arf.test.js +10 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +39 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-greylist.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-tls.test.js +39 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mime-parse.test.js +106 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/money.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-revocation.test.js +98 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-release.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-memory-getorinsert.test.js +100 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +88 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-async-loops.test.js +278 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +37 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-jsonpath.test.js +14 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sandbox.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +2 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/session-valid-from.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +100 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/structured-fields.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/validate-opts-shape.test.js +235 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +374 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +75 -8
- package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +3 -3
- package/package.json +1 -1
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* b.session.bump / validFrom / check — per-subject valid-from boundary for
|
|
4
|
+
* STATELESS self-validating tokens (sealed cookies with no DB row, JWTs) that
|
|
5
|
+
* destroy()/destroyAllForUser() can't revoke by deleting a row (#331).
|
|
6
|
+
*
|
|
7
|
+
* Drives the real consumer path through the public b.session surface against a
|
|
8
|
+
* real test DB (setupTestDb provisions the framework _blamejs_session_valid_from
|
|
9
|
+
* table). RED on the current tree: b.session.bump is undefined.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
var helpers = require("../helpers");
|
|
13
|
+
var b = helpers.b;
|
|
14
|
+
var check = helpers.check;
|
|
15
|
+
var setupTestDb = helpers.setupTestDb;
|
|
16
|
+
var teardownTestDb = helpers.teardownTestDb;
|
|
17
|
+
var fs = require("fs");
|
|
18
|
+
var os = require("os");
|
|
19
|
+
var path = require("path");
|
|
20
|
+
|
|
21
|
+
async function run() {
|
|
22
|
+
var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-svf-"));
|
|
23
|
+
try {
|
|
24
|
+
await setupTestDb(tmpDir);
|
|
25
|
+
var s = b.session;
|
|
26
|
+
|
|
27
|
+
check("bump / validFrom / check are exported on b.session",
|
|
28
|
+
typeof s.bump === "function" && typeof s.validFrom === "function" && typeof s.check === "function");
|
|
29
|
+
|
|
30
|
+
// A never-bumped subject has boundary 0 — every non-negative iat is valid.
|
|
31
|
+
check("validFrom is 0 for a never-bumped subject", (await s.validFrom("user-1")) === 0);
|
|
32
|
+
var t0 = Date.now() - 10000;
|
|
33
|
+
check("a token issued before any bump is valid", (await s.check("user-1", t0)) === true);
|
|
34
|
+
|
|
35
|
+
// bump raises the boundary to now; tokens issued before it are revoked.
|
|
36
|
+
var boundary = await s.bump("user-1");
|
|
37
|
+
check("bump returns the effective boundary (>= the pre-bump iat)",
|
|
38
|
+
typeof boundary === "number" && boundary >= t0);
|
|
39
|
+
check("validFrom now reflects the bump", (await s.validFrom("user-1")) === boundary);
|
|
40
|
+
check("a token issued BEFORE the bump is now revoked", (await s.check("user-1", t0)) === false);
|
|
41
|
+
check("a token issued AFTER the bump is still valid", (await s.check("user-1", boundary + 1000)) === true);
|
|
42
|
+
|
|
43
|
+
// Monotonic: a lower (replayed / clock-skewed) epoch can't move it back.
|
|
44
|
+
var lower = await s.bump("user-1", { epochMs: boundary - 5000 });
|
|
45
|
+
check("a bump to a LOWER epoch is a monotonic no-op", lower === boundary);
|
|
46
|
+
var higher = await s.bump("user-1", { epochMs: boundary + 5000 });
|
|
47
|
+
check("a bump to a HIGHER epoch advances the boundary", higher === boundary + 5000);
|
|
48
|
+
|
|
49
|
+
// check fails CLOSED on a malformed iat (treat an unparseable token as revoked).
|
|
50
|
+
check("check fails closed on NaN iat", (await s.check("user-1", NaN)) === false);
|
|
51
|
+
check("check fails closed on a negative iat", (await s.check("user-1", -1)) === false);
|
|
52
|
+
check("check fails closed on a non-number iat", (await s.check("user-1", "123")) === false);
|
|
53
|
+
|
|
54
|
+
// bump validates its inputs (config-time throw tier).
|
|
55
|
+
var threwSubject = false;
|
|
56
|
+
try { await s.bump(""); } catch (e) { threwSubject = /INVALID_ARG/.test(e.code || ""); }
|
|
57
|
+
check("bump rejects an empty subjectId", threwSubject);
|
|
58
|
+
var threwEpoch = false;
|
|
59
|
+
try { await s.bump("user-1", { epochMs: -1 }); } catch (e) { threwEpoch = /INVALID_ARG/.test(e.code || ""); }
|
|
60
|
+
check("bump rejects a negative epochMs", threwEpoch);
|
|
61
|
+
|
|
62
|
+
// #17 integration: a "logout everywhere" via destroyAllForUser also raises
|
|
63
|
+
// the stateless boundary, so the operator's stateless tokens are revoked
|
|
64
|
+
// too — not only the store-backed rows.
|
|
65
|
+
check("a fresh subject starts un-bumped", (await s.validFrom("user-2")) === 0);
|
|
66
|
+
await s.destroyAllForUser("user-2");
|
|
67
|
+
check("destroyAllForUser raises the stateless valid-from boundary", (await s.validFrom("user-2")) > 0);
|
|
68
|
+
} finally {
|
|
69
|
+
try { await teardownTestDb(tmpDir); } catch (_e) { /* best-effort */ }
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
module.exports = { run: run };
|
|
@@ -31,6 +31,7 @@ async function run() {
|
|
|
31
31
|
check("b.sql.update", typeof b.sql.update === "function");
|
|
32
32
|
check("b.sql.delete", typeof b.sql.delete === "function");
|
|
33
33
|
check("b.sql.upsert", typeof b.sql.upsert === "function");
|
|
34
|
+
check("b.sql.insertSelectWhere", typeof b.sql.insertSelectWhere === "function");
|
|
34
35
|
check("b.sql.table", typeof b.sql.table === "function");
|
|
35
36
|
check("b.sql.createTable", typeof b.sql.createTable === "function");
|
|
36
37
|
check("b.sql.createIndex", typeof b.sql.createIndex === "function");
|
|
@@ -590,6 +591,105 @@ async function run() {
|
|
|
590
591
|
check("upsert readback renders a cast conflict key (CAST) binding the inner value, not the wrapper",
|
|
591
592
|
rbCast.readbackSql && rbCast.readbackSql.sql.indexOf("CAST(") !== -1 &&
|
|
592
593
|
rbCast.readbackSql.params.length === 1 && rbCast.readbackSql.params[0] === "42");
|
|
594
|
+
|
|
595
|
+
// ==== insertSelectWhere (conditional INSERT...SELECT...WHERE, #335) ====
|
|
596
|
+
// The append-only-ledger debit: a row written ONLY when a guard derived
|
|
597
|
+
// from the table itself holds, with no mutable counter row to increment().
|
|
598
|
+
// Standard SQL across all three dialects; the SELECT is value-less and the
|
|
599
|
+
// WHERE admits one row or zero.
|
|
600
|
+
|
|
601
|
+
// Object-form values infer the column list; the guard is an EXISTS over a
|
|
602
|
+
// same-dialect sub-builder (the balance fence). The cells route through the
|
|
603
|
+
// value-cell choke-point (fn(NOW) emits a token, no param).
|
|
604
|
+
var ledgerBalance = sql.select("wallet_ledger", { dialect: "postgres" }).selectRaw("1")
|
|
605
|
+
.whereRaw('"wallet_id" = ?', ["w-1"]);
|
|
606
|
+
var debit = sql.insertSelectWhere("wallet_ledger", { dialect: "postgres" })
|
|
607
|
+
.values({ wallet_id: "w-1", amount: -25, at: sql.fn("NOW") })
|
|
608
|
+
.whereExists(ledgerBalance)
|
|
609
|
+
.returning(["id"]).toSql();
|
|
610
|
+
check("insertSelectWhere emits INSERT...SELECT cells...WHERE EXISTS...RETURNING",
|
|
611
|
+
debit.sql === 'INSERT INTO wallet_ledger ("wallet_id", "amount", "at") ' +
|
|
612
|
+
'SELECT ?, ?, NOW() WHERE EXISTS (SELECT 1 FROM wallet_ledger WHERE ("wallet_id" = ?)) ' +
|
|
613
|
+
'RETURNING "id"');
|
|
614
|
+
check("insertSelectWhere binds value cells then the guard params in order, fn emits no param",
|
|
615
|
+
debit.params.length === 3 && debit.params[0] === "w-1" &&
|
|
616
|
+
debit.params[1] === -25 && debit.params[2] === "w-1");
|
|
617
|
+
|
|
618
|
+
// Positional values() aligned to a prior columns() call, sqlite dialect,
|
|
619
|
+
// a scalar guard (whereOp). No RETURNING -> none emitted.
|
|
620
|
+
var lit = sql.insertSelectWhere("seats", { dialect: "sqlite" })
|
|
621
|
+
.columns(["event_id", "seat_no"]).values(["e-9", 12])
|
|
622
|
+
.whereOp("event_id", "=", "e-9").toSql();
|
|
623
|
+
check("insertSelectWhere positional values + sqlite quoting + scalar guard",
|
|
624
|
+
lit.sql === 'INSERT INTO seats ("event_id", "seat_no") SELECT ?, ? WHERE "event_id" = ?' &&
|
|
625
|
+
lit.params.length === 3 && lit.params[2] === "e-9");
|
|
626
|
+
|
|
627
|
+
// cast cell binds value + casts the placeholder (Postgres ?::jsonb).
|
|
628
|
+
var castSel = sql.insertSelectWhere("docs", { dialect: "postgres" })
|
|
629
|
+
.values({ id: 1, meta: sql.cast('{"a":1}', "jsonb") })
|
|
630
|
+
.whereOp("id", "=", 1).toSql();
|
|
631
|
+
check("insertSelectWhere renders a cast SELECT cell (?::jsonb) binding the inner value",
|
|
632
|
+
/SELECT \?, \?::jsonb WHERE "id" = \?/.test(castSel.sql) &&
|
|
633
|
+
castSel.params.length === 3 && castSel.params[1] === '{"a":1}');
|
|
634
|
+
|
|
635
|
+
// MySQL: standard form, backtick quoting; RETURNING refused (run an explicit read).
|
|
636
|
+
var my = sql.insertSelectWhere("ledger", { dialect: "mysql" })
|
|
637
|
+
.values({ k: "a", n: 1 }).whereOp("k", "=", "a").toSql();
|
|
638
|
+
check("insertSelectWhere mysql backtick quoting",
|
|
639
|
+
my.sql === "INSERT INTO ledger (`k`, `n`) SELECT ?, ? WHERE `k` = ?");
|
|
640
|
+
rejects("insertSelectWhere RETURNING refused on mysql", function () {
|
|
641
|
+
return sql.insertSelectWhere("ledger", { dialect: "mysql" })
|
|
642
|
+
.values({ k: "a" }).whereOp("k", "=", "a").returning(["k"]).toSql();
|
|
643
|
+
}, "sql-builder/returning-unsupported");
|
|
644
|
+
|
|
645
|
+
// Safety default: an un-guarded conditional insert THROWS (like update/delete);
|
|
646
|
+
// allowNoWhere() opts in deliberately.
|
|
647
|
+
rejects("insertSelectWhere without where throws (no-where default)", function () {
|
|
648
|
+
return sql.insertSelectWhere("ledger").values({ k: "a", n: 1 }).toSql();
|
|
649
|
+
}, "sql-builder/no-where");
|
|
650
|
+
var noWhere = sql.insertSelectWhere("ledger").values({ k: "a", n: 1 }).allowNoWhere().toSql();
|
|
651
|
+
check("insertSelectWhere allowNoWhere() emits a guard-less SELECT",
|
|
652
|
+
noWhere.sql === 'INSERT INTO ledger ("k", "n") SELECT ?, ?' && noWhere.params.length === 2);
|
|
653
|
+
|
|
654
|
+
// No values() -> empty-values; values() missing a declared column -> missing-column;
|
|
655
|
+
// an extra key not in the declared column set -> extra-column (no silent data drop).
|
|
656
|
+
rejects("insertSelectWhere without values throws", function () {
|
|
657
|
+
return sql.insertSelectWhere("ledger").columns(["k"]).whereOp("k", "=", "a").toSql();
|
|
658
|
+
}, "sql-builder/empty-values");
|
|
659
|
+
rejects("insertSelectWhere positional value-count mismatch", function () {
|
|
660
|
+
return sql.insertSelectWhere("ledger").columns(["k", "n"]).values(["only-one"]);
|
|
661
|
+
}, "sql-builder/value-count");
|
|
662
|
+
rejects("insertSelectWhere row missing a declared column", function () {
|
|
663
|
+
return sql.insertSelectWhere("ledger").columns(["k", "n"]).values({ k: "a" });
|
|
664
|
+
}, "sql-builder/missing-column");
|
|
665
|
+
// extra-column only fires against an EXPLICIT column set (an inferred set
|
|
666
|
+
// can't have an extra key) — declare ["k","n"] first, then the ghost key.
|
|
667
|
+
rejects("insertSelectWhere row with an extra column", function () {
|
|
668
|
+
return sql.insertSelectWhere("ledger").columns(["k", "n"]).values({ k: "a", n: 1, ghost: 2 })
|
|
669
|
+
.whereOp("k", "=", "a").toSql();
|
|
670
|
+
}, "sql-builder/extra-column");
|
|
671
|
+
|
|
672
|
+
// The output gate still fires: a NUL byte in a bound cell value is refused
|
|
673
|
+
// by _assertEmittable, same as every other verb.
|
|
674
|
+
rejects("insertSelectWhere NUL in a cell value refused by the output gate", function () {
|
|
675
|
+
return sql.insertSelectWhere("ledger").values({ k: "x" + NUL + "y", n: 1 })
|
|
676
|
+
.whereOp("n", "=", 1).toSql();
|
|
677
|
+
}, "sql-builder/null-byte-param");
|
|
678
|
+
|
|
679
|
+
// Sub-builder dialect-mismatch is refused (a mysql guard sub spliced into a
|
|
680
|
+
// default-sqlite parent has baked the wrong quote char).
|
|
681
|
+
rejects("insertSelectWhere guard sub dialect-mismatch refused", function () {
|
|
682
|
+
return sql.insertSelectWhere("ledger")
|
|
683
|
+
.values({ k: "a", n: 1 })
|
|
684
|
+
.whereExists(sql.select("other", { dialect: "mysql" }).columns(["id"])).toSql();
|
|
685
|
+
}, "sql-builder/dialect-mismatch");
|
|
686
|
+
|
|
687
|
+
// toExternalSql translates ? -> $N on postgres at the boundary (direct-driver path).
|
|
688
|
+
var ext = sql.insertSelectWhere("ledger", { dialect: "postgres" })
|
|
689
|
+
.values({ k: "a", n: 1 }).whereOp("k", "=", "a").toExternalSql("postgres");
|
|
690
|
+
check("insertSelectWhere toExternalSql postgres $N",
|
|
691
|
+
ext.sql.indexOf("$1") !== -1 && ext.sql.indexOf("$2") !== -1 &&
|
|
692
|
+
ext.sql.indexOf("$3") !== -1 && ext.sql.indexOf("?") === -1);
|
|
593
693
|
}
|
|
594
694
|
|
|
595
695
|
module.exports = { run: run };
|
|
@@ -50,6 +50,42 @@ function testSplitTopLevelSemi() {
|
|
|
50
50
|
threw instanceof TypeError);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
function testParseTagList() {
|
|
54
|
+
var ptl = b.structuredFields.parseTagList;
|
|
55
|
+
// Default: `;` sep, `=` kv, lower-cased keys, raw values.
|
|
56
|
+
check("parseTagList: simple ;/= list, keys lower-cased",
|
|
57
|
+
JSON.stringify(ptl("v=DKIM1; K=rsa; p=ABC")) ===
|
|
58
|
+
JSON.stringify([["v", "DKIM1"], ["k", "rsa"], ["p", "ABC"]]));
|
|
59
|
+
// Empty entries + entries without a kv separator are skipped.
|
|
60
|
+
check("parseTagList: empty + no-kv entries skipped",
|
|
61
|
+
JSON.stringify(ptl("a=1; ; novalue ;b=2")) ===
|
|
62
|
+
JSON.stringify([["a", "1"], ["b", "2"]]));
|
|
63
|
+
// Repeated keys are PRESERVED as pairs (no last-wins collapse) —
|
|
64
|
+
// MTA-STS relies on this for repeated mx: lines.
|
|
65
|
+
check("parseTagList: repeated keys preserved as pairs",
|
|
66
|
+
JSON.stringify(ptl("mx=a; mx=b; mx=c")) ===
|
|
67
|
+
JSON.stringify([["mx", "a"], ["mx", "b"], ["mx", "c"]]));
|
|
68
|
+
// unfold collapses CRLF+WSP folds to a space before splitting (DKIM FWS).
|
|
69
|
+
check("parseTagList: unfold collapses folded value",
|
|
70
|
+
JSON.stringify(ptl("p=ABC\r\n DEF", { unfold: true, stripValueWs: true })) ===
|
|
71
|
+
JSON.stringify([["p", "ABCDEF"]]));
|
|
72
|
+
// stripValueWs removes all whitespace inside a value (DKIM/ARC FWS).
|
|
73
|
+
check("parseTagList: stripValueWs removes internal whitespace",
|
|
74
|
+
JSON.stringify(ptl("p=A B\tC", { stripValueWs: true })) ===
|
|
75
|
+
JSON.stringify([["p", "ABC"]]));
|
|
76
|
+
// Regex sep + colon kv (MTA-STS shape), value whitespace kept.
|
|
77
|
+
check("parseTagList: regex sep + colon kv",
|
|
78
|
+
JSON.stringify(ptl("version: STSv1\r\nmode: enforce\nmx: a", { sep: /\r?\n/, kvSep: ":" })) ===
|
|
79
|
+
JSON.stringify([["version", "STSv1"], ["mode", "enforce"], ["mx", "a"]]));
|
|
80
|
+
// lowerKey:false keeps original key case; first `=` wins (value may hold `=`).
|
|
81
|
+
check("parseTagList: lowerKey:false preserves case, first kvSep wins",
|
|
82
|
+
JSON.stringify(ptl("Key=a=b=c", { lowerKey: false })) ===
|
|
83
|
+
JSON.stringify([["Key", "a=b=c"]]));
|
|
84
|
+
// Non-string input is coerced (String()) — empty/garbage yields [].
|
|
85
|
+
check("parseTagList: empty string → []",
|
|
86
|
+
JSON.stringify(ptl("")) === JSON.stringify([]));
|
|
87
|
+
}
|
|
88
|
+
|
|
53
89
|
function testRefuseControlBytes() {
|
|
54
90
|
var SfError = b.structuredFields.refuseControlBytes;
|
|
55
91
|
// Generate a generic framework-error-shaped class for the test.
|
|
@@ -178,12 +214,56 @@ function testUnquoteSfString() {
|
|
|
178
214
|
b.structuredFields.unquoteSfString(null) === null);
|
|
179
215
|
}
|
|
180
216
|
|
|
217
|
+
function testForEachKeyValue() {
|
|
218
|
+
// Bare entries (no kvSep → null value) are skipped; surviving values trimmed;
|
|
219
|
+
// index reflects the kvps position (so the skipped bare entry leaves a gap).
|
|
220
|
+
var kvps = b.structuredFields.parseKeyValuePieces("a = 1 ; b ; c=3".split(";"));
|
|
221
|
+
var seen = [];
|
|
222
|
+
b.structuredFields.forEachKeyValue(kvps, function (key, value, i) {
|
|
223
|
+
seen.push([key, value, i]);
|
|
224
|
+
});
|
|
225
|
+
check("forEachKeyValue: skips bare (null-value) entries", seen.length === 2);
|
|
226
|
+
check("forEachKeyValue: trims surviving values + passes key",
|
|
227
|
+
seen[0][0] === "a" && seen[0][1] === "1" &&
|
|
228
|
+
seen[1][0] === "c" && seen[1][1] === "3");
|
|
229
|
+
check("forEachKeyValue: index reflects kvps position (bare skipped)",
|
|
230
|
+
seen[0][2] === 0 && seen[1][2] === 2);
|
|
231
|
+
|
|
232
|
+
// A handler `return` skips the current entry — `continue` semantics.
|
|
233
|
+
var kept = [];
|
|
234
|
+
b.structuredFields.forEachKeyValue(
|
|
235
|
+
b.structuredFields.parseKeyValuePieces("x=1; y=2; z=3".split(";")),
|
|
236
|
+
function (key) { if (key === "y") return; kept.push(key); });
|
|
237
|
+
check("forEachKeyValue: handler return skips like continue", kept.join(",") === "x,z");
|
|
238
|
+
|
|
239
|
+
// Non-function handler throws at the wiring (config-time tier).
|
|
240
|
+
var threw = null;
|
|
241
|
+
try { b.structuredFields.forEachKeyValue([], "nope"); } catch (e) { threw = e; }
|
|
242
|
+
check("forEachKeyValue: non-function handler throws TypeError", threw instanceof TypeError);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function testUnfoldHeaderContinuations() {
|
|
246
|
+
// RFC 5322 header unfolding: a CRLF (or bare LF) followed by WSP is
|
|
247
|
+
// folding whitespace — unfold collapses each run to a single space so a
|
|
248
|
+
// wrapped header value (DKIM/DMARC/Authentication-Results, etc.) parses
|
|
249
|
+
// as one logical line.
|
|
250
|
+
check("unfoldHeaderContinuations collapses CRLF+WSP to a single space",
|
|
251
|
+
b.structuredFields.unfoldHeaderContinuations("v=DKIM1;\r\n k=rsa") === "v=DKIM1; k=rsa");
|
|
252
|
+
check("unfoldHeaderContinuations handles bare LF + tab",
|
|
253
|
+
b.structuredFields.unfoldHeaderContinuations("a=1;\n\tb=2") === "a=1; b=2");
|
|
254
|
+
check("unfoldHeaderContinuations leaves an unfolded value unchanged",
|
|
255
|
+
b.structuredFields.unfoldHeaderContinuations("a=1; b=2") === "a=1; b=2");
|
|
256
|
+
}
|
|
257
|
+
|
|
181
258
|
async function run() {
|
|
182
259
|
testSplitTopLevelComma();
|
|
183
260
|
testSplitTopLevelSemi();
|
|
261
|
+
testParseTagList();
|
|
262
|
+
testForEachKeyValue();
|
|
184
263
|
testRefuseControlBytes();
|
|
185
264
|
testContainsControlBytes();
|
|
186
265
|
testUnquoteSfString();
|
|
266
|
+
testUnfoldHeaderContinuations();
|
|
187
267
|
}
|
|
188
268
|
|
|
189
269
|
module.exports = { run: run };
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* validateOpts.shape — declarative opts validator that collapses the
|
|
4
|
+
* per-factory `requireObject + requireNonEmptyString + optionalPositiveFinite
|
|
5
|
+
* + ...` preamble into one schema-driven call.
|
|
6
|
+
*
|
|
7
|
+
* Covers: top-level object requirement; each rule token dispatching to the
|
|
8
|
+
* right underlying check (required/optional string, string-array, boolean,
|
|
9
|
+
* positive-int/finite, non-negative, function, plain-object); the
|
|
10
|
+
* dependency-with-methods rule (required + optional); unknown-rule-throws; that
|
|
11
|
+
* a valid opts object passes and is returned.
|
|
12
|
+
*
|
|
13
|
+
* Run standalone: node test/layer-0-primitives/validate-opts-shape.test.js
|
|
14
|
+
*/
|
|
15
|
+
var helpers = require("../helpers");
|
|
16
|
+
var check = helpers.check;
|
|
17
|
+
var validateOpts = require("../../lib/validate-opts");
|
|
18
|
+
var { WebhookDispatcherError, defineClass } = require("../../lib/framework-error");
|
|
19
|
+
|
|
20
|
+
var E = WebhookDispatcherError;
|
|
21
|
+
var CODE = "test/bad-opt";
|
|
22
|
+
|
|
23
|
+
function _throws(fn, re) {
|
|
24
|
+
try { fn(); return false; }
|
|
25
|
+
catch (e) { return re ? re.test(e.message || "") : true; }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function run() {
|
|
29
|
+
// top-level: opts must be an object.
|
|
30
|
+
check("non-object opts throws", _throws(function () {
|
|
31
|
+
validateOpts.shape(null, { a: "required-string" }, "t", E, CODE);
|
|
32
|
+
}, /must be an object/));
|
|
33
|
+
|
|
34
|
+
// required-string
|
|
35
|
+
check("required-string missing throws", _throws(function () {
|
|
36
|
+
validateOpts.shape({}, { a: "required-string" }, "t", E, CODE);
|
|
37
|
+
}, /non-empty string/));
|
|
38
|
+
check("required-string present passes",
|
|
39
|
+
validateOpts.shape({ a: "x" }, { a: "required-string" }, "t", E, CODE).a === "x");
|
|
40
|
+
|
|
41
|
+
// optional-* absent is fine
|
|
42
|
+
check("optional-string absent ok", (function () {
|
|
43
|
+
validateOpts.shape({}, { a: "optional-string" }, "t", E, CODE); return true;
|
|
44
|
+
})());
|
|
45
|
+
check("optional-positive-finite bad throws", _throws(function () {
|
|
46
|
+
validateOpts.shape({ n: -1 }, { n: "optional-positive-finite" }, "t", E, CODE);
|
|
47
|
+
}));
|
|
48
|
+
check("optional-positive-int bad throws", _throws(function () {
|
|
49
|
+
validateOpts.shape({ n: 1.5 }, { n: "optional-positive-int" }, "t", E, CODE);
|
|
50
|
+
}));
|
|
51
|
+
check("optional-boolean bad throws", _throws(function () {
|
|
52
|
+
validateOpts.shape({ b: "yes" }, { b: "optional-boolean" }, "t", E, CODE);
|
|
53
|
+
}));
|
|
54
|
+
check("optional-function bad throws", _throws(function () {
|
|
55
|
+
validateOpts.shape({ f: 42 }, { f: "optional-function" }, "t", E, CODE);
|
|
56
|
+
}));
|
|
57
|
+
check("optional-non-negative bad throws", _throws(function () {
|
|
58
|
+
validateOpts.shape({ n: -5 }, { n: "optional-non-negative" }, "t", E, CODE);
|
|
59
|
+
}));
|
|
60
|
+
|
|
61
|
+
// optional-date: present-but-invalid throws; absent ok; valid passes.
|
|
62
|
+
check("optional-date non-Date throws", _throws(function () {
|
|
63
|
+
validateOpts.shape({ at: "2020-01-01" }, { at: "optional-date" }, "t", E, CODE);
|
|
64
|
+
}, /valid Date/));
|
|
65
|
+
check("optional-date Invalid Date throws", _throws(function () {
|
|
66
|
+
validateOpts.shape({ at: new Date("nope") }, { at: "optional-date" }, "t", E, CODE);
|
|
67
|
+
}, /valid Date/));
|
|
68
|
+
check("optional-date absent ok", (function () {
|
|
69
|
+
validateOpts.shape({}, { at: "optional-date" }, "t", E, CODE); return true;
|
|
70
|
+
})());
|
|
71
|
+
check("optional-date valid Date passes",
|
|
72
|
+
validateOpts.shape({ at: new Date(0) }, { at: "optional-date" }, "t", E, CODE).at instanceof Date);
|
|
73
|
+
// direct optionalDate: returns the value when absent / valid; throws the
|
|
74
|
+
// `<label> must be a valid Date` message (byte-identical to the old hand-rolls).
|
|
75
|
+
check("optionalDate(undefined) returns undefined",
|
|
76
|
+
validateOpts.optionalDate(undefined, "x.at", E, CODE) === undefined);
|
|
77
|
+
check("optionalDate(validDate) returns it", (function () {
|
|
78
|
+
var d = new Date(0); return validateOpts.optionalDate(d, "x.at", E, CODE) === d;
|
|
79
|
+
})());
|
|
80
|
+
check("optionalDate(InvalidDate) throws '<label> must be a valid Date'", _throws(function () {
|
|
81
|
+
validateOpts.optionalDate(new Date("nope"), "x.verify: opts.at", E, CODE);
|
|
82
|
+
}, /^x\.verify: opts\.at must be a valid Date$/));
|
|
83
|
+
|
|
84
|
+
// string-array: per-element validation
|
|
85
|
+
check("optional-string-array bad element throws", _throws(function () {
|
|
86
|
+
validateOpts.shape({ a: ["ok", 3] }, { a: "optional-string-array" }, "t", E, CODE);
|
|
87
|
+
}));
|
|
88
|
+
check("optional-string-array valid passes", (function () {
|
|
89
|
+
validateOpts.shape({ a: ["x", "y"] }, { a: "optional-string-array" }, "t", E, CODE); return true;
|
|
90
|
+
})());
|
|
91
|
+
|
|
92
|
+
// required-object field
|
|
93
|
+
check("required-object missing throws", _throws(function () {
|
|
94
|
+
validateOpts.shape({}, { cfg: "required-object" }, "t", E, CODE);
|
|
95
|
+
}));
|
|
96
|
+
|
|
97
|
+
// dependency with methods
|
|
98
|
+
check("methods dep non-object throws", _throws(function () {
|
|
99
|
+
validateOpts.shape({ db: 5 }, { db: { methods: ["query"] } }, "t", E, CODE);
|
|
100
|
+
}));
|
|
101
|
+
check("methods dep missing method throws", _throws(function () {
|
|
102
|
+
validateOpts.shape({ db: {} }, { db: { methods: ["query", "transaction"] } }, "t", E, CODE);
|
|
103
|
+
}, /query/));
|
|
104
|
+
check("methods dep complete passes", (function () {
|
|
105
|
+
validateOpts.shape({ db: { query: function () {}, transaction: function () {} } },
|
|
106
|
+
{ db: { methods: ["query", "transaction"] } }, "t", E, CODE); return true;
|
|
107
|
+
})());
|
|
108
|
+
check("optional methods dep absent ok", (function () {
|
|
109
|
+
validateOpts.shape({}, { db: { methods: ["query"], optional: true } }, "t", E, CODE); return true;
|
|
110
|
+
})());
|
|
111
|
+
|
|
112
|
+
// requireMethods permanent flag — a config-time dependency check whose
|
|
113
|
+
// failure is non-retryable forwards `permanent` to the framework error's
|
|
114
|
+
// third constructor argument. Uses a GENERIC error class (arg3 = permanent)
|
|
115
|
+
// so the flag is observable (alwaysPermanent classes set it unconditionally).
|
|
116
|
+
var PermTestError = defineClass("ValidateOptsPermTestError");
|
|
117
|
+
check("requireMethods without permanent → permanent falsy", (function () {
|
|
118
|
+
try { validateOpts.requireMethods({}, ["query"], "x.db", PermTestError, "C"); return false; }
|
|
119
|
+
catch (e) { return e.permanent === false; }
|
|
120
|
+
})());
|
|
121
|
+
check("requireMethods permanent=true → error.permanent true", (function () {
|
|
122
|
+
try { validateOpts.requireMethods({}, ["query"], "x.db", PermTestError, "C", true); return false; }
|
|
123
|
+
catch (e) { return e.permanent === true; }
|
|
124
|
+
})());
|
|
125
|
+
check("requireMethods permanent=true on missing method → permanent true", (function () {
|
|
126
|
+
try { validateOpts.requireMethods({ query: function () {} }, ["query", "tx"], "x.db", PermTestError, "C", true); return false; }
|
|
127
|
+
catch (e) { return e.permanent === true && e.code === "C"; }
|
|
128
|
+
})());
|
|
129
|
+
check("shape methods rule permanent → error.permanent true", (function () {
|
|
130
|
+
try { validateOpts.shape({ db: 5 }, { db: { methods: ["query"], permanent: true } }, "t", PermTestError, "C"); return false; }
|
|
131
|
+
catch (e) { return e.permanent === true; }
|
|
132
|
+
})());
|
|
133
|
+
|
|
134
|
+
// per-field code override preserves a distinct code per field
|
|
135
|
+
check("per-field code override preserved", (function () {
|
|
136
|
+
try {
|
|
137
|
+
validateOpts.shape({ a: "ok" }, {
|
|
138
|
+
a: { rule: "required-string", code: "BAD_A" },
|
|
139
|
+
b: { rule: "required-string", code: "BAD_B" },
|
|
140
|
+
}, "t", E, CODE);
|
|
141
|
+
return false;
|
|
142
|
+
} catch (e) { return e.code === "BAD_B"; } // b is missing → its own code
|
|
143
|
+
})());
|
|
144
|
+
check("per-field label override preserved", (function () {
|
|
145
|
+
try {
|
|
146
|
+
validateOpts.shape({}, { a: { rule: "required-string", label: "custom.path" } }, "t", E, CODE);
|
|
147
|
+
return false;
|
|
148
|
+
} catch (e) { return /custom\.path/.test(e.message); }
|
|
149
|
+
})());
|
|
150
|
+
|
|
151
|
+
// arbitrary validator function — the universal hatch
|
|
152
|
+
check("function rule runs + can throw", _throws(function () {
|
|
153
|
+
validateOpts.shape({ a: 5 }, {
|
|
154
|
+
a: function (v, l, e, c) { if (v > 3) throw e.factory(c, l + " too big"); },
|
|
155
|
+
}, "t", E, CODE);
|
|
156
|
+
}, /too big/));
|
|
157
|
+
check("function rule receives label/errorClass/code", (function () {
|
|
158
|
+
var seen = null;
|
|
159
|
+
validateOpts.shape({ a: 1 }, {
|
|
160
|
+
a: function (v, l, e, c) { seen = { l: l, hasFactory: typeof e.factory === "function", c: c }; },
|
|
161
|
+
}, "t", E, CODE);
|
|
162
|
+
return seen && seen.l === "t: a" && seen.hasFactory && seen.c === CODE;
|
|
163
|
+
})());
|
|
164
|
+
|
|
165
|
+
// nested sub-object shape
|
|
166
|
+
check("nested shape validates sub-object field", _throws(function () {
|
|
167
|
+
validateOpts.shape({ srv: { issuer: "x" } }, {
|
|
168
|
+
srv: { shape: { issuer: "required-string", jwksUri: "required-string" } },
|
|
169
|
+
}, "t", E, CODE); // jwksUri missing
|
|
170
|
+
}, /jwksUri|non-empty string/));
|
|
171
|
+
check("nested shape passes when complete", (function () {
|
|
172
|
+
validateOpts.shape({ srv: { issuer: "x", jwksUri: "y" } }, {
|
|
173
|
+
srv: { shape: { issuer: "required-string", jwksUri: "required-string" } },
|
|
174
|
+
}, "t", E, CODE);
|
|
175
|
+
return true;
|
|
176
|
+
})());
|
|
177
|
+
check("optional nested shape absent ok", (function () {
|
|
178
|
+
validateOpts.shape({}, { srv: { shape: { issuer: "required-string" }, optional: true } }, "t", E, CODE);
|
|
179
|
+
return true;
|
|
180
|
+
})());
|
|
181
|
+
|
|
182
|
+
// mandatory exhaustive: an undeclared opt is always rejected
|
|
183
|
+
check("undeclared opt rejected (mandatory exhaustive)", _throws(function () {
|
|
184
|
+
validateOpts.shape({ known: "x", typo: 1 }, { known: "required-string" }, "t", E, CODE);
|
|
185
|
+
}, /unknown opt "typo"/));
|
|
186
|
+
check("options.allow permits a pass-through key", (function () {
|
|
187
|
+
validateOpts.shape({ known: "x", fwd: 1 }, { known: "required-string" },
|
|
188
|
+
"t", E, CODE, { allow: ["fwd"] });
|
|
189
|
+
return true;
|
|
190
|
+
})());
|
|
191
|
+
check("exhaustive has no opt-out (only allow)", _throws(function () {
|
|
192
|
+
// even passing a (now-ignored) exhaustive:false cannot disable the contract
|
|
193
|
+
validateOpts.shape({ known: "x", extra: 1 }, { known: "required-string" },
|
|
194
|
+
"t", E, CODE, { exhaustive: false });
|
|
195
|
+
}, /unknown opt "extra"/));
|
|
196
|
+
|
|
197
|
+
// numeric-bounds int tokens (finite — reject Infinity, unlike optional-positive-int)
|
|
198
|
+
check("optional-positive-finite-int rejects Infinity", _throws(function () {
|
|
199
|
+
validateOpts.shape({ n: Infinity }, { n: "optional-positive-finite-int" }, "t", E, CODE);
|
|
200
|
+
}));
|
|
201
|
+
check("optional-positive-finite-int rejects 0", _throws(function () {
|
|
202
|
+
validateOpts.shape({ n: 0 }, { n: "optional-positive-finite-int" }, "t", E, CODE);
|
|
203
|
+
}));
|
|
204
|
+
check("optional-positive-finite-int accepts a positive int", (function () {
|
|
205
|
+
validateOpts.shape({ n: 1024 }, { n: "optional-positive-finite-int" }, "t", E, CODE);
|
|
206
|
+
return true;
|
|
207
|
+
})());
|
|
208
|
+
check("optional-non-negative-finite-int accepts 0", (function () {
|
|
209
|
+
validateOpts.shape({ n: 0 }, { n: "optional-non-negative-finite-int" }, "t", E, CODE);
|
|
210
|
+
return true;
|
|
211
|
+
})());
|
|
212
|
+
|
|
213
|
+
// unknown rule is the author's bug — throws loudly
|
|
214
|
+
check("unknown rule token throws", _throws(function () {
|
|
215
|
+
validateOpts.shape({}, { a: "bogus-rule" }, "t", E, CODE);
|
|
216
|
+
}, /unknown shape rule/));
|
|
217
|
+
|
|
218
|
+
// a full mixed schema passes and returns opts
|
|
219
|
+
var opts = { externalDb: { query: function () {}, transaction: function () {} },
|
|
220
|
+
name: "svc", maxAttempts: 8, dryRun: false, hook: function () {} };
|
|
221
|
+
check("mixed valid schema returns opts", validateOpts.shape(opts, {
|
|
222
|
+
externalDb: { methods: ["query", "transaction"] },
|
|
223
|
+
name: "required-string",
|
|
224
|
+
maxAttempts: "optional-positive-finite",
|
|
225
|
+
dryRun: "optional-boolean",
|
|
226
|
+
hook: "optional-function",
|
|
227
|
+
}, "svc", E, CODE) === opts);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
module.exports = { run: run };
|
|
231
|
+
|
|
232
|
+
if (require.main === module) {
|
|
233
|
+
try { run(); console.log("[validate-opts-shape] OK — " + helpers.getChecks() + " checks passed"); }
|
|
234
|
+
catch (e) { console.error("FAIL:", e && e.stack || e); process.exit(1); }
|
|
235
|
+
}
|