@blamejs/blamejs-shop 0.4.55 → 0.4.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/lib/admin.js +385 -2
- package/lib/asset-manifest.json +1 -1
- package/lib/vendor/MANIFEST.json +426 -366
- package/lib/vendor/blamejs/.github/codeql/codeql-config.yml +25 -0
- package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +1 -1
- package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +1 -1
- package/lib/vendor/blamejs/.github/workflows/ci.yml +13 -13
- package/lib/vendor/blamejs/.github/workflows/codeql.yml +8 -7
- package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +2 -2
- package/lib/vendor/blamejs/.github/workflows/release-container.yml +4 -4
- package/lib/vendor/blamejs/.github/workflows/scorecard.yml +1 -1
- package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
- package/lib/vendor/blamejs/CHANGELOG.md +2 -0
- package/lib/vendor/blamejs/api-snapshot.json +1381 -4
- package/lib/vendor/blamejs/eslint.config.mjs +1 -0
- package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +4 -1
- package/lib/vendor/blamejs/examples/wiki/lib/symbol-index.js +5 -2
- package/lib/vendor/blamejs/examples/wiki/routes/pages.js +4 -1
- package/lib/vendor/blamejs/fuzz/guard-text.fuzz.js +20 -0
- package/lib/vendor/blamejs/index.js +2 -0
- package/lib/vendor/blamejs/lib/a2a-tasks.js +7 -23
- package/lib/vendor/blamejs/lib/acme.js +6 -5
- package/lib/vendor/blamejs/lib/agent-event-bus.js +5 -4
- package/lib/vendor/blamejs/lib/agent-idempotency.js +2 -5
- package/lib/vendor/blamejs/lib/agent-orchestrator.js +2 -5
- package/lib/vendor/blamejs/lib/agent-saga.js +3 -5
- package/lib/vendor/blamejs/lib/agent-tenant.js +2 -5
- package/lib/vendor/blamejs/lib/ai-adverse-decision.js +2 -15
- package/lib/vendor/blamejs/lib/ai-capability.js +1 -6
- package/lib/vendor/blamejs/lib/ai-dp.js +1 -5
- package/lib/vendor/blamejs/lib/ai-input.js +2 -2
- package/lib/vendor/blamejs/lib/ai-pref.js +3 -8
- package/lib/vendor/blamejs/lib/ai-quota.js +3 -14
- package/lib/vendor/blamejs/lib/api-key.js +37 -28
- package/lib/vendor/blamejs/lib/archive-adapters.js +2 -4
- package/lib/vendor/blamejs/lib/archive-entry-policy.js +32 -0
- package/lib/vendor/blamejs/lib/archive-read.js +5 -17
- package/lib/vendor/blamejs/lib/archive-tar-read.js +5 -16
- package/lib/vendor/blamejs/lib/archive.js +2 -10
- package/lib/vendor/blamejs/lib/arg-parser.js +7 -6
- package/lib/vendor/blamejs/lib/asyncapi-traits.js +2 -6
- package/lib/vendor/blamejs/lib/atomic-file.js +108 -31
- package/lib/vendor/blamejs/lib/audit-chain.js +133 -53
- package/lib/vendor/blamejs/lib/audit-daily-review.js +24 -14
- package/lib/vendor/blamejs/lib/audit-emit.js +82 -0
- package/lib/vendor/blamejs/lib/audit-sign.js +257 -0
- package/lib/vendor/blamejs/lib/audit.js +84 -0
- package/lib/vendor/blamejs/lib/auth/access-lock.js +5 -27
- package/lib/vendor/blamejs/lib/auth/dpop.js +23 -35
- package/lib/vendor/blamejs/lib/auth/fido-mds3.js +9 -15
- package/lib/vendor/blamejs/lib/auth/jwt-external.js +26 -8
- package/lib/vendor/blamejs/lib/auth/jwt.js +13 -15
- package/lib/vendor/blamejs/lib/auth/lockout.js +6 -25
- package/lib/vendor/blamejs/lib/auth/oauth.js +67 -45
- package/lib/vendor/blamejs/lib/auth/oid4vci.js +55 -32
- package/lib/vendor/blamejs/lib/auth/oid4vp.js +3 -2
- package/lib/vendor/blamejs/lib/auth/openid-federation.js +6 -6
- package/lib/vendor/blamejs/lib/auth/passkey.js +3 -3
- package/lib/vendor/blamejs/lib/auth/password.js +7 -1
- package/lib/vendor/blamejs/lib/auth/saml.js +37 -27
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-holder.js +2 -14
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-issuer.js +2 -14
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +1 -1
- package/lib/vendor/blamejs/lib/auth/status-list.js +7 -7
- package/lib/vendor/blamejs/lib/auth/step-up.js +6 -12
- package/lib/vendor/blamejs/lib/auth-bot-challenge.js +6 -37
- package/lib/vendor/blamejs/lib/backup/bundle.js +11 -18
- package/lib/vendor/blamejs/lib/backup/index.js +14 -47
- package/lib/vendor/blamejs/lib/bounded-map.js +112 -1
- package/lib/vendor/blamejs/lib/breach-deadline.js +1 -11
- package/lib/vendor/blamejs/lib/cache.js +7 -18
- package/lib/vendor/blamejs/lib/cbor.js +2 -1
- package/lib/vendor/blamejs/lib/cdn-cache-control.js +8 -9
- package/lib/vendor/blamejs/lib/cert.js +3 -10
- package/lib/vendor/blamejs/lib/chain-writer.js +162 -47
- package/lib/vendor/blamejs/lib/cli.js +5 -1
- package/lib/vendor/blamejs/lib/client-hints.js +7 -9
- package/lib/vendor/blamejs/lib/cloud-events.js +40 -31
- package/lib/vendor/blamejs/lib/cluster-storage.js +2 -38
- package/lib/vendor/blamejs/lib/cms-codec.js +2 -1
- package/lib/vendor/blamejs/lib/codepoint-class.js +67 -1
- package/lib/vendor/blamejs/lib/compliance-ai-act-logging.js +1 -6
- package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +2 -4
- package/lib/vendor/blamejs/lib/compliance-eaa.js +1 -11
- package/lib/vendor/blamejs/lib/compliance-sanctions-fetcher.js +21 -28
- package/lib/vendor/blamejs/lib/compliance-sanctions.js +2 -14
- package/lib/vendor/blamejs/lib/compliance.js +2 -9
- package/lib/vendor/blamejs/lib/config-drift.js +2 -12
- package/lib/vendor/blamejs/lib/content-digest.js +10 -8
- package/lib/vendor/blamejs/lib/cookies.js +5 -11
- package/lib/vendor/blamejs/lib/cose.js +19 -11
- package/lib/vendor/blamejs/lib/cra-report.js +1 -11
- package/lib/vendor/blamejs/lib/crypto-field.js +5 -10
- package/lib/vendor/blamejs/lib/crypto.js +120 -3
- package/lib/vendor/blamejs/lib/csp.js +235 -3
- package/lib/vendor/blamejs/lib/daemon.js +42 -41
- package/lib/vendor/blamejs/lib/data-act.js +19 -9
- package/lib/vendor/blamejs/lib/db-query.js +6 -40
- package/lib/vendor/blamejs/lib/db.js +34 -12
- package/lib/vendor/blamejs/lib/dbsc.js +5 -6
- package/lib/vendor/blamejs/lib/ddl-change-control.js +18 -14
- package/lib/vendor/blamejs/lib/deprecate.js +4 -5
- package/lib/vendor/blamejs/lib/did.js +6 -2
- package/lib/vendor/blamejs/lib/dsr.js +8 -12
- package/lib/vendor/blamejs/lib/external-db-migrate.js +21 -22
- package/lib/vendor/blamejs/lib/external-db.js +14 -26
- package/lib/vendor/blamejs/lib/fda-21cfr11.js +12 -8
- package/lib/vendor/blamejs/lib/fdx.js +22 -18
- package/lib/vendor/blamejs/lib/file-upload.js +80 -66
- package/lib/vendor/blamejs/lib/flag-evaluation-context.js +5 -8
- package/lib/vendor/blamejs/lib/framework-error.js +12 -0
- package/lib/vendor/blamejs/lib/framework-schema.js +19 -0
- package/lib/vendor/blamejs/lib/fsm.js +7 -12
- package/lib/vendor/blamejs/lib/gate-contract.js +869 -38
- package/lib/vendor/blamejs/lib/gdpr-ropa.js +4 -13
- package/lib/vendor/blamejs/lib/graphql-federation.js +1 -1
- package/lib/vendor/blamejs/lib/guard-agent-registry.js +2 -1
- package/lib/vendor/blamejs/lib/guard-all.js +1 -0
- package/lib/vendor/blamejs/lib/guard-archive.js +9 -30
- package/lib/vendor/blamejs/lib/guard-auth.js +23 -80
- package/lib/vendor/blamejs/lib/guard-cidr.js +20 -96
- package/lib/vendor/blamejs/lib/guard-csv.js +135 -196
- package/lib/vendor/blamejs/lib/guard-domain.js +23 -106
- package/lib/vendor/blamejs/lib/guard-dsn.js +16 -13
- package/lib/vendor/blamejs/lib/guard-email.js +46 -53
- package/lib/vendor/blamejs/lib/guard-envelope.js +1 -1
- package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +2 -1
- package/lib/vendor/blamejs/lib/guard-filename.js +12 -60
- package/lib/vendor/blamejs/lib/guard-graphql.js +28 -75
- package/lib/vendor/blamejs/lib/guard-html-wcag.js +15 -2
- package/lib/vendor/blamejs/lib/guard-html.js +65 -117
- package/lib/vendor/blamejs/lib/guard-idempotency-key.js +2 -1
- package/lib/vendor/blamejs/lib/guard-image.js +280 -77
- package/lib/vendor/blamejs/lib/guard-imap-command.js +8 -9
- package/lib/vendor/blamejs/lib/guard-json.js +87 -103
- package/lib/vendor/blamejs/lib/guard-jsonpath.js +20 -88
- package/lib/vendor/blamejs/lib/guard-jwt.js +32 -114
- package/lib/vendor/blamejs/lib/guard-list-id.js +2 -7
- package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -7
- package/lib/vendor/blamejs/lib/guard-mail-compose.js +5 -6
- package/lib/vendor/blamejs/lib/guard-mail-move.js +2 -1
- package/lib/vendor/blamejs/lib/guard-mail-query.js +5 -3
- package/lib/vendor/blamejs/lib/guard-mail-sieve.js +6 -7
- package/lib/vendor/blamejs/lib/guard-managesieve-command.js +5 -4
- package/lib/vendor/blamejs/lib/guard-markdown.js +76 -110
- package/lib/vendor/blamejs/lib/guard-message-id.js +5 -6
- package/lib/vendor/blamejs/lib/guard-mime.js +20 -99
- package/lib/vendor/blamejs/lib/guard-oauth.js +19 -73
- package/lib/vendor/blamejs/lib/guard-pdf.js +65 -72
- package/lib/vendor/blamejs/lib/guard-pop3-command.js +12 -13
- package/lib/vendor/blamejs/lib/guard-posture-chain.js +2 -1
- package/lib/vendor/blamejs/lib/guard-regex.js +24 -99
- package/lib/vendor/blamejs/lib/guard-saga-config.js +2 -1
- package/lib/vendor/blamejs/lib/guard-shell.js +22 -87
- package/lib/vendor/blamejs/lib/guard-smtp-command.js +8 -11
- package/lib/vendor/blamejs/lib/guard-sql.js +15 -13
- package/lib/vendor/blamejs/lib/guard-stream-args.js +2 -1
- package/lib/vendor/blamejs/lib/guard-svg.js +95 -140
- package/lib/vendor/blamejs/lib/guard-template.js +23 -80
- package/lib/vendor/blamejs/lib/guard-tenant-id.js +2 -1
- package/lib/vendor/blamejs/lib/guard-text.js +592 -0
- package/lib/vendor/blamejs/lib/guard-time.js +27 -95
- package/lib/vendor/blamejs/lib/guard-uuid.js +21 -93
- package/lib/vendor/blamejs/lib/guard-xml.js +76 -106
- package/lib/vendor/blamejs/lib/guard-yaml.js +24 -60
- package/lib/vendor/blamejs/lib/http-client-cache.js +5 -12
- package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +2 -4
- package/lib/vendor/blamejs/lib/http-client.js +8 -21
- package/lib/vendor/blamejs/lib/http-message-signature.js +3 -2
- package/lib/vendor/blamejs/lib/i18n-messageformat.js +5 -7
- package/lib/vendor/blamejs/lib/i18n.js +83 -26
- package/lib/vendor/blamejs/lib/inbox.js +8 -8
- package/lib/vendor/blamejs/lib/incident-report.js +3 -21
- package/lib/vendor/blamejs/lib/ip-utils.js +49 -6
- package/lib/vendor/blamejs/lib/jobs.js +3 -2
- package/lib/vendor/blamejs/lib/keychain.js +6 -18
- package/lib/vendor/blamejs/lib/legal-hold.js +6 -15
- package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +44 -112
- package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +17 -14
- package/lib/vendor/blamejs/lib/log-stream-otlp.js +16 -80
- package/lib/vendor/blamejs/lib/log-stream-webhook.js +20 -92
- package/lib/vendor/blamejs/lib/mail-arc-sign.js +8 -3
- package/lib/vendor/blamejs/lib/mail-arf.js +3 -2
- package/lib/vendor/blamejs/lib/mail-auth.js +40 -66
- package/lib/vendor/blamejs/lib/mail-bimi.js +19 -39
- package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +3 -2
- package/lib/vendor/blamejs/lib/mail-dav.js +8 -35
- package/lib/vendor/blamejs/lib/mail-deploy.js +6 -9
- package/lib/vendor/blamejs/lib/mail-dkim.js +19 -38
- package/lib/vendor/blamejs/lib/mail-greylist.js +15 -26
- package/lib/vendor/blamejs/lib/mail-helo.js +2 -3
- package/lib/vendor/blamejs/lib/mail-journal.js +2 -1
- package/lib/vendor/blamejs/lib/mail-mdn.js +4 -3
- package/lib/vendor/blamejs/lib/mail-rbl.js +5 -8
- package/lib/vendor/blamejs/lib/mail-scan.js +2 -2
- package/lib/vendor/blamejs/lib/mail-send-deliver.js +33 -20
- package/lib/vendor/blamejs/lib/mail-server-imap.js +32 -87
- package/lib/vendor/blamejs/lib/mail-server-jmap.js +35 -51
- package/lib/vendor/blamejs/lib/mail-server-managesieve.js +29 -83
- package/lib/vendor/blamejs/lib/mail-server-mx.js +33 -74
- package/lib/vendor/blamejs/lib/mail-server-net.js +177 -0
- package/lib/vendor/blamejs/lib/mail-server-pop3.js +30 -83
- package/lib/vendor/blamejs/lib/mail-server-rate-limit.js +30 -6
- package/lib/vendor/blamejs/lib/mail-server-submission.js +34 -73
- package/lib/vendor/blamejs/lib/mail-server-tls.js +89 -0
- package/lib/vendor/blamejs/lib/mail-spam-score.js +7 -8
- package/lib/vendor/blamejs/lib/mail-store.js +3 -2
- package/lib/vendor/blamejs/lib/mail.js +6 -11
- package/lib/vendor/blamejs/lib/markup-escape.js +31 -0
- package/lib/vendor/blamejs/lib/markup-tokenizer.js +54 -0
- package/lib/vendor/blamejs/lib/mcp-tool-registry.js +26 -23
- package/lib/vendor/blamejs/lib/mcp.js +1 -1
- package/lib/vendor/blamejs/lib/mdoc.js +11 -12
- package/lib/vendor/blamejs/lib/metrics.js +32 -30
- package/lib/vendor/blamejs/lib/middleware/age-gate.js +3 -23
- package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +11 -22
- package/lib/vendor/blamejs/lib/middleware/assetlinks.js +2 -7
- package/lib/vendor/blamejs/lib/middleware/bearer-auth.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/body-parser.js +31 -48
- package/lib/vendor/blamejs/lib/middleware/bot-disclose.js +7 -10
- package/lib/vendor/blamejs/lib/middleware/bot-guard.js +2 -10
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +13 -2
- package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +6 -26
- package/lib/vendor/blamejs/lib/middleware/deny-response.js +19 -1
- package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +7 -0
- package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +4 -20
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +20 -28
- package/lib/vendor/blamejs/lib/middleware/scim-server.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/security-headers.js +9 -1
- package/lib/vendor/blamejs/lib/middleware/security-txt.js +2 -6
- package/lib/vendor/blamejs/lib/middleware/tus-upload.js +12 -27
- package/lib/vendor/blamejs/lib/middleware/web-app-manifest.js +2 -7
- package/lib/vendor/blamejs/lib/migrations.js +4 -13
- package/lib/vendor/blamejs/lib/mime-parse.js +34 -17
- package/lib/vendor/blamejs/lib/module-loader.js +44 -0
- package/lib/vendor/blamejs/lib/money.js +105 -0
- package/lib/vendor/blamejs/lib/mtls-ca.js +116 -36
- package/lib/vendor/blamejs/lib/network-byte-quota.js +4 -18
- package/lib/vendor/blamejs/lib/network-dane.js +8 -6
- package/lib/vendor/blamejs/lib/network-dns-resolver.js +97 -6
- package/lib/vendor/blamejs/lib/network-dnssec.js +16 -16
- package/lib/vendor/blamejs/lib/network-heartbeat.js +3 -2
- package/lib/vendor/blamejs/lib/network-smtp-policy.js +29 -41
- package/lib/vendor/blamejs/lib/network-tls.js +40 -42
- package/lib/vendor/blamejs/lib/nis2-report.js +1 -11
- package/lib/vendor/blamejs/lib/nonce-store.js +81 -3
- package/lib/vendor/blamejs/lib/numeric-bounds.js +22 -8
- package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +2 -6
- package/lib/vendor/blamejs/lib/object-store/azure-blob.js +5 -45
- package/lib/vendor/blamejs/lib/object-store/gcs.js +8 -71
- package/lib/vendor/blamejs/lib/object-store/http-put.js +1 -5
- package/lib/vendor/blamejs/lib/object-store/http-request.js +128 -0
- package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +2 -1
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +9 -77
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +9 -25
- package/lib/vendor/blamejs/lib/observability.js +95 -0
- package/lib/vendor/blamejs/lib/openapi-paths-builder.js +7 -3
- package/lib/vendor/blamejs/lib/otel-export.js +7 -10
- package/lib/vendor/blamejs/lib/outbox.js +43 -37
- package/lib/vendor/blamejs/lib/pagination.js +11 -15
- package/lib/vendor/blamejs/lib/parsers/safe-env.js +5 -4
- package/lib/vendor/blamejs/lib/parsers/safe-ini.js +10 -4
- package/lib/vendor/blamejs/lib/parsers/safe-toml.js +11 -9
- package/lib/vendor/blamejs/lib/parsers/safe-xml.js +2 -2
- package/lib/vendor/blamejs/lib/parsers/safe-yaml.js +7 -6
- package/lib/vendor/blamejs/lib/pick.js +63 -5
- package/lib/vendor/blamejs/lib/pipl-cn.js +69 -59
- package/lib/vendor/blamejs/lib/privacy-pass.js +8 -6
- package/lib/vendor/blamejs/lib/problem-details.js +2 -5
- package/lib/vendor/blamejs/lib/pubsub.js +4 -8
- package/lib/vendor/blamejs/lib/redact.js +2 -1
- package/lib/vendor/blamejs/lib/render.js +4 -2
- package/lib/vendor/blamejs/lib/request-helpers.js +133 -6
- package/lib/vendor/blamejs/lib/restore.js +5 -22
- package/lib/vendor/blamejs/lib/retention.js +3 -5
- package/lib/vendor/blamejs/lib/safe-async.js +457 -0
- package/lib/vendor/blamejs/lib/safe-buffer.js +137 -6
- package/lib/vendor/blamejs/lib/safe-decompress.js +2 -1
- package/lib/vendor/blamejs/lib/safe-dns.js +2 -1
- package/lib/vendor/blamejs/lib/safe-ical.js +12 -26
- package/lib/vendor/blamejs/lib/safe-json.js +7 -8
- package/lib/vendor/blamejs/lib/safe-jsonpath.js +6 -5
- package/lib/vendor/blamejs/lib/safe-mime.js +25 -29
- package/lib/vendor/blamejs/lib/safe-redirect.js +2 -5
- package/lib/vendor/blamejs/lib/safe-schema.js +7 -6
- package/lib/vendor/blamejs/lib/safe-sql.js +126 -0
- package/lib/vendor/blamejs/lib/safe-vcard.js +12 -26
- package/lib/vendor/blamejs/lib/sandbox-worker.js +9 -2
- package/lib/vendor/blamejs/lib/sandbox.js +3 -2
- package/lib/vendor/blamejs/lib/scheduler.js +5 -12
- package/lib/vendor/blamejs/lib/sec-cyber.js +82 -37
- package/lib/vendor/blamejs/lib/seeders.js +4 -11
- package/lib/vendor/blamejs/lib/self-update.js +92 -69
- package/lib/vendor/blamejs/lib/session-device-binding.js +112 -66
- package/lib/vendor/blamejs/lib/session.js +194 -6
- package/lib/vendor/blamejs/lib/sql.js +225 -78
- package/lib/vendor/blamejs/lib/sse.js +6 -10
- package/lib/vendor/blamejs/lib/static.js +136 -98
- package/lib/vendor/blamejs/lib/storage.js +4 -2
- package/lib/vendor/blamejs/lib/structured-fields.js +275 -16
- package/lib/vendor/blamejs/lib/tenant-quota.js +2 -20
- package/lib/vendor/blamejs/lib/tsa.js +11 -15
- package/lib/vendor/blamejs/lib/validate-opts.js +154 -8
- package/lib/vendor/blamejs/lib/vault/seal-pem-file.js +30 -48
- package/lib/vendor/blamejs/lib/vault-aad.js +3 -2
- package/lib/vendor/blamejs/lib/vc.js +2 -7
- package/lib/vendor/blamejs/lib/vex.js +35 -13
- package/lib/vendor/blamejs/lib/web-push-vapid.js +23 -20
- package/lib/vendor/blamejs/lib/webhook-dispatcher.js +706 -0
- package/lib/vendor/blamejs/lib/webhook.js +43 -18
- package/lib/vendor/blamejs/lib/websocket-channels.js +9 -7
- package/lib/vendor/blamejs/lib/websocket.js +7 -3
- package/lib/vendor/blamejs/lib/worm.js +2 -3
- package/lib/vendor/blamejs/lib/ws-client.js +8 -10
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.15.13.json +81 -0
- package/lib/vendor/blamejs/scripts/check-changelog-extract.js +1 -1
- package/lib/vendor/blamejs/test/00-primitives.js +136 -7
- package/lib/vendor/blamejs/test/10-state.js +9 -3
- package/lib/vendor/blamejs/test/30-chain.js +40 -0
- package/lib/vendor/blamejs/test/helpers/check.js +18 -0
- package/lib/vendor/blamejs/test/helpers/db.js +4 -0
- package/lib/vendor/blamejs/test/helpers/index.js +1 -0
- package/lib/vendor/blamejs/test/integration/audit-chain-external-db.test.js +2 -1
- package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +2 -1
- package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +8 -1
- package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +1 -1
- package/lib/vendor/blamejs/test/integration/framework-schema-mysql.test.js +2 -1
- package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +269 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-fd-read.test.js +149 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-framework-namespaces.test.js +51 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +88 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-use-store.test.js +55 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-object-store-adapter.test.js +2 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/bot-guard.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/bounded-map.test.js +129 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/chain-writer-multichain.test.js +107 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-api-key.test.js +12 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +2788 -3214
- package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +78 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-base64url.test.js +63 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +2 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-builder.test.js +50 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-nonce.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +2 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/defineguard-resolve-opts.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +9 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract-content-gate.test.js +290 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +84 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-email.test.js +78 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +23 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-gate-disposition-coverage.test.js +93 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +60 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +184 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-json.test.js +54 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +10 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +45 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +101 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-text.test.js +365 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-xml.test.js +35 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-yaml.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +20 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +15 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-arf.test.js +10 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +39 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-greylist.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-tls.test.js +39 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mime-parse.test.js +106 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/money.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-revocation.test.js +98 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-release.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-memory-getorinsert.test.js +100 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +88 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-async-loops.test.js +278 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +37 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-jsonpath.test.js +14 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sandbox.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +2 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/session-valid-from.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +100 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/structured-fields.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/validate-opts-shape.test.js +235 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +374 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +75 -8
- package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +3 -3
- package/lib/winback-campaigns.js +202 -42
- package/package.json +1 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* b.auditSign.anchor / verifyAnchor / verifyAnchorChain — the chain-checkpoint
|
|
4
|
+
* protocol lifted off the framework audit store so a consumer can anchor THEIR
|
|
5
|
+
* OWN hash chain with PQC signatures (#327).
|
|
6
|
+
*
|
|
7
|
+
* RED on the current tree: b.auditSign.anchor is undefined. Uses ml-dsa-65 (the
|
|
8
|
+
* fastest PQC keypair) so the per-run keygen stays cheap.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
var helpers = require("../helpers");
|
|
12
|
+
var b = helpers.b;
|
|
13
|
+
var check = helpers.check;
|
|
14
|
+
var fs = require("fs");
|
|
15
|
+
var os = require("os");
|
|
16
|
+
var path = require("path");
|
|
17
|
+
|
|
18
|
+
async function run() {
|
|
19
|
+
var dir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-anchor-"));
|
|
20
|
+
try {
|
|
21
|
+
b.auditSign._resetForTest();
|
|
22
|
+
await b.auditSign.init({ dataDir: dir, mode: "plaintext", algorithm: "ml-dsa-65" });
|
|
23
|
+
var as = b.auditSign;
|
|
24
|
+
|
|
25
|
+
check("anchor / verifyAnchor / verifyAnchorChain are exported",
|
|
26
|
+
typeof b.auditSign.anchor === "function" &&
|
|
27
|
+
typeof b.auditSign.verifyAnchor === "function" &&
|
|
28
|
+
typeof b.auditSign.verifyAnchorChain === "function");
|
|
29
|
+
|
|
30
|
+
var a1 = as.anchor({ counter: 1, tipHash: "h1" });
|
|
31
|
+
check("anchor returns a self-describing signed object",
|
|
32
|
+
a1 && typeof a1.signature === "string" && a1.tipHash === "h1" &&
|
|
33
|
+
a1.publicKeyFingerprint && a1.format === "blamejs-chain-anchor-v1");
|
|
34
|
+
check("a distinct format magic separates anchors from audit checkpoints",
|
|
35
|
+
a1.format !== "blamejs-audit-checkpoint-v1");
|
|
36
|
+
|
|
37
|
+
check("verifyAnchor accepts a clean anchor", as.verifyAnchor(a1).ok === true);
|
|
38
|
+
|
|
39
|
+
// A full-chain rewrite changes the tipHash — the signature catches it.
|
|
40
|
+
check("verifyAnchor rejects a tampered tipHash",
|
|
41
|
+
as.verifyAnchor(Object.assign({}, a1, { tipHash: "ffff" })).ok === false);
|
|
42
|
+
// A forged signature (truncated hex) fails closed.
|
|
43
|
+
check("verifyAnchor rejects malformed-hex signature",
|
|
44
|
+
as.verifyAnchor(Object.assign({}, a1, { signature: "zz" })).ok === false);
|
|
45
|
+
// An unknown signing key fails closed.
|
|
46
|
+
check("verifyAnchor rejects an unknown signing-key fingerprint",
|
|
47
|
+
as.verifyAnchor(Object.assign({}, a1, { publicKeyFingerprint: "deadbeef" })).ok === false);
|
|
48
|
+
|
|
49
|
+
var a2 = as.anchor({ counter: 2, tipHash: "h2", prevTipHash: "h1" });
|
|
50
|
+
// The linkage is SIGNED (#327 C2): tampering prevTipHash breaks the signature.
|
|
51
|
+
check("prevTipHash is bound into the signature (tampering it breaks verify)",
|
|
52
|
+
as.verifyAnchor(Object.assign({}, a2, { prevTipHash: "wrong" })).ok === false);
|
|
53
|
+
|
|
54
|
+
check("verifyAnchorChain accepts a linked, increasing sequence",
|
|
55
|
+
as.verifyAnchorChain([a1, a2]).ok === true && as.verifyAnchorChain([a1, a2]).anchorsVerified === 2);
|
|
56
|
+
|
|
57
|
+
// Truncation: a non-genesis anchor presented first (its prevTipHash has no
|
|
58
|
+
// predecessor) is a break.
|
|
59
|
+
var tr = as.verifyAnchorChain([a2]);
|
|
60
|
+
check("verifyAnchorChain catches a dropped predecessor", tr.ok === false && tr.breakAt === 0);
|
|
61
|
+
|
|
62
|
+
// A broken link (prevTipHash != prior tipHash) is caught.
|
|
63
|
+
var a3 = as.anchor({ counter: 3, tipHash: "h3", prevTipHash: "not-h2" });
|
|
64
|
+
var br = as.verifyAnchorChain([a1, a2, a3]);
|
|
65
|
+
check("verifyAnchorChain catches a broken link", br.ok === false && br.breakAt === 2);
|
|
66
|
+
|
|
67
|
+
// Non-monotonic counters are caught.
|
|
68
|
+
var lower = as.anchor({ counter: 1, tipHash: "h4", prevTipHash: "h2" });
|
|
69
|
+
check("verifyAnchorChain catches a non-increasing counter",
|
|
70
|
+
as.verifyAnchorChain([a1, a2, lower]).ok === false);
|
|
71
|
+
|
|
72
|
+
// requireLinkage:false admits unlinked anchors on the signature alone.
|
|
73
|
+
var u1 = as.anchor({ counter: 10, tipHash: "u1" });
|
|
74
|
+
var u2 = as.anchor({ counter: 11, tipHash: "u2" });
|
|
75
|
+
check("requireLinkage:false admits unlinked anchors",
|
|
76
|
+
as.verifyAnchorChain([u1, u2], { requireLinkage: false }).ok === true);
|
|
77
|
+
|
|
78
|
+
// Malformed tip throws a typed config-time error.
|
|
79
|
+
var threw = false;
|
|
80
|
+
try { as.anchor({ counter: 1 }); } catch (e) { threw = e.code === "ANCHOR_BAD_TIPHASH"; }
|
|
81
|
+
check("anchor throws a typed error on a malformed tip", threw);
|
|
82
|
+
} finally {
|
|
83
|
+
try { b.auditSign._resetForTest(); } catch (_e) { /* best-effort */ }
|
|
84
|
+
try { fs.rmSync(dir, { recursive: true, force: true }); } catch (_e) { /* best-effort */ }
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = { run: run };
|
|
@@ -19,6 +19,8 @@ var fs = helpers.fs;
|
|
|
19
19
|
var os = helpers.os;
|
|
20
20
|
var path = helpers.path;
|
|
21
21
|
var check = helpers.check;
|
|
22
|
+
var waitUntil = helpers.waitUntil;
|
|
23
|
+
var passiveObserve = helpers.passiveObserve;
|
|
22
24
|
var setupTestDb = helpers.setupTestDb;
|
|
23
25
|
var teardownTestDb = helpers.teardownTestDb;
|
|
24
26
|
|
|
@@ -228,9 +230,53 @@ async function testUnregisterPaths() {
|
|
|
228
230
|
}
|
|
229
231
|
}
|
|
230
232
|
|
|
233
|
+
// ---- b.audit.namespaced — the drop-silent prefixed emitter every primitive
|
|
234
|
+
// used to hand-roll as a private _emitAudit closure ----
|
|
235
|
+
|
|
236
|
+
async function testNamespacedEmitter() {
|
|
237
|
+
var tmpDir = _tmp();
|
|
238
|
+
await setupTestDb(tmpDir);
|
|
239
|
+
try {
|
|
240
|
+
var captured = [];
|
|
241
|
+
b.audit.useStore({ record: async function (row) { captured.push(row); } });
|
|
242
|
+
|
|
243
|
+
check("b.audit.namespaced is a function", typeof b.audit.namespaced === "function");
|
|
244
|
+
|
|
245
|
+
function has(action) { return captured.some(function (r) { return r.action === action; }); }
|
|
246
|
+
function row(action) { return captured.find(function (r) { return r.action === action; }); }
|
|
247
|
+
|
|
248
|
+
// "auth" is a registered framework namespace; the emitter prefixes it.
|
|
249
|
+
// (Match by action — a setup-time boot row can land in the shadow store
|
|
250
|
+
// after useStore registers, so index 0 is not necessarily our emit.)
|
|
251
|
+
var emit = b.audit.namespaced("auth", undefined);
|
|
252
|
+
emit("login", "success", { src: "namespaced-test" });
|
|
253
|
+
await waitUntil(function () { return has("auth.login"); },
|
|
254
|
+
{ timeoutMs: 5000, label: "namespaced: prefixed emit landed in chain" });
|
|
255
|
+
check("namespaced prefixes the action (auth + login → auth.login)", has("auth.login"));
|
|
256
|
+
check("namespaced carries the outcome", row("auth.login").outcome === "success");
|
|
257
|
+
|
|
258
|
+
// metadata omitted → defaults to {} (no throw, still emits).
|
|
259
|
+
emit("logout", "success");
|
|
260
|
+
await waitUntil(function () { return has("auth.logout"); },
|
|
261
|
+
{ timeoutMs: 5000, label: "namespaced: default-metadata emit landed" });
|
|
262
|
+
check("namespaced defaults metadata when omitted", has("auth.logout"));
|
|
263
|
+
|
|
264
|
+
// auditFlag === false → the emitter is a no-op (nothing reaches the chain).
|
|
265
|
+
var off = b.audit.namespaced("auth", false);
|
|
266
|
+
off("blocked", "failure", { src: "should-not-emit" });
|
|
267
|
+
await passiveObserve(400, "namespaced(prefix, false): disabled emitter stays a no-op");
|
|
268
|
+
check("namespaced(prefix, false) emits nothing", !has("auth.blocked"));
|
|
269
|
+
|
|
270
|
+
b.audit.useStore(null);
|
|
271
|
+
} finally {
|
|
272
|
+
await teardownTestDb(tmpDir);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
231
276
|
async function run() {
|
|
232
277
|
testSurface();
|
|
233
278
|
testUseStoreBadArg();
|
|
279
|
+
await testNamespacedEmitter();
|
|
234
280
|
await testShadowReceivesRow();
|
|
235
281
|
await testShadowSeesMonotonicCounters();
|
|
236
282
|
await testShadowFailureIsDropSilent();
|
|
@@ -242,5 +288,13 @@ module.exports = { run: run };
|
|
|
242
288
|
|
|
243
289
|
if (require.main === module) {
|
|
244
290
|
run().then(function () { console.log("OK"); })
|
|
245
|
-
.catch(function (e) {
|
|
291
|
+
.catch(function (e) {
|
|
292
|
+
// Log only the error class (not its message/stack): the crypto/db
|
|
293
|
+
// setup path is flagged as carrying passphrase-length-derived data,
|
|
294
|
+
// and logging error content derived from it is a clear-text-logging
|
|
295
|
+
// sink. The class name signals the failure; the non-zero exit makes
|
|
296
|
+
// it loud, and the smoke runner surfaces full detail via check().
|
|
297
|
+
console.error("FAIL: " + (e && e.name ? e.name : "error"));
|
|
298
|
+
process.exit(1);
|
|
299
|
+
});
|
|
246
300
|
}
|
|
@@ -79,13 +79,13 @@ async function testObjectStoreAdapterRefusesBadClient() {
|
|
|
79
79
|
b.backup.bundleAdapterStorage.objectStoreAdapter({}); // missing put/get/etc
|
|
80
80
|
} catch (e) { refused = e; }
|
|
81
81
|
check("objectStoreAdapter: missing methods refused upfront",
|
|
82
|
-
refused && /
|
|
82
|
+
refused && refused.code === "backup/bad-adapter" && /must expose a \w+\(\) method/.test(refused.message || ""));
|
|
83
83
|
var refused2 = null;
|
|
84
84
|
try {
|
|
85
85
|
b.backup.bundleAdapterStorage.objectStoreAdapter(null);
|
|
86
86
|
} catch (e) { refused2 = e; }
|
|
87
87
|
check("objectStoreAdapter: null client refused upfront",
|
|
88
|
-
refused2 && /
|
|
88
|
+
refused2 && refused2.code === "backup/bad-adapter" && /must be an object exposing/.test(refused2.message || ""));
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
async function testObjectStoreAdapterPagination() {
|
|
@@ -99,4 +99,4 @@ async function run() {
|
|
|
99
99
|
testOverridesAndSkips();
|
|
100
100
|
}
|
|
101
101
|
module.exports = { run: run };
|
|
102
|
-
if (require.main === module) { run().then(function () { console.log("[bot-guard] OK — " + helpers.getChecks() + " checks passed"); }, function (e) { console.error("FAIL:"
|
|
102
|
+
if (require.main === module) { run().then(function () { console.log("[bot-guard] OK — " + helpers.getChecks() + " checks passed"); }, function (e) { console.error("FAIL: " + helpers.formatErr(e)); process.exit(1); }); }
|
|
@@ -71,12 +71,141 @@ function testValidation() {
|
|
|
71
71
|
check("bad policy → throws bad-policy", e && e.code === "bounded-map/bad-policy");
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
var getOrInsert = require("../../lib/bounded-map").getOrInsert;
|
|
75
|
+
function _threw(fn) { try { fn(); return null; } catch (e) { return e; } }
|
|
76
|
+
|
|
77
|
+
function testGetOrInsert() {
|
|
78
|
+
// get-or-insert: factory runs once, second call returns the cached value.
|
|
79
|
+
var m = new Map();
|
|
80
|
+
var calls = 0;
|
|
81
|
+
var v1 = getOrInsert(m, "a", function () { calls++; return [1]; });
|
|
82
|
+
var v2 = getOrInsert(m, "a", function () { calls++; return [2]; });
|
|
83
|
+
check("getOrInsert: returns cached value on 2nd call", v1 === v2);
|
|
84
|
+
check("getOrInsert: factory ran exactly once", calls === 1);
|
|
85
|
+
check("getOrInsert: stored the value", m.get("a") === v1);
|
|
86
|
+
|
|
87
|
+
// cap path — at maxSize with an absent key, do NOT store; fire onFull.
|
|
88
|
+
var capped = new Map(); capped.set("x", 1); capped.set("y", 2);
|
|
89
|
+
var full = false;
|
|
90
|
+
var r = getOrInsert(capped, "z", function () { return 9; },
|
|
91
|
+
{ maxSize: 2, onFull: function () { full = true; return "DROPPED"; } });
|
|
92
|
+
check("getOrInsert cap: absent key not stored at cap", !capped.has("z"));
|
|
93
|
+
check("getOrInsert cap: onFull fired", full === true);
|
|
94
|
+
check("getOrInsert cap: returns onFull result", r === "DROPPED");
|
|
95
|
+
check("getOrInsert cap: existing key still returned",
|
|
96
|
+
getOrInsert(capped, "x", function () { return 99; }, { maxSize: 2 }) === 1);
|
|
97
|
+
// cap with no onFull → undefined.
|
|
98
|
+
check("getOrInsert cap: no onFull → undefined",
|
|
99
|
+
getOrInsert(capped, "w", function () { return 1; }, { maxSize: 2 }) === undefined);
|
|
100
|
+
|
|
101
|
+
// validation — every input checked, throws typed BoundedMapError.
|
|
102
|
+
check("getOrInsert: non-Map map throws bad-map",
|
|
103
|
+
(_threw(function () { getOrInsert({}, "k", function () { return 1; }); }) || {}).code === "bounded-map/bad-map");
|
|
104
|
+
check("getOrInsert: non-function factory throws bad-factory",
|
|
105
|
+
(_threw(function () { getOrInsert(new Map(), "k", 42); }) || {}).code === "bounded-map/bad-factory");
|
|
106
|
+
["__NaN__", "__Infinity__", -1, 0, 1.5, "5"].forEach(function (bad) {
|
|
107
|
+
var v = bad === "__NaN__" ? NaN : (bad === "__Infinity__" ? Infinity : bad);
|
|
108
|
+
check("getOrInsert: maxSize " + String(bad) + " throws bad-max-size",
|
|
109
|
+
(_threw(function () { getOrInsert(new Map(), "k", function () { return 1; }, { maxSize: v }); }) || {}).code
|
|
110
|
+
=== "bounded-map/bad-max-size");
|
|
111
|
+
});
|
|
112
|
+
check("getOrInsert: non-function onFull throws bad-on-full",
|
|
113
|
+
(_threw(function () { getOrInsert(new Map(), "k", function () { return 1; }, { maxSize: 1, onFull: 7 }); }) || {}).code
|
|
114
|
+
=== "bounded-map/bad-on-full");
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
var requireAbsent = require("../../lib/bounded-map").requireAbsent;
|
|
118
|
+
var requirePresent = require("../../lib/bounded-map").requirePresent;
|
|
119
|
+
|
|
120
|
+
function testRequireAbsent() {
|
|
121
|
+
// uniqueness guard: absent key → returns undefined, onConflict NOT called.
|
|
122
|
+
var m = new Map();
|
|
123
|
+
var conflicts = 0;
|
|
124
|
+
var r = requireAbsent(m, "k", function () { conflicts++; });
|
|
125
|
+
check("requireAbsent: absent → undefined", r === undefined);
|
|
126
|
+
check("requireAbsent: absent → onConflict silent", conflicts === 0);
|
|
127
|
+
// present key → onConflict(key, existing) called, its result returned.
|
|
128
|
+
m.set("k", 42);
|
|
129
|
+
var seen = null;
|
|
130
|
+
var r2 = requireAbsent(m, "k", function (key, existing) { seen = key + "=" + existing; return "DUP"; });
|
|
131
|
+
check("requireAbsent: present → onConflict fired", seen === "k=42");
|
|
132
|
+
check("requireAbsent: present → returns onConflict result", r2 === "DUP");
|
|
133
|
+
// the canonical caller throws a typed error from onConflict.
|
|
134
|
+
check("requireAbsent: onConflict can throw",
|
|
135
|
+
(_threw(function () {
|
|
136
|
+
requireAbsent(m, "k", function () { throw new BoundedMapError("x/dup", "duplicate"); });
|
|
137
|
+
}) || {}).code === "x/dup");
|
|
138
|
+
// validation
|
|
139
|
+
check("requireAbsent: non-Map throws bad-map",
|
|
140
|
+
(_threw(function () { requireAbsent({}, "k", function () {}); }) || {}).code === "bounded-map/bad-map");
|
|
141
|
+
check("requireAbsent: non-function onConflict throws bad-on-conflict",
|
|
142
|
+
(_threw(function () { requireAbsent(new Map(), "k", 7); }) || {}).code === "bounded-map/bad-on-conflict");
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function testRequirePresent() {
|
|
146
|
+
// existence guard: present key → returns the existing value, onMissing NOT called.
|
|
147
|
+
var m = new Map(); m.set("k", 99);
|
|
148
|
+
var missing = 0;
|
|
149
|
+
var v = requirePresent(m, "k", function () { missing++; });
|
|
150
|
+
check("requirePresent: present → returns value", v === 99);
|
|
151
|
+
check("requirePresent: present → onMissing silent", missing === 0);
|
|
152
|
+
// absent key → onMissing(key) called, its result returned.
|
|
153
|
+
var seen = null;
|
|
154
|
+
var r = requirePresent(m, "nope", function (key) { seen = key; return "MISS"; });
|
|
155
|
+
check("requirePresent: absent → onMissing fired", seen === "nope");
|
|
156
|
+
check("requirePresent: absent → returns onMissing result", r === "MISS");
|
|
157
|
+
check("requirePresent: onMissing can throw",
|
|
158
|
+
(_threw(function () {
|
|
159
|
+
requirePresent(m, "nope", function () { throw new BoundedMapError("x/nf", "not found"); });
|
|
160
|
+
}) || {}).code === "x/nf");
|
|
161
|
+
// validation
|
|
162
|
+
check("requirePresent: non-Map throws bad-map",
|
|
163
|
+
(_threw(function () { requirePresent({}, "k", function () {}); }) || {}).code === "bounded-map/bad-map");
|
|
164
|
+
check("requirePresent: non-function onMissing throws bad-on-missing",
|
|
165
|
+
(_threw(function () { requirePresent(new Map(), "k", 7); }) || {}).code === "bounded-map/bad-on-missing");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
var requireAbsentMember = require("../../lib/bounded-map").requireAbsentMember;
|
|
169
|
+
|
|
170
|
+
function testRequireAbsentMember() {
|
|
171
|
+
// Set-uniqueness guard: absent member → undefined, onConflict NOT called.
|
|
172
|
+
var s = new Set();
|
|
173
|
+
var conflicts = 0;
|
|
174
|
+
var r = requireAbsentMember(s, "k", function () { conflicts++; });
|
|
175
|
+
check("requireAbsentMember: absent → undefined", r === undefined);
|
|
176
|
+
check("requireAbsentMember: absent → onConflict silent", conflicts === 0);
|
|
177
|
+
// present member → onConflict(key) called, its result returned.
|
|
178
|
+
s.add("k");
|
|
179
|
+
var seen = null;
|
|
180
|
+
var r2 = requireAbsentMember(s, "k", function (key) { seen = key; return "DUP"; });
|
|
181
|
+
check("requireAbsentMember: present → onConflict fired", seen === "k");
|
|
182
|
+
check("requireAbsentMember: present → returns onConflict result", r2 === "DUP");
|
|
183
|
+
// the canonical caller throws a typed duplicate/cycle error.
|
|
184
|
+
check("requireAbsentMember: onConflict can throw",
|
|
185
|
+
(_threw(function () {
|
|
186
|
+
requireAbsentMember(s, "k", function () { throw new BoundedMapError("x/dup", "duplicate"); });
|
|
187
|
+
}) || {}).code === "x/dup");
|
|
188
|
+
// works on any { has } view, including object identity in a Set.
|
|
189
|
+
var nodeA = {}, visited = new Set([nodeA]);
|
|
190
|
+
check("requireAbsentMember: object-identity membership (cycle use)",
|
|
191
|
+
requireAbsentMember(visited, nodeA, function () { return "CYCLE"; }) === "CYCLE");
|
|
192
|
+
// validation
|
|
193
|
+
check("requireAbsentMember: non-Set throws bad-set",
|
|
194
|
+
(_threw(function () { requireAbsentMember({}, "k", function () {}); }) || {}).code === "bounded-map/bad-set");
|
|
195
|
+
check("requireAbsentMember: non-function onConflict throws bad-on-conflict",
|
|
196
|
+
(_threw(function () { requireAbsentMember(new Set(), "k", 7); }) || {}).code === "bounded-map/bad-on-conflict");
|
|
197
|
+
}
|
|
198
|
+
|
|
74
199
|
function run() {
|
|
75
200
|
testEvictOldest();
|
|
76
201
|
testUpdateDoesNotGrowOrEvict();
|
|
77
202
|
testRejectPolicy();
|
|
78
203
|
testMapFacade();
|
|
79
204
|
testValidation();
|
|
205
|
+
testGetOrInsert();
|
|
206
|
+
testRequireAbsent();
|
|
207
|
+
testRequirePresent();
|
|
208
|
+
testRequireAbsentMember();
|
|
80
209
|
}
|
|
81
210
|
|
|
82
211
|
module.exports = { run: run };
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* b.chainWriter consumer-owned + multi-chain (chainKey) support, and
|
|
4
|
+
* b.auditChain.verifyChain / getChainTip per-partition scoping (#326).
|
|
5
|
+
*
|
|
6
|
+
* Drives the real consumer path: register an app table, build a keyed writer,
|
|
7
|
+
* append to two partitions, and verify each sub-chain independently. RED on the
|
|
8
|
+
* current tree (chainWriter.registerTable + the chainKey opt did not exist).
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
var helpers = require("../helpers");
|
|
12
|
+
var b = helpers.b;
|
|
13
|
+
var check = helpers.check;
|
|
14
|
+
var setupTestDb = helpers.setupTestDb;
|
|
15
|
+
var teardownTestDb = helpers.teardownTestDb;
|
|
16
|
+
var fs = require("fs");
|
|
17
|
+
var os = require("os");
|
|
18
|
+
var path = require("path");
|
|
19
|
+
|
|
20
|
+
var CONSUMER_SCHEMA = [{
|
|
21
|
+
name: "device_event_log",
|
|
22
|
+
columns: {
|
|
23
|
+
_id: "TEXT PRIMARY KEY",
|
|
24
|
+
deviceId: "TEXT NOT NULL",
|
|
25
|
+
monotonicCounter: "INTEGER NOT NULL",
|
|
26
|
+
recordedAt: "INTEGER NOT NULL",
|
|
27
|
+
kind: "TEXT",
|
|
28
|
+
payload: "TEXT",
|
|
29
|
+
prevHash: "TEXT",
|
|
30
|
+
rowHash: "TEXT",
|
|
31
|
+
nonce: "BLOB",
|
|
32
|
+
fencingToken: "TEXT",
|
|
33
|
+
},
|
|
34
|
+
// A keyed chain's uniqueness is the composite (deviceId, monotonicCounter),
|
|
35
|
+
// never monotonicCounter alone (it restarts at 1 per key).
|
|
36
|
+
indexes: [{ name: "idx_dev_chain", columns: ["deviceId", "monotonicCounter"], unique: true }],
|
|
37
|
+
sealedFields: [],
|
|
38
|
+
}];
|
|
39
|
+
|
|
40
|
+
var COLS = ["_id", "deviceId", "monotonicCounter", "recordedAt", "kind", "payload",
|
|
41
|
+
"prevHash", "rowHash", "nonce", "fencingToken"];
|
|
42
|
+
var HASHABLE = ["_id", "deviceId", "monotonicCounter", "recordedAt", "kind", "payload"];
|
|
43
|
+
|
|
44
|
+
async function run() {
|
|
45
|
+
var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-cwmc-"));
|
|
46
|
+
try {
|
|
47
|
+
await setupTestDb(tmpDir, CONSUMER_SCHEMA);
|
|
48
|
+
var queryAll = b.clusterStorage.executeAll;
|
|
49
|
+
|
|
50
|
+
// A consumer table must be registered before create() accepts it — the
|
|
51
|
+
// ALLOWED_CHAIN_TABLES allowlist is never bypassed.
|
|
52
|
+
check("create() refuses an unregistered consumer table",
|
|
53
|
+
(function () { try { b.chainWriter.create({ table: "device_event_log", columnsForInsert: COLS, hashableColumns: HASHABLE }); return false; } catch (_e) { return true; } })());
|
|
54
|
+
|
|
55
|
+
b.chainWriter.registerTable("device_event_log");
|
|
56
|
+
var w = b.chainWriter.create({
|
|
57
|
+
table: "device_event_log", chainKey: "deviceId",
|
|
58
|
+
columnsForInsert: COLS, hashableColumns: HASHABLE,
|
|
59
|
+
});
|
|
60
|
+
check("keyed writer exposes its chainKey", w.chainKey === "deviceId");
|
|
61
|
+
|
|
62
|
+
// Append to two independent partitions; counters restart per key.
|
|
63
|
+
var a1 = await w.append({ deviceId: "dev-A", kind: "boot", payload: "1" });
|
|
64
|
+
var a2 = await w.append({ deviceId: "dev-A", kind: "tick", payload: "2" });
|
|
65
|
+
var b1 = await w.append({ deviceId: "dev-B", kind: "boot", payload: "1" });
|
|
66
|
+
check("dev-A first row counter is 1", a1.monotonicCounter === 1);
|
|
67
|
+
check("dev-A second row counter is 2", a2.monotonicCounter === 2);
|
|
68
|
+
check("dev-B first row counter restarts at 1 (independent chain)", b1.monotonicCounter === 1);
|
|
69
|
+
check("dev-A row 2 links to row 1's rowHash (per-key tip)", a2.prevHash === a1.rowHash);
|
|
70
|
+
check("dev-B row 1 starts a fresh chain (ZERO_HASH prev)", b1.prevHash === b.auditChain.ZERO_HASH);
|
|
71
|
+
|
|
72
|
+
// A keyed writer fails closed on a missing partition key.
|
|
73
|
+
var threwKey = false;
|
|
74
|
+
try { await w.append({ kind: "no-device" }); } catch (e) { threwKey = /chain-writer/.test(e.code || ""); }
|
|
75
|
+
check("append refuses a row missing the chainKey", threwKey);
|
|
76
|
+
|
|
77
|
+
// verifyChain scopes per key: each sub-chain verifies clean independently.
|
|
78
|
+
var ok = await b.auditChain.verifyChain(queryAll, "device_event_log", { chainKey: "deviceId" });
|
|
79
|
+
check("verifyChain({chainKey}) reports ok across all partitions", ok.ok === true);
|
|
80
|
+
check("verifyChain counts both partitions", ok.chains === 2);
|
|
81
|
+
check("verifyChain totals every row across sub-chains", ok.rowsVerified === 3);
|
|
82
|
+
|
|
83
|
+
// getChainTip scoped to one partition returns that key's tip.
|
|
84
|
+
var tipA = await b.auditChain.getChainTip(b.clusterStorage.executeOne, "device_event_log",
|
|
85
|
+
{ chainKey: "deviceId", keyValue: "dev-A" });
|
|
86
|
+
check("getChainTip({chainKey}) returns dev-A's tip (counter 2)", tipA.counter === 2 && tipA.prevHash === a2.rowHash);
|
|
87
|
+
var tipB = await b.auditChain.getChainTip(b.clusterStorage.executeOne, "device_event_log",
|
|
88
|
+
{ chainKey: "deviceId", keyValue: "dev-B" });
|
|
89
|
+
check("getChainTip({chainKey}) returns dev-B's tip (counter 1)", tipB.counter === 1);
|
|
90
|
+
|
|
91
|
+
// Tamper a row in dev-A and confirm verify breaks on THAT key.
|
|
92
|
+
await b.clusterStorage.execute(
|
|
93
|
+
'UPDATE device_event_log SET payload = ? WHERE deviceId = ? AND monotonicCounter = ?',
|
|
94
|
+
["tampered", "dev-A", 2]);
|
|
95
|
+
var bad = await b.auditChain.verifyChain(queryAll, "device_event_log", { chainKey: "deviceId" });
|
|
96
|
+
check("verifyChain detects a tampered row", bad.ok === false);
|
|
97
|
+
check("verifyChain reports the broken chainKey", bad.chainKey === "dev-A");
|
|
98
|
+
|
|
99
|
+
// maxChains fails closed when the partition fan-out exceeds the cap.
|
|
100
|
+
var capped = await b.auditChain.verifyChain(queryAll, "device_event_log", { chainKey: "deviceId", maxChains: 1 });
|
|
101
|
+
check("verifyChain fails closed past maxChains", capped.ok === false && /too many chains/.test(capped.reason));
|
|
102
|
+
} finally {
|
|
103
|
+
try { await teardownTestDb(tmpDir); } catch (_e) { /* best-effort */ }
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
module.exports = { run: run };
|
|
@@ -77,6 +77,18 @@ async function run() {
|
|
|
77
77
|
// revoke takes the bare idHex (matches what `list` prints in the
|
|
78
78
|
// first column).
|
|
79
79
|
|
|
80
|
+
// ---- issue with --expires-ms (the flag must actually set the expiry;
|
|
81
|
+
// it was a silent no-op when the CLI passed the wrong opt key) ----
|
|
82
|
+
var futureMs = 4102444800000; // 2100-01-01T00:00:00Z, absolute unix ms
|
|
83
|
+
var ctxE = _captureCtx();
|
|
84
|
+
var cE = await cli.main(
|
|
85
|
+
["api-key", "issue"].concat(base).concat([
|
|
86
|
+
"--owner-id", "carol", "--scopes", "users:read", "--expires-ms", String(futureMs),
|
|
87
|
+
]), ctxE);
|
|
88
|
+
check("issue --expires-ms: returns 0", cE === 0);
|
|
89
|
+
check("issue --expires-ms: prints the expiry line (flag is not a no-op)",
|
|
90
|
+
/^expires:\s+2100-01-01T00:00:00/m.test(ctxE.out()));
|
|
91
|
+
|
|
80
92
|
// ---- issue (missing --scopes) ----
|
|
81
93
|
var ctx2 = _captureCtx();
|
|
82
94
|
var c2 = await cli.main(
|