Commit Graph
2429 Commits
Author SHA1 Message Date
timothyandClaude Fable 5 4db142c2f2 docs: advance ChicoryTV issue queue past #97 (PR #112)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 21:55:10 +02:00
timothyandClaude Fable 5 73455aae28 fix(api): surface programs not filler in channel state, tighten queries
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 4m40s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 4m52s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Adversarial review fixes for the #97 endpoint:

- nowPlaying now resolves like the XMLTV guide: when the wall-clock item
  is pre/mid-roll filler, surface the guide group's program item (title +
  full program bounds) instead of the filler; a guide entry with no
  program item (e.g. fallback loop) reports null. Previously an ad break
  would retitle the channel and reset progress every 30 seconds.
- covering-item lookup now runs one cheap projected query per distinct
  playout offset instead of hydrating the full metadata include tree for
  a window widened by the largest offset across ALL channels (up to 24h);
  metadata is fetched in a second query scoped to the covering guide
  groups, time-bounded to stay safe against GuideGroup recycling (mod
  10000). Regression caught while testing: covering items are keyed by
  (source channel, lookup time) so a source channel no longer inherits
  its offset mirror's lookup result.
- GetChannelStatesForApi now carries Now explicitly (controller passes
  DateTime.UtcNow), making boundary semantics testable: new tests pin
  now == Start (playing) and now == Finish (not playing), plus mid-roll,
  filler-only, and mirror-source-row cases.
