Commit Graph

251 Commits

Author SHA1 Message Date
Jason Staack
9fcabb22d3 fix(lint): resolve ESLint errors in frontend components and tests
- Remove unused imports: Mock, VariableDef, within, Badge, deviceGroupsApi, devicesApi
- Fix Unexpected any in AlertRulesPage catch block (use unknown + type assertion)
- Suppress react-refresh/only-export-components for getPasswordScore helper
- Add Link mock to LoginPage test and useAuth.getState() stub for navigation test
- Fix DeviceList tests to use data-testid selectors and correct empty state text
  (component renders dual mobile/desktop views causing multiple-element errors)
- Remove unused container destructuring from TemplatePushWizard test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 22:20:07 -05:00
Jason Staack
06a41ca9bf fix(lint): resolve all ruff lint errors
Add ruff config to exclude alembic E402, SQLAlchemy F821, and pre-existing
E501 line-length issues. Auto-fix 69 unused imports and 2 f-strings without
placeholders. Manually fix 8 unused variables. Apply ruff format to 127 files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 22:17:50 -05:00
Jason Staack
2ad0367c91 fix(vpn): backport VPN fixes from production debugging
- Fix _commit_and_sync infinite recursion
- Use admin session for subnet_index allocation (bypass RLS)
- Auto-set VPN endpoint from CORS_ORIGINS hostname
- Remove server address field from VPN setup UI
- Add DELETE endpoint and button for VPN config removal
- Add wg-reload watcher for reliable config hot-reload via wg syncconf
- Add wg_status.json writer for live peer handshake status in UI
- Per-tenant SNAT for poller-to-device routing through VPN
- Restrict VPN→eth0 forwarding to Docker networks only (block exit node abuse)
- Use 10.10.0.0/16 allowed-address in RouterOS commands
- Fix structlog event= conflict (use audit=True)
- Export backup_scheduler proxy for firmware/upgrade imports
2026-03-14 20:59:14 -05:00
Jason Staack
b5f9bf14df fix(vpn): commit before sync_wireguard_config to ensure data visibility
sync_wireguard_config opens its own AdminAsyncSessionLocal connection
which cannot see uncommitted data from the caller's transaction. Add
_commit_and_sync helper that commits first, then regenerates wg0.conf.

