Commit Graph

21 Commits

Author SHA1 Message Date
Pouzor cc68fcf1c1 test: add deployment test tiers (shellcheck, hadolint, Docker smoke, integration)
Tier 1 — quality.yml: ShellCheck on lxc-install.sh, hadolint on both Dockerfiles
Tier 2 — docker-ci.yml: build images, smoke-test backend health + frontend 200
Tier 3 — test_integration.py: full stack pytest (auth, canvas save/reload, dimensions)
Also adds Docker healthcheck to backend service in docker-compose.yml
2026-03-28 12:33:35 +01:00
Pouzor 2a9cbc5932 feat: resizable nodes with width/height persistence
Add NodeResizer to BaseNode so users can drag corners to resize any node.
Persist width/height through the full stack: DB model, schemas, canvas
save/load route, and migration for existing databases.

Add tests covering save, update, clear, and load of node dimensions.
2026-03-28 11:57:09 +01:00
Pouzor 06ec18a137 feat: add hardware specs to nodes (CPU, RAM, Disk) with canvas display
- Add cpu_count, cpu_model, ram_gb, disk_gb, show_hardware fields to NodeData
- NodeModal: collapsible Hardware section with toggle to show specs on canvas
- BaseNode: 2-line hardware section with Cpu/MemoryStick/HardDrive icons, only renders set fields
- DetailPanel: Hardware section with GB/TB formatting
- Backend: schema, model, DB migration, canvas save/load support
- Tests: frontend (NodeModal, DetailPanel) + backend (canvas persist/load)
2026-03-21 00:01:15 +01:00
Pouzor e14a9e87aa fix: stop exposing JWT in WebSocket URL query param
Token was visible in server logs, browser history, and proxy access logs.
Backend now accepts the connection first, then validates a JSON auth
message {"token": "<jwt>"} sent by the client on open before adding
the socket to the active connections pool.
2026-03-18 00:49:03 +01:00
Pouzor 300567c88d feat(mcp): expose parent_id in update_node tool
- Add parent_id to NodeUpdate schema in backend so PATCH /nodes/{id}
  accepts it (was silently ignored before)
- Expose parent_id in update_node MCP tool schema so the MCP SDK
  forwards it to the backend instead of stripping it
- Add regression tests in both backend and MCP layers
2026-03-13 21:29:27 +01:00
Pouzor e3f8c27a04 test: add backend tests for MCP service key auth in deps.py 2026-03-13 16:42:48 +01:00
Pouzor a56204a5f2 refactor: replace config.yml with .env for all configuration
All settings (auth credentials, scanner ranges, status_checker interval)
now live in a single .env file via pydantic-settings. config.yml and
config.yml.example are deleted.

- Settings: add auth_username, auth_password_hash, scanner_ranges,
  status_checker_interval; add load_overrides()/save_overrides() for
  persisting runtime changes to data/scan_config.json
- auth.py: read credentials directly from settings
- scan.py: read ranges/interval from settings; write-back via save_overrides()
- scheduler.py: read interval directly from settings
- main.py: call settings.load_overrides() at startup
- docker-compose.yml: remove config.yml volume mount, add new env vars
- conftest.py: set settings fields directly instead of writing a temp config.yml
2026-03-09 11:26:49 +01:00
Pouzor 45189e2748 fix: generate test config.yml in conftest for CI
Login route reads config.yml for credentials but it is gitignored.
Session-scoped autouse fixture now writes a minimal config.yml to a
temp path and patches settings.config_path so test_scan.py auth
fixtures work in CI without a real config file.
2026-03-09 09:30:53 +01:00
Pouzor 8da39327ab test: add tests for status WebSocket and scheduler
- test_status.py: 8 tests covering WS auth rejection/acceptance, broadcast_status (dead connection removal, no response_time, no connections), broadcast_scan_update
- test_scheduler.py: 9 tests covering _load_interval variants, _run_status_checks DB update/last_seen/error handling, start/stop lifecycle
- scheduler.py: reinitialize AsyncIOScheduler on each start() to avoid stale event loop across test restarts
2026-03-09 01:32:31 +01:00
Pouzor 20fe4ed9e4 fix: set SECRET_KEY in test conftest before app imports for CI 2026-03-09 00:17:59 +01:00
Pouzor 0cd263537f test: cover custom_icon persistence and cctv icon presence 2026-03-08 12:01:46 +01:00
Pouzor 88634aeb1d feat: add Camera node type + flag RTSP/camera ports during scan
- New 'camera' node type with Camera icon (frontend + types)
- Scanner fingerprint: camera ports (554, 8554, 37777, 34567, 2020) now suggest 'camera' instead of 'iot'
- service_signatures.json: all camera/NVR entries updated to suggested_node_type=camera
- 'camera' added to priority list in suggest_node_type (above iot)
2026-03-08 11:55:26 +01:00
Pouzor e306cd7b49 test: add missing tests for cluster edges, handles, colors, and none check method
- backend: cluster edge creation with source/target handles, handle persistence through PATCH
- frontend: cluster color in edgeColors, onConnect preserves sourceHandle/targetHandle
2026-03-08 11:41:09 +01:00
Pouzor f93afd0646 test: add coverage for none check method, re-scan update, icon registry 2026-03-08 01:12:32 +01:00
Pouzor 2441d72b41 fix: banner_regex sigs require actual banner match — prevents wrong type inference
Banner-specific signatures (e.g. AdGuard on port 3000) were incorrectly
matching when nmap returned no banner, causing wrong suggested_node_type
(e.g. 'router' for a media server). Now a signature with banner_regex is
only matched when a banner is present AND matches the regex.

