Commit graph

48 commits

Author SHA1 Message Date
ee1d742a71 fix: add victoriametrics container in prod compose
Some checks failed
Dev / test (push) Failing after 2m47s
Dev / docker (push) Has been skipped
2026-03-31 19:17:18 -05:00
71a5f57105 feat: live traffic chart, connection status indicators, 5s refresh
Some checks failed
Dev / test (push) Failing after 2m43s
Dev / docker (push) Has been skipped
- 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
2026-03-31 19:12:33 -05:00
c5b66349d6 feat: WireGuard metrics collector + integration test stack
Some checks failed
Dev / test (push) Failing after 2m43s
Dev / docker (push) Has been skipped
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
2026-03-31 18:30:15 -05:00
70eb9f6b12 fix: run migrations before unit tests in CI
Some checks failed
Dev / test (push) Failing after 2m37s
Dev / docker (push) Has been skipped
Some unit tests (test_api_deps, test_server_key) are integration tests
that need DB tables. Move alembic upgrade head before unit tests.
2026-03-31 17:02:49 -05:00
06b5a3dc12 feat: comprehensive test suite + SAML auth fixes + mock SAML IdP
Some checks failed
Dev / test (push) Failing after 3m14s
Dev / docker (push) Has been skipped
Tests (198 unit + 70 e2e = 268 total):
- Add test_api_deps.py: Bearer token auth, get_current_api_user, require_admin
- Add test_wireguard_extended.py: ensure_interface, set_private_key, set_listen_port
- Add test_firewall_extended.py: _nft/_nft_batch errors, jump rules, policies
- Add test_mfa_login.py: MFA redirect, TOTP verify, invalid code, cancel
- Add test_magic_link_page.py: page render, submit, empty email, back to login
- Add test_admin_devices.py: list, filter, create, edit, delete, config dialog
- Add test_admin_rules.py: list, create, edit, delete (all DB-verified)
- Add test_admin_settings.py: defaults, security, OIDC/SAML providers
- Add test_saml_login.py: button visible, redirect, metadata, full login flow

Bug fixes:
- Fix SAML callback to use /auth/complete bridge (same fix as OIDC)
- Fix missing get_settings import in admin settings page
- Add SAML provider buttons to login page
- Make SAML strict mode configurable per-provider

