Skip to content

Commit 9e14c28

Browse files
github-actions[bot]Wikid82renovate[bot]actions-userclaude
authored
Weekly: Promote nightly to main (2026-06-29) (#1112)
* chore(deps): update github-actions-non-major * chore(deps): update go-non-major * chore(deps): update npm-non-major * fix: regenerate lockfile to restore missing eslint and vite package entries Renovate's automated update regenerated package-lock.json incorrectly, omitting top-level node_modules entries for eslint and vite. This caused npm ci to fail in CI during dependency installation. Regenerating with Node v22.22.1 and npm v11.16.0 restores the correct entries. * fix(security): restore stale Grype code scanning pipeline The supply-chain Grype scan last ran on Feb 4, 2026 due to a cascade of compounding failures. This commit resolves all root causes: - Twelve .trivyignore CVE suppressions expired between Apr 30 and May 25, causing the Trivy PR gate to block all PR merges and starve the pipeline of push events. All entries extended 60–90 days with appropriate review comments; no entry exceeds Sep 1, 2026. - Ten .grype.yaml suppressions also expired in May, meaning Grype scans that did run would immediately fail on HIGH findings and produce no fresh SARIF. All entries extended with matching dates. - The supply-chain-pr.yml job condition had a dead workflow_run branch and was missing the push and schedule event names, silently skipping the verify-supply-chain job on every push to main. Added push and schedule to the condition. - Added a weekly schedule trigger (Mondays at 02:00 UTC) so scans run regardless of PR activity. Added development to push branches to match docker-build.yml scope. - Removed continue-on-error: true from the SARIF upload step so upload failures surface as visible workflow failures rather than silent no-ops. - Simplified concurrency.group to remove dead workflow_run expressions. Refs: GitHub Code Scanning "last scanned Feb 4, 2026" alert * fix(deps): update Renovate configuration to correctly map gopkg.in/yaml.v3 * chore(deps): update go-non-major * fix(deps): update Caddy version to 2.11.4 in Dockerfile * fix(deps): update prometheus/common to v0.68.1 * fix(deps): update @tanstack/react-query to v5.101.0 and axios to v1.17.0 * fix(deps): update Go version to 1.26.4 in settings, Dockerfile, and module files * fix(deps): update Syft version to v1.45.0 in multiple workflows and scripts * fix(theme): prevent flash of unstyled content on page load Add anti-FOUC inline script to index.html that applies the stored theme class synchronously before React mounts. Switch ThemeContext to useLayoutEffect for synchronous class application, add explicit light-mode CSS overrides, update CSP to allowlist the inline script hash, and add a Playwright regression suite. * fix(dep): update grype version to 0.113.0 * fix(go): align all workflow and VS Code go.goroot references to 1.26.4 Update GO_VERSION from 1.26.3 to 1.26.4 in all 9 CI workflow files and fix go.goroot in .vscode/settings.json to point to /usr/local/go where 1.26.4 is installed, replacing the missing sdk/go1.26.4 path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(deps): update go-non-major to v1.75.0 * fix(ci): resolve Go toolchain mismatch in CodeQL and all CI workflows Switch setup-go from go-version env var to go-version-file: backend/go.mod so the action reads the required version directly from go.mod instead of relying on a cached toolchain version that may lag behind. Change GOTOOLCHAIN from auto to local across all workflows so Go uses exactly the version installed by setup-go without attempting auto-downloads that can silently fall back to an older release. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(sec): patch CVE-2026-40898 in buger/jsonparser via crowdsec-builder Upgrades github.com/buger/jsonparser to v1.1.2 in the CrowdSec dependency patch block to fix a panic in Delete() caused by a negative slice index on malformed JSON input. Affects both the crowdsec and cscli binaries. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(deps): update go-non-major * chore(deps): update i18next version to 26.3.1 * chore(deps): update github-actions-non-major * chore(deps): update go-non-major * fix(deps): update npm-non-major to ^7.17.0 * fix(sec): patch CVE-2026-40898 in buger/jsonparser via caddy-builder Adds go get github.com/buger/jsonparser@v1.2.0 to the xcaddy build stage. The Caddy binary embeds buger/jsonparser transitively through caddy-crowdsec-bouncer -> crowdsec, which Trivy flags as a blocker. The crowdsec-builder stage already had this pin; this closes the gap in the caddy-builder stage. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(sec): patch CVE-2026-40898 (quic-go QPACK) in crowdsec-builder CVE-2026-40898 / GHSA-vvgj-x9jq-8cj9 is a quic-go HTTP/3 QPACK Trailer Expansion Memory Exhaustion, fixed in github.com/quic-go/quic-go@v0.59.1. CrowdSec v1.7.8 embeds quic-go v0.57.0; this is what Trivy flags as 2 blockers (crowdsec + cscli binaries). Caddy already resolves v0.59.1 through its own module graph and is unaffected. Also corrects the caddy-builder comment for buger/jsonparser, which was incorrectly attributed to CVE-2026-40898 in the prior commit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(sec): suppress GO-2024-2565, GO-2024-2557, GO-2026-4518 in grype/trivy Three new findings block CI on the development branch: - GO-2024-2565 / CVE-2024-21495 (CRITICAL): Insufficient randomness in caddy-security. FALSE POSITIVE — Go vulndb has no fixed version recorded, but per Snyk/NVD the fix shipped in v1.0.42; we run v1.1.62. Suppressed with documented rationale pending Go vulndb update. - GO-2024-2557 / CVE-2024-21492 (HIGH): Insufficient session expiration in caddy-security. No upstream fix; stateless JWT architecture means no server-side revocation. JWT TTL bounds exploitation window. Risk accepted. - GO-2026-4518 (HIGH): Go vulndb alias for the pgproto3/v2 DataRow negative field length panic already suppressed under GHSA-jqcq-xjh3-6g23 / CVE-2026-4427. Same EOL-module rationale applies. All entries include expiry dates (2026-09-05 for caddy-security, 2026-09-01 for pgproto3) and removal criteria. .trivyignore updated for the two CVE IDs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(dep) update syft to v 1.45.1 in multiple workflows * fix(dep): update knip to v 6.16.0 * fix(dep): update bytedance/sonic to v1.15.2 and mattn/go-sqlite3 to v1.14.45 * chore: add Claude Code configuration from .github copilot files Convert the project's GitHub Copilot configuration into native Claude Code equivalents so the same team conventions, agent roles, and slash commands work out-of-the-box in Claude Code sessions. - CLAUDE.md — project-wide instructions adapted from copilot-instructions.md; covers architecture rules, backend/frontend workflows, DoD checklist, and a quick-reference skills table - .claude/agents/ — nine specialized subagents (management, planning, supervisor, backend-dev, frontend-dev, qa-security, devops, docs-writer, playwright-dev) translated from .github/agents/*.agent.md, with VS Code- specific frontmatter removed and references updated to CLAUDE.md - .claude/commands/ — five slash commands translated from .github/prompts/: /create-implementation-plan, /debug-web-console-errors, /supply-chain-remediation, /playwright-generate-test, /fix-patch-coverage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(frontend): remove deprecated Firefox CSS and add modern browserslist targets (#1060) Remove -moz-osx-font-smoothing (Firefox never supported it; -webkit-font-smoothing already handles Chrome/Safari). Add .browserslistrc targeting modern browsers so autoprefixer stops emitting legacy -moz- vendor prefixes eliminated from Firefox ESR+. Co-authored-by: GitHub Actions <actions@github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: update ignore files * fix(dep) update npm deps to lates versions * chore(deps): update dependency anchore/syft to v1.45.1 (#1061) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency anchore/grype to v0.114.0 (#1062) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(dep): update codecov action * chore(docker): update GeoLite2-Country.mmdb checksum (#1064) Automated checksum update for GeoLite2-Country.mmdb database. Old: c77ac1d7e64b3fcd1447045615fc3aefb3ed886e176608c568b01f29f955e21a New: abce3a42f4f6bfb2c90cded582341da6764f5e152782ce6c832bc8fa1d873778 Auto-generated by: .github/workflows/update-geolite2.yml Co-authored-by: Wikid82 <176516789+Wikid82@users.noreply.github.com> * fix(assets): serve banner.webp and use picture element for optimized image delivery (#1063) * fix(assets): serve banner.webp and use picture element for optimized image delivery Register /banner.webp, /banner.svg, /logo.webp, and /logo.svg as static routes so browsers receive WebP variants with correct MIME types instead of falling through to index.html. Replace the bare <img src="/banner.png"> in the sidebar with a <picture> element that serves the 74%-smaller WebP to capable browsers and falls back to PNG, eliminating NS_BINDING_ABORTED caused by the 1.2 MB PNG stalling under load. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: remove tracked worktree gitlink and ignore .claude/worktrees/ The .claude/worktrees/enumerated-snacking-parnas path was committed as a gitlink (unregistered submodule), causing `git submodule foreach` to exit with code 128 and failing Codecov upload steps in CI. Remove it from the index and add .claude/worktrees/ to .gitignore so future worktrees are never inadvertently staged. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: GitHub Actions <actions@github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(deps): bump quic-go, maxminddb, and sqlite dependencies * chore(deps): bump knip from 6.16.0 to 6.16.1 * docs: add no-worktrees instruction to CLAUDE.md * chore(deps): bump react-hook-form and eslint-plugin-unicorn * chore: ignore gorilla/websocket in renovate updates * fix(deps): add Renovate sourceUrl overrides for gin packages (#1065) * chore(deps): bump quic-go, maxminddb, and sqlite dependencies * fix(deps): add sourceUrl overrides for gin packages in Renovate config Renovate fails to resolve github.com/gin-gonic/gin and its sibling packages gin-contrib/gzip and gin-contrib/sse with a "no-result" error. Adds three sourceUrl packageRules entries following the established pattern already present for google/uuid, gorm.io/gorm, and other Go packages in this repo. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: GitHub Actions <actions@github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: clean node_modules before npm install in update script * chore(frontend): bump typescript-eslint to 8.61.0 and update deps * chore: bump dev dependencies (obug, semver, tinyexec) * chore(deps): bump golang.org/x/sys from v0.45.0 to v0.46.0 * chore(deps): bump golang.org/x and modernc.org dependencies * fix(ci): pass pr_number when dispatching security-pr.yml from weekly promotion The trigger-required-checks job in weekly-nightly-promotion.yml dispatched security-pr.yml without providing the required pr_number input, causing HttpError: Required input 'pr_number' not provided. The fix resolves the PR number from the create-promotion-pr job output and passes it as an input when dispatching the security workflow. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(ci): extend no-cache-filters to caddy-builder and crowdsec-builder in e2e workflow Prevents stale GHA BuildKit layer cache from serving outdated caddy-builder and crowdsec-builder stage outputs in e2e-tests-split.yml, mirroring the same fix already applied to nightly-build.yml for CVE-2026-45135. Also corrects a stale fallback version comment in Dockerfile (v2.11.3 → v2.11.4) and updates SECURITY.md to mark CVE-2026-45135 as fully remediated across all affected build workflows. * chore: bump prettier from 3.8.3 to 3.8.4 * chore(deps): bump eslint-plugin-unicorn to 65.0.1 * fix(dockerfile): gate Delve install on BUILD_DEBUG, pin x/sys for GO-2026-5024 Production builds now install a harmless stub instead of Delve to avoid shipping golang.org/x/sys < v0.27.0 (GO-2026-5024). Debug builds pin golang.org/x/sys to v0.46.0 via a temporary module before installing dlv. * fix(entrypoint): gracefully handle production dlv stub when CHARON_DEBUG=1 The GO-2026-5024 fix replaced the Delve binary with a shell stub in production images. When CI integration tests run with CHARON_DEBUG=1, the entrypoint tried to launch `dlv exec /app/charon`, the stub exited immediately with code 1, APP_PID captured the dead stub PID, and the wait loop triggered container shutdown before Charon ever started. Guard the Delve path with `dlv version` — real Delve exits 0, the stub exits 1 — and fall back to direct execution when the stub is detected. * chore(deps): update go-non-major (#1058) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jeremy <jhatfield82@gmail.com> * chore(deps): update github-actions-non-major to v46.1.15 (#1067) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jeremy <jhatfield82@gmail.com> * fix(deps): update go-non-major to v0.7.2 (#1068) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update alpine docker tag to v3.24.0 (#1069) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): bump go-pkcs12 from v0.7.1 to v0.7.2 * chore: bump semver from 7.8.3 to 7.8.4 * chore(deps): bump frontend dev dependencies to latest patch versions * chore: replace eslint-plugin-react-compiler with react-hooks built-in * fix(frontend): unregister auth error handler on AuthProvider unmount (#1070) Issue #579 reported that page reload did not redirect to /login when the session expired. Root-cause tracing showed the reload guard already works on development (all 16 auth E2E tests pass), but the trace surfaced a real hazard: the axios 401 interceptor kept a stale handler closure after AuthProvider unmounted. setAuthErrorHandler now accepts null and the provider unregisters its handler on unmount. Adds regression tests for RequireAuth, AuthContext mount/unmount handler lifecycle, and the client interceptor null-handler path. Closes #579 Co-authored-by: GitHub Actions <actions@github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * chore: bump golang.org/x/net from v0.55.0 to v0.56.0 * chore: bump @napi-rs/wasm-runtime from 1.1.4 to 1.1.5 * chore: bump frontend dev dependencies to latest versions * chore: add Docker Scout CLI install script * fix(docker): move frontend builder to node alpine3.24 base to clear critical/high base-image CVEs The pinned node:24.16.0-alpine (alpine 3.23) base was flagged with 1 critical and 8 high vulnerabilities. Repin to the freshly published alpine 3.24 variant, which also aligns the builder with the alpine 3.24 runtime base. Remaining openssl advisories (CVE-2026-45447) are patched in-stage by the existing apk upgrade step; the rebuilt stage scans clean for critical/high findings. * chore: bump @types/node from 25.9.2 to 25.9.3 * chore: remove lint step from npm_update script * chore: enhance go_update.sh with vuln checks and test runs - Auto-install govulncheck if missing - Update go/toolchain directives before deps - Include test dependencies with -t flag - Run tests and govulncheck after each module update * fix(go_update): simplify PATH export and remove redundant list cmd * chore(renovate): group Dockerfile ARG updates separately from Go/NPM - Replace Go github-tags Dockerfile fallback rule with a generic custom.regex + Dockerfile filename matcher - New group: dockerfile-non-major with "dockerfile" label - Preserves npm-non-major grouping rule unchanged * chore(deps): update go-non-major to v0.56.0 (#1071) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore: update acorn from 8.16.0 to 8.17.0 * chore: bump frontend deps (acorn, caniuse-lite, enhanced-resolve) * chore: bump felixge/httpsnoop from v1.0.4 to v1.1.0 * chore: update frontend lock file dependencies * fix(security): prepare for npm v12 breaking changes (#1072) * chore(ci): bump e2e workflow Node to 24.12.0 and track NODE_VERSION via Renovate Node 20 is EOL and will be unsupported by npm 12. Adds a Renovate custom manager so all workflow NODE_VERSION pins receive update PRs. * fix(security): disable dependency install scripts for all npm installs Adopts npm v12's secure default today: every npm ci/install call site (CI workflows, Dockerfile, Makefile, scripts, package.json pre-hooks) now passes --ignore-scripts, and unrs-resolver's postinstall is explicitly denied via allowScripts (it ships prebuilt binaries; the script is only a fallback build). Verified: clean installs, frontend build, type-check, and full unit suite all pass with scripts disabled. --------- Co-authored-by: GitHub Actions <actions@github.com> * chore: bump eslint-plugin-security to 4.0.1 * chore: bump npm to 11.17.0 * chore(frontend): bump lucide-react, tailwindcss, and eslint deps * chore: bump obug from 2.1.2 to 2.1.3 * chore(deps): bump modernc.org/libc from v1.73.0 to v1.73.1 * chore: fix renovate datasource config for expr-lang/expr * chore(deps): bump react-hook-form from 7.78.0 to 7.79.0 * chore(deps): update npm-non-major to ^10.5.0 (#1073) * chore(deps): update npm-non-major to ^10.5.0 * fix: regenerate frontend lock file to restore missing eslint@10.5.0 entries Renovate's automated update removed top-level node_modules entries for eslint@10.5.0 (and transitive deps eslint-visitor-keys, ignore) from frontend/package-lock.json, causing all CI jobs to fail at npm ci. --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: GitHub Actions <actions@github.com> * chore: bump regjsparser from 0.13.1 to 0.13.2 * chore: update go.work.sum with golang.org/x/term v0.44.0 * chore(deps): bump modernc.org/libc from v1.73.1 to v1.73.3 * chore: bump @csstools/css-color-parser to 4.1.4 * chore(deps): update eslint-plugin-unicorn to v66 and react-refresh to v0.5.3 * chore(docker): update GeoLite2-Country.mmdb checksum (#1074) Automated checksum update for GeoLite2-Country.mmdb database. Old: abce3a42f4f6bfb2c90cded582341da6764f5e152782ce6c832bc8fa1d873778 New: 11b88595d026953920668d91f6d531057b397f05170237fc98a13a8b051ab861 Auto-generated by: .github/workflows/update-geolite2.yml Co-authored-by: Wikid82 <176516789+Wikid82@users.noreply.github.com> * chore: bump tldts, playwright, and vitest deps * chore: bump mongo-driver to v2.6.1 and modernc/libc to v1.73.4 * chore(deps): update node.js to 21f403a (#1077) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update alpine docker tag to v3.24.1 (#1078) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dockerfile-non-major (#1079) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update github-actions-non-major (#1080) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update node.js to v24.16.0 (#1081) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update npm-non-major (#1082) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency eslint-plugin-unicorn to v67 (#1083) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update npm-non-major to ^7.18.0 (#1084) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * feat: enhanced dashboard with statistics (#25) (#1075) * feat(models): add RequestLog model and AutoMigrate registration Adds RequestLog struct to record proxied HTTP requests for the enhanced dashboard statistics feature (issue #25). Includes BeforeCreate hook for UUID generation, compound (host_id, timestamp) indexes, and GDPR-safe pseudonymised client IP hashing. Registers model in AutoMigrate. * feat(services): add StatsIngester for log fan-out and batch DB writes - Add stats_types.go with StatsPushData, HostStat, StatusStat, StatsPushMessage, and BroadcastHub interface (avoids import cycles) - Add StatsIngester: channel buffer=1000, batch flush at 100 entries or 500ms interval via CreateInBatches; atomic dropped-count tracking - Hash client IPs with SHA-256 (first 16 bytes, hex) for GDPR safety - Add LogWatcher.RegisterIngester() + fan-out in broadcast() - TDD: 6 tests covering count-flush, timer-flush, back-pressure, graceful Stop drain, IP hashing determinism, and fan-out wiring * feat(services): add StatsService with aggregation queries and TTL cache Adds StatsService providing GetSummary (30s TTL cache), GetTopHosts, GetStatusDistribution, GetTrafficVolume, and GetCertExpiry with input validation allowlists. Extends stats_types.go with StatsSummary, TrafficBucket, and CertExpiry types. * feat(frontend/api): add stats API client and TypeScript type definitions Add typed API functions and interfaces for all 8 stats endpoints (summary, top-hosts, status-distribution, traffic-volume, cert-expiry, requests, health, and WebSocket hub) with full Vitest test coverage (33 tests). * feat(frontend/hooks): add useStats and useStatsWebSocket hooks Add six TanStack Query hooks (useStatsSummary, useTopHosts, useStatusDistribution, useTrafficVolume, useCertExpiry, useStatsHealth) with stable query keys and appropriate polling intervals. Add useStatsWebSocket hook that tracks live summary updates via the stats WebSocket and disables REST polling when connected. Full Vitest coverage for all hooks (22 tests). Also remove unicorn/no-array-for-each ESLint rule removed in unicorn v66. * feat(frontend/components): add stats chart and widget components Add 8 pure presentational components under frontend/src/components/stats/: - RequestCountWidget: 3-stat card for 24h/7d/30d request counts - TopHostsChart: horizontal bar chart (recharts BarChart) - StatusDistributionChart: donut chart with accessible HTML summary list - TrafficVolumeChart: line chart with KB/MB Y-axis formatting - CertExpiryList: accessible table with red/amber/green day-based color coding - ServiceHealthWidget: WebSocket live/offline indicator + dropped-event warning - PeriodSelector: controlled radio button group for 24h/7d/30d - BucketSelector: controlled radio button group for 1h/6h/1d All components are pure (no data fetching), strictly typed with no `any` types, and keyboard accessible. Includes 58 Vitest unit tests covering loading states, data rendering, color coding, and interaction callbacks. * feat(frontend/dashboard): integrate stats sections into Dashboard page Add a responsive Statistics section to the Dashboard page below the existing content. Uses useStatsWebSocket for live updates, useState for period/bucket controls, and the six stats hooks + eight stats components (RequestCountWidget, ServiceHealthWidget, CertExpiryList, TrafficVolumeChart, TopHostsChart, StatusDistributionChart, PeriodSelector, BucketSelector). Layout is mobile-first with single column on small screens, 2-col on sm/md, 3-col top row on lg. Adds dashboard.statistics and dashboard.trafficVolume i18n keys to all five locale files. Expands Dashboard tests from 3 to 12 cases. * test(e2e): add Playwright tests for enhanced dashboard statistics - tests/stats.spec.ts: 12 E2E tests covering all 9 required scenarios (stats heading, period selector, bucket selector, request count widget, service health widget, cert expiry section, traffic/top-hosts/status distribution chart containers) plus accessibility radio-count assertion - backend/internal/api/handlers/stats_api_integration_test.go: adds TestStatsAPI_CertExpiry_366Days_Returns400 to cover the upper-bound validation (within_days > 365 returns HTTP 400); simplifies function signature to remove unused return value - backend/internal/services/stats_ingester_test.go: adds TestStatsIngester_RegisterHub and TestStatsIngester_ToRequestLog_InvalidTimestamp to cover the RegisterHub wiring path and the timestamp parse-error fallback All 12 E2E tests pass against the running E2E container at :8080. Backend unit tests pass (88.4% coverage, above 87% minimum). Frontend tests pass (87.86% statement coverage, above 85% minimum). GORM scan: 0 CRITICAL/HIGH findings. * docs: update ARCHITECTURE.md and features.md for stats subsystem * feat(api): add stats handler and WebSocket hub for dashboard stats * test: fix patch coverage for stats subsystem Adds targeted tests to cover all previously uncovered patch lines: Backend: - stats_ws_hub_test.go (new): full hub coverage — constructor, non-blocking broadcast, ctx cancel exit, client broadcast, slow-client drop, client unregister, StatsWS upgrade-error path, StatsWS nil-hub close - stats_handler_test.go: error-path 500s for all six handlers, non-integer within_days → 400, invalid limit param silently ignored - stats_ingester_test.go: Stop flushes batches > batchSize; Run drains big batch on ctx cancel (covers batchSize branch in drain loop) - stats_service_test.go: GetTrafficVolume 6h and 1d buckets; GetSummary DB error Frontend: - StatusDistributionChart: extended recharts mock calls Pie label/Tooltip content; adds 1xx test to cover statusClass "other" return - TrafficVolumeChart: mock calls YAxis tickFormatter with MB/KB/B values and Tooltip content to cover formatBytes branches - TopHostsChart: mock calls Tooltip content including hostname ?? label fallback - CertExpiryList: adds undefined-data test to cover (data ?? []) branch - useStatsWebSocket: adds non-stats_update message test for the else branch * feat(frontend): add widget tooltips, top-hosts color coding, and hide/show controls Adds ELI5 info tooltips to all 6 dashboard stats widgets, a color-coded legend for the Top Hosts chart, and a per-widget visibility toggle persisted in localStorage so users can hide widgets they don't need. * fix(frontend): add aria-expanded to sidebar accordion buttons Adding the Dashboard "Customize" button (which also carries aria-expanded) shifted DOM order and caused the WebKit navigation E2E test to target it instead of the sidebar, since the sidebar's collapsible accordion buttons never actually exposed aria-expanded. Add the missing attribute to the real sidebar toggles and scope the test to the sidebar so it tests what it claims to. * fix(api): join proxy_hosts to populate Top Hosts hostname GetTopHosts only selected host_id and a count, never the hostname, so every entry in the Top Hosts legend and tooltip rendered with a blank or duplicate label. With every chart category collapsing to the same empty string, Recharts merged the bars and hovering any bar showed the same (highest) data point. Join proxy_hosts by UUID to populate the real hostname, falling back to host_id if the host has since been deleted. * fix(database): run SQLite integrity check in background to avoid blocking startup PRAGMA quick_check was running synchronously in Connect() and could take well over a minute on larger databases (observed 93.5s), despite being intended as a non-blocking, warn-only check. * fix(database): give startup integrity check its own connection The previous fix moved PRAGMA quick_check to a goroutine, but the main pool is capped at one connection (SQLite single-writer constraint), so the background check still held that connection for the full scan and blocked AutoMigrate behind it. Open a dedicated connection for the check so it no longer serializes against the rest of startup. * fix(api): use proxy host Name instead of domain names for Top Hosts GetTopHosts joined proxy_hosts.domain_names, showing raw domains in the legend/tooltip instead of the user-assigned host Name. Switch the join to proxy_hosts.name to match what users configured. * fix(database): silence record-not-found noise in GORM query logs Optional lookups (e.g. caddy.keepalive_idle/keepalive_count settings) return ErrRecordNotFound when unset, which call sites already handle via `if err == nil` fallbacks. GORM's default logger still logged these as errors on every startup. Configure IgnoreRecordNotFoundError so only real query errors and slow queries are logged. * fix(api): match Top Hosts by domain instead of ProxyHost UUID RequestLog.HostID stores the raw Host header seen by the proxy (a domain), not the ProxyHost UUID, so the previous join on proxy_hosts.uuid = request_logs.host_id never matched and silently fell back to showing the domain. Build a domain -> name lookup from proxy_hosts.domain_names (which can hold several comma-separated domains per host) and resolve hostnames against that instead. * feat(stats): add warmup guide and improve empty state UX - Log successful LogWatcher startup with path info - Add deployment/warmup guide for stats feature (docs) - Improve TrafficVolumeChart empty state with helpful messaging - Add data collection info to tooltip when no data available * test(TrafficVolumeChart): update empty state text assertions * fix(stats): replace CSS variable with hex literal in TrafficVolumeChart SVG presentation attributes cannot resolve CSS custom properties defined as space-separated RGB triplets (Tailwind v4 token format). Replace `var(--color-brand-500)` with `LINE_COLOR = '#3b82f6'` so Recharts renders a visible line stroke. Add unit tests asserting stroke is a valid hex value and tooltip renders correctly. Add Playwright step verifying recharts-line-curve path exists when data is present. * fix(stats): add LineChart mock and update QA report for feature/stats * test: fix recharts mock to drop importActual for Vitest ESM compat * chore(deps): bump go-toml to v2.4.0 and prometheus/common to v0.69.0 --------- Co-authored-by: GitHub Actions <actions@github.com> * fix(deps): resolve js-yaml and markdown-it DoS vulnerabilities via npm overrides Force js-yaml to >=4.2.0 and markdown-it to >=14.2.0 via npm overrides to address GHSA-h67p-54hq-rp68 and GHSA-6v5v-wf23-fmfq in markdownlint-cli2 transitive deps. Also correct lint:md scripts to use valid markdownlint-cli2 negated glob syntax instead of the unsupported --ignore flag. * fix(ci): align trivyignores and upload-sarif SHA across scan workflows Add trivyignores: '.trivyignore' to the main-image table and SARIF Trivy scan steps in docker-build.yml so suppressed CVEs are excluded from both log output and SARIF uploads, consistent with the PR scan steps. Align the upload-sarif action SHA in security-pr.yml from the stale pre-v4.36.2 pin to the canonical 8aad20d SHA (v4.36.2) used by every other security workflow in this repository. * fix(ci): add post-upload SARIF verification to weekly security rebuild Add trivyignores: '.trivyignore' to the SARIF scan step in security-weekly-rebuild.yml so accepted/pending CVE suppressions are excluded from the weekly Security tab upload, matching all other scan workflows. Add id: upload-trivy-weekly to the upload step and a new 'Verify SARIF was uploaded' step that validates the SARIF file exists, that the upload succeeded, and that the file is parseable JSON. Fails the workflow visibly instead of silently discarding SARIF upload errors, preventing the pipeline from going stale undetected as happened Feb-May 2026. * chore: bump mongo-driver/v2 from v2.6.1 to v2.7.0 * chore(deps): bump frontend lockfile dependencies * chore: add package package-lock.json * chore(deps): bump lucide-react from 1.20.0 to 1.21.0 * chore: bump go-sqlite3 from v1.14.45 to v1.14.46 * chore(deps): bump moby/moby client to v0.5.0 and api to v1.55.0 * chore: bump nanoid to 3.3.13 and yargs to 16.2.2 * chore(deps): bump eslint-plugin-sonarjs to 4.1.0 * chore(frontend): remove autoprefixer from postcss config * fix(frontend): remove unused autoprefixer dependency * fix: wrap webkit scrollbar styles in @supports selector guard * chore: bump @types/node from 25.9.3 to 26.0.0 * chore(deps): bump @types/node to v26 and eslint-plugin-unicorn to v68 * chore(renovate): add gomodTidy, fix golang-jwt/jwt v5 tracking * chore(deps): bump react-hook-form from 7.79.0 to 7.80.0 * chore(deps): update github-actions-non-major (#1086) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jeremy <jhatfield82@gmail.com> * chore(deps): update node.js to v24.17.0 (#1088) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jeremy <jhatfield82@gmail.com> * fix(deps): correct react-hook-form 7.80.0 integrity hash in lockfile The react-hook-form@7.80.0 tarball was republished on the npm registry after the package-lock.json was generated, producing a different SHA-512 digest. npm ci --ignore-scripts in the Docker Alpine build layer failed with EINTEGRITY because the stored hash no longer matched the served tarball. Updated the integrity field from the stale sha512-mhYp/... to the current sha512-4P+fk6... value, which resolves the Docker build failure. * chore(deps): update dockerfile-non-major to v1.77.0 (#1087) * chore(deps): update dockerfile-non-major to v1.77.0 * fix: eliminate TempDir cleanup race in database tests runQuickCheck ran as an untracked goroutine, leaving WAL/SHM file handles open when t.TempDir() cleanup fired, causing intermittent "directory not empty" failures. Introduce launchQuickCheck (defaults to the goroutine) so tests can override it to run synchronously via TestMain, ensuring the integrity check connection is closed before temp dirs are removed. --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jeremy <jhatfield82@gmail.com> Co-authored-by: GitHub Actions <actions@github.com> * chore(deps): update go-non-major to v1.4.0 (#1090) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jeremy <jhatfield82@gmail.com> * chore(deps): update actions/checkout action to v7 (#1089) * chore(deps): update actions/checkout action to v7 * fix(auth): ensure server-side session is invalidated before local state clears on logout The logout() function in AuthContext was clearing React/localStorage state before the backend POST /auth/logout completed. Because the onClick handler never awaits the returned Promise, React redirected to /login (and Playwright's waitForURL resolved) while the session_version increment and cookie-clearing were still in-flight. Any immediate check against /api/v1/auth/me would receive 200 via the still-valid auth_token cookie (Firefox accepts Secure cookies on http://127.0.0.1), causing the E2E "Session isolation after logout and re-login" test to fail consistently. Fix: call the backend first (cookie still authenticates it), then clear local state in a finally block so local and server-side state are always consistent. Also fix a flaky Playwright test ("User cannot promote self to admin") where page.goto('/users') raced with Login.tsx's pending invalidateQueries→navigate('/') chain. Adding waitForURL+waitForLoadingComplete after loginWithCredentials ensures the app settles on the dashboard before navigating. --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jeremy <jhatfield82@gmail.com> Co-authored-by: GitHub Actions <actions@github.com> * chore: bump nanoid from 3.3.13 to 3.3.14 * chore: bump nanoid from 3.3.13 to 3.3.14 * chore(dep): update package rules for js-yaml * chore(docker): update GeoLite2-Country.mmdb checksum (#1091) Automated checksum update for GeoLite2-Country.mmdb database. Old: 11b88595d026953920668d91f6d531057b397f05170237fc98a13a8b051ab861 New: 6e9212f23d3279a2454404d3b2a7ac30159fddbb9870ba33763014877296455c Auto-generated by: .github/workflows/update-geolite2.yml Co-authored-by: Wikid82 <176516789+Wikid82@users.noreply.github.com> * chore(frontend): bump dependencies to latest versions * chore: bump nanoid to 3.3.15 and smol-toml to 1.7.0 * chore: add Claude worktree isolation settings * chore(deps): bump go-sqlite3 to v1.14.47 and modernc/sqlite to v1.53.0 * chore(dep): move js-yaml to ignoreDeps — packageRule didn't cover overrides entries Renovate doesn't apply allowedVersions constraints to npm overrides blocks, so the prior packageRule wasn't preventing v5 proposals. Moving js-yaml to ignoreDeps silences Renovate entirely; the overrides pin in package.json already locks it to ^4.2.0. Also adds .claude/settings.json to disable background-session worktree isolation (CLAUDE.md prohibits worktrees in this repo). * chore(deps): bump go-toml/v2 from v2.4.0 to v2.4.1 * feat(theme): comprehensive theme system + FOUC fix (closes #34) (#1092) * fix(theme): migrate CSS to data-theme selectors and update Tailwind config * fix(theme): replace useLayoutEffect with useEffect + data-theme attribute; fix FOUC - Move inline theme script to last in <head> via Vite plugin so stylesheet loads first (AC-02) - Switch from classList.add to setAttribute('data-theme', ...) to avoid forced layout (AC-03) - Replace useLayoutEffect with useEffect + useRef first-render skip in ThemeProvider (AC-04) - Expand ThemeContextValue with full ThemeId, CustomTheme, ThemeExport types - Add BUILT_IN_THEMES, BUILT_IN_THEME_LABELS, THEME_STORAGE_KEY, CUSTOM_THEME_STORAGE_KEY - Add setTheme, resolvedTheme, customTheme, setCustomTheme, exportTheme, importTheme to context - Fallback migration: reads old 'theme' key if 'charon-theme' not set (AC-12) - ThemeToggle now navigates to /settings/appearance instead of binary toggle - Add Appearance nav item to Settings page - Add settings.appearance i18n key to all 5 locale files - New ThemeContext.test.tsx with TC-01 through TC-13 scenarios - Extend useTheme.test.tsx with happy-path and new API coverage - Update Settings.test.tsx to include Appearance in nav order assertion * feat(theme): add Settings Appearance tab, theme gallery, and preview - Add ThemeGallery, ThemeCard, ThemePreviewOverlay components under frontend/src/components/theme/ - ThemeGallery renders 6 cards (5 built-ins + system) with role="radiogroup" and role="radio" accessibility attributes per WCAG 2.1 SC 4.1.2 - ThemeCard shows mini color swatches, handles hover/focus preview events, and keyboard selection (Enter/Space) - ThemePreviewOverlay transiently sets data-theme on <html> without committing to context; restores resolvedCurrentTheme on null - AppearanceSettings page at /settings/appearance with race-condition-safe handleThemeChange (setPreviewTheme(null) before setTheme) - Add appearance route to App.tsx lazy routes - Add all appearance.* i18n keys to en/de/es/fr/zh locale files - 50 unit tests across 4 test files covering TG-01 through TG-06 scenarios * feat(theme): add custom color picker and theme import/export Add CustomColorPicker component with hex↔RGB conversion helpers and 10 color token inputs plus a color scheme toggle. Add ThemeImportExport component with CSS injection-safe validation (RGB_PATTERN + VALID_THEME_IDS). Extend AppearanceSettings to show the custom picker when theme=custom and the import/export section always. * feat(theme): add logo customization — backend upload endpoint and frontend UI - Add LogoHandler (POST/DELETE /api/v1/settings/logo) with server-side MIME detection via net/http.DetectContentType; MaxBytesReader enforced at 2MB; SVG uploads rejected; filename always normalized to logo.<ext> - Update NewRouter to accept dataDir and serve /uploads static directory - Register logo routes in routes.go; derive dataDir from cfg.DatabasePath - Add uploadLogo/deleteLogo to frontend settings API client - Add LogoCustomizer component with Upload/URL tabs and admin-only guard - Update AppearanceSettings with logo section using React Query mutations - Update Layout.tsx to read ui.logo_url from settings and use as logo src - Tests: BL-01..BL-07 backend, LC-01..LC-08 frontend, settings API tests * test(e2e): add Playwright theme system E2E tests + docs updates Adds theme.spec.ts covering FOUC fix, default theme, localStorage persistence, system mode, gallery UI, preview-on-hover, custom color picker, export/import, and logo customization. Updates ARCHITECTURE.md, docs/features.md, and docs/features/ui-themes.md to reflect the new data-theme CSS custom properties system. Closes #34 * feat(theme): add banner upload endpoint and named themes backend CRUD - Extract shared ImageUploadHandler with AssetConfig to DRY up image upload logic - Refactor LogoHandler to delegate to ImageUploadHandler (zero API changes) - Add BannerHandler for POST/DELETE /api/v1/settings/banner (admin-only) - Add CustomTheme GORM model with UUID BeforeCreate hook and uniqueIndex on Name - Add CustomThemeHandler with full CRUD: GET/POST /themes, PUT/DELETE /themes/:id - Wire banner and theme routes into management group in routes.go - Add CustomTheme to AutoMigrate list - All logo_handler_test.go tests pass unchanged * feat(theme): add banner customizer and named user themes frontend Integrates banner upload/preview/delete UI with BannerCustomizer component, and introduces UserThemeManager for creating, applying, editing, and deleting named custom themes. Updates ThemeContext, ThemeContextValue, AppearanceSettings, Layout, LogoCustomizer, ThemePreviewOverlay, settings API, and all i18n locales. Adds full unit test coverage for new hooks (useUserThemes) and components. * docs(theme): document banner upload and named custom themes in features.md * test(theme): add E2E tests for banner upload and named user themes Covers the two new Appearance settings features: - Banner: upload PNG via file input, preview, sidebar display, URL-based save, and reset to default - User themes: create via dialog, activate (verifies data-theme="custom"), edit name via PUT /api/v1/themes/:id, delete with confirmation dialog Root-cause notes discovered during implementation: - Backend stores theme colors as a JSON string; page.request must pass colors as JSON.stringify(colorsObj), not a plain nested object - ThemeContext maps all user:* ThemeIds to data-theme="custom" on <html>, not to the raw user:<uuid> string - All routes live under /api/v1/ (not /api/) * fix(theme): update test mocks for ThemeContext useUserThemes dependency and banner API - Mock useUserThemes in ThemeContext, ThemeImportExport, and AppearanceSettings tests so ThemeProvider does not require QueryClientProvider - Add uploadBanner/deleteBanner to AppearanceSettings settings API mock * test(theme): add backend coverage tests for error paths in custom theme and image upload handlers - ListThemes, CreateTheme, UpdateTheme, DeleteTheme: add DB-closed error path tests - UpdateTheme: add tests for malformed body, name > 100 chars, invalid colors JSON, duplicate name on rename - BannerHandler: add JPEG upload test (covers acceptedMIME JPEG branch) and DB-closed test (covers upsertSetting error path) * chore(deps): bump go-sqlite3, go-toml, and modernc/sqlite * fix(e2e): update theme-fouc spec to use data-theme attribute instead of className The inline anti-FOUC script now sets data-theme="dark"|"light" on <html> (via setAttribute) rather than classList.add('dark'|'light'). Update T1-T5 to capture and assert the data-theme attribute at DOMContentLoaded, and update T4 to verify the attribute before the background-color check. T6 is rewritten: ThemeToggle no longer directly toggles the theme — it navigates to /settings/appearance. The test now verifies the button title and navigation target instead of a synchronous class change. beforeEach now clears both 'theme' and 'charon-theme' localStorage keys since the inline script reads from 'charon-theme' first. * chore(deps): bump frontend dependencies to latest versions * test(coverage): add patch coverage tests to reach 90% overall threshold Frontend: - ThemeToggle.test.tsx (new): onClick navigates to /settings/appearance, icon/aria-label reflect resolvedTheme — covers ThemeToggle.tsx:14 - LogoCustomizer.test.tsx: LC-09 invalid URL shows HTTPS error (covers lines 72-73), LC-10 switching URL→Upload tab re-shows file input (covers line 117); add logoUrlHttpsRequired to i18n mock - BannerCustomizer.test.tsx: BC-12 switching URL→Upload tab re-shows file input (covers line 119) - ThemeImportExport.test.tsx: simulate non-string FileReader result triggers error toast (covers lines 96-97) Backend: - server_test.go: TestNewRouter_WithDataDir verifies /uploads is served when dataDir is set (covers server.go:23-24); add SPA fallback test Overall patch coverage: 89.1% → 90.8% * chore: add Claude Code settings with enabled plugins * fix(html): add explicit semicolons in FOUC script to satisfy CodeQL ASI rule * fix(e2e): remove unused imports in theme.spec.ts to resolve CodeQL finding * fix(e2e): rewrite theme-fouc spec to eliminate unreliable DOMContentLoaded listener The DOMContentLoaded listener capture via addInitScript consistently returns empty string in CI across all three browsers. Root causes: 1. Listener timing: the initScript's DOMContentLoaded listener races with the browser's fast headless page load; the attribute is null when the event fires, collapsing to '' via the ?? '' fallback. 2. Wrong localStorage key: T2-T5 used the old 'theme' fallback key instead of the primary 'charon-theme' key. The inline script reads charon-theme first, so setting only the fallback is unreliable when storageState may already contain a charon-theme value from the auth session. Fix: remove the DOMContentLoaded listener entirely. Navigate to '/' with { waitUntil: 'domcontentloaded' } and read the attribute directly via page.evaluate(). At domcontentloaded React's useEffect has not fired, so if data-theme is set correctly it was set by the inline script — the FOUC proof is preserved. Update all tests to use the charon-theme key. * fix(security): suppress CVE-2026-39824 (GO-2026-5024) in Trivy and Grype golang.org/x/sys/windows.NewNTUnicodeString integer overflow (CWE-190). Go vulndb considers this fixed at v0.44.0; we ship v0.46.0 (above threshold). The affected function is Windows-only — Charon is a Linux-only deployment and this code path is never executed. NVD currently shows "no confirmed patch", causing a discrepancy with Trivy v0.71.2+; govulncheck and Trivy v0.52.2 (fresh DB 2026-06-23) both report clean. No x/sys > v0.46.0 exists yet. - .trivyignore: suppress CVE-2026-39824 with exp: 2026-09-23 - .grype.yaml: suppress GO-2026-5024 + CVE-2026-39824 with full justification - .claude/settings.json: fix JSON syntax error (missing comma between keys) Review: 2026-09-23 — remove once x/sys v0.47.0+ ships or NVD/Trivy converge. * test(theme): add targeted tests to raise patch coverage from 90.8% to 95.4% - backend logo handler: add error-path tests for empty file, MkdirAll failure, and read-only uploads directory - settings API: add uploadBanner and deleteBanner unit tests - UserThemeManager: add UTM-12 through UTM-17 covering dialog type, cancel, save, and edit flows - ThemeContext: add 5 new tests covering user-theme loading guard, fallback-to-dark, system media query change, setUserTheme tokens, and activeUserTheme lookup - AppearanceSettings: add mutation trigger tests for URL save, reset, custom color change, and UserThemeManager onActivate callback --------- Co-authored-by: GitHub Actions <actions@github.com> * chore: bump tldts, axe-core/playwright, and vite dependencies * chore(frontend): bump frontend dependencies to latest versions * chore: bump playwright from 1.61.0 to 1.61.1 * chore(deps): update dockerfile-non-major (#1095) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update actions/cache action to v6 (#1096) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * test: increase login redirect timeout to 15s for Firefox CI * chore(deps): update github-actions-non-major (#1094) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jeremy <jhatfield82@gmail.com> * chore(deps): update node.js to v24.18.0 (#1097) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jeremy <jhatfield82@gmail.com> * chore: bump electron-to-chromium from 1.5.377 to 1.5.378 * fix: use axios for session validation to fix Firefox E2E auth test Playwright's Firefox CDP network interception has known timing issues with native fetch() during page.goto() navigation, while XHR (axios) is intercepted reliably in all browsers. `fetchSessionUser` used a raw fetch('/api/v1/auth/me') call, which meant the Playwright route intercept in the Firefox session-expiry test could let the auth check succeed against the real server instead of returning the mocked 401. This prevented the redirect to /login from firing, causing the test to fail consistently. Switch to `client.get('/auth/me')` so all API calls go through the same axios instance. The existing interceptor already excludes /auth/me from triggering onAuthError, so the catch-block in checkAuth handles the 401 as before. Also increase the success-modal visibility timeout in caddy-import-gaps from the global 5s default to 10s to address Firefox CI flakiness where React state updates after a commit response can take >5s. * chore: bump rolldown to 1.1.3 and napi-rs/wasm-runtime to 1.1.6 * chore(deps): bump i18next to 26.3.2 and rolldown to 1.1.3 * chore(deps): bump go-toml/v2 from v2.4.1 to v2.4.2 * chore: update npm overrides deps in npm_update.sh Handle flat and nested override entries separately to avoid ncu crashes; add targeted typescript-only pass for frontend module. * chore: ignore tempCodeRunnerFile.sh in scripts directory * chore: pin js-yaml to ^5 in npm update script * chore: bump knip to 6.19.0 and smol-toml to 1.7.0 * chore(deps): update npm-non-major (#1098) * chore(deps): update npm-non-major * fix: restore missing vite@8.1.0 entry in frontend lock file Renovate's lock file regeneration omitted the node_modules/vite resolved entry while updating the packages specifier to ^8.1.0, causing npm ci to fail with "Missing: vite@8.1.0 from lock file". --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: GitHub Actions <actions@github.com> Co-authored-by: Jeremy <jhatfield82@gmail.com> * chore(deps): update npm-non-major (#1099) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update node.js to v24.18.0 (#1101) * chore(deps): update node.js to v24.18.0 * fix: revert node image to 24.16.0-alpine3.24 with valid multi-arch digest node:24.18.0-alpine3.24@sha256:eb37f58646... was published to Docker Hub today with an empty OCI image index (zero platform entries), making it unpullable on any platform. All node:24.18.x tags share this broken digest, indicating a Docker Hub publishing failure for that release. Revert to node:24.16.0-alpine3.24@sha256:fb71d01... which has 6 confirmed platform manifests (linux/amd64, linux/arm64, s390x) and produces a successful docker build --target frontend-builder. * fix: upgrade node image to 24.17.0 and patch undici CVE-2026-12151 node:24.16.0-alpine3.24 carries two HIGH CVEs: - CVE-2026-45447: OpenSSL heap-use-after-free in libcrypto3 (fixed in 3.5.7-r0) - CVE-2026-12151: undici DoS via unbounded memory (fixed in undici 6.27.0) node:24.17.0-alpine3.24 resolves the OpenSSL CVE via apk upgrade and ships a valid 6-platform manifest (linux/amd64, linux/arm64, s390x), making it the highest patched Node 24 image with a working multi-arch index. node:24.18.0 was published to Docker Hub with an empty OCI manifest index (zero platform entries) — a Docker Hub publishing failure — so it cannot be used until Docker Hub resolves the issue. Patch the remaining undici CVE-2026-12151 via targeted npm install -g, following the same pattern as the existing picomatch CVE patch. Remove both patches once a Node 24 image ships with undici >=6.27.0. --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: GitHub Actions <actions@github.com> * chore(deps): update github-actions-non-major (#1100) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore: bump @types/node from 26.0.0 to 26.0.1 * chore: bump go-pkcs12 from v0.7.2 to v0.7.3 * chore(deps): update node.js to v24.18.0 (#1102) * chore(deps): update node.js to v24.18.0 * chore: update node frontend-builder image digest --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jeremy <jhatfield82@gmail.com> Co-authored-by: GitHub Actions <actions@github.com> * chore(deps): bump eslint-plugin-unicorn from 68 to 69 * chore(deps): update dockerfile-non-major (#1103) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update module gorm.io/gorm to v1.31.2 (#1105) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update release-drafter/release-drafter digest to 73b95fa (#1104) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): bump frontend dev dependencies to latest versions * chore: bump tar to 7.5.17 and expect-type to 1.4.0 * chore: bump es-to-primitive from 1.3.1 to 1.3.3 * refactor(scripts): merge go_update.sh and npm_update.sh into dep_update.sh - Consolidate Go and npm update scripts into a single script - Use repo-relative paths instead of hardcoded /projects/Charon - Add type-check and test steps to npm update flow - Allow npm audit fix and outdated to fail without aborting * chore: remove test step from dep_update.sh module loop * docs(security): add CVE-2026-39824 analysis and CHANGELOG entry Document golang.org/x/sys vulnerability assessment confirming v0.46.0 already exceeds the v0.44.0 fix; Linux-only deployment excludes the vulnerable Windows code path entirely. Includes govulncheck clean-scan evidence and Trivy false-positive explanation. * chore(deps): update module golang.org/x/vuln to v1.5.0 (#1107) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update release-drafter/release-drafter digest to 4d75298 (#1106) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): bump es-toolkit from 1.48.1 to 1.49.0 * chore(deps): update actions/cache digest to 55cc834 (#1108) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): bump modernc and golang.org/x indirect deps * chore: bump prettier and analyze-trace to latest patch versions * chore(deps): bump i18next, eslint, and knip to latest versions * chore(deps): update dependency anchore/grype to v0.115.0 (#1109) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency anchore/syft to v1.46.0 (#1110) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jeremy <jhatfield82@gmail.com> * chore: bump prometheus/procfs from v0.20.1 to v0.21.0 * chore: bump prettier to 3.9.1 and tar to 7.5.19 * chore(deps): bump react-query to 5.101.2 and knip to 6.22.0 * fix(renovate): add sourceUrl for prometheus/client_golang lookup * chore(renovate): disable js-yaml auto-updates, managed manually * chore(docker): update GeoLite2-Country.mmdb checksum (#1111) Automated checksum update for GeoLite2-Country.mmdb database. Old: 6e9212f23d3279a2454404d3b2a7ac30159fddbb9870ba33763014877296455c New: 1522faf7b5f6a96c3a0128bca813bd4b0ae24dce38e9d37acdff0efaa75fcdd9 Auto-generated by: .github/workflows/update-geolite2.yml Co-authored-by: Wikid82 <176516789+Wikid82@users.noreply.github.com> * chore(deps): bump eslint-plugin-import-x and knip dev dependencies * fix(ci): squash merge warning and safe PR number env var --------- Co-authored-by: Jeremy <jhatfield82@gmail.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: GitHub Actions <actions@github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Wikid82 <176516789+Wikid82@users.noreply.github.com>
1 parent 3687b94 commit 9e14c28

104 files changed

Lines changed: 10560 additions & 1254 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/settings.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"enabledPlugins": {
3+
"frontend-design@claude-plugins-official": true,
4+
"superpowers@claude-plugins-official": true,
5+
"github@claude-plugins-official": true,
6+
"playwright@claude-plugins-official": true,
7+
"typescript-lsp@claude-plugins-official": true,
8+
"semgrep@claude-plugins-official": true,
9+
"pr-review-toolkit@claude-plugins-official": true
10+
},
11+
"worktree": {
12+
"bgIsolation": "none"
13+
}
14+
}

.github/renovate.json

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727

2828
"ignoreDeps": [
2929
"github.com/gorilla/websocket",
30-
"github.com/golang-jwt/jwt/v5"
30+
"github.com/golang-jwt/jwt/v5",
31+
"js-yaml"
3132
],
3233

3334
"minimumReleaseAge": null,
@@ -413,16 +414,6 @@
413414
]
414415
},
415416
"packageRules": [
416-
{
417-
"description": "Pin js-yaml to v4.x — transitive dependents (@eslint/eslintrc, markdownlint-cli2) use v4 API internally; v5 is a breaking rewrite incompatible with their pinned calls",
418-
"matchDatasources": [
419-
"npm"
420-
],
421-
"matchPackageNames": [
422-
"js-yaml"
423-
],
424-
"allowedVersions": "<5.0.0"
425-
},
426417
{
427418
"description": "Group GitHub Actions non-major updates into one PR",
428419
"matchManagers": [
@@ -753,6 +744,23 @@
753744
"github.com/gin-contrib/sse"
754745
],
755746
"sourceUrl": "https://github.com/gin-contrib/sse"
747+
},
748+
{
749+
"description": "Fix Renovate lookup for prometheus/client_golang",
750+
"matchDatasources": [
751+
"go"
752+
],
753+
"matchPackageNames": [
754+
"github.com/prometheus/client_golang"
755+
],
756+
"sourceUrl": "https://github.com/prometheus/client_golang"
757+
},
758+
{
759+
"description": "Disable js-yaml updates — pinned in overrides for security; managed manually",
760+
"matchPackageNames": [
761+
"js-yaml"
762+
],
763+
"enabled": false
756764
}
757765
]
758766
}

.github/skills/examples/gorm-scanner-ci-workflow.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
2424

2525
- name: Setup Go
26-
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
26+
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
2727
with:
2828
go-version: "1.26.4"
2929

.github/skills/security-scan-docker-image-scripts/run.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ fi
3535
# Check Grype
3636
if ! command -v grype >/dev/null 2>&1; then
3737
log_error "Grype not found - install from: https://github.com/anchore/grype"
38-
log_error "Installation: curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin v0.114.0"
38+
log_error "Installation: curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin v0.115.0"
3939
error_exit "Grype is required for vulnerability scanning" 2
4040
fi
4141

@@ -50,8 +50,8 @@ SYFT_INSTALLED_VERSION=$(syft version | grep -oP 'Version:\s*\Kv?[0-9]+\.[0-9]+\
5050
GRYPE_INSTALLED_VERSION=$(grype version | grep -oP 'Version:\s*\Kv?[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "unknown")
5151

5252
# Set defaults matching CI workflow
53-
set_default_env "SYFT_VERSION" "v1.45.1"
54-
set_default_env "GRYPE_VERSION" "v0.114.0"
53+
set_default_env "SYFT_VERSION" "v1.46.0"
54+
set_default_env "GRYPE_VERSION" "v0.115.0"
5555
set_default_env "IMAGE_TAG" "charon:local"
5656
set_default_env "FAIL_ON_SEVERITY" "Critical,High"
5757

.github/workflows/auto-changelog.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ jobs:
2424
with:
2525
ref: ${{ github.event.workflow_run.head_sha || github.sha }}
2626
- name: Draft Release
27-
uses: release-drafter/release-drafter@ed4bc48ec97379be2258e7b7ac2624a3e26ab809 # v7
27+
uses: release-drafter/release-drafter@4d75298e00d9e34c483e5ff8c68d0ea1c1940c1e # v7
2828
env:
2929
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/benchmark.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
ref: ${{ github.event.pull_request.head.sha || github.event.workflow_run.head_sha || github.sha }}
4040

4141
- name: Set up Go
42-
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
42+
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
4343
with:
4444
go-version-file: backend/go.mod
4545

.github/workflows/codecov-upload.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ concurrency:
2424

2525
env:
2626
GO_VERSION: '1.26.4'
27-
NODE_VERSION: '24.17.0'
27+
NODE_VERSION: '24.18.0'
2828
GOTOOLCHAIN: local
2929

3030
permissions:
@@ -45,7 +45,7 @@ jobs:
4545
ref: ${{ github.sha }}
4646

4747
- name: Set up Go
48-
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
48+
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
4949
with:
5050
go-version-file: backend/go.mod
5151

.github/workflows/codeql.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ jobs:
6363

6464
- name: Setup Go
6565
if: matrix.language == 'go'
66-
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
66+
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
6767
with:
6868
go-version-file: backend/go.mod
6969
cache-dependency-path: backend/go.sum

.github/workflows/docs-to-issues.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ concurrency:
2323
cancel-in-progress: false
2424

2525
env:
26-
NODE_VERSION: '24.17.0'
26+
NODE_VERSION: '24.18.0'
2727

2828
permissions:
2929
contents: write

.github/workflows/docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ concurrency:
1818
cancel-in-progress: false
1919

2020
env:
21-
NODE_VERSION: '24.17.0'
21+
NODE_VERSION: '24.18.0'
2222

2323
jobs:
2424
build:

0 commit comments

Comments
 (0)