# Per-Integration Gap Audit: `kodi` > Status legend, method, and sizing: see [`docs/03-quality-scale-audit-rubric.md`](../03-quality-scale-audit-rubric.md). > Snapshot findings; ๐Ÿ” items must be re-verified against `dev` before implementation. ## 1. Snapshot | Field | Value | |---|---| | Domain | `kodi` | | Category | Media center / media player | | IoT class | `local_push` (websocket) with HTTP fallback (polling) | | Backing library | `pykodi` (wraps `jsonrpc-async` / `jsonrpc-websocket`) | | Platforms | `media_player` (incl. browse media, play media), `remote` ๐Ÿ” | | Custom services | `add_to_playlist`, `call_method` | | Declared `quality_scale` | none (unrated) | | Code owners | Single primary code owner at snapshot ๐Ÿ” โ€” coordination plan must assume limited review bandwidth | | Popularity band (M1 dataset) | High โ€” long-tail classic, top-100 media integration | | Issue-volume band (M1 dataset) | High โ€” themes: auth errors after Kodi settings change, websocket vs HTTP confusion, entity unavailable when Kodi off (expected but poorly communicated), media browsing errors | **Why selected:** high install base, high issue volume, real reauth gap (Kodi has HTTP credentials), and a very large single-module `media_player.py` that benefits disproportionately from typing + tests. The single-owner situation makes our small-PR discipline essential and valuable. ## 2. Architecture summary A config entry stores host/port/credentials and whether to use websocket. The `pykodi` connection object is shared by entities; websocket connection provides push updates, with periodic ping/reconnect; HTTP-only mode polls. Discovery via zeroconf (`_xbmc-jsonrpc-h._tcp`) ๐Ÿ”. The `media_player` entity implements a wide method surface (browse, seek, playlists, volume) and two custom services pass through to the JSON-RPC API. ## 3. Gap audit | # | Dimension | Status | Evidence / notes | |---|---|---|---| | D1 | Config flow completeness | ๐ŸŸก Partial | Zeroconf discovery + manual flow with credential step and websocket-port step; duplicate prevention via Kodi UUID. Gaps: no `reconfigure` step (host changes force re-add โ€” recurring complaint); verify discovery updates host on UUID match ๐Ÿ”; options flow absent (polling interval / timeout could be options, but do not add options speculatively โ€” only `reconfigure`). | | D2 | Reauth & credentials | โŒ Gap | **Primary gap.** Kodi HTTP auth (username/password) can be changed in Kodi's settings at any time; today runtime 401s surface as unavailable entities / log errors with no reauth prompt. Need: map JSON-RPC auth failures to `ConfigEntryAuthFailed` in the connection layer and add a reauth flow re-collecting credentials (pre-filled username), with tests. | | D3 | Runtime data & typing | ๐ŸŸก Partial | Connection stored via `hass.data` at snapshot ๐Ÿ”; migrate to typed `runtime_data`. `media_player.py` is large and loosely typed (JSON-RPC payloads as untyped dicts); introduce `TypedDict`s for the handful of hot payloads (player item, properties) rather than attempting full strict typing in one pass. | | D4 | Update strategy | ๐ŸŸก Partial | Push via websocket with ping-based liveness; HTTP mode polls. Gaps: reconnect/backoff logging hygiene; verify `PARALLEL_UPDATES`; ensure HTTP-mode polling interval is the platform default and documented ๐Ÿ”. No coordinator needed (push-primary; rubric exemption applies). | | D5 | Diagnostics & repairs | โŒ Gap | No `diagnostics.py`. Payload: Kodi version/build, JSON-RPC API version, connection mode (ws/http), application properties, redacted host/credentials. Media-browse bug reports are currently unresolvable without this. | | D6 | Entity naming & device registry | ๐ŸŸก Partial ๐Ÿ” | Device registry entry exists. Verify `has_entity_name` (`media_player` should be `name=None` primary). Remote entity (if present on `dev`) should follow the same pattern. | | D7 | Error handling & availability | ๐ŸŸก Partial | "Unavailable when Kodi is off" is *correct* but generates issue noise โ€” docs fix, not code fix. Code gaps: `call_method`/`add_to_playlist` raise raw `jsonrpc` exceptions (should be translation-backed `HomeAssistantError`/`ServiceValidationError`); browse-media errors should produce `BrowseError` with readable messages. | | D8 | Test coverage | ๐ŸŸก Partial | Config-flow tests comprehensive (discovery, auth, ws paths). Platform tests thin relative to the method surface: no snapshot tests, no browse-media tests, no service tests, no reconnection tests. | | D9 | Documentation & strings | ๐ŸŸก Partial | Missing `data_description` on credential/ws fields. Docs need: "entity is unavailable when Kodi is off โ€” use Wake-on-LAN" section (top noise source), `call_method` examples with response handling, and websocket-vs-HTTP explanation. | | D10 | Quality-scale declaration | โŒ Gap | Undeclared. Bronze requires D2 + D8 work; achievable. Silver gated on reauth (D2) โ€” which is also the top user-value item, so the program naturally lands at **Silver-track**. | ## 4. Detailed findings ### D2 โ€” Reauth (highest-impact gap) Implementation sketch: `pykodi` raises distinguishable errors for HTTP 401 vs connection failure ๐Ÿ” (confirm exact exception classes against the pinned version; if indistinct, add upstream discrimination first โ€” small upstream PR). On auth failure during any RPC, the shared connection wrapper raises `ConfigEntryAuthFailed`, which core converts into a reauth flow. The reauth step validates by calling `JSONRPC.Ping`/`Application.GetProperties` before `async_update_reload_and_abort`. ### D7 + D9 โ€” Converting issue noise into docs Roughly a third of sampled Kodi issues are expected-behavior reports (entity unavailable while Kodi is off). A docs troubleshooting section plus a clearer unavailable-reason in diagnostics is the cheapest issue-volume reduction in the whole program. Track as its own item so impact is measurable. ## 5. Work items | ID | Title | Dimensions | Effort | Depends on | |---|---|---|---|---| | KOD-01 | Migrate connection to typed `runtime_data` | D3 | S | โ€” | | KOD-02 | Auth-failure discrimination + `ConfigEntryAuthFailed` + reauth flow + tests (possible small upstream `pykodi` PR first ๐Ÿ”) | D2, D8 | M (+S upstream) | KOD-01 | | KOD-03 | Add `diagnostics.py` + tests | D5 | S | KOD-01 | | KOD-04 | `reconfigure` flow for host/port changes + tests | D1 | M | KOD-02 | | KOD-05 | Translation-backed errors for services + browse-media | D7, D9 | M | โ€” | | KOD-06 | `has_entity_name` migration | D6 | S | โ€” | | KOD-07 | Snapshot + browse + service + reconnect tests; `TypedDict`s for hot payloads | D3, D8 | L โ†’ split: tests (M) + typing (S) | KOD-05, KOD-06 | | KOD-08 | Docs: unavailability/WoL, ws-vs-http, `call_method` examples; strings `data_description` | D9 | S | โ€” | | KOD-09 | Declare `quality_scale: bronze` (then `silver` after KOD-02) + checklist | D10 | S | KOD-02, KOD-03, KOD-07 | Target tier: **Silver declared.** ## 6. Risks & coordination notates - Single code owner: cap to **one open PR at a time** for this integration (engagement plan ยง4.3), sequenced KOD-01 โ†’ KOD-02 โ†’ โ€ฆ Expect longer review latency; schedule Kodi work interleaved with multi-owner integrations. - KOD-02 may require an upstream `pykodi` release; the dependency bump is its own tiny PR per core conventions. - `call_method` is a power-user passthrough โ€” no schema tightening; only error surfacing improvements.