@blamejs/blamejs-shop 0.5.12 → 0.5.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/lib/asset-manifest.json +1 -1
- package/lib/vendor/MANIFEST.json +632 -416
- package/lib/vendor/blamejs/.clusterfuzzlite/Dockerfile +21 -10
- package/lib/vendor/blamejs/.clusterfuzzlite/build.sh +30 -9
- package/lib/vendor/blamejs/.github/dependabot.yml +8 -0
- package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +7 -2
- package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +7 -2
- package/lib/vendor/blamejs/.github/workflows/ci.yml +21 -21
- package/lib/vendor/blamejs/.github/workflows/codeql.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +4 -4
- package/lib/vendor/blamejs/.github/workflows/release-container.yml +7 -7
- package/lib/vendor/blamejs/.github/workflows/scorecard.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
- package/lib/vendor/blamejs/.gitignore +2 -0
- package/lib/vendor/blamejs/CHANGELOG.md +122 -0
- package/lib/vendor/blamejs/NOTICE +26 -1
- package/lib/vendor/blamejs/SECURITY.md +1 -1
- package/lib/vendor/blamejs/api-snapshot.json +207 -5
- package/lib/vendor/blamejs/docker/keycloak/realm-blamejs-test.json +29 -0
- package/lib/vendor/blamejs/examples/wiki/DEPLOY.md +1 -0
- package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +31 -0
- package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +109 -0
- package/lib/vendor/blamejs/examples/wiki/nginx.conf +106 -0
- package/lib/vendor/blamejs/examples/wiki/package-lock.json +1 -1
- package/lib/vendor/blamejs/examples/wiki/test/e2e.js +92 -0
- package/lib/vendor/blamejs/fuzz/asn1-der.fuzz.js +28 -0
- package/lib/vendor/blamejs/fuzz/cms-codec.fuzz.js +17 -0
- package/lib/vendor/blamejs/fuzz/link-header.fuzz.js +18 -0
- package/lib/vendor/blamejs/index.js +6 -0
- package/lib/vendor/blamejs/lib/a2a.js +4 -4
- package/lib/vendor/blamejs/lib/agent-idempotency.js +18 -2
- package/lib/vendor/blamejs/lib/agent-saga.js +36 -8
- package/lib/vendor/blamejs/lib/agent-snapshot.js +63 -6
- package/lib/vendor/blamejs/lib/app-shutdown.js +23 -20
- package/lib/vendor/blamejs/lib/archive-read.js +8 -0
- package/lib/vendor/blamejs/lib/archive-tar.js +12 -2
- package/lib/vendor/blamejs/lib/arg-parser.js +49 -5
- package/lib/vendor/blamejs/lib/asn1-der.js +12 -0
- package/lib/vendor/blamejs/lib/audit-sign.js +47 -1
- package/lib/vendor/blamejs/lib/audit.js +71 -8
- package/lib/vendor/blamejs/lib/auth/ciba.js +14 -2
- package/lib/vendor/blamejs/lib/auth/fido-mds3.js +58 -47
- package/lib/vendor/blamejs/lib/auth/jwt.js +34 -0
- package/lib/vendor/blamejs/lib/auth/oauth.js +90 -13
- package/lib/vendor/blamejs/lib/auth/oid4vci.js +20 -17
- package/lib/vendor/blamejs/lib/auth/openid-federation.js +214 -23
- package/lib/vendor/blamejs/lib/auth/saml.js +38 -20
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +10 -4
- package/lib/vendor/blamejs/lib/backup/bundle.js +13 -3
- package/lib/vendor/blamejs/lib/backup/index.js +16 -5
- package/lib/vendor/blamejs/lib/backup/manifest.js +18 -5
- package/lib/vendor/blamejs/lib/base32.js +21 -0
- package/lib/vendor/blamejs/lib/break-glass.js +19 -10
- package/lib/vendor/blamejs/lib/bundler.js +5 -1
- package/lib/vendor/blamejs/lib/cache-status.js +3 -7
- package/lib/vendor/blamejs/lib/calendar.js +21 -1
- package/lib/vendor/blamejs/lib/cbor.js +12 -1
- package/lib/vendor/blamejs/lib/cert.js +29 -11
- package/lib/vendor/blamejs/lib/cli.js +94 -24
- package/lib/vendor/blamejs/lib/cloud-events.js +2 -2
- package/lib/vendor/blamejs/lib/cluster-provider-db.js +13 -3
- package/lib/vendor/blamejs/lib/codepoint-class.js +85 -0
- package/lib/vendor/blamejs/lib/compliance-ai-act-prohibited.js +8 -4
- package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +19 -4
- package/lib/vendor/blamejs/lib/compliance-ai-act.js +6 -8
- package/lib/vendor/blamejs/lib/content-credentials.js +1 -1
- package/lib/vendor/blamejs/lib/content-digest.js +2 -1
- package/lib/vendor/blamejs/lib/cookies.js +13 -3
- package/lib/vendor/blamejs/lib/cose.js +31 -16
- package/lib/vendor/blamejs/lib/crypto-field.js +32 -0
- package/lib/vendor/blamejs/lib/crypto-oprf.js +11 -2
- package/lib/vendor/blamejs/lib/crypto-xwing.js +22 -4
- package/lib/vendor/blamejs/lib/crypto.js +314 -19
- package/lib/vendor/blamejs/lib/csp.js +11 -3
- package/lib/vendor/blamejs/lib/daemon.js +270 -24
- package/lib/vendor/blamejs/lib/dark-patterns.js +5 -2
- package/lib/vendor/blamejs/lib/db-declare-view.js +2 -2
- package/lib/vendor/blamejs/lib/db-query.js +34 -7
- package/lib/vendor/blamejs/lib/db.js +18 -6
- package/lib/vendor/blamejs/lib/dbsc.js +17 -0
- package/lib/vendor/blamejs/lib/dev.js +21 -2
- package/lib/vendor/blamejs/lib/dsr.js +157 -102
- package/lib/vendor/blamejs/lib/external-db.js +41 -2
- package/lib/vendor/blamejs/lib/file-upload.js +25 -7
- package/lib/vendor/blamejs/lib/flag-providers.js +27 -15
- package/lib/vendor/blamejs/lib/forms.js +113 -27
- package/lib/vendor/blamejs/lib/gate-contract.js +23 -10
- package/lib/vendor/blamejs/lib/gdpr-ropa.js +8 -1
- package/lib/vendor/blamejs/lib/guard-agent-registry.js +1 -1
- package/lib/vendor/blamejs/lib/guard-archive.js +2 -2
- package/lib/vendor/blamejs/lib/guard-cidr.js +27 -1
- package/lib/vendor/blamejs/lib/guard-graphql.js +30 -11
- package/lib/vendor/blamejs/lib/guard-html.js +26 -53
- package/lib/vendor/blamejs/lib/guard-image.js +24 -5
- package/lib/vendor/blamejs/lib/guard-imap-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-jmap.js +19 -3
- package/lib/vendor/blamejs/lib/guard-jwt.js +18 -2
- package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -2
- package/lib/vendor/blamejs/lib/guard-managesieve-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-markdown.js +11 -24
- package/lib/vendor/blamejs/lib/guard-pdf.js +18 -2
- package/lib/vendor/blamejs/lib/guard-pop3-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-regex.js +8 -5
- package/lib/vendor/blamejs/lib/guard-svg.js +31 -32
- package/lib/vendor/blamejs/lib/guard-time.js +1 -1
- package/lib/vendor/blamejs/lib/guard-uuid.js +2 -2
- package/lib/vendor/blamejs/lib/html-balance.js +3 -3
- package/lib/vendor/blamejs/lib/http-client-cache.js +82 -4
- package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +16 -1
- package/lib/vendor/blamejs/lib/http-client.js +39 -7
- package/lib/vendor/blamejs/lib/http-message-signature.js +35 -1
- package/lib/vendor/blamejs/lib/i18n-messageformat.js +31 -6
- package/lib/vendor/blamejs/lib/i18n.js +35 -21
- package/lib/vendor/blamejs/lib/incident-report.js +8 -1
- package/lib/vendor/blamejs/lib/ip-utils.js +11 -1
- package/lib/vendor/blamejs/lib/json-path.js +23 -1
- package/lib/vendor/blamejs/lib/jwk.js +20 -3
- package/lib/vendor/blamejs/lib/link-header.js +2 -1
- package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +5 -1
- package/lib/vendor/blamejs/lib/log-stream-otlp.js +5 -1
- package/lib/vendor/blamejs/lib/log-stream.js +8 -3
- package/lib/vendor/blamejs/lib/mail-auth.js +123 -22
- package/lib/vendor/blamejs/lib/mail-bimi.js +1 -1
- package/lib/vendor/blamejs/lib/mail-bounce.js +8 -0
- package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +46 -10
- package/lib/vendor/blamejs/lib/mail-dav.js +22 -3
- package/lib/vendor/blamejs/lib/mail-dkim.js +96 -30
- package/lib/vendor/blamejs/lib/mail-helo.js +6 -1
- package/lib/vendor/blamejs/lib/mail-scan.js +23 -16
- package/lib/vendor/blamejs/lib/mail-send-deliver.js +34 -8
- package/lib/vendor/blamejs/lib/mail-server-imap.js +3 -4
- package/lib/vendor/blamejs/lib/mail-server-managesieve.js +7 -11
- package/lib/vendor/blamejs/lib/mail-server-mx.js +93 -7
- package/lib/vendor/blamejs/lib/mail-server-registry.js +8 -2
- package/lib/vendor/blamejs/lib/mail.js +15 -5
- package/lib/vendor/blamejs/lib/metrics.js +268 -63
- package/lib/vendor/blamejs/lib/middleware/age-gate.js +7 -1
- package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/body-parser.js +19 -4
- package/lib/vendor/blamejs/lib/middleware/bot-guard.js +5 -9
- package/lib/vendor/blamejs/lib/middleware/csp-report.js +40 -8
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +24 -10
- package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -5
- package/lib/vendor/blamejs/lib/middleware/index.js +6 -1
- package/lib/vendor/blamejs/lib/middleware/nel.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +12 -1
- package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/scim-server.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/tus-upload.js +6 -2
- package/lib/vendor/blamejs/lib/mtls-ca.js +18 -2
- package/lib/vendor/blamejs/lib/network-dns-resolver.js +11 -1
- package/lib/vendor/blamejs/lib/network-dns.js +21 -2
- package/lib/vendor/blamejs/lib/network-tls.js +69 -7
- package/lib/vendor/blamejs/lib/nonce-store.js +9 -1
- package/lib/vendor/blamejs/lib/object-store/gcs.js +7 -0
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +31 -0
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +1 -1
- package/lib/vendor/blamejs/lib/outbox.js +1 -1
- package/lib/vendor/blamejs/lib/parsers/safe-ini.js +9 -1
- package/lib/vendor/blamejs/lib/parsers/safe-toml.js +10 -1
- package/lib/vendor/blamejs/lib/permissions.js +6 -3
- package/lib/vendor/blamejs/lib/pid-probe.js +55 -0
- package/lib/vendor/blamejs/lib/pqc-agent.js +8 -1
- package/lib/vendor/blamejs/lib/pqc-software.js +3 -3
- package/lib/vendor/blamejs/lib/pubsub.js +20 -9
- package/lib/vendor/blamejs/lib/queue-local.js +8 -1
- package/lib/vendor/blamejs/lib/queue-redis.js +5 -0
- package/lib/vendor/blamejs/lib/redact.js +54 -0
- package/lib/vendor/blamejs/lib/restore-bundle.js +10 -2
- package/lib/vendor/blamejs/lib/restore.js +19 -0
- package/lib/vendor/blamejs/lib/retention.js +12 -4
- package/lib/vendor/blamejs/lib/router.js +60 -6
- package/lib/vendor/blamejs/lib/safe-buffer.js +69 -0
- package/lib/vendor/blamejs/lib/safe-decompress.js +8 -2
- package/lib/vendor/blamejs/lib/safe-dns.js +25 -20
- package/lib/vendor/blamejs/lib/safe-ical.js +7 -3
- package/lib/vendor/blamejs/lib/safe-mime.js +12 -1
- package/lib/vendor/blamejs/lib/safe-object.js +80 -0
- package/lib/vendor/blamejs/lib/safe-path.js +52 -4
- package/lib/vendor/blamejs/lib/safe-redirect.js +10 -2
- package/lib/vendor/blamejs/lib/safe-schema.js +4 -1
- package/lib/vendor/blamejs/lib/safe-sieve.js +33 -1
- package/lib/vendor/blamejs/lib/safe-sql.js +88 -0
- package/lib/vendor/blamejs/lib/safe-vcard.js +7 -3
- package/lib/vendor/blamejs/lib/scheduler.js +8 -1
- package/lib/vendor/blamejs/lib/security-assert.js +6 -6
- package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +74 -27
- package/lib/vendor/blamejs/lib/self-update.js +517 -87
- package/lib/vendor/blamejs/lib/server-timing.js +2 -4
- package/lib/vendor/blamejs/lib/session.js +34 -12
- package/lib/vendor/blamejs/lib/sql.js +15 -1
- package/lib/vendor/blamejs/lib/ssrf-guard.js +52 -0
- package/lib/vendor/blamejs/lib/static.js +55 -13
- package/lib/vendor/blamejs/lib/storage.js +8 -2
- package/lib/vendor/blamejs/lib/subject.js +6 -1
- package/lib/vendor/blamejs/lib/tenant-quota.js +52 -13
- package/lib/vendor/blamejs/lib/tls-exporter.js +3 -3
- package/lib/vendor/blamejs/lib/tsa.js +34 -13
- package/lib/vendor/blamejs/lib/uri-template.js +8 -1
- package/lib/vendor/blamejs/lib/vault/index.js +13 -0
- package/lib/vendor/blamejs/lib/vc.js +44 -5
- package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +26 -26
- package/lib/vendor/blamejs/lib/vendor/noble-ciphers.cjs +792 -1
- package/lib/vendor/blamejs/lib/vendor/noble-curves.cjs +3443 -1
- package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +2737 -1
- package/lib/vendor/blamejs/lib/vendor/pki.cjs +39550 -13
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +55 -53
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5551 -5554
- package/lib/vendor/blamejs/lib/vendor/simplewebauthn-server.cjs +22459 -32
- package/lib/vendor/blamejs/lib/watcher.js +89 -17
- package/lib/vendor/blamejs/lib/webhook-dispatcher.js +25 -3
- package/lib/vendor/blamejs/lib/webhook.js +12 -2
- package/lib/vendor/blamejs/lib/ws-client.js +32 -1
- package/lib/vendor/blamejs/lib/xml-c14n.js +29 -1
- package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile +1 -1
- package/lib/vendor/blamejs/package-lock.json +2 -2
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.16.x.json +1462 -0
- package/lib/vendor/blamejs/release-notes/v0.17.0.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.1.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.10.json +30 -0
- package/lib/vendor/blamejs/release-notes/v0.17.11.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.17.12.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.13.json +77 -0
- package/lib/vendor/blamejs/release-notes/v0.17.14.json +40 -0
- package/lib/vendor/blamejs/release-notes/v0.17.15.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.16.json +27 -0
- package/lib/vendor/blamejs/release-notes/v0.17.17.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.18.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.19.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.2.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.20.json +43 -0
- package/lib/vendor/blamejs/release-notes/v0.17.21.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.22.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.3.json +43 -0
- package/lib/vendor/blamejs/release-notes/v0.17.4.json +35 -0
- package/lib/vendor/blamejs/release-notes/v0.17.5.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.6.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.7.json +35 -0
- package/lib/vendor/blamejs/release-notes/v0.17.8.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.17.9.json +26 -0
- package/lib/vendor/blamejs/scripts/validate-source-comment-blocks.js +4 -0
- package/lib/vendor/blamejs/scripts/vendor-update.sh +293 -9
- package/lib/vendor/blamejs/socket.yml +94 -0
- package/lib/vendor/blamejs/test/00-primitives.js +605 -0
- package/lib/vendor/blamejs/test/helpers/drivers.js +12 -9
- package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +90 -1
- package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +122 -1
- package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +30 -0
- package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +29 -0
- package/lib/vendor/blamejs/test/integration/dsr-cluster-mysql.test.js +479 -0
- package/lib/vendor/blamejs/test/integration/dsr-cluster-pg.test.js +487 -0
- package/lib/vendor/blamejs/test/integration/federation-auth.test.js +313 -5
- package/lib/vendor/blamejs/test/integration/mail-dkim.test.js +80 -0
- package/lib/vendor/blamejs/test/integration/openid-federation-chain.test.js +275 -0
- package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +96 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +401 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/acme.test.js +1649 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +33 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-saga.test.js +60 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/api-encrypt.test.js +891 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/app-shutdown.test.js +128 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-adapters.test.js +271 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-read.test.js +628 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-tar-read.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-wrap.test.js +227 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/arg-parser.test.js +15 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file.test.js +114 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +141 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-tools.test.js +624 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit.test.js +769 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +436 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth.test.js +1697 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oid4vp.test.js +495 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-password.test.js +500 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml.test.js +1809 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-status-list.test.js +243 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-index.test.js +2226 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +183 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/base32.test.js +105 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +693 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cache.test.js +603 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/calendar.test.js +557 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/case-insensitive-security-token-guard.test.js +214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cbor.test.js +25 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cert.test.js +843 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/ciba-authreqid-binding.test.js +77 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/ciba.test.js +866 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-erase.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli.test.js +2790 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cluster-lease-renewal-ttl.test.js +114 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cluster.test.js +1032 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cms-codec.test.js +575 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +739 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +8 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +194 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-lifecycle-proto-key.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +254 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +613 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/cookies.test.js +140 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cose.test.js +407 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-adversarial.test.js +352 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field.test.js +575 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-files-parallel.test.js +10 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +24 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-oprf.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-spki-pin.test.js +183 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-xwing.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto.test.js +345 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-report.test.js +58 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csv.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +459 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/dark-patterns.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-query.test.js +1019 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db.test.js +1621 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ddl-change-control.test.js +462 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/dnssec.test.js +323 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-verify.test.js +562 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +901 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/dual-control.test.js +249 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +561 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db.test.js +1214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fal.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fedcm-dbsc.test.js +46 -20
- package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +147 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +907 -38
- package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +29 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/file-upload.test.js +1135 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/forms.test.js +747 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract.test.js +1855 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gdpr-ropa.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-archive.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-auth.test.js +117 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-cidr.test.js +151 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-domain.test.js +422 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +424 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{guard-gate-disposition-coverage.test.js → guard-gate-disposition.test.js} +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-graphql.test.js +340 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +29 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-idempotency-key.test.js +28 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +519 -45
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jmap.test.js +51 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jsonpath.test.js +66 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jwt.test.js +436 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +25 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +16 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-mime.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-oauth.test.js +140 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-regex.test.js +99 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-shell.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{guard-sql-coverage.test.js → guard-sql.test.js} +3 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-template.test.js +71 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-time.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-uuid.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/html-balance.test.js +38 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache-authorization.test.js +347 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +908 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client.test.js +2874 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-message-signature.test.js +643 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n-messageformat.test.js +38 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +1153 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +494 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jsdoc-example-execution.test.js +177 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/json-path.test.js +103 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/json-schema.test.js +214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jwk.test.js +41 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +276 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/keychain.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log-stream.test.js +241 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log.test.js +106 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +441 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +2136 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-bimi.test.js +759 -12
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-bounce.test.js +811 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp-experimental.test.js +401 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +751 -8
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +864 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto.test.js +110 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dav.test.js +830 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy.test.js +635 -86
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +818 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-helo.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-scan.test.js +199 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-send-deliver.test.js +686 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +778 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +1438 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-managesieve.test.js +449 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +773 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-pop3.test.js +623 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-rate-limit.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-registry.test.js +13 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-submission.test.js +877 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-sieve.test.js +326 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store-fts.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +242 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail.test.js +1596 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mcp.test.js +440 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics-snapshot.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics.test.js +1230 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-assetlinks.test.js +113 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-body-parser.test.js +1169 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-bot-disclose.test.js +123 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-cookies.test.js +108 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-gpc.test.js +121 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-headers.test.js +163 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-host-allowlist.test.js +154 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-require-content-type.test.js +127 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{middleware-tus-upload-coverage.test.js → middleware-tus-upload.test.js} +45 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-web-app-manifest.test.js +132 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-crl-fingerprint-only.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns-resolver.test.js +65 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +1727 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/network-nts.test.js +699 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy.test.js +1181 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +1876 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/network.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-enforce-replay-nonboolean.test.js +81 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ntp-check.test.js +122 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +378 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/oid4vci.test.js +1016 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/openid-federation.test.js +946 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/outbox.test.js +818 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/own-property-membership-guards.test.js +109 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-safe-toml.test.js +543 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{parsers-safe-yaml-coverage.test.js → parsers-safe-yaml.test.js} +2 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/passkey.test.js +649 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/permissions.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +22 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pubsub.test.js +295 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue-flow-repeat.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-xff-spoofing.test.js +34 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/redact.test.js +1031 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/require-bound-key.test.js +401 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/restore-empty-manifest-wipe.test.js +154 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/retention.test.js +600 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-host-path-injection.test.js +231 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-tls0rtt.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router.test.js +1277 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-async.test.js +133 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +14 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-decompress.test.js +28 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-dns.test.js +245 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-ical.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-ini.test.js +376 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-json.test.js +175 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-mime.test.js +518 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-object.test.js +62 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-schema.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-sql.test.js +142 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-url.test.js +112 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-vcard.test.js +26 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scheduler.test.js +157 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scim-server.test.js +396 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +930 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/security-assert.test.js +755 -82
- package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +1053 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +200 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-strict-binding-missing-failclosed.test.js +110 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +636 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql-offset-without-limit.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +1190 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +850 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/storage-presigned-url.test.js +146 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/storage.test.js +621 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/subject.test.js +47 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/template.test.js +582 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +587 -25
- package/lib/vendor/blamejs/test/layer-0-primitives/time.test.js +11 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tsa.test.js +524 -63
- package/lib/vendor/blamejs/test/layer-0-primitives/uri-template.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault-rotate.test.js +866 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault.test.js +74 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vc.test.js +215 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +550 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +388 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +262 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/websocket.test.js +1294 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +629 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/xml-c14n-attr-normalization.test.js +164 -0
- package/lib/vendor/blamejs/test/smoke.js +2 -0
- package/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.16.0.json +0 -44
- package/lib/vendor/blamejs/release-notes/v0.16.1.json +0 -36
- package/lib/vendor/blamejs/release-notes/v0.16.2.json +0 -71
- package/lib/vendor/blamejs/release-notes/v0.16.3.json +0 -71
- package/lib/vendor/blamejs/test/layer-0-primitives/acme-coverage.test.js +0 -441
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth-coverage.test.js +0 -482
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml-coverage.test.js +0 -671
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-index-coverage.test.js +0 -690
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-coverage.test.js +0 -238
- package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials-coverage.test.js +0 -319
- package/lib/vendor/blamejs/test/layer-0-primitives/keychain-coverage.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth-coverage.test.js +0 -437
- package/lib/vendor/blamejs/test/layer-0-primitives/mcp-coverage.test.js +0 -443
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics-coverage.test.js +0 -395
- package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy-coverage.test.js +0 -565
- package/lib/vendor/blamejs/test/layer-0-primitives/router-coverage.test.js +0 -592
- package/lib/vendor/blamejs/test/layer-0-primitives/sql-coverage.test.js +0 -422
- package/lib/vendor/blamejs/test/layer-0-primitives/test-coverage.test.js +0 -573
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# nginx config for blamejs.com — reverse-proxy to the wiki container,
|
|
2
|
+
# mirroring examples/wiki/Caddyfile for operators who front the wiki with
|
|
3
|
+
# nginx instead of Caddy.
|
|
4
|
+
#
|
|
5
|
+
# Unlike Caddy, nginx does not issue TLS certificates itself. Obtain and
|
|
6
|
+
# renew them with certbot (https://certbot.eff.org) — the paths below
|
|
7
|
+
# assume the standard certbot layout. Everything else (the TLS floor, the
|
|
8
|
+
# forwarded headers the wiki trusts, the www→apex redirect, and HSTS)
|
|
9
|
+
# matches the Caddy hardening so the wiki emits its own strong security
|
|
10
|
+
# headers rather than a weaker proxy default.
|
|
11
|
+
#
|
|
12
|
+
# Drop this in /etc/nginx/conf.d/blamejs.conf (or include it from the main
|
|
13
|
+
# nginx.conf). Set WIKI_ADMIN_TRUSTED_PROXIES to the CIDR nginx connects
|
|
14
|
+
# from so the wiki trusts the X-Forwarded-* headers below (the prod compose
|
|
15
|
+
# already defaults it to the private ranges).
|
|
16
|
+
|
|
17
|
+
# The wiki container speaks plain HTTP on the compose network. "wiki" is
|
|
18
|
+
# the compose service name; 3008 is the default WIKI_PORT (override both
|
|
19
|
+
# together if you change it).
|
|
20
|
+
upstream blamejs_wiki {
|
|
21
|
+
server wiki:3008;
|
|
22
|
+
keepalive 16;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
# Port 80 — ACME HTTP-01 challenge (certbot webroot) plus a permanent
|
|
26
|
+
# redirect of everything else to HTTPS.
|
|
27
|
+
server {
|
|
28
|
+
listen 80;
|
|
29
|
+
listen [::]:80;
|
|
30
|
+
server_name blamejs.com www.blamejs.com;
|
|
31
|
+
|
|
32
|
+
location /.well-known/acme-challenge/ {
|
|
33
|
+
root /var/www/certbot;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
location / {
|
|
37
|
+
return 308 https://blamejs.com$request_uri;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# Canonicalize www.blamejs.com → apex over TLS (308 preserves method/body).
|
|
42
|
+
server {
|
|
43
|
+
# `http2` as a listen parameter works on packaged nginx back to 1.9.5;
|
|
44
|
+
# the standalone `http2 on;` directive is 1.25.1+ only.
|
|
45
|
+
listen 443 ssl http2;
|
|
46
|
+
listen [::]:443 ssl http2;
|
|
47
|
+
server_name www.blamejs.com;
|
|
48
|
+
|
|
49
|
+
ssl_certificate /etc/letsencrypt/live/blamejs.com/fullchain.pem;
|
|
50
|
+
ssl_certificate_key /etc/letsencrypt/live/blamejs.com/privkey.pem;
|
|
51
|
+
ssl_protocols TLSv1.3;
|
|
52
|
+
|
|
53
|
+
return 308 https://blamejs.com$request_uri;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# Apex — TLS termination + reverse proxy to the wiki container.
|
|
57
|
+
server {
|
|
58
|
+
# `http2` as a listen parameter works on packaged nginx back to 1.9.5;
|
|
59
|
+
# the standalone `http2 on;` directive is 1.25.1+ only.
|
|
60
|
+
listen 443 ssl http2;
|
|
61
|
+
listen [::]:443 ssl http2;
|
|
62
|
+
server_name blamejs.com;
|
|
63
|
+
|
|
64
|
+
ssl_certificate /etc/letsencrypt/live/blamejs.com/fullchain.pem;
|
|
65
|
+
ssl_certificate_key /etc/letsencrypt/live/blamejs.com/privkey.pem;
|
|
66
|
+
|
|
67
|
+
# TLS 1.3 floor, matching the Caddyfile.
|
|
68
|
+
ssl_protocols TLSv1.3;
|
|
69
|
+
ssl_prefer_server_ciphers off;
|
|
70
|
+
ssl_session_timeout 1d;
|
|
71
|
+
ssl_session_cache shared:blamejs_tls:10m;
|
|
72
|
+
|
|
73
|
+
# HSTS two years, subdomains, preload — matches the wiki's own
|
|
74
|
+
# production posture so the header is present even on the proxy edge.
|
|
75
|
+
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
|
|
76
|
+
|
|
77
|
+
location / {
|
|
78
|
+
proxy_pass http://blamejs_wiki;
|
|
79
|
+
proxy_http_version 1.1;
|
|
80
|
+
|
|
81
|
+
# Tell the wiki it is behind TLS so its same-origin / CSRF /
|
|
82
|
+
# cookie-Secure logic trusts the edge. WIKI_ADMIN_TRUSTED_PROXIES
|
|
83
|
+
# must include this proxy's address for these to be honored.
|
|
84
|
+
proxy_set_header X-Forwarded-Proto https;
|
|
85
|
+
proxy_set_header X-Forwarded-For $remote_addr;
|
|
86
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
87
|
+
proxy_set_header Host $host;
|
|
88
|
+
|
|
89
|
+
# WebSocket / SSE upgrades used by the wiki's live islands.
|
|
90
|
+
proxy_set_header Connection $connection_upgrade;
|
|
91
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
92
|
+
proxy_read_timeout 300s;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# Docker captures stdout/stderr.
|
|
96
|
+
access_log /dev/stdout;
|
|
97
|
+
error_log /dev/stderr;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# Map for the Connection header on WebSocket upgrades. Place this in the
|
|
101
|
+
# http {} context (it is included here for a self-contained reference; if
|
|
102
|
+
# your main nginx.conf already defines $connection_upgrade, drop this map).
|
|
103
|
+
map $http_upgrade $connection_upgrade {
|
|
104
|
+
default upgrade;
|
|
105
|
+
'' close;
|
|
106
|
+
}
|
|
@@ -372,6 +372,98 @@ async function run() {
|
|
|
372
372
|
assert("POST /login with bad CSRF body mentions mismatch",
|
|
373
373
|
/CSRF token mismatch/i.test(badCsrf.body));
|
|
374
374
|
|
|
375
|
+
// ---- Age-gate demo route (b.middleware.ageGate through the wired stack) ----
|
|
376
|
+
// /age-check derives the age from ?age= via Number(). A value that
|
|
377
|
+
// fails to parse (Number("unknowable") → NaN) must classify as
|
|
378
|
+
// "unknown" and carry the child-safety privacy defaults through the
|
|
379
|
+
// live securityHeaders/compression/rate-limit chain — NOT be
|
|
380
|
+
// admitted as an adult. These header assertions run on the wired
|
|
381
|
+
// HTTP response, so a middleware later in the chain clobbering the
|
|
382
|
+
// gate's headers fails here too.
|
|
383
|
+
var ageUnknown = await _request({
|
|
384
|
+
method: "GET", host: "127.0.0.1", port: port, path: "/age-check?age=unknowable",
|
|
385
|
+
headers: BROWSER_HEADERS,
|
|
386
|
+
});
|
|
387
|
+
assert("GET /age-check?age=unknowable → 200", ageUnknown.statusCode === 200);
|
|
388
|
+
assert("unparseable age (NaN) classified unknown (X-Privacy-Posture: unknown)",
|
|
389
|
+
ageUnknown.headers["x-privacy-posture"] === "unknown");
|
|
390
|
+
assert("unparseable age gets Cache-Control: private, no-store",
|
|
391
|
+
ageUnknown.headers["cache-control"] === "private, no-store");
|
|
392
|
+
assert("unparseable age gets Referrer-Policy: no-referrer",
|
|
393
|
+
ageUnknown.headers["referrer-policy"] === "no-referrer");
|
|
394
|
+
assert("unparseable age body reports unknown classification",
|
|
395
|
+
/"classification"\s*:\s*"unknown"/.test(ageUnknown.body));
|
|
396
|
+
|
|
397
|
+
var ageBelow = await _request({
|
|
398
|
+
method: "GET", host: "127.0.0.1", port: port, path: "/age-check?age=10",
|
|
399
|
+
headers: BROWSER_HEADERS,
|
|
400
|
+
});
|
|
401
|
+
assert("GET /age-check?age=10 → 200", ageBelow.statusCode === 200);
|
|
402
|
+
assert("below-threshold age classified below-threshold",
|
|
403
|
+
ageBelow.headers["x-privacy-posture"] === "below-threshold");
|
|
404
|
+
assert("below-threshold age gets Cache-Control: private, no-store",
|
|
405
|
+
ageBelow.headers["cache-control"] === "private, no-store");
|
|
406
|
+
assert("below-threshold age gets Referrer-Policy: no-referrer",
|
|
407
|
+
ageBelow.headers["referrer-policy"] === "no-referrer");
|
|
408
|
+
assert("below-threshold age body reports below-threshold classification",
|
|
409
|
+
/"classification"\s*:\s*"below-threshold"/.test(ageBelow.body));
|
|
410
|
+
|
|
411
|
+
var ageAbove = await _request({
|
|
412
|
+
method: "GET", host: "127.0.0.1", port: port, path: "/age-check?age=30",
|
|
413
|
+
headers: BROWSER_HEADERS,
|
|
414
|
+
});
|
|
415
|
+
assert("GET /age-check?age=30 → 200", ageAbove.statusCode === 200);
|
|
416
|
+
assert("above-threshold age carries no X-Privacy-Posture header",
|
|
417
|
+
ageAbove.headers["x-privacy-posture"] === undefined);
|
|
418
|
+
assert("above-threshold age is not forced private/no-store",
|
|
419
|
+
(ageAbove.headers["cache-control"] || "") !== "private, no-store");
|
|
420
|
+
assert("above-threshold age body reports above-threshold classification",
|
|
421
|
+
/"classification"\s*:\s*"above-threshold"/.test(ageAbove.body));
|
|
422
|
+
|
|
423
|
+
// ---- Host-header path injection through the wired router ----
|
|
424
|
+
// The dispatched route must be a pure function of the request
|
|
425
|
+
// target: a path-like Host header (Host: trusted/admin) must not
|
|
426
|
+
// bleed its "/admin" segment into route matching. A vulnerable
|
|
427
|
+
// router composes "http://trusted/admin" + "/welcome" and dispatches
|
|
428
|
+
// "/admin/welcome" — the public page vanishes (404) and path-scoped
|
|
429
|
+
// admin guards see a path the request line never named. Assert the
|
|
430
|
+
// PUBLIC page is served unchanged and the admin auth gate never
|
|
431
|
+
// engages.
|
|
432
|
+
var hostInject = await _request({
|
|
433
|
+
method: "GET", host: "127.0.0.1", port: port, path: "/welcome",
|
|
434
|
+
headers: Object.assign({}, BROWSER_HEADERS, { host: "trusted/admin" }),
|
|
435
|
+
});
|
|
436
|
+
assert("GET /welcome with Host: trusted/admin → 200 (public page, not rerouted)",
|
|
437
|
+
hostInject.statusCode === 200);
|
|
438
|
+
var hostInjectH1 = hostInject.body.match(/<h1[^>]*>([\s\S]*?)<\/h1>/);
|
|
439
|
+
assert("path-like Host still serves the public welcome page (h1 Welcome)",
|
|
440
|
+
hostInjectH1 !== null && /Welcome/.test(hostInjectH1[1]));
|
|
441
|
+
assert("path-like Host does not engage the admin auth gate (no 401)",
|
|
442
|
+
hostInject.statusCode !== 401 && !/Sign in/i.test(hostInject.body));
|
|
443
|
+
|
|
444
|
+
// X-Forwarded-Host variant — the e2e boot trusts loopback as a
|
|
445
|
+
// reverse proxy, so a forwarded host is the worst case: even then
|
|
446
|
+
// the forwarded value must not steer routing.
|
|
447
|
+
var xfhInject = await _request({
|
|
448
|
+
method: "GET", host: "127.0.0.1", port: port, path: "/welcome",
|
|
449
|
+
headers: Object.assign({}, BROWSER_HEADERS, { "x-forwarded-host": "trusted/admin" }),
|
|
450
|
+
});
|
|
451
|
+
assert("GET /welcome with X-Forwarded-Host: trusted/admin → 200 (public page)",
|
|
452
|
+
xfhInject.statusCode === 200);
|
|
453
|
+
var xfhInjectH1 = xfhInject.body.match(/<h1[^>]*>([\s\S]*?)<\/h1>/);
|
|
454
|
+
assert("forwarded path-like host still serves the public welcome page",
|
|
455
|
+
xfhInjectH1 !== null && /Welcome/.test(xfhInjectH1[1]));
|
|
456
|
+
|
|
457
|
+
// Control: /admin stays auth-gated under a benign Host — the
|
|
458
|
+
// injection probes above pass because the Host is ignored for
|
|
459
|
+
// routing, not because the admin gate went missing.
|
|
460
|
+
var adminBenignHost = await _request({
|
|
461
|
+
method: "GET", host: "127.0.0.1", port: port, path: "/admin",
|
|
462
|
+
headers: Object.assign({}, BROWSER_HEADERS, { host: "trusted" }),
|
|
463
|
+
});
|
|
464
|
+
assert("control: GET /admin under a benign Host stays auth-gated (401)",
|
|
465
|
+
adminBenignHost.statusCode === 401);
|
|
466
|
+
|
|
375
467
|
// ---- Static asset checks ----
|
|
376
468
|
var prismJs = await _request({
|
|
377
469
|
method: "GET", host: "127.0.0.1", port: port, path: "/vendor/prism.js",
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) blamejs contributors
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
var asn1 = require("../lib/asn1-der");
|
|
6
|
+
var expected = require("./_expected");
|
|
7
|
+
|
|
8
|
+
// asn1-der is the DER byte parser under every untrusted-certificate path in the
|
|
9
|
+
// framework -- peer TLS certificates, S/MIME, BIMI VMCs, CMS, ACME and TSA
|
|
10
|
+
// responses. readNode / readSequence take raw adversarial bytes and MUST refuse
|
|
11
|
+
// malformed input with a typed Asn1Error, never crash with an uncaught
|
|
12
|
+
// RangeError / TypeError or blow the stack on deep nesting.
|
|
13
|
+
module.exports.fuzz = function (data) {
|
|
14
|
+
var node = null;
|
|
15
|
+
try {
|
|
16
|
+
node = asn1.readNode(data, 0);
|
|
17
|
+
} catch (e) {
|
|
18
|
+
if (!expected.isExpected(e)) throw e;
|
|
19
|
+
}
|
|
20
|
+
try { asn1.readSequence(data); }
|
|
21
|
+
catch (e) { if (!expected.isExpected(e)) throw e; }
|
|
22
|
+
if (node) {
|
|
23
|
+
[asn1.readOid, asn1.readOctetString, asn1.readUnsignedInt, asn1.readBitString].forEach(function (rd) {
|
|
24
|
+
try { rd(node); }
|
|
25
|
+
catch (e) { if (!expected.isExpected(e)) throw e; }
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) blamejs contributors
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
var b = require("..");
|
|
6
|
+
var expected = require("./_expected");
|
|
7
|
+
|
|
8
|
+
// b.cms parses CMS SignedData / EnvelopedData from untrusted DER (S/MIME
|
|
9
|
+
// messages, signed timestamps, enveloped payloads) on top of asn1-der. decode /
|
|
10
|
+
// parseSignedData MUST refuse a malformed structure with a typed cms/* error,
|
|
11
|
+
// never crash with an uncaught RangeError / TypeError.
|
|
12
|
+
module.exports.fuzz = function (data) {
|
|
13
|
+
try { b.cms.decode(data); }
|
|
14
|
+
catch (e) { if (!expected.isExpected(e)) throw e; }
|
|
15
|
+
try { b.cms.parseSignedData(data); }
|
|
16
|
+
catch (e) { if (!expected.isExpected(e)) throw e; }
|
|
17
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) blamejs contributors
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
var b = require("..");
|
|
6
|
+
var expected = require("./_expected");
|
|
7
|
+
|
|
8
|
+
// b.linkHeader.parse consumes an untrusted HTTP Link response-header string
|
|
9
|
+
// (RFC 8288) -- a server (or an SSRF-reachable origin) fully controls it. It
|
|
10
|
+
// MUST refuse a malformed header with a typed error or a benign return, never
|
|
11
|
+
// crash with an uncaught error or hang.
|
|
12
|
+
module.exports.fuzz = function (data) {
|
|
13
|
+
var s;
|
|
14
|
+
try { s = data.toString("latin1"); }
|
|
15
|
+
catch (_e) { return; }
|
|
16
|
+
try { b.linkHeader.parse(s); }
|
|
17
|
+
catch (e) { if (!expected.isExpected(e)) throw e; }
|
|
18
|
+
};
|
|
@@ -128,6 +128,7 @@ var sql = require("./lib/sql");
|
|
|
128
128
|
var chainWriter = require("./lib/chain-writer");
|
|
129
129
|
var codepointClass = require("./lib/codepoint-class");
|
|
130
130
|
var safeBuffer = require("./lib/safe-buffer");
|
|
131
|
+
var safeObject = require("./lib/safe-object");
|
|
131
132
|
var safeDecompress = require("./lib/safe-decompress").safeDecompress;
|
|
132
133
|
var safeMountInfo = require("./lib/safe-mount-info");
|
|
133
134
|
var lazyRequire = require("./lib/lazy-require");
|
|
@@ -301,6 +302,10 @@ mail.rbl = require("./lib/mail-rbl");
|
|
|
301
302
|
mail.serverRegistry = require("./lib/mail-server-registry");
|
|
302
303
|
mail.send = mail.send || {};
|
|
303
304
|
mail.send.deliver = require("./lib/mail-send-deliver").create;
|
|
305
|
+
// Expose the documented `b.mail.send.deliver.create(opts)` factory form
|
|
306
|
+
// (its @signature / @example) alongside the collapsed callable so an
|
|
307
|
+
// operator following the docs reaches the same builder.
|
|
308
|
+
mail.send.deliver.create = require("./lib/mail-send-deliver").create;
|
|
304
309
|
mail.send.deliver.DeliverError = require("./lib/mail-send-deliver").DeliverError;
|
|
305
310
|
mail.greylist = require("./lib/mail-greylist");
|
|
306
311
|
mail.helo = require("./lib/mail-helo");
|
|
@@ -535,6 +540,7 @@ module.exports = {
|
|
|
535
540
|
chainWriter: chainWriter,
|
|
536
541
|
codepointClass: codepointClass,
|
|
537
542
|
safeBuffer: safeBuffer,
|
|
543
|
+
safeObject: safeObject,
|
|
538
544
|
safeDecompress: safeDecompress,
|
|
539
545
|
safeMountInfo: safeMountInfo,
|
|
540
546
|
lazyRequire: lazyRequire,
|
|
@@ -117,7 +117,7 @@ function _validateCardShape(card, errorClass) {
|
|
|
117
117
|
* `verifyCard` use the same canonicalizer internally.
|
|
118
118
|
*
|
|
119
119
|
* @example
|
|
120
|
-
* var b = require("blamejs")
|
|
120
|
+
* var b = require("blamejs");
|
|
121
121
|
* var bytes = b.a2a.canonicalize({
|
|
122
122
|
* issuer: "agent.example.com",
|
|
123
123
|
* agentId: "ops-bot-1",
|
|
@@ -159,7 +159,7 @@ function canonicalize(card) {
|
|
|
159
159
|
* }
|
|
160
160
|
*
|
|
161
161
|
* @example
|
|
162
|
-
* var b = require("blamejs")
|
|
162
|
+
* var b = require("blamejs");
|
|
163
163
|
* var card = b.a2a.createCard({
|
|
164
164
|
* issuer: "agent.example.com",
|
|
165
165
|
* agentId: "ops-bot-1",
|
|
@@ -209,7 +209,7 @@ function createCard(opts) {
|
|
|
209
209
|
* }
|
|
210
210
|
*
|
|
211
211
|
* @example
|
|
212
|
-
* var b = require("blamejs")
|
|
212
|
+
* var b = require("blamejs");
|
|
213
213
|
* var card = b.a2a.createCard({
|
|
214
214
|
* issuer: "agent.example.com",
|
|
215
215
|
* agentId: "ops-bot-1",
|
|
@@ -292,7 +292,7 @@ function signCard(card, privateKeyPem, opts) {
|
|
|
292
292
|
* }
|
|
293
293
|
*
|
|
294
294
|
* @example
|
|
295
|
-
* var b = require("blamejs")
|
|
295
|
+
* var b = require("blamejs");
|
|
296
296
|
* var result = b.a2a.verifyCard(envelope, peerPublicKeyPem, {
|
|
297
297
|
* expectedIssuer: "agent.example.com"
|
|
298
298
|
* });
|
|
@@ -249,9 +249,18 @@ async function _putIfAbsent(store, method, actorId, key, putOpts, ttlMs, maxResu
|
|
|
249
249
|
if (existing.status === "pending") {
|
|
250
250
|
return { alreadyClaimed: true, pending: true, firstAt: existing.firstAt };
|
|
251
251
|
}
|
|
252
|
-
// Completed cached result.
|
|
252
|
+
// Completed cached result. Unseal the result blob when a vault is
|
|
253
|
+
// configured — put() sealed it at rest via b.cryptoField, so parsing the
|
|
254
|
+
// raw sealed cell as JSON would throw. Mirrors _get's unseal path (same
|
|
255
|
+
// seal-table, same unseal call-site shape); vault-less / pre-sealing rows
|
|
256
|
+
// carry plain JSON and pass through unchanged.
|
|
257
|
+
var unsealed = existing;
|
|
258
|
+
if (vault().isInitialized()) {
|
|
259
|
+
_ensureSealTable();
|
|
260
|
+
unsealed = cryptoField().unsealRow(SEAL_TABLE, existing);
|
|
261
|
+
}
|
|
253
262
|
var result;
|
|
254
|
-
try { result = safeJson.parse(
|
|
263
|
+
try { result = safeJson.parse(unsealed.resultBlob, { maxBytes: maxResultBytes }); }
|
|
255
264
|
catch (e) {
|
|
256
265
|
throw new AgentIdempotencyError("agent-idempotency/corrupt-result",
|
|
257
266
|
"putIfAbsent: cached result failed to parse — " + (e && e.message ? e.message : String(e)));
|
|
@@ -280,6 +289,13 @@ async function _get(store, method, actorId, key, auditImpl, ttlMs, maxResultByte
|
|
|
280
289
|
{ method: method, actorIdHash: _truncHash(_actorIdHash(actorId)) });
|
|
281
290
|
return null;
|
|
282
291
|
}
|
|
292
|
+
// A pending row (claimed via putIfAbsent, no result written yet) carries a
|
|
293
|
+
// null resultBlob — there is no cached result to return. Report absent
|
|
294
|
+
// rather than feeding null to safeJson.parse, which throws corrupt-result.
|
|
295
|
+
// get() is a public status-check path and putIfAbsent produces pending rows,
|
|
296
|
+
// so a concurrent claim must not turn a peer's get() into a spurious throw;
|
|
297
|
+
// a later put() replaces the pending row with the completed result.
|
|
298
|
+
if (row.resultBlob === null || row.resultBlob === undefined) return null;
|
|
283
299
|
// Unseal the result blob into a copy (when a vault is configured;
|
|
284
300
|
// vault-less or pre-sealing rows are plain JSON and used as-is). The
|
|
285
301
|
// original sealed `row` is preserved so the replay-count re-put below
|
|
@@ -115,10 +115,15 @@ function create(config) {
|
|
|
115
115
|
// Interface: { saveStep, loadResumePoint, markCompleted, markFailed }.
|
|
116
116
|
// saveStep({sagaId, stepIndex, stepName, state, status}) commits
|
|
117
117
|
// after each step.run; loadResumePoint(sagaId) returns the resume
|
|
118
|
-
// shape `{ stepIndex, state }` on restart
|
|
119
|
-
//
|
|
120
|
-
//
|
|
121
|
-
//
|
|
118
|
+
// shape `{ stepIndex, state }` on restart — and, for a saga that already
|
|
119
|
+
// reached a terminal state, SHOULD set `terminal: true` (or return null)
|
|
120
|
+
// after markFailed / markCompleted so a resume of a failed-and-compensated
|
|
121
|
+
// (or completed) saga is refused rather than replayed. Compensators MUST be
|
|
122
|
+
// idempotent: a crash mid-compensation-cascade (before markFailed persists)
|
|
123
|
+
// can replay a compensation on the next resume, so compensating twice must be
|
|
124
|
+
// safe. Without a stateStore, the saga still runs end-to-end in-memory but a
|
|
125
|
+
// mid-saga crash loses progress (operator-acknowledged dev mode; the audit
|
|
126
|
+
// emit `agent.saga.no_state_store` surfaces the posture per call).
|
|
122
127
|
var stateStore = config.stateStore || null;
|
|
123
128
|
if (stateStore !== null) {
|
|
124
129
|
validateOpts.requireMethods(stateStore, ["saveStep", "loadResumePoint"],
|
|
@@ -147,6 +152,21 @@ async function _resume(config, auditImpl, stateStore, sagaId, ctx, opts) {
|
|
|
147
152
|
throw new AgentSagaError("agent-saga/not-found",
|
|
148
153
|
"resume: no resume point for saga '" + sagaId + "'");
|
|
149
154
|
}
|
|
155
|
+
// A saga that already reached a terminal state — failed-and-compensated, or
|
|
156
|
+
// completed — must NOT be resumed. Replaying it re-runs the remaining steps
|
|
157
|
+
// AND, on a failure, re-invokes the completed steps' compensators (including
|
|
158
|
+
// the pre-crash steps this run seeds); compensators are not required to be
|
|
159
|
+
// idempotent, so a second compensation could corrupt external state (a double
|
|
160
|
+
// refund). A well-behaved stateStore marks the saga terminal via markFailed /
|
|
161
|
+
// markCompleted and reflects it here (resumePoint.terminal); refuse the resume
|
|
162
|
+
// when it does. The residual window — a crash after a compensation but before
|
|
163
|
+
// markFailed — is inherent at-least-once compensation and is why compensators
|
|
164
|
+
// MUST be idempotent (see the interface note on create()).
|
|
165
|
+
if (resumePoint.terminal === true) {
|
|
166
|
+
throw new AgentSagaError("agent-saga/not-resumable",
|
|
167
|
+
"resume: saga '" + sagaId + "' is terminal and cannot be resumed — " +
|
|
168
|
+
"replaying a failed/completed saga would re-invoke its compensators");
|
|
169
|
+
}
|
|
150
170
|
return _runFrom(config, auditImpl, stateStore, ctx,
|
|
151
171
|
resumePoint.state || {}, opts, sagaId, resumePoint.stepIndex);
|
|
152
172
|
}
|
|
@@ -158,11 +178,19 @@ async function _run(config, auditImpl, stateStore, ctx, initialState, opts) {
|
|
|
158
178
|
}
|
|
159
179
|
|
|
160
180
|
async function _runFrom(config, auditImpl, stateStore, ctx, state, opts, sagaId, startIndex) {
|
|
161
|
-
// completedSteps captures index + step reference
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
//
|
|
181
|
+
// completedSteps captures index + step reference for the reverse-order
|
|
182
|
+
// compensation cascade. On resume (startIndex > 0) the steps before
|
|
183
|
+
// startIndex were completed and committed BEFORE the crash; a failure in
|
|
184
|
+
// this run must still compensate them, or a saga that resumes and then
|
|
185
|
+
// fails leaves its pre-crash work uncompensated (a broken distributed-
|
|
186
|
+
// transaction guarantee — e.g. a charge committed pre-crash is never
|
|
187
|
+
// refunded when a later step fails). Seed those prior steps so the cascade
|
|
188
|
+
// unwinds the FULL completed set, not only this run's steps. Compensation
|
|
189
|
+
// runs against the resumed state, which already reflects their effects.
|
|
165
190
|
var completedSteps = [];
|
|
191
|
+
for (var pre = 0; pre < startIndex; pre += 1) {
|
|
192
|
+
completedSteps.push({ step: config.steps[pre], index: pre });
|
|
193
|
+
}
|
|
166
194
|
|
|
167
195
|
if (startIndex === 0) {
|
|
168
196
|
agentAudit.safeAudit(auditImpl, "agent.saga.started", opts.actor, {
|
|
@@ -457,9 +457,12 @@ async function _persist(ctx, snap) {
|
|
|
457
457
|
snap.sigPubKey = (typeof signer.getPublicKey === "function" && signer.getPublicKey()) || null;
|
|
458
458
|
|
|
459
459
|
// Seal the entire envelope under AAD that pins
|
|
460
|
-
//
|
|
460
|
+
// table + snapshotId + schemaVersion. AAD mismatch on unseal (a
|
|
461
461
|
// copy-paste attack from one snapshotId's row into another) fails
|
|
462
|
-
// the Poly1305 tag check; tampered bytes also fail. The
|
|
462
|
+
// the Poly1305 tag check; tampered bytes also fail. The tenantId is
|
|
463
|
+
// authenticated by the signature (it is a signed field) and the
|
|
464
|
+
// wrapper's decorative tenantId is cross-checked against the signed
|
|
465
|
+
// body at load, so it is not additionally bound in the AAD. The sealed
|
|
463
466
|
// string is what reaches durable storage.
|
|
464
467
|
var sealer = _resolveSealer(ctx);
|
|
465
468
|
var serialized = safeJson.stringify(snap);
|
|
@@ -475,7 +478,9 @@ async function _persist(ctx, snap) {
|
|
|
475
478
|
// implementation needs to filter by tenantId / takenAt without
|
|
476
479
|
// having to unseal every row. Sealed-blob carries the full
|
|
477
480
|
// envelope; the metadata is decorative + may be tamper-fuzzed by
|
|
478
|
-
// a hostile backend
|
|
481
|
+
// a hostile backend. snapshotId is bound by the AAD (unseal fails on
|
|
482
|
+
// a swap) and tenantId is cross-checked against the signed body at
|
|
483
|
+
// load, so a relabelled wrapper is refused rather than trusted.
|
|
479
484
|
stored = {
|
|
480
485
|
snapshotId: snap.snapshotId,
|
|
481
486
|
takenAt: snap.takenAt,
|
|
@@ -547,6 +552,31 @@ async function _unwrapAndVerify(ctx, raw, expectedId) {
|
|
|
547
552
|
throw new AgentSnapshotError("agent-snapshot/snapshot-id-mismatch",
|
|
548
553
|
"load: wrapper snapshotId='" + expectedId + "' does not match envelope='" + snap.snapshotId + "'");
|
|
549
554
|
}
|
|
555
|
+
// The wrapper's decorative tenantId is what the backend's list() /
|
|
556
|
+
// loadLatest tenant filter selects on, but it is NOT bound by the seal's
|
|
557
|
+
// AAD (which pins table + snapshotId + schemaVersion). A hostile backend
|
|
558
|
+
// can therefore relabel a sealed row's wrapper tenantId while the
|
|
559
|
+
// Poly1305 tag still verifies — so loadLatest({ tenantId }) would return
|
|
560
|
+
// a DIFFERENT tenant's authentic snapshot (cross-tenant restore).
|
|
561
|
+
// Cross-check the untrusted wrapper tenantId against the signed body's
|
|
562
|
+
// tenantId and refuse the mismatch, mirroring the snapshotId gate above;
|
|
563
|
+
// the inner value is the authentic one (covered by the signature).
|
|
564
|
+
if ((raw.tenantId || null) !== (snap.tenantId || null)) {
|
|
565
|
+
throw new AgentSnapshotError("agent-snapshot/tenant-id-mismatch",
|
|
566
|
+
"load: wrapper tenantId='" + (raw.tenantId || null) +
|
|
567
|
+
"' does not match envelope tenantId='" + (snap.tenantId || null) + "'");
|
|
568
|
+
}
|
|
569
|
+
// Same class as the tenantId/snapshotId gates: the wrapper takenAt is the
|
|
570
|
+
// field loadLatest sorts on to pick "latest", but it is not AAD-bound, so a
|
|
571
|
+
// hostile backend could relabel a returned row's age (misrepresenting when
|
|
572
|
+
// the restored state was captured — an audit-integrity / rollback signal).
|
|
573
|
+
// takenAt is a signed body field, so cross-check the untrusted wrapper value
|
|
574
|
+
// against it and refuse a divergence; the inner value is the authentic one.
|
|
575
|
+
if ((raw.takenAt || null) !== (snap.takenAt || null)) {
|
|
576
|
+
throw new AgentSnapshotError("agent-snapshot/taken-at-mismatch",
|
|
577
|
+
"load: wrapper takenAt='" + (raw.takenAt || null) +
|
|
578
|
+
"' does not match envelope takenAt='" + (snap.takenAt || null) + "'");
|
|
579
|
+
}
|
|
550
580
|
// Verify the signature before returning the envelope
|
|
551
581
|
// to the caller. Restore-side trust derives from this gate. The
|
|
552
582
|
// allowPlaintext escape hatch (operator-acknowledged dev mode)
|
|
@@ -595,9 +625,36 @@ async function _loadLatest(ctx, loadOpts) {
|
|
|
595
625
|
});
|
|
596
626
|
if (filtered.length === 0) return null;
|
|
597
627
|
filtered.sort(function (a, b) { return (b.takenAt || 0) - (a.takenAt || 0); });
|
|
598
|
-
var
|
|
599
|
-
var raw = await ctx.backend.get(
|
|
600
|
-
|
|
628
|
+
var selected = filtered[0];
|
|
629
|
+
var raw = await ctx.backend.get(selected.snapshotId);
|
|
630
|
+
var snap = await _unwrapAndVerify(ctx, raw, selected.snapshotId);
|
|
631
|
+
// list() and get() are independently-tamperable untrusted backend surfaces.
|
|
632
|
+
// _unwrapAndVerify only proves the get() wrapper agrees with the signed body;
|
|
633
|
+
// it does NOT prove the list() metadata used to FILTER and SELECT this row is
|
|
634
|
+
// honest. A backend that relabels tenant A's list() entry as tenant B while
|
|
635
|
+
// leaving A's get() row untouched would pass that wrapper/body check yet
|
|
636
|
+
// still surface A's authentic snapshot for a tenant-B query. So bind the
|
|
637
|
+
// REQUESTED selection criteria to the authenticated body: the loaded signed
|
|
638
|
+
// tenantId must equal the requested tenantId.
|
|
639
|
+
if (loadOpts.tenantId && (snap.tenantId || null) !== loadOpts.tenantId) {
|
|
640
|
+
throw new AgentSnapshotError("agent-snapshot/tenant-id-mismatch",
|
|
641
|
+
"loadLatest: requested tenantId='" + loadOpts.tenantId +
|
|
642
|
+
"' does not match the loaded snapshot's authenticated tenantId='" +
|
|
643
|
+
(snap.tenantId || null) + "'");
|
|
644
|
+
}
|
|
645
|
+
// The list() sort key that selected this row must match its authenticated
|
|
646
|
+
// takenAt, so a backend cannot inflate a row's list() age to win the "latest"
|
|
647
|
+
// sort while get() returns the honest (older) body. A backend can still
|
|
648
|
+
// withhold or reorder rows it never reveals -- an inherent freshness limit of
|
|
649
|
+
// an untrusted store -- but every RETURNED snapshot is authentic, tenant-
|
|
650
|
+
// bound, and carries its own authenticated capture time.
|
|
651
|
+
if ((selected.takenAt || null) !== (snap.takenAt || null)) {
|
|
652
|
+
throw new AgentSnapshotError("agent-snapshot/taken-at-mismatch",
|
|
653
|
+
"loadLatest: list() takenAt='" + (selected.takenAt || null) +
|
|
654
|
+
"' for the selected snapshot does not match its authenticated takenAt='" +
|
|
655
|
+
(snap.takenAt || null) + "'");
|
|
656
|
+
}
|
|
657
|
+
return snap;
|
|
601
658
|
}
|
|
602
659
|
|
|
603
660
|
async function _loadById(ctx, snapshotId) {
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
|
|
46
46
|
var safeAsync = require("./safe-async");
|
|
47
47
|
var numericBounds = require("./numeric-bounds");
|
|
48
|
+
var pidProbe = require("./pid-probe");
|
|
48
49
|
var validateOpts = require("./validate-opts");
|
|
49
50
|
var tracing = null;
|
|
50
51
|
try { tracing = require("./tracing"); } catch (_e) { /* tracing optional */ }
|
|
@@ -547,35 +548,37 @@ function pidLock(lockPath) {
|
|
|
547
548
|
var fd = null;
|
|
548
549
|
var ownsLock = false;
|
|
549
550
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
catch (e) { return e.code === "EPERM"; } // EPERM means process exists, just no rights
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
function _readExisting() {
|
|
557
|
-
try {
|
|
558
|
-
// fd-safe + capped + symlink-refusing read: a PID lockfile is never a
|
|
559
|
-
// legitimate symlink (unlike a k8s/certbot secret mount), so refuseSymlink
|
|
560
|
-
// is safe here and stops a planted symlink/oversized file from redirecting
|
|
561
|
-
// or OOM-ing the read. Any throw (symlink/too-large/enoent) → null, the
|
|
562
|
-
// existing "no live lock" semantic.
|
|
563
|
-
var raw = atomicFile.fdSafeReadSync(lockPath, { maxBytes: C.BYTES.kib(1), refuseSymlink: true, encoding: "utf8" });
|
|
564
|
-
var pid = parseInt(String(raw).trim(), 10);
|
|
565
|
-
return isFinite(pid) && pid > 0 ? pid : null;
|
|
566
|
-
} catch (_e) { return null; }
|
|
567
|
-
}
|
|
551
|
+
// Signal-0 liveness probe + fd-safe pidfile reader are the shared
|
|
552
|
+
// lib/pid-probe primitive (b.daemon carried a byte-identical copy).
|
|
553
|
+
function _readExisting() { return pidProbe.readPidFile(lockPath); }
|
|
568
554
|
|
|
569
555
|
function acquire() {
|
|
570
556
|
if (ownsLock) return;
|
|
571
557
|
nodeFs.mkdirSync(nodePath.dirname(lockPath), { recursive: true });
|
|
572
558
|
var existing = _readExisting();
|
|
573
|
-
if (existing &&
|
|
559
|
+
if (existing && pidProbe.isLivePid(existing) && existing !== process.pid) {
|
|
574
560
|
throw new AppShutdownError("app-shutdown/pidlock-held",
|
|
575
561
|
"pidLock: '" + lockPath + "' already held by live PID " + existing);
|
|
576
562
|
}
|
|
563
|
+
if (existing === process.pid) {
|
|
564
|
+
// The lockfile already records OUR PID — a parent wrote it and handed off,
|
|
565
|
+
// or start() re-acquires after leaving its own live pidfile. ADOPT the
|
|
566
|
+
// existing inode in place: the reap path below would unlink + O_EXCL-
|
|
567
|
+
// recreate, opening a no-pidfile window a concurrent daemon.stop misreads
|
|
568
|
+
// as "no-pidfile". openNoFollowSync holds the inode (a symlink at lockPath
|
|
569
|
+
// is refused with ELOOP) so we own the lock without ever removing the
|
|
570
|
+
// file. release() closes this fd + unlinks as usual.
|
|
571
|
+
try {
|
|
572
|
+
fd = atomicFile.openNoFollowSync(lockPath);
|
|
573
|
+
} catch (e) {
|
|
574
|
+
throw new AppShutdownError("app-shutdown/pidlock-open-failed",
|
|
575
|
+
"pidLock: failed to adopt self-held '" + lockPath + "': " + e.message);
|
|
576
|
+
}
|
|
577
|
+
ownsLock = true;
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
577
580
|
if (existing) {
|
|
578
|
-
// Stale lock — owner is dead. Reap.
|
|
581
|
+
// Stale lock — owner is dead (foreign PID that is no longer live). Reap.
|
|
579
582
|
try { nodeFs.unlinkSync(lockPath); } catch (_e) { /* race: someone else reaped it */ }
|
|
580
583
|
}
|
|
581
584
|
try {
|
|
@@ -606,6 +606,14 @@ async function _decompressEntry(adapter, entry, dataStart, bombPolicy) {
|
|
|
606
606
|
algorithm: "deflate-raw",
|
|
607
607
|
maxOutputBytes: maxOutput,
|
|
608
608
|
maxCompressedBytes: entry.compressedSize,
|
|
609
|
+
// Honor the reader's own expansion-ratio cap. Without this, the
|
|
610
|
+
// composition inherits safeDecompress's DEFAULT_MAX_RATIO (50),
|
|
611
|
+
// which silently overrides bombPolicy.maxExpansionRatio and refuses
|
|
612
|
+
// every entry compressing better than 50:1 even when the operator's
|
|
613
|
+
// policy (default 100) permits it. The declared-size ratio was
|
|
614
|
+
// already validated in _enforceBombPolicy; this re-check on the
|
|
615
|
+
// actual inflated bytes uses the SAME configured cap.
|
|
616
|
+
maxRatio: bombPolicy.maxExpansionRatio,
|
|
609
617
|
});
|
|
610
618
|
if (decompressed.length !== entry.uncompressedSize) {
|
|
611
619
|
throw new ArchiveReadError("archive-read/inflate-size-mismatch",
|