mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-02-27 18:22:41 -08:00
feat(jellyfin): move auth to env and stored session
This commit is contained in:
@@ -477,8 +477,6 @@ Jellyfin integration is optional and disabled by default. When enabled, SubMiner
|
||||
"enabled": true,
|
||||
"serverUrl": "http://127.0.0.1:8096",
|
||||
"username": "",
|
||||
"accessToken": "",
|
||||
"userId": "",
|
||||
"remoteControlEnabled": true,
|
||||
"remoteControlAutoConnect": true,
|
||||
"autoAnnounce": false,
|
||||
@@ -496,8 +494,6 @@ Jellyfin integration is optional and disabled by default. When enabled, SubMiner
|
||||
| `enabled` | `true`, `false` | Enable Jellyfin integration and CLI commands (default: `false`) |
|
||||
| `serverUrl` | string (URL) | Jellyfin server base URL |
|
||||
| `username` | string | Default username used by `--jellyfin-login` |
|
||||
| `accessToken` | string | Optional explicit Jellyfin access token override; leave empty to use stored local token |
|
||||
| `userId` | string | Jellyfin user id bound to token/session |
|
||||
| `deviceId` | string | Client device id sent in auth headers (default: `subminer`) |
|
||||
| `clientName` | string | Client name sent in auth headers (default: `SubMiner`) |
|
||||
| `clientVersion` | string | Client version sent in auth headers (default: `0.1.0`) |
|
||||
@@ -512,7 +508,10 @@ Jellyfin integration is optional and disabled by default. When enabled, SubMiner
|
||||
| `directPlayContainers` | string[] | Container allowlist for direct play decisions |
|
||||
| `transcodeVideoCodec` | string | Preferred transcode video codec fallback (default: `h264`) |
|
||||
|
||||
When `jellyfin.accessToken` is empty, SubMiner uses the locally stored encrypted token saved from Jellyfin login/setup.
|
||||
Jellyfin auth resolution order:
|
||||
|
||||
1. `SUBMINER_JELLYFIN_ACCESS_TOKEN` (and optional `SUBMINER_JELLYFIN_USER_ID`) environment overrides.
|
||||
2. Locally stored encrypted Jellyfin session payload saved by login/setup (`accessToken` + `userId`).
|
||||
|
||||
Jellyfin direct app CLI commands (`SubMiner.AppImage ...`):
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ remote playback target in Jellyfin's cast-to-device menu.
|
||||
### Requirements
|
||||
|
||||
- `jellyfin.enabled=true`
|
||||
- valid `jellyfin.serverUrl`, `jellyfin.accessToken`, and `jellyfin.userId`
|
||||
- valid `jellyfin.serverUrl` and Jellyfin auth session (env override or stored login session)
|
||||
- `jellyfin.remoteControlEnabled=true` (default)
|
||||
- `jellyfin.remoteControlAutoConnect=true` (default)
|
||||
- `jellyfin.autoAnnounce=false` by default (`true` enables auto announce/visibility check logs on connect)
|
||||
@@ -149,8 +149,8 @@ User-visible errors are shown through CLI logs and mpv OSD for:
|
||||
|
||||
## Security Notes and Limitations
|
||||
|
||||
- Jellyfin access token is stored in local encrypted token storage after login/setup.
|
||||
- `jellyfin.accessToken` remains as an optional explicit override in `config.jsonc`.
|
||||
- Jellyfin auth session (`accessToken` + `userId`) is stored in local encrypted token storage after login/setup.
|
||||
- Optional environment overrides are supported: `SUBMINER_JELLYFIN_ACCESS_TOKEN` and `SUBMINER_JELLYFIN_USER_ID`.
|
||||
- Treat both token storage and config files as secrets and avoid committing them.
|
||||
- Password is used only for login and is not stored.
|
||||
- Optional setup UI is available via `--jellyfin`; all actions are also available via CLI flags.
|
||||
|
||||
@@ -273,15 +273,15 @@
|
||||
// ==========================================
|
||||
// Jellyfin
|
||||
// Optional Jellyfin integration for auth, browsing, and playback launch.
|
||||
// Access token is stored in local encrypted token storage after login/setup.
|
||||
// jellyfin.accessToken below remains an optional explicit override.
|
||||
// Auth session (access token + user id) is stored in local encrypted storage after login/setup.
|
||||
// Optional environment overrides:
|
||||
// SUBMINER_JELLYFIN_ACCESS_TOKEN
|
||||
// SUBMINER_JELLYFIN_USER_ID
|
||||
// ==========================================
|
||||
"jellyfin": {
|
||||
"enabled": false, // Enable optional Jellyfin integration and CLI control commands. Values: true | false
|
||||
"serverUrl": "", // Base Jellyfin server URL (for example: http://localhost:8096).
|
||||
"username": "", // Default Jellyfin username used during CLI login.
|
||||
"accessToken": "", // Optional explicit access token override; leave empty to use stored local token.
|
||||
"userId": "", // User id setting.
|
||||
"deviceId": "subminer", // Device id setting.
|
||||
"clientName": "SubMiner", // Client name setting.
|
||||
"clientVersion": "0.1.0", // Client version setting.
|
||||
|
||||
@@ -5,6 +5,7 @@ Read first. Keep concise.
|
||||
| agent_id | alias | mission | status | file | last_update_utc |
|
||||
| ------------ | -------------- | ---------------------------------------------------- | --------- | ------------------------------------- | ---------------------- |
|
||||
| `codex-generate-minecard-image-20260220T112900Z-vsxr` | `codex-generate-minecard-image` | `Generate media fallbacks (GIF) from assets/minecard.webm and wire README/docs fallback markup` | `done` | `docs/subagents/agents/codex-generate-minecard-image-20260220T112900Z-vsxr.md` | `2026-02-20T11:35:30Z` |
|
||||
| `codex-frequency-dup-log-20260221T042815Z-r4k1` | `codex-frequency-dup-log` | `Reduce frequency dictionary duplicate-term startup log spam` | `completed` | `docs/subagents/agents/codex-frequency-dup-log-20260221T042815Z-r4k1.md` | `2026-02-21T04:32:40Z` |
|
||||
| `codex-main` | `planner-exec` | `Fix frequency/N+1 regression in plugin --start flow` | `in_progress` | `docs/subagents/agents/codex-main.md` | `2026-02-19T19:36:46Z` |
|
||||
| `codex-task85-20260219T233711Z-46hc` | `codex-task85` | `Resume TASK-85 maintainability refactor from latest handoff point` | `in_progress` | `docs/subagents/agents/codex-task85-20260219T233711Z-46hc.md` | `2026-02-20T11:42:39Z` |
|
||||
| `codex-config-validation-20260219T172015Z-iiyf` | `codex-config-validation` | `Find root cause of config validation error for ~/.config/SubMiner/config.jsonc` | `completed` | `docs/subagents/agents/codex-config-validation-20260219T172015Z-iiyf.md` | `2026-02-19T17:26:17Z` |
|
||||
@@ -20,9 +21,10 @@ Read first. Keep concise.
|
||||
| `codex-release-mpv-plugin-20260220T035757Z-d4yf` | `codex-release-mpv-plugin` | `Package optional release assets bundle (mpv plugin + rofi theme), move theme to assets/themes, update install/docs` | `completed` | `docs/subagents/agents/codex-release-mpv-plugin-20260220T035757Z-d4yf.md` | `2026-02-20T04:02:26Z` |
|
||||
| `codex-bundle-config-example-20260220T092408Z-a1b2` | `codex-bundle-config-example` | `Bundle config.example.jsonc in release assets tarball and align install docs` | `completed` | `docs/subagents/agents/codex-bundle-config-example-20260220T092408Z-a1b2.md` | `2026-02-20T09:26:24Z` |
|
||||
| `codex-tsconfig-modernize-20260220T093035Z-68qb` | `codex-tsconfig-modernize` | `Enable noUncheckedIndexedAccess + isolatedModules in root tsconfig and fix resulting compile errors` | `completed` | `docs/subagents/agents/codex-tsconfig-modernize-20260220T093035Z-68qb.md` | `2026-02-20T09:46:26Z` |
|
||||
| `codex-jellyfin-secret-store-20260220T101428Z-om4z` | `codex-jellyfin-secret-store` | `Verify whether Jellyfin token can use same secret-store path as AniList token` | `completed` | `docs/subagents/agents/codex-jellyfin-secret-store-20260220T101428Z-om4z.md` | `2026-02-20T10:22:45Z` |
|
||||
| `codex-jellyfin-secret-store-20260220T101428Z-om4z` | `codex-jellyfin-secret-store` | `Move Jellyfin token/userId out of config into env override + stored session payload` | `completed` | `docs/subagents/agents/codex-jellyfin-secret-store-20260220T101428Z-om4z.md` | `2026-02-21T04:27:24Z` |
|
||||
| `codex-vitepress-subagents-ignore-20260220T101755Z-k2m9` | `codex-vitepress-subagents-ignore` | `Exclude docs/subagents from VitePress build` | `completed` | `docs/subagents/agents/codex-vitepress-subagents-ignore-20260220T101755Z-k2m9.md` | `2026-02-20T10:18:30Z` |
|
||||
| `codex-preserve-linebreak-display-20260220T110436Z-r8f1` | `codex-preserve-linebreak-display` | `Fix visible overlay display artifact when subtitleStyle.preserveLineBreaks is disabled` | `completed` | `docs/subagents/agents/codex-preserve-linebreak-display-20260220T110436Z-r8f1.md` | `2026-02-20T11:10:51Z` |
|
||||
| `codex-review-refactor-cleanup-20260220T113818Z-i2ov` | `codex-review-refactor-cleanup` | `Review recent TASK-85 refactor effort and identify remaining cleanup work` | `handoff` | `docs/subagents/agents/codex-review-refactor-cleanup-20260220T113818Z-i2ov.md` | `2026-02-20T11:48:28Z` |
|
||||
| `codex-commit-unstaged-20260220T115057Z-k7q2` | `codex-commit-unstaged` | `Commit all current unstaged repository changes with content-derived conventional message` | `in_progress` | `docs/subagents/agents/codex-commit-unstaged-20260220T115057Z-k7q2.md` | `2026-02-20T11:51:18Z` |
|
||||
| `codex-overlay-whitespace-newline-20260221T040705Z-aw2j` | `codex-overlay-whitespace-newline` | `Fix visible overlay whitespace/newline token rendering bug with TDD regression coverage` | `completed` | `docs/subagents/agents/codex-overlay-whitespace-newline-20260221T040705Z-aw2j.md` | `2026-02-21T04:18:16Z` |
|
||||
| `codex-duplicate-kiku-20260221T043006Z-5vkz` | `codex-duplicate-kiku` | `Fix Kiku duplicate-card detection/grouping regression for Yomitan duplicate-marked + N+1-highlighted cards` | `completed` | `docs/subagents/agents/codex-duplicate-kiku-20260221T043006Z-5vkz.md` | `2026-02-21T04:33:17Z` |
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# codex-jellyfin-secret-store-20260220T101428Z-om4z
|
||||
|
||||
- alias: `codex-jellyfin-secret-store`
|
||||
- mission: `Verify whether Jellyfin token can use same secret-store path as AniList token`
|
||||
- mission: `Move Jellyfin token/userId out of config into env override + stored session payload`
|
||||
- status: `completed`
|
||||
- last_update_utc: `2026-02-20T10:22:45Z`
|
||||
- last_update_utc: `2026-02-21T04:27:24Z`
|
||||
|
||||
## Intent
|
||||
|
||||
@@ -63,3 +63,54 @@
|
||||
- `node --test dist/main/runtime/jellyfin-client-info.test.js dist/main/runtime/jellyfin-cli-auth.test.js dist/main/runtime/jellyfin-setup-window.test.js dist/main/runtime/jellyfin-client-info-main-deps.test.js dist/main/runtime/jellyfin-cli-main-deps.test.js dist/main/runtime/jellyfin-setup-window-main-deps.test.js`
|
||||
- `bun run test:fast`
|
||||
- `bun run docs:build`
|
||||
|
||||
## Next Intent (2026-02-21)
|
||||
|
||||
- remove `jellyfin.accessToken` config path; add env override (`SUBMINER_JELLYFIN_ACCESS_TOKEN`)
|
||||
- move `jellyfin.userId` out of config into stored Jellyfin auth session payload
|
||||
- keep login/logout semantics via setup/CLI commands
|
||||
- add/update runtime tests first, then implementation + docs
|
||||
|
||||
## 2026-02-21 Outcome
|
||||
|
||||
- removed `jellyfin.accessToken` + `jellyfin.userId` from config defaults/parsing/docs surface
|
||||
- added env override precedence in resolver:
|
||||
- `SUBMINER_JELLYFIN_ACCESS_TOKEN`
|
||||
- `SUBMINER_JELLYFIN_USER_ID` (optional; falls back to stored userId if session exists)
|
||||
- moved Jellyfin store from token-only to auth-session payload (`accessToken` + `userId`)
|
||||
- updated login/setup/logout flows to save/clear stored session payload
|
||||
|
||||
## 2026-02-21 Files Touched
|
||||
|
||||
- `src/core/services/jellyfin-token-store.ts`
|
||||
- `src/main.ts`
|
||||
- `src/main/runtime/jellyfin-client-info.ts`
|
||||
- `src/main/runtime/jellyfin-client-info-main-deps.ts`
|
||||
- `src/main/runtime/jellyfin-cli-auth.ts`
|
||||
- `src/main/runtime/jellyfin-cli-main-deps.ts`
|
||||
- `src/main/runtime/jellyfin-setup-window.ts`
|
||||
- `src/main/runtime/jellyfin-setup-window-main-deps.ts`
|
||||
- `src/main/runtime/jellyfin-remote-commands.ts`
|
||||
- `src/main/runtime/jellyfin-remote-session-lifecycle.ts`
|
||||
- `src/config/definitions.ts`
|
||||
- `src/config/service.ts`
|
||||
- `src/types.ts`
|
||||
- `src/main/runtime/jellyfin-client-info.test.ts`
|
||||
- `src/main/runtime/jellyfin-client-info-main-deps.test.ts`
|
||||
- `src/main/runtime/jellyfin-cli-auth.test.ts`
|
||||
- `src/main/runtime/jellyfin-cli-main-deps.test.ts`
|
||||
- `src/main/runtime/jellyfin-setup-window.test.ts`
|
||||
- `src/main/runtime/jellyfin-setup-window-main-deps.test.ts`
|
||||
- `docs/configuration.md`
|
||||
- `docs/jellyfin-integration.md`
|
||||
- `docs/public/config.example.jsonc`
|
||||
- `backlog/tasks/task-93 - Remove-Jellyfin-token-userId-from-config-use-env-and-stored-session.md`
|
||||
|
||||
## 2026-02-21 Verification
|
||||
|
||||
- `bun run tsc --noEmit`
|
||||
- `bun test src/main/runtime/jellyfin-client-info.test.ts src/main/runtime/jellyfin-cli-auth.test.ts src/main/runtime/jellyfin-setup-window.test.ts src/main/runtime/jellyfin-client-info-main-deps.test.ts src/main/runtime/jellyfin-cli-main-deps.test.ts src/main/runtime/jellyfin-setup-window-main-deps.test.ts src/main/runtime/jellyfin-remote-session-lifecycle.test.ts src/main/runtime/jellyfin-command-dispatch.test.ts src/main/runtime/jellyfin-remote-commands.test.ts src/config/config.test.ts` (73 pass)
|
||||
|
||||
## Blockers
|
||||
|
||||
- full `bun run build` currently blocked by local disk-full (`ENOSPC`) in workspace output path
|
||||
|
||||
@@ -20,3 +20,7 @@ Shared notes. Append-only.
|
||||
- [2026-02-21T04:09:02Z] [codex-overlay-whitespace-newline-20260221T040705Z-aw2j|codex-overlay-whitespace-newline] completed: whitespace-only token surfaces no longer become token segments; non-preserve mode now flattens token newlines to spaces and renders whitespace as text nodes; added regression test in renderer suite.
|
||||
- [2026-02-21T04:14:30Z] [codex-overlay-whitespace-newline-20260221T040705Z-aw2j|codex-overlay-whitespace-newline] preserve-line-breaks follow-up: when token surface mismatches source (e.g., `1` vs `1`), alignment now skips unmatched token instead of appending both source tail + token; fixes duplicated no-break line artifact.
|
||||
- [2026-02-21T04:18:16Z] [codex-overlay-whitespace-newline-20260221T040705Z-aw2j|codex-overlay-whitespace-newline] follow-up fix: non-token fallback now honors preserveLineBreaks flag by collapsing line breaks when disabled; prevents visible multi-line -> single-line transition while tokenized payload arrives.
|
||||
- [2026-02-21T04:18:58Z] [codex-jellyfin-secret-store-20260220T101428Z-om4z|codex-jellyfin-secret-store] overlap note: follow-up Jellyfin auth refactor touching `src/main.ts`, `src/main/runtime/jellyfin-*`, and config/docs to remove config token/userId fields in favor of env+stored session payload.
|
||||
- [2026-02-21T04:27:24Z] [codex-jellyfin-secret-store-20260220T101428Z-om4z|codex-jellyfin-secret-store] completed TASK-93: removed Jellyfin accessToken/userId config fields; resolver now uses env-first (`SUBMINER_JELLYFIN_ACCESS_TOKEN` + optional `SUBMINER_JELLYFIN_USER_ID`) then stored encrypted session payload; login/setup save session and logout clears session.
|
||||
- [2026-02-21T04:30:06Z] [codex-duplicate-kiku-20260221T043006Z-5vkz|codex-duplicate-kiku] investigating Kiku duplicate grouping regression; expecting touches in `src/anki-integration/duplicate.ts` and duplicate-detection tests only.
|
||||
- [2026-02-21T04:33:17Z] [codex-duplicate-kiku-20260221T043006Z-5vkz|codex-duplicate-kiku] completed TASK-94: duplicate check now resolves `word`/`expression` alias fields when validating candidate notes; added regression test `src/anki-integration/duplicate.test.ts`; targeted build + duplicate/anki-integration tests passed.
|
||||
|
||||
Reference in New Issue
Block a user