Also make _PORT_TYPE_HINTS always contribute to suggest_node_type found set
(not just as elif fallback) so well-known ports like 8006 still resolve to
proxmox even when a generic sig also matched.
2026-03-07 23:31:33 +01:00
Pouzor 1a72f9fa20 feat: improve service detection — expanded signatures, port hints, better nmap args
- Expand service_signatures.json from 35 → ~120 entries covering *arr apps,
  smart-home (HA, MQTT, ESPHome), cameras (RTSP, Dahua, Tapo, Reolink),
  network gear (MikroTik, UniFi, Pi-hole), auth (Authelia, Authentik, Vault),
  monitoring (Grafana, InfluxDB, Loki, Uptime Kuma), containers (Portainer),
  and many more home lab services
- Expand nmap port range to cover home lab ports (8989, 7878, 8123, 554, 1883, etc.)
  and increase --host-timeout from 30s to 120s for reliable -sV detection
- Add _PORT_TYPE_HINTS fallback in suggest_node_type for ports without signatures
  (cameras→iot, MQTT→iot, Proxmox→proxmox, MikroTik→router, etc.)
- Show actual port/protocol (e.g. TCP/9999) instead of "unknown_service" so
  all open ports are visible even when not matched
- Update tests to reflect new unknown-port label format
2026-03-07 16:33:03 +01:00
Pouzor 1811afa749 fix: upgrade fastapi to 0.135.1, fix starlette CVEs, update auth test assertions
- fastapi 0.115.0 → 0.135.1 pulls starlette 0.52.1 (fixes CVE-2024-47874, CVE-2025-54121)
- pip-audit: ignore CVE-2024-23342 (ecdsa Minerva attack, no fix exists; app uses HS256 only)
- Update auth guard tests: FastAPI 0.135 returns 401 (not 403) when Bearer token is missing
2026-03-07 15:18:28 +01:00
Pouzor ba91d0f545 test: improve coverage across frontend and backend
Frontend (22 → 37 tests):
- canvasStore: add tests for onNodesChange, onEdgesChange, onConnect,
  addNode with parentId, updateEdge, deleteEdge, setProxmoxContainerMode
  ON/OFF, loadCanvas parent-before-child ordering
- edgeColors: 6 tests for EDGE_DEFAULT_COLORS (all types, hex format, values)

Backend (40 → 80 tests):
- test_canvas (new): load empty canvas, default viewport, save creates/updates/
  deletes nodes+edges, viewport upsert, custom_colors, edge custom_color+path_style,
  auth guard
- test_fingerprint (new): match_port (known, unknown, wrong protocol, banner match,
  banner no-match, no banner), fingerprint_ports (matched, unknown, mixed, empty,
  default protocol), suggest_node_type (proxmox, server, generic, priority)
- test_nodes: update/delete 404, custom_colors CRUD, container_mode CRUD, auth guard
- test_edges: update edge, update/delete 404, custom_color, path_style, auth guard
2026-03-07 15:01:00 +01:00
Pouzor 8a18ded2bc fix: remove trailing slash from GET/POST routes to prevent 307→403 redirect
FastAPI's redirect_slashes=True causes GET /api/v1/canvas to 307 redirect
to /api/v1/canvas/ — axios follows the redirect but drops the Authorization
header, resulting in 403. Fixed by declaring routes as empty string instead
of '/' so no redirect is issued. Same fix applied to nodes and edges routes.
Updated all tests to use paths without trailing slashes.
2026-03-07 01:01:24 +01:00
Pouzor 0bd714a68b feat: Phase 3 & 4 — monitoring, discovery, polish, deployment
Phase 3 — Discovery & Monitoring:
- Network scanner: nmap wrapper + mock fallback, fingerprint service (35 signatures)
- Status checker: ping/http/https/tcp/ssh/prometheus/health per-node checks
- APScheduler: status checks every 60s, WebSocket broadcast
- WebSocket /ws/status: live node status updates to frontend
- Sidebar panels: Pending Devices, Hidden Devices, Scan History
- Auth token persisted to localStorage (survive page refresh)
- 24 new backend tests (scan flow + status_checker)

Phase 4 — Polish & Deployment:
- Auto-layout: Dagre hierarchical TB via Toolbar button
- Export PNG: html-to-image download via Toolbar button
- Scan config modal: CIDR ranges + check interval, GET/POST /api/v1/scan/config
- Dockerfile.backend (Python 3.13 slim + nmap), Dockerfile.frontend (nginx)
- docker-compose.yml with data volume and NET_RAW cap for ping
- scripts/lxc-install.sh: Proxmox VE systemd bootstrap
- README.md: quick-start, config reference, stack overview
2026-03-07 00:45:50 +01:00
Pouzor 44a448e26d fix: all lint errors, test + lint pre-commit passing
Frontend:
- Split nodeTypes/edgeTypes into separate .ts files (react-refresh)
- Remove setState-in-effect in NodeModal (key prop reset)
- Fix handleSave accessed before declaration (useRef pattern)
- Exclude src/components/ui/** from eslint (shadcn generated)
- Use defineConfig from vitest/config for test type support

Backend:
- ruff --fix: sort imports, datetime.UTC alias
- Raise line-length to 120, ignore E501 in tests
- Break long update_node/update_edge signatures
- pyproject.toml: per-file-ignores for tests
2026-03-06 23:58:10 +01:00