Skip to content

Harden proxy trust, guide output, and channel identity - #183

Merged
cbulock merged 1 commit into
mainfrom
codex/explicit-proxy-trust
Sep 6, 2026
Merged

cbulock merged 1 commit into
mainfrom
codex/explicit-proxy-trust

Conversation

@cbulock

@cbulock cbulock commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Summary

  • make inbound reverse-proxy trust explicit and route generated origins through Express trust policy
  • preserve canonical/source relationships across provider and mapping edits, with stable source-channel playback URLs
  • close upstream streams promptly and make backup restore transactional
  • make output profiles and XMLTV filtering deterministic, isolated, and empty-profile safe
  • bound EPG response-cache variants and make guide deduplication deterministic

Validation

  • ESLint passes
  • 196 non-integration tests pass
  • focused integration suites for lineup, output profiles, EPG, backup, MCP, and provider persistence pass
  • git diff --check passes

The admin build was intentionally not run.

Copilot AI lite review requested due to automatic review settings September 6, 2026 19:21
Comment thread libs/proxy-image.js
Comment on lines +44 to +47
const response = await axios.get(parsedUrl.href, {
responseType: 'stream',
signal: upstreamRequest.signal,
});
@cbulock
cbulock merged commit 3910b66 into main Sep 6, 2026
12 of 15 checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new stable-ID streaming paths still clone/scan the full channels cache per request in hot endpoints, which is an avoidable performance regression that should be fixed before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR hardens proxy/origin handling, stabilizes channel identity across provider/mapping edits, and makes lineup/XMLTV generation more deterministic and cache-bounded to avoid operational edge cases (empty profiles, filter variance blowups, nondeterministic guide dedupe).

Changes:

  • Make reverse-proxy trust explicit (configurable trusted proxies) and route base-URL generation through Express’s trust proxy policy.
  • Introduce stable source-channel playback URLs (/stream/channel/:id) and preserve canonical/source relationships across provider and mapping updates.
  • Improve determinism and safety: bounded LRU caching for large XMLTV variants, deterministic XMLTV deduplication, and transactional/validated backup restore.
File summaries
File Description
test/unit/source-service.test.js Updates provider persistence tests to include stable provider IDs and relationship preservation assertions.
test/unit/cache-manager.test.js Adds LRU eviction test for bounded caches.
test/integration/output-profiles.test.js Validates XMLTV fanout + deterministic dedupe behavior across canonical outputs.
test/integration/output-profile-routes.test.js Adds MCP-assisted profile update coverage; verifies profile-isolated XMLTV + empty-profile behavior.
test/integration/mcp.test.js Updates MCP provider listing expectations to include id and enabled.
test/integration/lineup.test.js Prevents developer HTTP proxy inheritance from affecting nock-based tests.
test/integration/legacy-config-compat.test.js Adjusts legacy provider API expectations for provider IDs; tests relationship preservation on saves.
test/integration/improvements.test.js Extends backup/restore integration coverage to include DB snapshot restoration of bindings/output settings.
test/integration/epg.test.js Adds coverage for deterministic XMLTV deduplication while preserving language-tagged titles.
test/integration/canonical-routes.test.js Validates canonical settings survive mapping rename/renumber changes.
server/transcode.js Supports stable channel-ID addressing for transcode route.
server/stream-probe.js Supports stable channel-ID addressing for stream probe route.
server/oauth.js Switches base URL computation to shared getBaseUrl logic (Express trust-proxy aware).
server/mcp.js Extends list_providers MCP tool output with provider id and enabled.
server/lineup.js Uses stable stream URLs when available; avoids legacy fallback when profiles are initialized; improves upstream cleanup on disconnect.
server/epg.js Bounds XMLTV rewrite cache variants; adds deterministic XMLTV record dedup; profiles/filters intersect deterministically; base URL via getBaseUrl.
server/backup.js Makes backup/restore transactional and validated; adds DB snapshot export of YAML configs; serializes backup ops; invalidates dependent caches post-restore.
scripts/check-channel-health.js Ensures streaming probe connections are consistently torn down (including error response bodies).
libs/source-service.js Preserves provider IDs/created_at on config replaces; avoids destructive delete-all; supports enabled flag.
libs/source-channel-resolver.js Adds DB-backed resolver for stable source-channel lookup by ID.
libs/proxy-image.js Adds abort/cleanup logic for upstream image streams to avoid holding connections after client disconnect.
libs/output-profile-service.js Threads sourceChannelId through output channels; adds hasOutputProfileEntries() to disambiguate “empty vs uninitialized”.
libs/getBaseUrl.js Avoids manual forwarded-header inspection for live Express requests; relies on Express trust-proxy policy.
libs/config-loader.js Adds schema support for provider IDs, provider enabled flag, and trusted_proxies list in app config.
libs/canonical-channel-service.js Preserves canonical IDs/settings across mapping identity changes using stable source-channel association.
libs/cache-manager.js Adds bounded-entry support and LRU behavior to cache implementation.
index.js Makes trust proxy explicit/opt-in via trusted_proxies config.
config/examples/app.example.yaml Documents trusted_proxies configuration.
Review details
  • Files reviewed: 28/28 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread server/lineup.js
Comment on lines +369 to +373
let { source, name } = req.params;
const upstreamOverride = req.query.upstream ? String(req.query.upstream) : null;
const channels = loadChannels();

const channel = channels.find(c => c.source === source && c.name === name);
let channel = channels.find(c => c.source === source && c.name === name);
Comment thread server/stream-probe.js
Comment on lines 366 to +370
app.get('/api/stream-probe/:source/:name', requireAuth, async (req, res) => {
const { source, name } = req.params;
let { source, name } = req.params;
const channels = getChannels();
const channel = channels.find(c => c.source === source && c.name === name);
const channel = source === 'channel' ? getSourceChannelById(name) : channels.find(c => c.source === source && c.name === name);
if (channel) {
Comment thread server/transcode.js
Comment on lines +50 to +52
let { source, name } = req.params;
const channels = getChannels();
const channel = channels.find(c => c.source === source && c.name === name);
const channel = source === 'channel' ? getSourceChannelById(name) : channels.find(c => c.source === source && c.name === name);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants