@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
|
@@ -40,11 +40,12 @@
|
|
|
40
40
|
*/
|
|
41
41
|
|
|
42
42
|
var lazyRequire = require("./lazy-require");
|
|
43
|
-
var
|
|
43
|
+
var auditEmit = require("./audit-emit");
|
|
44
44
|
var log = lazyRequire(function () { return require("./log").boot("scheduler"); });
|
|
45
45
|
var clusterStorage = require("./cluster-storage");
|
|
46
46
|
var sql = require("./sql");
|
|
47
47
|
var validateOpts = require("./validate-opts");
|
|
48
|
+
var boundedMap = require("./bounded-map");
|
|
48
49
|
var C = require("./constants");
|
|
49
50
|
var { SchedulerError } = require("./framework-error");
|
|
50
51
|
|
|
@@ -417,15 +418,7 @@ function create(opts) {
|
|
|
417
418
|
|
|
418
419
|
var _err = SchedulerError.factory;
|
|
419
420
|
|
|
420
|
-
|
|
421
|
-
if (!auditOn) return;
|
|
422
|
-
audit().safeEmit({
|
|
423
|
-
action: action,
|
|
424
|
-
outcome: outcome,
|
|
425
|
-
metadata: info || {},
|
|
426
|
-
reason: info && info.reason ? info.reason : null,
|
|
427
|
-
});
|
|
428
|
-
}
|
|
421
|
+
var _emit = auditEmit.gatedReasonEmitter({ audit: auditOn });
|
|
429
422
|
|
|
430
423
|
function _isLeaderHere() {
|
|
431
424
|
if (!clusterInstance) return true;
|
|
@@ -447,10 +440,10 @@ function create(opts) {
|
|
|
447
440
|
if (typeof spec.name !== "string" || spec.name.length === 0) {
|
|
448
441
|
throw _err("INVALID_NAME", "scheduler.schedule: spec.name is required", true);
|
|
449
442
|
}
|
|
450
|
-
|
|
443
|
+
boundedMap.requireAbsent(tasks, spec.name, function () {
|
|
451
444
|
throw _err("DUPLICATE_NAME",
|
|
452
445
|
"scheduler.schedule: '" + spec.name + "' is already scheduled", true);
|
|
453
|
-
}
|
|
446
|
+
});
|
|
454
447
|
|
|
455
448
|
var hasCron = typeof spec.cron === "string";
|
|
456
449
|
var hasEvery = typeof spec.every === "number";
|
|
@@ -94,45 +94,90 @@ function eightKArtifact(opts) {
|
|
|
94
94
|
throw SecCyberError.factory("sec-cyber/bad-opts",
|
|
95
95
|
"secCyber.eightKArtifact: opts required");
|
|
96
96
|
}
|
|
97
|
-
validateOpts.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
97
|
+
validateOpts.shape(opts, {
|
|
98
|
+
incidentId: "required-string",
|
|
99
|
+
registrant: function (registrant) {
|
|
100
|
+
if (!registrant || typeof registrant !== "object") {
|
|
101
|
+
throw SecCyberError.factory("sec-cyber/bad-registrant",
|
|
102
|
+
"secCyber.eightKArtifact: registrant object required");
|
|
103
|
+
}
|
|
104
|
+
validateOpts.requireNonEmptyString(registrant.name,
|
|
105
|
+
"secCyber.eightKArtifact: registrant.name", SecCyberError, "BAD_REGISTRANT_NAME");
|
|
106
|
+
validateOpts.requireNonEmptyString(registrant.cik,
|
|
107
|
+
"secCyber.eightKArtifact: registrant.cik", SecCyberError, "BAD_CIK");
|
|
108
|
+
},
|
|
109
|
+
detectedAt: function (detectedAt) {
|
|
110
|
+
numericBounds.requirePositiveFiniteIntIfPresent(detectedAt,
|
|
111
|
+
"secCyber.eightKArtifact: detectedAt", SecCyberError, "BAD_DETECTED_AT");
|
|
112
|
+
},
|
|
113
|
+
materialityDeterminedAt: function (materialityDeterminedAt) {
|
|
114
|
+
numericBounds.requirePositiveFiniteIntIfPresent(materialityDeterminedAt,
|
|
115
|
+
"secCyber.eightKArtifact: materialityDeterminedAt", SecCyberError, "BAD_MAT_AT");
|
|
116
|
+
},
|
|
117
|
+
// materialityFinding / materialityReasoning and the material-only fields
|
|
118
|
+
// (nature/scope/timing/impact) and the AG-delay fields each carry their own
|
|
119
|
+
// per-field code (BAD_FINDING / BAD_REASONING / BAD_NATURE / ... /
|
|
120
|
+
// BAD_AG_JUSTIFICATION). Cross-field requiredness (the material-only and
|
|
121
|
+
// AG-delay fields) lives in the function rule via the 5th `opts` arg, so the
|
|
122
|
+
// whole contract is enforced inside this one exhaustive shape.
|
|
123
|
+
materialityFinding: function (v) {
|
|
124
|
+
if (FINDINGS.indexOf(v) === -1) {
|
|
125
|
+
throw SecCyberError.factory("sec-cyber/bad-finding",
|
|
126
|
+
"secCyber.eightKArtifact: materialityFinding must be one of " + FINDINGS.join(", "));
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
materialityReasoning: function (v) {
|
|
130
|
+
validateOpts.requireNonEmptyString(v,
|
|
131
|
+
"secCyber.eightKArtifact: materialityReasoning", SecCyberError, "BAD_REASONING");
|
|
132
|
+
},
|
|
133
|
+
nature: function (v, label, e, c, o) {
|
|
134
|
+
if (o.materialityFinding === "material") {
|
|
135
|
+
validateOpts.requireNonEmptyString(v,
|
|
136
|
+
"secCyber.eightKArtifact: nature", SecCyberError, "BAD_NATURE");
|
|
137
|
+
} else {
|
|
138
|
+
validateOpts.optionalNonEmptyString(v, label, e, c);
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
scope: function (v, label, e, c, o) {
|
|
142
|
+
if (o.materialityFinding === "material") {
|
|
143
|
+
validateOpts.requireNonEmptyString(v,
|
|
144
|
+
"secCyber.eightKArtifact: scope", SecCyberError, "BAD_SCOPE");
|
|
145
|
+
} else {
|
|
146
|
+
validateOpts.optionalNonEmptyString(v, label, e, c);
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
timing: function (v, label, e, c, o) {
|
|
150
|
+
if (o.materialityFinding === "material") {
|
|
151
|
+
validateOpts.requireNonEmptyString(v,
|
|
152
|
+
"secCyber.eightKArtifact: timing", SecCyberError, "BAD_TIMING");
|
|
153
|
+
} else {
|
|
154
|
+
validateOpts.optionalNonEmptyString(v, label, e, c);
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
impact: function (v, label, e, c, o) {
|
|
158
|
+
if (o.materialityFinding === "material") {
|
|
159
|
+
validateOpts.requireNonEmptyString(v,
|
|
160
|
+
"secCyber.eightKArtifact: impact", SecCyberError, "BAD_IMPACT");
|
|
161
|
+
} else {
|
|
162
|
+
validateOpts.optionalNonEmptyString(v, label, e, c);
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
agDelayRequested: "optional-boolean",
|
|
166
|
+
agDelayJustification: function (v, label, e, c, o) {
|
|
167
|
+
if (o.agDelayRequested === true) {
|
|
168
|
+
validateOpts.requireNonEmptyString(v,
|
|
169
|
+
"secCyber.eightKArtifact: agDelayJustification (required when agDelayRequested=true)",
|
|
170
|
+
SecCyberError, "BAD_AG_JUSTIFICATION");
|
|
171
|
+
} else {
|
|
172
|
+
validateOpts.optionalNonEmptyString(v, label, e, c);
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
// audit is a boolean toggle (`opts.audit !== false` suppresses emission);
|
|
176
|
+
// the emit uses the module-level b.audit sink, not this value.
|
|
177
|
+
audit: "optional-boolean",
|
|
178
|
+
}, "secCyber.eightKArtifact", SecCyberError, "BAD_INCIDENT_ID");
|
|
129
179
|
|
|
130
180
|
var agDelayRequested = opts.agDelayRequested === true;
|
|
131
|
-
if (agDelayRequested) {
|
|
132
|
-
validateOpts.requireNonEmptyString(opts.agDelayJustification,
|
|
133
|
-
"secCyber.eightKArtifact: agDelayJustification (required when agDelayRequested=true)",
|
|
134
|
-
SecCyberError, "BAD_AG_JUSTIFICATION");
|
|
135
|
-
}
|
|
136
181
|
|
|
137
182
|
var matAt = opts.materialityDeterminedAt || Date.now();
|
|
138
183
|
var deadline = agDelayRequested ? null : _addBusinessDays(matAt, 4);
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
*/
|
|
56
56
|
|
|
57
57
|
var nodePath = require("node:path");
|
|
58
|
+
var moduleLoader = require("./module-loader");
|
|
58
59
|
var atomicFile = require("./atomic-file");
|
|
59
60
|
var C = require("./constants");
|
|
60
61
|
var dbSchema = require("./db-schema");
|
|
@@ -190,18 +191,10 @@ function _listSeedFiles(rootDir, env) {
|
|
|
190
191
|
}
|
|
191
192
|
|
|
192
193
|
function _loadSeed(rootDir, env, file) {
|
|
193
|
-
var
|
|
194
|
-
|
|
195
|
-
// between calls picks it up. Production restarts the process anyway.
|
|
196
|
-
try { delete require.cache[require.resolve(fullPath)]; } catch (_e) { /* not yet cached */ }
|
|
197
|
-
var mod;
|
|
198
|
-
// Operator-supplied seed — dynamic by design, can't be bundle-traced.
|
|
199
|
-
// Host-CLI scope; deploying via SEA / pkg drops this surface.
|
|
200
|
-
try { mod = require(fullPath); } // allow:dynamic-require — operator-supplied seed
|
|
201
|
-
catch (e) {
|
|
202
|
-
throw _err("LOAD_FAILED",
|
|
194
|
+
var mod = moduleLoader.requireFresh(nodePath.join(_envDir(rootDir, env), file), function (e) {
|
|
195
|
+
return _err("LOAD_FAILED",
|
|
203
196
|
"seed '" + env + "/" + file + "' failed to load: " + ((e && e.message) || String(e)));
|
|
204
|
-
}
|
|
197
|
+
});
|
|
205
198
|
if (!mod || typeof mod.run !== "function") {
|
|
206
199
|
throw _err("BAD_SEED",
|
|
207
200
|
"seed '" + env + "/" + file + "' must export an async `run(db, ctx)` function");
|
|
@@ -57,13 +57,12 @@ var bCrypto = require("./crypto");
|
|
|
57
57
|
var httpClient = require("./http-client");
|
|
58
58
|
var safeJson = require("./safe-json");
|
|
59
59
|
var { URL: NodeUrl } = require("node:url");
|
|
60
|
-
var lazyRequire = require("./lazy-require");
|
|
61
60
|
var C = require("./constants");
|
|
62
61
|
var standaloneVerifier = require("./self-update-standalone-verifier");
|
|
63
62
|
var { boot } = require("./log");
|
|
64
63
|
var { defineClass } = require("./framework-error");
|
|
65
64
|
|
|
66
|
-
var
|
|
65
|
+
var auditEmit = require("./audit-emit");
|
|
67
66
|
|
|
68
67
|
var SelfUpdateError = defineClass("SelfUpdateError", { alwaysPermanent: true });
|
|
69
68
|
var log = boot("self-update");
|
|
@@ -76,13 +75,7 @@ var DEFAULT_HASH_ALG = "sha3-512";
|
|
|
76
75
|
var DEFAULT_RELEASES_BYTES = C.BYTES.mib(8); // GitHub releases JSON ~hundreds of KB; 8 MiB caps a malicious response
|
|
77
76
|
|
|
78
77
|
function _safeAuditEmit(action, outcome, metadata) {
|
|
79
|
-
|
|
80
|
-
audit().safeEmit({
|
|
81
|
-
action: action,
|
|
82
|
-
outcome: outcome || "success",
|
|
83
|
-
metadata: metadata || {},
|
|
84
|
-
});
|
|
85
|
-
} catch (_e) { /* drop-silent — by design */ }
|
|
78
|
+
auditEmit.emit(action, metadata, outcome);
|
|
86
79
|
}
|
|
87
80
|
|
|
88
81
|
// ---- semver-shaped comparison (tag_name like "v0.7.30" or "0.7.30") ----
|
|
@@ -218,44 +211,66 @@ function _compareTags(a, b) {
|
|
|
218
211
|
// ---- poll ----
|
|
219
212
|
|
|
220
213
|
function _validatePollOpts(opts) {
|
|
221
|
-
validateOpts.
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
214
|
+
validateOpts.shape(opts, {
|
|
215
|
+
releasesUrl: function (value) {
|
|
216
|
+
validateOpts.requireNonEmptyString(value,
|
|
217
|
+
"selfUpdate.poll: opts.releasesUrl", SelfUpdateError, "selfupdate/bad-releases-url");
|
|
218
|
+
// Scheme enforcement at config-time so the bug surfaces here, not
|
|
219
|
+
// inside the request loop. Default policy: https only. Operators
|
|
220
|
+
// wiring against an internal mirror can pass allowedProtocols
|
|
221
|
+
// explicitly to opt in to http (e.g. a TLS-terminating proxy
|
|
222
|
+
// upstream of the framework process). The full SSRF / hostname /
|
|
223
|
+
// length policy still runs inside httpClient.request.
|
|
224
|
+
var parsedProto;
|
|
225
|
+
try { parsedProto = new NodeUrl(value).protocol; }
|
|
226
|
+
catch (_e) {
|
|
227
|
+
throw new SelfUpdateError("selfupdate/bad-releases-url",
|
|
228
|
+
"selfUpdate.poll: opts.releasesUrl is not parseable as a URL");
|
|
229
|
+
}
|
|
230
|
+
var allowedProtocols = Array.isArray(opts.allowedProtocols) && opts.allowedProtocols.length > 0
|
|
231
|
+
? opts.allowedProtocols.slice() : ["https:"];
|
|
232
|
+
if (allowedProtocols.indexOf(parsedProto) === -1) {
|
|
233
|
+
throw new SelfUpdateError("selfupdate/bad-releases-url",
|
|
234
|
+
"selfUpdate.poll: opts.releasesUrl protocol '" + parsedProto +
|
|
235
|
+
"' not in allowedProtocols [" + allowedProtocols.join(", ") + "]");
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
currentVersion: { rule: "required-string", code: "selfupdate/bad-current-version",
|
|
239
|
+
label: "selfUpdate.poll: opts.currentVersion" },
|
|
240
|
+
assetPattern: function (value) {
|
|
241
|
+
if (value !== undefined && !(value instanceof RegExp) && typeof value !== "string") {
|
|
242
|
+
throw new SelfUpdateError("selfupdate/bad-asset-pattern",
|
|
243
|
+
"selfUpdate.poll: opts.assetPattern must be a RegExp or string when present");
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
signaturePattern: function (value) {
|
|
247
|
+
if (value !== undefined && !(value instanceof RegExp) && typeof value !== "string") {
|
|
248
|
+
throw new SelfUpdateError("selfupdate/bad-sig-pattern",
|
|
249
|
+
"selfUpdate.poll: opts.signaturePattern must be a RegExp or string when present");
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
maxBytes: function (value) {
|
|
253
|
+
numericBounds.requirePositiveFiniteIntIfPresent(value,
|
|
254
|
+
"selfUpdate.poll: opts.maxBytes", SelfUpdateError, "selfupdate/bad-max-bytes");
|
|
255
|
+
},
|
|
256
|
+
timeoutMs: function (value) {
|
|
257
|
+
numericBounds.requirePositiveFiniteIntIfPresent(value,
|
|
258
|
+
"selfUpdate.poll: opts.timeoutMs", SelfUpdateError, "selfupdate/bad-timeout");
|
|
259
|
+
},
|
|
260
|
+
// allowedProtocols is consumed locally (the releasesUrl scheme gate
|
|
261
|
+
// above reads it) and also forwarded to httpClient.request.
|
|
262
|
+
allowedProtocols: { rule: "optional-string-array", code: "selfupdate/bad-allowed-protocols",
|
|
263
|
+
label: "selfUpdate.poll: opts.allowedProtocols" },
|
|
264
|
+
// headers is merged onto the outbound request headers locally.
|
|
265
|
+
headers: { rule: "optional-plain-object", code: "selfupdate/bad-headers",
|
|
266
|
+
label: "selfUpdate.poll: opts.headers" },
|
|
267
|
+
// etag is used locally for the If-None-Match request header.
|
|
268
|
+
etag: { rule: "optional-string", code: "selfupdate/bad-etag",
|
|
269
|
+
label: "selfUpdate.poll: opts.etag" },
|
|
270
|
+
// allowedHosts / allowInternal are forwarded verbatim to
|
|
271
|
+
// httpClient.request, which owns their SSRF-gate validation.
|
|
272
|
+
}, "selfUpdate.poll", SelfUpdateError, "selfupdate/bad-opts",
|
|
273
|
+
{ allow: ["allowedHosts", "allowInternal"] });
|
|
259
274
|
}
|
|
260
275
|
|
|
261
276
|
function _matchAsset(name, pattern, fallback) {
|
|
@@ -461,21 +476,25 @@ async function poll(opts) {
|
|
|
461
476
|
// ---- verify ----
|
|
462
477
|
|
|
463
478
|
function _validateVerifyOpts(opts) {
|
|
464
|
-
validateOpts.
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
+
validateOpts.shape(opts, {
|
|
480
|
+
assetPath: { rule: "required-string", code: "selfupdate/bad-asset-path",
|
|
481
|
+
label: "selfUpdate.verify: opts.assetPath" },
|
|
482
|
+
signaturePath: { rule: "required-string", code: "selfupdate/bad-signature-path",
|
|
483
|
+
label: "selfUpdate.verify: opts.signaturePath" },
|
|
484
|
+
pubkeyPem: { rule: "required-string", code: "selfupdate/bad-pubkey",
|
|
485
|
+
label: "selfUpdate.verify: opts.pubkeyPem (PEM-encoded public key)" },
|
|
486
|
+
hashAlgo: function (value) {
|
|
487
|
+
if (value !== undefined &&
|
|
488
|
+
(typeof value !== "string" || ALLOWED_HASH_ALGS.indexOf(value) === -1)) {
|
|
489
|
+
throw new SelfUpdateError("selfupdate/bad-hash-algo",
|
|
490
|
+
"selfUpdate.verify: opts.hashAlgo must be one of " + ALLOWED_HASH_ALGS.join(", "));
|
|
491
|
+
}
|
|
492
|
+
},
|
|
493
|
+
maxBytes: function (value) {
|
|
494
|
+
numericBounds.requirePositiveFiniteIntIfPresent(value,
|
|
495
|
+
"selfUpdate.verify: opts.maxBytes", SelfUpdateError, "selfupdate/bad-max-bytes");
|
|
496
|
+
},
|
|
497
|
+
}, "selfUpdate.verify", SelfUpdateError, "selfupdate/bad-opts");
|
|
479
498
|
}
|
|
480
499
|
|
|
481
500
|
/**
|
|
@@ -565,15 +584,19 @@ async function verify(opts) {
|
|
|
565
584
|
// ---- swap ----
|
|
566
585
|
|
|
567
586
|
function _validateSwapOpts(opts, label) {
|
|
568
|
-
|
|
587
|
+
// requireObject runs first (shape does it) so an opts-shape error keeps
|
|
588
|
+
// the selfupdate/bad-opts code. `from` is validated only for swap, and
|
|
589
|
+
// first to preserve the original field-evaluation order.
|
|
590
|
+
var schema = {};
|
|
569
591
|
if (label === "swap") {
|
|
570
|
-
|
|
571
|
-
|
|
592
|
+
schema.from = { rule: "required-string", code: "selfupdate/bad-from",
|
|
593
|
+
label: "selfUpdate.swap: opts.from" };
|
|
572
594
|
}
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
595
|
+
schema.to = { rule: "required-string", code: "selfupdate/bad-to",
|
|
596
|
+
label: "selfUpdate." + label + ": opts.to" };
|
|
597
|
+
schema.backupTo = { rule: "required-string", code: "selfupdate/bad-backup",
|
|
598
|
+
label: "selfUpdate." + label + ": opts.backupTo" };
|
|
599
|
+
validateOpts.shape(opts, schema, "selfUpdate." + label, SelfUpdateError, "selfupdate/bad-opts");
|
|
577
600
|
}
|
|
578
601
|
|
|
579
602
|
// _safeRollback — best-effort restore of `to` from `backupTo` during
|
|
@@ -97,13 +97,8 @@ function _requireFunction(name, val) {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
function _requireBindingStore(s) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
typeof s.set !== "function" ||
|
|
103
|
-
typeof s.del !== "function") {
|
|
104
|
-
throw new SessionDeviceBindingError("session-device-binding/bad-opt",
|
|
105
|
-
"bindingStore must be a b.cache-shaped object (get/set/del)");
|
|
106
|
-
}
|
|
100
|
+
validateOpts.requireMethods(s, ["get", "set", "del"],
|
|
101
|
+
"bindingStore (b.cache-shaped)", SessionDeviceBindingError, "session-device-binding/bad-opt");
|
|
107
102
|
}
|
|
108
103
|
|
|
109
104
|
function _requireToken(token) {
|
|
@@ -164,6 +159,105 @@ function _ipPrefix(ip, bits) {
|
|
|
164
159
|
return "v4:" + maskedOctets.join(".") + "/" + v4Bits;
|
|
165
160
|
}
|
|
166
161
|
|
|
162
|
+
// Resolve operator-supplied fingerprintExtras(req) to a stable string. A
|
|
163
|
+
// throwing or non-serializable extractor drops to "" — extras only sharpen the
|
|
164
|
+
// digest, they must never crash fingerprinting.
|
|
165
|
+
function _resolveExtrasFn(fn, req) {
|
|
166
|
+
if (!fn) return "";
|
|
167
|
+
var v;
|
|
168
|
+
try { v = fn(req); } catch (_e) { return ""; }
|
|
169
|
+
if (v === null || v === undefined) return "";
|
|
170
|
+
if (typeof v === "string") return v;
|
|
171
|
+
try { return JSON.stringify(v); } catch (_e) { return ""; }
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Clamp an { v4, v6 } prefix-bits opt to valid IPv4/IPv6 ranges, defaulting
|
|
175
|
+
// each independently.
|
|
176
|
+
function _resolveIpBits(ipBits) {
|
|
177
|
+
ipBits = ipBits || {};
|
|
178
|
+
return {
|
|
179
|
+
v4: (typeof ipBits.v4 === "number" && isFinite(ipBits.v4) && ipBits.v4 >= 0 && ipBits.v4 <= 32) // IPv4 max prefix length in bits
|
|
180
|
+
? ipBits.v4 : DEFAULT_IP_V4_PREFIX,
|
|
181
|
+
v6: (typeof ipBits.v6 === "number" && isFinite(ipBits.v6) && ipBits.v6 >= 0 && ipBits.v6 <= 128) // IPv6 max prefix length in bits
|
|
182
|
+
? ipBits.v6 : DEFAULT_IP_V6_PREFIX,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Pure request-shape device fingerprint — the side-effect-free core shared by
|
|
187
|
+
// the instance lookup and the static fingerprint() entry point. cfg: { v4Bits,
|
|
188
|
+
// v6Bits, extras (string), boundKey (Buffer|null) }. No store, no audit, no
|
|
189
|
+
// session — just headers + masked client IP (+ optional bound key) -> SHAKE256.
|
|
190
|
+
function _computeDeviceFingerprint(req, cfg) {
|
|
191
|
+
_requireReq(req);
|
|
192
|
+
var headers = req.headers || {};
|
|
193
|
+
var ua = typeof headers["user-agent"] === "string" ? headers["user-agent"] : "";
|
|
194
|
+
var al = _normalizeAcceptLanguage(headers["accept-language"]);
|
|
195
|
+
var ae = _normalizeAcceptEncoding(headers["accept-encoding"]);
|
|
196
|
+
var ip = "";
|
|
197
|
+
try { ip = requestHelpers.clientIp(req); } catch (_e) { ip = ""; }
|
|
198
|
+
var family = ip.indexOf(":") !== -1 ? "v6" : "v4";
|
|
199
|
+
var ipPart = _ipPrefix(ip, family === "v6" ? cfg.v6Bits : cfg.v4Bits);
|
|
200
|
+
var keyPart = "";
|
|
201
|
+
if (Buffer.isBuffer(cfg.boundKey)) {
|
|
202
|
+
keyPart = "k:" + nodeCrypto.createHash("sha3-256").update(cfg.boundKey).digest("hex");
|
|
203
|
+
}
|
|
204
|
+
var canonical = [
|
|
205
|
+
"ua=" + ua,
|
|
206
|
+
"al=" + al,
|
|
207
|
+
"ae=" + ae,
|
|
208
|
+
"ip=" + ipPart,
|
|
209
|
+
"ex=" + (cfg.extras || ""),
|
|
210
|
+
keyPart,
|
|
211
|
+
].join("\n");
|
|
212
|
+
var hash = nodeCrypto.createHash("shake256", { outputLength: FINGERPRINT_BYTES })
|
|
213
|
+
.update(canonical)
|
|
214
|
+
.digest();
|
|
215
|
+
return { fingerprint: hash, components: {
|
|
216
|
+
ua: ua, al: al, ae: ae, ip: ipPart, hasBoundKey: !!keyPart,
|
|
217
|
+
} };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* @primitive b.sessionDeviceBinding.fingerprint
|
|
222
|
+
* @signature b.sessionDeviceBinding.fingerprint(req, opts?)
|
|
223
|
+
* @since 0.15.13
|
|
224
|
+
* @status stable
|
|
225
|
+
* @related b.session.rotate, b.session.create
|
|
226
|
+
*
|
|
227
|
+
* Compute the stateless SHAKE256 device-shape digest for a request with no
|
|
228
|
+
* store, no session, and no side effects — the soft device-binding building
|
|
229
|
+
* block for self-validating tokens (a sealed cookie, a JWT) that carry the
|
|
230
|
+
* fingerprint inside the token and compare it themselves. `create()` requires a
|
|
231
|
+
* bindingStore for the persisted bind()/verify() lifecycle; this static form
|
|
232
|
+
* skips that gate because it touches no store. Returns a 32-byte Buffer derived
|
|
233
|
+
* from User-Agent + normalized Accept-Language / Accept-Encoding + the masked
|
|
234
|
+
* client-IP prefix (+ optional operator extras). Throws only on a missing or
|
|
235
|
+
* malformed request object.
|
|
236
|
+
*
|
|
237
|
+
* @opts
|
|
238
|
+
* ipPrefixBits: { v4: number, v6: number }, // default { v4: 24, v6: 48 } — mask width that survives a roaming IP
|
|
239
|
+
* fingerprintExtras: function, // (req) => string|object, optional extra signal folded into the digest
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
* var fp = b.sessionDeviceBinding.fingerprint(req);
|
|
243
|
+
* // seal fp inside the cookie/JWT; on the next request recompute + constant-time compare
|
|
244
|
+
*/
|
|
245
|
+
function fingerprint(req, opts) {
|
|
246
|
+
opts = opts || {};
|
|
247
|
+
if (opts.fingerprintExtras !== undefined && opts.fingerprintExtras !== null &&
|
|
248
|
+
typeof opts.fingerprintExtras !== "function") {
|
|
249
|
+
throw new SessionDeviceBindingError("session-device-binding/bad-opt",
|
|
250
|
+
"fingerprint: fingerprintExtras must be a function (req) => string|object");
|
|
251
|
+
}
|
|
252
|
+
var bits = _resolveIpBits(opts.ipPrefixBits);
|
|
253
|
+
return _computeDeviceFingerprint(req, {
|
|
254
|
+
v4Bits: bits.v4,
|
|
255
|
+
v6Bits: bits.v6,
|
|
256
|
+
extras: _resolveExtrasFn(opts.fingerprintExtras, req),
|
|
257
|
+
boundKey: null,
|
|
258
|
+
}).fingerprint;
|
|
259
|
+
}
|
|
260
|
+
|
|
167
261
|
function create(opts) {
|
|
168
262
|
opts = opts || {};
|
|
169
263
|
validateOpts(opts, ALLOWED_OPTS, "sessionDeviceBinding.create");
|
|
@@ -215,29 +309,9 @@ function create(opts) {
|
|
|
215
309
|
var boundKeyResolver = opts.boundKeyResolver || null;
|
|
216
310
|
var fingerprintExtras = opts.fingerprintExtras || null;
|
|
217
311
|
|
|
218
|
-
|
|
219
|
-
var sink = obsInst || _safeGlobalObs();
|
|
220
|
-
if (!sink) return;
|
|
221
|
-
try { sink.event(name, 1, labels); } catch (_e) { /* drop-silent */ }
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
function _safeGlobalObs() {
|
|
225
|
-
try { return observability(); } catch (_e) { return null; }
|
|
226
|
-
}
|
|
312
|
+
var _emitObs = observability().makeCounterEmitter(obsInst);
|
|
227
313
|
|
|
228
|
-
|
|
229
|
-
if (!auditInst) return;
|
|
230
|
-
try {
|
|
231
|
-
var event = {
|
|
232
|
-
action: action,
|
|
233
|
-
outcome: outcome,
|
|
234
|
-
resource: { kind: "session.device", id: tokenHash },
|
|
235
|
-
metadata: metadata || {},
|
|
236
|
-
};
|
|
237
|
-
if (req) event.actor = requestHelpers.extractActorContext(req);
|
|
238
|
-
auditInst.safeEmit(event);
|
|
239
|
-
} catch (_e) { /* drop-silent */ }
|
|
240
|
-
}
|
|
314
|
+
var _emitAudit = requestHelpers.makeResourceAuditEmitter(auditInst, "session.device");
|
|
241
315
|
|
|
242
316
|
function _hashTokenForAudit(token) {
|
|
243
317
|
// Don't put the raw session id in the audit log. SHAKE256 to a
|
|
@@ -259,51 +333,22 @@ function create(opts) {
|
|
|
259
333
|
}
|
|
260
334
|
|
|
261
335
|
function _resolveExtras(req) {
|
|
262
|
-
|
|
263
|
-
var v;
|
|
264
|
-
try { v = fingerprintExtras(req); }
|
|
265
|
-
catch (_e) { return ""; }
|
|
266
|
-
if (v === null || v === undefined) return "";
|
|
267
|
-
if (typeof v === "string") return v;
|
|
268
|
-
try { return JSON.stringify(v); } catch (_e) { return ""; }
|
|
336
|
+
return _resolveExtrasFn(fingerprintExtras, req);
|
|
269
337
|
}
|
|
270
338
|
|
|
271
339
|
function _computeFingerprint(req) {
|
|
272
340
|
_requireReq(req);
|
|
273
|
-
var headers = req.headers || {};
|
|
274
|
-
var ua = typeof headers["user-agent"] === "string" ? headers["user-agent"] : "";
|
|
275
|
-
var al = _normalizeAcceptLanguage(headers["accept-language"]);
|
|
276
|
-
var ae = _normalizeAcceptEncoding(headers["accept-encoding"]);
|
|
277
|
-
var ip = "";
|
|
278
|
-
try { ip = requestHelpers.clientIp(req); } catch (_e) { ip = ""; }
|
|
279
|
-
var family = ip.indexOf(":") !== -1 ? "v6" : "v4";
|
|
280
|
-
var ipPart = _ipPrefix(ip, family === "v6" ? v6Bits : v4Bits);
|
|
281
|
-
var extras = _resolveExtras(req);
|
|
282
|
-
|
|
283
341
|
var boundKeyMaybe = _resolveBoundKey(req);
|
|
284
342
|
if (requireBoundKey && (boundKeyMaybe === null || boundKeyMaybe === undefined)) {
|
|
285
343
|
return { ok: false, reason: "missing-bound-key" };
|
|
286
344
|
}
|
|
287
|
-
var
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
"al=" + al,
|
|
295
|
-
"ae=" + ae,
|
|
296
|
-
"ip=" + ipPart,
|
|
297
|
-
"ex=" + extras,
|
|
298
|
-
keyPart,
|
|
299
|
-
].join("\n");
|
|
300
|
-
|
|
301
|
-
var hash = nodeCrypto.createHash("shake256", { outputLength: FINGERPRINT_BYTES })
|
|
302
|
-
.update(canonical)
|
|
303
|
-
.digest();
|
|
304
|
-
return { ok: true, fingerprint: hash, components: {
|
|
305
|
-
ua: ua, al: al, ae: ae, ip: ipPart, hasBoundKey: !!keyPart,
|
|
306
|
-
} };
|
|
345
|
+
var r = _computeDeviceFingerprint(req, {
|
|
346
|
+
v4Bits: v4Bits,
|
|
347
|
+
v6Bits: v6Bits,
|
|
348
|
+
extras: _resolveExtras(req),
|
|
349
|
+
boundKey: Buffer.isBuffer(boundKeyMaybe) ? boundKeyMaybe : null,
|
|
350
|
+
});
|
|
351
|
+
return { ok: true, fingerprint: r.fingerprint, components: r.components };
|
|
307
352
|
}
|
|
308
353
|
|
|
309
354
|
async function bind(token, req) {
|
|
@@ -421,6 +466,7 @@ function create(opts) {
|
|
|
421
466
|
|
|
422
467
|
module.exports = {
|
|
423
468
|
create: create,
|
|
469
|
+
fingerprint: fingerprint,
|
|
424
470
|
SessionDeviceBindingError: SessionDeviceBindingError,
|
|
425
471
|
DEFAULTS: Object.freeze({
|
|
426
472
|
ttlMs: DEFAULT_TTL_MS,
|