@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
|
@@ -31,8 +31,17 @@
|
|
|
31
31
|
* `b.appShutdown.pidLock`, which layers O_EXCL atomic-create +
|
|
32
32
|
* signal-0 liveness probe + reap-on-stale.
|
|
33
33
|
*
|
|
34
|
+
* On Windows a received signal can never reach a JS handler
|
|
35
|
+
* (process.kill maps it to TerminateProcess), so `stop` drives a
|
|
36
|
+
* cooperative stop-request sentinel (`<pidFile>.stop`) that `start`
|
|
37
|
+
* watches and routes into the same orchestrator, escalating to a hard
|
|
38
|
+
* TerminateProcess only after the stop timeout. `status` is a read-only
|
|
39
|
+
* liveness probe that never mutates the pidfile.
|
|
40
|
+
*
|
|
34
41
|
* Audit events: `daemon.started` (pidFile + logFile + commandKind +
|
|
35
|
-
* pid), `daemon.stopped` (pidFile + signal + waitMs + escalated
|
|
42
|
+
* pid), `daemon.stopped` (pidFile + signal + waitMs + escalated +
|
|
43
|
+
* mechanism: signal|cooperative|terminate), `daemon.spawn_failed`
|
|
44
|
+
* (pidFile + command) when a detached child fails to launch, and
|
|
36
45
|
* `daemon.stale_pid_cleaned` (pidFile + stalePid).
|
|
37
46
|
*
|
|
38
47
|
* @card
|
|
@@ -43,6 +52,7 @@ var nodeFs = require("node:fs");
|
|
|
43
52
|
var nodePath = require("node:path");
|
|
44
53
|
var numericBounds = require("./numeric-bounds");
|
|
45
54
|
var appShutdown = require("./app-shutdown");
|
|
55
|
+
var pidProbe = require("./pid-probe");
|
|
46
56
|
var processSpawn = require("./process-spawn");
|
|
47
57
|
var safeAsync = require("./safe-async");
|
|
48
58
|
var atomicFile = require("./atomic-file");
|
|
@@ -62,27 +72,23 @@ var DEFAULT_STOP_TIMEOUT_MS = C.TIME.seconds(30);
|
|
|
62
72
|
var DEFAULT_STOP_SIGNAL = "SIGTERM";
|
|
63
73
|
var DEFAULT_POLL_MS = 100;
|
|
64
74
|
var DEFAULT_LOG_FILE_MODE = 0o600;
|
|
75
|
+
// Poll cadence for the Windows cooperative-stop sentinel (a synchronous
|
|
76
|
+
// existsSync on this interval; see _installStopSentinelWatcher for why it is a
|
|
77
|
+
// poll and not a filesystem watch). Runs for a foreground daemon's whole
|
|
78
|
+
// lifetime, so it is coarser than DEFAULT_POLL_MS (which only polls during the
|
|
79
|
+
// brief stop window); 250ms keeps graceful-stop detection sub-second at
|
|
80
|
+
// negligible idle cost.
|
|
81
|
+
var STOP_SENTINEL_POLL_MS = 250;
|
|
65
82
|
|
|
66
83
|
function _safeAuditEmit(action, outcome, metadata) {
|
|
67
84
|
auditEmit.emit(action, metadata, outcome);
|
|
68
85
|
}
|
|
69
86
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
function _readPidFile(pidFile) {
|
|
77
|
-
try {
|
|
78
|
-
// Same fd-safe + capped + symlink-refusing read as app-shutdown's lockfile
|
|
79
|
-
// reader (one shape): a PID file is never a legit symlink mount, so
|
|
80
|
-
// refuseSymlink is safe; any throw → null ("nothing live there").
|
|
81
|
-
var raw = atomicFile.fdSafeReadSync(pidFile, { maxBytes: C.BYTES.kib(1), refuseSymlink: true, encoding: "utf8" });
|
|
82
|
-
var pid = parseInt(String(raw).trim(), 10);
|
|
83
|
-
return isFinite(pid) && pid > 0 ? pid : null;
|
|
84
|
-
} catch (_e) { return null; }
|
|
85
|
-
}
|
|
87
|
+
// Signal-0 liveness probe + fd-safe pidfile reader live in lib/pid-probe.js so
|
|
88
|
+
// b.daemon and b.appShutdown.pidLock share ONE implementation (they carried
|
|
89
|
+
// byte-identical copies). Local aliases keep the call sites terse.
|
|
90
|
+
var _isLivePid = pidProbe.isLivePid;
|
|
91
|
+
var _readPidFile = pidProbe.readPidFile;
|
|
86
92
|
|
|
87
93
|
function _validateStartOpts(opts) {
|
|
88
94
|
validateOpts.shape(opts, {
|
|
@@ -100,6 +106,8 @@ function _validateStartOpts(opts) {
|
|
|
100
106
|
},
|
|
101
107
|
command: { rule: "optional-string", code: "daemon/bad-command",
|
|
102
108
|
label: "daemon.start: opts.command (path to executable)" },
|
|
109
|
+
cwd: { rule: "optional-string", code: "daemon/bad-cwd",
|
|
110
|
+
label: "daemon.start: opts.cwd (working directory for the detached child)" },
|
|
103
111
|
args: function (value) {
|
|
104
112
|
if (value !== undefined && !Array.isArray(value)) {
|
|
105
113
|
throw new DaemonError("daemon/bad-args",
|
|
@@ -130,6 +138,13 @@ function _validateStopOpts(opts) {
|
|
|
130
138
|
}, "daemon.stop", DaemonError, "daemon/bad-opts");
|
|
131
139
|
}
|
|
132
140
|
|
|
141
|
+
function _validateStatusOpts(opts) {
|
|
142
|
+
validateOpts.shape(opts, {
|
|
143
|
+
pidFile: { rule: "required-string", code: "daemon/bad-pid-file",
|
|
144
|
+
label: "daemon.status: opts.pidFile" },
|
|
145
|
+
}, "daemon.status", DaemonError, "daemon/bad-opts");
|
|
146
|
+
}
|
|
147
|
+
|
|
133
148
|
function _maybeReapStale(pidFile) {
|
|
134
149
|
var existing = _readPidFile(pidFile);
|
|
135
150
|
if (existing === null) return false;
|
|
@@ -185,6 +200,85 @@ function _redirectStdio(fd) {
|
|
|
185
200
|
// start() in the same process don't double-install signals.
|
|
186
201
|
var _foregroundOrchestrators = Object.create(null);
|
|
187
202
|
|
|
203
|
+
// Sibling-sentinel path a cooperative stop request is written to. Kept beside
|
|
204
|
+
// the pidFile so it inherits the same operator-owned directory + permissions.
|
|
205
|
+
function _stopSentinelPath(pidFile) {
|
|
206
|
+
return pidFile + ".stop";
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Remove a cooperative stop sentinel (best-effort — it may already be gone, or
|
|
210
|
+
// never have existed on the POSIX path). unlink removes the LINK, not a target.
|
|
211
|
+
function _cleanupSentinel(sentinelPath) {
|
|
212
|
+
try { nodeFs.unlinkSync(sentinelPath); } catch (_e) { /* best-effort — may not exist */ }
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Install the Windows cooperative-stop watcher for a foreground daemon. Fires
|
|
216
|
+
// the orchestrator's graceful shutdown the first time the sibling <pidFile>.stop
|
|
217
|
+
// sentinel appears — the same orchestrator.shutdown() the POSIX signal path
|
|
218
|
+
// drives, so the exit code is set from the phase result and the event loop
|
|
219
|
+
// drains once the phases release the daemon's resources.
|
|
220
|
+
//
|
|
221
|
+
// Detection is a synchronous existsSync on a plain unref'd interval, NOT a
|
|
222
|
+
// filesystem watch, for two Windows-specific reasons:
|
|
223
|
+
// - fs.watch (libuv ReadDirectoryChangesW) aborts the whole process — an
|
|
224
|
+
// uncatchable src/win/fs-event.c assertion, "!_wcsnicmp(filename, dir,
|
|
225
|
+
// dirlen)" — when the watched directory is reached through an 8.3
|
|
226
|
+
// short-name path, exactly the shape of a CI runner's temp dir
|
|
227
|
+
// (C:\Users\RUNNER~1\AppData\Local\Temp\...): GetFinalPathNameByHandle
|
|
228
|
+
// returns the long form and the prefix check fails. A try/catch cannot
|
|
229
|
+
// recover from an abort().
|
|
230
|
+
// - fs.watchFile's StatWatcher stats through the libuv threadpool, which
|
|
231
|
+
// starves under heavy concurrent filesystem load and delays detection by
|
|
232
|
+
// seconds; a synchronous existsSync runs inline on the main thread and is
|
|
233
|
+
// immune.
|
|
234
|
+
// The interval is unref'd so it never itself keeps the process alive; a clean
|
|
235
|
+
// daemon exits on its own once shutdown completes. If the sentinel is never
|
|
236
|
+
// written the poll is a no-op the release phase clears at shutdown. Returns a
|
|
237
|
+
// handle exposing close().
|
|
238
|
+
function _installStopSentinelWatcher(pidFile, orchestrator) {
|
|
239
|
+
var dir = nodePath.dirname(pidFile);
|
|
240
|
+
var sentinelName = nodePath.basename(pidFile) + ".stop";
|
|
241
|
+
var sentinelPath = nodePath.join(dir, sentinelName);
|
|
242
|
+
var fired = false;
|
|
243
|
+
var timer = null;
|
|
244
|
+
function _stopPolling() {
|
|
245
|
+
if (!timer) return;
|
|
246
|
+
try { clearInterval(timer); } catch (_e) { /* best-effort */ }
|
|
247
|
+
timer = null;
|
|
248
|
+
}
|
|
249
|
+
function _maybeFire() {
|
|
250
|
+
if (fired) return;
|
|
251
|
+
// Synchronous existsSync on the main thread — deliberately not an async
|
|
252
|
+
// stat, so detection never queues behind a saturated libuv threadpool.
|
|
253
|
+
if (!nodeFs.existsSync(sentinelPath)) return;
|
|
254
|
+
fired = true;
|
|
255
|
+
_stopPolling();
|
|
256
|
+
log("cooperative stop-request observed (" + sentinelPath + ") — initiating graceful shutdown");
|
|
257
|
+
// Mirror the POSIX signal path: run the orchestrator's phases, derive the
|
|
258
|
+
// exit code from the result, then let the loop drain (a foreground daemon's
|
|
259
|
+
// phases release its server/db so the process exits on its own).
|
|
260
|
+
Promise.resolve(orchestrator.shutdown()).then(function (result) {
|
|
261
|
+
if (process.exitCode === undefined || process.exitCode === 0) {
|
|
262
|
+
process.exitCode = (result && result.ok) ? 0 : 1;
|
|
263
|
+
}
|
|
264
|
+
}).catch(function () { process.exitCode = 1; });
|
|
265
|
+
}
|
|
266
|
+
try {
|
|
267
|
+
timer = setInterval(_maybeFire, STOP_SENTINEL_POLL_MS);
|
|
268
|
+
if (timer && typeof timer.unref === "function") timer.unref();
|
|
269
|
+
} catch (_e) {
|
|
270
|
+
// Timer scheduling unavailable — no cooperative channel; daemon.stop()
|
|
271
|
+
// still hard-stops via TerminateProcess after its timeout.
|
|
272
|
+
timer = null;
|
|
273
|
+
}
|
|
274
|
+
// The sentinel may already exist (stop() raced ahead of this install).
|
|
275
|
+
_maybeFire();
|
|
276
|
+
return {
|
|
277
|
+
close: function () { _stopPolling(); },
|
|
278
|
+
sentinelPath: sentinelPath,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
188
282
|
/**
|
|
189
283
|
* @primitive b.daemon.start
|
|
190
284
|
* @signature b.daemon.start(opts)
|
|
@@ -284,6 +378,33 @@ function start(opts) {
|
|
|
284
378
|
throw new DaemonError("daemon/spawn-failed",
|
|
285
379
|
"daemon.start: spawn failed: " + ((e && e.message) || String(e)));
|
|
286
380
|
}
|
|
381
|
+
// A bad command does NOT throw synchronously from spawn — child_process
|
|
382
|
+
// reports it ASYNC via a 'error' event, with child.pid left undefined. The
|
|
383
|
+
// sync try/catch above only covers spawn() itself, so without this the old
|
|
384
|
+
// path wrote "undefined\n" to the pidFile and returned success. Subscribe a
|
|
385
|
+
// one-shot 'error' handler that reaps the sidecar + audits the failure, then
|
|
386
|
+
// refuse to proceed for a child that never got a pid.
|
|
387
|
+
child.on("error", function (err) {
|
|
388
|
+
try { nodeFs.unlinkSync(pidFile); } catch (_e) { /* best-effort — may not exist */ }
|
|
389
|
+
_safeAuditEmit("daemon.spawn_failed", "failure", {
|
|
390
|
+
pidFile: pidFile,
|
|
391
|
+
command: opts.command,
|
|
392
|
+
error: (err && err.message) || String(err),
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
// child.pid must be a real, positive PID. A command that failed to launch
|
|
396
|
+
// leaves it undefined; the same positive-integer front-guard the shared
|
|
397
|
+
// liveness probe (pidProbe.isLivePid) applies before it will signal a pid —
|
|
398
|
+
// a non-number / non-finite / non-positive value is never a launched child.
|
|
399
|
+
// Fail closed BEFORE any pidfile write so no "undefined" sidecar survives
|
|
400
|
+
// for daemon.stop to misread.
|
|
401
|
+
if (typeof child.pid !== "number" || !isFinite(child.pid) || child.pid <= 0) {
|
|
402
|
+
try { if (typeof logFd === "number") nodeFs.closeSync(logFd); }
|
|
403
|
+
catch (_c) { /* best-effort */ }
|
|
404
|
+
throw new DaemonError("daemon/spawn-failed",
|
|
405
|
+
"daemon.start: spawn of '" + opts.command + "' produced no pid (the command " +
|
|
406
|
+
"failed to launch)");
|
|
407
|
+
}
|
|
287
408
|
// Write the child's PID via atomic temp+rename so a concurrent
|
|
288
409
|
// observer never sees a half-written pidFile.
|
|
289
410
|
atomicFile.ensureDir(nodePath.dirname(pidFile));
|
|
@@ -332,6 +453,15 @@ function start(opts) {
|
|
|
332
453
|
}
|
|
333
454
|
}
|
|
334
455
|
|
|
456
|
+
// Cooperative stop channel (Windows). Node maps process.kill(pid, "SIGTERM")
|
|
457
|
+
// to TerminateProcess on win32, so a "signal" never reaches a JS handler and
|
|
458
|
+
// the graceful orchestrator would be unreachable. daemon.stop() writes a
|
|
459
|
+
// sibling <pidFile>.stop sentinel; a watcher installed below routes it into
|
|
460
|
+
// the SAME orchestrator.shutdown() the POSIX signal path uses. Assigned after
|
|
461
|
+
// the orchestrator exists; the release phase (which runs at shutdown) closes
|
|
462
|
+
// it + removes the sentinel.
|
|
463
|
+
var stopWatcher = null;
|
|
464
|
+
|
|
335
465
|
var orchestrator = appShutdown.create({
|
|
336
466
|
signals: signals,
|
|
337
467
|
installSignalHandlers: true,
|
|
@@ -339,16 +469,21 @@ function start(opts) {
|
|
|
339
469
|
{
|
|
340
470
|
name: "pidLock-release",
|
|
341
471
|
run: function () {
|
|
472
|
+
if (stopWatcher) { try { stopWatcher.close(); } catch (_w) { /* best-effort */ } }
|
|
342
473
|
try { lock.release(); } catch (_e) { /* best-effort */ }
|
|
343
474
|
if (logFdForeground !== null) {
|
|
344
475
|
try { nodeFs.closeSync(logFdForeground); } catch (_c) { /* best-effort */ }
|
|
345
476
|
}
|
|
477
|
+
_cleanupSentinel(_stopSentinelPath(pidFile));
|
|
346
478
|
},
|
|
347
479
|
timeoutMs: C.TIME.seconds(2),
|
|
348
480
|
},
|
|
349
481
|
],
|
|
350
482
|
});
|
|
351
483
|
_foregroundOrchestrators[pidFile] = orchestrator;
|
|
484
|
+
if (process.platform === "win32") {
|
|
485
|
+
stopWatcher = _installStopSentinelWatcher(pidFile, orchestrator);
|
|
486
|
+
}
|
|
352
487
|
|
|
353
488
|
_safeAuditEmit("daemon.started", "success", {
|
|
354
489
|
pidFile: pidFile,
|
|
@@ -421,16 +556,26 @@ async function stop(opts) {
|
|
|
421
556
|
}
|
|
422
557
|
|
|
423
558
|
var t0 = Date.now();
|
|
424
|
-
|
|
559
|
+
|
|
560
|
+
// Windows has no cooperative signal: process.kill(pid, "SIGTERM") maps to
|
|
561
|
+
// TerminateProcess (a hard kill), so the graceful appShutdown orchestration is
|
|
562
|
+
// only reachable via the cooperative stop-request sentinel start() watches.
|
|
563
|
+
// Drive that channel first and escalate to the hard kill only on timeout.
|
|
564
|
+
if (process.platform === "win32") {
|
|
565
|
+
return await _stopWin32Cooperative(pidFile, pid, signal, timeoutMs, pollMs, t0, opts);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// POSIX signal path — first signal (typically SIGTERM), wait up to timeoutMs
|
|
569
|
+
// for exit, then escalate to SIGKILL. mechanism is always "signal" here.
|
|
425
570
|
try { process.kill(pid, signal); }
|
|
426
571
|
catch (e) {
|
|
427
572
|
if (e && e.code === "ESRCH") {
|
|
428
573
|
// Died between read and kill — cleanup + report.
|
|
429
574
|
try { nodeFs.unlinkSync(pidFile); } catch (_u) { /* best-effort */ }
|
|
430
575
|
_safeAuditEmit("daemon.stopped", "success", {
|
|
431
|
-
pidFile: pidFile, signal: signal, waitMs: Date.now() - t0, escalated: false,
|
|
576
|
+
pidFile: pidFile, signal: signal, waitMs: Date.now() - t0, escalated: false, mechanism: "signal",
|
|
432
577
|
});
|
|
433
|
-
return { stopped: true, pid: pid, signal: signal };
|
|
578
|
+
return { stopped: true, pid: pid, signal: signal, mechanism: "signal" };
|
|
434
579
|
}
|
|
435
580
|
throw new DaemonError("daemon/kill-failed",
|
|
436
581
|
"daemon.stop: kill(" + pid + ", " + signal + ") failed: " + e.message);
|
|
@@ -441,9 +586,9 @@ async function stop(opts) {
|
|
|
441
586
|
if (!_isLivePid(pid)) {
|
|
442
587
|
try { nodeFs.unlinkSync(pidFile); } catch (_u) { /* best-effort */ }
|
|
443
588
|
_safeAuditEmit("daemon.stopped", "success", {
|
|
444
|
-
pidFile: pidFile, signal: signal, waitMs: Date.now() - t0, escalated: false,
|
|
589
|
+
pidFile: pidFile, signal: signal, waitMs: Date.now() - t0, escalated: false, mechanism: "signal",
|
|
445
590
|
});
|
|
446
|
-
return { stopped: true, pid: pid, signal: signal };
|
|
591
|
+
return { stopped: true, pid: pid, signal: signal, mechanism: "signal" };
|
|
447
592
|
}
|
|
448
593
|
await safeAsync.sleep(pollMs, { signal: opts.abortSignal });
|
|
449
594
|
}
|
|
@@ -464,9 +609,109 @@ async function stop(opts) {
|
|
|
464
609
|
}
|
|
465
610
|
try { nodeFs.unlinkSync(pidFile); } catch (_u) { /* best-effort */ }
|
|
466
611
|
_safeAuditEmit("daemon.stopped", "success", {
|
|
467
|
-
pidFile: pidFile, signal: "SIGKILL", waitMs: Date.now() - t0, escalated: true,
|
|
612
|
+
pidFile: pidFile, signal: "SIGKILL", waitMs: Date.now() - t0, escalated: true, mechanism: "signal",
|
|
613
|
+
});
|
|
614
|
+
return { stopped: true, pid: pid, signal: "SIGKILL", escalated: true, mechanism: "signal" };
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// Windows cooperative stop. Writes the sibling <pidFile>.stop sentinel the
|
|
618
|
+
// foreground start() watcher routes into the graceful orchestrator, polls for a
|
|
619
|
+
// clean exit up to timeoutMs, and escalates to a hard TerminateProcess (Windows
|
|
620
|
+
// maps any real signal to it) ONLY on timeout — preserving the POSIX
|
|
621
|
+
// graceful-first / forced-on-timeout shape and the same brief post-kill reap
|
|
622
|
+
// wait. mechanism distinguishes the cooperative exit from the forced one; the
|
|
623
|
+
// sentinel is removed on both paths.
|
|
624
|
+
async function _stopWin32Cooperative(pidFile, pid, signal, timeoutMs, pollMs, t0, opts) {
|
|
625
|
+
var sentinel = _stopSentinelPath(pidFile);
|
|
626
|
+
// O_NOFOLLOW-staged write (atomicFile.writeSync → _openExclTemp with
|
|
627
|
+
// O_EXCL | O_NOFOLLOW) so a symlink planted at <pidFile>.stop can't redirect
|
|
628
|
+
// the request to an attacker-chosen file (CWE-59).
|
|
629
|
+
try {
|
|
630
|
+
atomicFile.writeSync(sentinel, String(pid) + "\n", { fileMode: 0o600 });
|
|
631
|
+
} catch (e) {
|
|
632
|
+
throw new DaemonError("daemon/stop-request-failed",
|
|
633
|
+
"daemon.stop: failed to write cooperative stop-request '" + sentinel + "': " +
|
|
634
|
+
((e && e.message) || String(e)));
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// Poll for cooperative exit up to timeoutMs.
|
|
638
|
+
var deadline = t0 + timeoutMs;
|
|
639
|
+
while (Date.now() < deadline) {
|
|
640
|
+
if (!_isLivePid(pid)) {
|
|
641
|
+
_cleanupSentinel(sentinel);
|
|
642
|
+
try { nodeFs.unlinkSync(pidFile); } catch (_u) { /* best-effort */ }
|
|
643
|
+
_safeAuditEmit("daemon.stopped", "success", {
|
|
644
|
+
pidFile: pidFile, signal: signal, waitMs: Date.now() - t0, escalated: false, mechanism: "cooperative",
|
|
645
|
+
});
|
|
646
|
+
return { stopped: true, pid: pid, signal: signal, mechanism: "cooperative" };
|
|
647
|
+
}
|
|
648
|
+
await safeAsync.sleep(pollMs, { signal: opts.abortSignal });
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// Timed out — the daemon ignored the cooperative request. Hard-stop it.
|
|
652
|
+
try { process.kill(pid, "SIGKILL"); }
|
|
653
|
+
catch (e) {
|
|
654
|
+
if (!(e && e.code === "ESRCH")) {
|
|
655
|
+
_cleanupSentinel(sentinel);
|
|
656
|
+
throw new DaemonError("daemon/kill-failed",
|
|
657
|
+
"daemon.stop: TerminateProcess escalation failed for pid " + pid + ": " + e.message);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
var killDeadline = Date.now() + C.TIME.seconds(2);
|
|
661
|
+
while (Date.now() < killDeadline) {
|
|
662
|
+
if (!_isLivePid(pid)) break;
|
|
663
|
+
await safeAsync.sleep(pollMs, { signal: opts.abortSignal });
|
|
664
|
+
}
|
|
665
|
+
_cleanupSentinel(sentinel);
|
|
666
|
+
try { nodeFs.unlinkSync(pidFile); } catch (_u) { /* best-effort */ }
|
|
667
|
+
_safeAuditEmit("daemon.stopped", "success", {
|
|
668
|
+
pidFile: pidFile, signal: "SIGKILL", waitMs: Date.now() - t0, escalated: true, mechanism: "terminate",
|
|
468
669
|
});
|
|
469
|
-
return { stopped: true, pid: pid, signal: "SIGKILL", escalated: true };
|
|
670
|
+
return { stopped: true, pid: pid, signal: "SIGKILL", escalated: true, mechanism: "terminate" };
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* @primitive b.daemon.status
|
|
675
|
+
* @signature b.daemon.status(opts)
|
|
676
|
+
* @since 0.17.13
|
|
677
|
+
* @status stable
|
|
678
|
+
* @related b.daemon.start, b.daemon.stop
|
|
679
|
+
*
|
|
680
|
+
* Read-only PID-liveness probe. Reads `pidFile` and reports whether the
|
|
681
|
+
* recorded process is alive, WITHOUT mutating anything — unlike `stop()`,
|
|
682
|
+
* a stale pidfile is reported but never unlinked, so a health check can't
|
|
683
|
+
* disturb the daemon's lifecycle state. A missing / malformed / symlinked /
|
|
684
|
+
* oversized pidfile reports `running: false` with `reason: "no-pidfile"`
|
|
685
|
+
* rather than throwing (the same fd-safe, symlink-refusing, 1 KiB-capped
|
|
686
|
+
* read that `start` and `stop` use). Bad opts throw `daemon/bad-pid-file`.
|
|
687
|
+
*
|
|
688
|
+
* Returns `{ running, pid, reason? }`. `reason` is `"no-pidfile"` when no
|
|
689
|
+
* live sidecar was found and `"stale"` when the pidfile pointed at a dead
|
|
690
|
+
* PID — the file is left in place for the operator to inspect or for `stop`
|
|
691
|
+
* to reap.
|
|
692
|
+
*
|
|
693
|
+
* @opts
|
|
694
|
+
* pidFile: string, // absolute path of the PID sidecar (required)
|
|
695
|
+
*
|
|
696
|
+
* @example
|
|
697
|
+
* var s = b.daemon.status({ pidFile: "/tmp/blamejs-daemon-demo.pid" });
|
|
698
|
+
* s.running; // → false
|
|
699
|
+
* s.reason; // → "no-pidfile"
|
|
700
|
+
*/
|
|
701
|
+
function status(opts) {
|
|
702
|
+
_validateStatusOpts(opts);
|
|
703
|
+
var pidFile = opts.pidFile;
|
|
704
|
+
var pid = _readPidFile(pidFile);
|
|
705
|
+
if (pid === null) {
|
|
706
|
+
// Missing / malformed / symlinked / oversized — nothing live to report.
|
|
707
|
+
// READ-ONLY: never unlink (stop() reaps; status() must not).
|
|
708
|
+
return { running: false, pid: null, reason: "no-pidfile" };
|
|
709
|
+
}
|
|
710
|
+
if (!_isLivePid(pid)) {
|
|
711
|
+
// Recorded PID is dead. Report it but leave the sidecar in place.
|
|
712
|
+
return { running: false, pid: pid, reason: "stale" };
|
|
713
|
+
}
|
|
714
|
+
return { running: true, pid: pid };
|
|
470
715
|
}
|
|
471
716
|
|
|
472
717
|
// Test-only — drop process-wide foreground orchestrator state so smoke
|
|
@@ -483,6 +728,7 @@ function _resetForTest() {
|
|
|
483
728
|
module.exports = {
|
|
484
729
|
start: start,
|
|
485
730
|
stop: stop,
|
|
731
|
+
status: status,
|
|
486
732
|
DaemonError: DaemonError,
|
|
487
733
|
DEFAULT_STOP_SIGNAL: DEFAULT_STOP_SIGNAL,
|
|
488
734
|
DEFAULT_STOP_TIMEOUT_MS: DEFAULT_STOP_TIMEOUT_MS,
|
|
@@ -266,11 +266,14 @@ function assertParity(signup, cancel, opts) {
|
|
|
266
266
|
"darkPatterns.assertParity: resourceId differs between flows");
|
|
267
267
|
}
|
|
268
268
|
var postureName = opts.posture || "ftc-2024";
|
|
269
|
-
|
|
270
|
-
|
|
269
|
+
// Own-property lookup: postureName is operator input, so a bare
|
|
270
|
+
// `POSTURES[postureName]` with a truthiness guard would let a prototype key
|
|
271
|
+
// ("constructor") resolve to an inherited member and run under it (fail-open).
|
|
272
|
+
if (!Object.prototype.hasOwnProperty.call(POSTURES, postureName)) {
|
|
271
273
|
throw errorClass.factory("dark-patterns/bad-posture",
|
|
272
274
|
"darkPatterns.assertParity: unknown posture " + postureName);
|
|
273
275
|
}
|
|
276
|
+
var posture = POSTURES[postureName];
|
|
274
277
|
|
|
275
278
|
var toleranceClicks = typeof opts.toleranceClicks === "number"
|
|
276
279
|
? opts.toleranceClicks : posture.toleranceClicks;
|
|
@@ -359,7 +359,7 @@ function declareView(opts) {
|
|
|
359
359
|
// Build CREATE VIEW. Each column is independently quoted so a
|
|
360
360
|
// reserved-word column name (e.g. "user", "order") resolves correctly.
|
|
361
361
|
var quotedCols = selectedColumns.map(function (c) {
|
|
362
|
-
return safeSql.quoteIdentifier(c, "postgres");
|
|
362
|
+
return safeSql.quoteIdentifier(c, "postgres", { allowReserved: true }); // reserved-word column names (e.g. "user"/"order") — parity with b.db.from()
|
|
363
363
|
}).join(", ");
|
|
364
364
|
var createSql = "CREATE VIEW " + qView + " AS SELECT " + quotedCols +
|
|
365
365
|
" FROM " + qSource;
|
|
@@ -370,7 +370,7 @@ function declareView(opts) {
|
|
|
370
370
|
// GRANT SELECT — one statement covers all roles.
|
|
371
371
|
if (spec.grantTo.length > 0) {
|
|
372
372
|
var quotedRoles = spec.grantTo.map(function (r) {
|
|
373
|
-
return safeSql.quoteIdentifier(r, "postgres");
|
|
373
|
+
return safeSql.quoteIdentifier(r, "postgres", { allowReserved: true }); // parity with b.db.from()
|
|
374
374
|
}).join(", ");
|
|
375
375
|
await xdb.query(
|
|
376
376
|
"GRANT SELECT ON " + qView + " TO " + quotedRoles,
|
|
@@ -1430,6 +1430,29 @@ function _stripLeadingSqlComments(sql) {
|
|
|
1430
1430
|
return s;
|
|
1431
1431
|
}
|
|
1432
1432
|
|
|
1433
|
+
// _normalizeForWriteParse — the single parse-copy normalizer the residency
|
|
1434
|
+
// write-detection regexes run against. The regexes hand-roll SQL tokenization
|
|
1435
|
+
// with `\s+` (whitespace-separated) token boundaries, but SQL lets two tokens
|
|
1436
|
+
// abut with NO whitespace whenever a comment or a quoted-identifier boundary
|
|
1437
|
+
// separates them — so a real write escaped the whitespace-strict detection
|
|
1438
|
+
// entirely (the gate was skipped → a cross-border write landed ungated):
|
|
1439
|
+
//
|
|
1440
|
+
// an INSERT whose quoted table name abuts INTO with no space
|
|
1441
|
+
// an INSERT with a slash-star comment wedged between INSERT and INTO
|
|
1442
|
+
// an UPDATE with a slash-star comment wedged between UPDATE and the table
|
|
1443
|
+
//
|
|
1444
|
+
// All are valid SQLite (the engine tokenizes the comment / quote as a
|
|
1445
|
+
// separator), so the executed statement writes rows while `_rawWriteTable`
|
|
1446
|
+
// returned null and the gate never engaged (CWE-863; GDPR Art. 44-46 transfer
|
|
1447
|
+
// restriction bypass). safeSql.normalizeForScan produces a parse-only copy
|
|
1448
|
+
// where every token boundary is real whitespace (comments collapsed to a space,
|
|
1449
|
+
// a separating space inserted where a quoted token abuts a word character);
|
|
1450
|
+
// leading comments then strip so the ^-anchored regexes see the statement head.
|
|
1451
|
+
// The executed SQL is unchanged; this copy only feeds the gate's parse.
|
|
1452
|
+
function _normalizeForWriteParse(sql) {
|
|
1453
|
+
return _stripLeadingSqlComments(safeSql.normalizeForScan(sql));
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1433
1456
|
// Non-anchored write-target scan for the writable-CTE / EXPLAIN-prefixed case.
|
|
1434
1457
|
// A SQLite `WITH c AS (...) INSERT INTO residents ...` / `WITH ... UPDATE residents
|
|
1435
1458
|
// SET ...` is a real write, but its effective verb is hidden behind the prefix so
|
|
@@ -1452,10 +1475,12 @@ function _firstResidencyWriteTarget(s) {
|
|
|
1452
1475
|
}
|
|
1453
1476
|
|
|
1454
1477
|
function _rawWriteTable(sql) {
|
|
1455
|
-
// The ^-anchored regexes scan only the statement head (constant-time).
|
|
1456
|
-
//
|
|
1478
|
+
// The ^-anchored regexes scan only the statement head (constant-time).
|
|
1479
|
+
// Normalize first so a leading OR internal comment, and a quoted table that
|
|
1480
|
+
// abuts the keyword with no whitespace, can't hide the write from the
|
|
1481
|
+
// whitespace-anchored detection (a gate-skip → cross-border-write bypass).
|
|
1457
1482
|
if (typeof sql !== "string") return null;
|
|
1458
|
-
var s =
|
|
1483
|
+
var s = _normalizeForWriteParse(sql);
|
|
1459
1484
|
if (_RAW_WRITE_KEYWORD_RE.test(s)) { // allow:regex-no-length-cap
|
|
1460
1485
|
var m = _RAW_TABLE_RE.exec(s); // allow:regex-no-length-cap
|
|
1461
1486
|
return m ? _unquoteIdent(m[1] || m[2]) : null;
|
|
@@ -1546,11 +1571,13 @@ function _assertRawWriteResidency(sql, boundParams) {
|
|
|
1546
1571
|
if (!cryptoField.getPerRowResidency(table) && !cryptoField.getColumnResidency(table)) return;
|
|
1547
1572
|
boundParams = _flattenRunParams(boundParams);
|
|
1548
1573
|
|
|
1549
|
-
//
|
|
1550
|
-
//
|
|
1551
|
-
//
|
|
1574
|
+
// Normalize the parse copy the same way engagement did: a leading OR internal
|
|
1575
|
+
// comment, and a quoted table/column that abuts the keyword with no whitespace,
|
|
1576
|
+
// must not hide the INSERT/UPDATE body from the whitespace-anchored regexes
|
|
1577
|
+
// below (that would let a residency-restricted write parse as unmodelled and,
|
|
1578
|
+
// for the value it can't read, skip the tag check). The executed SQL is
|
|
1552
1579
|
// unchanged; this normalized copy is only for residency parsing.
|
|
1553
|
-
var norm =
|
|
1580
|
+
var norm = _normalizeForWriteParse(sql);
|
|
1554
1581
|
|
|
1555
1582
|
// The INSERT/UPDATE body regexes below scan with [\s\S]+; bound the input
|
|
1556
1583
|
// first and fail CLOSED on an over-long statement - a residency write the
|
|
@@ -1877,15 +1877,19 @@ function stream(sql) {
|
|
|
1877
1877
|
objectMode: true,
|
|
1878
1878
|
read: function () {
|
|
1879
1879
|
try {
|
|
1880
|
+
var step = iter.next();
|
|
1881
|
+
if (step.done) { this.push(null); return; }
|
|
1882
|
+
// Enforce the cap AFTER pulling the row + the done-check: a result set of
|
|
1883
|
+
// EXACTLY streamLimit rows completes cleanly; only a row BEYOND the cap
|
|
1884
|
+
// (the streamLimit+1'th) trips the guard (the top-of-read `>=` form errored
|
|
1885
|
+
// at == limit, turning a valid complete export into a stream error).
|
|
1880
1886
|
if (emitted >= perCallLimit) {
|
|
1881
1887
|
this.destroy(new DbError("db/stream-limit-exceeded",
|
|
1882
|
-
"db.stream:
|
|
1883
|
-
|
|
1888
|
+
"db.stream: result set exceeds streamLimit " + perCallLimit +
|
|
1889
|
+
" (reached row " + (emitted + 1) + "). Pass opts.streamLimit higher OR raise via " +
|
|
1884
1890
|
"db.init({ streamLimit }) after auditing the export path."));
|
|
1885
1891
|
return;
|
|
1886
1892
|
}
|
|
1887
|
-
var step = iter.next();
|
|
1888
|
-
if (step.done) { this.push(null); return; }
|
|
1889
1893
|
emitted += 1;
|
|
1890
1894
|
var row = step.value;
|
|
1891
1895
|
this.push(unseal ? unseal.unsealRow(table, row) : row);
|
|
@@ -2207,7 +2211,10 @@ function exportCsv(opts) {
|
|
|
2207
2211
|
validateOpts.requireNonEmptyString(opts.table, "exportCsv: opts.table", DbError, "db/bad-export-table");
|
|
2208
2212
|
// Quote-validate the table identifier — refuses anything with embedded
|
|
2209
2213
|
// quotes, schema-qualified names valid via dot-separated parts.
|
|
2210
|
-
|
|
2214
|
+
// allowReserved: parity with b.db.from() — a schema-valid operator table
|
|
2215
|
+
// whose name is a SQL keyword must validate here too (still fails closed on
|
|
2216
|
+
// shape/length/null-byte/sqlite_ prefix; the keyword is safe once quoted).
|
|
2217
|
+
safeSql.quoteIdentifier(opts.table, undefined, { allowReserved: true });
|
|
2211
2218
|
var meta = tableMetadata[opts.table];
|
|
2212
2219
|
if (!meta) {
|
|
2213
2220
|
throw new DbError("db/unknown-table",
|
|
@@ -2251,7 +2258,12 @@ function exportCsv(opts) {
|
|
|
2251
2258
|
var col = columns[cj];
|
|
2252
2259
|
var v = src[col];
|
|
2253
2260
|
if (timestampFields.indexOf(col) !== -1 && typeof v === "number" && isFinite(v)) {
|
|
2254
|
-
|
|
2261
|
+
// A finite ms value outside ±8.64e15 (JS Date's representable range)
|
|
2262
|
+
// yields an Invalid Date whose toISOString() throws RangeError. Degrade
|
|
2263
|
+
// to the raw numeric string so one garbage timestamp value can't crash
|
|
2264
|
+
// the whole export.
|
|
2265
|
+
var ts = new Date(v);
|
|
2266
|
+
out[cj] = isNaN(ts.getTime()) ? String(v) : ts.toISOString();
|
|
2255
2267
|
} else if (Buffer.isBuffer(v)) {
|
|
2256
2268
|
out[cj] = v.toString("base64");
|
|
2257
2269
|
} else if (v === null || v === undefined) {
|
|
@@ -47,6 +47,15 @@ var DbscError = defineClass("DbscError", { alwaysPermanent: true });
|
|
|
47
47
|
|
|
48
48
|
var DEFAULT_CHALLENGE_TTL_MS = C.TIME.minutes(5);
|
|
49
49
|
|
|
50
|
+
// Clock-skew allowance for a forward-dated `iat`. An assertion whose iat
|
|
51
|
+
// sits further ahead than this is refused: without an upper bound a future
|
|
52
|
+
// iat makes the stale check (Date.now() - iat*1000 > maxAge) permanently
|
|
53
|
+
// false, so the assertion never expires and the maxAge replay window is
|
|
54
|
+
// defeated. Mirrors the future-iat bound in b.auth.jwt.verifyExternal
|
|
55
|
+
// (iat-future) and dpop's ±window; sized to tolerate ordinary client clock
|
|
56
|
+
// drift without admitting a far-future token.
|
|
57
|
+
var IAT_FUTURE_SKEW_MS = C.TIME.minutes(1);
|
|
58
|
+
|
|
50
59
|
/**
|
|
51
60
|
* @primitive b.dbsc.challenge
|
|
52
61
|
* @signature b.dbsc.challenge(opts)
|
|
@@ -243,6 +252,14 @@ function verifyBindingAssertion(assertion, opts) {
|
|
|
243
252
|
throw new DbscError("dbsc/stale",
|
|
244
253
|
"verifyBindingAssertion: iat is more than " + opts.maxAgeSec + "s old");
|
|
245
254
|
}
|
|
255
|
+
// Upper-bound iat: a forward-dated assertion (beyond IAT_FUTURE_SKEW_MS)
|
|
256
|
+
// is refused. A future iat makes the stale check above never fire, so the
|
|
257
|
+
// assertion would stay "fresh" indefinitely — a freshness fail-open on an
|
|
258
|
+
// attacker-chosen iat that defeats the maxAge replay bound.
|
|
259
|
+
if (typeof payloadJson.iat === "number" && payloadJson.iat * 1000 - Date.now() > IAT_FUTURE_SKEW_MS) { // allow:raw-time-literal — sec→ms
|
|
260
|
+
throw new DbscError("dbsc/iat-future",
|
|
261
|
+
"verifyBindingAssertion: iat is more than " + (IAT_FUTURE_SKEW_MS / C.TIME.seconds(1)) + "s in the future");
|
|
262
|
+
}
|
|
246
263
|
// Re-verify any embedded challenge if the assertion claims one.
|
|
247
264
|
if (payloadJson.challenge) {
|
|
248
265
|
verifyChallenge(payloadJson.challenge, { secretKey: opts.secretKey });
|
|
@@ -200,7 +200,11 @@ function create(opts) {
|
|
|
200
200
|
return childProcess().spawn(cmd, sargs, sopts);
|
|
201
201
|
};
|
|
202
202
|
var watchFn = opts._watch || function (dir, wopts, listener) {
|
|
203
|
-
|
|
203
|
+
// realpathSync.native expands an 8.3 short-name component before the watch;
|
|
204
|
+
// fs.watch aborts libuv (uncatchable) on a Windows short-name path.
|
|
205
|
+
var target = dir;
|
|
206
|
+
try { target = nodeFs.realpathSync.native(dir); } catch (_e) { /* keep raw path */ }
|
|
207
|
+
return nodeFs.watch(target, wopts, listener);
|
|
204
208
|
};
|
|
205
209
|
var setTimeoutFn = opts._setTimeout || setTimeout;
|
|
206
210
|
var clearTimeoutFn = opts._clearTimeout || clearTimeout;
|
|
@@ -251,14 +255,29 @@ function create(opts) {
|
|
|
251
255
|
if (killTimer) { try { clearTimeoutFn(killTimer); } catch (_e) { /* timer already cleared */ } killTimer = null; }
|
|
252
256
|
resolve();
|
|
253
257
|
}
|
|
258
|
+
// 'exit' is the only event that reliably means the process is gone, so
|
|
259
|
+
// it is the only one that completes shutdown. A child that FAILED TO
|
|
260
|
+
// SPAWN has no pid and never emits 'exit' — it is settled by the
|
|
261
|
+
// no-process check below, NOT by listening for 'error'/'close', which
|
|
262
|
+
// can also fire for a LIVE child (a rejected kill emits 'error' while
|
|
263
|
+
// the process keeps running) and must not complete shutdown then.
|
|
254
264
|
c.once("exit", done);
|
|
255
|
-
|
|
265
|
+
var sent;
|
|
266
|
+
try { sent = c.kill(killSignal); }
|
|
256
267
|
catch (e) {
|
|
257
268
|
_logVia(log, "warn", "kill threw, child may already be gone",
|
|
258
269
|
{ error: (e && e.message) || String(e) });
|
|
259
270
|
done();
|
|
260
271
|
return;
|
|
261
272
|
}
|
|
273
|
+
// kill() returning false means the signal was NOT delivered — which can
|
|
274
|
+
// be either "no process exists" (a child that failed to spawn has no
|
|
275
|
+
// pid; no 'exit' will ever arrive, so settle now) OR "a live process
|
|
276
|
+
// rejected the signal" (e.g. EPERM after the child changed credentials;
|
|
277
|
+
// pid is set). Only the no-process case completes shutdown here; a live
|
|
278
|
+
// child keeps the SIGKILL escalation + awaits exit/close, so stop()
|
|
279
|
+
// never falsely reports termination while the process is still running.
|
|
280
|
+
if (!sent && !c.pid) { done(); return; }
|
|
262
281
|
// Hard-kill if the child ignores SIGTERM
|
|
263
282
|
killTimer = setTimeoutFn(function () {
|
|
264
283
|
if (settled) return;
|