Chromium cannot resolve Docker service hostnames (mock-saml) in CI.
Skip the two tests that require browser navigation to the IdP; the
other SAML tests (button visibility, SP metadata) still run.
SAML e2e tests were timing out in CI waiting for the IdP redirect.
Increase Playwright wait_for_url timeout from 10s to 30s and add a
health check on the mock-saml service container so it's ready before
tests start.
Remove 7 test files fully covered by e2e tests (admin, account, models,
API routes, integration MFA/OIDC, notifications). Trim 5 more files to
keep only edge cases not reachable via e2e.
Fix conftest to replace wiregui.db engine/session at import time so all
code uses the test database. Use session-scoped tables with per-test
savepoint isolation to prevent data leaking between tests.
- Add ECharts live traffic rate chart on device detail page (RX/s + TX/s
area lines, 60-point rolling window, human-readable byte axis)
- Add traffic rate display (B/s) next to RX/TX totals
- Add connection status column (green/yellow/red dot) to user and admin
device tables based on handshake age
- Add status badge to device detail page
- Reduce all UI refresh timers from 30s to 5s
- Add row click navigation on admin devices table
- Allow admins to view any device detail (not just their own)
- Fix rowClick event args (list not dict) on both device tables
- Add connection_status() helper in utils/time.py
Metrics collector (wiregui/collector.py):
- Standalone process spawned by web app when WG_METRICS_ENABLED=true
- Polls wg show dump every WG_METRICS_POLL_INTERVAL seconds (default 5)
- Updates device stats in PostgreSQL
- Pushes Prometheus-format metrics to VictoriaMetrics (if configured)
- Graceful shutdown on SIGTERM
Integration test stack (compose.yml):
- Unified compose file for dev, test, and integration modes
- VictoriaMetrics single-node TSDB for metrics storage
- 3 mock WireGuard client containers generating ping traffic
- Automated setup script seeds server keypair, admin user, client devices
- make test-stack-up: one command to start everything
- make test-stack-verify: validates metrics flowing end-to-end
Infrastructure:
- Makefile with targets for dev, test, integration, and production
- Integration tests verify VictoriaMetrics has data for all 3 clients
- Fix Dockerfile to include img/ directory
- Separate TESTS.md for test tracking, clean TODO.md for features only
- Put logo and title on same row in login page
- Use ui.code with syntax highlighting for nftables ruleset dialog
- Widen nftables dialog to 900px
- Limit WAN connectivity checks to last 10 entries
- Add transparent SVG logo to img/
- Serve img/ as static files, set SVG favicon
- Show logo on login page and header bar
- Theme Quasar CSS variables using logo palette:
light: primary #3598C3, secondary #5AA6B9, header navy gradient
dark: primary #5AA6B9, secondary #3598C3, darker header gradient
- Add valkey and mock-oidc services to both release and dev workflows
- Install Playwright with Chromium deps for headless e2e tests
- Set WG_REDIS_URL and MOCK_OIDC_HOST env vars for CI
- Make mock OIDC discovery URL configurable via MOCK_OIDC_HOST env var
- Add full test job (unit + e2e) to dev pipeline before Docker build
- Fix OIDC callback to extract email from ID token claims as fallback
- Add /auth/complete bridge page to transfer auth to NiceGUI storage
- Use window.location.href for OIDC login (full navigation for OAuth)
- Hide password change card for OIDC-only users
- Widen config dialog, use ui.code with syntax highlighting
- Switch QR codes to PNG base64 images
- Rename logging.py to log_config.py to avoid stdlib shadow
- Add mock-oauth2-server to compose.yml for dev/testing
Add WG_IDP_CONFIG_FILE env var to seed OIDC/SAML identity providers
from a YAML file at startup, enabling GitOps and IaC workflows.
Providers are upserted by id (merge strategy preserves manual additions).
Convert all e2e tests from NiceGUI User fixture to Playwright async API
with --headed and --slowmo flags for visual debugging. Add full OIDC
login flow test against the mock-oidc service.
Override fields now display the actual configured defaults (from
DB Settings or env vars) instead of empty placeholders. Fields
are still disabled when the "use default" toggle is on, but users
can see what values their device will get.
build_client_config was reading defaults (allowed IPs, DNS, endpoint,
MTU, keepalive) from env vars only, ignoring the values set in the
admin Settings page. Now reads from the Configuration DB table first,
falling back to env vars when no DB config exists.
- Add peer-to-peer and LAN-to-peers switches on the rules page
- Both settings persisted in configurations table and applied
as nftables chains on toggle
- Add "View nftables Rules" button to dump the live ruleset
for troubleshooting
- Rules page redesigned with card-based layout matching other
admin pages
- Rule create/edit/delete events fire as background tasks
allocate_ipv4/ipv6 was calling list(network.hosts()) which
materializes 4+ million IP objects for a /10 network, blocking
the event loop for 6+ seconds. Now uses random sampling with
O(1) per attempt — allocates in <1ms on any network size.
This was the root cause of WebSocket disconnects during device
creation in production.
Builds and pushes docker images on every push to dev branch.
Tags based on latest main release: e.g. v1.2.3.dev0, v1.2.3.dev5.
No tests — fast feedback loop for testing.
In production (WG_WG_ENABLED=true), on_device_created() runs multiple
WG and nftables subprocess calls that take seconds. The UI handler
was awaiting all of them before showing the config dialog, causing
WebSocket timeouts and page reloads.
Now the dialog/QR/download appears right after DB commit, and WG peer
+ firewall configuration runs as a background task via asyncio.create_task.
Replace subprocess calls to wg genkey/pubkey with cryptography
library's X25519PrivateKey. This eliminates the wg CLI dependency
for key generation, fixes device creation on machines without
wireguard-tools, and removes the event loop blocking that caused
WebSocket disconnects during device creation.
Also fix E2E test teardown to use a fresh engine for cleanup,
avoiding cross-event-loop issues with asyncpg connection pools.
generate_keypair() used synchronous subprocess.run() which blocked
the NiceGUI event loop during wg genkey/pubkey calls. This caused
WebSocket disconnects, page reloads, and the config dialog never
appearing after device creation.
Switched to asyncio.create_subprocess_exec so the event loop stays
responsive while waiting for the wg CLI.
Long-running async handlers (DB insert + WG events) can outlive
the client connection. Guard all UI operations after async work
with RuntimeError catches so disconnected clients don't crash.
AGPL-3.0-or-later ensures copyleft applies even when WireGUI is
run as a network service. README covers features, deployment,
env vars, and our stance against enshittification.
The ORM-based cleanup couldn't see devices created by the NiceGUI
app's session, so the user delete hit a FK constraint. Raw SQL
DELETE in correct order (children first) works reliably.
10 E2E tests using NiceGUI's User fixture:
- Device creation flow and name validation
- Password change (success, wrong current, mismatch, too short)
- API token creation, TOTP registration, invalid code rejection
- Account deletion with email confirmation
Tests live in tests/e2e/ with a separate conftest that loads the
NiceGUI testing plugin. CI runs unit and E2E tests as separate steps.
The config dialog was being created inside the create dialog's slot
context. When NiceGUI tried to attach the new dialog, the parent
slot was already marked for deletion, causing a RuntimeError.
The manual git clone doesn't set up HTTPS credentials like
actions/checkout did. Configure the extraheader with GITHUB_TOKEN
so git push can authenticate when creating release tags.
- Add Manrope as primary UI font via Google Fonts (wiregui/pages/style.py)
- Add dark/light/auto theme toggle in header, persisted to users.theme_preference
- Alembic migration for theme_preference column
- Redesign account page with card-based layout matching admin pages
- Convert settings page from tabs to stacked cards
- Replace all outline buttons with solid unelevated buttons
- Fix dark mode: remove hardcoded bg-grey-1/text-grey-7, use theme-safe colors
- Fix CI: add ca-certificates to release job for SSL cert verification
- Add no-coauthor and commit conventions to CLAUDE.md
The Forgejo runner's container images lack CA certificates, causing
actions/checkout@v4 to fail on SSL verification. Use direct git clone
(same approach as the test job) for release and docker jobs.
- Remove tabbed layout, stack all sections vertically
- Compact key-value rows for user details
- Dense bordered tables for API tokens and MFA methods
- Consistent button styling with proper padding (BTN_PRIMARY/OUTLINE/DANGER)
- Token creation with inline copy-to-clipboard banner
- TOTP registration with compact inline QR + form
- Danger zone with typed-email confirmation dialog
- Add .idea and .coverage to gitignore
- Fix CI: add node:20-slim container to release job
- Fix connectivity check URL to Cloudflare endpoint