@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
|
@@ -45,12 +45,14 @@ var safeAsync = require("./safe-async");
|
|
|
45
45
|
var safeSql = require("./safe-sql");
|
|
46
46
|
var sql = require("./sql");
|
|
47
47
|
var C = require("./constants");
|
|
48
|
+
var boundedMap = require("./bounded-map");
|
|
48
49
|
var { FrameworkError } = require("./framework-error");
|
|
49
50
|
|
|
50
|
-
// Allowlist of chain table names.
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
// table
|
|
51
|
+
// Allowlist of chain table names. The two framework chains ship registered; a
|
|
52
|
+
// consumer's own append-only hash-chained table is added at config time via
|
|
53
|
+
// registerTable() BEFORE create() accepts it. The allowlist is never bypassed
|
|
54
|
+
// — an unregistered table throws at create(), so a misconfig can't point a
|
|
55
|
+
// chain-writer at a non-chain table and corrupt the chain semantics.
|
|
54
56
|
var ALLOWED_CHAIN_TABLES = new Set(["audit_log", "consent_log"]);
|
|
55
57
|
|
|
56
58
|
var FRAMEWORK_SQL_TIMEOUT_MS = C.TIME.seconds(30);
|
|
@@ -74,24 +76,83 @@ class ChainWriterError extends FrameworkError {
|
|
|
74
76
|
}
|
|
75
77
|
}
|
|
76
78
|
|
|
79
|
+
/**
|
|
80
|
+
* @primitive b.chainWriter.registerTable
|
|
81
|
+
* @signature b.chainWriter.registerTable(table)
|
|
82
|
+
* @since 0.15.13
|
|
83
|
+
* @status stable
|
|
84
|
+
* @related b.chainWriter.create, b.safeSql.validateIdentifier
|
|
85
|
+
*
|
|
86
|
+
* Register a consumer-owned append-only table as chain-writable so
|
|
87
|
+
* `b.chainWriter.create({ table })` accepts it. Call once at boot (config
|
|
88
|
+
* time) for each app table carrying the chain columns (`monotonicCounter`,
|
|
89
|
+
* `recordedAt`, `nonce`, `prevHash`, `rowHash` — plus `fencingToken` in
|
|
90
|
+
* cluster mode). The framework chains (`audit_log`, `consent_log`) are
|
|
91
|
+
* pre-registered. Throws `ChainWriterError` (`chain-writer/invalid-config`) on
|
|
92
|
+
* a non-identifier name; the name is validated against the SQL identifier
|
|
93
|
+
* rules because it is interpolated into the chain SQL. Idempotent. Returns the
|
|
94
|
+
* registered name.
|
|
95
|
+
*
|
|
96
|
+
* Operator footgun to avoid on a MULTI-chain table (one configured with a
|
|
97
|
+
* `chainKey`): the per-key writer restarts `monotonicCounter` at 1 for each
|
|
98
|
+
* key, so a UNIQUE index on `monotonicCounter` ALONE (the shape the framework
|
|
99
|
+
* `audit_log` uses for its single chain) will reject the second key's first
|
|
100
|
+
* row. A keyed chain's uniqueness must be the composite
|
|
101
|
+
* `(chainKey, monotonicCounter)`, never `monotonicCounter` by itself.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* b.chainWriter.registerTable("device_event_log");
|
|
105
|
+
* var writer = b.chainWriter.create({
|
|
106
|
+
* table: "device_event_log",
|
|
107
|
+
* chainKey: "deviceId",
|
|
108
|
+
* columnsForInsert: ["_id", "deviceId", "monotonicCounter", "recordedAt",
|
|
109
|
+
* "kind", "payload",
|
|
110
|
+
* "prevHash", "rowHash", "nonce", "fencingToken"],
|
|
111
|
+
* hashableColumns: ["_id", "deviceId", "monotonicCounter", "recordedAt",
|
|
112
|
+
* "kind", "payload"],
|
|
113
|
+
* });
|
|
114
|
+
*/
|
|
115
|
+
function registerTable(table) {
|
|
116
|
+
if (typeof table !== "string" || table.length === 0) {
|
|
117
|
+
throw new ChainWriterError(
|
|
118
|
+
"registerTable requires a non-empty table name",
|
|
119
|
+
"chain-writer/invalid-config"
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
// Identifier-validate before admitting to the allowlist — the name is
|
|
123
|
+
// interpolated into the chain SQL, so the same shape rules create() relies
|
|
124
|
+
// on must hold here, at the config-time entry point.
|
|
125
|
+
safeSql.validateIdentifier(table);
|
|
126
|
+
ALLOWED_CHAIN_TABLES.add(table);
|
|
127
|
+
return table;
|
|
128
|
+
}
|
|
129
|
+
|
|
77
130
|
/**
|
|
78
131
|
* @primitive b.chainWriter.create
|
|
79
132
|
* @signature b.chainWriter.create(opts)
|
|
80
133
|
* @since 0.8.48
|
|
81
134
|
* @status stable
|
|
82
|
-
* @related b.audit, b.consent, b.auditChain
|
|
135
|
+
* @related b.audit, b.consent, b.auditChain, b.chainWriter.registerTable
|
|
83
136
|
*
|
|
84
137
|
* Build a chain-writer bound to a single hash-chained table. Returns
|
|
85
|
-
* `{ table, append, _resetForTest, _getMutexForTest }`.
|
|
86
|
-
* is the public surface — async, leader-gated,
|
|
87
|
-
* success it returns the logical row decorated with the
|
|
88
|
-
* `rowHash` and `prevHash`.
|
|
138
|
+
* `{ table, chainKey, append, _resetForTest, _getMutexForTest }`.
|
|
139
|
+
* `append(logical)` is the public surface — async, leader-gated,
|
|
140
|
+
* mutex-serialized; on success it returns the logical row decorated with the
|
|
141
|
+
* computed `rowHash` and `prevHash`.
|
|
142
|
+
*
|
|
143
|
+
* A `chainKey` makes one table hold many independent chains (one per account /
|
|
144
|
+
* device / tenant): tip-read, counter monotonicity, and the append Mutex all
|
|
145
|
+
* scope per key, so concurrent appends to DIFFERENT keys run in parallel while
|
|
146
|
+
* same-key appends serialize. Bind `chainKey` into `hashableColumns` so the
|
|
147
|
+
* partition is tamper-evident in the row hash, and key the table's uniqueness
|
|
148
|
+
* constraint on `(chainKey, monotonicCounter)`, never `monotonicCounter` alone.
|
|
89
149
|
*
|
|
90
150
|
* @opts
|
|
91
|
-
* table: string, //
|
|
151
|
+
* table: string, // a registered chain table (audit_log | consent_log | registerTable name)
|
|
152
|
+
* chainKey: string, // optional partition column — one independent chain per key value
|
|
92
153
|
* columnsForInsert: string[], // INSERT column order (every name is identifier-validated)
|
|
93
154
|
* hashableColumns: string[], // columns that participate in the rowHash canonicalization
|
|
94
|
-
* validateInput: Function, // optional; (logical)
|
|
155
|
+
* validateInput: Function, // optional; (logical) -> throws on invalid shape
|
|
95
156
|
*
|
|
96
157
|
* @example
|
|
97
158
|
* var writer = b.chainWriter.create({
|
|
@@ -136,27 +197,57 @@ function create(opts) {
|
|
|
136
197
|
var hashableColumns = opts.hashableColumns.slice();
|
|
137
198
|
var validateInput = opts.validateInput || null;
|
|
138
199
|
|
|
139
|
-
//
|
|
200
|
+
// chainKey: the partition column for many independent chains in one table
|
|
201
|
+
// (one chain per account / device / tenant). When set, the tip read,
|
|
202
|
+
// counter priming, and the append Mutex all scope to a single key value, so
|
|
203
|
+
// appends to DIFFERENT keys run in parallel while same-key appends
|
|
204
|
+
// serialize. Identifier-validated at config time (THROW tier) because it is
|
|
205
|
+
// interpolated as a column name; it must also appear in columnsForInsert so
|
|
206
|
+
// every row carries its partition key.
|
|
207
|
+
var chainKey = opts.chainKey || null;
|
|
208
|
+
if (chainKey !== null) {
|
|
209
|
+
safeSql.validateIdentifier(chainKey);
|
|
210
|
+
if (columnsForInsert.indexOf(chainKey) === -1) {
|
|
211
|
+
throw new ChainWriterError(
|
|
212
|
+
"chainKey '" + chainKey + "' must be listed in columnsForInsert so " +
|
|
213
|
+
"every appended row carries its partition key",
|
|
214
|
+
"chain-writer/invalid-config"
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Per-CHAIN-KEY Mutex serializes the read-prev-tip + compute-hash + insert
|
|
140
220
|
// sequence. Without serialization, two concurrent awaiting append() calls
|
|
141
|
-
// would hash against the same prev-tip and
|
|
142
|
-
//
|
|
143
|
-
|
|
221
|
+
// would hash against the same prev-tip and fork the chain. A single-chain
|
|
222
|
+
// writer (no chainKey) uses one shared lock under the sentinel key; a
|
|
223
|
+
// multi-chain writer keys the lock by the partition value so appends to
|
|
224
|
+
// DIFFERENT keys run concurrently while same-key appends serialize.
|
|
225
|
+
var _SINGLE_CHAIN_KEY = "__single_chain__"; // sentinel; not a valid driver value
|
|
226
|
+
var _mutexByKey = new Map();
|
|
227
|
+
function _mutexFor(keyValue) {
|
|
228
|
+
var k = chainKey !== null ? String(keyValue) : _SINGLE_CHAIN_KEY;
|
|
229
|
+
return boundedMap.getOrInsert(_mutexByKey, k, function () { return new safeAsync.Mutex(); });
|
|
230
|
+
}
|
|
144
231
|
|
|
145
|
-
// Lazy counter primer — first append
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
|
|
149
|
-
var
|
|
232
|
+
// Lazy counter primer — first append for a given key reads
|
|
233
|
+
// MAX(monotonicCounter) [WHERE chainKey = ?] and increments from there.
|
|
234
|
+
// Per-key so each chain's counter is independent; a per-key Once shares one
|
|
235
|
+
// in-flight init across concurrent first-callers for the same key.
|
|
236
|
+
var _nextCounterByKey = new Map();
|
|
237
|
+
var _counterInitByKey = new Map();
|
|
150
238
|
|
|
151
|
-
function _ensureCounterInit() {
|
|
152
|
-
|
|
153
|
-
|
|
239
|
+
function _ensureCounterInit(keyValue) {
|
|
240
|
+
var k = chainKey !== null ? String(keyValue) : _SINGLE_CHAIN_KEY;
|
|
241
|
+
var once = boundedMap.getOrInsert(_counterInitByKey, k, function () {
|
|
242
|
+
return new safeAsync.Once(async function () {
|
|
154
243
|
// BARE logical table name — clusterStorage rewrites the framework
|
|
155
|
-
// name to the configured-prefix form
|
|
156
|
-
// quotes the camelCase column +
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
244
|
+
// name to the configured-prefix form (consumer tables pass through
|
|
245
|
+
// unchanged) and placeholderizes; b.sql quotes the camelCase column +
|
|
246
|
+
// emits the MAX aggregate. A keyed writer scopes the MAX to the
|
|
247
|
+
// partition via a bound WHERE.
|
|
248
|
+
var maxQ = sql.select(table, _sqlOpts()).max("monotonicCounter", "m");
|
|
249
|
+
if (chainKey !== null) maxQ = maxQ.where(chainKey, keyValue);
|
|
250
|
+
var maxBuilt = maxQ.toSql();
|
|
160
251
|
var row = await safeAsync.withTimeout(
|
|
161
252
|
safeAsync.asyncRetry(function () {
|
|
162
253
|
return clusterStorage.executeOne(maxBuilt.sql, maxBuilt.params);
|
|
@@ -164,18 +255,21 @@ function create(opts) {
|
|
|
164
255
|
FRAMEWORK_SQL_TIMEOUT_MS,
|
|
165
256
|
{ name: table + ".readMaxCounter" }
|
|
166
257
|
);
|
|
167
|
-
|
|
258
|
+
_nextCounterByKey.set(k, (row && row.m ? Number(row.m) : 0) + 1);
|
|
168
259
|
});
|
|
169
|
-
}
|
|
170
|
-
return
|
|
260
|
+
});
|
|
261
|
+
return once.invoke();
|
|
171
262
|
}
|
|
172
263
|
|
|
173
|
-
async function _readChainTipRow() {
|
|
174
|
-
var
|
|
264
|
+
async function _readChainTipRow(keyValue) {
|
|
265
|
+
var tipQ = sql.select(table, _sqlOpts())
|
|
175
266
|
.columns(["rowHash"])
|
|
176
267
|
.orderBy("monotonicCounter", "desc")
|
|
177
|
-
.limit(1)
|
|
178
|
-
|
|
268
|
+
.limit(1);
|
|
269
|
+
// Scope the tip to the partition so per-key chains link correctly —
|
|
270
|
+
// bound value, never interpolated.
|
|
271
|
+
if (chainKey !== null) tipQ = tipQ.where(chainKey, keyValue);
|
|
272
|
+
var tipBuilt = tipQ.toSql();
|
|
179
273
|
return await safeAsync.withTimeout(
|
|
180
274
|
safeAsync.asyncRetry(function () {
|
|
181
275
|
return clusterStorage.executeOne(tipBuilt.sql, tipBuilt.params);
|
|
@@ -209,15 +303,33 @@ function create(opts) {
|
|
|
209
303
|
async function append(logical) {
|
|
210
304
|
if (validateInput) validateInput(logical);
|
|
211
305
|
cluster.requireLeader();
|
|
212
|
-
await _ensureCounterInit();
|
|
213
306
|
|
|
214
|
-
|
|
215
|
-
|
|
307
|
+
// Resolve the partition key from the logical row for a multi-chain writer.
|
|
308
|
+
// Fail closed: a keyed writer with a missing / empty key can't pick a
|
|
309
|
+
// chain to append to, so refuse rather than silently fold the row into the
|
|
310
|
+
// wrong chain.
|
|
311
|
+
var keyValue = _SINGLE_CHAIN_KEY;
|
|
312
|
+
if (chainKey !== null) {
|
|
313
|
+
keyValue = logical ? logical[chainKey] : undefined;
|
|
314
|
+
if (keyValue === undefined || keyValue === null || String(keyValue).length === 0) {
|
|
315
|
+
throw new ChainWriterError(
|
|
316
|
+
"append: a chainKey writer requires logical['" + chainKey + "'] to be a " +
|
|
317
|
+
"non-empty partition value",
|
|
318
|
+
"chain-writer/invalid-input"
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
await _ensureCounterInit(keyValue);
|
|
323
|
+
|
|
324
|
+
return await _mutexFor(keyValue).runExclusive(async function () {
|
|
325
|
+
return await _appendInsideMutex(logical, keyValue);
|
|
216
326
|
});
|
|
217
327
|
}
|
|
218
328
|
|
|
219
|
-
async function _appendInsideMutex(logical) {
|
|
220
|
-
var
|
|
329
|
+
async function _appendInsideMutex(logical, keyValue) {
|
|
330
|
+
var _ck = chainKey !== null ? String(keyValue) : _SINGLE_CHAIN_KEY;
|
|
331
|
+
var counter = _nextCounterByKey.get(_ck);
|
|
332
|
+
_nextCounterByKey.set(_ck, counter + 1);
|
|
221
333
|
var nowMs = Date.now();
|
|
222
334
|
var nonce = generateBytes(C.BYTES.bytes(16));
|
|
223
335
|
|
|
@@ -239,8 +351,8 @@ function create(opts) {
|
|
|
239
351
|
if (!(hashableColumns[hci] in sealed)) sealed[hashableColumns[hci]] = null;
|
|
240
352
|
}
|
|
241
353
|
|
|
242
|
-
// Compute rowHash over the sealed content fields
|
|
243
|
-
var tipRow = await _readChainTipRow();
|
|
354
|
+
// Compute rowHash over the sealed content fields, linking to THIS key's tip.
|
|
355
|
+
var tipRow = await _readChainTipRow(keyValue);
|
|
244
356
|
var prevHash = tipRow ? tipRow.rowHash : auditChain.ZERO_HASH;
|
|
245
357
|
var rowHash = auditChain.computeRowHash(prevHash, sealed, nonce);
|
|
246
358
|
|
|
@@ -259,22 +371,25 @@ function create(opts) {
|
|
|
259
371
|
}
|
|
260
372
|
|
|
261
373
|
function _resetForTest() {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
374
|
+
_mutexByKey = new Map();
|
|
375
|
+
_counterInitByKey = new Map();
|
|
376
|
+
_nextCounterByKey = new Map();
|
|
265
377
|
}
|
|
266
378
|
|
|
267
379
|
return {
|
|
268
380
|
table: table,
|
|
381
|
+
chainKey: chainKey,
|
|
269
382
|
append: append,
|
|
270
383
|
_resetForTest: _resetForTest,
|
|
271
|
-
// Expose for diagnostic introspection
|
|
272
|
-
|
|
384
|
+
// Expose for diagnostic introspection — the lock for a given key (or the
|
|
385
|
+
// single-chain lock when no chainKey is configured).
|
|
386
|
+
_getMutexForTest: function (keyValue) { return _mutexFor(keyValue); },
|
|
273
387
|
};
|
|
274
388
|
}
|
|
275
389
|
|
|
276
390
|
module.exports = {
|
|
277
391
|
create: create,
|
|
392
|
+
registerTable: registerTable,
|
|
278
393
|
ChainWriterError: ChainWriterError,
|
|
279
394
|
ALLOWED_CHAIN_TABLES: ALLOWED_CHAIN_TABLES,
|
|
280
395
|
FRAMEWORK_SQL_TIMEOUT_MS: FRAMEWORK_SQL_TIMEOUT_MS,
|
|
@@ -1110,12 +1110,16 @@ async function _runApiKey(args, ctx) {
|
|
|
1110
1110
|
return report.error("--scopes must contain at least one non-empty scope", 2);
|
|
1111
1111
|
}
|
|
1112
1112
|
var label = typeof args.flags.label === "string" ? args.flags.label : null;
|
|
1113
|
+
// --expires-ms is the absolute expiry as a unix-ms timestamp; the
|
|
1114
|
+
// registry's validated opt is `expiresAt` (apiKey.issue rejects any other
|
|
1115
|
+
// key). Passing `expiresMs` silently did nothing before — the lib only
|
|
1116
|
+
// ever read `expiresAt` — so the flag was a no-op; map it correctly.
|
|
1113
1117
|
var expiresMs = args.flags["expires-ms"];
|
|
1114
1118
|
var issued = await registry.issue({
|
|
1115
1119
|
ownerId: String(ownerId),
|
|
1116
1120
|
scopes: scopeList,
|
|
1117
1121
|
metadata: label ? { label: label } : null,
|
|
1118
|
-
|
|
1122
|
+
expiresAt: expiresMs && expiresMs !== true ? Number(expiresMs) : undefined,
|
|
1119
1123
|
});
|
|
1120
1124
|
report.write("id: " + issued.id);
|
|
1121
1125
|
report.write("key: " + issued.key);
|
|
@@ -158,15 +158,13 @@ function _parseBrandMember(piece) {
|
|
|
158
158
|
var brand = _parseSfString(params[0].trim());
|
|
159
159
|
if (brand === null) return null;
|
|
160
160
|
var member = { brand: brand, version: null, params: {} };
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
member.params[k] = v;
|
|
169
|
-
if (k === "v" && v !== null) member.version = v;
|
|
161
|
+
var kvps = structuredFields.parseKeyValuePieces(params, 1);
|
|
162
|
+
for (var i = 0; i < kvps.length; i += 1) {
|
|
163
|
+
var kv = kvps[i];
|
|
164
|
+
if (kv.value === null) { member.params[kv.key] = true; continue; }
|
|
165
|
+
var v = _parseSfString(kv.value);
|
|
166
|
+
member.params[kv.key] = v;
|
|
167
|
+
if (kv.key === "v" && v !== null) member.version = v;
|
|
170
168
|
}
|
|
171
169
|
return member;
|
|
172
170
|
}
|
|
@@ -118,21 +118,41 @@ function _genId() {
|
|
|
118
118
|
* // → "1.0"
|
|
119
119
|
*/
|
|
120
120
|
function wrap(opts) {
|
|
121
|
-
validateOpts.
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
121
|
+
validateOpts.shape(opts, {
|
|
122
|
+
source: { rule: "required-string", code: "cloud-events/bad-source" },
|
|
123
|
+
type: { rule: "required-string", code: "cloud-events/bad-type" },
|
|
124
|
+
id: { rule: "optional-string", code: "cloud-events/bad-id" },
|
|
125
|
+
subject: { rule: "optional-string", code: "cloud-events/bad-subject" },
|
|
126
|
+
time: { rule: "optional-string", code: "cloud-events/bad-time" },
|
|
127
|
+
datacontenttype: { rule: "optional-string", code: "cloud-events/bad-datacontenttype" },
|
|
128
|
+
dataschema: { rule: "optional-string", code: "cloud-events/bad-dataschema" },
|
|
129
|
+
// data is any JSON value or a Buffer — wrap routes Buffers to
|
|
130
|
+
// data_base64 and everything else to the data attribute, imposing no
|
|
131
|
+
// type constraint of its own, so accept any value here.
|
|
132
|
+
data: function () {},
|
|
133
|
+
// extensions — plain object whose keys conform to the §3.1 naming
|
|
134
|
+
// rules (lowercase ASCII alnum, 1-20 chars) and collide with no spec
|
|
135
|
+
// attribute. Validation lives IN the shape; the body only copies the
|
|
136
|
+
// validated keys onto the envelope.
|
|
137
|
+
extensions: function (v) {
|
|
138
|
+
validateOpts.optionalPlainObject(v,
|
|
139
|
+
"cloudEvents.wrap: extensions", CloudEventsError, "cloud-events/bad-extensions");
|
|
140
|
+
if (v === undefined || v === null) return;
|
|
141
|
+
var extKeys = Object.keys(v);
|
|
142
|
+
for (var i = 0; i < extKeys.length; i += 1) {
|
|
143
|
+
var k = extKeys[i];
|
|
144
|
+
// bound BEFORE regex test — k.length > 0 && k.length <= 20
|
|
145
|
+
if (typeof k !== "string" || k.length === 0 || k.length > 20 || !EXT_ATTR_NAME_RE.test(k)) {
|
|
146
|
+
throw new CloudEventsError("cloud-events/bad-extension-name",
|
|
147
|
+
"cloudEvents.wrap: extension '" + k + "' must match [a-z0-9]{1,20}");
|
|
148
|
+
}
|
|
149
|
+
if (REQUIRED_ATTRS.indexOf(k) !== -1 || KNOWN_OPTIONAL_ATTRS[k]) {
|
|
150
|
+
throw new CloudEventsError("cloud-events/extension-conflicts-with-spec",
|
|
151
|
+
"cloudEvents.wrap: extension '" + k + "' conflicts with a spec attribute");
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
}, "cloudEvents.wrap", CloudEventsError);
|
|
136
156
|
|
|
137
157
|
var out = {
|
|
138
158
|
specversion: SPECVERSION,
|
|
@@ -158,24 +178,13 @@ function wrap(opts) {
|
|
|
158
178
|
out.datacontenttype = opts.datacontenttype;
|
|
159
179
|
}
|
|
160
180
|
|
|
161
|
-
// Extension attributes —
|
|
162
|
-
// §3.1 naming
|
|
181
|
+
// Extension attributes — validated in the shape above (plain object,
|
|
182
|
+
// §3.1 key naming, no spec collisions); copy the validated keys onto
|
|
183
|
+
// the envelope.
|
|
163
184
|
if (opts.extensions !== undefined && opts.extensions !== null) {
|
|
164
|
-
validateOpts.optionalPlainObject(opts.extensions,
|
|
165
|
-
"cloudEvents.wrap: extensions", CloudEventsError, "cloud-events/bad-extensions");
|
|
166
185
|
var extKeys = Object.keys(opts.extensions);
|
|
167
186
|
for (var i = 0; i < extKeys.length; i += 1) {
|
|
168
|
-
|
|
169
|
-
// bound BEFORE regex test — k.length > 0 && k.length <= 20
|
|
170
|
-
if (typeof k !== "string" || k.length === 0 || k.length > 20 || !EXT_ATTR_NAME_RE.test(k)) {
|
|
171
|
-
throw new CloudEventsError("cloud-events/bad-extension-name",
|
|
172
|
-
"cloudEvents.wrap: extension '" + k + "' must match [a-z0-9]{1,20}");
|
|
173
|
-
}
|
|
174
|
-
if (REQUIRED_ATTRS.indexOf(k) !== -1 || KNOWN_OPTIONAL_ATTRS[k]) {
|
|
175
|
-
throw new CloudEventsError("cloud-events/extension-conflicts-with-spec",
|
|
176
|
-
"cloudEvents.wrap: extension '" + k + "' conflicts with a spec attribute");
|
|
177
|
-
}
|
|
178
|
-
out[k] = opts.extensions[k];
|
|
187
|
+
out[extKeys[i]] = opts.extensions[extKeys[i]];
|
|
179
188
|
}
|
|
180
189
|
}
|
|
181
190
|
return out;
|
|
@@ -668,7 +677,7 @@ function decodeBinary(headers, body, opts) {
|
|
|
668
677
|
else if (Buffer.isBuffer(body)) raw = body;
|
|
669
678
|
else if (typeof body === "string") raw = Buffer.from(body, "utf8");
|
|
670
679
|
else throw new CloudEventsError("cloud-events/bad-input", "cloudEvents.http.decodeBinary: body must be a string or Buffer");
|
|
671
|
-
if (raw
|
|
680
|
+
if (safeBuffer.byteLengthOf(raw) > maxBytes) throw new CloudEventsError("cloud-events/too-large", "cloudEvents.http.decodeBinary: body exceeds maxBytes (" + maxBytes + ")");
|
|
672
681
|
if (raw.length > 0) {
|
|
673
682
|
if (_isJsonMedia(ct)) {
|
|
674
683
|
try { event.data = safeJson.parse(raw, { maxBytes: maxBytes }); }
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
var cluster = require("./cluster");
|
|
31
31
|
var frameworkSchema = require("./framework-schema");
|
|
32
32
|
var externalDb = require("./external-db");
|
|
33
|
+
var safeSql = require("./safe-sql");
|
|
33
34
|
var lazyRequire = require("./lazy-require");
|
|
34
35
|
var { FrameworkError } = require("./framework-error");
|
|
35
36
|
|
|
@@ -277,44 +278,7 @@ function resolveTables(sql) {
|
|
|
277
278
|
* // → "SELECT id FROM audit_log WHERE counter > $1 AND actor = $2"
|
|
278
279
|
*/
|
|
279
280
|
function placeholderize(sql, dialect) {
|
|
280
|
-
|
|
281
|
-
var out = "";
|
|
282
|
-
var n = 0;
|
|
283
|
-
var i = 0;
|
|
284
|
-
var len = sql.length;
|
|
285
|
-
while (i < len) {
|
|
286
|
-
var c = sql.charAt(i);
|
|
287
|
-
var nx = i + 1 < len ? sql.charAt(i + 1) : "";
|
|
288
|
-
// Quote contexts: ' string literal, " identifier, ` mysql identifier.
|
|
289
|
-
// A doubled quote escapes itself within the span.
|
|
290
|
-
if (c === "'" || c === '"' || c === "`") {
|
|
291
|
-
out += c;
|
|
292
|
-
i += 1;
|
|
293
|
-
while (i < len) {
|
|
294
|
-
var q = sql.charAt(i);
|
|
295
|
-
if (q === c) {
|
|
296
|
-
if (sql.charAt(i + 1) === c) { out += c + c; i += 2; continue; }
|
|
297
|
-
out += c; i += 1; break;
|
|
298
|
-
}
|
|
299
|
-
out += q; i += 1;
|
|
300
|
-
}
|
|
301
|
-
continue;
|
|
302
|
-
}
|
|
303
|
-
if (c === "-" && nx === "-") { // line comment
|
|
304
|
-
while (i < len && sql.charAt(i) !== "\n") { out += sql.charAt(i); i += 1; }
|
|
305
|
-
continue;
|
|
306
|
-
}
|
|
307
|
-
if (c === "/" && nx === "*") { // block comment
|
|
308
|
-
out += "/*"; i += 2;
|
|
309
|
-
while (i < len && !(sql.charAt(i) === "*" && sql.charAt(i + 1) === "/")) { out += sql.charAt(i); i += 1; }
|
|
310
|
-
if (i < len) { out += "*/"; i += 2; }
|
|
311
|
-
continue;
|
|
312
|
-
}
|
|
313
|
-
if (c === "?") { n += 1; out += "$" + n; i += 1; continue; }
|
|
314
|
-
out += c;
|
|
315
|
-
i += 1;
|
|
316
|
-
}
|
|
317
|
-
return out;
|
|
281
|
+
return safeSql.toPositional(sql, dialect);
|
|
318
282
|
}
|
|
319
283
|
|
|
320
284
|
// ---- execute() ----
|
|
@@ -68,6 +68,7 @@
|
|
|
68
68
|
*/
|
|
69
69
|
|
|
70
70
|
var nodeCrypto = require("node:crypto");
|
|
71
|
+
var safeBuffer = require("./safe-buffer");
|
|
71
72
|
var asn1 = require("./asn1-der");
|
|
72
73
|
var bCrypto = require("./crypto");
|
|
73
74
|
var pqcSoftware = require("./pqc-software");
|
|
@@ -322,7 +323,7 @@ function decode(buf, opts) {
|
|
|
322
323
|
throw new CmsCodecError("cms/bad-input", "decode: buf must be a Buffer");
|
|
323
324
|
}
|
|
324
325
|
var maxBytes = opts.maxBytes || DEFAULT_MAX_LEN;
|
|
325
|
-
if (buf
|
|
326
|
+
if (safeBuffer.byteLengthOf(buf) > maxBytes) {
|
|
326
327
|
throw new CmsCodecError("cms/oversize",
|
|
327
328
|
"decode: input " + buf.length + " bytes exceeds maxBytes=" + maxBytes);
|
|
328
329
|
}
|
|
@@ -172,7 +172,7 @@ function detectMixedScripts(label, allowedScripts) {
|
|
|
172
172
|
//
|
|
173
173
|
// issues.push.apply(issues,
|
|
174
174
|
// codepointClass.detectCharThreats(text, opts, "html"));
|
|
175
|
-
function detectCharThreats(text, opts, codePrefix) {
|
|
175
|
+
function detectCharThreats(text, opts, codePrefix, zeroWidthSeverity) {
|
|
176
176
|
var issues = [];
|
|
177
177
|
if (typeof text !== "string") return issues;
|
|
178
178
|
if (opts && opts.bidiPolicy !== "allow") {
|
|
@@ -208,6 +208,28 @@ function detectCharThreats(text, opts, codePrefix) {
|
|
|
208
208
|
});
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
|
+
// Zero-width / invisible-formatting chars — the fourth Trojan-source-class
|
|
212
|
+
// character threat, detected here alongside its siblings so no guard
|
|
213
|
+
// hand-rolls it. OPT-IN AND severity via zeroWidthSeverity: a caller that
|
|
214
|
+
// wants zero-width detection passes the context-appropriate severity
|
|
215
|
+
// ("high" where an invisible char spoofs an identifier / filename / line of
|
|
216
|
+
// text; "warn" where it is cosmetic), and omitting it skips the scan. Gated
|
|
217
|
+
// further on a defined non-`allow` zeroWidthPolicy — flagged under `strip`
|
|
218
|
+
// too (like bidi / null / control) so a zero-width-only input under `strip`
|
|
219
|
+
// reaches the sanitizer and is removed rather than served unchanged.
|
|
220
|
+
if (zeroWidthSeverity && opts && opts.zeroWidthPolicy &&
|
|
221
|
+
opts.zeroWidthPolicy !== "allow") {
|
|
222
|
+
var zwMatch = text.match(ZERO_WIDTH_RE);
|
|
223
|
+
if (zwMatch) {
|
|
224
|
+
issues.push({
|
|
225
|
+
kind: "zero-width", severity: zeroWidthSeverity,
|
|
226
|
+
ruleId: codePrefix + ".zero-width",
|
|
227
|
+
location: zwMatch.index,
|
|
228
|
+
snippet: "zero-width / invisible-formatting char U+" +
|
|
229
|
+
zwMatch[0].charCodeAt(0).toString(HEX_RADIX) + " at byte " + zwMatch.index,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
211
233
|
return issues;
|
|
212
234
|
}
|
|
213
235
|
|
|
@@ -292,7 +314,51 @@ function isUnreserved(cc) {
|
|
|
292
314
|
cc === 0x7e; // ~
|
|
293
315
|
}
|
|
294
316
|
|
|
317
|
+
// isForbiddenControlChar — the header-injection / RFC 5322 control-byte
|
|
318
|
+
// predicate every "refuse control bytes in a header / line / value" loop
|
|
319
|
+
// shares across the mail guards (dsn / imap / list-id / list-unsubscribe /
|
|
320
|
+
// mail-compose / mail-sieve / managesieve) and the safe-* text parsers
|
|
321
|
+
// (ical / mime / vcard / toml). TRUE for DEL (0x7f) and any C0 control
|
|
322
|
+
// (< 0x20) other than TAB (0x09); LF (0x0a) and CR (0x0d) are refused by
|
|
323
|
+
// default but can be permitted per call (a line reader that has already
|
|
324
|
+
// split on CRLF, or a grammar that allows folding). Distinct from the
|
|
325
|
+
// C0_CTRL_RANGES regex above, which is the stripping/scanning table that
|
|
326
|
+
// always exempts LF/CR and never matches DEL.
|
|
327
|
+
//
|
|
328
|
+
// opts.forbidTab — TAB (0x09) is normally permitted (it is folding
|
|
329
|
+
// whitespace in RFC 5322 header values). The stricter identifier / key /
|
|
330
|
+
// name / single-line-value contexts (idempotency keys, step-up challenge
|
|
331
|
+
// values, mailbox / folder / message-id names, assembly ids, DNSBL-free
|
|
332
|
+
// single-line values) forbid EVERY C0 control plus DEL — there is no
|
|
333
|
+
// folding to honour — so they pass `{ forbidTab: true }`, making the
|
|
334
|
+
// predicate exactly `code < 0x20 || code === 0x7f`.
|
|
335
|
+
function isForbiddenControlChar(code, opts) {
|
|
336
|
+
if (code === 0x7f) return true; // DEL
|
|
337
|
+
if (code >= 0x20) return false;
|
|
338
|
+
if (code === 0x09 && (!opts || !opts.forbidTab)) return false; // TAB — permitted unless forbidTab
|
|
339
|
+
if (opts) {
|
|
340
|
+
if (opts.allowLf && code === 0x0a) return false;
|
|
341
|
+
if (opts.allowCr && code === 0x0d) return false;
|
|
342
|
+
}
|
|
343
|
+
return true;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// firstControlCharOffset — index of the first isForbiddenControlChar in `s`
|
|
347
|
+
// (under the same opts), or -1 when none. Callers wrap it as a boolean
|
|
348
|
+
// (`offset !== -1`), throw with the offending code (`s.charCodeAt(offset)`),
|
|
349
|
+
// or derive a byte offset from the index — replacing the open-coded
|
|
350
|
+
// `for (i) { c = charCodeAt(i); if (c === 0 || c === 0x7f || (c < 0x20 &&
|
|
351
|
+
// c !== 0x09)) … }` scan each parser previously rolled by hand.
|
|
352
|
+
function firstControlCharOffset(s, opts) {
|
|
353
|
+
for (var i = 0; i < s.length; i += 1) {
|
|
354
|
+
if (isForbiddenControlChar(s.charCodeAt(i), opts)) return i;
|
|
355
|
+
}
|
|
356
|
+
return -1;
|
|
357
|
+
}
|
|
358
|
+
|
|
295
359
|
module.exports = {
|
|
360
|
+
isForbiddenControlChar: isForbiddenControlChar,
|
|
361
|
+
firstControlCharOffset: firstControlCharOffset,
|
|
296
362
|
isAsciiAlnum: isAsciiAlnum,
|
|
297
363
|
isUnreserved: isUnreserved,
|
|
298
364
|
hex4: hex4,
|
|
@@ -131,12 +131,7 @@ function emit(event) {
|
|
|
131
131
|
// namespace uses underscores, so the kind is rewritten before emit.
|
|
132
132
|
try {
|
|
133
133
|
var kindCanonical = String(event.kind || "log").replace(/-/g, "_");
|
|
134
|
-
audit().
|
|
135
|
-
action: "compliance.aiact." + kindCanonical,
|
|
136
|
-
outcome: event.outcome || "success",
|
|
137
|
-
actor: event.actor || null,
|
|
138
|
-
metadata: event,
|
|
139
|
-
});
|
|
134
|
+
audit().namespaced("compliance.aiact")(kindCanonical, event.outcome || "success", event, { actor: event.actor || null });
|
|
140
135
|
} catch (_e) { /* drop-silent */ }
|
|
141
136
|
return event;
|
|
142
137
|
}
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
*/
|
|
40
40
|
|
|
41
41
|
var validateOpts = require("./validate-opts");
|
|
42
|
+
var markupEscape = require("./markup-escape").markupEscape;
|
|
42
43
|
var { ComplianceError } = require("./framework-error");
|
|
43
44
|
|
|
44
45
|
var BANNER_KINDS = Object.freeze([
|
|
@@ -118,10 +119,7 @@ function htmlBanner(opts) {
|
|
|
118
119
|
|
|
119
120
|
function _escapeHtml(s) {
|
|
120
121
|
if (typeof s !== "string") return "";
|
|
121
|
-
return s
|
|
122
|
-
.replace(/</g, "<")
|
|
123
|
-
.replace(/>/g, ">")
|
|
124
|
-
.replace(/"/g, """);
|
|
122
|
+
return markupEscape(s);
|
|
125
123
|
}
|
|
126
124
|
|
|
127
125
|
// Watermark builder for Art. 50(2). Operators integrate with C2PA /
|