docs: documentazione iniziale (requisiti, architettura, roadmap, ADR 0001-0013)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
davideandClaude Sonnet 5.5 committed 2026-10-11 18:49:10 +02:00
commit a49b1b13ca
24 files changed
+677

No files matched your search

+9
View File
@@ -0,0 +1,9 @@
# dati e binari (vedi docs/02-architettura.md)
pb_data/
/pocketbase
/pocketbase.exe
*.zip
# segreti
.env
.env.*
!.env.example
+26
View File
@@ -0,0 +1,26 @@
# Changelog
Formato: [Keep a Changelog](https://keepachangelog.com/it-IT/1.1.0/). Versionamento semantico dal primo rilascio.
## [Non rilasciato]
### Aggiunto
- 2026-10-11: struttura documentale iniziale (requisiti, architettura, roadmap, rischi, ADR 0001-0006, PROJECT_STATE).
- 2026-10-11: requisito F-11 (accesso necessario per aggiungere/modificare/eliminare filmati e categorie) e domanda aperta Q-07.
- 2026-10-11: requisito F-12 (per guardare serve un account; gli utenti per ora possono solo guardare); domanda aperta Q-08 (progresso per utente).
- 2026-10-11: ADR 0008, progresso e stato "visto" per utente; sostituisce ADR 0006 (Q-08 chiusa); modello dati `progress` aggiornato.
- 2026-10-11: deciso un solo account admin (F-11); Q-07 ridotta ai punti ancora aperti.
- 2026-10-11: ADR 0009 (admin = superuser PocketBase, account creati solo dall'admin, accesso già dall'MVP); Q-07 chiusa.
- 2026-10-11: risposte Q-02/Q-03/Q-04: ADR 0010 (filmati solo nelle foglie, sostituisce 0005), F-08 diventa Must, N-06 (originali conservati nell'MVP); Q-01/Q-05/Q-06 riformulate.
- 2026-10-11: ADR 0011 (poi sostituito).
- 2026-10-11: risposta Q-05: N-09 dimensionamento iniziale (~40 filmati da 2-3 GB, SSD 1 TB), R-05/R-06 aggiornati;
- 2026-10-11: risposta Q-11: password dimenticata reimpostata dall'admin (F-14/F-15);
- 2026-10-11: risposta Q-09: F-15 profilo utente con cambio password, gestione account in F-14; nuova Q-11 (password dimenticata).
- 2026-10-11: domande Q-13…Q-16 convertite in assunzioni dell'MVP; documentazione pronta per il primo commit.
- 2026-10-11: l'app gira su Raspberry Pi nella rete di casa (N-01, N-10); Q-12 chiusa; nuove Q-14, Q-15, Q-16 e rischi R-07, R-08; sezione Sicurezza riscritta; ADR 0013 sostituisce 0009 (server sulla rete di casa invece di 127.0.0.1).
- 2026-10-11: N-07 riscritto (compatibilità con Safari iOS, Chrome Android e Windows); Q-10 chiusa; nuove Q-12 (accesso da telefono) e Q-13 (admin da telefono); ADR 0003 e R-03 aggiornati.
- 2026-10-11: Q-10 resta aperta, browser di destinazione non decisi (prototipo); non blocca M0.
- 2026-10-11: risposte Q-01 (ipotesi Chrome e Safari, poi ritirata: browser non ancora decisi, N-07/Q-10) e Q-06 (visivamente identico, N-08); ADR 0003 aggiornato con i vincoli dei due browser; nuova Q-10 (dispositivi Safari).
- 2026-10-11: README con cosa c'è da fare; domanda aperta Q-09 (password degli account utenti).
- 2026-10-11: ADR 0012 (pannello admin proprio, F-14, fase M3b; superuser come da documentazione PocketBase, niente `.env`); sostituisce 0011.
- 2026-10-11: allineati PROJECT_STATE, roadmap (M1/M3/M4/M6) e CLAUDE.md alle decisioni su accesso, progresso e categorie.
+23
View File
@@ -0,0 +1,23 @@
# CLAUDE.md — regole di lavoro per l'IA su questo repo
1. **Document-first**: prima di scrivere codice, aggiorna il documento pertinente in `docs/` (o crea un ADR). Poi implementa.
2. **SSOT**: non duplicare informazioni. Consulta `docs/index.md` per sapere dove vive ogni tema; negli altri file usa link.
3. **ADR**: ogni scelta tecnica rilevante → nuovo file `docs/adr/NNNN-titolo.md` (numerazione progressiva, mai riusata). Non modificare un ADR accettato: se la decisione cambia, crea un nuovo ADR che lo sostituisce e aggiorna lo stato del vecchio in `Sostituito da NNNN`.
4. **Stato**: a fine lavoro aggiorna `docs/PROJECT_STATE.md` e `CHANGELOG.md` (root).
5. **Verifica**: fatti su librerie/versioni/limiti vanno verificati su fonti ufficiali e citati nel documento (con data). Mai a memoria.
6. **Decisioni aperte**: non scegliere al posto dell'utente; elencale in `docs/04-rischi-e-domande-aperte.md` e chiedi.
7. **Casi limite**: per ogni modulo ragiona sui casi possibili (input vuoti, file corrotti, interruzioni, concorrenza, spazio disco) come farebbe uno sviluppatore senior, e documentali.
8. **Costo zero**: preferire soluzioni gratuite e self-hosted; se serve qualcosa a pagamento, verificare il costo reale e segnalarlo prima.
9. La struttura di `docs/` può adattarsi al progetto: se serve un nuovo documento, aggiungilo a `docs/index.md`.
## Contesto del progetto (non duplicare: i dettagli stanno nei link)
- **Cos'è**: web app locale per archiviare e guardare filmati per categoria/sottocategoria, con ripresa dal punto lasciato. Stack: PocketBase + frontend vanilla (ADR 0001, 0007). Stato: [docs/PROJECT_STATE.md](docs/PROJECT_STATE.md). Fase attuale: pre-M0, nessun codice.
- **Lingua**: documentazione, commit e risposte in italiano.
- **Vincoli che non vanno violati senza nuovo ADR**: un solo admin = superuser PocketBase, gli utenti con account possono solo guardare ([ADR 0013](docs/adr/0013-accesso-su-rete-di-casa.md)); progresso e "visto" per utente ([ADR 0008](docs/adr/0008-progresso-per-utente.md)); filmati solo in categorie foglia ([ADR 0010](docs/adr/0010-filmati-solo-nelle-foglie.md)); originali conservati nell'MVP (N-06 in [docs/01-vision-requisiti.md](docs/01-vision-requisiti.md)).
- **Ogni modifica a una regola API o a un campo dati**: aggiorna il modello in [docs/02-architettura.md](docs/02-architettura.md) e ricontrolla i casi limite di accesso (un utente non deve vedere né scrivere i dati di un altro).
- **Fatti su PocketBase/ffmpeg/codec/browser**: verifica sulla documentazione ufficiale e cita URL e data nell'ADR (regola 5). Non assumere comportamenti a memoria (es. collection `users` predefinita: non confermata).
- **Nuovo documento**: aggiungilo a `docs/index.md`. **Nuovo ADR**: aggiungi la riga al registro in `docs/index.md` e usa il template [docs/adr/0000-template.md](docs/adr/0000-template.md).
- **Alla chiusura di una domanda aperta** (Q-xx): rimuovila da `docs/04-rischi-e-domande-aperte.md`, registra l'esito nel requisito o nell'ADR, aggiorna `PROJECT_STATE.md` e `CHANGELOG.md`.
- **Segreti**: nessuna password o token nel repo, nei log o nel changelog; il superuser si crea come da documentazione PocketBase ([ADR 0012](docs/adr/0012-pannello-admin-proprio.md)).
- **Verifica dei link** tra file `.md` dopo ogni modifica alla documentazione.
+32
View File
@@ -0,0 +1,32 @@
# Videoteca
Web app **locale** per archiviare filmati per categoria/sottocategoria e guardarli nel browser, con ripresa dal punto in cui si era rimasti.
- Stato corrente: [docs/PROJECT_STATE.md](docs/PROJECT_STATE.md)
- Indice documentazione e fonti uniche: [docs/index.md](docs/index.md)
- Storico modifiche: [CHANGELOG.md](CHANGELOG.md)
## Cosa c'è da fare
Stato: documentazione completa, **nessun codice** (primo commit = solo documentazione). Dettagli e criteri di completamento: [docs/03-roadmap.md](docs/03-roadmap.md).
1. **Assunzioni dell'MVP** (da rivedere dopo): [docs/04-rischi-e-domande-aperte.md](docs/04-rischi-e-domande-aperte.md).
2. **M0** — spike: PocketBase in locale, prova di codec e ffmpeg su 3 file campione.
3. **M1** — schema dati, utenti e regole di accesso.
4. **M2** — upload e ricodifica.
5. **M3 / M3b** — interfaccia per gli utenti e pannello admin.
6. **M4** — player con ripresa.
7. **M5** — robustezza, backup. **M6** (futura) — esposizione in rete con HTTPS.
## Principi del repo
| Principio | Significato qui |
|---|---|
| Docs-as-code | Tutta la documentazione è Markdown nel repo, versionata con il codice |
| Document-first | Prima si scrive/aggiorna doc o ADR, poi il codice |
| ADR | Ogni scelta tecnica rilevante ha un record in `docs/adr/` |
| SSOT | Ogni informazione ha **un solo** documento di riferimento (vedi `docs/index.md`); gli altri la linkano |
## Avvio (a regime, dopo M1)
Da definire in `docs/02-architettura.md` §Esecuzione. Non duplicare qui i comandi: linkare.
+45
View File
@@ -0,0 +1,45 @@
# Visione e requisiti
## Visione
Archivio personale di filmati, navigabile per categoria → sottocategoria, riproducibile nel browser, che occupa meno spazio possibile senza attese di "decompressione" e ricorda dove ti sei fermato.
## Correzione del presupposto iniziale
L'idea originale era: salvare i filmati in archivio (zip/tar.gz), decomprimerli all'apertura, ricomprimerli alla chiusura. Non adottata: gli .mp4 (H.264/H.265) sono già compressi e un archivio generico non li riduce in modo apprezzabile, mentre costa tempo e spazio temporaneo a ogni apertura. Il risparmio reale si ottiene **ricodificando** il video una sola volta. Dettagli: [ADR 0002](adr/0002-ricodifica-invece-di-archivio.md).
Conseguenza: non esiste il ciclo "decomprimi → guarda → ricomprimi"; il file è sempre pronto alla riproduzione.
## Requisiti funzionali
| ID | Requisito | Priorità |
|---|---|---|
| F-01 | Gestire categorie con sottocategorie (es. A → A1, A2) | Must |
| F-02 | Caricare un filmato assegnandolo a una categoria foglia (come un episodio in una stagione; [ADR 0010](adr/0010-filmati-solo-nelle-foglie.md)) | Must |
| F-03 | Dopo il caricamento il filmato viene ricodificato per ridurne il peso; stato visibile (in elaborazione / pronto / errore) | Must |
| F-04 | Navigare: scegli categoria → sottocategoria → filmato | Must |
| F-05 | Riprodurre nel browser con play/pausa, seek avanti/indietro (±10 s e barra) | Must |
| F-06 | Alla pausa/chiusura, la posizione è salvata; alla riapertura si riparte da lì | Must |
| F-07 | Segnare come "visto" un filmato finito (la posizione riparte da 0) | Should |
| F-08 | Passare al filmato precedente/successivo della stessa categoria | Must (insieme ai ±10 s di F-05) |
| F-09 | Rinominare/spostare/eliminare filmati e categorie | Should |
| F-10 | Miniatura per filmato | Could |
| F-11 | Aggiungere, modificare ed eliminare filmati, categorie e sottocategorie (F-01, F-02, F-09) richiede un accesso (login); senza accesso non si può modificare nulla. Esiste un solo account admin e solo lui ha questo accesso; è il superuser PocketBase e vale già dall'MVP ([ADR 0013](adr/0013-accesso-su-rete-di-casa.md)) | Must |
| F-12 | Per guardare i filmati serve un account (login). Gli utenti con account possono solo guardare: non possono aggiungere, modificare né eliminare nulla (per ora) | Must |
| F-14 | Pannello admin intuitivo, accessibile solo all'admin: caricare filmati con stato di elaborazione visibile, gestire l'albero categorie/stagioni, gestire gli account utenti (creare con password iniziale, reimpostare la password dimenticata, eliminare), rinominare/spostare/eliminare con conferma ([ADR 0012](adr/0012-pannello-admin-proprio.md)) | Must |
| F-15 | Ogni utente ha un profilo con impostazioni dove può cambiare la propria password; la password iniziale la decide l'admin alla creazione dell'account. Se la dimentica, la reimposta l'admin (nessun recupero via email, N-01 costo zero). Un utente può modificare solo il proprio profilo | Must |
## Requisiti non funzionali
| ID | Requisito |
|---|---|
| N-01 | L'app gira su un Raspberry Pi nella rete di casa; telefoni, tablet e PC la raggiungono dall'indirizzo IP del Raspberry (decisione 2026-10-11). Nessun accesso da Internet; nessun servizio a pagamento |
| N-02 | Seek fluido anche su file grandi: nessuna riproduzione "tutto in memoria" |
| N-03 | Un upload interrotto o una transcodifica fallita non lasciano stato incoerente né file orfani |
| N-04 | I dati vivono in una sola cartella (`pb_data/`) per un backup semplice |
| N-05 | Ogni scelta tecnica rilevante è tracciata in un ADR |
| N-06 | Gli originali sono conservati durante l'MVP, finché la qualità non è validata |
| N-07 | Compatibilità ampia (decisione 2026-10-11): deve funzionare in modo affidabile su Safari iOS, Chrome Android e Windows (Chrome/Edge), oltre agli altri browser desktop. Implicazioni: interfaccia adatta al touch (pulsanti ±10 s e precedente/successivo grandi, niente scorciatoie solo da tastiera), layout responsive, riproduzione in pagina, file video riproducibili da tutti i browser (vedi [ADR 0003](adr/0003-codec-av1-vs-hevc.md)) |
| N-08 | Qualità: ricodifica "visivamente identica" (CRF prudente, taratura in M0 con confronto visivo); non lossless. Si parte con pochi filmati e poi si allarga |
| N-09 | Dimensionamento iniziale (decisione 2026-10-11): circa 40 filmati da 2-3 GB ciascuno, cioè circa 80-120 GB di originali; SSD da 1 TB. Il risparmio reale e i tempi di ricodifica si misurano in M0 |
| N-10 | Il backend e la ricodifica devono poter girare su Raspberry Pi (Linux ARM). Modello, RAM e disco: Q-14 |
## Fuori scopo (per ora)
Permessi utente oltre a "guardare" (F-12) e "amministrare" (F-11), accesso da Internet, streaming adattivo (HLS/DASH), sottotitoli, trascodifica al volo per dispositivi diversi.
+91
View File
@@ -0,0 +1,91 @@
# Architettura
## Vista d'insieme
```
Browser ──HTTP──> PocketBase (Raspberry Pi, rete di casa, :8090; ADR 0013)
│ ├─ / → pb_public/ (frontend statico, ADR 0007)
│ ├─ /api/... → REST: categories, videos, progress
│ ├─ /api/files/ → video (Range supportato)
│ └─ pb_hooks/ → logica di ingest (ADR 0004)
└─ <video> nativo ffmpeg (processo esterno) ← ricodifica
```
Stack: PocketBase ([ADR 0001](adr/0001-backend-pocketbase.md)), JS vanilla senza build ([ADR 0007](adr/0007-frontend-vanilla.md)), ffmpeg ([ADR 0004](adr/0004-pipeline-di-ingest.md)).
## Struttura del repository
```
videoteca/
├─ CLAUDE.md README.md CHANGELOG.md
├─ docs/ (questa documentazione)
├─ pb_public/ frontend (index.html, app.js, style.css)
├─ pb_hooks/ hook JS di PocketBase
├─ pb_migrations/ migrazioni schema (committate)
├─ scripts/ ingest/utility (se ADR 0004 lo richiede)
├─ pocketbase binario (non committato)
└─ pb_data/ DB + file (NON committato, .gitignore)
```
## Modello dati
**categories**
| Campo | Tipo | Note |
|---|---|---|
| name | text, obbligatorio | |
| parent | relation → categories, opzionale | `null` = categoria radice ([ADR 0005](adr/0005-categorie-ad-albero.md)) |
| position | number | ordinamento manuale |
Vincoli: nome univoco tra fratelli; una categoria o ha figli o ha filmati, mai entrambi ([ADR 0010](adr/0010-filmati-solo-nelle-foglie.md)); no cicli (parent ≠ sé stesso né un discendente); eliminazione di una categoria con figli/filmati **bloccata** (non a cascata).
**videos**
| Campo | Tipo | Note |
|---|---|---|
| title | text | |
| category | relation → categories, obbligatorio | |
| file | file (mp4), `maxSize` alzato | default PocketBase ~5 MB, va configurato |
| thumb | file (immagine), opzionale | |
| status | select: processing / ready / error | |
| error_msg | text | diagnostica in caso di errore |
| duration_s, size_bytes, original_size_bytes, codec | number/text | statistiche, utili per misurare il risparmio |
**progress** (un record per utente e filmato, [ADR 0008](adr/0008-progresso-per-utente.md); salvataggio: [ADR 0006](adr/0006-posizione-di-riproduzione.md))
| Campo | Tipo | Note |
|---|---|---|
| user | relation → utenti | eliminazione a cascata con l'utente; rules: ognuno vede solo i propri record |
| video | relation → videos, univoco insieme a `user` | eliminazione a cascata col filmato |
| position_s | number | |
| completed | bool | |
## Flussi
**Ingest** (F-02, F-03): upload → record `status=processing` → ricodifica ffmpeg → file sostituito, statistiche scritte, `status=ready`. In caso di errore: `status=error` + `error_msg`, file originale conservato. Meccanica esatta: [ADR 0004](adr/0004-pipeline-di-ingest.md).
**Navigazione** (F-04): lista figli di `parent=X` (o radici) + filmati con `category=X` e `status=ready`.
**Riproduzione e ripresa** (F-05, F-06):
1. `<video src=/api/files/videos/ID/FILE preload="metadata">`.
2. `loadedmetadata`: se esiste un `progress` dell'utente loggato non completato, `currentTime = position_s` (se mancano meno di ~5 s alla fine, riparti da 0).
3. Salvataggio: all'evento `pause`, ogni ~10 s in riproduzione, su `visibilitychange`/`pagehide` (fetch con `keepalive`). Scritture limitate per non martellare il DB.
4. `ended` → `completed=true`, `position_s=0`.
5. Controlli: controlli nativi + pulsanti −10 s/+10 s + tastiera (spazio, ←/→).
Il seek funziona perché PocketBase serve i file con `http.ServeContent` (Range supportato, verificato nel codice sorgente il 2026-10-11) e perché i file mp4 sono prodotti con `-movflags +faststart` (indice `moov` all'inizio).
## Casi limite da coprire (checklist per i moduli)
- Upload: file non video, mp4 corrotto, estensione falsa, file enorme, nome con caratteri speciali, upload duplicato, disco pieno.
- Transcodifica: ffmpeg assente, processo killato, riavvio di PocketBase durante l'elaborazione (record bloccati in `processing` → riconciliazione all'avvio), file già in codec target, nessuna traccia audio, rotazione/metadata, risultato più grande dell'originale (tenere l'originale).
- Account: password dimenticata (la reimposta l'admin dal pannello; la comunica di persona o con un messaggio, fuori dall'app), utente eliminato mentre ha una sessione aperta, cambio password con sessioni già attive, utente che modifica il profilo di un altro (rifiutato dalle rules), password debole.
- Categorie: filmato in una categoria con figli, sottocategoria sotto una categoria con filmati, spostamento di filmati o rami che viola la regola foglie, cicli, eliminazione con contenuti, nomi duplicati, spostamento di un ramo.
- Player: filmato eliminato mentre è aperto, codec non supportato dal browser (messaggio chiaro), due schede sullo stesso filmato (vince l'ultima scrittura), posizione oltre la durata.
- Dati: backup/ripristino di `pb_data/`, migrazioni su dati esistenti.
## Esecuzione
Da compilare in M0/M1 (comandi di avvio, variabili, percorso ffmpeg). Unico posto in cui vivono: qui. Creazione del superuser e pannello admin: [ADR 0012](adr/0012-pannello-admin-proprio.md).
## Sicurezza (rete di casa)
Il server gira sul Raspberry Pi ed è in ascolto sulla rete locale (non più solo su 127.0.0.1), non esposto a Internet: niente port forwarding sul router. Le API rules sono restrittive già dall'MVP: lettura solo da utenti loggati, scrittura solo al superuser ([ADR 0013](adr/0013-accesso-su-rete-di-casa.md)). Rischio: su HTTP semplice le password viaggiano in chiaro sulla rete Wi-Fi di casa (R-08, Q-16). Esposizione a Internet: fase M6 in [03-roadmap.md](03-roadmap.md).
+25
View File
@@ -0,0 +1,25 @@
# Roadmap
MVP = M0-M4 con l'admin che usa la dashboard standard di PocketBase; il pannello admin proprio (M3b) segue subito dopo. Regola per ogni fase: **document-first** (doc/ADR aggiornati prima del codice) e, a fine fase, aggiornamento di `PROJECT_STATE.md` e `CHANGELOG.md`.
| Fase | Obiettivo | Deliverable | Criterio di completamento |
|---|---|---|---|
| **M0 — Spike e fondamenta** | Chiudere i rischi tecnici prima di costruire | Repo con docs; PocketBase (build ARM da verificare) e ffmpeg avviati sul Raspberry reale; 3 file campione provati (tra i 2 e i 3 GB, N-09) su Safari iOS, Chrome Android e Windows reali (N-07) | Vedi sotto |
| **M1 — Dati** | Schema e gestione categorie | Migrazioni in `pb_migrations/`; collezioni `categories`, `videos`, `progress`; validazione cicli e regola foglie ([ADR 0010](adr/0010-filmati-solo-nelle-foglie.md)); creazione del superuser (da documentazione PocketBase), collection utenti e rules (ogni utente modifica solo il proprio profilo, F-15) ([ADR 0013](adr/0013-accesso-su-rete-di-casa.md)) | Categorie creabili/spostabili da dashboard; cicli rifiutati |
| **M2 — Ingest** | Upload → ricodifica → pronto | Pipeline secondo ADR 0004 | Upload di un file di test arriva a `ready`; errori finiscono in `error`; riavvio riconciliato |
| **M3 — Navigazione UI** | Categoria → sottocategoria → lista filmati | `pb_public/` | Login utente; pagina profilo con cambio password (F-15); navigazione completa, stati di caricamento/vuoto/errore |
| **M3b — Pannello admin** | Gestione da interfaccia | Pagina admin in `pb_public/` con login superuser: upload con stato, albero categorie, gestione account utenti (creazione, reimpostazione password, eliminazione), modifica/sposta/elimina ([ADR 0012](adr/0012-pannello-admin-proprio.md)) | L'admin carica un filmato, ne vede lo stato fino a `ready`, crea una stagione, sposta e elimina con conferma; un utente normale non accede né scrive |
| **M4 — Player e ripresa** | Riproduzione con ripresa | Player, salvataggio posizione, "visto" | Pausa → chiudi → riapri riparte dallo stesso punto (±2 s); seek corretto su file grande; precedente/successivo; un utente non legge né scrive il progresso di un altro ([ADR 0008](adr/0008-progresso-per-utente.md)) |
| **M5 — Qualità** | Robustezza | Checklist casi limite (docs/02) verificata; backup/ripristino provato; lint Markdown e link check | Tutti i casi della checklist hanno esito documentato |
| **M6 — Esposizione in rete** *(futura)* | Uso da Internet (la rete di casa è già nell'MVP, N-01) | HTTPS e revisione rules (l'auth c'è già dall'MVP, ADR 0013) | Nuovo ADR sulla sicurezza prima di iniziare |
## M0 in dettaglio (spike)
1. Scaricare PocketBase (versione fissata) dal sito ufficiale e avviarlo in locale.
2. Su 3 file reali (piccolo, medio, grande): ricodificare con ffmpeg in AV1 e HEVC; **misurare** peso prima/dopo e tempo.
3. Provarli nei browser che usi davvero (riproduzione, seek, riapertura) → decide [ADR 0003](adr/0003-codec-av1-vs-hevc.md).
4. Misurare cosa fa zip/tar.gz sugli stessi file → conferma [ADR 0002](adr/0002-ricodifica-invece-di-archivio.md).
5. Verificare: limite upload per file grandi; seek con `Range` via `/api/files/`; esecuzione non bloccante di ffmpeg da hook → decide [ADR 0004](adr/0004-pipeline-di-ingest.md).
6. Aggiornare ADR, rischi e `PROJECT_STATE.md` con i risultati misurati.
**Fatto quando**: ADR 0003 e 0004 sono "Accettato" con numeri a supporto, e R-01…R-03 sono chiusi o ridimensionati.
+31
View File
@@ -0,0 +1,31 @@
# Rischi e domande aperte
## Rischi
| ID | Rischio | Impatto | Mitigazione | Stato |
|---|---|---|---|---|
| R-01 | PocketBase è pre-1.0: possibili breaking change tra versioni | Medio | Versione fissata; leggere il changelog prima di aggiornare; migrazioni committate; backup prima di ogni upgrade | Aperto |
| R-02 | ffmpeg non eseguibile in modo non bloccante dai hook | Alto (cambia ADR 0004) | Spike M0; ripiego: worker esterno | Aperto |
| R-03 | Codec scelto non riproducibile dal browser (target: Safari iOS, Chrome Android e desktop, N-07) | Alto | Matrice di test in M0 anche su iPhone/Android reali; messaggio chiaro nel player | Aperto |
| R-04 | Perdita di qualità/originali con la ricodifica | Medio | Originali conservati durante l'MVP (N-06); dove e per quanto: da definire in M0 (spazio disco) | Aperto |
| R-05 | Limite upload/body per file grandi (file da 2-3 GB, N-09), anche dal pannello admin | Medio | Verifica in M0; documentare la configurazione | Aperto |
| R-06 | Dati persi (nessun backup di `pb_data/`; originali + ricodificati circa 120-200 GB: stima da confermare in M0, il backup deve starci su un secondo disco) | Alto | Procedura di backup/ripristino in M5 | Aperto |
| R-07 | Il Raspberry è lento per la ricodifica (AV1 in software molto lento; Pi 5 senza encoder H.264 hardware, Pi 4 con encoder H.264 hardware limitato nella qualità, [Raspberry Pi](https://pip-assets.raspberrypi.com/categories/685-app-notes-guides-whitepapers/documents/RP-010033-WP-1-H.264%20encoding%20performance%20on%20Raspberry%20Pi%205_series%20computers.pdf), consultato 2026-10-11) | Alto | Misurare in M0 sul Raspberry reale; ricodifica sul PC (Q-15) |
| R-08 | Password in chiaro su HTTP in rete locale | Medio | Q-16; password dedicate all'app |
## Domande aperte (richiedono una tua decisione)
Nessuna bloccante. Le questioni di dettaglio (modello di Raspberry, dove ricodificare, HTTP/HTTPS, admin da telefono) sono sotto come assunzioni dell'MVP.
## Assunzioni adottate per l'MVP (su richiesta dell'utente, 2026-10-11: "iniziare con l'MVP e poi curare i dettagli")
Sono default scelti per poter partire, non risposte dell'utente: da rivedere dopo l'MVP. Se una cambia, aggiornare qui e, se tecnica, con un nuovo ADR.
| ID | Tema | Assunzione per l'MVP | Quando rivederla |
|---|---|---|---|
| Q-13 | Pannello admin da telefono | Solo da PC; il telefono serve per guardare | Dopo M3b |
| Q-14 | Raspberry (modello, OS, disco) | Raspberry Pi a 64 bit con SSD USB; il codice non dipende dal modello. Fino alla disponibilità del Raspberry si sviluppa su PC | Quando il Raspberry è disponibile (M0) |
| Q-15 | Dove avviene la ricodifica | Dove gira il server (il PC in sviluppo, poi il Raspberry); se sul Raspberry è troppo lenta (R-07), si ricodifica sul PC e si carica il file già pronto | Dopo la misura dei tempi in M0 |
| Q-16 | HTTP o HTTPS in rete di casa | HTTP, con password dedicate all'app (non riusate altrove) | M6 |
| Q-05 | Dimensioni | ~40 filmati da 2-3 GB (N-09); si parte con pochi | Quando i numeri cambiano |
| Codec | Formato video | H.264 (unico dato come universale da MDN, N-07); parametro configurabile ([ADR 0003](adr/0003-codec-av1-vs-hevc.md) resta Proposto) | Dopo le misure di M0 |
+26
View File
@@ -0,0 +1,26 @@
# Stato del progetto
Aggiornato: 2026-10-11
## Fase corrente
Pre-M0: documentazione completa, nessun codice.
## Decisioni prese
Registro completo e stato di ogni ADR: [index.md](index.md). In sintesi:
- Backend PocketBase (0001); ricodifica invece di archivio (0002).
- Categorie ad albero con filmati solo nelle foglie, stile serie/stagioni (0010, sostituisce 0005).
- Progresso e "visto" per utente (0008, sostituisce 0006); frontend vanilla (0007).
- Accesso (0013, sostituisce 0009): per guardare serve un account; un solo admin (superuser PocketBase) aggiunge/modifica/elimina; account creati solo dall'admin; valido già dall'MVP.
- Pannello admin proprio e intuitivo (0012, sostituisce 0011); superuser creato come da documentazione PocketBase, nessuna password in `.env`.
- Raspberry Pi nella rete di casa, accessibile dall'IP (N-01, N-10); nessun accesso da Internet.
- Profilo utente con cambio password; password iniziale decisa dall'admin (F-15); password dimenticata reimpostata dall'admin, comunicata fuori dall'app.
- Dimensionamento iniziale: ~40 filmati da 2-3 GB, SSD 1 TB (N-09).
- Web app compatibile con Safari iOS, Chrome Android e Windows oltre al resto del desktop (N-07); qualità "visivamente identica" (N-08).
- Precedente/successivo (F-08) e ±10 s: entrambi Must. Originali conservati nell'MVP (N-06).
## Decisioni in sospeso
- Codec (ADR 0003) e pipeline di ingest (ADR 0004): per l'MVP vale H.264 configurabile; si confermano con le misure di M0.
- Nessuna domanda bloccante: i dettagli (Raspberry, ricodifica, HTTP/HTTPS, admin da telefono) sono assunzioni dell'MVP in [04-rischi-e-domande-aperte.md](04-rischi-e-domande-aperte.md).
## Prossimo passo
Iniziare l'MVP: M0 (spike con 3 filmati campione) e M1 (schema, utenti, regole) secondo [03-roadmap.md](03-roadmap.md). L'admin usa la dashboard di PocketBase finché non c'è il pannello (M3b).
+19
View File
@@ -0,0 +1,19 @@
# NNNN — Titolo
- **Stato**: Proposto | Accettato | Sostituito da NNNN
- **Data**: AAAA-MM-GG
## Contesto
Problema e vincoli.
## Decisione
Cosa si fa.
## Alternative considerate
Opzione → perché sì/no.
## Conseguenze
Positive, negative, cosa va verificato.
## Fonti
Link con data di consultazione.
+28
View File
@@ -0,0 +1,28 @@
# 0001 — Backend: PocketBase
- **Stato**: Accettato (con riserve, vedi R-01)
- **Data**: 2026-10-11
## Contesto
Serve un backend locale, gratuito, con DB, API, storage file e Range. Obiettivo: poca infrastruttura e poco codice.
## Decisione
PocketBase (eseguibile singolo, SQLite embedded, REST, dashboard admin, storage file, hook JS, serve anche `pb_public/`).
## Alternative
- Python + FastAPI + SQLite: più controllo e ffmpeg più naturale, ma più codice da scrivere/mantenere (API, upload, Range, migrazioni).
- Node + Express: idem.
## Conseguenze
- ✔ Un solo binario (~12 MB), nessuna dipendenza, admin UI gratuita per gestire categorie in M1.
- ✔ File serviti con Range: `Serve` usa `http.ServeContent`.
- ✔ Migrazioni in `pb_migrations/` committabili.
- ⚠ **Pre-1.0**: la documentazione ufficiale dice che la retrocompatibilità non è garantita e che non è raccomandato per applicazioni di produzione critiche senza leggere il changelog e applicare migrazioni manuali. Per un uso locale personale è accettabile; **fissare la versione** (oggi v0.40.5) e aggiornare in modo consapevole.
- ⚠ Limite file: i campi file hanno max ~5 MB di default; va alzato nelle opzioni del campo (verificare in M0 anche limiti di body/upload per file grandi).
- ⚠ Il motore JS dei hook (goja) è ES5/ES6 parziale, senza `setTimeout`, né concorrenza dentro un handler: la transcodifica non va eseguita in modo bloccante in un handler → vedi [ADR 0004](0004-pipeline-di-ingest.md).
## Fonti (consultate 2026-10-11)
- https://pocketbase.io/docs/ (versione, avviso pre-1.0, directory)
- https://pocketbase.io/docs/files-handling/ (limite ~5 MB, storage locale/S3)
- https://pocketbase.io/docs/js-overview/ (goja, `$os`, limiti del motore)
- https://github.com/pocketbase/pocketbase/blob/master/tools/filesystem/filesystem.go (`Serve` → `http.ServeContent`)
@@ -0,0 +1,20 @@
# 0002 — Ricodifica video invece di archivio zip/tar.gz
- **Stato**: Accettato
- **Data**: 2026-10-11
## Contesto
Requisito originale: risparmiare spazio salvando i filmati compressi e decomprimendoli all'apertura.
## Decisione
Non usare archivi. Alla prima acquisizione il video viene **ricodificato una volta** con un codec più efficiente e salvato come .mp4 direttamente riproducibile.
## Alternative
- zip/tar.gz con decompressione all'apertura: gli mp4 sono già compressi da codec video, quindi un compressore generico guadagna in genere pochissimo (ordine di 0-2%, **da misurare sui tuoi file in M0**); costa attesa, spazio temporaneo, gestione dei file decompressi aperti e della ricompressione.
- Tenere gli mp4 così come sono: nessun risparmio, nessuna perdita di qualità. Resta un'opzione valida se lo spazio non è un problema.
## Conseguenze
- ✔ Nessun ciclo decomprimi/ricomprimi; seek e ripresa nativi.
- ✔ Risparmio reale (da misurare in M0; l'entità dipende da sorgente e impostazioni).
- ⚠ Ricodificare è **con perdita**: tenere gli originali finché la qualità del risultato non è validata (Q-04).
- ⚠ Costo: tempo di CPU all'ingest.
+40
View File
@@ -0,0 +1,40 @@
# 0003 — Codec di destinazione: AV1 o HEVC (H.265)
- **Stato**: **Proposto** — decide lo spike M0 con i dispositivi di N-07 (Safari iOS, Chrome Android, desktop)
- **Data**: 2026-10-11
## Contesto
Il video è riprodotto dal tag `<video>` del browser, quindi il codec deve essere decodificabile dal browser dell'utente.
## Supporto browser (caniuse, consultato 2026-10-11)
| Browser | AV1 | HEVC |
|---|---|---|
| Chrome / Edge | Supportato | Parziale |
| Firefox | Supportato | Parziale (dalla 137) |
| Safari (macOS/iOS) | Parziale | Supportato |
"Parziale" per HEVC su Chrome/Edge/Firefox dipende da decodifica hardware/OS: va provato sulla macchina reale. Per Safari AV1 è "parziale" (tipicamente richiede hardware recente).
## Browser di destinazione
Requisito dell'utente (2026-10-11, N-07): compatibilità ampia, in particolare Safari iOS, Chrome Android e Windows (su Windows HEVC in Chrome richiede un decoder hardware, quindi non è affidabile). Con questo vincolo un solo codec moderno spesso non basta:
- AV1 su Safari richiede un decoder hardware (Safari 17: Mac M3 e successivi, iPhone 15 Pro, iPhone 16 e successivi): non è garantito sui iPhone più vecchi.
- HEVC su Chrome dipende dall'hardware/OS (decoder hardware su Windows, Linux e ChromeOS; macOS Big Sur 11+ e Android 5.0+).
- H.264 è l'unico indicato come supportato da tutte le versioni di Chrome, Edge, Firefox, Opera e Safari, ma comprime meno.
Fonte: https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Formats/Video_codecs (consultata 2026-10-11; le tabelle HEVC della pagina sono incoerenti: riconfermare con caniuse e con prova diretta in M0).
Strade possibili (la scelta è dell'utente dopo le misure di M0): (a) H.264 come unica copia: massima compatibilità, risparmio di spazio minore; (b) H.264 + una seconda versione AV1/HEVC per i dispositivi che la supportano: più spazio e più complessità; (c) un solo codec moderno e rinuncia ai dispositivi più vecchi. Se si vuole "compatibile con tutti", (a) è la più semplice e va misurata per prima.
## Opzioni
- **AV1** (libsvtav1): libero da royalty, buon supporto su Chrome/Edge/Firefox, ottima efficienza; codifica più lenta.
- **HEVC** (libx265, `-tag:v hvc1`): ottimo su Safari, supporto altrove legato all'hardware; codifica media.
- **H.264 ricodificato con CRF più alto**: massima compatibilità, risparmio minore.
## Decisione provvisoria
Se si usa Chrome/Edge/Firefox → AV1. Se Safari → HEVC. Il default non si fissa finché M0 non ha: (1) verificato la riproduzione sui browser dell'utente, (2) misurato risparmio e tempi su 3 file campione, (3) confrontato la qualità visiva.
Parametri iniziali da tarare (non definitivi): `-c:v libsvtav1 -crf 30 -preset 6` oppure `-c:v libx265 -crf 26 -preset medium -tag:v hvc1`; audio `aac`; sempre `-movflags +faststart`.
## Conseguenze
Se il codec non è supportato, il player mostra un messaggio esplicito (non uno schermo nero).
## Fonti
- https://caniuse.com/av1 · https://caniuse.com/hevc (2026-10-11)
+21
View File
@@ -0,0 +1,21 @@
# 0004 — Pipeline di ingest e transcodifica
- **Stato**: **Proposto** — decide lo spike M0 (R-02)
- **Data**: 2026-10-11
## Contesto
PocketBase non transcodifica. Serve ffmpeg (processo esterno, gratuito). I hook JS possono eseguire comandi (`$os` espone l'esecuzione di comandi di shell), ma il motore non ha concorrenza interna a un handler.
## Opzioni
- **A. Hook su creazione record**: l'upload crea il record `processing`; un hook lancia ffmpeg. Se bloccante, la richiesta HTTP resta appesa per tutta la transcodifica → inadatto. Va verificato se si può avviare il processo in modo non bloccante (`$os.cmd(...).start()`): **non verificato**.
- **B. Script CLI separato** (`scripts/ingest`): lo script ricodifica e poi carica via API. L'upload "passa" dallo script, non dal browser. Semplice e robusto, UX meno immediata.
- **C. Worker che sonda i record `processing`** (script o processo separato) e li lavora in coda, uno alla volta (evita saturare la CPU).
## Decisione provvisoria
Preferire **C** (upload da browser → record `processing` → worker ricodifica → `ready`), con **B** come ripiego. **A** solo se lo spike dimostra che l'esecuzione non bloccante è affidabile.
## Requisiti indipendenti dall'opzione
Idempotenza (rilanciare non duplica); un job alla volta; file temporaneo scritto fuori da `pb_data/` e spostato a fine lavoro; all'avvio i record bloccati in `processing` vengono riconciliati; se l'output è più grande dell'originale si tiene l'originale; scritte statistiche (peso prima/dopo, durata, codec).
## Da verificare in M0
Esecuzione non bloccante da hook; limite di dimensione upload accettato da PocketBase per file grandi; comportamento a riavvio durante la lavorazione.
+19
View File
@@ -0,0 +1,19 @@
# 0005 — Categorie come albero (self-relation)
- **Stato**: Sostituito da 0010
- **Data**: 2026-10-11
## Contesto
Categoria A contiene A1, A2…; oggi serve un livello di sottocategorie, domani potrebbero servirne di più.
## Decisione
Collezione `categories` con campo `parent` (relazione a sé stessa, nullo per le radici). Il modello supporta profondità arbitraria; la UI naviga un livello alla volta in modo generico.
## Alternative
- Due collezioni (categorie, sottocategorie): più rigida, da riscrivere se serve un terzo livello.
- Percorso come testo (`A/A1`): fragile in rinomina/spostamento.
## Conseguenze
- Serve evitare i cicli (validazione in hook di creazione/aggiornamento).
- Eliminazione bloccata se ci sono figli o filmati.
- Un filmato può stare anche in una categoria non foglia (Q-02).
@@ -0,0 +1,16 @@
# 0006 — Salvataggio della posizione di riproduzione
- **Stato**: Sostituito da 0008
- **Data**: 2026-10-11
## Contesto
Alla pausa o chiusura il filmato deve ripartire dal punto in cui era.
## Decisione
Collezione `progress` (un record per filmato) nel DB. Scritture: su `pause`, ogni ~10 s in play, su `visibilitychange`/`pagehide` con `keepalive`.
## Alternative
- `localStorage`: zero backend, ma legato a un solo browser/profilo e perso se si svuotano i dati del sito.
## Conseguenze
Persistente, nel backup di `pb_data/`, e riutilizzabile se in futuro ci saranno più dispositivi. Ultima scrittura vince in caso di due schede aperte.
+16
View File
@@ -0,0 +1,16 @@
# 0007 — Frontend senza build step
- **Stato**: Accettato
- **Data**: 2026-10-11
## Contesto
Interfaccia semplice (alberatura, lista, player, upload). Obiettivo: minima complessità e zero toolchain.
## Decisione
HTML + JavaScript (moduli ES) + CSS serviti da `pb_public/`, SDK JavaScript ufficiale di PocketBase. Player: tag `<video>` nativo.
## Alternative
Svelte/React con Vite: più comodo se la UI cresce, ma aggiunge toolchain e build. Rivalutabile con un nuovo ADR se la UI supera la gestione manuale.
## Conseguenze
Niente transpile né bundle; il codice deve restare organizzato in moduli piccoli.
+24
View File
@@ -0,0 +1,24 @@
# 0008 — Progresso di riproduzione per utente
- **Stato**: Accettato
- **Data**: 2026-10-11
## Contesto
Con gli account (F-12) più persone guardano gli stessi filmati. [ADR 0006](0006-posizione-di-riproduzione.md) prevedeva un record `progress` per filmato, quindi condiviso: la posizione di uno sovrascriverebbe quella degli altri.
## Decisione
Il record `progress` è univoco per coppia (utente, filmato). Resta invariato il resto di ADR 0006 (collezione nel DB, momenti di scrittura: `pause`, ~10 s in play, `visibilitychange`/`pagehide` con `keepalive`). Anche lo stato "visto" (`completed`, F-07) è per utente.
Le API rules permettono a ciascun utente di leggere e scrivere solo i propri record `progress`. Dettaglio dei campi: [02-architettura.md](../02-architettura.md).
## Alternative considerate
- Progresso condiviso (ADR 0006): semplice, ma sbagliato con più utenti.
- `localStorage`: già scartato in ADR 0006; per utente non seguirebbe l'account tra dispositivi.
## Conseguenze
- ✔ Ogni utente riprende dal proprio punto.
- ✔ Eliminando un utente o un filmato i relativi `progress` vanno eliminati a cascata.
- ✘ Più record (utenti × filmati) e una regola in più da testare: un utente non deve poter leggere o scrivere il progresso di un altro (verificare in M4).
- Resta valido: con due schede dello stesso utente sullo stesso filmato vince l'ultima scrittura.
## Fonti
Nessuna esterna: decisione dell'utente del 2026-10-11 ("progresso per utente").
+29
View File
@@ -0,0 +1,29 @@
# 0009 — Accesso: admin = superuser PocketBase, utenti con account
- **Stato**: Sostituito da 0013
- **Data**: 2026-10-11
## Contesto
Requisiti [F-11 e F-12](../01-vision-requisiti.md): per guardare serve un account; solo l'admin (uno solo) aggiunge, modifica ed elimina filmati e categorie. Decisioni dell'utente del 2026-10-11: account creati solo dall'admin, accesso già dall'MVP, admin = superuser.
## Decisione
- **Admin**: l'unico superuser di PocketBase. Non è un ruolo applicativo: l'interfaccia di gestione (upload, categorie, modifica, eliminazione) richiede il login da superuser.
- **Utenti**: record di una collection di autenticazione, creati solo dall'admin; nessuna registrazione libera (`createRule` bloccata).
- **API rules** su `categories` e `videos`: lettura solo con `@request.auth.id != ""`; creazione, modifica, eliminazione bloccate (`null`) ⇒ solo superuser. Su `progress`: ogni utente solo i propri record ([ADR 0008](0008-progresso-per-utente.md)).
- Il server resta su 127.0.0.1 ([02-architettura.md](../02-architettura.md)); l'accesso vale già in locale.
## Alternative considerate
- Ruolo `admin` su un utente normale: permette più admin, ma l'utente ne vuole uno solo; più superficie e più regole da testare.
- Lettura libera senza login: scartata dall'utente (F-12).
- Registrazione libera: scartata, gli account li crea l'admin.
## Conseguenze
- ✔ Nessun codice di ruoli: le rules con `null` sono il meccanismo nativo.
- ✔ Pochissime regole da testare.
- ✘ L'admin non può guardare "come utente" con lo stesso account: i superuser ignorano le rules e non sono utenti della collection; per testare la vista utente serve un account utente.
- ✘ Il frontend deve gestire due login distinti (utente e superuser), da verificare in M1.
- Da verificare in M0/M1: nome e comportamento della collection di autenticazione utenti e del superuser nella versione fissata (la pagina collections non lo specifica); durata del token; reset password creata dall'admin.
## Fonti
- https://pocketbase.io/docs/api-rules-and-filters/ (consultata 2026-10-11): le rules sono ignorate per i superuser; `null` = solo superuser (default); stringa vuota = chiunque; `@request.auth.id != ""` = utente autenticato.
- https://pocketbase.io/docs/collections/ (consultata 2026-10-11): `_superusers` citata solo per la gestione delle collection; esistenza di una collection `users` predefinita e registrazione libera **non** confermate.
@@ -0,0 +1,24 @@
# 0010 — Categorie ad albero con filmati solo nelle foglie
- **Stato**: Accettato
- **Data**: 2026-10-11
- Sostituisce [0005](0005-categorie-ad-albero.md)
## Contesto
Risposta dell'utente a Q-02 (2026-10-11): la struttura è come una serie TV, cioè serie → stagioni → episodi. Gli episodi (filmati) stanno dentro le stagioni, non nella serie.
## Decisione
Resta quanto deciso in ADR 0005: collezione `categories` con `parent` (self-relation, nullo per le radici), profondità arbitraria, UI generica un livello alla volta.
Aggiunta: un filmato può appartenere solo a una categoria **foglia** (senza sottocategorie), e una categoria che contiene filmati non può ricevere sottocategorie. Una categoria è quindi o un contenitore di categorie o un contenitore di filmati, mai entrambe le cose.
## Alternative considerate
- Filmati ovunque nell'albero (ADR 0005): più flessibile, ma una categoria mista (sottocategorie + filmati sciolti) è ambigua da navigare e non corrisponde al modello serie/stagioni.
## Conseguenze
- Serve validazione in hook: creare un filmato in una categoria con figli, creare una sottocategoria sotto una categoria con filmati, e spostare filmati o rami che violerebbero la regola vengono rifiutati con messaggio chiaro.
- Si conferma: no cicli; eliminazione bloccata se ci sono figli o filmati.
- La navigazione ([02-architettura.md](../02-architettura.md)) in una categoria mostra o figli o filmati, mai entrambi.
- Da verificare: l'ordine degli episodi per il "precedente/successivo" (F-08) usa un campo di ordinamento manuale dentro la stagione.
## Fonti
Decisione dell'utente del 2026-10-11 (Q-02).
@@ -0,0 +1,26 @@
# 0011 — Interfaccia admin = dashboard PocketBase; credenziali in `.env`
- **Stato**: Sostituito da 0012
- **Data**: 2026-10-11
## Contesto
L'admin (un solo superuser, [ADR 0009](0009-accesso-admin-e-utenti.md)) deve caricare, modificare ed eliminare filmati e categorie (F-11). Decisioni dell'utente del 2026-10-11: iniziare con la dashboard di PocketBase; la password in `.env`.
## Decisione
- **Interfaccia admin dell'MVP**: la dashboard di PocketBase. Nessuna pagina di gestione nostra; il frontend ([ADR 0007](0007-frontend-vanilla.md)) è solo per gli utenti che guardano. Una pagina di gestione propria è rimandata e, se serve, avrà un nuovo ADR (motivo probabile: stato di ricodifica poco visibile dalla dashboard, vedi F-03).
- **Credenziali**: email e password del superuser stanno in `.env` nella radice, **mai committato** (in `.gitignore`). Il repo contiene solo `.env.example` con nomi e valori fittizi. Lo script di avvio legge `.env` e crea il superuser al primo avvio.
- `.env` serve solo alla creazione iniziale. Dopo, la password vive nel DB di PocketBase: cambiarla da dashboard non aggiorna `.env`, e viceversa. Per evitare ambiguità, `.env` non è la fonte di verità della password dopo il primo avvio.
## Alternative considerate
- Pagina di gestione propria dal giorno uno: più codice e più superficie da proteggere prima di aver validato la pipeline.
- Password solo nell'installer web: nessun file da proteggere, ma non ripetibile in modo scriptato.
## Conseguenze
- ✔ Nessun codice di gestione nell'MVP.
- ✘ Dalla dashboard l'upload è meno guidato e lo stato `processing / ready / error` si vede solo guardando il record.
- ✘ Password in chiaro su disco: accettabile solo perché il server è locale (127.0.0.1); permessi del file ristretti all'utente, mai nei log né nel changelog.
- Da verificare in M0/M1: l'host del file `.env` e come lo script lo legge (nessuna libreria: solo shell); se esiste un comando per aggiornare un superuser già esistente (nella documentazione consultata è confermato solo `superuser create`); dimensione massima di upload dalla dashboard.
## Fonti
- https://pocketbase.io/docs/going-to-production/ (consultata 2026-10-11): il primo superuser si crea con il comando `superuser create EMAIL PASS` o con il link dell'installer web scritto nei log. Nessun meccanismo generale per i segreti: le impostazioni sono salvate in chiaro nel DB; l'unica variabile d'ambiente citata serve a cifrarle (`--encryptionEnv`).
- https://pocketbase.io/docs/use-as-framework/ (consultata 2026-10-11): non descrive la creazione di superuser da CLI né credenziali via variabili d'ambiente. Quindi PocketBase **non** legge la password da `.env` da solo: lo fa lo script di avvio.
+28
View File
@@ -0,0 +1,28 @@
# 0012 — Pannello admin proprio; superuser creato come da documentazione PocketBase
- **Stato**: Accettato
- **Data**: 2026-10-11
- Sostituisce [0011](0011-interfaccia-admin-e-credenziali.md)
## Contesto
Nuova decisione dell'utente (2026-10-11): niente `.env` per la password; seguire la documentazione di PocketBase; l'admin gestisce tutto da un pannello (dashboard) intuitivo creato da noi, non dalla dashboard standard di PocketBase.
## Decisione
- **Superuser**: creato come indica la documentazione ufficiale: link dell'installer web scritto nei log al primo avvio, oppure `superuser create EMAIL PASS` da terminale. Nessun `.env` con la password, nessuno script che la legge. La password vive solo nel DB di PocketBase.
- **Pannello admin**: pagina del frontend ([ADR 0007](0007-frontend-vanilla.md), `pb_public/`, senza build step) accessibile solo dopo il login da superuser (`pb.collection('_superusers').authWithPassword`). Requisito: [F-14](../01-vision-requisiti.md).
- Le operazioni di scrittura restano protette dalle API rules ([ADR 0009](0009-accesso-admin-e-utenti.md)): il pannello è solo un'interfaccia; nascondere i pulsanti non è sicurezza.
- La dashboard standard di PocketBase resta disponibile come strumento di emergenza dell'admin (schema, ripristino), non come interfaccia d'uso.
## Alternative considerate
- Solo dashboard PocketBase (ADR 0011): zero codice, ma poco intuitiva per caricare e vedere lo stato della ricodifica.
- Password in `.env`: scartata dall'utente; PocketBase non la legge comunque da solo.
## Conseguenze
- ✔ Interfaccia pensata per le operazioni reali: carica, stato, categorie.
- ✘ Più codice frontend da scrivere e testare (fase M3b in [03-roadmap.md](../03-roadmap.md)), incluso il login da superuser separato da quello utenti.
- Casi limite da coprire: token scaduto durante un upload lungo (la durata del token superuser non è specificata nella documentazione consultata: verificare in M0), upload interrotto, eliminazione con contenuti (bloccata), doppio invio, rifiuto della regola foglie ([ADR 0010](0010-filmati-solo-nelle-foglie.md)) con messaggio chiaro.
- Accessibilità di base: tastiera, etichette dei campi, messaggi d'errore in italiano.
## Fonti
- https://pocketbase.io/docs/authentication/ (consultata 2026-10-11): il superuser si autentica con `authWithPassword` sulla collection `_superusers`; le rules sono ignorate per i superuser; durata del token non indicata.
- https://pocketbase.io/docs/going-to-production/ (consultata 2026-10-11): primo superuser via `superuser create EMAIL PASS` o installer web (link nei log).
+24
View File
@@ -0,0 +1,24 @@
# 0013 — Accesso: admin = superuser, utenti con account, server sulla rete di casa
- **Stato**: Accettato
- **Data**: 2026-10-11
- Sostituisce [0009](0009-accesso-admin-e-utenti.md)
## Contesto
L'app gira su un Raspberry Pi e telefoni, tablet e PC la raggiungono dall'indirizzo IP nella rete di casa (decisione dell'utente, 2026-10-11, N-01). L'ADR 0009 prevedeva il server solo su 127.0.0.1.
## Decisione
Resta quanto deciso in ADR 0009: admin = unico superuser PocketBase; utenti con account creati solo dall'admin, solo lettura; API rules: lettura con `@request.auth.id != ""`, scrittura (`null`) solo al superuser; `progress` solo propri record ([ADR 0008](0008-progresso-per-utente.md)); accesso già dall'MVP.
Cambia: il server ascolta sull'interfaccia di rete locale del Raspberry, non solo su 127.0.0.1. Nessuna esposizione a Internet (niente port forwarding sul router). Il trasporto (HTTP o HTTPS) è aperto: Q-16.
## Alternative considerate
- Solo 127.0.0.1 (ADR 0009): incompatibile con telefoni e tablet.
- Esposizione a Internet: fuori scopo per ora (fase M6).
## Conseguenze
- ✔ Le rules restrittive diventano indispensabili da subito: chiunque sia sulla rete di casa raggiunge il server.
- ✘ Su HTTP le password viaggiano in chiaro sul Wi-Fi di casa (R-08, Q-16).
- Da verificare in M0: indirizzo di ascolto e configurazione di PocketBase su rete locale (documentazione ufficiale); IP del Raspberry fisso o nome locale.
## Fonti
Decisione dell'utente del 2026-10-11. Fatti su PocketBase come in ADR 0009 (https://pocketbase.io/docs/api-rules-and-filters/ e https://pocketbase.io/docs/authentication/, consultate 2026-10-11).
+35
View File
@@ -0,0 +1,35 @@
# Indice della documentazione
## Fonti uniche (SSOT)
| Tema | Documento di riferimento |
|---|---|
| Cosa deve fare l'app, requisiti, fuori scopo | [01-vision-requisiti.md](01-vision-requisiti.md) |
| Architettura, modello dati, flussi, esecuzione | [02-architettura.md](02-architettura.md) |
| Perché una scelta tecnica è stata fatta | [adr/](adr/) |
| Fasi, criteri di completamento | [03-roadmap.md](03-roadmap.md) |
| Rischi e decisioni ancora aperte | [04-rischi-e-domande-aperte.md](04-rischi-e-domande-aperte.md) |
| A che punto siamo ora | [PROJECT_STATE.md](PROJECT_STATE.md) |
| Cosa è cambiato e quando | [../CHANGELOG.md](../CHANGELOG.md) |
Regola: se un'informazione compare in due posti, uno dei due diventa un link.
## Registro ADR
| N. | Titolo | Stato |
|---|---|---|
| [0001](adr/0001-backend-pocketbase.md) | Backend: PocketBase | Accettato (con riserve, vedi R-01) |
| [0002](adr/0002-ricodifica-invece-di-archivio.md) | Ricodifica video invece di zip/tar.gz | Accettato |
| [0003](adr/0003-codec-av1-vs-hevc.md) | Codec di destinazione | **Proposto** (decide lo spike M0) |
| [0004](adr/0004-pipeline-di-ingest.md) | Pipeline di ingest/transcodifica | **Proposto** (decide lo spike M0) |
| [0005](adr/0005-categorie-ad-albero.md) | Categorie come albero (self-relation) | Sostituito da 0010 |
| [0006](adr/0006-posizione-di-riproduzione.md) | Salvataggio della posizione di riproduzione | Sostituito da 0008 |
| [0007](adr/0007-frontend-vanilla.md) | Frontend senza build step | Accettato |
| [0008](adr/0008-progresso-per-utente.md) | Progresso di riproduzione per utente | Accettato |
| [0009](adr/0009-accesso-admin-e-utenti.md) | Accesso: admin = superuser, utenti con account | Sostituito da 0013 |
| [0010](adr/0010-filmati-solo-nelle-foglie.md) | Categorie ad albero con filmati solo nelle foglie | Accettato |
| [0011](adr/0011-interfaccia-admin-e-credenziali.md) | Interfaccia admin = dashboard PocketBase; credenziali in `.env` | Sostituito da 0012 |
| [0012](adr/0012-pannello-admin-proprio.md) | Pannello admin proprio; superuser come da documentazione PocketBase | Accettato |
| [0013](adr/0013-accesso-su-rete-di-casa.md) | Accesso: admin = superuser, utenti con account, server sulla rete di casa | Accettato |
Template ADR: [adr/0000-template.md](adr/0000-template.md)