@blamejs/blamejs-shop 0.4.55 → 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 +4 -0
- package/lib/admin.js +385 -2
- 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/lib/winback-campaigns.js +202 -42
- package/package.json +1 -1
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// audit-emit — the stateless drop-silent audit emitter with a metadata-first,
|
|
4
|
+
// success-default signature `(action, metadata, outcome?)`. Many primitives —
|
|
5
|
+
// the mail servers and DAV bridge, the A2A task store, the compliance posture
|
|
6
|
+
// tracker, the MCP tool registry, the idempotency-key middleware — emit audit
|
|
7
|
+
// events where the per-event detail (metadata) is almost always supplied and
|
|
8
|
+
// the outcome is almost always "this happened", so they pass metadata second
|
|
9
|
+
// and let outcome default to "success". They route through the drop-silent
|
|
10
|
+
// audit.safeEmit so a misbehaving sink never crashes the request. Unlike
|
|
11
|
+
// b.audit.namespaced (gated, action-prefixed, outcome-first), this is ungated
|
|
12
|
+
// and passes the action verbatim — matching what each of them hand-rolled.
|
|
13
|
+
//
|
|
14
|
+
// This module self-lazy-requires audit so a consumer can `require("./audit-emit")`
|
|
15
|
+
// at the top of the file without re-introducing the audit load cycle that the
|
|
16
|
+
// per-file `lazyRequire(() => require("./audit"))` was guarding against.
|
|
17
|
+
|
|
18
|
+
var lazyRequire = require("./lazy-require");
|
|
19
|
+
var audit = lazyRequire(function () { return require("./audit"); });
|
|
20
|
+
|
|
21
|
+
// emit(action, metadata, outcome?) — drop-silent audit emit. `outcome` defaults
|
|
22
|
+
// to "success"; `metadata` defaults to `{}`.
|
|
23
|
+
function emit(action, metadata, outcome) {
|
|
24
|
+
try {
|
|
25
|
+
audit().safeEmit({
|
|
26
|
+
action: action,
|
|
27
|
+
outcome: outcome || "success",
|
|
28
|
+
metadata: metadata || {},
|
|
29
|
+
});
|
|
30
|
+
} catch (_e) { /* drop-silent — audit best-effort */ }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// emitToSink(opts, action, outcome, metadata) — drop-silent audit emit to an
|
|
34
|
+
// OPERATOR-SUPPLIED sink threaded through `opts.audit`, the no-op-when-absent
|
|
35
|
+
// variant the archive reader / tar-reader / writer share verbatim: forward the
|
|
36
|
+
// event only when `opts.audit` exposes a `safeEmit`, otherwise stay silent.
|
|
37
|
+
// Distinct from emit() (which targets the framework's GLOBAL audit()) — here the
|
|
38
|
+
// caller carries the sink in opts, so a reader/writer with no audit configured
|
|
39
|
+
// emits nothing. (Callers whose payload carries extra top-level fields — e.g.
|
|
40
|
+
// http-client's `resource` — keep their own wrapper; this is the bare
|
|
41
|
+
// action/outcome/metadata shape.)
|
|
42
|
+
function emitToSink(opts, action, outcome, metadata) {
|
|
43
|
+
if (!opts || !opts.audit || typeof opts.audit.safeEmit !== "function") return;
|
|
44
|
+
try {
|
|
45
|
+
opts.audit.safeEmit({ action: action, outcome: outcome, metadata: metadata });
|
|
46
|
+
} catch (_e) { /* drop-silent — operator audit sink must never crash the caller */ }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// gatedReasonEmitter({ audit, sink?, extra? }) — build a gated drop-silent
|
|
50
|
+
// emitter `(action, info, outcome)` that records a structured top-level `reason`
|
|
51
|
+
// (hoisted from `info.reason`) alongside the audit metadata. The gated +
|
|
52
|
+
// reason-hoisting sibling of emit() / b.audit.namespaced, for the primitives
|
|
53
|
+
// (backup / restore / scheduler / config-drift / legal-hold) that emit a reason
|
|
54
|
+
// the audit chain surfaces as a first-class field. `audit` is the gate flag
|
|
55
|
+
// (false disables); `sink` is an optional operator-supplied audit target (the
|
|
56
|
+
// no-op-without-safeEmit guard the hand-rolled `auditInstance || audit()`
|
|
57
|
+
// pattern carried); `extra(info)` optionally returns more top-level event
|
|
58
|
+
// fields (e.g. legal-hold's `resource`). Routes through b.audit.namespaced, so
|
|
59
|
+
// the same redaction + drop-silent guarantees apply.
|
|
60
|
+
function gatedReasonEmitter(opts) {
|
|
61
|
+
opts = opts || {};
|
|
62
|
+
var ns = audit().namespaced(null, { audit: opts.audit, sink: opts.sink });
|
|
63
|
+
var extra = typeof opts.extra === "function" ? opts.extra : null;
|
|
64
|
+
return function (action, info, outcome) {
|
|
65
|
+
var fields = { reason: (info && info.reason) || null };
|
|
66
|
+
if (extra) {
|
|
67
|
+
var more = extra(info);
|
|
68
|
+
if (more) {
|
|
69
|
+
for (var k in more) {
|
|
70
|
+
if (Object.prototype.hasOwnProperty.call(more, k)) fields[k] = more[k];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
ns(action, outcome, info, fields);
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
module.exports = {
|
|
79
|
+
emit: emit,
|
|
80
|
+
emitToSink: emitToSink,
|
|
81
|
+
gatedReasonEmitter: gatedReasonEmitter,
|
|
82
|
+
};
|
|
@@ -190,6 +190,33 @@ function _computeFingerprint(publicKeyPem) {
|
|
|
190
190
|
return sha3Hash(publicKeyPem);
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
+
// ---- Store-independent chain anchor (the checkpoint protocol lifted off the
|
|
194
|
+
// framework audit_log / audit_checkpoints store so a consumer can anchor THEIR
|
|
195
|
+
// OWN hash chain) ----
|
|
196
|
+
|
|
197
|
+
// Domain-separation magic for a consumer anchor's signed bytes. DISTINCT from
|
|
198
|
+
// the framework audit-checkpoint format on purpose: a checkpoint signature can
|
|
199
|
+
// never be replayed as an anchor (or vice versa), and the framework
|
|
200
|
+
// audit_checkpoints wire format stays byte-stable (b.audit.checkpoint is
|
|
201
|
+
// untouched). Changing this invalidates every prior anchor.
|
|
202
|
+
var ANCHOR_FORMAT = "blamejs-chain-anchor-v1";
|
|
203
|
+
|
|
204
|
+
// Build the canonical signed bytes for one anchor. Fixed multi-line layout (no
|
|
205
|
+
// JSON serializer quirks). prevTipHash IS part of the signed payload, so the
|
|
206
|
+
// link between consecutive anchors is tamper-evident — an attacker cannot
|
|
207
|
+
// rewrite the linkage without breaking the signature. `format` lets a consumer
|
|
208
|
+
// domain-separate their own anchors from any other anchored chain.
|
|
209
|
+
function anchorPayload(counter, tipHash, prevTipHash, createdAt, format) {
|
|
210
|
+
return Buffer.from(
|
|
211
|
+
(format || ANCHOR_FORMAT) + "\n" +
|
|
212
|
+
String(counter) + "\n" +
|
|
213
|
+
tipHash + "\n" +
|
|
214
|
+
(prevTipHash || "") + "\n" +
|
|
215
|
+
String(createdAt),
|
|
216
|
+
"utf8"
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
193
220
|
// ---- Passphrase sourcing (delegates to lib/passphrase-source.js with
|
|
194
221
|
// audit-signing-specific env var names) ----
|
|
195
222
|
|
|
@@ -798,6 +825,233 @@ async function rotateSigningKey(rotOpts) {
|
|
|
798
825
|
};
|
|
799
826
|
}
|
|
800
827
|
|
|
828
|
+
// Defensive coercion of an operator-supplied tip into the canonical fields.
|
|
829
|
+
// Config-time tier: throws a typed AuditSignError on a malformed tip so the
|
|
830
|
+
// consumer catches the bug at the call site, not as an opaque "signature
|
|
831
|
+
// failed" later. prevTipHash is OPTIONAL (absent for the genesis anchor).
|
|
832
|
+
function _normalizeTip(tip, fnLabel) {
|
|
833
|
+
if (!tip || typeof tip !== "object") {
|
|
834
|
+
throw _err("ANCHOR_BAD_TIP",
|
|
835
|
+
"auditSign." + fnLabel + ": tip must be an object { counter, tipHash }");
|
|
836
|
+
}
|
|
837
|
+
var counter = tip.counter;
|
|
838
|
+
if (typeof counter !== "number" || !isFinite(counter) || counter < 0 || Math.floor(counter) !== counter) {
|
|
839
|
+
throw _err("ANCHOR_BAD_COUNTER",
|
|
840
|
+
"auditSign." + fnLabel + ": tip.counter must be a non-negative integer (got: " + counter + ")");
|
|
841
|
+
}
|
|
842
|
+
if (typeof tip.tipHash !== "string" || tip.tipHash.length === 0) {
|
|
843
|
+
throw _err("ANCHOR_BAD_TIPHASH",
|
|
844
|
+
"auditSign." + fnLabel + ": tip.tipHash must be a non-empty string");
|
|
845
|
+
}
|
|
846
|
+
if (tip.prevTipHash != null && typeof tip.prevTipHash !== "string") {
|
|
847
|
+
throw _err("ANCHOR_BAD_PREV",
|
|
848
|
+
"auditSign." + fnLabel + ": tip.prevTipHash, when present, must be a string");
|
|
849
|
+
}
|
|
850
|
+
return {
|
|
851
|
+
counter: counter,
|
|
852
|
+
tipHash: tip.tipHash,
|
|
853
|
+
prevTipHash: tip.prevTipHash != null ? tip.prevTipHash : null,
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
/**
|
|
858
|
+
* @primitive b.auditSign.anchor
|
|
859
|
+
* @signature b.auditSign.anchor(tip, opts?)
|
|
860
|
+
* @since 0.15.13
|
|
861
|
+
* @status stable
|
|
862
|
+
* @compliance hipaa, pci-dss, gdpr, soc2, sox-404
|
|
863
|
+
* @related b.auditSign.verifyAnchor, b.auditSign.verifyAnchorChain, b.audit.checkpoint
|
|
864
|
+
*
|
|
865
|
+
* Sign a hash-chain tip with the in-memory PQC key, returning a
|
|
866
|
+
* self-describing anchor object the consumer persists in THEIR OWN store. This
|
|
867
|
+
* is the `b.audit.checkpoint()` protocol lifted off the framework `audit_log` /
|
|
868
|
+
* `audit_checkpoints` tables: a consumer running their own append-only chain
|
|
869
|
+
* anchors its tip the same tamper-evident way, with no framework table, no
|
|
870
|
+
* `clusterStorage`, and no leader requirement. A full-chain rewrite that
|
|
871
|
+
* recomputes every row hash still cannot forge the signature without the
|
|
872
|
+
* audit-signing private key, so a later `verifyAnchorChain` detects it.
|
|
873
|
+
*
|
|
874
|
+
* `tip.prevTipHash` (optional) is bound into the signed bytes, so truncation /
|
|
875
|
+
* reorder of a stored anchor sequence is caught by the signature, not just a
|
|
876
|
+
* plaintext compare. `opts.format` domain-separates a consumer's anchors
|
|
877
|
+
* (default `"blamejs-chain-anchor-v1"`).
|
|
878
|
+
*
|
|
879
|
+
* Verification resolves the public key from the recorded fingerprint via the
|
|
880
|
+
* key-history file under the `init({ dataDir })` directory, so it is bound to
|
|
881
|
+
* that key store (not fully store-free) — keep the history with the anchors.
|
|
882
|
+
*
|
|
883
|
+
* Throws `AuditSignError` (`ANCHOR_BAD_TIP` / `ANCHOR_BAD_COUNTER` /
|
|
884
|
+
* `ANCHOR_BAD_TIPHASH` / `ANCHOR_BAD_PREV`) on a malformed tip;
|
|
885
|
+
* `audit-sign/not-initialized` when `init()` has not been awaited.
|
|
886
|
+
*
|
|
887
|
+
* @opts
|
|
888
|
+
* format: string, // default "blamejs-chain-anchor-v1" — domain-separation magic in the signed payload
|
|
889
|
+
* createdAt: number, // default Date.now() — the anchor timestamp (also signed)
|
|
890
|
+
*
|
|
891
|
+
* @example
|
|
892
|
+
* await b.auditSign.init({ dataDir: "/var/lib/blamejs/data" });
|
|
893
|
+
* var a = b.auditSign.anchor({ counter: 42, tipHash: "9f4e", prevTipHash: "1b7d" },
|
|
894
|
+
* { format: "my-app-ledger-v1" });
|
|
895
|
+
* // → { format, counter, tipHash, prevTipHash, createdAt, algorithm,
|
|
896
|
+
* // publicKeyFingerprint, signature }
|
|
897
|
+
*/
|
|
898
|
+
function anchor(tip, opts) {
|
|
899
|
+
_requireInit();
|
|
900
|
+
opts = opts || {};
|
|
901
|
+
var t = _normalizeTip(tip, "anchor");
|
|
902
|
+
var format = (typeof opts.format === "string" && opts.format.length > 0) ? opts.format : ANCHOR_FORMAT;
|
|
903
|
+
var createdAt = (typeof opts.createdAt === "number" && isFinite(opts.createdAt)) ? opts.createdAt : Date.now();
|
|
904
|
+
var payload = anchorPayload(t.counter, t.tipHash, t.prevTipHash, createdAt, format);
|
|
905
|
+
var sigBuf = sign(payload);
|
|
906
|
+
return {
|
|
907
|
+
format: format,
|
|
908
|
+
counter: t.counter,
|
|
909
|
+
tipHash: t.tipHash,
|
|
910
|
+
prevTipHash: t.prevTipHash,
|
|
911
|
+
createdAt: createdAt,
|
|
912
|
+
algorithm: keys.algorithm,
|
|
913
|
+
publicKeyFingerprint: keys.fingerprint,
|
|
914
|
+
signature: sigBuf.toString("hex"),
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
// Resolve + verify ONE anchor's signature. Returns { ok, reason? }. Never
|
|
919
|
+
// throws on a forgery / unknown key (defensive-reader tier) — the caller
|
|
920
|
+
// branches on ok.
|
|
921
|
+
function _verifyOneAnchor(a) {
|
|
922
|
+
if (!a || typeof a !== "object") return { ok: false, reason: "anchor is not an object" };
|
|
923
|
+
if (typeof a.tipHash !== "string" || typeof a.signature !== "string" ||
|
|
924
|
+
typeof a.publicKeyFingerprint !== "string") {
|
|
925
|
+
return { ok: false, reason: "anchor missing tipHash / signature / publicKeyFingerprint" };
|
|
926
|
+
}
|
|
927
|
+
if (typeof a.counter !== "number" || !isFinite(a.counter)) {
|
|
928
|
+
return { ok: false, reason: "anchor counter is not a finite number" };
|
|
929
|
+
}
|
|
930
|
+
var pub = getPublicKeyByFingerprint(a.publicKeyFingerprint);
|
|
931
|
+
if (!pub) {
|
|
932
|
+
return { ok: false, reason: "no audit-signing key on record for this anchor's fingerprint" };
|
|
933
|
+
}
|
|
934
|
+
var format = (typeof a.format === "string" && a.format.length > 0) ? a.format : ANCHOR_FORMAT;
|
|
935
|
+
// prevTipHash is part of the signed payload — rebuild it the same way anchor()
|
|
936
|
+
// did (absent / null → "") so the bytes are byte-identical on a clean anchor.
|
|
937
|
+
var prevTipHash = (a.prevTipHash != null && typeof a.prevTipHash === "string") ? a.prevTipHash : "";
|
|
938
|
+
var payload = anchorPayload(Number(a.counter), a.tipHash, prevTipHash, Number(a.createdAt), format);
|
|
939
|
+
// Buffer.from(hex) silently truncates on non-hex / odd-length; reject when
|
|
940
|
+
// the parsed bytes don't round-trip to the original lowercased hex.
|
|
941
|
+
var sigBuf = Buffer.from(a.signature, "hex");
|
|
942
|
+
if (sigBuf.toString("hex") !== String(a.signature).toLowerCase()) {
|
|
943
|
+
return { ok: false, reason: "anchor signature is not valid hex" };
|
|
944
|
+
}
|
|
945
|
+
if (!verify(payload, sigBuf, pub)) {
|
|
946
|
+
return { ok: false, reason: "post-quantum signature failed" };
|
|
947
|
+
}
|
|
948
|
+
return { ok: true };
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
/**
|
|
952
|
+
* @primitive b.auditSign.verifyAnchor
|
|
953
|
+
* @signature b.auditSign.verifyAnchor(anchor)
|
|
954
|
+
* @since 0.15.13
|
|
955
|
+
* @status stable
|
|
956
|
+
* @compliance hipaa, pci-dss, gdpr, soc2, sox-404
|
|
957
|
+
* @related b.auditSign.anchor, b.auditSign.verifyAnchorChain
|
|
958
|
+
*
|
|
959
|
+
* Verify a single anchor produced by `b.auditSign.anchor`. Resolves the public
|
|
960
|
+
* key by the anchor's recorded fingerprint (live key or a rotated-out key from
|
|
961
|
+
* the unsealed history), rebuilds the canonical payload, and checks the
|
|
962
|
+
* post-quantum signature. Returns `{ ok: true }` when valid, or
|
|
963
|
+
* `{ ok: false, reason }` for a forgery, an unknown signing key, malformed hex,
|
|
964
|
+
* or a missing field. Never throws on adversarial content.
|
|
965
|
+
*
|
|
966
|
+
* @example
|
|
967
|
+
* var a = b.auditSign.anchor({ counter: 1, tipHash: "ab12" });
|
|
968
|
+
* b.auditSign.verifyAnchor(a); // → { ok: true }
|
|
969
|
+
*/
|
|
970
|
+
function verifyAnchor(a) {
|
|
971
|
+
_requireInit();
|
|
972
|
+
return _verifyOneAnchor(a);
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
/**
|
|
976
|
+
* @primitive b.auditSign.verifyAnchorChain
|
|
977
|
+
* @signature b.auditSign.verifyAnchorChain(anchors, opts?)
|
|
978
|
+
* @since 0.15.13
|
|
979
|
+
* @status stable
|
|
980
|
+
* @compliance hipaa, pci-dss, gdpr, soc2, sox-404
|
|
981
|
+
* @related b.auditSign.anchor, b.auditSign.verifyAnchor, b.audit.verifyCheckpoints
|
|
982
|
+
*
|
|
983
|
+
* Walk an ordered array of anchors (oldest first) and verify each one's
|
|
984
|
+
* signature AND that the sequence is internally consistent: counters strictly
|
|
985
|
+
* increase, and each anchor's `prevTipHash` equals the previous anchor's
|
|
986
|
+
* `tipHash`. This catches the two attacks a single-anchor check cannot — a
|
|
987
|
+
* stored-anchor truncation / reorder (link break) and a full-chain rewrite
|
|
988
|
+
* (signature break). Returns `{ ok: true, anchorsVerified }`, or
|
|
989
|
+
* `{ ok: false, anchorsVerified, breakAt, reason }` at the first break.
|
|
990
|
+
*
|
|
991
|
+
* `requireLinkage` (default true) makes a non-genesis anchor that omits
|
|
992
|
+
* `prevTipHash` a break, so an attacker can't drop the link to bypass the
|
|
993
|
+
* check. Pass `requireLinkage: false` for unlinked anchors.
|
|
994
|
+
*
|
|
995
|
+
* @opts
|
|
996
|
+
* requireLinkage: boolean, // default true — every non-genesis anchor must carry a matching prevTipHash
|
|
997
|
+
*
|
|
998
|
+
* @example
|
|
999
|
+
* var a1 = b.auditSign.anchor({ counter: 1, tipHash: "h1" });
|
|
1000
|
+
* var a2 = b.auditSign.anchor({ counter: 2, tipHash: "h2", prevTipHash: "h1" });
|
|
1001
|
+
* b.auditSign.verifyAnchorChain([a1, a2]); // → { ok: true, anchorsVerified: 2 }
|
|
1002
|
+
*/
|
|
1003
|
+
function verifyAnchorChain(anchors, opts) {
|
|
1004
|
+
_requireInit();
|
|
1005
|
+
opts = opts || {};
|
|
1006
|
+
var requireLinkage = opts.requireLinkage !== false;
|
|
1007
|
+
if (!Array.isArray(anchors)) {
|
|
1008
|
+
return { ok: false, anchorsVerified: 0, breakAt: 0, reason: "anchors must be an array" };
|
|
1009
|
+
}
|
|
1010
|
+
if (anchors.length === 0) return { ok: true, anchorsVerified: 0 };
|
|
1011
|
+
|
|
1012
|
+
var prev = null;
|
|
1013
|
+
for (var i = 0; i < anchors.length; i += 1) {
|
|
1014
|
+
var a = anchors[i];
|
|
1015
|
+
var sigResult = _verifyOneAnchor(a);
|
|
1016
|
+
if (!sigResult.ok) {
|
|
1017
|
+
return { ok: false, anchorsVerified: i, breakAt: i, reason: sigResult.reason };
|
|
1018
|
+
}
|
|
1019
|
+
if (prev === null) {
|
|
1020
|
+
// Genesis: a prevTipHash on the FIRST anchor means a predecessor was
|
|
1021
|
+
// dropped — fail closed.
|
|
1022
|
+
if (a.prevTipHash != null) {
|
|
1023
|
+
return {
|
|
1024
|
+
ok: false, anchorsVerified: i, breakAt: i,
|
|
1025
|
+
reason: "non-genesis anchor missing predecessor (prevTipHash set on first anchor)",
|
|
1026
|
+
};
|
|
1027
|
+
}
|
|
1028
|
+
} else {
|
|
1029
|
+
if (!(Number(a.counter) > Number(prev.counter))) {
|
|
1030
|
+
return {
|
|
1031
|
+
ok: false, anchorsVerified: i, breakAt: i,
|
|
1032
|
+
reason: "anchor counter not strictly increasing",
|
|
1033
|
+
};
|
|
1034
|
+
}
|
|
1035
|
+
if (requireLinkage) {
|
|
1036
|
+
if (a.prevTipHash == null) {
|
|
1037
|
+
return {
|
|
1038
|
+
ok: false, anchorsVerified: i, breakAt: i,
|
|
1039
|
+
reason: "non-genesis anchor missing prevTipHash linkage",
|
|
1040
|
+
};
|
|
1041
|
+
}
|
|
1042
|
+
if (a.prevTipHash !== prev.tipHash) {
|
|
1043
|
+
return {
|
|
1044
|
+
ok: false, anchorsVerified: i, breakAt: i,
|
|
1045
|
+
reason: "anchor prevTipHash does not match the previous tipHash (truncation / reorder)",
|
|
1046
|
+
};
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
prev = a;
|
|
1051
|
+
}
|
|
1052
|
+
return { ok: true, anchorsVerified: anchors.length };
|
|
1053
|
+
}
|
|
1054
|
+
|
|
801
1055
|
function _resetForTest() {
|
|
802
1056
|
keys = null;
|
|
803
1057
|
initialized = false;
|
|
@@ -810,6 +1064,9 @@ module.exports = {
|
|
|
810
1064
|
init: init,
|
|
811
1065
|
sign: sign,
|
|
812
1066
|
verify: verify,
|
|
1067
|
+
anchor: anchor,
|
|
1068
|
+
verifyAnchor: verifyAnchor,
|
|
1069
|
+
verifyAnchorChain: verifyAnchorChain,
|
|
813
1070
|
rotateSigningKey: rotateSigningKey,
|
|
814
1071
|
reSignAll: reSignAll,
|
|
815
1072
|
getPublicKey: getPublicKey,
|
|
@@ -424,6 +424,13 @@ var FRAMEWORK_NAMESPACES = [
|
|
|
424
424
|
"bootgates", // b.bootGates (bootgates.passed / bootgates.failed / bootgates.onfail_threw — boot-invariant runner)
|
|
425
425
|
"metrics", // b.metrics.snapshot.shadowRegistry (metrics.shadow.cardinality_dropped — namespaced metrics export)
|
|
426
426
|
"jose", // b.jose.jwe.experimental (jose.jwe.experimental.encrypt / .decrypt — ML-KEM-JWE pre-IANA)
|
|
427
|
+
"ai", // b.ai.adverseDecision (ai.adverse_decision.* — FCRA adverse-action decisioning)
|
|
428
|
+
"breach", // b.breachDeadline (breach.report.* — breach-notification deadline clock)
|
|
429
|
+
"cra", // b.craReport (cra.report.* — EU Cyber Resilience Act conformity)
|
|
430
|
+
"gdpr", // b.gdprRopa (gdpr.ropa.* — GDPR Art. 30 Records of Processing Activities)
|
|
431
|
+
"incident", // b.incidentReport (incident.report.* — incident lifecycle)
|
|
432
|
+
"middleware", // b.middleware.ageGate / dailyByteQuota (middleware.age_gate.* / middleware.daily_byte_quota.*)
|
|
433
|
+
"nis2", // b.nis2Report (nis2.report.* — NIS2 Directive incident reporting)
|
|
427
434
|
];
|
|
428
435
|
var registeredNamespaces = new Set(FRAMEWORK_NAMESPACES);
|
|
429
436
|
|
|
@@ -944,6 +951,13 @@ async function checkpoint(opts) {
|
|
|
944
951
|
cluster.requireLeader();
|
|
945
952
|
opts = opts || {};
|
|
946
953
|
|
|
954
|
+
// Bind this checkpoint to the database it reads the tip from. checkpoint()
|
|
955
|
+
// spans async boundaries (tip read → sign → insert); a fire-and-forget call
|
|
956
|
+
// launched by db.close() can have its insert resume AFTER the database it
|
|
957
|
+
// read closed and a fresh one opened, anchoring the old tip into the wrong
|
|
958
|
+
// database. Capture the live db generation now and re-check before the write.
|
|
959
|
+
var dbGenAtEntry = db()._dbGeneration();
|
|
960
|
+
|
|
947
961
|
var tipReadBuilt = sql.select("audit_log", _sqlOpts())
|
|
948
962
|
.columns(["_id", "monotonicCounter", "rowHash"])
|
|
949
963
|
.orderBy("monotonicCounter", "desc")
|
|
@@ -972,6 +986,12 @@ async function checkpoint(opts) {
|
|
|
972
986
|
var signature = auditSign.sign(payload);
|
|
973
987
|
var pubFp = auditSign.getPublicKeyFingerprint();
|
|
974
988
|
|
|
989
|
+
// Fail closed if the database changed under us between the tip read and here
|
|
990
|
+
// (e.g. a close()-launched checkpoint resuming after a fresh db opened). The
|
|
991
|
+
// tip we signed belongs to a database that is gone; anchoring it into the
|
|
992
|
+
// current one would forge a checkpoint. Write nothing.
|
|
993
|
+
if (db()._dbGeneration() !== dbGenAtEntry) return null;
|
|
994
|
+
|
|
975
995
|
var ckptId = generateToken(TRACE_ID_BYTES);
|
|
976
996
|
var fencingToken = cluster.fencingToken();
|
|
977
997
|
await _insertCheckpoint(
|
|
@@ -1445,6 +1465,69 @@ function safeEmit(event) {
|
|
|
1445
1465
|
} catch (_e) { /* audit best-effort — never break the caller */ }
|
|
1446
1466
|
}
|
|
1447
1467
|
|
|
1468
|
+
/**
|
|
1469
|
+
* @primitive b.audit.namespaced
|
|
1470
|
+
* @signature b.audit.namespaced(prefix, opts?)
|
|
1471
|
+
* @since 0.15.13
|
|
1472
|
+
* @status stable
|
|
1473
|
+
* @compliance hipaa, pci-dss, gdpr, soc2
|
|
1474
|
+
* @related b.audit.safeEmit, b.audit.emit, b.observability.namespaced
|
|
1475
|
+
*
|
|
1476
|
+
* Build a drop-silent emitter bound to one action namespace — the shape every
|
|
1477
|
+
* framework primitive hand-rolled as a private `_emitAudit(action, outcome,
|
|
1478
|
+
* metadata)` closure (or inline) (`if (!on) return; try { safeEmit({ action:
|
|
1479
|
+
* "ns." + action, outcome, metadata }); } catch {}`). The returned function
|
|
1480
|
+
* prefixes `action` with `prefix + "."`, fills `metadata` with `{}` when
|
|
1481
|
+
* omitted, and routes through `safeEmit` (so the same redaction + outcome
|
|
1482
|
+
* normalization applies).
|
|
1483
|
+
*
|
|
1484
|
+
* Every caller drives the SAME 4-argument emitter `(action, outcome, metadata,
|
|
1485
|
+
* extra?)`: `extra` is an object whose fields are merged onto the event, which
|
|
1486
|
+
* carries the only per-emit variations seen across the framework — `actor`
|
|
1487
|
+
* (constant `{ type: "system" }` for an unattended worker, or a per-request
|
|
1488
|
+
* `ctx.actor`) and `resource`. So a hand-rolled emitter with extra event fields
|
|
1489
|
+
* is never an exception — pass them through `extra`. `opts` is the gate flag for
|
|
1490
|
+
* the common case OR `{ audit, sink }`, where `sink` emits to an
|
|
1491
|
+
* operator-supplied audit object instead of the framework chain (the emitter is
|
|
1492
|
+
* a no-op if that sink has no `safeEmit`, matching the hand-rolled sink guard).
|
|
1493
|
+
*
|
|
1494
|
+
* A falsy `prefix` (`null` / `""`) builds the no-namespace variant: `action`
|
|
1495
|
+
* passes through verbatim (no `prefix + "."`). This serves the primitives whose
|
|
1496
|
+
* audit actions are already fully-qualified at the call site (`emitAudit(
|
|
1497
|
+
* "system.outbox.started", …)`) — the same gated drop-silent passthrough,
|
|
1498
|
+
* without re-homing the qualifier.
|
|
1499
|
+
*
|
|
1500
|
+
* @opts
|
|
1501
|
+
* audit: boolean, // false disables the emitter (default on); passing a bare boolean === { audit }
|
|
1502
|
+
* sink: object, // alternate audit target with a .safeEmit(event) (defaults to b.audit)
|
|
1503
|
+
*
|
|
1504
|
+
* @example
|
|
1505
|
+
* var emitAudit = b.audit.namespaced("gdpr.ropa", opts.audit);
|
|
1506
|
+
* emitAudit("activity_added", "success", { activityId: id });
|
|
1507
|
+
* // → safeEmit({ action: "gdpr.ropa.activity_added", outcome: "success",
|
|
1508
|
+
* // metadata: { activityId: id } })
|
|
1509
|
+
*
|
|
1510
|
+
* var emitGate = b.audit.namespaced("guardSql.gate");
|
|
1511
|
+
* emitGate("refused", "denied", { route: r }, { actor: ctx.actor }); // per-call actor
|
|
1512
|
+
*/
|
|
1513
|
+
function namespaced(prefix, opts) {
|
|
1514
|
+
// Back-compat: a bare boolean/undefined is the gate; an object carries the
|
|
1515
|
+
// gate plus the sink axis.
|
|
1516
|
+
var cfg = (opts && typeof opts === "object") ? opts : { audit: opts };
|
|
1517
|
+
var on = cfg.audit !== false;
|
|
1518
|
+
return function (action, outcome, metadata, extra) {
|
|
1519
|
+
if (!on) return;
|
|
1520
|
+
// module.exports.safeEmit (late-bound) so a test that stubs b.audit.safeEmit
|
|
1521
|
+
// still observes the emit; cfg.sink routes to an operator-supplied audit
|
|
1522
|
+
// object (no-op if it lacks safeEmit, matching the hand-rolled sink guard).
|
|
1523
|
+
var sink = cfg.sink || module.exports;
|
|
1524
|
+
if (!sink || typeof sink.safeEmit !== "function") return;
|
|
1525
|
+
var evt = { action: prefix ? prefix + "." + action : action, outcome: outcome, metadata: metadata || {} };
|
|
1526
|
+
if (extra) { for (var k in extra) { if (Object.prototype.hasOwnProperty.call(extra, k)) evt[k] = extra[k]; } }
|
|
1527
|
+
try { sink.safeEmit(evt); } catch (_e) { /* drop-silent — audit is best-effort */ }
|
|
1528
|
+
};
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1448
1531
|
/**
|
|
1449
1532
|
* @primitive b.audit.flush
|
|
1450
1533
|
* @signature b.audit.flush()
|
|
@@ -1814,6 +1897,7 @@ module.exports = {
|
|
|
1814
1897
|
useStore: useStore,
|
|
1815
1898
|
emit: emit,
|
|
1816
1899
|
safeEmit: safeEmit,
|
|
1900
|
+
namespaced: namespaced,
|
|
1817
1901
|
applyPosture: applyPosture,
|
|
1818
1902
|
activePosture: activePosture,
|
|
1819
1903
|
bindActor: bindActor,
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
var defineClass = require("../framework-error").defineClass;
|
|
42
42
|
var lazyRequire = require("../lazy-require");
|
|
43
43
|
var validateOpts = require("../validate-opts");
|
|
44
|
+
var requestHelpers = require("../request-helpers");
|
|
44
45
|
|
|
45
46
|
var audit = lazyRequire(function () { return require("../audit"); });
|
|
46
47
|
var observability = lazyRequire(function () { return require("../observability"); });
|
|
@@ -77,7 +78,6 @@ function create(opts) {
|
|
|
77
78
|
}
|
|
78
79
|
var passthroughPaths = Array.isArray(opts.passthroughPaths)
|
|
79
80
|
? opts.passthroughPaths.slice() : [];
|
|
80
|
-
var auditOn = opts.audit !== false;
|
|
81
81
|
var getRole = typeof opts.getRole === "function" ? opts.getRole : null;
|
|
82
82
|
var errorMessage = typeof opts.errorMessage === "string" && opts.errorMessage.length > 0
|
|
83
83
|
? opts.errorMessage : "service in restricted access mode";
|
|
@@ -87,33 +87,11 @@ function create(opts) {
|
|
|
87
87
|
var modeSetBy = "boot";
|
|
88
88
|
var modeReason = "initial mode at boot";
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
try {
|
|
93
|
-
audit().safeEmit({
|
|
94
|
-
action: "auth.access_lock." + action,
|
|
95
|
-
outcome: outcome,
|
|
96
|
-
metadata: metadata || {},
|
|
97
|
-
});
|
|
98
|
-
} catch (_e) { /* drop-silent — audit is best-effort */ }
|
|
99
|
-
}
|
|
100
|
-
function _emitMetric(verb, n, labels) {
|
|
101
|
-
try { observability().safeEvent("auth.access_lock." + verb, n || 1, labels || {}); }
|
|
102
|
-
catch (_e) { /* drop-silent */ }
|
|
103
|
-
}
|
|
90
|
+
var _emitAudit = audit().namespaced("auth.access_lock", opts.audit);
|
|
91
|
+
var _emitMetric = observability().namespaced("auth.access_lock");
|
|
104
92
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
var p = req.url || "";
|
|
108
|
-
var qpos = p.indexOf("?");
|
|
109
|
-
if (qpos !== -1) p = p.slice(0, qpos);
|
|
110
|
-
for (var i = 0; i < passthroughPaths.length; i++) {
|
|
111
|
-
var entry = passthroughPaths[i];
|
|
112
|
-
if (typeof entry === "string" && (p === entry || p.indexOf(entry + "/") === 0)) return true;
|
|
113
|
-
if (entry instanceof RegExp && entry.test(p)) return true;
|
|
114
|
-
}
|
|
115
|
-
return false;
|
|
116
|
-
}
|
|
93
|
+
var _isPassthrough = requestHelpers.makeSkipMatcher(
|
|
94
|
+
{ skipPaths: passthroughPaths }, "auth.accessLock");
|
|
117
95
|
|
|
118
96
|
function _hasUnlockRole(req) {
|
|
119
97
|
if (!getRole || unlockRoles.length === 0) return false;
|
|
@@ -29,9 +29,11 @@
|
|
|
29
29
|
var nodeCrypto = require("node:crypto");
|
|
30
30
|
var bCrypto = require("../crypto");
|
|
31
31
|
var jwk = require("../jwk");
|
|
32
|
+
var jwtExternal = require("./jwt-external");
|
|
32
33
|
var safeJson = require("../safe-json");
|
|
33
34
|
var safeUrl = require("../safe-url");
|
|
34
35
|
var validateOpts = require("../validate-opts");
|
|
36
|
+
var nonceStore = require("../nonce-store");
|
|
35
37
|
var C = require("../constants");
|
|
36
38
|
var { AuthError } = require("../framework-error");
|
|
37
39
|
|
|
@@ -74,16 +76,12 @@ var REFUSED_ALGS = ["HS256", "HS384", "HS512", "none"];
|
|
|
74
76
|
|
|
75
77
|
function _b64urlEncode(buf) { return bCrypto.toBase64Url(buf); }
|
|
76
78
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
throw new AuthError("auth-dpop/bad-base64",
|
|
84
|
-
"DPoP segment is not valid base64url");
|
|
85
|
-
}
|
|
86
|
-
}
|
|
79
|
+
var _b64urlDecode = bCrypto.makeBase64UrlDecoder({
|
|
80
|
+
errorClass: AuthError,
|
|
81
|
+
code: "auth-dpop/bad-base64",
|
|
82
|
+
typeMessage: "expected base64url string",
|
|
83
|
+
badMessage: "DPoP segment is not valid base64url",
|
|
84
|
+
});
|
|
87
85
|
|
|
88
86
|
// Asymmetric key types DPoP accepts (its proof model relies on a
|
|
89
87
|
// signature, so symmetric "oct" keys are refused). AKP is the IANA key
|
|
@@ -128,16 +126,10 @@ function _normalizeHtu(htu) {
|
|
|
128
126
|
// Pick alg-specific node:crypto verify params. PQC algs use
|
|
129
127
|
// signWithoutAlgorithm shape (`null` algorithm).
|
|
130
128
|
function _signParamsForAlg(alg) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
if (
|
|
135
|
-
if (alg === "PS384") return { hash: "sha384", padding: nodeCrypto.constants.RSA_PKCS1_PSS_PADDING, saltLength: 48 }; // RFC 7518 PS384 salt length
|
|
136
|
-
if (alg === "PS512") return { hash: "sha512", padding: nodeCrypto.constants.RSA_PKCS1_PSS_PADDING, saltLength: 64 }; // RFC 7518 PS512 salt length
|
|
137
|
-
if (alg === "ES256") return { hash: "sha256", dsaEncoding: "ieee-p1363" };
|
|
138
|
-
if (alg === "ES384") return { hash: "sha384", dsaEncoding: "ieee-p1363" };
|
|
139
|
-
if (alg === "ES512") return { hash: "sha512", dsaEncoding: "ieee-p1363" };
|
|
140
|
-
if (alg === "EdDSA") return { hash: null };
|
|
129
|
+
// Classical-JOSE params (RS/PS/ES/EdDSA) from the shared table; DPoP layers
|
|
130
|
+
// PQC ML-DSA-87 on top (the only verifier that accepts it).
|
|
131
|
+
var params = jwtExternal.algParams(alg);
|
|
132
|
+
if (params) return params;
|
|
141
133
|
if (alg === "ML-DSA-87") return { hash: null, pqc: true };
|
|
142
134
|
throw new AuthError("auth-dpop/unsupported-alg",
|
|
143
135
|
"alg '" + alg + "' is not supported by DPoP");
|
|
@@ -195,11 +187,11 @@ function _detectAlgFromKey(key) {
|
|
|
195
187
|
}
|
|
196
188
|
|
|
197
189
|
function _jwkToKeyObject(jwk) {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
190
|
+
return bCrypto.importPublicJwk(jwk, {
|
|
191
|
+
errorClass: AuthError,
|
|
192
|
+
code: "auth-dpop/bad-jwk",
|
|
193
|
+
messagePrefix: "could not import jwk: ",
|
|
194
|
+
});
|
|
203
195
|
}
|
|
204
196
|
|
|
205
197
|
// ---- buildProof ----
|
|
@@ -460,16 +452,12 @@ async function verify(proof, opts) {
|
|
|
460
452
|
"verify: replayStore", AuthError, "auth-dpop/bad-replay-store",
|
|
461
453
|
"must expose checkAndInsert(jti, expireAtMs) — use b.nonceStore.create()");
|
|
462
454
|
var expireAtMs = nowMs + iatWindowSec * C.TIME.seconds(1) * 2;
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
}
|
|
469
|
-
if (inserted === false) {
|
|
470
|
-
throw new AuthError("auth-dpop/replay",
|
|
471
|
-
"DPoP proof jti='" + payload.jti + "' has been seen before — replay refused");
|
|
472
|
-
}
|
|
455
|
+
await nonceStore.enforceReplay(opts.replayStore, payload.jti, expireAtMs, {
|
|
456
|
+
errorClass: AuthError,
|
|
457
|
+
storeFailedCode: "auth-dpop/replay-store-failed",
|
|
458
|
+
replayCode: "auth-dpop/replay",
|
|
459
|
+
tokenLabel: "DPoP proof",
|
|
460
|
+
});
|
|
473
461
|
}
|
|
474
462
|
|
|
475
463
|
return { header: header, payload: payload, jkt: jkt };
|
|
@@ -43,6 +43,7 @@ var safeJson = require("../safe-json");
|
|
|
43
43
|
var safeBuffer = require("../safe-buffer");
|
|
44
44
|
var lazyRequire = require("../lazy-require");
|
|
45
45
|
var validateOpts = require("../validate-opts");
|
|
46
|
+
var jwtExternal = require("./jwt-external");
|
|
46
47
|
var _wa = require("../vendor/simplewebauthn-server.cjs");
|
|
47
48
|
var { FidoMds3Error } = require("../framework-error");
|
|
48
49
|
|
|
@@ -141,21 +142,14 @@ function _parseJws(token) {
|
|
|
141
142
|
// in practice; PS* and EdDSA are listed for completeness so future
|
|
142
143
|
// BLOBs over the same surface validate without a code edit.
|
|
143
144
|
function _verifyParamsForAlg(alg) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
case "ES384": return { hash: "sha384", dsaEncoding: "ieee-p1363" };
|
|
153
|
-
case "ES512": return { hash: "sha512", dsaEncoding: "ieee-p1363" };
|
|
154
|
-
case "EdDSA": return { hash: null };
|
|
155
|
-
default:
|
|
156
|
-
throw new FidoMds3Error("fido-mds3/unsupported-alg",
|
|
157
|
-
"JWS alg '" + alg + "' is not supported");
|
|
158
|
-
}
|
|
145
|
+
// Classical-JOSE alg→crypto params (RS/PS/ES/EdDSA) shared with the rest of
|
|
146
|
+
// the JOSE verifiers — jwtExternal.algParams owns the single table.
|
|
147
|
+
var params = jwtExternal.algParams(alg);
|
|
148
|
+
if (!params) {
|
|
149
|
+
throw new FidoMds3Error("fido-mds3/unsupported-alg",
|
|
150
|
+
"JWS alg '" + alg + "' is not supported");
|
|
151
|
+
}
|
|
152
|
+
return params;
|
|
159
153
|
}
|
|
160
154
|
|
|
161
155
|
// Resolve the trust roots. Operator override via caCertificate lets
|