@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
|
@@ -28,7 +28,6 @@ var { Readable } = require("node:stream");
|
|
|
28
28
|
var bCrypto = require("../crypto");
|
|
29
29
|
var safeJson = require("../safe-json");
|
|
30
30
|
var C = require("../constants");
|
|
31
|
-
var numericBounds = require("../numeric-bounds");
|
|
32
31
|
var requestHelpers = require("../request-helpers");
|
|
33
32
|
var { ObjectStoreError } = require("../framework-error");
|
|
34
33
|
var safeUrl = require("../safe-url");
|
|
@@ -60,11 +59,6 @@ var GCS_V4_ALGORITHM = "GOOG4-RSA-SHA256";
|
|
|
60
59
|
var GCS_V4_SERVICE = "storage";
|
|
61
60
|
var GCS_V4_REGION = "auto";
|
|
62
61
|
|
|
63
|
-
// Same expiry bounds as SigV4 — V4 presigning shares the spec's 7-day cap.
|
|
64
|
-
var PRESIGN_DEFAULT_EXPIRES_SECONDS = C.TIME.minutes(15) / C.TIME.seconds(1);
|
|
65
|
-
var PRESIGN_MAX_EXPIRES_SECONDS = C.TIME.days(7) / C.TIME.seconds(1);
|
|
66
|
-
var PRESIGN_MIN_EXPIRES_SECONDS = 1;
|
|
67
|
-
|
|
68
62
|
var SERVICE_ACCOUNT_SCHEMA = {
|
|
69
63
|
type: "object",
|
|
70
64
|
required: ["client_email", "private_key"],
|
|
@@ -238,32 +232,13 @@ function create(config) {
|
|
|
238
232
|
var token = await _ensureToken();
|
|
239
233
|
var url = _objectUrl(key, { alt: "media" });
|
|
240
234
|
var headers = authHeader.bearer(token);
|
|
241
|
-
|
|
242
|
-
headers["Range"] = "bytes=" + opts.range.start + "-" + opts.range.end;
|
|
243
|
-
}
|
|
244
|
-
if (opts.ifNoneMatch) headers["If-None-Match"] = opts.ifNoneMatch;
|
|
245
|
-
if (opts.ifMatch) headers["If-Match"] = opts.ifMatch;
|
|
246
|
-
if (opts.ifModifiedSince) headers["If-Modified-Since"] = opts.ifModifiedSince;
|
|
247
|
-
if (opts.ifUnmodifiedSince) headers["If-Unmodified-Since"] = opts.ifUnmodifiedSince;
|
|
235
|
+
sharedRequest.applyConditionalGetHeaders(headers, opts, "Range");
|
|
248
236
|
try {
|
|
249
237
|
var res = await _httpRequest("GET", url, headers, null, reqOpts);
|
|
250
|
-
return
|
|
251
|
-
statusCode: res.statusCode,
|
|
252
|
-
body: res.body,
|
|
253
|
-
etag: res.headers && res.headers.etag,
|
|
254
|
-
lastModified: res.headers && res.headers["last-modified"]
|
|
255
|
-
? Date.parse(res.headers["last-modified"]) : null,
|
|
256
|
-
contentRange: res.headers && res.headers["content-range"] || null,
|
|
257
|
-
size: res.headers && res.headers["content-length"]
|
|
258
|
-
? parseInt(res.headers["content-length"], 10) : null,
|
|
259
|
-
contentType: res.headers && res.headers["content-type"] || null,
|
|
260
|
-
};
|
|
238
|
+
return sharedRequest.mapGetResponse(res);
|
|
261
239
|
} catch (err) {
|
|
262
240
|
if (err && err.statusCode === requestHelpers.HTTP_STATUS.NOT_MODIFIED) {
|
|
263
|
-
return
|
|
264
|
-
statusCode: requestHelpers.HTTP_STATUS.NOT_MODIFIED,
|
|
265
|
-
body: null, etag: null, lastModified: null,
|
|
266
|
-
};
|
|
241
|
+
return sharedRequest.notModifiedGetResult();
|
|
267
242
|
}
|
|
268
243
|
throw err;
|
|
269
244
|
}
|
|
@@ -326,21 +301,8 @@ function create(config) {
|
|
|
326
301
|
|
|
327
302
|
function _v4Presign(method, opts) {
|
|
328
303
|
opts = opts || {};
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
}
|
|
332
|
-
if (opts.key.indexOf("\0") !== -1) {
|
|
333
|
-
throw _err("INVALID_KEY", "null byte in key", true);
|
|
334
|
-
}
|
|
335
|
-
var expiresIn = opts.expiresIn != null ? opts.expiresIn : PRESIGN_DEFAULT_EXPIRES_SECONDS;
|
|
336
|
-
if (typeof expiresIn !== "number" ||
|
|
337
|
-
expiresIn < PRESIGN_MIN_EXPIRES_SECONDS ||
|
|
338
|
-
expiresIn > PRESIGN_MAX_EXPIRES_SECONDS) {
|
|
339
|
-
throw _err("INVALID_EXPIRES",
|
|
340
|
-
"presigned URL: expiresIn must be a number of seconds between " +
|
|
341
|
-
PRESIGN_MIN_EXPIRES_SECONDS + " and " + PRESIGN_MAX_EXPIRES_SECONDS +
|
|
342
|
-
" (7 days, V4 hard cap)", true);
|
|
343
|
-
}
|
|
304
|
+
sharedRequest.requirePresignKey(opts, "presigned URL");
|
|
305
|
+
var expiresIn = sharedRequest.resolvePresignExpires(opts, "presigned URL", "V4");
|
|
344
306
|
|
|
345
307
|
// V4 presigned URLs target the XML API path-style endpoint
|
|
346
308
|
// (storage.googleapis.com/{bucket}/{key}), not the JSON API used
|
|
@@ -418,34 +380,9 @@ function create(config) {
|
|
|
418
380
|
// declared range get a 403 from the bucket itself.
|
|
419
381
|
function presignedUploadPolicy(opts) {
|
|
420
382
|
opts = opts || {};
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
if (opts.key.indexOf("\0") !== -1) {
|
|
425
|
-
throw _err("INVALID_KEY", "null byte in key", true);
|
|
426
|
-
}
|
|
427
|
-
if (typeof opts.maxBytes !== "number" || !Number.isFinite(opts.maxBytes) ||
|
|
428
|
-
opts.maxBytes <= 0) {
|
|
429
|
-
throw _err("INVALID_MAX_BYTES",
|
|
430
|
-
"presignedUploadPolicy: maxBytes (positive number of bytes) is required — " +
|
|
431
|
-
"POST-form policy enforces body size via the content-length-range condition; " +
|
|
432
|
-
"use presignedUploadUrl if size enforcement is not needed", true);
|
|
433
|
-
}
|
|
434
|
-
if (opts.minBytes !== undefined && !numericBounds.isNonNegativeFiniteInt(opts.minBytes)) {
|
|
435
|
-
throw _err("INVALID_MIN_BYTES",
|
|
436
|
-
"presignedUploadPolicy: minBytes must be a non-negative finite integer; got " +
|
|
437
|
-
numericBounds.shape(opts.minBytes), true);
|
|
438
|
-
}
|
|
439
|
-
var minBytes = opts.minBytes !== undefined ? opts.minBytes : 0;
|
|
440
|
-
var expiresIn = opts.expiresIn != null ? opts.expiresIn : PRESIGN_DEFAULT_EXPIRES_SECONDS;
|
|
441
|
-
if (typeof expiresIn !== "number" ||
|
|
442
|
-
expiresIn < PRESIGN_MIN_EXPIRES_SECONDS ||
|
|
443
|
-
expiresIn > PRESIGN_MAX_EXPIRES_SECONDS) {
|
|
444
|
-
throw _err("INVALID_EXPIRES",
|
|
445
|
-
"presignedUploadPolicy: expiresIn must be a number of seconds between " +
|
|
446
|
-
PRESIGN_MIN_EXPIRES_SECONDS + " and " + PRESIGN_MAX_EXPIRES_SECONDS +
|
|
447
|
-
" (7 days, V4 hard cap)", true);
|
|
448
|
-
}
|
|
383
|
+
sharedRequest.requirePresignKey(opts, "presignedUploadPolicy");
|
|
384
|
+
var minBytes = sharedRequest.resolvePresignUploadMinBytes(opts);
|
|
385
|
+
var expiresIn = sharedRequest.resolvePresignExpires(opts, "presignedUploadPolicy", "V4");
|
|
449
386
|
|
|
450
387
|
var date = opts.date || new Date();
|
|
451
388
|
var amzDate = sigv4.formatAmzDate(date);
|
|
@@ -102,11 +102,7 @@ function create(config) {
|
|
|
102
102
|
function head(key) {
|
|
103
103
|
var url = _keyToUrl(baseUrl, key);
|
|
104
104
|
return _request("HEAD", url, null, headers, reqOpts).then(function (res) {
|
|
105
|
-
return
|
|
106
|
-
size: res.headers["content-length"] ? parseInt(res.headers["content-length"], 10) : null,
|
|
107
|
-
etag: res.headers.etag,
|
|
108
|
-
lastModified: res.headers["last-modified"] ? Date.parse(res.headers["last-modified"]) : null,
|
|
109
|
-
};
|
|
105
|
+
return sharedRequest.mapHeadResponse(res);
|
|
110
106
|
});
|
|
111
107
|
}
|
|
112
108
|
|
|
@@ -17,8 +17,17 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
var httpClient = require("../http-client");
|
|
20
|
+
var C = require("../constants");
|
|
21
|
+
var numericBounds = require("../numeric-bounds");
|
|
22
|
+
var requestHelpers = require("../request-helpers");
|
|
20
23
|
var { ObjectStoreError } = require("../framework-error");
|
|
21
24
|
|
|
25
|
+
// Same code-first error factory the object-store backends use; the bare
|
|
26
|
+
// cloud-provider-style codes (INVALID_KEY / INVALID_EXPIRES / ...) are the
|
|
27
|
+
// existing object-store convention, swept to namespace/kebab-case for the
|
|
28
|
+
// whole family in the v1.0 error-code pass.
|
|
29
|
+
var _err = ObjectStoreError.factory;
|
|
30
|
+
|
|
22
31
|
function request(method, url, headers, body, opts) {
|
|
23
32
|
opts = opts || {};
|
|
24
33
|
var req = {
|
|
@@ -35,4 +44,123 @@ function request(method, url, headers, body, opts) {
|
|
|
35
44
|
return httpClient.request(req);
|
|
36
45
|
}
|
|
37
46
|
|
|
47
|
+
// ---- Shared presign opts validation (gcs / sigv4) ----
|
|
48
|
+
// Every presigning entry point (presigned GET/PUT URLs and the POST-form
|
|
49
|
+
// upload policy) opened with the same key + expiry bounds checks, varying
|
|
50
|
+
// only in the message prefix and the signature-version label in the
|
|
51
|
+
// hard-cap text. Centralized so the bounds are enforced identically and a
|
|
52
|
+
// future change (a new cap, a different default) is one edit.
|
|
53
|
+
var PRESIGN_DEFAULT_EXPIRES_SECONDS = C.TIME.minutes(15) / C.TIME.seconds(1); // 15 minutes
|
|
54
|
+
var PRESIGN_MAX_EXPIRES_SECONDS = C.TIME.days(7) / C.TIME.seconds(1); // 7 days
|
|
55
|
+
var PRESIGN_MIN_EXPIRES_SECONDS = 1;
|
|
56
|
+
|
|
57
|
+
function requirePresignKey(opts, msgPrefix) {
|
|
58
|
+
if (!opts.key || typeof opts.key !== "string") {
|
|
59
|
+
throw _err("INVALID_KEY", msgPrefix + ": key is required", true);
|
|
60
|
+
}
|
|
61
|
+
if (opts.key.indexOf("\0") !== -1) {
|
|
62
|
+
throw _err("INVALID_KEY", "null byte in key", true);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// hardCapLabel names the signing version in the cap text ("V4" / "SigV4"
|
|
67
|
+
// → "(7 days, V4 hard cap)"); an empty / omitted label yields the plain
|
|
68
|
+
// "(7 days)" tail used by the Azure SAS path, whose cap is the same 7 days
|
|
69
|
+
// but is not a SigV4 family limit.
|
|
70
|
+
function resolvePresignExpires(opts, msgPrefix, hardCapLabel) {
|
|
71
|
+
var expiresIn = opts.expiresIn != null ? opts.expiresIn : PRESIGN_DEFAULT_EXPIRES_SECONDS;
|
|
72
|
+
if (typeof expiresIn !== "number" ||
|
|
73
|
+
expiresIn < PRESIGN_MIN_EXPIRES_SECONDS ||
|
|
74
|
+
expiresIn > PRESIGN_MAX_EXPIRES_SECONDS) {
|
|
75
|
+
var capTail = hardCapLabel ? " (7 days, " + hardCapLabel + " hard cap)" : " (7 days)";
|
|
76
|
+
throw _err("INVALID_EXPIRES",
|
|
77
|
+
msgPrefix + ": expiresIn must be a number of seconds between " +
|
|
78
|
+
PRESIGN_MIN_EXPIRES_SECONDS + " and " + PRESIGN_MAX_EXPIRES_SECONDS +
|
|
79
|
+
capTail, true);
|
|
80
|
+
}
|
|
81
|
+
return expiresIn;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// POST-form upload policy size bounds — returns the resolved minBytes
|
|
85
|
+
// (defaulting to 0). maxBytes is validated here but consumed by the
|
|
86
|
+
// caller (it becomes the content-length-range upper bound).
|
|
87
|
+
function resolvePresignUploadMinBytes(opts) {
|
|
88
|
+
if (typeof opts.maxBytes !== "number" || !Number.isFinite(opts.maxBytes) ||
|
|
89
|
+
opts.maxBytes <= 0) {
|
|
90
|
+
throw _err("INVALID_MAX_BYTES",
|
|
91
|
+
"presignedUploadPolicy: maxBytes (positive number of bytes) is required — " +
|
|
92
|
+
"POST-form policy enforces body size via the content-length-range condition; " +
|
|
93
|
+
"use presignedUploadUrl if size enforcement is not needed", true);
|
|
94
|
+
}
|
|
95
|
+
if (opts.minBytes !== undefined && !numericBounds.isNonNegativeFiniteInt(opts.minBytes)) {
|
|
96
|
+
throw _err("INVALID_MIN_BYTES",
|
|
97
|
+
"presignedUploadPolicy: minBytes must be a non-negative finite integer; got " +
|
|
98
|
+
numericBounds.shape(opts.minBytes), true);
|
|
99
|
+
}
|
|
100
|
+
return opts.minBytes !== undefined ? opts.minBytes : 0;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ---- Shared conditional-GET request + response mapping (gcs / sigv4 / azure) ----
|
|
104
|
+
// Every backend's getResponse() set the same RFC 7232/7233 conditional
|
|
105
|
+
// headers (Range + If-Match family), mapped the HTTP response into the same
|
|
106
|
+
// { statusCode, body, etag, lastModified, contentRange, size, contentType }
|
|
107
|
+
// shape, and turned a 304 into the same short-circuit result. Only the Range
|
|
108
|
+
// header NAME differs (S3/GCS "Range" vs Azure "x-ms-range"), so it is a
|
|
109
|
+
// parameter; the rest is identical.
|
|
110
|
+
function applyConditionalGetHeaders(target, opts, rangeHeaderName) {
|
|
111
|
+
if (opts.range) {
|
|
112
|
+
target[rangeHeaderName] = "bytes=" + opts.range.start + "-" + opts.range.end;
|
|
113
|
+
}
|
|
114
|
+
if (opts.ifNoneMatch) target["If-None-Match"] = opts.ifNoneMatch;
|
|
115
|
+
if (opts.ifMatch) target["If-Match"] = opts.ifMatch;
|
|
116
|
+
if (opts.ifModifiedSince) target["If-Modified-Since"] = opts.ifModifiedSince;
|
|
117
|
+
if (opts.ifUnmodifiedSince) target["If-Unmodified-Since"] = opts.ifUnmodifiedSince;
|
|
118
|
+
return target;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function mapGetResponse(res) {
|
|
122
|
+
return {
|
|
123
|
+
statusCode: res.statusCode,
|
|
124
|
+
body: res.body,
|
|
125
|
+
etag: res.headers && res.headers.etag,
|
|
126
|
+
lastModified: res.headers && res.headers["last-modified"]
|
|
127
|
+
? Date.parse(res.headers["last-modified"]) : null,
|
|
128
|
+
contentRange: res.headers && res.headers["content-range"] || null,
|
|
129
|
+
size: res.headers && res.headers["content-length"]
|
|
130
|
+
? parseInt(res.headers["content-length"], 10) : null,
|
|
131
|
+
contentType: res.headers && res.headers["content-type"] || null,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// HEAD response projection — { size, etag, lastModified } from the response
|
|
136
|
+
// headers. Shared by the header-driven backends (azure / sigv4 / http-put);
|
|
137
|
+
// gcs.head is NOT a member (it reads a JSON metadata body, not headers).
|
|
138
|
+
function mapHeadResponse(res) {
|
|
139
|
+
return {
|
|
140
|
+
size: res.headers["content-length"] ? parseInt(res.headers["content-length"], 10) : null,
|
|
141
|
+
etag: res.headers.etag,
|
|
142
|
+
lastModified: res.headers["last-modified"] ? Date.parse(res.headers["last-modified"]) : null,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// The structured result a conditional GET returns when the server answers
|
|
147
|
+
// 304 Not Modified (httpClient surfaces it as a non-2xx error each backend
|
|
148
|
+
// catches and maps here).
|
|
149
|
+
function notModifiedGetResult() {
|
|
150
|
+
return {
|
|
151
|
+
statusCode: requestHelpers.HTTP_STATUS.NOT_MODIFIED,
|
|
152
|
+
body: null, etag: null, lastModified: null,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
38
156
|
module.exports = request;
|
|
157
|
+
module.exports.applyConditionalGetHeaders = applyConditionalGetHeaders;
|
|
158
|
+
module.exports.mapGetResponse = mapGetResponse;
|
|
159
|
+
module.exports.mapHeadResponse = mapHeadResponse;
|
|
160
|
+
module.exports.notModifiedGetResult = notModifiedGetResult;
|
|
161
|
+
module.exports.PRESIGN_DEFAULT_EXPIRES_SECONDS = PRESIGN_DEFAULT_EXPIRES_SECONDS;
|
|
162
|
+
module.exports.PRESIGN_MAX_EXPIRES_SECONDS = PRESIGN_MAX_EXPIRES_SECONDS;
|
|
163
|
+
module.exports.PRESIGN_MIN_EXPIRES_SECONDS = PRESIGN_MIN_EXPIRES_SECONDS;
|
|
164
|
+
module.exports.requirePresignKey = requirePresignKey;
|
|
165
|
+
module.exports.resolvePresignExpires = resolvePresignExpires;
|
|
166
|
+
module.exports.resolvePresignUploadMinBytes = resolvePresignUploadMinBytes;
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
* BUCKET_ALREADY_OWNED, BUCKET_NOT_EMPTY, etc.).
|
|
51
51
|
*/
|
|
52
52
|
var nodeCrypto = require("node:crypto");
|
|
53
|
+
var safeBuffer = require("../safe-buffer");
|
|
53
54
|
var C = require("../constants");
|
|
54
55
|
var requestHelpers = require("../request-helpers");
|
|
55
56
|
var sigv4 = require("./sigv4");
|
|
@@ -403,7 +404,7 @@ function _validateObjectKey(key) {
|
|
|
403
404
|
if (typeof key !== "string" || key.length === 0) {
|
|
404
405
|
throw _err("INVALID_KEY", "object key must be a non-empty string", true);
|
|
405
406
|
}
|
|
406
|
-
if (key
|
|
407
|
+
if (safeBuffer.byteLengthOf(key) > C.BYTES.kib(1)) {
|
|
407
408
|
throw _err("INVALID_KEY", "object key exceeds 1024 bytes (S3 limit)", true);
|
|
408
409
|
}
|
|
409
410
|
}
|
|
@@ -29,7 +29,6 @@ var { Readable } = require("node:stream");
|
|
|
29
29
|
var safeXml = require("../parsers/safe-xml");
|
|
30
30
|
var sharedRequest = require("./http-request");
|
|
31
31
|
var C = require("../constants");
|
|
32
|
-
var numericBounds = require("../numeric-bounds");
|
|
33
32
|
var requestHelpers = require("../request-helpers");
|
|
34
33
|
var { ObjectStoreError } = require("../framework-error");
|
|
35
34
|
var safeUrl = require("../safe-url");
|
|
@@ -66,12 +65,6 @@ function _arrayify(value) {
|
|
|
66
65
|
var SERVICE = "s3";
|
|
67
66
|
var ALGORITHM = "AWS4-HMAC-SHA256";
|
|
68
67
|
|
|
69
|
-
// Presigned-URL expiry bounds. The SigV4 spec caps query-string-signed
|
|
70
|
-
// URLs at 7 days; below 1 second is effectively unsignable.
|
|
71
|
-
var PRESIGN_DEFAULT_EXPIRES_SECONDS = C.TIME.minutes(15) / C.TIME.seconds(1); // 15 minutes
|
|
72
|
-
var PRESIGN_MAX_EXPIRES_SECONDS = C.TIME.days(7) / C.TIME.seconds(1); // 7 days (SigV4 hard cap)
|
|
73
|
-
var PRESIGN_MIN_EXPIRES_SECONDS = 1;
|
|
74
|
-
|
|
75
68
|
var _err = ObjectStoreError.factory;
|
|
76
69
|
|
|
77
70
|
// ---- SigV4 primitives ----
|
|
@@ -658,35 +651,16 @@ function create(config) {
|
|
|
658
651
|
// param is in the SigV4 canonical request.
|
|
659
652
|
if (opts.versionId) url.searchParams.set("versionId", opts.versionId);
|
|
660
653
|
var headers = _makeSigned("GET", url, sha256Hex(Buffer.alloc(0)));
|
|
661
|
-
|
|
662
|
-
headers["Range"] = "bytes=" + opts.range.start + "-" + opts.range.end;
|
|
663
|
-
}
|
|
664
|
-
if (opts.ifNoneMatch) headers["If-None-Match"] = opts.ifNoneMatch;
|
|
665
|
-
if (opts.ifMatch) headers["If-Match"] = opts.ifMatch;
|
|
666
|
-
if (opts.ifModifiedSince) headers["If-Modified-Since"] = opts.ifModifiedSince;
|
|
667
|
-
if (opts.ifUnmodifiedSince) headers["If-Unmodified-Since"] = opts.ifUnmodifiedSince;
|
|
654
|
+
sharedRequest.applyConditionalGetHeaders(headers, opts, "Range");
|
|
668
655
|
var localReqOpts = Object.assign({}, reqOpts, { _resolveOnRedirect: false });
|
|
669
656
|
return _request("GET", url, headers, null, localReqOpts).then(function (res) {
|
|
670
|
-
return
|
|
671
|
-
statusCode: res.statusCode,
|
|
672
|
-
body: res.body,
|
|
673
|
-
etag: res.headers && res.headers.etag,
|
|
674
|
-
lastModified: res.headers && res.headers["last-modified"]
|
|
675
|
-
? Date.parse(res.headers["last-modified"]) : null,
|
|
676
|
-
contentRange: res.headers && res.headers["content-range"] || null,
|
|
677
|
-
size: res.headers && res.headers["content-length"]
|
|
678
|
-
? parseInt(res.headers["content-length"], 10) : null,
|
|
679
|
-
contentType: res.headers && res.headers["content-type"] || null,
|
|
680
|
-
};
|
|
657
|
+
return sharedRequest.mapGetResponse(res);
|
|
681
658
|
}, function (err) {
|
|
682
659
|
// 304 surfaces as a "non-2xx error" via httpClient; propagate it
|
|
683
660
|
// as a structured 304 result instead so operator routes get
|
|
684
661
|
// the conditional-GET short-circuit they expect.
|
|
685
662
|
if (err && err.statusCode === requestHelpers.HTTP_STATUS.NOT_MODIFIED) {
|
|
686
|
-
return
|
|
687
|
-
statusCode: requestHelpers.HTTP_STATUS.NOT_MODIFIED,
|
|
688
|
-
body: null, etag: null, lastModified: null,
|
|
689
|
-
};
|
|
663
|
+
return sharedRequest.notModifiedGetResult();
|
|
690
664
|
}
|
|
691
665
|
throw err;
|
|
692
666
|
});
|
|
@@ -698,11 +672,7 @@ function create(config) {
|
|
|
698
672
|
if (opts.versionId) url.searchParams.set("versionId", opts.versionId);
|
|
699
673
|
var headers = _makeSigned("HEAD", url, sha256Hex(Buffer.alloc(0)));
|
|
700
674
|
return _request("HEAD", url, headers, null, reqOpts).then(function (res) {
|
|
701
|
-
return
|
|
702
|
-
size: res.headers["content-length"] ? parseInt(res.headers["content-length"], 10) : null,
|
|
703
|
-
etag: res.headers.etag,
|
|
704
|
-
lastModified: res.headers["last-modified"] ? Date.parse(res.headers["last-modified"]) : null,
|
|
705
|
-
};
|
|
675
|
+
return sharedRequest.mapHeadResponse(res);
|
|
706
676
|
}, function (e) {
|
|
707
677
|
// A missing key surfaces as the framework NOT_FOUND code — the same
|
|
708
678
|
// contract local.js head() exposes and that deleteKey already maps 404
|
|
@@ -758,21 +728,8 @@ function create(config) {
|
|
|
758
728
|
|
|
759
729
|
function _presign(method, opts) {
|
|
760
730
|
opts = opts || {};
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
}
|
|
764
|
-
if (opts.key.indexOf("\0") !== -1) {
|
|
765
|
-
throw _err("INVALID_KEY", "null byte in key", true);
|
|
766
|
-
}
|
|
767
|
-
var expiresIn = opts.expiresIn != null ? opts.expiresIn : PRESIGN_DEFAULT_EXPIRES_SECONDS;
|
|
768
|
-
if (typeof expiresIn !== "number" ||
|
|
769
|
-
expiresIn < PRESIGN_MIN_EXPIRES_SECONDS ||
|
|
770
|
-
expiresIn > PRESIGN_MAX_EXPIRES_SECONDS) {
|
|
771
|
-
throw _err("INVALID_EXPIRES",
|
|
772
|
-
"presigned URL: expiresIn must be a number of seconds between " +
|
|
773
|
-
PRESIGN_MIN_EXPIRES_SECONDS + " and " + PRESIGN_MAX_EXPIRES_SECONDS +
|
|
774
|
-
" (7 days, SigV4 hard cap)", true);
|
|
775
|
-
}
|
|
731
|
+
sharedRequest.requirePresignKey(opts, "presigned URL");
|
|
732
|
+
var expiresIn = sharedRequest.resolvePresignExpires(opts, "presigned URL", "SigV4");
|
|
776
733
|
|
|
777
734
|
// Validate opts.responseHeaders shape — operators pass camelCase
|
|
778
735
|
// keys; refuse unknown keys at config-time so a typo surfaces at
|
|
@@ -876,34 +833,9 @@ function create(config) {
|
|
|
876
833
|
// Reference: AWS S3 "Browser-Based Uploads Using POST".
|
|
877
834
|
function presignedUploadPolicy(opts) {
|
|
878
835
|
opts = opts || {};
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
if (opts.key.indexOf("\0") !== -1) {
|
|
883
|
-
throw _err("INVALID_KEY", "null byte in key", true);
|
|
884
|
-
}
|
|
885
|
-
if (typeof opts.maxBytes !== "number" || !Number.isFinite(opts.maxBytes) ||
|
|
886
|
-
opts.maxBytes <= 0) {
|
|
887
|
-
throw _err("INVALID_MAX_BYTES",
|
|
888
|
-
"presignedUploadPolicy: maxBytes (positive number of bytes) is required — " +
|
|
889
|
-
"POST-form policy enforces body size via the content-length-range condition; " +
|
|
890
|
-
"use presignedUploadUrl if size enforcement is not needed", true);
|
|
891
|
-
}
|
|
892
|
-
if (opts.minBytes !== undefined && !numericBounds.isNonNegativeFiniteInt(opts.minBytes)) {
|
|
893
|
-
throw _err("INVALID_MIN_BYTES",
|
|
894
|
-
"presignedUploadPolicy: minBytes must be a non-negative finite integer; got " +
|
|
895
|
-
numericBounds.shape(opts.minBytes), true);
|
|
896
|
-
}
|
|
897
|
-
var minBytes = opts.minBytes !== undefined ? opts.minBytes : 0;
|
|
898
|
-
var expiresIn = opts.expiresIn != null ? opts.expiresIn : PRESIGN_DEFAULT_EXPIRES_SECONDS;
|
|
899
|
-
if (typeof expiresIn !== "number" ||
|
|
900
|
-
expiresIn < PRESIGN_MIN_EXPIRES_SECONDS ||
|
|
901
|
-
expiresIn > PRESIGN_MAX_EXPIRES_SECONDS) {
|
|
902
|
-
throw _err("INVALID_EXPIRES",
|
|
903
|
-
"presignedUploadPolicy: expiresIn must be a number of seconds between " +
|
|
904
|
-
PRESIGN_MIN_EXPIRES_SECONDS + " and " + PRESIGN_MAX_EXPIRES_SECONDS +
|
|
905
|
-
" (7 days, SigV4 hard cap)", true);
|
|
906
|
-
}
|
|
836
|
+
sharedRequest.requirePresignKey(opts, "presignedUploadPolicy");
|
|
837
|
+
var minBytes = sharedRequest.resolvePresignUploadMinBytes(opts);
|
|
838
|
+
var expiresIn = sharedRequest.resolvePresignExpires(opts, "presignedUploadPolicy", "SigV4");
|
|
907
839
|
|
|
908
840
|
var date = opts.date || new Date();
|
|
909
841
|
var amzDate = _formatAmzDate(date);
|
|
@@ -37,6 +37,7 @@ var safeBuffer = require("./safe-buffer");
|
|
|
37
37
|
var validateOpts = require("./validate-opts");
|
|
38
38
|
var safeUrl = require("./safe-url");
|
|
39
39
|
var pb = require("./protobuf-encoder");
|
|
40
|
+
var boundedMap = require("./bounded-map");
|
|
40
41
|
var { defineClass } = require("./framework-error");
|
|
41
42
|
|
|
42
43
|
var OtlpExporterError = defineClass("OtlpExporterError", { alwaysPermanent: true });
|
|
@@ -167,15 +168,13 @@ function _bundleSpans(spans) {
|
|
|
167
168
|
for (var i = 0; i < spans.length; i++) {
|
|
168
169
|
var s = spans[i];
|
|
169
170
|
var resKey = JSON.stringify(s.resource || {});
|
|
170
|
-
var bucket =
|
|
171
|
-
|
|
172
|
-
bucket = {
|
|
171
|
+
var bucket = boundedMap.getOrInsert(byResource, resKey, function () {
|
|
172
|
+
return {
|
|
173
173
|
resource: s.resource || {},
|
|
174
174
|
scope: s.scope || { name: "blamejs", version: null },
|
|
175
175
|
spans: [],
|
|
176
176
|
};
|
|
177
|
-
|
|
178
|
-
}
|
|
177
|
+
});
|
|
179
178
|
bucket.spans.push(s);
|
|
180
179
|
}
|
|
181
180
|
var resourceSpans = [];
|
|
@@ -380,15 +379,13 @@ function _bundleSpansToProto(spansArray) {
|
|
|
380
379
|
for (var i = 0; i < spansArray.length; i += 1) {
|
|
381
380
|
var s = spansArray[i];
|
|
382
381
|
var resKey = JSON.stringify(s.resource || {});
|
|
383
|
-
var bucket =
|
|
384
|
-
|
|
385
|
-
bucket = {
|
|
382
|
+
var bucket = boundedMap.getOrInsert(byResource, resKey, function () {
|
|
383
|
+
return {
|
|
386
384
|
resource: s.resource || {},
|
|
387
385
|
scope: s.scope || { name: "blamejs", version: null },
|
|
388
386
|
spans: [],
|
|
389
387
|
};
|
|
390
|
-
|
|
391
|
-
}
|
|
388
|
+
});
|
|
392
389
|
bucket.spans.push(s);
|
|
393
390
|
}
|
|
394
391
|
var resourceSpansPieces = [];
|
|
@@ -493,21 +490,8 @@ function create(opts) {
|
|
|
493
490
|
var inFlight = false;
|
|
494
491
|
var stopping = false;
|
|
495
492
|
|
|
496
|
-
var
|
|
497
|
-
|
|
498
|
-
try { observability().safeEvent("otlp.exporter." + verb, n || 1, labels || {}); }
|
|
499
|
-
catch (_e) { /* drop-silent */ }
|
|
500
|
-
}
|
|
501
|
-
function _emitAudit(action, outcome, metadata) {
|
|
502
|
-
if (!auditOn) return;
|
|
503
|
-
try {
|
|
504
|
-
audit().safeEmit({
|
|
505
|
-
action: "system.observability.otlp_exporter." + action,
|
|
506
|
-
outcome: outcome,
|
|
507
|
-
metadata: metadata || {},
|
|
508
|
-
});
|
|
509
|
-
} catch (_e) { /* drop-silent — audit is best-effort, never crashes the exporter */ }
|
|
510
|
-
}
|
|
493
|
+
var _emitMetric = observability().namespaced("otlp.exporter");
|
|
494
|
+
var _emitAudit = audit().namespaced("system.observability.otlp_exporter", opts.audit);
|
|
511
495
|
|
|
512
496
|
function queue_(span) {
|
|
513
497
|
if (stopping) { droppedExportFailed += 1; return; }
|
|
@@ -343,6 +343,98 @@ function safeEvent(name, value, labels) {
|
|
|
343
343
|
catch (_e) { /* hot-path observability sink — drops silent on internal throws */ }
|
|
344
344
|
}
|
|
345
345
|
|
|
346
|
+
/**
|
|
347
|
+
* @primitive b.observability.safeEmit
|
|
348
|
+
* @signature b.observability.safeEmit(sink, name, value, labels)
|
|
349
|
+
* @since 0.15.13
|
|
350
|
+
* @related b.observability.safeEvent, b.observability.event
|
|
351
|
+
*
|
|
352
|
+
* The sink-aware sibling of `safeEvent`: emit a metric event to an
|
|
353
|
+
* explicitly-configured observability `sink` (a per-instance
|
|
354
|
+
* observability object) when one is supplied, otherwise fall back to
|
|
355
|
+
* the global registry — each path wrapped in a try/catch so a
|
|
356
|
+
* misconfigured counter never crashes the request that triggered it.
|
|
357
|
+
* Replaces the `_emitObs` + `_safeGlobalObs` helper pair that the auth
|
|
358
|
+
* brute-force modules (bot-challenge / lockout / session-device-binding)
|
|
359
|
+
* each duplicated to route a configured observability instance with a
|
|
360
|
+
* global fallback.
|
|
361
|
+
*
|
|
362
|
+
* @example
|
|
363
|
+
* b.observability.safeEmit(opts.observability, "auth.lockout.hit", 1,
|
|
364
|
+
* { namespace: ns });
|
|
365
|
+
*/
|
|
366
|
+
function safeEmit(sink, name, value, labels) {
|
|
367
|
+
if (sink) {
|
|
368
|
+
try { sink.event(name, value, labels); }
|
|
369
|
+
catch (_e) { /* per-instance observability sink — drops silent */ }
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
safeEvent(name, value, labels);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* @primitive b.observability.makeCounterEmitter
|
|
377
|
+
* @signature b.observability.makeCounterEmitter(sink)
|
|
378
|
+
* @since 0.15.13
|
|
379
|
+
* @status stable
|
|
380
|
+
* @related b.observability.safeEmit, b.observability.namespaced
|
|
381
|
+
*
|
|
382
|
+
* Bind a per-instance counter emitter. Returns `(name, labels)` that
|
|
383
|
+
* increments metric `name` by 1 (with `labels`) on the supplied
|
|
384
|
+
* observability `sink`, drop-silent on a sink throw and falling back to
|
|
385
|
+
* the global tap when `sink` is null. The shorthand every primitive that
|
|
386
|
+
* accepts an `observability` instance wrapped in a private
|
|
387
|
+
* `_emitObs(name, labels)` closure around
|
|
388
|
+
* `safeEmit(obsInst, name, 1, labels)` — build it once with the instance
|
|
389
|
+
* and call the returned emitter.
|
|
390
|
+
*
|
|
391
|
+
* @example
|
|
392
|
+
* var b = require("blamejs");
|
|
393
|
+
* var emit = b.observability.makeCounterEmitter(myObsInstance);
|
|
394
|
+
* emit("auth.lockout.tripped", { actor: "alice" });
|
|
395
|
+
*/
|
|
396
|
+
function makeCounterEmitter(sink) {
|
|
397
|
+
return function (name, labels) {
|
|
398
|
+
safeEmit(sink, name, 1, labels);
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* @primitive b.observability.namespaced
|
|
404
|
+
* @signature b.observability.namespaced(prefix, gateFlag?)
|
|
405
|
+
* @since 0.15.13
|
|
406
|
+
* @status stable
|
|
407
|
+
* @related b.observability.safeEvent, b.observability.event, b.audit.namespaced
|
|
408
|
+
*
|
|
409
|
+
* Build a drop-silent metric emitter bound to one name prefix — the shape every
|
|
410
|
+
* primitive hand-rolled as a private `_emitMetric(verb, n, labels)` closure
|
|
411
|
+
* (`try { observability().safeEvent("ns." + verb, n || 1, labels || {}); }
|
|
412
|
+
* catch {}`). The returned function prefixes `verb` with `prefix + "."`,
|
|
413
|
+
* defaults the value to `1` and labels to `{}`, and routes through `safeEvent`
|
|
414
|
+
* so a misconfigured counter / label name cannot crash the caller. The metric
|
|
415
|
+
* sibling of `b.audit.namespaced`. Metrics emit unconditionally by default;
|
|
416
|
+
* pass `gateFlag === false` to disable a primitive's own metrics in lockstep
|
|
417
|
+
* with its audit (the few primitives that gate both behind one `opts.audit`).
|
|
418
|
+
*
|
|
419
|
+
* @example
|
|
420
|
+
* var emitMetric = b.observability.namespaced("network.byte_quota");
|
|
421
|
+
* emitMetric("exceeded", 1, { key: k });
|
|
422
|
+
* // → safeEvent("network.byte_quota.exceeded", 1, { key: k })
|
|
423
|
+
* emitMetric("reset");
|
|
424
|
+
* // → safeEvent("network.byte_quota.reset", 1, {})
|
|
425
|
+
*/
|
|
426
|
+
function namespaced(prefix, gateFlag) {
|
|
427
|
+
var on = gateFlag !== false;
|
|
428
|
+
return function (verb, n, labels) {
|
|
429
|
+
if (!on) return;
|
|
430
|
+
// module.exports.safeEvent (late-bound) so a test that stubs
|
|
431
|
+
// b.observability.safeEvent still observes the emit — the closures this
|
|
432
|
+
// replaces all called `observability().safeEvent(...)`.
|
|
433
|
+
try { module.exports.safeEvent(prefix + "." + verb, n || 1, labels || {}); }
|
|
434
|
+
catch (_e) { /* drop-silent — observability sink */ }
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
|
|
346
438
|
// timed — convenience wrapper that measures wall-clock duration of a
|
|
347
439
|
// sync or async operation and emits a counter event with
|
|
348
440
|
// duration_ms in the labels. Returns the wrapped function's return
|
|
@@ -870,6 +962,9 @@ module.exports = {
|
|
|
870
962
|
tap: tap,
|
|
871
963
|
event: event,
|
|
872
964
|
safeEvent: safeEvent,
|
|
965
|
+
safeEmit: safeEmit,
|
|
966
|
+
makeCounterEmitter: makeCounterEmitter,
|
|
967
|
+
namespaced: namespaced,
|
|
873
968
|
timed: timed,
|
|
874
969
|
setTap: setTap,
|
|
875
970
|
setRedactor: setRedactor,
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
|
|
26
26
|
var validateOpts = require("./validate-opts");
|
|
27
27
|
var schemaWalk = require("./openapi-schema-walk");
|
|
28
|
+
var pick = require("./pick");
|
|
28
29
|
var { defineClass } = require("./framework-error");
|
|
29
30
|
var OpenApiError = defineClass("OpenApiError", { alwaysPermanent: true });
|
|
30
31
|
|
|
@@ -44,7 +45,10 @@ function _extractPathParams(pathTemplate) {
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
function PathsBuilder() {
|
|
47
|
-
|
|
48
|
+
// null-proto so a urlPattern keyed into _paths (operator-supplied API path)
|
|
49
|
+
// can never reach Object.prototype — a "__proto__" / "constructor" path lands
|
|
50
|
+
// as an own property, not a prototype mutation (prototype-polluting-assignment).
|
|
51
|
+
this._paths = Object.create(null);
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
// _buildOperation — normalise a single Operation Object from operator
|
|
@@ -133,7 +137,7 @@ PathsBuilder.prototype.add = function (method, urlPattern, opts) {
|
|
|
133
137
|
}
|
|
134
138
|
}
|
|
135
139
|
|
|
136
|
-
if (!this._paths[urlPattern]) this._paths[urlPattern] =
|
|
140
|
+
if (!this._paths[urlPattern]) this._paths[urlPattern] = Object.create(null);
|
|
137
141
|
if (this._paths[urlPattern][method.toLowerCase()]) {
|
|
138
142
|
throw new OpenApiError("openapi/duplicate-operation",
|
|
139
143
|
"paths.add: duplicate operation " + method.toUpperCase() + " " + urlPattern);
|
|
@@ -279,7 +283,7 @@ WebhooksBuilder.prototype.add = function (name, method, opts) {
|
|
|
279
283
|
opts = opts || {};
|
|
280
284
|
validateOpts.requireNonEmptyString(name, "webhook.add: name",
|
|
281
285
|
OpenApiError, "openapi/bad-webhook");
|
|
282
|
-
if (name
|
|
286
|
+
if (pick.isPoisonedKey(name)) {
|
|
283
287
|
throw new OpenApiError("openapi/bad-webhook",
|
|
284
288
|
"webhook.add: name must not be a reserved object key (" + JSON.stringify(name) + ")");
|
|
285
289
|
}
|