fix(frontend): stabilize CrowdSec first-enable UX and guard empty-value regression#859
fix(frontend): stabilize CrowdSec first-enable UX and guard empty-value regression#859Wikid82 wants to merge 40 commits intodevelopmentfrom
Conversation
…n-major-updates chore(deps): update dependency knip to ^5.88.0 (feature/beta-release)
…n and uptime service tests
…across documentation, frontend development, planning, Playwright testing, QA security, and supervisor roles.
…nd libssl3 with justification and review timeline
…ue regression When CrowdSec is first enabled, the 10-60 second startup window caused the toggle to immediately flicker back to unchecked, the card badge to show 'Disabled' throughout startup, CrowdSecKeyWarning to flash before bouncer registration completed, and CrowdSecConfig to show alarming LAPI-not-ready banners to the user. Root cause: the toggle, badge, and warning conditions all read from stale sources (crowdsecStatus local state and status.crowdsec.enabled server data) which neither reflects user intent during a pending mutation. - Derive crowdsecChecked from crowdsecPowerMutation.variables during the pending window so the UI reflects intent immediately on click, not the lagging server state - Show a 'Starting...' badge in warning variant throughout the startup window so the user knows the operation is in progress - Suppress CrowdSecKeyWarning unconditionally while the mutation is pending, preventing the bouncer key alert from flashing before registration completes on the backend - Broadcast the mutation's running state to the QueryClient cache via a synthetic crowdsec-starting key so CrowdSecConfig.tsx can read it without prop drilling - In CrowdSecConfig, suppress the LAPI 'not running' (red) and 'initializing' (yellow) banners while the startup broadcast is active, with a 90-second safety cap to prevent stale state from persisting if the tab is closed mid-mutation - Add security.crowdsec.starting translation key to all five locales - Add two backend regression tests confirming that empty-string setting values are accepted (not rejected by binding validation), preventing silent re-introduction of the Issue 4 bug - Add nine RTL tests covering toggle stabilization, badge text, warning suppression, and LAPI banner suppression/expiry - Add four Playwright E2E tests using route interception to simulate the startup delay in a real browser context Fixes Issues 3 and 4 from the fresh-install bug report.
|
You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool. What Enabling Code Scanning Means:
For more information about GitHub Code Scanning, check out the documentation. |
✅ Supply Chain Verification Results✅ PASSED 📦 SBOM Summary
🔍 Vulnerability Scan
📎 Artifacts
Generated by Supply Chain Verification workflow • View Details |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…n-major-updates fix(deps): update non-major-updates (feature/beta-release)
There was a problem hiding this comment.
Pull request overview
This PR stabilizes the “enable CrowdSec on fresh install” UX during the long-running startup mutation by reflecting user intent immediately, suppressing transient warnings/banners during startup, and adding regression tests for the empty-value settings fix.
Changes:
- Stabilize CrowdSec toggle/badge/warning behavior while the start mutation is pending, including a new “Starting…” badge state.
- Coordinate “CrowdSec is starting” state across
Security→CrowdSecConfigvia TanStack Query cache to suppress LAPI banners during startup. - Add/expand automated coverage: RTL unit tests, Playwright E2E tests, and backend regression tests; plus dependency and security-scan housekeeping updates.
Reviewed changes
Copilot reviewed 32 out of 34 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/security/crowdsec-first-enable.spec.ts | New Playwright E2E coverage for first-enable UX and empty setting value acceptance |
| frontend/src/pages/tests/Security.crowdsec.test.tsx | New RTL tests for pending-mutation UX in Security |
| frontend/src/pages/tests/CrowdSecConfig.crowdsec.test.tsx | New RTL tests for startup banner suppression + 90s safety cap |
| frontend/src/pages/Security.tsx | Derive checked state from pending mutation variables; add “Starting…” badge; suppress key warning while pending; broadcast starting state |
| frontend/src/pages/CrowdSecConfig.tsx | Read synthetic crowdsec-starting query cache state and suppress LAPI warning banners during startup |
| frontend/src/locales/en/translation.json | Add security.crowdsec.starting string |
| frontend/src/locales/de/translation.json | Add security.crowdsec.starting string |
| frontend/src/locales/es/translation.json | Add security.crowdsec.starting string |
| frontend/src/locales/fr/translation.json | Add security.crowdsec.starting string |
| frontend/src/locales/zh/translation.json | Add security.crowdsec.starting string |
| frontend/package.json | Bump frontend deps (@tanstack/react-query, Tailwind-related, knip) |
| docs/reports/qa_security_scan_report.md | New QA security scan report documenting upstream-blocked OpenSSL CVE |
| docs/reports/qa_report_pr4.md | New QA report for PR-4 results/coverage/security checks |
| backend/internal/services/uptime_service_test.go | Adjust RFC1918 bypass integration tests (server readiness + DB create handling changed) |
| backend/internal/security/url_validator_test.go | Relax/adjust AllowRFC1918 URL validator tests and metadata/mapped cases |
| backend/internal/security/url_validator.go | Modify IPv4-mapped IPv6 private-IP error handling text/formatting |
| backend/internal/api/tests/user_smtp_audit_test.go | Test setup updates (bcrypt min-cost helper; invite token assertions improved) |
| backend/internal/api/handlers/settings_handler_test.go | Add regression tests ensuring empty setting values are accepted and missing key is rejected |
| backend/go.mod | Update indirect Go deps (e.g., morikuni/aec, objx, OTLP trace exporter) |
| backend/go.sum | Corresponding checksum updates for bumped Go deps |
| .trivyignore | Suppress CVE-2026-2673 (OpenSSL in Alpine) with review/expiry notes |
| .grype.yaml | Add Grype suppressions for CVE-2026-2673 (libcrypto3/libssl3) with expiry/justification |
| .github/workflows/security-pr.yml | Update pinned github/codeql-action/upload-sarif SHA |
| .github/workflows/e2e-tests-split.yml | Update pinned actions/cache SHA |
| .github/agents/Supervisor.agent.md | Simplify/normalize tools: list in agent frontmatter |
| .github/agents/QA_Security.agent.md | Simplify/normalize tools: list in agent frontmatter |
| .github/agents/Playwright_Dev.agent.md | Simplify/normalize tools: list in agent frontmatter |
| .github/agents/Planning.agent.md | Simplify/normalize tools: list in agent frontmatter |
| .github/agents/Frontend_Dev.agent.md | Simplify/normalize tools: list in agent frontmatter |
| .github/agents/Doc_Writer.agent.md | Simplify/normalize tools: list in agent frontmatter |
| .github/agents/DevOps.agent.md | Simplify/normalize tools: list in agent frontmatter |
| .github/agents/Backend_Dev.agent.md | Simplify/normalize tools: list in agent frontmatter |
Files not reviewed (1)
- frontend/package-lock.json: Language not supported
You can also share your feedback on Copilot code review. Take the survey.
…revent misleading failures
There was a problem hiding this comment.
Pull request overview
Stabilizes the first-time CrowdSec enable experience by making the Security dashboard reflect user intent during the long-running startup mutation, coordinating “starting” state across pages via TanStack Query cache, and adding regression coverage (frontend RTL, Playwright E2E, backend handler tests).
Changes:
- Make CrowdSec toggle/badge/key-warning UI derive from mutation pending state (including a “Starting...” badge state).
- Broadcast/read a synthetic
['crowdsec-starting']cache signal to suppress noisy CrowdSecConfig LAPI banners during startup (with a 90s safety cap). - Add test coverage (RTL + Playwright + backend tests) and update security scan suppressions/workflow pins/deps.
Reviewed changes
Copilot reviewed 32 out of 34 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/security/crowdsec-first-enable.spec.ts | Adds Playwright E2E coverage for “first enable” pending-state UX and empty-value setting acceptance. |
| frontend/src/pages/tests/Security.crowdsec.test.tsx | Adds RTL tests asserting toggle/badge/warning behavior during pending/success/error states. |
| frontend/src/pages/tests/CrowdSecConfig.crowdsec.test.tsx | Adds RTL tests for suppressing LAPI warning banners during startup with fake timers. |
| frontend/src/pages/Security.tsx | Implements pending-derived crowdsecChecked, “Starting...” badge, suppresses key warning during pending, and broadcasts startup state to query cache. |
| frontend/src/pages/CrowdSecConfig.tsx | Reads startup signal from query cache and suppresses LAPI banners while startup is in progress (with 90s guard). |
| frontend/src/locales/en/translation.json | Adds security.crowdsec.starting translation key. |
| frontend/src/locales/de/translation.json | Adds security.crowdsec.starting translation key. |
| frontend/src/locales/es/translation.json | Adds security.crowdsec.starting translation key. |
| frontend/src/locales/fr/translation.json | Adds security.crowdsec.starting translation key. |
| frontend/src/locales/zh/translation.json | Adds security.crowdsec.starting translation key. |
| frontend/package.json | Bumps a few frontend dependencies (React Query, Tailwind-related, knip). |
| backend/internal/api/handlers/settings_handler_test.go | Adds regression tests ensuring empty setting values are accepted and missing keys are rejected. |
| backend/internal/security/url_validator_test.go | Adjusts URL validation tests to avoid overly strict assumptions about resolution errors while still checking the security invariant. |
| backend/internal/security/url_validator.go | Simplifies private-IP error messaging and ensures cloud-metadata error remains specific for IPv4-mapped IPv6. |
| backend/internal/api/tests/user_smtp_audit_test.go | Improves invite-token assertions and speeds up password hashing in tests. |
| backend/go.mod | Updates indirect dependencies. |
| backend/go.sum | Updates dependency checksums to match go.mod changes. |
| .trivyignore | Suppresses CVE-2026-2673 with a documented expiry/review plan. |
| .grype.yaml | Adds detailed suppression entries for CVE-2026-2673 (libcrypto3/libssl3) with expiry and removal criteria. |
| .github/workflows/security-pr.yml | Updates pinned upload-sarif action SHA. |
| .github/workflows/e2e-tests-split.yml | Updates pinned actions/cache SHA. |
| docs/reports/qa_security_scan_report.md | Adds QA security scan report documenting upstream-blocked OpenSSL CVE status. |
| docs/reports/qa_report_pr4.md | Adds a QA report capturing checks/coverage notes for this PR. |
| .github/agents/Supervisor.agent.md | Simplifies/normalizes tool declarations for the Supervisor agent. |
| .github/agents/QA_Security.agent.md | Simplifies/normalizes tool declarations for the QA Security agent. |
| .github/agents/Playwright_Dev.agent.md | Simplifies/normalizes tool declarations for the Playwright Dev agent. |
| .github/agents/Planning.agent.md | Simplifies/normalizes tool declarations for the Planning agent. |
| .github/agents/Frontend_Dev.agent.md | Simplifies/normalizes tool declarations for the Frontend Dev agent. |
| .github/agents/Doc_Writer.agent.md | Simplifies/normalizes tool declarations for the Docs Writer agent. |
| .github/agents/DevOps.agent.md | Simplifies/normalizes tool declarations for the DevOps agent. |
| .github/agents/Backend_Dev.agent.md | Simplifies/normalizes tool declarations for the Backend Dev agent. |
Files not reviewed (1)
- frontend/package-lock.json: Language not supported
You can also share your feedback on Copilot code review. Take the survey.
There was a problem hiding this comment.
Pull request overview
This PR stabilizes the CrowdSec “first enable” UX by making the Security dashboard reflect user intent immediately during the long-running startup mutation, suppressing transient warnings, and coordinating a temporary “starting” state across the Security and CrowdSecConfig pages. It also adds regression coverage to prevent reintroducing the backend empty-value validation bug.
Changes:
- Frontend: derive CrowdSec toggle/badge state from pending mutation variables; add “Starting…” badge; suppress key warning during startup; broadcast startup state via TanStack Query cache and suppress LAPI banners for up to 90s.
- Tests: add RTL + Playwright E2E coverage for the pending-startup UX, and backend regression tests for empty
valueacceptance. - Ops/tooling: dependency bumps, security scan documentation, CVE suppressions, and workflow/action pin updates.
Reviewed changes
Copilot reviewed 33 out of 35 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/security/crowdsec-first-enable.spec.ts | Adds Playwright E2E coverage for pending startup UX and empty setting value acceptance |
| frontend/src/pages/tests/Security.crowdsec.test.tsx | Adds RTL tests covering toggle/badge/warning behavior during pending/success/failure |
| frontend/src/pages/tests/CrowdSecConfig.crowdsec.test.tsx | Adds RTL tests covering banner suppression during startup window and expiry behavior |
| frontend/src/pages/Security.tsx | Implements derived crowdsecChecked, “Starting…” badge state, key-warning suppression, and cache broadcast |
| frontend/src/pages/CrowdSecConfig.tsx | Reads startup state from QueryClient cache and suppresses LAPI banners with a 90s guard |
| frontend/src/locales/en/translation.json | Adds security.crowdsec.starting i18n string |
| frontend/src/locales/de/translation.json | Adds security.crowdsec.starting i18n string |
| frontend/src/locales/es/translation.json | Adds security.crowdsec.starting i18n string |
| frontend/src/locales/fr/translation.json | Adds security.crowdsec.starting i18n string |
| frontend/src/locales/zh/translation.json | Adds security.crowdsec.starting i18n string |
| frontend/package.json | Bumps React Query / Tailwind / Knip versions |
| docs/reports/qa_security_scan_report.md | Adds security scan report (Trivy/Grype) documenting upstream-blocked OpenSSL CVE |
| docs/reports/qa_report_pr4.md | Adds QA report for this PR’s validation steps and results |
| backend/internal/security/url_validator_test.go | Adjusts URL validator tests around AllowRFC1918 and IPv4-mapped IPv6 behavior |
| backend/internal/security/url_validator.go | Refines error messaging for private IP blocking (incl. IPv4-mapped IPv6 path) |
| backend/internal/api/tests/user_smtp_audit_test.go | Improves audit tests (token checks) and speeds setup via bcrypt MinCost helper |
| backend/internal/api/handlers/settings_handler_test.go | Adds regression tests for empty-value acceptance and missing-key rejection |
| backend/go.mod | Updates indirect deps (aec, objx, otel exporter) |
| Dockerfile | Bumps caddy-security plugin version |
| .trivyignore | Adds CVE-2026-2673 suppression with review/expiry metadata |
| .grype.yaml | Adds CVE-2026-2673 suppressions for libcrypto3/libssl3 with expiry and justification |
| .github/workflows/security-pr.yml | Updates pinned CodeQL SARIF upload action SHA |
| .github/workflows/e2e-tests-split.yml | Updates pinned actions/cache SHA |
| .github/agents/Supervisor.agent.md | Simplifies tools frontmatter (but introduces parsing risk; see comments) |
| .github/agents/QA_Security.agent.md | Simplifies tools frontmatter (but introduces parsing risk; see comments) |
| .github/agents/Playwright_Dev.agent.md | Simplifies tools frontmatter (but introduces parsing risk; see comments) |
| .github/agents/Planning.agent.md | Simplifies tools frontmatter (but introduces parsing risk; see comments) |
| .github/agents/Frontend_Dev.agent.md | Simplifies tools frontmatter (but introduces parsing risk; see comments) |
| .github/agents/Doc_Writer.agent.md | Simplifies tools frontmatter (but introduces parsing risk; see comments) |
| .github/agents/DevOps.agent.md | Simplifies tools frontmatter (but introduces parsing risk; see comments) |
| .github/agents/Backend_Dev.agent.md | Simplifies tools frontmatter (but introduces parsing risk; see comments) |
Files not reviewed (1)
- frontend/package-lock.json: Language not supported
You can also share your feedback on Copilot code review. Take the survey.
There was a problem hiding this comment.
Pull request overview
This PR stabilizes the “first enable” CrowdSec experience on fresh installs by ensuring the UI reflects user intent during the long-running startup mutation, suppressing premature warnings/banners during that window, and adding regression coverage for the “empty setting value must be accepted” behavior. It also includes supporting test additions and maintenance updates (security scan suppressions, minor dependency bumps, CI pin updates).
Changes:
- Frontend UX: derive CrowdSec toggle/badge state from mutation variables while pending; add “Starting…” badge state; suppress key warning and startup banners via a shared React Query cache signal.
- Tests: add RTL unit tests and Playwright E2E coverage for the pending-mutation UX and the empty-value setting regression.
- Maintenance: update security scan ignore configuration for an upstream-blocked OpenSSL CVE with expiry/review notes; refresh a few dependency versions and pinned GitHub Actions SHAs.
Reviewed changes
Copilot reviewed 33 out of 35 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| tests/security/crowdsec-first-enable.spec.ts | New Playwright E2E coverage for CrowdSec first-enable pending UX + empty setting value API behavior |
| frontend/src/pages/tests/Security.crowdsec.test.tsx | New RTL tests asserting toggle/badge/warning behavior while startup mutation is pending |
| frontend/src/pages/tests/CrowdSecConfig.crowdsec.test.tsx | New RTL tests asserting LAPI banner suppression while startup signal is active (with fake timers) |
| frontend/src/pages/Security.tsx | Stabilize toggle/badge via derived crowdsecChecked; suppress key warning during pending; broadcast startup state via QueryClient cache |
| frontend/src/pages/CrowdSecConfig.tsx | Read startup signal from QueryClient cache; suppress LAPI warning banners during startup with a 90s safety cap |
| frontend/src/locales/en/translation.json | Add security.crowdsec.starting translation |
| frontend/src/locales/de/translation.json | Add security.crowdsec.starting translation |
| frontend/src/locales/es/translation.json | Add security.crowdsec.starting translation |
| frontend/src/locales/fr/translation.json | Add security.crowdsec.starting translation |
| frontend/src/locales/zh/translation.json | Add security.crowdsec.starting translation |
| frontend/package.json | Minor dependency bumps (React Query, Tailwind/PostCSS, knip) |
| docs/reports/qa_security_scan_report.md | New report documenting upstream-blocked OpenSSL CVE findings and recommended monitoring/actions |
| docs/reports/qa_report_pr4.md | New QA report capturing test/lint/typecheck/security-scan status for this PR’s changes |
| backend/internal/security/url_validator_test.go | Adjust URL validator tests to match updated error behavior and avoid leaking IPv4-mapped forms |
| backend/internal/security/url_validator.go | Align private-IP / metadata blocking errors for IPv4-mapped IPv6 and avoid leaking raw mapped form |
| backend/internal/api/tests/user_smtp_audit_test.go | Test-only helper for fast bcrypt hashes; tighten invite-token validation assertions |
| backend/internal/api/handlers/settings_handler_test.go | Add regression tests: empty value accepted (200) and missing key rejected (400) |
| backend/go.mod | Indirect dependency updates |
| Dockerfile | Bump caddy-security version used in build |
| .trivyignore | Add CVE-2026-2673 suppression with review/expiry notes (upstream-blocked) |
| .grype.yaml | Add package-specific CVE-2026-2673 suppressions (libcrypto3/libssl3) with expiry and justification |
| .github/workflows/security-pr.yml | Update pinned SHA for SARIF upload action |
| .github/workflows/e2e-tests-split.yml | Update pinned SHA for actions/cache |
| .github/agents/Supervisor.agent.md | Simplify/normalize agent tool list configuration |
| .github/agents/QA_Security.agent.md | Simplify/normalize agent tool list configuration |
| .github/agents/Playwright_Dev.agent.md | Simplify/normalize agent tool list configuration |
| .github/agents/Planning.agent.md | Simplify/normalize agent tool list configuration |
| .github/agents/Frontend_Dev.agent.md | Simplify/normalize agent tool list configuration |
| .github/agents/Doc_Writer.agent.md | Simplify/normalize agent tool list configuration |
| .github/agents/DevOps.agent.md | Simplify/normalize agent tool list configuration |
| .github/agents/Backend_Dev.agent.md | Simplify/normalize agent tool list configuration |
Files not reviewed (1)
- frontend/package-lock.json: Language not supported
You can also share your feedback on Copilot code review. Take the survey.
…n-major-updates chore(deps): update non-major-updates (feature/beta-release)
…0 for improved compatibility
…, eslint-plugin-testing-library, i18next, and knip to latest versions for improved stability and performance
…n-major-updates fix(deps): update non-major-updates (feature/beta-release)
…ns for improved stability
…and i18next to latest versions for improved stability
… and expiry dates
… patch embedded binary CVEs
Problem
On a fresh install, enabling CrowdSec for the first time produces a broken 10–60 second experience:
CrowdSecKeyWarningflashes — appears briefly before bouncer registration completes on the backend/security/crowdsecduring startupRoot cause: the toggle, badge, and warning conditions all read from stale sources that don't reflect user intent until
onSuccessfires — which takes 10–60 seconds.Additionally, Issue 4 (empty-value setting rejection) was already fixed in PR-1. This PR adds a regression test to ensure
binding:"required"is never re-added toUpdateSettingRequest.Value.Fixes Issues 3 and 4 from the fresh-install bug report.
Solution
Toggle & Badge Stabilization (
Security.tsx)Derive
crowdsecCheckedfromcrowdsecPowerMutation.variableswhile the mutation is pending. This is an established pattern in the same file (used bygetMessage()at line ~241). The UI immediately reflects user intent rather than lagging server state.The badge gains a third state: "Starting..." (
variant="warning") during the pending window.Warning Suppression (
Security.tsx)CrowdSecKeyWarningis suppressed with&& !crowdsecPowerMutation.isPendingto prevent the bouncer-key alert from flashing before backend registration completes.Cross-Component Coordination (
Security.tsx→CrowdSecConfig.tsx)Security.tsxbroadcasts the mutation's running state to the TanStack Query cache via a synthetic['crowdsec-starting']key inonMutate/onSuccess/onError.CrowdSecConfig.tsxreads this viauseQuerywithstaleTime: Infinity(no HTTP call) and suppresses both LAPI warning banners for the duration. A 90-second safety cap prevents stale state from persisting if the tab is closed mid-mutation.Changes
frontend/src/pages/Security.tsxcrowdsecCheckedderived state; 6 condition replacements;CrowdSecKeyWarningsuppression;onMutate/onError/onSuccesscache broadcastfrontend/src/pages/CrowdSecConfig.tsxuseQuerycache read;isStartingUp90s guard; both LAPI banner conditions patchedfrontend/src/locales/{en,de,es,fr,zh}/translation.jsonsecurity.crowdsec.startingkey added to all 5 localesbackend/internal/api/handlers/settings_handler_test.gofrontend/src/pages/__tests__/Security.crowdsec.test.tsxfrontend/src/pages/__tests__/CrowdSecConfig.crowdsec.test.tsxvi.useFakeTimers()forinitialCheckCompleteguard)tests/security/crowdsec-first-enable.spec.tsTests
11 new tests across 3 test files (89.5% frontend coverage):
RTL —
Security.crowdsec.test.tsx:CrowdSecKeyWarningabsent while pendingRTL —
CrowdSecConfig.crowdsec.test.tsx(fake timers required):isStartingUpis trueisStartingUpis trueisStartingUpis falseBackend:
TestUpdateSetting_EmptyValueIsAccepted— POST withvalue: ""returns 200TestUpdateSetting_MissingKeyRejected— POST with nokeyfield returns 400Playwright (E2E, route-interception):
aria-checked="true"during 2s delayed API responseCrowdSecKeyWarningabsent during startup (with key-status endpoint returning rejected key)No Breaking Changes
crowdsecCheckedis a pure derived variable — no state shape changes['crowdsec-starting']QueryClient key is ephemeral in-memory only; removing this PR removes the key cleanlyonSuccess/onErrorlogic is fully preserved