- ChannelNowPlayingResponseModel title is non-nullable in the schema
  (#nullable enable) — GetDisplayTitle always returns a string.
- GetState uses the typed-return controller convention; Playouts.Mapper
  reverted to internal (handler lives in the same assembly).
- Spec doc notes the OnDemand drift caveat and filler semantics.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 21:53:21 +02:00
timothyandClaude Fable 5 e66f49e54a fix(api): make channel state NowPlaying nullable in DTO
An off-air channel has no current playout item, so the handler returns
null for NowPlaying; the DTO now declares that (file-scoped #nullable —
ErsatzTV.Core has NRT disabled project-wide). Regenerated OpenAPI and
web types: nowPlaying keeps its nullable oneOf schema (matching the
schema contract test) and channelNumber loses a spurious nullable
annotation left over from an earlier draft — the field is required.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 21:37:00 +02:00
timothyandClaude Fable 5 3e44947597 docs: add ChicoryTV issue-queue handoff (one issue per session)
Living handoff document driving the sequential backend-gap work
(#97, #100-#111, merge pass, then UX screens). Each session works
one queue item and rewrites this file for the next.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 21:31:22 +02:00
timothyandClaude Fable 5 8912686a47 wip: partial implementation salvaged from interrupted workflow run
Untrusted draft — no build/test had run yet. Review before building on it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 21:27:40 +02:00
timothy 07e9d9838d fix(api): resolve mirror channel now playing state 2026-07-02 20:02:01 +02:00
timothy f01ffc6254 test(api): enforce nullable channel now playing schema 2026-07-02 19:50:19 +02:00
timothy 6057bcea7d docs(api): document channel state endpoint 2026-07-02 19:45:53 +02:00
timothy 7b903d4bb4 feat(api): return channel runtime state 2026-07-02 19:37:14 +02:00
timothy 7c1a1d5672 feat(api): add channel state endpoint contract 2026-07-02 19:29:59 +02:00
timothy 1891498563 chore: ignore local worktrees 2026-07-02 19:24:06 +02:00
timothy 7484df1e5b docs(api): plan channel state endpoint 2026-07-02 19:20:50 +02:00
timothy 52bfdbcdce docs(api): specify channel state endpoint 2026-07-02 19:16:07 +02:00
timothy 6b3a698283 feat(api): add bulk channel operations
fixes #98
2026-07-02 19:07:35 +02:00
timothy 32c0d6a6d3 feat(api): enrich channel list response 2026-07-02 18:56:05 +02:00
timothy 97b6c4bee7 fix(web): harden spa foundation
refs #95
2026-07-02 18:36:56 +02:00
timothy 032b9d8116 fix(web): address app shell review findings
refs #94
2026-07-02 18:33:16 +02:00
timothy 6e6fd67fea feat(web): implement ChicoryTV dashboard
refs #83
2026-07-02 18:29:19 +02:00
timothy 5fb3bb2ebc feat(web): add ChicoryTV app shell
refs #82
2026-07-02 18:21:59 +02:00
timothy d1cc12e065 feat(web): add typed API client auth
refs #81
2026-07-02 08:23:19 +02:00
timothy e6df6ac10a feat(web): add ChicoryTV component primitives
refs #80
2026-07-02 08:09:09 +02:00
timothy e282bcecfa feat(frontend): wire ChicoryTV SPA themes
refs #79
2026-07-02 07:56:12 +02:00
timothy b183c6a154 feat(frontend): scaffold ChicoryTV SPA
refs #78
2026-07-02 07:37:00 +02:00
timothyandClaude Opus 4.8 c0b20a0ac5 docs: add auto-tuning screen + borrowed-concept enrichments to brief
Adds the Auto-tuning wizard as hero screen 5 (#69) and annotates the
Channels-list and Schedule-editor sections + prompts with the borrowed
enrichments: lineup health + resume badge (#72, #68), weighted
distribution / reroll / pad-to-boundary / seasonal (#70, #71, #77, #73).

Refs #59 #69

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 00:45:07 +02:00
timothyandClaude Opus 4.8 482396497e docs: link Create Channel backend gaps to epic #62 (#63-#68)
Refs #59 #62

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 23:02:48 +02:00
timothyandClaude Opus 4.8 4229717575 docs: add Create Channel workflow redesign + backend gaps
Replaces the inherited 4-editor channel-creation chain with a single
library-to-lineup builder: browse/search library with artwork, drag
shows into the lineup, friendly toggles (shuffle, always-on), one image
for logo+bug, technical settings via built-in/custom Channel Templates
with advanced override. Lists prerequisite backend gaps (composite
create endpoint, Channel Templates, library browse API, full image-type
support incl. transparent re-encode, unified logo/bug, always-on vs
on-demand) and a Claude Design prompt for the screen.

Refs #59

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 23:00:09 +02:00
timothy d1dfe6eb5a docs: add Codex verification guidance
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 4m6s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 5m4s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 4m23s
2026-07-01 22:39:16 +02:00
timothyandClaude Opus 4.8 0826198d21 docs: add ChicoryTV UI redesign visual-direction brief (Pass 1)
Records the locked design direction for #59: React SPA on the REST API,
API-first (design pulls the API), Komodo-slick look, ChicoryTV dark +
chicory-blue brand. Includes the 4 hero screens with real domain
vocabulary and ready-to-paste Claude Design prompts.

Refs #59

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 20:58:12 +02:00
timothy a2d2f5930c chore: stop tracking local MCP config
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 2m31s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 3m31s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 3m50s
2026-07-01 19:59:18 +02:00
timothy 45ade1fd78 Merge pull request #56 from issue9-ffmpeg8
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 4m17s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 5m13s
Build ErsatzTV Image / Build & push image (amd64) (push) Has been cancelled
fix(ffmpeg): align transcode pipelines with ffmpeg 8
2026-07-01 17:51:13 +00:00
timothy e170b2dc3c fix(ffmpeg): align transcode pipelines with ffmpeg 8
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 4m4s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 5m17s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
refs #9
2026-07-01 19:37:51 +02:00
timothy 183f6c5d2a Merge pull request #55 from issue42-jellyfin-musicvideos
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 4m20s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 5m15s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 3m58s
feat(jellyfin): sync MusicVideo libraries
2026-06-30 20:54:20 +00:00
timothy 5560790bcb feat(jellyfin): sync music video libraries refs #42
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 3m53s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 5m4s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
2026-06-30 19:33:06 +02:00
timothy f25cfdb593 feat(api): default-deny mutating API writes
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 4m42s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 5m55s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 3m52s
feat(api): default-deny mutating API writes

Refs #43
2026-06-30 16:55:31 +00:00
timothy 527332a3ac feat(api): default-deny mutating API writes
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 4m36s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 5m37s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Refs #43
2026-06-30 18:49:35 +02:00
timothy cd20dfb2aa Merge pull request 'test: make channel logo generator testable' (#53) from feature/39-channel-logo-generator-testable into main
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 3m42s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 4m52s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 3m33s
Merge pull request #53 from feature/39-channel-logo-generator-testable

Test channel logo generator path injection
2026-06-30 16:20:48 +00:00
timothy 8e6379a51b test: make channel logo generator testable
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 4m13s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 5m14s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
refs #39
2026-06-30 18:14:23 +02:00
timothy 4aec234e20 feat(api): standardize FFmpeg profile endpoints
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 4m8s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 5m19s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 4m43s
Merge PR #52: feat(api): standardize FFmpeg profile endpoints

Refs #38
2026-06-30 05:42:06 +00:00
timothy 861827dcbc feat(api): standardize ffmpeg profile endpoints
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 5m12s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 6m13s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
refs #38
2026-06-30 07:29:47 +02:00
timothy 30ecd9a8a7 Merge pull request 'feat(api): add playout REST endpoints' (#51) from issue37-rest-api-playouts into main
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 3m58s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 4m47s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 4m58s
Merge pull request #51: feat(api): add playout REST endpoints
2026-06-29 18:37:26 +00:00
timothy b53b06c615 feat(api): add playout REST endpoints
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 3m34s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 4m48s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
fixes #37
2026-06-29 20:31:18 +02:00
timothy 4f8b3042db feat(api): add schedule REST endpoints
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 4m12s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 5m13s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 6m23s
Merge pull request 'feat(api): add schedule REST endpoints' (#50) from feature/36-rest-api-schedules into main
2026-06-29 16:17:40 +00:00
timothy b552905799 feat(api): add schedule REST endpoints
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 3m40s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 4m52s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Refs #36
2026-06-29 08:13:14 +02:00
timothy 0d101e79b1 Merge pull request 'fix(api): standardize error response contract' (#47) from issue46-rest-api-error-contract into main
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 3m54s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 4m55s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 4m54s
Renovate / Renovate (push) Successful in 49s
Dependency vulnerability scan / NuGet vulnerable packages (push) Successful in 41s
fix(api): standardize error response contract

Refs #46
2026-06-28 14:37:54 +00:00
timothy c113142a3d fix(api): standardize error response contract
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 3m34s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 4m36s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
refs #46
2026-06-28 14:58:48 +02:00
timothy 7c646a6829 Merge pull request 'feat(api): add collections REST endpoints' (#45) from feature/35-rest-api-collections into main
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 3m50s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 4m51s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 4m41s
Merge pull request #45 from timothy/feature/35-rest-api-collections

feat(api): add collections REST endpoints
2026-06-28 07:37:13 +00:00
timothy 82f3a1e633 docs(api): document collection REST response codes
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 3m39s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 4m33s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Refs #35
2026-06-28 09:03:59 +02:00
timothy 2f306ce59f docs(api): refresh OpenAPI for collections REST
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 6m22s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 7m54s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Refs #35
2026-06-27 22:26:26 +02:00
timothy fb3f2856da feat(api): add collections REST endpoints
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 4m5s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 5m9s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Refs #35
2026-06-27 21:43:11 +02:00
timothyandClaude Opus 4.8 8f7d240fc8 feat(api): REST foundation + Channels CRUD (#34)
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 3m43s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 4m58s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 3m44s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 5m0s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 3m41s
First slice of the REST API (ersatztv#2). Idiomatic REST over existing MediatR handlers; design in docs/rest-api.md.

Foundation: NotFoundError : BaseError (Core) to split 404 from 422; ApiResults mapping helpers (Either/Option -> 201+Location / 200 / 204 / 404 / 422), additive (existing *ToActionResult untouched); ApiKeyAuthorizationFilter (optional X-Api-Key on mutating actions, gated by Api:WriteKey, no-op when unset) — independent of the IPTV JWT toggle so Jellyfin/Dispatcharr reads are unaffected, applied at controller-class level so every mutating action incl. ResetPlayout is covered fail-safe.

Channels: POST /api/channels (201+Location), PUT/{id} (200/404), DELETE/{id} (204/404), GET/{id} (200/404). Request DTOs -> existing commands; responses reuse ChannelViewModel. Ported page-only validations into handlers (ShowInEpg-when-disabled, external-logo-URL, Group NotEmpty) + FFmpegProfile/Watermark/Filler existence on update for create-parity. Fixed a latent 500: the .Filter(c>0) existence pattern threw TaskCanceledException on not-found; rewritten to AnyAsync.

Tests (NUnit, TZ=UTC): handler success/404/422, ApiResults mapping, API-key filter, controller status/Location/mapping, a controller-security regression net, and a create->read->delete EF integration test on a new in-memory SQLite harness. ErsatzTV.Tests 46/46, Architecture 5/5.

Refs #34

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 15:51:06 +02:00