• v1.0.0 47edf56852

    kayos released this 2026-05-23 13:17:27 -07:00 | 11 commits to main since this release

    Big sweep ahead of tagging v1:

    WATCH LATER STALENESS (MED-2 2nd audit) — actually shipped.

    • New _refresh_watch_later_item() that load-mutate-saves under the lock
      helper, replacing the metadata for a single id in place.
    • 'Refresh metadata' context-menu entry on every Watch Later item.
    • _wl_refresh_action handler: validate id, call _resolve_video_metadata
      (which factors out the same logic both wl_add and wl_refresh need),
      patch the on-disk record, refresh the container if the user is
      currently viewing the WL list.
    • Bug: this was supposed to ship in the prior sprint but a duplicate
      Edit replaced the wrong block and the _refresh_watch_later_item
      function never actually landed in the file. Smoke caught it:
      Kodi reported 'Error getting plugin://…?action=wl_refresh' because
      the action raised NameError. Now landed properly; verified
      end-to-end after a Kodi restart cleared the cached-addon stub.

    MULTI-NIC _lan_ip (MED-7 2nd audit) — fixed.

    • gethostbyname_ex now scans local interfaces first and prefers a
      private-range LAN IP (192.168.x.x / 10.x.x.x / 172.16-31.x.x).
    • Connect-trick to 8.8.8.8 stays as the fallback for hosts with a
      single default route. 127.0.0.1 is the last resort.
    • On hosts with Tailscale / OpenVPN / VPN tunnels as the default
      route, this prevents inputstream.adaptive from getting handed a
      VPN-tunnel IP it can't reach.

    REMAINING LOW BATCH (1st + 2nd audit) — landed.

    • _CHANNEL_ID_RE check in _add_video_items drops 'Go to channel'
      entries when rustypipe ever hands us a non-UC-shaped id (LOW-1 2nd).
    • _redact_query truncates queries before logging (LOW-3 2nd).
    • _add_to_watch_later() now returns 'was_full' so the wl_add notify
      can surface 'Watch Later at cap (500) — dropped oldest' (LOW-9 2nd).
    • _remove_from_watch_later() returns 'removed' so wl_remove notifies
      'Item was not in Watch Later' on no-op (LOW-7 2nd).
    • _add_to_watch_later validates yt_id shape before writing (LOW-6 2nd).
    • _record_search collapses whitespace before dedup (LOW-4 2nd).
    • Sidecar tokio runtime now flavor='current_thread' — one-shot per
      invocation, saves ~100KB RSS per spawn (LOW-6 1st).
    • _MIME_CODEC_RE accepts either quote style (MED-5).
    • Response::ok has a debug_assert! tripwire if a handler ever returns
      its own 'ok' key (MED-6).
    • _pick_thumbnail defends against rustypipe handing it a string,
      dict, or list-of-non-dicts shape (MED-9 / HIGH-3 redux).

    DANGEROUS-FUNCTIONS SCAN — clean.

    • Zero shell=True, os.system, os.popen, eval, exec, pickle,
      import across both Python and Rust.
    • All subprocess calls list-form, all URL building via urlencode,
      all JSON via json/serde_json.
    • xbmc.executebuiltin Container.Update / RunPlugin URLs always go
      through _plugin_url(urlencode) — channel_id additionally regex-
      validated for defense-in-depth.

    CODE FEEL — humanized.

    • Stripped all 'Audit CRIT-1 (2nd pass)' / 'Audit MED-X' ticket
      prefixes across main.py + sidecar Rust. The 'why' comments stay;
      the audit-trail breadcrumbs go. Code reads like working software,
      not a postmortem trail.
    • Section comments (── Search history ──, ── Watch Later ──,
      ── Subscriptions ──) added on the persistence block for navigation.

    VERSION — bumped addon.xml to 1.0.0, Cargo.toml workspace to 1.0.0.
    Verified live on Livingroom Pi after a Kodi restart: wl_add writes
    fresh LTT metadata, manual mutation to 'STALE STUB' detected,
    wl_refresh re-fetches and restores the canonical title.

    Downloads