Files
houseplan-card/docs/AUDIT-QUALITY.md
T
Cursor AgentandMatysh 99f7c3a4a9 docs: full project audit pack for agents (market, quality, gaps)
Add docs/AUDIT*.md covering competitive landscape (easy-floorplan 11→430★),
implementation quality, functional integrity, and P0–P3 recommendations.
Refresh PRODUCT.md competitor claim and point STATUS watchlist at the pack.

Co-authored-by: Matysh <Matysh@users.noreply.github.com>
2026-08-05 04:56:01 +00:00

133 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Audit — implementation quality
> Snapshot: **2026-08-05**, product **v1.58.0**.
> Severity: **critical / major / minor / nit**. No critical RCE found under
> normal HA session auth.
## 1. Architecture snapshot
```
src/ Lit 3 Lovelace cards (houseplan + space-card)
houseplan-card.ts ~8691 LOC — orchestration god-object
logic.ts / devices.ts / … extracted pure modules (good)
styles.ts ~2223 LOC CSS-in-JS
custom_components/houseplan/ HA integration (storage, WS, HTTP, trails)
dist/ + frontend/ committed bundle (CI byte-compares)
demo/ Playwright harness + smoke_*.mjs
tests_backend/ pure + HA-harness pytest
```
Bundle: **≈449 KB** raw / **≈128 KB** gzip — acceptable for a full editor+viewer.
## 2. What is strong
### Backend
- Single write-auth helper (`auth.may_write`) with **fail-closed** when entry
missing (audit B2 lesson documented in the module).
- Voluptuous validation with **cross-language option-list tests** that parse
`DISPLAY_MODES` / `TAP_ACTIONS` from `logic.ts` — rare and valuable.
- Config CAS via `expected_rev`; plan COW + quotas; never-delete-on-inference
file policy (SCOPE).
- Geometry migration with durable `geom_pending` intent (HP-1490 class).
- Content HTTP: `requires_auth`, signed URLs for `<image href>`, SVG CSP sandbox.
- Diagnostics / repairs / system_health present; `quality_scale.yaml` mostly
**honest** (`test-coverage`, `strict-typing`, docs todos marked todo).
### Frontend (extracted brain)
- Tap security model in `resolveTapAction` — locks/alarms never toggle from the
plan; cover garage/door/gate guarded; `run` limited to automation/script/scene.
- Pure geometry / devices / sun / vacuum / resize / align-grid / signing modules
with solid `node:test` coverage (~270 tests).
- Shared `config-store` + space-geometry/render for `houseplan-space-card`.
- Optimistic UI without rollback is **documented intentional** (ARCHITECTURE).
### Process
- Four test layers + smoke policy (“`[manual]` must have a failing auto check”).
- Dual CHANGELOG (en/ru), SCOPE guard rail, CONTRIBUTING five-minute loop.
- CI: hacs + hassfest + frontend + backend + smoke job.
## 3. Findings (ranked)
| # | Sev | Finding | Where |
|---|---|---|---|
| 1 | **major** | God-object card: ~8691 LOC, ~359 methods, ~125 private fields; `render()` ~382 lines. Smokes-only coverage for orchestration. | `src/houseplan-card.ts` |
| 2 | **major** | `strict: true` hollowed by `noImplicitAny: false`; ~200 `any` sites in the card alone; `hass: any` everywhere | `tsconfig.json`, card / devices / logic |
| 3 | **major** | Write-policy split: UI `_canEdit` is always admin-gated; API default `admin_only=False` lets **any** authenticated user write via WS/HTTP | `houseplan-card.ts` ≈L247–249, `auth.py` |
| 4 | **major** | `_canEdit` fails **open** when `hass.user` is missing (`is_admin !== false`) | card ≈L248 |
| 5 | **major** | `styles.ts` ~2223 LOC — second maintainability sink; untested | `src/styles.ts` |
| 6 | **minor** | `layout/update` has no `expected_rev` — multi-tablet last-writer-wins per point | `websocket_api.py` |
| 7 | **minor** | Marker `binding` is bare `str`; `ripple_color` not hex-matched; decor `w`/`h` allow negatives via `_NORM` | `validation.py` |
| 8 | **minor** | Card-level `tap_action` / `resolveTapAction` cardDefault is dead / ignored — confusing API surface | `types.ts`, click path |
| 9 | **minor** | Store `_async_migrate_func` is a no-op; real migrations live ad-hoc in setup | `store.py`, `__init__.py` |
| 10 | **nit** | `quality_scale.yaml` cites `test_config_flow.py`; file is `test_ha_config_flow.py` | quality_scale.yaml |
| 11 | **nit** | Duplicated `fireEvent` / `navigate` in card + space-card | both files |
| — | positive | Forbidden-domain tap model + confirm + cover guards | `logic.ts` |
| — | positive | Signed content + SVG sandbox | `http_api.py`, `signing.ts` |
**No critical** auth bypass of HA sessions found. Closest systemic issue is
finding #3 (API openness vs UI) under the default options.
## 4. TypeScript & tooling
| Item | State |
|---|---|
| `tsc --noEmit` in build | Yes — correct (rollup TS plugin can warn-and-ship) |
| ESLint / Prettier | **Absent** |
| `noImplicitAny` | **Off** |
| Frontend unit of the Lit class | **None** |
| mypy strict (backend) | quality_scale **todo** |
## 5. Test map
| Layer | What it proves | Gap |
|---|---|---|
| `npm test` (~270) | Pure logic, i18n parity, tap security, geometry | Not the card shell |
| `pytest` pure | validation.py without HA | — |
| HA-harness (py≥3.13) | setup, WS races, auth, upload, geometry repair | Coverage % unmeasured |
| `demo/smoke_*.mjs` (~100) | Real pointer/UI against fake hass | Pixel flakes (`smoke_opening_measure`); no Safari/Companion matrix |
Human checklist in TESTING.md last full self-run recorded at **v1.21.1** while
product is at **v1.58.0** — auto net grew; documented human pass did not.
## 6. Docs drift (quality of truth)
| Doc | Drift |
|---|---|
| `ARCHITECTURE.md` intro | Still mentions old `src/data/house.ts` / 1489×1053 era in places; square/infinite canvas sections newer |
| `UX-MODES.md` header | Still says “No code has been changed yet” — Phase 11 shipped |
| `PRODUCT.md` competitor table | **Stale** — easy-floorplan 11→430★ (see AUDIT-MARKET) |
| `STATUS.md` | Generally current as of 2026-08-04 |
Docs discipline is a project strength; these drifts are fixable and should be
treated as debt, not ignored.
## 7. Top 10 technical debt (actionable)
1. Split `houseplan-card.ts` into shell + Plan/Devices/Decor editors + dialogs.
2. Turn on `noImplicitAny` incrementally; type a thin `Hass` surface.
3. Align write policy: wire UI to `admin_only`, or default `admin_only=True`.
4. Fail closed on missing `hass.user`.
5. Add CAS / expected_rev to `layout/update` (or document single-writer assumption).
6. Split `styles.ts` by feature surface.
7. Tighten MARKER_SCHEMA (`binding`, colors, decor extents, space ids).
8. Unit-test orchestration hotspots (`_clickDevice`, write-chain conflicts, modes).
9. Real Store migrations or document setup-time migrations as the only path.
10. Remove or re-wire dead card-level `tap_action` / cardDefault.
Detailed priority and sequencing: [`AUDIT-RECOMMENDATIONS.md`](AUDIT-RECOMMENDATIONS.md).
## 8. Quality-scale honesty check
| Claim | Audit view |
|---|---|
| Bronze structural items `done` | Accurate |
| Silver unloading / owner `done` | Accurate |
| Gold diagnostics / repairs `done` | Accurate |
| `test-coverage` / `strict-typing` / docs examples `todo` | Accurate — keep them todo until measured |
| `config-flow-test-coverage` path typo | Nit — fix filename in yaml |
Overall: self-assessment is trustworthy; do not mark coverage done without a number.