Production hardening, deployment docs, and dead signal cleanup#16
Merged
Conversation
Add cookieSecure option to all four middleware packages, allowing the Secure flag to be set on the session cookie. Defaults to false for local dev compatibility; set to true for HTTPS deployments. Add privacy and cookie consent section to getting-started guide covering GDPR, ePrivacy Directive, UK GDPR, CCPA/CPRA, and Brazil LGPD implications of collecting device capability signals.
RedisStorageAdapter now catches errors on all methods instead of letting them propagate. get() and exists() return safe defaults (null/false), set() and delete() silently degrade.
userAgent is collected by the probe for bot/crawler filtering but serves no purpose after that check. All four endpoints now strip it before persisting to storage. JSON schema and docs updated to reflect.
Viewport is only used for bot detection (presence check), not classification. Strip it alongside userAgent before persisting. Remove orphaned Viewport definition from JSON schema. Add comprehensive unit tests for isValidSignals covering all validation branches (was only testing battery paths).
Bump all packages to 0.3.0, finalize changelog, and switch publish workflow to extract release notes from CHANGELOG.md via ffurrer2/extract-release-notes@v3.
Merged
SimplyLiz
added a commit
that referenced
this pull request
Feb 23, 2026
* Add CI/CD quality gates and Dependabot config Enforce coverage thresholds in CI and publish, add security audit, version-tag validation, GitHub Release creation, and Dependabot for automated dependency updates targeting develop. * Split CI into separate lint, audit, and test jobs * Remove redundant push trigger for develop in CI * Add Node.js version label to test job names * Bump actions/setup-node from 4 to 6 (#3) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 6. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](actions/setup-node@v4...v6) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump actions/checkout from 4 to 6 (#4) Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@v4...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump esbuild from 0.25.12 to 0.27.3 in the dev-deps group (#5) Bumps the dev-deps group with 1 update: [esbuild](https://github.com/evanw/esbuild). Updates `esbuild` from 0.25.12 to 0.27.3 - [Release notes](https://github.com/evanw/esbuild/releases) - [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md) - [Commits](evanw/esbuild@v0.25.12...v0.27.3) --- updated-dependencies: - dependency-name: esbuild dependency-version: 0.27.3 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-deps ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump koa and @types/koa (#6) Bumps [koa](https://github.com/koajs/koa) and [@types/koa](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/koa). These dependencies needed to be updated together. Updates `koa` from 2.16.3 to 3.1.1 - [Release notes](https://github.com/koajs/koa/releases) - [Changelog](https://github.com/koajs/koa/blob/master/History.md) - [Commits](koajs/koa@v2.16.3...v3.1.1) Updates `@types/koa` from 2.15.0 to 3.0.1 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/koa) --- updated-dependencies: - dependency-name: koa dependency-version: 3.1.1 dependency-type: direct:production update-type: version-update:semver-major - dependency-name: "@types/koa" dependency-version: 3.0.1 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Add GPU detection via WebGL renderer string (#7) * Add GPU detection via WebGL renderer string Detect GPU capabilities using the UNMASKED_RENDERER_WEBGL string from WebGL debug info. Classifies GPUs into none/low/mid/high tiers and derives a disable3dEffects rendering hint for apps serving 3D or GPU-intensive content. * Harden GPU detection, add thresholds, extract shared demo template - Fix probe bundle size references (762 B -> 988 B) across README, docs, examples - Add WebGL context cleanup via loseContext() to free GPU resources - Use failIfMajorPerformanceCaveat to detect software renderers even when WEBGL_debug_renderer_info is blocked by privacy settings - Add GpuThresholds (softwarePattern, highEndPattern) to TierThresholds for API consistency with CPU/memory/connection thresholds - Extract duplicated HTML template from 4 example servers into examples/shared/demo-template.ts (~1000 lines removed) - Fix misaligned ASCII diagram in README - Update API docs with GPU threshold documentation - Add tests for loseContext, failIfMajorPerformanceCaveat fallback, and custom GPU thresholds * Fix ASCII diagram box alignment in README * Fix prettier formatting * Add Battery API signal to constrain rendering hints (#8) * Add Battery API signal to constrain hints on low power Battery is transient state (not a device capability), so it bypasses tier classification and feeds directly into deriveHints(). When the device is unplugged and below 15% charge, deferHeavyComponents, reduceAnimations, and disableAutoplay are forced on. Probe collects battery via navigator.getBattery() (Chromium-only), silently skipped on Firefox/Safari. Bundle stays at 1024 bytes gzipped by reclaiming bytes from cookie handling code. * Fix prettier formatting * Fix stale docs, add package READMEs, patch minimatch CVE (#10) * Replace stale probe byte counts with ~1 KB Exact byte counts (988 B, 901 B) went stale after battery signal landed. Use ~1 KB in all display references — the actual limit is enforced at build time in bundle.js and ci.yml. * Fix minimatch ReDoS vulnerability (high) Override minimatch <10.2.1 → ^10.2.1 via pnpm overrides. Vulnerable 9.0.6 was pulled in transitively by typescript-eslint. * Add README to each package for npm npm shows the README from the package directory at publish time. Each package now has a detailed README covering installation, usage, API surface, options, and compatibility. * Link npm badge to scope search page * Update README and CHANGELOG for v0.2.0 - Add battery row to signals table - Update 3 hint descriptions to mention low battery - Fix classify step to mention GPU tier - Add 0.2.0 changelog entry (GPU, battery, validation, deps, CI) * Fix prettier formatting * Bump version to 0.2.1 * Add bot/crawler filtering to probe endpoint (#12) * Add CLAUDE.md with project guidance for Claude Code * Add bot/crawler filtering to probe endpoint Reject bots, crawlers, and headless browsers before they create garbage profiles in storage. Detection uses UA pattern matching, headless GPU fingerprinting (SwiftShader/llvmpipe), and empty-signal plausibility checks. Enabled by default via rejectBots option. * Expand bot detection patterns and update docs Add AI crawlers (GPTBot, ChatGPT-User, ClaudeBot, Claude-Web, Google-Extended, Gemini, Perplexity, MistralAI, Cohere, DeepSeek, Grok, Meta, Bytedance), automation tools (Selenium), and HTTP clients (Scrapy, Apache-HttpClient). Document rejectBots option and isBotSignals() in API docs and getting-started guide. * Remove redundant grokbot and ai2bot patterns Both are already matched by the generic bot pattern. * Fix Prettier formatting * Add format-before-commit reminder to CLAUDE.md * Add first-request fallback via UA/Client Hints classification (#13) * Add first-request fallback via UA/Client Hints classification Solve the null-profile problem on first page load by adding two opt-in strategies: header-based classification (UA + Client Hints) and a fallback profile option (conservative/optimistic/custom tiers). - Add ProfileSource, FallbackProfile types and source field to ClassifiedProfile - Add classifyFromHeaders(), resolveFallback(), ACCEPT_CH_VALUE to types - Add CONSERVATIVE_TIERS / OPTIMISTIC_TIERS preset constants - Update all four middleware packages (Express, Fastify, Hono, Koa) with fallbackProfile and classifyFromHeaders options - Set Accept-CH response header when header classification is enabled * Update docs for first-request fallback and header classification Document new types (ProfileSource, FallbackProfile), functions (classifyFromHeaders, resolveFallback), constants (CONSERVATIVE_TIERS, OPTIMISTIC_TIERS, ACCEPT_CH_VALUE), the source field on ClassifiedProfile, and the classifyFromHeaders/fallbackProfile middleware options across all API docs, getting-started guide, profile schema reference, and package READMEs. * Add changelog entry and README section for first-request handling * Add missing bot-filtering docs to package READMEs and changelog (#14) The bot-filtering PR (#12) added rejectBots and isBotSignals but didn't update the package READMEs or changelog. * Add threshold validation to reject invalid configs at startup (#15) * Add cookie-parser as peer dependency for Express middleware cookie-parser is required for req.cookies to be populated, but was only listed in devDependencies. Without it the middleware silently fails to find session tokens. Mirrors how @fastify/cookie is declared in the Fastify middleware package. * Add threshold validation to reject invalid configs at startup validateThresholds() checks ordering, positivity, and RegExp types after merging with defaults. Called in all four middleware factories so inverted or nonsensical thresholds fail fast instead of silently producing wrong classifications. * Document validateThresholds in API docs, READMEs, and getting started guide * Production hardening, deployment docs, and dead signal cleanup (#16) * Add cookieSecure option and privacy documentation Add cookieSecure option to all four middleware packages, allowing the Secure flag to be set on the session cookie. Defaults to false for local dev compatibility; set to true for HTTPS deployments. Add privacy and cookie consent section to getting-started guide covering GDPR, ePrivacy Directive, UK GDPR, CCPA/CPRA, and Brazil LGPD implications of collecting device capability signals. * Add deployment guide for Docker, Cloudflare Workers, and serverless * Document streaming response limitation for probe auto-injection * Handle Redis connection failures and corrupted JSON gracefully RedisStorageAdapter now catches errors on all methods instead of letting them propagate. get() and exists() return safe defaults (null/false), set() and delete() silently degrade. * Strip userAgent from stored profiles userAgent is collected by the probe for bot/crawler filtering but serves no purpose after that check. All four endpoints now strip it before persisting to storage. JSON schema and docs updated to reflect. * Strip viewport from stored profiles and expand isValidSignals tests Viewport is only used for bot detection (presence check), not classification. Strip it alongside userAgent before persisting. Remove orphaned Viewport definition from JSON schema. Add comprehensive unit tests for isValidSignals covering all validation branches (was only testing battery paths). * Document Redis error handling and add missing changelog entries * Prepare v0.3.0 release Bump all packages to 0.3.0, finalize changelog, and switch publish workflow to extract release notes from CHANGELOG.md via ffurrer2/extract-release-notes@v3. --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
docs/deployment.mdcovering Docker (Node.js + Redis), Cloudflare Workers (Hono + KV), and serverless (Lambda, Vercel)RedisStorageAdapternow catches connection failures and corrupted JSON on all methods instead of throwing unhandled.get/existsreturn safe defaults,set/deletesilently degradeuserAgentandviewportare collected by the probe for bot filtering but were persisted unnecessarily. All endpoints now strip them before storage. JSON schema and docs updated (breaking change for consumers reading storedRawSignals)Test plan
pnpm build— all packages compilepnpm test— 345/345 tests passpnpm format— no formatting issues