From d2d9a56096502304b2087086908ef8df7980e2af Mon Sep 17 00:00:00 2001 From: 4gray Date: Sat, 26 Sep 2026 12:44:56 +0200 Subject: [PATCH] fix(settings): gate the Electron cached category/content reads while locks are unknown The warm-route hydration reads the cache directly; it now returns nothing while the lock store withholds everything, like the live reads. Co-Authored-By: Claude Fable 5.1 --- docs/architecture/parental-lock.md | 3 ++- .../data-sources/electron-xtream-data-source.spec.ts | 6 ++++++ .../lib/data-sources/electron-xtream-data-source.ts | 12 ++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/docs/architecture/parental-lock.md b/docs/architecture/parental-lock.md index c9d1aff43..8028d5173 100644 --- a/docs/architecture/parental-lock.md +++ b/docs/architecture/parental-lock.md @@ -119,7 +119,8 @@ store), and while the lock is active with the store unreadable predicate answers true and the set-based filters (PWA Xtream, Stalker content and search, the M3U channel list) receive `ALL_CATEGORIES_WITHHELD`, and `ElectronXtreamDataSource` serves no -categories, content or search hits either, since its SQLite index may still +categories, content, cached categories/content (the warm-route hydration +path) or search hits either, since its SQLite index may still carry a stale stamp — under which a row WITHOUT a genre is withheld too (`isStalkerItemWithheld`, `isStalkerCategoryLocked`), since "no genre" must not be the one row a withheld catalog still shows — so the whole diff --git a/libs/portal/xtream/data-access/src/lib/data-sources/electron-xtream-data-source.spec.ts b/libs/portal/xtream/data-access/src/lib/data-sources/electron-xtream-data-source.spec.ts index 3dde236be..d564416ca 100644 --- a/libs/portal/xtream/data-access/src/lib/data-sources/electron-xtream-data-source.spec.ts +++ b/libs/portal/xtream/data-access/src/lib/data-sources/electron-xtream-data-source.spec.ts @@ -66,6 +66,12 @@ describe('ElectronXtreamDataSource (DB-first strategy)', () => { await expect( harness.dataSource.searchContent(playlistId, 'news', ['live']) ).resolves.toEqual([]); + await expect( + harness.dataSource.getCachedCategories(playlistId, 'live') + ).resolves.toEqual([]); + await expect( + harness.dataSource.getCachedContent(playlistId, 'live') + ).resolves.toEqual([]); expect( harness.dbService.getXtreamCategories ).not.toHaveBeenCalled(); diff --git a/libs/portal/xtream/data-access/src/lib/data-sources/electron-xtream-data-source.ts b/libs/portal/xtream/data-access/src/lib/data-sources/electron-xtream-data-source.ts index 65fe37919..85b88c213 100644 --- a/libs/portal/xtream/data-access/src/lib/data-sources/electron-xtream-data-source.ts +++ b/libs/portal/xtream/data-access/src/lib/data-sources/electron-xtream-data-source.ts @@ -273,6 +273,12 @@ export class ElectronXtreamDataSource implements IXtreamDataSource { playlistId: string, type: CategoryType ): Promise { + // Same fail-closed gate as the live reads: the warm-route hydration + // reads the cache directly and must not publish rows a stale index + // stamp still marks unlocked. + if (this.parentalLock.withholdsEverything?.()) { + return []; + } return this.dbService.getXtreamCategories( playlistId, mapCategoryTypeToDbType(type) @@ -403,6 +409,12 @@ export class ElectronXtreamDataSource implements IXtreamDataSource { playlistId: string, type: StreamType ): Promise { + // Same fail-closed gate as the live reads: the warm-route hydration + // reads the cache directly and must not publish rows a stale index + // stamp still marks unlocked. + if (this.parentalLock.withholdsEverything?.()) { + return []; + } return this.dbService.getXtreamContent(playlistId, type); }