a7fa2ec4aa
iCalendar import: parse_ical + API + MCP tool ( #16 )
2026-07-12 14:46:15 +02:00
6b0d060945
expand MCP tools: browse_library, stats, analyze, preview, suggest, config tools ( #17 )
2026-07-12 14:34:36 +02:00
6dbf7ab98c
SCTE-35 markers + overlay metadata in playout ( #10 )
2026-07-12 14:33:22 +02:00
e27e2ab6d1
wire utoipa OpenAPI: #[utoipa::path] on all handlers, Scalar UI ( #14 )
2026-07-12 14:31:20 +02:00
b00272aceb
iCalendar export: domain service + API + MCP tool ( #15 )
2026-07-12 14:27:20 +02:00
affd7f0223
merge feat/playout: HLS streaming, FFmpeg, multi-channel playout service ( #9 , #11 )
2026-07-12 14:14:52 +02:00
8db70df0a0
merge feat/schedule-engine: interstitials, gap filler, mid-roll breaks ( #3 , #4 , #8 , #6 )
2026-07-12 14:14:43 +02:00
c14e01e0f2
merge feat/library-sync: chapter extraction + MediaRole auto-detection ( #5 , #7 )
2026-07-12 14:14:33 +02:00
874de68fb5
wire mid-roll breaks into schedule engine with chapter-aware splitting
2026-07-12 14:12:59 +02:00
79e975f057
wire gap_filler into schedule engine, API, MCP
2026-07-12 14:08:55 +02:00
8edd7a9c0b
wire interstitial insertion into schedule engine resolve_block
2026-07-12 14:05:33 +02:00
8e4f724562
add integration tests for all 6 FillStrategy variants, role filter on LibrarySearchFilter
2026-07-12 14:02:45 +02:00
f21d70c559
MediaRole auto-detection + manual role API + sync wiring ( #7 )
...
role_detector: classify items as Interstitial by collection name/tag patterns.
Wire chapter extraction + role detection into sync adapter (worker + presentation).
SQLite: persist/read role column, migration.
PUT /library/items/{id}/role endpoint for manual override.
2026-07-12 14:00:28 +02:00
607d311375
chapter extraction via ffprobe during library sync ( #5 )
...
ffprobe module in adapter-common: parse JSON output into Vec<Chapter>,
should_probe_chapters gate (movie OR >45min), graceful failure.
Add set_chapters/set_role setters to MediaItem.
2026-07-12 14:00:17 +02:00
84dd05a8a6
multi-channel playout: concurrent tick, status endpoint, ffmpeg restart ( #11 )
2026-07-12 13:59:54 +02:00
1b3ecc10e1
add playout service: HLS streaming, FFmpeg, SegmentStore port ( #9 )
2026-07-12 13:58:09 +02:00
de7f3092d2
add parallel execution plan for roadmap issues
2026-07-12 07:54:01 +02:00
60524c56f7
add domain concepts: FillStrategy variants, Chapter, InterstitialRule, MidRollRule, gap_filler
...
- FillStrategy: +Alternating (round-robin series), +Weighted (fresh-first), +Marathon (always ep1, loops)
- Chapter value object on MediaItem (JSON column in library_items)
- InterstitialRule + MidRollRule on ProgrammingBlock (data model only)
- gap_filler: Option<MediaFilter> on Channel (persisted as JSON column)
- migration: 20260712000002_add_chapters_and_gap_filler.sql
2026-07-12 07:41:57 +02:00
39f5f99bfd
refactor: replace get_stream_url with get_source_uri per ADR-0002
...
Providers now expose a source URI (for FFmpeg) instead of a
viewer-facing stream URL. Playout Service will own transcoding.
- Add SourceUri value object (NetworkUrl | FilePath)
- Remove StreamQuality, StreamingProtocol from domain
- Simplify ProviderCapabilities (drop streaming_protocol, transcode)
- Jellyfin: return static direct stream URL
- Local files: return absolute file path
- Rename use case get_stream_url -> get_source
- Stream endpoint returns JSON SourceUri instead of 307 redirect
2026-07-12 07:34:13 +02:00
abcf69ce7e
extract background tasks into worker binary
...
Move auto_scheduler, library_sync, broadcast_poller, webhook_consumer
from presentation/background/ into crates/worker/src/jobs/.
Presentation is now a pure HTTP server.
2026-07-12 07:28:17 +02:00
826e824b58
replace tokio::broadcast event bus with SQLite-backed event queue (ADR-0003)
...
- DomainEvent: add Serialize/Deserialize
- EventConsumer port: poll_next/ack/nack replacing recv()
- EventEnvelope: wraps event with id/retry_count/created_at
- SqliteEventPublisher/SqliteEventConsumer: INSERT/poll/DLQ
- migration: event_queue + dead_letter_queue tables
- InMemoryEventBus: combined publisher+consumer test double
- NoopEventConsumer: test stub
- webhook_consumer: polls EventConsumer instead of broadcast::Receiver
- presentation+mcp wiring: create from SqlitePool
2026-07-12 07:23:21 +02:00
e2393be635
collapse 20 pass-through use cases; handlers call ports directly
...
delete get/list/list_by_owner channels, get_settings/activity_log admin,
get_item/get_sync_status/list_collections/list_seasons/list_shows/list_genres library,
get/list/delete providers, get/list/patch_label config_snapshots,
get_active/list_history/delete_after schedule — all single-delegation.
remove ChannelQueryDeps, LibraryQueryDeps, deleted query/command structs.
add direct port fields to AppState. update MCP crate accordingly.
2026-07-12 07:18:26 +02:00
a6558e15b2
kill LibraryItem, unify to MediaItem; decouple schedule engine from providers
...
ADR-0001: MediaItem absorbs LibraryItem fields (provider_id, external_id,
collection_name, collection_type, synced_at, role/MediaRole).
LibraryItem + LibraryItemRow deleted. All ports/adapters/tests updated.
ADR-0002: schedule engine takes LibraryQuery instead of IProviderRegistry.
Algorithmic blocks query library via search(), manual blocks via get_by_id().
get_stream_url removed from engine; provider_registry moved to ScheduleDeps
for playback-time stream URL resolution in application layer.
BlockContent provider_id field removed (meaningless when querying library).
2026-07-12 07:02:08 +02:00
773e228e21
rename RecyclePolicy→RotationPolicy, collapse AccessMode, clean OIDC refs
2026-07-12 06:50:25 +02:00
efd15c4f53
domain glossary, context map, ADRs (library-as-source, playout, event queue)
2026-07-12 06:30:08 +02:00
f45eb38d97
add CLAUDE.md + agent skill config (issue tracker, triage labels, domain docs)
2026-07-12 05:32:57 +02:00
33b440d297
fix(presentation): extract 12 handler violations to use cases
...
- TokenService port + JwtTokenService adapter; login/refresh return LoginResult
- delete get_token (dup of login); create_tokens helper removed
- type UpdateChannelRequest schedule_config/recycle_policy (no serde_json::Value)
- update_settings returns updated Vec; handler calls one use case
- config use case in application::config; handler maps DTO only
- SyncStatusEntry moved to api-types w/ From<LibrarySyncLogEntry>
- trigger_sync: Conflict error, drop sync_trigger.send from handler
- UpsertProviderCommand.config accepts Value; serialization in use case
- get_current_broadcast returns BroadcastWithChannel; one call
- get_stream_url resolves broadcast internally; handler single call
2026-07-12 05:28:49 +02:00
9b18d3ff6d
remove OIDC/Postgres, replace ApiError w/ AppError, move params to api-types
2026-07-12 05:14:17 +02:00
c0e685a4ee
refactor(domain): Row structs for from_persistence, ID newtypes, kill clippy.toml
...
- delete clippy.toml (too-many-arguments-threshold=20 hack)
- ChannelRow/MediaItemRow/LibraryItemRow structs for from_persistence
- SnapshotId/ActivityEventId/PlaybackRecordId newtypes
- DomainError variants use ChannelId/UserId instead of Uuid
- ActivityEvent.channel_id: Option<ChannelId> not Option<Uuid>
- InMemory repos key on newtype IDs
- AlgorithmicParams struct for schedule engine
- update all adapters/application/presentation callers
2026-07-12 05:00:49 +02:00
031cba5cfb
fix: unreachable DbPool match arm for workspace feature unification
2026-07-12 04:39:06 +02:00
f6b2481758
clean(mcp): extract constants, use CARGO_PKG_VERSION, fix unreachable
...
- extract DEFAULT_DATABASE_URL, DEFAULT_SEARCH_LIMIT, SERVER_NAME
- use env!("CARGO_PKG_VERSION") instead of hardcoded "0.1.0"
- content_type_to_str returns &'static str instead of allocating String
- cfg guard on unreachable pattern in wire_repositories
2026-07-12 04:37:27 +02:00
ff5f299a84
clean(presentation): strip comments, kill dead code, extract constants
...
- remove all doc/inline comments
- delete unused ApiError variants (AuthRequired, NotImplemented) and helpers (internal, not_implemented)
- prefix lifetime-only AppState fields with _ to suppress dead_code warning
- extract magic numbers: TICK_INTERVAL_SECS, EXPIRY_THRESHOLD_HOURS, POLL_INTERVAL_SECS, EVENT_BUS_CAPACITY, DEFAULT_ACTIVITY_LIMIT, DEFAULT_SEARCH_LIMIT, etc
- replace inline serde_json::json! in sync_status with typed SyncStatusEntry
- fix mid-file import in schedule handler
- fix extractors: strip_prefix instead of magic offset 6
- fix unreachable pattern in wire_repositories with cfg guard
- use eq_ignore_ascii_case for content-type header check
2026-07-12 04:35:54 +02:00
25b33b6a0e
cleanup: strip comments, extract constants, DRY shared helpers across adapters + infra-wiring
...
- strip all comments except WHY workaround notes (3 remain)
- remove all #[allow(dead_code)]; fix via _prefix rename
- extract named constants: JWT time units, token types, default config values, jellyfin fallback bitrate
- DRY: move serialize_enum_as_string, content_type_str, parse_content_type, parse_genres_blob to adapter-common
- sqlite+postgres library.rs use shared helpers instead of local copies
- sqlite+postgres channel.rs use shared serialize_enum_as_string
- remove dead `let _ = ext` in scanner.rs
2026-07-12 04:21:21 +02:00
eff14228af
refactor(api-types): strip comments, extract DEFAULT_ACCESS_MODE constant
2026-07-12 04:12:51 +02:00
9dcd169689
refactor(application): strip comments, DRY ownership check + parse_content_type
2026-07-12 04:10:58 +02:00
98a54245b1
domain crate code quality cleanup
...
strip all comments, extract tests to tests/ dirs,
remove #[allow(clippy::...)], extract magic numbers to
constants, refactor schedule engine private methods to
use param structs, add Default impls, clippy.toml for
persistence constructors
2026-07-12 04:02:12 +02:00
d650e2ba07
makefile
2026-07-12 03:41:51 +02:00
a46ced4aca
add restructure design spec + implementation plan
2026-07-12 03:41:24 +02:00
f2f56b7143
resolve merge conflicts in tv page (merge password + quality/subtitle features)
2026-07-12 03:41:20 +02:00
8051ab58c0
add /target to gitignore for new workspace root
2026-07-12 03:41:16 +02:00
dd4389d53e
deprecate k-tv-backend, fix workspace feature-unification build
2026-07-12 03:35:09 +02:00
c869e9ab84
mcp: MCP server calling application use cases
2026-07-12 03:31:08 +02:00
56d742a74c
presentation: HTTP server crate w/ handlers, routes, background tasks
...
Axum binary that wires all clean-arch crates together:
- AppState holds pre-built Deps structs (auth, channels, schedule, library, etc.)
- JWT extractors (CurrentUser, AdminUser, OptionalCurrentUser)
- Handlers delegate to application use cases, map to api-types DTOs
- Routes: auth, channels, schedule, library, admin, providers, config, iptv
- Background: auto-scheduler, broadcast poller, webhook consumer, library sync
- Factory builds everything from Config + DbPool
- SimpleProviderRegistry impl of IProviderRegistry trait
- NoopMediaProvider fallback
2026-07-12 03:23:20 +02:00
afed5c01b4
adapter-event-publisher: broadcast channel event bus
2026-07-12 02:54:43 +02:00
b93b14efe4
adapter-local-files: media provider, index, transcoder
2026-07-12 02:53:27 +02:00
e389e9e002
adapter-jellyfin: media provider
2026-07-12 02:47:13 +02:00
72ef9b9e1b
adapter-auth: JWT, OIDC, password hashing
2026-07-12 02:44:16 +02:00
0fe80b545e
adapter-postgres: all repository implementations
2026-07-12 02:39:56 +02:00
e8179d1f53
adapter-sqlite: all repo implementations + wire fn + migrations copy
2026-07-12 02:34:12 +02:00
1428f264bb
adapter-common: shared DB mapping helpers
2026-07-12 02:26:42 +02:00