Enhanced Channel Manager v0.16.0 — first tagged release since v0.15.2 (513 commits). The earlier 0.16.0 build cut on 2026-04-20 was rolled back before any consumer pulled it; everything from that attempt ships here, with the blocking bugs fixed.
Highlights
Observability & data foundations
- Structured JSON logging on stdout with
trace_idcorrelation middleware (honors inboundX-Request-ID), plusbind_context()for long-running tasks. - Prometheus
/metricsendpoint —ecm_http_requests_total, request-duration histogram,ecm_health_ready_ok, health-check duration; route-pattern labels keep cardinality bounded. - Alembic migration system — baseline revision
0001(36 tables),alembic upgrade headon startup, legacy DBsstamped not re-DDLed; newGET /api/health/schemareports current/head revision, FK status, journal mode.
Auto-creation
- Rule analyzer — advisory linter that catches structural/regex configuration bugs (
UK|matches everything,^4Kunder "Contains" matches nothing, double-escape typos, droppednormalized_name_in_groupguards,merge_streamsinto an empty group) without running the rule. Live-DB endpoint + debug-bundle endpoint (never touches the DB) +analyze_auto_creation_rulesMCP tool. All findings are warnings — saves are never blocked. - Quality (resolution) stream sort → M3U-priority tie-break — equal-resolution streams now break ties on ECM M3U account priorities; per-rule
quality_tie_break_order(defaultdesc) andquality_m3u_tie_break_enabled(default on). match_scope_target_group— new rules default this on: a merging Create-Channel action now scopes its same-name lookup to the rule's target group instead of merging into a same-name channel in some other group (the "channels updated, 0 created" footgun). Existing rules keep their stored value; the analyzer emits aninfoadvisory on rules that still have it off.- Normalization → "Apply to existing channels" — Settings button with dry-run diff preview and per-row rename/merge/skip;
POST /api/normalization/apply-to-channels. /runand/rules/{id}/runare now async-enqueue (202+ pollGET .../executions/{id}), with supervised background tasks that mark the rowfailedon error — no more504on large catalogs; the 30s request-timeout defense is restored for the prefix.- Bulk edit for auto-creation rules — multi-select and apply per-section changes in one action via
POST /api/auto-creation/rules/bulk-update. ?batch_id=filter onGET /api/journal— filter to a single bulk operation's per-entity journal rows (backed byidx_journal_batch_id).- Debug bundle is now a
202+ poll job (concurrency-8 page/stream fetches) so it no longer times out on 15K-channel catalogs; the bundle now also shipsnormalization_rules.yaml.
MCP server
- Streamable HTTP transport at
/mcpreplaces the deprecated SSE transport at/sse— fixes Claude Desktop /mcp-remoteconnection failures (GH #218). Breaking for existing configs: update…/sse?api_key=→…/mcp?api_key=and"type": "sse"→"type": "http". API-key auth is unchanged. - Endpoint-contract registry — every MCP tool now routes backend calls through a declarative registry (~100 endpoints) with call-time key validation, plus an OpenAPI cross-check test; mutating tools now report the actual resulting state and WARN on "200 OK, nothing changed". Fixed a batch of drift bugs (
group_idvschannel_group_id, ignored query params,create_task_schedulecron →schedule_type, swallowed 422 detail, etc.).
Process / release engineering
- ADR-004 (release-cut promotion discipline) — short-lived
release/vX.Y.Zbranches, merge-commit PRs, a seven-item pre-cut gate (G1a–G7), narrow hotfix carve-out. Closes the 0.16.0-rollback root cause. - ADR-005 (code security gating) — CodeQL on PR/push to
dev, delta-zero merge protection ondevandmain, admin-bypass disabled, dismiss-with-comment policy. release-cut-gate.yml— mechanical CI enforcement of G1a/G1b/G5/G6/G7 on release-cut PRs (Release Cut Gaterequired check), release PR template, runbooks scaffold.
Security
- Path-traversal canonicalize-and-verify backstops on the backup download/delete and M3U/XMLTV export paths (CodeQL py/path-injection 1416-1419, 1354-1359).
- SSRF validators on OneDrive
tenant_id/drive_id(CodeQL CRITICAL py/partial-ssrf 1361-1362). - Eight stack-trace-exposure HIGH alerts remediated (1412-1415, 1350-1353) — full trace logged + correlated by
X-Request-ID, response carries only the exception class name; closes an unauthenticated leak on/api/health/ready. - User-controlled regex in auto-creation rule schema and M3U digest patterns now routes through
safe_regex.compile(ReDoS length cap + uniform error surface).
Notable bug fixes
stop_processingauto-creation action no longer terminates the entire Pass 2 loop (GH #225).- Compound (OR) normalization rules no longer strip the entire channel name when the first condition mismatches but a later one matches (GH #217).
- Stream probing now works on HTTPS streams (
tls/cryptoadded to the ffprobe protocol whitelist; GH #106). - Stats tab no longer crashes with React error #185 —
rechartspinned to2.15.4for React 19 compatibility. - Settings sub-pages no longer leak memory (render-loop +
@dnd-kitMutationObserverfixes; up to 5 GB reported on Edge — GH #207). - Scheduled-task enable/disable now persists; scheduled-task email alerts now actually deliver (SMTP recipient field in Notification Settings); success-email metrics now match the execution UI.
- Auto-creation no longer renumbers foreign-group channels matched via the normalized-name fallback; no longer creates duplicate channels for normalization-suffix name differences; Pass 3.5 stream reorder runs on pure-merge runs; name-based stream sort works without probe stats; quality sort honors
deprioritize_failed_streams. - Alembic revision
0005is now idempotent and SQLite-CircularDependencyError-safe. - A batch of MCP tool fixes (GH #221-224):
update_channel/create_channelgroup field,list_auto_creation_rulesenvelope,bulk_add_streams_to_channeltimeout (new pluraladd-streamsendpoint),bulk_commit_channels422-detail surfacing.
Contributors
Thanks to @stevencoutts (Alembic 0005 idempotency/SQLite fix, scheduled-task email metrics + persistence, quality M3U tie-break, normalization apply-to-channels test stabilization, auto-creation rule-duplicate field preservation), @krog (ffmpeg metadata pushed to Dispatcharr — width/height + source_fps cast), and the reporters who drove diagnoses: @swarthyplacebo (compound-OR normalization, MCP Streamable HTTP), @Koalamanx (match_scope_target_group / GH #226). Full per-change attribution is in CHANGELOG.md.
The complete, itemized changelog is in CHANGELOG.md under [0.16.0] — 2026-05-12.