Commit Graph

11 Commits

Author SHA1 Message Date
Pouzor b7985306cd test: cover auto-position and auto-edge-handle; fix negative-cell clamp
Add backend API tests for the two issue #265 features that shipped
untested: auto-positioning root nodes into a free grid slot (first at
origin, collision avoidance, child origin default, explicit coords and
explicit zero preserved) and auto-assigning edge handles from absolute
canvas Y (source above/below/equal target, partial handle fill, child
abs-Y resolved through parent).

Drop the max(0, round()) clamp in _find_free_position: it folded
negative-positioned nodes onto cell (0,0), falsely blocking or freeing
the origin slot. Negative nodes now keep their true cells and never
intersect the positive search space.
2026-07-10 00:16:32 +02:00
Pouzor 3384a05932 test: unify auth headers into a single conftest fixture
Replace 9 duplicated per-file 'headers' fixtures and the awkward
'auth_headers' coroutine factory with one canonical 'headers' fixture
in conftest.py. Migrate liveview/media tests off the await-based
factory. No behavior change; 627 passed.

ha-relevant: no
2026-07-09 21:26:45 +02:00
Pouzor 0792105b96 feat: prompt on duplicate device instead of silently blocking/merging approve
Single-device approve now guards duplicates per-design the same way bulk
approve does, and asks the user instead of failing or silently merging:

- create_node and approve_device reject a same-design duplicate (ieee, ip
  or mac) with 409 + the existing node; a force flag creates it anyway.
- Frontend shows a confirm dialog: go to existing node, add duplicate
  anyway, or cancel.
- approve_device no longer rejects a device already on another canvas
  (status is global, canvas membership is per-design) — it can be placed
  on a new design, matching bulk approve.
- IEEE (Zigbee/Z-Wave) devices now use the same prompt as ip/mac instead
  of auto-merging into the existing node.
- bulk approve reports which devices it skipped as duplicates.

Closes #260

ha-relevant: maybe
2026-07-09 13:05:19 +02:00
Pouzor cbc2bc03c2 fix: attach MCP-created nodes/edges to a design (#225)
create_node/create_edge persisted rows with design_id=null when the
client omitted it (the MCP write tools), so they existed in the DB but
never rendered on the canvas until a container restart reconciled them.
Both routes now fall back to the first design, matching bulk-approve.

Also fix MCP resource reads (homelable://canvas, homelable://edges):
the framework passes a pydantic AnyUrl, not a str, which raised
"'AnyUrl' object has no attribute 'startswith'". Coerce to str.

EdgeResponse now exposes design_id for symmetry with NodeResponse.

ha-relevant: no
2026-06-28 14:00:59 +02:00
Pouzor 3d89ba3b6f feat: replace static hardware fields with dynamic node properties
Replaces the 4 fixed hardware columns (cpu_count, cpu_model, ram_gb,
disk_gb) with a flexible properties system. Each property has a key,
value, icon (from a curated Lucide picker), and a visibility toggle
that controls whether it appears on the canvas node card.

- Backend: add `properties` JSON column to Node model; data migration
  converts existing hardware rows to properties with correct icons
  (idempotent, old columns kept for safety)
- Backend: add `properties` to NodeBase, NodeUpdate, NodeSave schemas
  and canvasSerializer so values survive canvas save/load
- Frontend: add NodeProperty type; new propertyIcons.ts registry (20
  icons); BaseNode renders visible properties with legacy hardware
  fallback for unmigrated nodes
- Frontend: DetailPanel gains interactive properties section (add /
  edit / remove / toggle visibility / icon picker) replacing the
  read-only hardware block; hardware section removed from NodeModal
- Tests: 6 migration tests, 7 API tests, 8 DetailPanel property tests,
  6 BaseNode render/fallback tests, 9 propertyIcons util tests
2026-04-09 13:47:36 +02: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 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 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 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