Also removes the unused db parameter from sync_wireguard_config.
2026-03-14 16:42:17 -05:00
Jason Staack
b4a7494016 feat(vpn): update API error handling for subnet exhaustion and IP validation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 16:36:46 -05:00
Jason Staack
5fb6cba4de test(vpn): add integration tests for per-tenant VPN isolation
Tests subnet allocation (gap-filling, duplicate rejection), global
server key sharing, peer isolation across tenant subnets, allowed-IPs
overlap validation, RouterOS command generation, and CASCADE cleanup
on tenant deletion. sync_wireguard_config is patched to a no-op since
it opens its own DB session outside the test transaction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 16:35:39 -05:00
Jason Staack
9213a1a965 test: add VPN router to integration test app fixture
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 16:31:36 -05:00
Jason Staack
17d9d3e00f feat(vpn): regenerate wg0.conf on tenant deletion
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 16:31:33 -05:00
Jason Staack
5e70890d76 feat(vpn): refactor setup_vpn and sync_wireguard_config for multi-tenant isolation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 16:30:13 -05:00
Jason Staack
93fe935edf feat(vpn): add global server key helpers, subnet allocation, and allowed-IPs validation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 16:27:35 -05:00
Jason Staack
593323d277 feat(vpn): add subnet_index column and global server keypair migration
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 16:25:09 -05:00
Jason Staack
3330f2a62f feat(vpn): add tenant isolation iptables rules to forwarding script
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 16:24:38 -05:00
Jason Staack
b27b0fc946 feat(vpn): update WireGuard forwarding script with tenant isolation rules
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 16:24:30 -05:00
Jason Staack
eba87b1889 docs: add VPN per-tenant isolation design spec 2026-03-14 12:43:53 -05:00
Jason Staack
6fb0796e14 docs: add SaaS tiers and invite system design spec 2026-03-14 12:33:10 -05:00
Jason Staack
cfa18a4095 refactor: rename remaining mikrotik references to tod across CI, helm, frontend, and observability
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 12:03:51 -05:00
Jason Staack
183f9de0f1 fix(setup): create data dirs with correct ownership and WireGuard forwarding rules
- git-store and firmware-cache owned by appuser (uid 1001)
- wireguard/wg_confs set world-writable for API+WG container sharing
- Auto-create iptables forwarding init script for WireGuard
- Fix init-postgres-prod.sql permissions to 644 (postgres needs to read it)
2026-03-14 11:54:17 -05:00
Jason Staack
17fb0feb1e fix: add NET_ADMIN capability to poller for VPN route setup 2026-03-14 11:28:56 -05:00
Jason Staack
9b060c5fdf refactor: rename database from mikrotik to tod in backend code 2026-03-14 10:57:20 -05:00
Jason Staack
b2ea6f0d76 fix(setup): show waiting status during health check with countdown 2026-03-14 10:37:03 -05:00
Jason Staack
a10a0b106c feat(setup): use sudo for writing proxy configs to system directories 2026-03-14 10:29:12 -05:00
Jason Staack
5cf901eda8 feat(setup): add reverse proxy detection and configuration wizard 2026-03-14 10:28:21 -05:00
Jason Staack
ac624fcf5f fix(setup): remove env_file from base compose to prevent .env requirement in prod 2026-03-14 10:24:26 -05:00
Jason Staack
197f9e993e fix(setup): add env_file overrides for postgres, redis, nats in prod compose 2026-03-14 10:21:30 -05:00
Jason Staack
4757b93d9d fix(setup): address security and robustness issues
- Use dollar-quoting in generated SQL to prevent injection
- Set .env.prod and init-postgres-prod.sql to mode 0600
- Use run_compose for OpenBao log capture (consistent env-file)
- Prompt user before continuing if OpenBao bootstrap fails
- Improve mask_secret to fully mask short secrets
- Check sysctl return code before parsing RAM
2026-03-14 10:01:44 -05:00
Jason Staack
9123c6e6c0 refactor: rename database from mikrotik to tod in dev override 2026-03-14 09:59:25 -05:00
Jason Staack
934d630eb0 feat(setup): mount production init SQL and use env var for healthcheck 2026-03-14 09:58:44 -05:00
Jason Staack
4885d14a1d feat: add production setup wizard (setup.py)
Interactive Python script that:
- Runs pre-flight checks (Docker, RAM, port conflicts)
- Walks through database, security, admin, email, domain config
- Auto-generates JWT secrets, encryption keys, DB passwords
- Writes .env.prod and init-postgres-prod.sql
- Bootstraps OpenBao (captures unseal key + token from logs)
- Builds images sequentially (avoids OOM)
- Starts the stack and verifies service health
2026-03-14 09:58:16 -05:00
Jason Staack
bb546cf4bc fix: hide first-run credential hint in production builds 2026-03-14 09:56:01 -05:00
Jason Staack
64b3cce4b8 refactor: rename database from mikrotik to tod 2026-03-14 09:55:35 -05:00
Jason Staack
c7c9f4d71e docs: add setup script implementation plan
7-task plan covering database rename, login page fix, setup.py
wizard with OpenBao bootstrap, sequential builds, and health checks.
Also fixes spec OpenBao timeout to 60s.
2026-03-14 09:52:58 -05:00
Jason Staack
1d1d5d4694 docs: add setup script design spec
Design for setup.py — interactive production setup wizard that
auto-generates secrets, bootstraps OpenBao, builds images sequentially,
and verifies service health.
2026-03-14 09:45:15 -05:00
Jason Staack
970501e453 feat: implement Remote WinBox worker, API, frontend integration, OpenBao persistence, and supporting docs 2026-03-14 09:05:14 -05:00
Jason Staack
7af08276ea chore: remove .planning from tracking (already in .gitignore)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 06:55:28 -05:00
Jason Staack
ed3ad8eb17 chore: update about page to v9.6 and Dockerfile to Go 1.25
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 06:54:08 -05:00
Jason Staack
45bdbedfb0 docs(10-01): complete config backup audit events plan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:47:30 -05:00
Jason Staack
fb91fed5b9 test(10-01): add tests verifying audit events for config backup operations
- Test config_snapshot_created event on new snapshot
- Test config_snapshot_skipped_duplicate event on dedup match
- Test config_diff_generated event after diff stored
- Test config_backup_manual_trigger event on manual trigger success

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:45:58 -05:00
Jason Staack
1a1ceb2cb1 feat(10-01): add audit event logging to config backup operations
- config_snapshot_created event after successful snapshot INSERT
- config_snapshot_skipped_duplicate event on dedup match
- config_diff_generated event after diff INSERT
- config_backup_manual_trigger event on manual trigger success
- All log_action calls wrapped in try/except for safety

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:44:00 -05:00
Jason Staack
50211d1853 docs(09-01): complete retention cleanup plan
- Create 09-01-SUMMARY.md with execution results
- Update STATE.md with phase 9 position and decisions
- Update ROADMAP.md with phase 9 progress
- Mark STOR-03 and STOR-04 requirements complete

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:35:37 -05:00
Jason Staack
4d62bc9499 feat(09-01): wire retention scheduler into application lifespan
- Import start/stop_retention_scheduler in lifespan
- Start scheduler after config snapshot subscriber (non-fatal pattern)
- Stop scheduler during shutdown alongside other cleanup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:34:03 -05:00
Jason Staack
a9f7a45a9b feat(09-01): implement retention cleanup service with configurable retention period
- Add CONFIG_RETENTION_DAYS setting (default 90) to config.py
- Create retention_service.py with cleanup_expired_snapshots (parameterized SQL via make_interval)
- APScheduler IntervalTrigger runs cleanup every 24h with 1h jitter
- Prometheus counter and histogram for observability
- CASCADE FKs handle diff/change deletion automatically
- All 4 unit tests pass

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:33:27 -05:00
Jason Staack
00bdde9975 test(09-01): add failing tests for retention cleanup service
- Test cleanup deletes expired snapshots
- Test snapshots within retention window are kept
- Test deleted count is returned
- Test empty table handled gracefully

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:32:20 -05:00
Jason Staack
be41add4e9 feat(08-02): add snapshot download button to config history timeline
- Add SnapshotResponse interface and getSnapshot API method
- Add deviceName prop to ConfigHistorySection
- Add download handler that fetches snapshot and triggers .rsc file download
- Add Download icon button on each timeline entry with stopPropagation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:23:55 -05:00
Jason Staack
8a64596d8b docs(08-01): complete diff viewer plan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:22:22 -05:00
Jason Staack
2cf426fa63 feat(08-01): wire diff viewer into config history timeline
- Add click handlers to timeline entries to open diff viewer
- Render DiffViewer inline above timeline when snapshot selected
- Add hover state and cursor-pointer to timeline entries

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:20:52 -05:00
Jason Staack
dda00fbd23 feat(08-01): add diff viewer component and API client
- Add DiffResponse interface and getDiff method to configHistoryApi
- Create DiffViewer component with unified diff rendering
- Green highlighting for added lines, red for removed lines
- Blue styling for hunk headers, loading skeleton, error state

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:20:24 -05:00
Jason Staack
bd09590c01 docs(07-01): complete config history UI timeline plan
- SUMMARY.md with plan execution results
- STATE.md updated to phase 7 complete
- ROADMAP.md and REQUIREMENTS.md updated

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:13:36 -05:00
Jason Staack
36861fffea feat(07-01): wire ConfigHistorySection into device detail page
- Import and render ConfigHistorySection below Interface Utilization
- Configuration history now visible on device overview tab

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:12:16 -05:00
Jason Staack
6bd24517ba feat(07-01): add config history API client and timeline component
- Add ConfigChangeEntry interface and configHistoryApi.list() to api.ts
- Create ConfigHistorySection with timeline, loading skeleton, and empty state
- Poll every 60s via TanStack Query refetchInterval

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:11:46 -05:00
Jason Staack
e8bf994e7d docs(06-02): complete snapshot view and diff retrieval plan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:04:48 -05:00