Infrastructure:
- Add mock SimpleSAMLphp IdP to compose.yml with SP config
- Add mock-saml service to CI workflows (release + dev)
2026-03-31 16:52:29 -05:00
25cff5e4d9 fix: UI tweaks — login layout, nftables code widget, connectivity limit
All checks were successful
Dev / test (push) Successful in 5m1s
Dev / docker (push) Successful in 1m55s
- 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
2026-03-31 15:50:50 -05:00
0c11cddb53 feat: add logo and logo-inspired color theme
All checks were successful
Dev / test (push) Successful in 4m55s
Dev / docker (push) Successful in 2m9s
- 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
2026-03-31 15:43:21 -05:00
f2b04ea668 fix: use branch-based shallow clone in CI to avoid missing SHA
All checks were successful
Dev / test (push) Successful in 5m1s
Dev / docker (push) Successful in 2m1s
Clone with -b GITHUB_REF_NAME instead of depth=1 + checkout SHA,
which fails when the shallow clone doesn't include the target commit.
2026-03-31 15:21:44 -05:00
a06ce9e156 fix: add Playwright, Valkey, and mock-OIDC to CI pipelines
Some checks failed
Dev / test (push) Failing after 46s
Dev / docker (push) Has been skipped
- 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
2026-03-31 14:48:27 -05:00
2163c89b6a feat: fix OIDC auth flow, improve config dialogs, add mock IdP
All checks were successful
Dev / docker (push) Successful in 2m16s
- 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
2026-03-31 14:28:34 -05:00
4d7a4810ff Merge remote-tracking branch 'refs/remotes/origin/dev'
Some checks failed
Dev / docker (push) Has been cancelled
CI / test (push) Failing after 1m52s
CI / release (push) Has been skipped
CI / docker (push) Has been skipped
# Conflicts:
#	TODO.md
2026-03-31 14:26:44 -05:00
3bf6fabcff feat: IdP provisioning from YAML file + Playwright e2e tests
Some checks failed
CI / test (push) Failing after 1m52s
CI / release (push) Has been skipped
CI / docker (push) Has been skipped
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.
2026-03-31 14:23:31 -05:00
Stefano Bertelli
e63f27b8a3 feat: show default values in device create dialog
All checks were successful
Dev / docker (push) Successful in 2m3s
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.
2026-03-31 00:21:56 -05:00
Stefano Bertelli
9aa58fbf22 fix: client config uses DB settings instead of only env vars
All checks were successful
Dev / docker (push) Successful in 1m56s
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.
2026-03-31 00:17:29 -05:00
Stefano Bertelli
d3705d224b chore: update TODO with pending items only
All checks were successful
Dev / docker (push) Successful in 1m54s
2026-03-31 00:13:54 -05:00
Stefano Bertelli
f608c542d1 fix: friendlier error when nft lacks permissions
All checks were successful
Dev / docker (push) Successful in 2m12s
2026-03-31 00:04:27 -05:00
Stefano Bertelli
49b2bd9083 feat: firewall policy switches and nftables troubleshooting
All checks were successful
Dev / docker (push) Successful in 2m6s
- 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
2026-03-31 00:00:21 -05:00
Stefano Bertelli
15e1b6360a fix: O(1) IP allocation instead of materializing entire network
All checks were successful
Dev / docker (push) Successful in 1m51s
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.
2026-03-30 23:43:59 -05:00
Stefano Bertelli
c9ef58a244 fix: add --no-cache to docker builds to prevent stale images
Some checks failed
CI / test (push) Failing after 2m7s
CI / release (push) Has been skipped
CI / docker (push) Has been skipped
Docker layer caching on the runner was reusing old layers even
when source code changed, resulting in images with outdated code.
2026-03-30 23:36:05 -05:00
Stefano Bertelli
fab5ad29d4 fix: add --no-cache to docker builds to prevent stale images
All checks were successful
Dev / docker (push) Successful in 2m22s
Docker layer caching on the runner was reusing old layers even
when source code changed, resulting in images with outdated code.
2026-03-30 23:35:44 -05:00
Stefano Bertelli
1c9de39079 chore: add dev branch pipeline for pre-release images
All checks were successful
Dev / docker (push) Successful in 7s
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.
2026-03-30 23:32:01 -05:00
Stefano Bertelli
a8784eec9c fix: show config dialog immediately, run WG/firewall setup in background
All checks were successful
CI / test (push) Successful in 2m5s
CI / release (push) Successful in 35s
CI / docker (push) Successful in 55s
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.
2026-03-30 23:24:51 -05:00
Stefano Bertelli
44c20cb66b fix: white background for QR codes in dark mode
All checks were successful
CI / test (push) Successful in 2m3s
CI / release (push) Successful in 35s
CI / docker (push) Successful in 55s
2026-03-30 23:14:57 -05:00
Stefano Bertelli
41a62832f7 fix: pure Python keypair generation, no wg CLI dependency
Some checks failed
CI / test (push) Successful in 2m5s
CI / release (push) Successful in 34s
CI / docker (push) Has been cancelled
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.
2026-03-30 23:11:58 -05:00
Stefano Bertelli
92554d4089 fix: make keypair generation async to avoid blocking the event loop
All checks were successful
CI / test (push) Successful in 1m58s
CI / release (push) Successful in 35s
CI / docker (push) Successful in 35s
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.
2026-03-30 22:57:00 -05:00
Stefano Bertelli
e51c53f247 fix: handle client disconnect during device creation
All checks were successful
CI / test (push) Successful in 2m9s
CI / release (push) Successful in 36s
CI / docker (push) Successful in 1m11s
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.
2026-03-30 22:51:22 -05:00
Stefano Bertelli
384b95b81d chore: add AGPL-3.0 license and README
All checks were successful
CI / test (push) Successful in 1m55s
CI / release (push) Successful in 29s
CI / docker (push) Has been skipped
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.
2026-03-30 22:45:10 -05:00
Stefano Bertelli
3747b963cb fix: use raw SQL for E2E test teardown to avoid FK violations
All checks were successful
CI / test (push) Successful in 2m2s
CI / release (push) Successful in 34s
CI / docker (push) Successful in 59s
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.
2026-03-30 22:34:06 -05:00
Stefano Bertelli
e59ba0dfe5 fix: run alembic migrations before E2E tests in CI
Some checks failed
CI / test (push) Failing after 2m8s
CI / release (push) Has been skipped
CI / docker (push) Has been skipped
The unit tests drop all tables on teardown, so the E2E step
needs to recreate the schema via alembic before running.
2026-03-30 22:29:55 -05:00
Stefano Bertelli
5adb0c86ce feat: add E2E tests for device creation and account management
Some checks failed
CI / test (push) Failing after 2m4s
CI / release (push) Has been skipped
CI / docker (push) Has been skipped
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.
2026-03-30 22:26:15 -05:00
Stefano Bertelli
3d1ca7444b fix: close create dialog before showing config dialog
All checks were successful
CI / test (push) Successful in 1m44s
CI / release (push) Successful in 30s
CI / docker (push) Successful in 49s
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.
2026-03-30 22:13:11 -05:00
Stefano Bertelli
2eb35e94e9 fix: configure git auth for tag push in release job
All checks were successful
CI / test (push) Successful in 1m34s
CI / release (push) Successful in 35s
CI / docker (push) Successful in 2m22s
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.
2026-03-30 21:47:25 -05:00
Stefano Bertelli
1fc80b9c0a feat: UI modernization — Manrope font, dark/light theme, card-based layouts
Some checks failed
CI / test (push) Successful in 1m48s
CI / release (push) Failing after 29s
CI / docker (push) Has been skipped
- 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
2026-03-30 21:40:29 -05:00
Stefano Bertelli
3601de3600 fix: replace actions/checkout with git clone to avoid SSL cert errors
Some checks failed
CI / test (push) Successful in 1m46s
CI / release (push) Failing after 25s
CI / docker (push) Has been skipped
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.
2026-03-30 20:56:42 -05:00
1b48702295 fix: install git before checkout in release job
Some checks failed
CI / test (push) Successful in 1m41s
CI / release (push) Failing after 52s
CI / docker (push) Has been skipped
2026-03-30 19:45:13 -05:00
8282f53478 fix: install git and python3 in release job
Some checks failed
CI / test (push) Successful in 1m45s
CI / release (push) Failing after 29s
CI / docker (push) Has been skipped
2026-03-30 19:40:59 -05:00
792a9a4151 fix: install bash in release job (node:20-slim uses dash)
Some checks failed
CI / test (push) Successful in 1m40s
CI / release (push) Failing after 18s
CI / docker (push) Has been skipped
2026-03-30 19:37:08 -05:00
17fdfb8d61 chore: trigger CI to test service containers
Some checks failed
CI / test (push) Successful in 1m55s
CI / release (push) Failing after 23s
CI / docker (push) Has been skipped
2026-03-30 19:29:05 -05:00
78acae7947 fix: revert to GITHUB_SERVER_URL for git clone (runner URL now public)
Some checks failed
CI / test (push) Failing after 38s
CI / release (push) Has been skipped
CI / docker (push) Has been skipped
2026-03-30 19:16:50 -05:00
af3c20b274 fix: use public forge URL for git clone in CI (isolated network can't reach localhost)
Some checks failed
CI / test (push) Successful in 1m38s
CI / release (push) Failing after 55s
CI / docker (push) Has been skipped
2026-03-30 19:13:43 -05:00
b841835de0 fix: revert to service containers for CI postgres (runner network fixed)
Some checks failed
CI / test (push) Failing after 38s
CI / release (push) Has been skipped
CI / docker (push) Has been skipped
2026-03-30 19:12:11 -05:00
5ce17943d5 fix: CI run postgres in-container instead of service container
Some checks failed
CI / test (push) Failing after 2m18s
CI / release (push) Has been skipped
CI / docker (push) Has been skipped
2026-03-30 19:05:14 -05:00
bba8d113e4 fix: CI wait for postgres + better error handling
Some checks failed
CI / release (push) Blocked by required conditions
CI / docker (push) Blocked by required conditions
CI / test (push) Has been cancelled
2026-03-30 19:02:16 -05:00
2ecd0bbc33 fix: CI test DB — use main DB in CI, skip test DB creation
Some checks failed
CI / release (push) Blocked by required conditions
CI / docker (push) Blocked by required conditions
CI / test (push) Has been cancelled
2026-03-30 18:55:09 -05:00
651a054971 fix: use manual git checkout in test job (python:3.13-slim has no node)
Some checks failed
CI / test (push) Failing after 53s
CI / release (push) Has been skipped
CI / docker (push) Has been skipped
2026-03-30 18:52:08 -05:00
5aff71ec4c feat: redesign account page — compact Firezone-style layout
Some checks failed
CI / test (push) Failing after 8s
CI / release (push) Has been skipped
CI / docker (push) Has been skipped
- 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
2026-03-30 18:47:07 -05:00
9d9afbe3ad fix: CI runner containers for Forgejo actions 2026-03-30 18:22:42 -05:00
0546b44507 feat: initial WireGUI implementation — full VPN management platform
Some checks failed
CI / test (push) Failing after 26s
CI / release (push) Has been skipped
CI / docker (push) Has been skipped
Complete Python/NiceGUI rewrite of the Wirezone (Elixir/Phoenix) VPN
management platform. All 10 implementation phases delivered.

Core stack:
- NiceGUI reactive UI with SQLModel ORM on PostgreSQL (asyncpg)
- Alembic migrations, Valkey/Redis cache, pydantic-settings config
- WireGuard management via subprocess (wg/ip/nft CLIs)
- 164 tests passing, 35% code coverage

Features:
- User/device/rule CRUD with admin and unprivileged roles
- Full device config form with per-device WG overrides
- WireGuard client config generation with QR codes
- REST API (v0) with Bearer token auth for all resources
- TOTP MFA with QR registration and challenge flow
- OIDC SSO with authlib (provider registry, auto-create users)
- Magic link passwordless sign-in via email
- SAML SP-initiated SSO with IdP metadata parsing
- WebAuthn/FIDO2 security key registration
- nftables firewall with per-user chains and masquerade
- Background tasks: WG stats polling, VPN session expiry,
  OIDC token refresh, WAN connectivity checks
- Startup reconciliation (DB ↔ WireGuard state sync)
- In-memory notification system with header badge
- Admin UI: users, devices, rules, settings (3 tabs), diagnostics
- Loguru logging with optional timestamped file output

Deployment:
- Multi-stage Dockerfile (python:3.13-slim)
- Docker Compose prod stack (bridge networking, NET_ADMIN, nftables)
- Forgejo CI: tests → semantic versioning → Docker registry push
- Health endpoint at /api/health
2026-03-30 16:53:46 -05:00