640 lines
14 KiB
Markdown
640 lines
14 KiB
Markdown
# Rename-MVP — Definitieve Codex instructie en technisch ontwerp
|
||
|
||
## Doel
|
||
|
||
Bouw verder aan een minimalistische webapplicatie als uitgeklede webversie van **Rename My TV Series**.
|
||
|
||
De applicatie moet:
|
||
|
||
- draaien in een **rootless Podman container**
|
||
- lokale mediabestanden kunnen hernoemen binnen expliciet toegestane videomappen
|
||
- metadata ophalen via **TheTVDB v4 API**
|
||
- een **4-panel interface** hebben
|
||
- altijd eerst een **preview** tonen voordat bestanden echt worden hernoemd
|
||
- veilig omgaan met paden, tokens en bestandsoperaties
|
||
- de **serienaam inclusief jaartal** gebruiken in de UI en in de bestandsnaam
|
||
|
||
Dit project heeft al een **werkende baseline**:
|
||
- container build werkt
|
||
- FastAPI health endpoint werkt
|
||
- TVDB login werkt
|
||
- JWT parsing werkt
|
||
- token persistence werkt
|
||
- auth-status endpoint werkt
|
||
- TVDB search werkt
|
||
- `token_source` werkt
|
||
|
||
Belangrijk: dit project is nu **geen greenfield ontwerp meer**, maar een **bestaand werkend project** dat gecontroleerd verder moet worden uitgebouwd.
|
||
|
||
---
|
||
|
||
# 1. Technische context
|
||
|
||
## Hostomgeving
|
||
|
||
- Host OS: Debian Trixie
|
||
- Podman version: 5.4.2
|
||
- Project root: `/home/kodi/.config/rename-mvp`
|
||
|
||
## Runtime
|
||
|
||
- Rootless Podman
|
||
- FastAPI backend
|
||
- SQLite voor app-state en logging
|
||
- JSON voor TVDB auth state
|
||
- TheTVDB API v4
|
||
- Lokale tests via `127.0.0.1:8085`
|
||
|
||
## Bestaande paden
|
||
|
||
### Auth state JSON
|
||
- Host: `/home/kodi/.config/rename-mvp/data/tvdb_auth.json`
|
||
- Container: `/app/data/tvdb_auth.json`
|
||
|
||
### Werkende testscripts
|
||
- `/home/kodi/.config/rename-mvp/regression_tests.sh`
|
||
- `/home/kodi/.config/rename-mvp/feature_test_template.sh`
|
||
|
||
### Governance-bestanden
|
||
- `/home/kodi/.config/rename-mvp/AGENTS.md`
|
||
- `/home/kodi/.config/rename-mvp/CHANGE_POLICY.md`
|
||
- `/home/kodi/.config/rename-mvp/SAFE_FILES.md`
|
||
- `/home/kodi/.config/rename-mvp/docs/ARCHITECTURE.md`
|
||
- `/home/kodi/.config/rename-mvp/contracts/API_GOLDEN.md`
|
||
|
||
---
|
||
|
||
# 2. Niet-onderhandelbare regels
|
||
|
||
## 2.1 Geen contractbreuk
|
||
|
||
Je mag geen bestaande API endpoints of bestaande response-structuren breken.
|
||
|
||
Je mag:
|
||
- nieuwe velden toevoegen
|
||
- nieuwe endpoints toevoegen
|
||
|
||
Je mag niet:
|
||
- bestaande veldnamen wijzigen
|
||
- bestaande velden verwijderen
|
||
- response-structuren wijzigen
|
||
- bestaande endpoints hernoemen
|
||
- bestaande endpoints verwijderen
|
||
|
||
`contracts/API_GOLDEN.md` is leidend.
|
||
|
||
## 2.2 Geen speculative improvements
|
||
|
||
Voer **geen refactors, herstructureringen of “verbeteringen” uit die niet expliciet nodig zijn voor de gevraagde wijziging**.
|
||
|
||
Als een wijziging niet strikt nodig is om het gevraagde doel te bereiken, doe die wijziging niet.
|
||
|
||
## 2.3 Safe files
|
||
|
||
De volgende bestanden zijn beschermd en mogen alleen gewijzigd worden als dat expliciet noodzakelijk is en als je het duidelijk benoemt:
|
||
|
||
- `app/services/tvdb_auth_service.py`
|
||
- `container/Containerfile`
|
||
- `requirements.txt`
|
||
- `contracts/API_GOLDEN.md`
|
||
- `AGENTS.md`
|
||
- `CHANGE_POLICY.md`
|
||
- `SAFE_FILES.md`
|
||
- `docs/ARCHITECTURE.md`
|
||
|
||
## 2.4 Scopebeperking
|
||
|
||
Werk alleen binnen deze repository:
|
||
|
||
Pad op de host: `/home/kodi/.config/rename-mvp`
|
||
Pad in deze codex omgeving: `/workspace/rename-mvp`
|
||
|
||
|
||
Je mag niets aanpassen buiten deze projectscope.
|
||
|
||
## 2.5 Escalated execution
|
||
|
||
Escalated execution is toegestaan binnen deze projectscope voor:
|
||
|
||
- `podman build`
|
||
- `podman run`
|
||
- curl tests
|
||
- lokale build- en testacties
|
||
- bestanden aanmaken of aanpassen binnen dit project
|
||
- dependency install binnen dit project
|
||
|
||
Niet toegestaan:
|
||
|
||
- systeembrede wijzigingen
|
||
- firewallwijzigingen
|
||
- system upgrades
|
||
- andere repositories
|
||
- andere stacks of containers aanpassen
|
||
- destructieve cleanup acties buiten deze projectscope
|
||
|
||
---
|
||
|
||
# 3. Bestaande baseline die behouden moet blijven
|
||
|
||
Deze functionaliteit werkt al en mag niet stuk:
|
||
|
||
## 3.1 Health endpoint
|
||
`GET /api/health`
|
||
|
||
Expected:
|
||
```json
|
||
{"status":"ok"}
|
||
```
|
||
|
||
## 3.2 TVDB login endpoint
|
||
`POST /api/tvdb/login`
|
||
|
||
Doet een expliciete forced login en vraagt een nieuw token aan.
|
||
|
||
Deze endpoint is **alleen voor debugging en handmatige auth-tests**, niet voor regressietests.
|
||
|
||
## 3.3 TVDB auth-status endpoint
|
||
`GET /api/tvdb/auth-status`
|
||
|
||
Deze endpoint moet de actuele auth-status tonen inclusief:
|
||
- configured
|
||
- has_token
|
||
- issued_at
|
||
- expires_at
|
||
- expires_at_unix
|
||
- renew_after
|
||
- renew_after_unix
|
||
- is_expired
|
||
- is_renewal_due
|
||
- last_login_attempt_at
|
||
- last_login_success_at
|
||
- last_login_status
|
||
- last_login_error
|
||
- jwt_payload
|
||
- token_source
|
||
|
||
## 3.4 TVDB search endpoint
|
||
`GET /api/tvdb/search?q=elsbeth`
|
||
|
||
Deze endpoint werkt al en moet series teruggeven met ten minste:
|
||
- id
|
||
- name
|
||
- year
|
||
- display_name
|
||
|
||
De UI en bestandsnaamopbouw moeten het **jaartal van de serie** gebruiken.
|
||
|
||
## 3.5 Token lifecycle
|
||
De TVDB bearer token is een JWT.
|
||
Gebruik:
|
||
- `exp` als primaire bron voor expiry
|
||
- `iat` indien aanwezig
|
||
- renew alleen wanneer nodig
|
||
- niet onnodig opnieuw `/login` doen
|
||
|
||
De token mag **niet continu vernieuwd worden**.
|
||
|
||
## 3.6 token_source
|
||
De auth-state gebruikt:
|
||
- `none`
|
||
- `login`
|
||
- `cached`
|
||
- `renewed`
|
||
|
||
Dit gedrag moet behouden blijven.
|
||
|
||
---
|
||
|
||
# 4. Functioneel doel van de applicatie
|
||
|
||
De uiteindelijke webapp moet een minimalistische 4-panel interface hebben.
|
||
|
||
## Paneel 1 — TVDB Search
|
||
Functie:
|
||
- zoekterm invoeren
|
||
- zoeken via backend naar TheTVDB
|
||
- resultaten tonen
|
||
- gekozen serie details tonen
|
||
|
||
Zoekresultaten moeten minimaal tonen:
|
||
- serienaam
|
||
- jaar
|
||
- first aired indien beschikbaar
|
||
- network indien beschikbaar
|
||
- poster indien beschikbaar
|
||
|
||
De series moeten in de UI worden weergegeven als bijvoorbeeld:
|
||
|
||
- `Elsbeth (2024)`
|
||
- `The Office (2005)`
|
||
|
||
## Paneel 2 — Episodes
|
||
Functie:
|
||
- afleveringen van gekozen serie tonen
|
||
- minimaal `Aired Order` ondersteunen
|
||
- afleveringen per seizoen tonen
|
||
- gebruiker kan willekeurige afleveringen selecteren
|
||
|
||
Afleveringen tonen bijvoorbeeld:
|
||
- `S02E03 - Devil's Night - 2025-03-13`
|
||
|
||
## Paneel 3 — Selected Episodes
|
||
Functie:
|
||
- lijst van gekozen afleveringen voor de huidige sessie
|
||
|
||
Functionaliteit:
|
||
- toevoegen
|
||
- verwijderen
|
||
- clear
|
||
- reorder
|
||
- move up / move down
|
||
|
||
## Paneel 4 — Selected Files
|
||
Functie:
|
||
- lijst van gekozen lokale videobestanden
|
||
|
||
Functionaliteit:
|
||
- Add Files
|
||
- Add Directory
|
||
- Sort
|
||
- Remove
|
||
- Clear
|
||
- Move Up / Move Down
|
||
|
||
## Workflow
|
||
1. user zoekt serie
|
||
2. user kiest serie
|
||
3. backend haalt afleveringen op
|
||
4. user voegt afleveringen toe aan selected episodes
|
||
5. user voegt bestanden toe aan selected files
|
||
6. backend maakt een 1-op-1 mapping op basis van volgorde
|
||
7. backend maakt preview
|
||
8. user bevestigt
|
||
9. backend voert rename uit
|
||
|
||
---
|
||
|
||
# 5. Bestandsnaamopbouw
|
||
|
||
De standaard bestandsnaam moet zijn:
|
||
|
||
```text
|
||
{series} ({year}) - S{season:02}E{episode:02} - {title}{ext}
|
||
```
|
||
|
||
Voorbeeld:
|
||
|
||
```text
|
||
Elsbeth (2024) - S02E03 - Devil's Night.mkv
|
||
```
|
||
|
||
Belangrijk:
|
||
- het **serienaam-jaartal** is verplicht onderdeel van de naam
|
||
- het jaartal komt uit TheTVDB serie metadata
|
||
- de UI moet dit jaartal ook tonen
|
||
|
||
De eerste MVP hoeft **airdate niet per se in de filename** te zetten zolang het afgesproken template hierboven intact blijft.
|
||
|
||
---
|
||
|
||
# 6. TVDB authenticatie en tokenbeheer
|
||
|
||
## 6.1 Authflow
|
||
Gebruik de officiële TVDB v4 flow:
|
||
- `POST /login`
|
||
- body bevat `apikey`
|
||
- `pin` alleen meesturen als aanwezig
|
||
- response bevat bearer token
|
||
|
||
## 6.2 JWT verwerking
|
||
De token is een JWT.
|
||
|
||
Verplicht:
|
||
- decodeer payload
|
||
- lees `exp`
|
||
- lees `iat` indien aanwezig
|
||
- gebruik `exp` als primaire expiry-bron
|
||
|
||
## 6.3 Opslag
|
||
TVDB auth state wordt persistent opgeslagen in:
|
||
|
||
`/app/data/tvdb_auth.json`
|
||
|
||
Hostpad:
|
||
|
||
`/home/kodi/.config/rename-mvp/data/tvdb_auth.json`
|
||
|
||
In JSON mogen staan:
|
||
- token
|
||
- issued_at
|
||
- expires_at
|
||
- expires_at_unix
|
||
- renew_after
|
||
- renew_after_unix
|
||
- last_login_attempt_at
|
||
- last_login_success_at
|
||
- last_login_status
|
||
- last_login_error
|
||
- jwt_payload
|
||
- token_source
|
||
|
||
Niet in JSON:
|
||
- `TVDB_API_KEY`
|
||
- `TVDB_PIN`
|
||
|
||
Die moeten uit environment variables komen.
|
||
|
||
## 6.4 Renew-logica
|
||
Renew alleen wanneer:
|
||
- `now >= renew_after`
|
||
- of TVDB `401` teruggeeft
|
||
|
||
Niet continu nieuwe tokens opvragen.
|
||
|
||
`POST /api/tvdb/login` is geen regressietest en geen normale flow; het is een debug endpoint.
|
||
|
||
---
|
||
|
||
# 7. Toegestane videopaden
|
||
|
||
De container moet dezelfde videopaden gebruiken als de host.
|
||
|
||
## Allowed media roots
|
||
|
||
- `/Volumes/8TB/Shared_Folders/TV_Shows`
|
||
- `/Volumes/8TB_RAID1/Shared_Folders/Library/TV_Shows`
|
||
|
||
## Volume mappings
|
||
|
||
- `/Volumes/8TB/Shared_Folders/TV_Shows -> /Volumes/8TB/Shared_Folders/TV_Shows`
|
||
- `/Volumes/8TB_RAID1/Shared_Folders/Library/TV_Shows -> /Volumes/8TB_RAID1/Shared_Folders/Library/TV_Shows`
|
||
- `/home/kodi/.config/rename-mvp/data -> /app/data`
|
||
|
||
De app mag alleen lezen/schrijven binnen een van de toegestane media roots.
|
||
|
||
---
|
||
|
||
# 8. Securitymodel
|
||
|
||
## Bestandspaden
|
||
Nooit:
|
||
- absolute clientpaden blind vertrouwen
|
||
- `..` toestaan
|
||
- buiten allowed media roots resolven
|
||
|
||
Altijd:
|
||
- path validation doen
|
||
- binnen allowlist van media roots blijven
|
||
- alleen toegestane extensies accepteren
|
||
- preview afdwingen vóór rename
|
||
|
||
## Allowed extensions MVP
|
||
- `.mkv`
|
||
- `.mp4`
|
||
- `.avi`
|
||
- `.m4v`
|
||
- `.srt`
|
||
|
||
## Logging
|
||
Nooit loggen:
|
||
- API keys
|
||
- bearer tokens
|
||
- env secrets
|
||
|
||
---
|
||
|
||
# 9. Container en runtime
|
||
|
||
## Containerfile
|
||
De bestaande werkende runtime moet behouden blijven.
|
||
|
||
## Rootless Podman
|
||
De applicatie draait rootless.
|
||
|
||
## Lokale test-URL
|
||
Gebruik voor runtime-tests de BASE_URL die bereikbaar is vanuit de huidige omgeving:
|
||
|
||
- op de host meestal: http://127.0.0.1:8085
|
||
- in sandbox/container-omgevingen meestal: http://host.containers.internal:8085
|
||
|
||
Gebruik niet automatisch localhost.
|
||
|
||
De testscripts moeten BASE_URL automatisch detecteren of expliciet meegegeven krijgen.
|
||
|
||
---
|
||
|
||
# 10. Verwachte repositorystructuur
|
||
|
||
Houd deze structuur aan. Geen onnodige nieuwe mappen toevoegen.
|
||
|
||
```text
|
||
/home/kodi/.config/rename-mvp
|
||
├── AGENTS.md
|
||
├── CHANGE_POLICY.md
|
||
├── SAFE_FILES.md
|
||
├── regression_tests.sh
|
||
├── feature_test_template.sh
|
||
├── requirements.txt
|
||
├── .env
|
||
├── .env.example
|
||
├── README.md
|
||
├── app/
|
||
├── container/
|
||
├── data/
|
||
├── contracts/
|
||
│ └── API_GOLDEN.md
|
||
└── docs/
|
||
└── ARCHITECTURE.md
|
||
```
|
||
|
||
---
|
||
|
||
# 11. API-contract dat behouden moet blijven
|
||
|
||
## 11.1 Health
|
||
`GET /api/health`
|
||
|
||
Response:
|
||
```json
|
||
{"status":"ok"}
|
||
```
|
||
|
||
## 11.2 TVDB Login
|
||
`POST /api/tvdb/login`
|
||
|
||
Response bevat ten minste:
|
||
```json
|
||
{
|
||
"status": "ok",
|
||
"issued_at": "...",
|
||
"expires_at": "...",
|
||
"renew_after": "..."
|
||
}
|
||
```
|
||
|
||
## 11.3 TVDB Auth Status
|
||
`GET /api/tvdb/auth-status`
|
||
|
||
Response bevat ten minste:
|
||
```json
|
||
{
|
||
"configured": true,
|
||
"has_token": true,
|
||
"expires_at": "...",
|
||
"renew_after": "...",
|
||
"token_source": "cached"
|
||
}
|
||
```
|
||
|
||
Meer velden zijn toegestaan, minder niet.
|
||
|
||
## 11.4 TVDB Search
|
||
`GET /api/tvdb/search?q=query`
|
||
|
||
Response bevat ten minste:
|
||
```json
|
||
{
|
||
"items": [
|
||
{
|
||
"id": "...",
|
||
"name": "...",
|
||
"year": "...",
|
||
"display_name": "..."
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
# 12. Testbeleid
|
||
|
||
## 12.1 Verplichte regressietests na elke wijziging
|
||
Na **iedere wijziging** moet dit script worden uitgevoerd:
|
||
|
||
```bash
|
||
./regression_tests.sh
|
||
```
|
||
|
||
Dit script is verplicht.
|
||
|
||
Het valideert de bestaande baseline en mag geen nieuw TVDB-token forceren.
|
||
|
||
## 12.2 Verplichte feature tests
|
||
Na iedere wijziging moet je daarnaast **drie tests uitvoeren voor de nieuwe of gewijzigde functionaliteit**.
|
||
|
||
Gebruik hiervoor als basis:
|
||
|
||
```bash
|
||
./feature_test_template.sh
|
||
```
|
||
|
||
Deze template moet per feature worden aangepast zodat de nieuwe functionaliteit echt en mechanisch getest wordt.
|
||
|
||
## 12.3 Geen forced login in regressie
|
||
Verboden als standaard regressietest:
|
||
|
||
```bash
|
||
curl -X POST 127.0.0.1:8085/api/tvdb/login
|
||
```
|
||
|
||
Deze endpoint is alleen voor debugging.
|
||
|
||
---
|
||
|
||
# 13. Ontwikkelworkflow voor Codex
|
||
|
||
Bij iedere opdracht moet je dit proces volgen:
|
||
|
||
1. lees eerst de bestaande governance-bestanden:
|
||
- `AGENTS.md`
|
||
- `CHANGE_POLICY.md`
|
||
- `SAFE_FILES.md`
|
||
- `docs/ARCHITECTURE.md`
|
||
- `contracts/API_GOLDEN.md`
|
||
|
||
2. vat kort samen wat je gaat wijzigen
|
||
|
||
3. benoem welke bestanden je wilt aanpassen
|
||
|
||
4. voer alleen de strikt noodzakelijke wijziging uit
|
||
|
||
5. draai verplichte regressietests:
|
||
- `./regression_tests.sh`
|
||
|
||
6. draai drie feature tests voor de nieuwe functionaliteit
|
||
|
||
7. rapporteer:
|
||
- welke bestanden zijn aangepast
|
||
- welke regressietests zijn uitgevoerd
|
||
- welke feature tests zijn uitgevoerd
|
||
- welke risico’s of beperkingen er nog zijn
|
||
|
||
---
|
||
|
||
# 14. Eerste concrete opdracht aan Codex
|
||
|
||
Begin niet meteen met een brede refactor.
|
||
|
||
Begin met een gecontroleerde volgende stap.
|
||
|
||
## Eerste aanbevolen fase
|
||
Bouw de volgende functionaliteit uit:
|
||
|
||
### Doel
|
||
- endpoint om afleveringen van een gekozen TVDB serie op te halen
|
||
- minimaal ondersteuning voor `aired order`
|
||
- seriegegevens inclusief `year` behouden
|
||
- output geschikt maken voor paneel 2 van de UI
|
||
|
||
### Verwachte richting
|
||
Bijvoorbeeld iets als:
|
||
|
||
`GET /api/tvdb/series/{series_id}/episodes?order_type=aired`
|
||
|
||
Maar:
|
||
- breek geen bestaande endpoints
|
||
- wijzig geen bestaande auth-logica
|
||
- wijzig geen container setup
|
||
- gebruik bestaande TVDB token lifecycle
|
||
- voeg tests toe
|
||
|
||
### Voor deze wijziging verplicht
|
||
1. regressietests blijven slagen
|
||
2. drie feature tests toevoegen/uitvoeren voor het nieuwe episodes endpoint
|
||
3. output JSON valideren
|
||
4. zoekresultaten en year-handling niet breken
|
||
|
||
---
|
||
|
||
# 15. Wat je uitdrukkelijk niet moet doen
|
||
|
||
- geen speculative refactors
|
||
- geen auth-systeem herschrijven
|
||
- geen token lifecycle vereenvoudigen
|
||
- geen nieuwe frameworkkeuzes introduceren
|
||
- geen projectstructuur wijzigen
|
||
- geen governance-bestanden wijzigen tenzij expliciet nodig en gemeld
|
||
- geen forced login gebruiken als regressietest
|
||
- geen container- of pathmodel veranderen
|
||
|
||
---
|
||
|
||
# 16. Samenvatting voor Codex
|
||
|
||
Dit project heeft al een werkende baseline.
|
||
|
||
Jouw taak is niet om het project opnieuw te ontwerpen, maar om het gecontroleerd uit te bouwen.
|
||
|
||
Belangrijkste regels:
|
||
- behoud werkende baseline
|
||
- breek geen API contract
|
||
- gebruik JWT `exp` als expiry-bron
|
||
- renew token alleen wanneer nodig
|
||
- gebruik seriejaar in UI en filename
|
||
- werk alleen binnen allowed media roots
|
||
- draai altijd `./regression_tests.sh`
|
||
- draai altijd drie feature tests voor nieuwe functionaliteit
|
||
- geen speculative improvements
|
||
- escalated execution is toegestaan binnen alleen deze projectscope
|