# Pulizia di Nextcloud dal Wizard - progetto

_Richiesta di Elena (03/08/2026): dal wizard che importa le foto, poter
**cancellare le foto da Nextcloud**. Documento di progetto, da discutere con
Vitti PRIMA di scrivere codice. ASCII puro come da B200 sez. 1.7._

Vedi anche [RICHIESTE_ELENA.md](RICHIESTE_ELENA.md) sez. 1 (il giro di oggi) e
il [diario di coding](VRP_B300_diario_coding.md).

---

## 1. Il problema, in una riga

Nextcloud e' **transito**, leNostre e' **archivio**. Oggi il wizard **copia** e
non sposta, quindi dopo ogni import Nextcloud resta pieno di roba gia'
archiviata, e la quota e' 40 GB a testa. Elena oggi pulisce **a mano dal
browser**, e per sapere cosa puo' cancellare deve rifare l'import in anteprima e
leggersi il registro. Il bottone deve fare quella verifica **da solo**.

## 2. LA REGOLA DI SICUREZZA (la parte piu' importante)

> ⚠️ **RIVISTA il 05/08, vedi sez. 11.** La regola qui sotto - "deve risultare
> presente in leNostre ADESSO" - si e' rivelata troppo stretta: si rompe appena
> Elena fa la sua cernita. La regola buona e' **"deve risultare ENTRATO"**.
> Il resto della sezione resta valido come descrizione del confronto.

> Si puo' proporre di cancellare **solo** cio' che, **ricontrollato in quel
> momento**, risulta gia' presente in leNostre.

In pratica: si rifa' il giro del giorno in **anteprima** e si guarda l'esito
file per file. Vale solo `skipped` **per doppione** (stessa dimensione, che e' il
criterio che `vrw_ingest()` usa gia'). Tutto il resto - `imported`, `indecise`,
`error` - **non si tocca**.

Tre corollari che NON vanno dimenticati:

1. **Mai fidarsi dell'esito di un import precedente.** Fra l'import e il clic
   sul bottone possono passare giorni: il file in leNostre puo' essere stato
   spostato o rinominato dal Gestore. Si ricontrolla **adesso**, sempre.
2. **Le Live Photo scartate NON sono archiviate.** Il `.mov` gemello viene
   scartato apposta dall'import: non e' mai entrato in leNostre. Se lo si
   cancellasse "perche' tanto c'e' la foto", si butterebbe l'unico esemplare.
   -> le clip Live Photo si cancellano **solo insieme alla loro foto gemella**,
   oppure si lasciano stare. Da decidere con Vitti (vedi sez. 8).
3. **Gli HEIC entrano convertiti in jpg.** L'originale `.heic` su Nextcloud non
   ha un gemello identico in leNostre (c'e' il jpg): il confronto per dimensione
   non li vede come doppioni. Vanno trattati a parte (vedi sez. 8).

## 3. ⚠️ NON si cancella dal filesystem

Il wizard oggi legge le cartelle di Nextcloud **direttamente dal disco**
(`/srv/dati/nextcloud/data/<acct>/files/Photos/...`). Per leggere va benissimo.
**Per cancellare no.**

Nextcloud tiene un proprio elenco dei file nel suo database (`oc_filecache`).
Un file tolto dal disco alle sue spalle:
- resta **visibile nel browser** come fantasma finche' non si rifa' una scansione
- **non passa dal cestino**, quindi non si recupera piu'
- puo' sballare i conteggi di quota

E il cestino ci ha gia' salvato la pelle: il 02/08 sono stati recuperati da li'
2 filmati mai arrivati in archivio.

> **La strada giusta e' chiedere a Nextcloud di cancellarlo lui**, con una
> richiesta **WebDAV DELETE** - la stessa porta che usa il telefono. Cosi' il
> file finisce **davvero nel cestino**, l'elenco resta coerente e il ripristino
> funziona.

URL: `https://cloud.casarosini.duckdns.org/remote.php/dav/files/<acct>/<percorso>`

## 4. Le credenziali - le tre strade di Vitti

### (a) Una password-applicazione per `vitti` + una per `lella`
Ogni account si pulisce con la propria. **E' quella che consiglio.**

### (b) Un account admin con i superpoteri, una sola chiave
⚠️ **Questa strada NON funziona come sembra.** In Nextcloud l'amministratore
**non vede i file degli altri utenti via WebDAV**: l'area file e' per utente, e
l'admin con la propria chiave vede soltanto la propria. Ci sono giri traversi
(l'app *Impersonate*, le *Group Folders*, oppure i comandi `occ` dentro il
contenitore Docker), ma sono tutti piu' complicati e piu' invasivi di due
password-applicazione. **Da verificare in 2 minuti** appena si ha una chiave in
mano, ma e' il comportamento noto.

### 📌 Il timore di Vitti («cosi' bisogna cambiare account») e' infondato
Il cambio di account **non lo fa la persona: lo fa il programma**, e non si
vede. Il wizard **sa gia'** quale account sta trattando - c'e' la tendina
`acct`, con la lista chiusa presa dalla targa (`["vitti","lella"]`). Quando
Elena preme il bottone sul giorno dell'account `lella`, il servizio usa la chiave
di `lella`. Se lo preme Vitti sull'account `vitti`, usa quella di `vitti`.
Nessuno esce e rientra da nessuna parte.

Sono **due cose diverse, da non confondere**:
- **chi puo' premere il bottone** -> lo dice il ruolo nella piattaforma
- **con quale chiave si cancella** -> lo dice la cartella che si sta pulendo

### E c'e' un argomento di sicurezza a favore della (a)
Una chiave d'amministratore che gira in un file di configurazione e' **una
stringa che, se sfugge, apre tutto**. Due chiavi separate hanno ciascuna un
raggio d'azione piccolo, si **revocano dal profilo Nextcloud** con un clic e
senza toccare l'altra, e si riconoscono nel registro accessi di Nextcloud
(«chi ha cancellato?» ha una risposta).

### Dove si mettono
**Non** in `vrw.json`: e' leggibile da tutti (664) e non e' il posto dei segreti.
Si segue il pattern che la piattaforma usa gia' per i database:
un file in `/srv/http/vittrosviaggi_shared/secrets/` (fuori dall'albero web),
e nella targa **solo il puntatore**. Copia anche in VittRos.kdbx.

## 5. Cosa vede Elena

Sulla riga di ogni giorno, **dopo** un import, compare un bottone:

    [ Pulisci questo giorno su Nextcloud ]

Premendolo **non cancella subito**: rifa' il controllo e mostra il risultato in
parole sue:

    Giorno 2026/08/02 - account lella
    38 file su 40 sono gia' in leNostre  (312 MB)
      -> vanno nel cestino di Nextcloud
    2 NON sono archiviati e restano dove sono:
      IMG_4471.mov   (clip di una foto animata)
      IMG_4480.heic  (non ancora convertita)

    [ Annulla ]   [ Sposta nel cestino i 38 gia' archiviati ]

Regole di lingua, da [feedback Elena]: **niente gergo**. Non «SKIPPED», non
«doppione by size», non «WebDAV». Si dice **«gia' in leNostre»** e **«cestino»**.

## 6. Chi puo' premerlo

**Solo Vitti ed Elena** (deciso il 03/08). Nella piattaforma sono i ruoli
`admin`/`editor` della targa; l'`guest` non lo vede proprio - non disabilitato,
**assente**.

## 7. Cosa NON fa (limiti dichiarati)

- **Non svuota il cestino.** Mai. Il cestino e' la rete, e si svuota a mano dal
  browser quando si e' sicuri.
- **Non tocca il telefono.** Il caricamento automatico e' a senso unico: quello
  che si cancella su Nextcloud resta nel rullino.
  ⚠️ **ECCEZIONE DA VERIFICARE** prima della pulizia dell'account `vitti`:
  l'opzione Android «elimina l'originale dopo il caricamento». Se e' attiva,
  Nextcloud e' **l'unica copia** fino all'import.
- **Non cancella cartelle**, solo file. La cartella-giorno vuota resta li' (e
  costa nulla).

## 8. ✅ CHIUSO il 05/08 - i due punti aperti sono decaduti da soli

Misurato invece che discusso (intuizione di Vitti: «Elena non produrra' piu'
Live Photo, e non penso che ce ne siano adesso» - aveva ragione).

1. **Le clip Live Photo**: su Nextcloud oggi ce ne sono **zero**. In tutto ci
   sono 188 file: 183 jpg, 3 filmati veri e 2 note; e nessuno dei 3 filmati ha
   una foto gemella, quindi la regola non scatta mai. **Nessuna spunta da
   aggiungere**: se un domani ne comparissero, il ricontrollo le lascia stare da
   solo, perche' non sono mai entrate in archivio e quindi non si ritrovano.
2. **Gli HEIC**: **zero** su Nextcloud, sia fra i file attivi sia nei cestini
   (l'iPhone di Elena carica in jpg). Gli 82 che esistono sono tutti in
   leNostre, cioe' gia' archiviati, e non c'entrano con la pulizia.
   ⚠️ **CORRETTO il 05/08 in serata, vedi sez. 12.** Qui c'era scritto che «il
   comportamento prudente viene gratis», cioe' che l'heic non si ritrova mai
   uguale in archivio e quindi resta dov'e'. Vero per la RICERCA in archivio,
   ma da quando c'e' il registro non basta piu' come descrizione: un heic che
   il Wizard ha davvero importato **e' entrato**, il registro lo sa, e ora si
   pulisce. La prudenza gratis vale solo per gli heic che nessuno ha importato.
3. **Il vincolo dei filmati nel cestino: SCIOLTO.** Vedi sez. 10.

## 8bis. Le Live Photo: cosa sono davvero (misurato il 03/08)

Domanda di Vitti: «sono clip o una sequenza di foto?»

**Sono una foto piena + un vero filmato** di ~3 secondi, con l'audio. NON una
raffica di scatti -> l'idea di «importarle tutte numerandole» non si applica.

**Estrarre il fotogramma preferito si puo'**, ed e' la richiesta che Vitti si
aspetta da Elena. Ma da dirle PRIMA: il filmato di una Live Photo ha **molti
meno pixel della foto** (iPhone: ~12 Mpx la foto, ~1,5 Mpx la clip, cioe' circa
**8 volte meno**). Buono per lo schermo, scarso per la stampa o il ritaglio.
-> ha senso **quando il momento buono non e' nello scatto** (l'occhio aperto, il
sorriso un attimo dopo), non come modo normale di scegliere le foto.

### 🐞 BUCO TROVATO nella regola delle Live Photo (03/08, non ancora corretto)
`vrw_is_live_photo()` riconosce la clip dal **gemello con lo stesso nome**. Ma
in archivio esiste gia' un controesempio vero:

    /srv/http/leNostre/2011/9999 Varie/1224 Natale dal Bruno.MOV   611K  MJPEG 720x1280
    /srv/http/leNostre/2011/9999 Varie/1224 Natale dal Bruno.jpg   238K  1936x2592

Non e' una Live Photo (2011: non esistevano; ed e' **MJPEG**), ma la regola la
scambierebbe per tale -> **reimportando materiale vecchio, quel filmato verrebbe
scartato in silenzio**. Oggi non fa danni (i due file sono in archivio, messi a
mano), ma e' il tipo di difetto che si scopre solo quando manca qualcosa.
**CURA PROPOSTA, non fatta**: guardare anche **durata e codec** - una Live Photo
dura 2-3 secondi ed e' H.264, non MJPEG.

## 9. Passi - tutti fatti il 05/08/2026, tranne il collaudo di Elena

1. ✅ Vitti ha creato le due password-applicazione (nome app `wizard-foto`).
2. ✅ Sono in `/srv/http/vittrosviaggi_shared/secrets/nextcloud_app.php` (640,
   gruppo `http`, come i file dei database); nella targa `vrw.json` c'e' solo il
   puntatore (`nextcloud.creds`). Da copiare in VittRos.kdbx.
3. ✅ **Prova a vuoto superata**: `PROPFIND` legge le cartelle di tutt'e due gli
   account (207); file finto creato, cancellato, **finito nel cestino**,
   **ripristinato**, e ripulito. E la domanda della sez. 4b ha avuto risposta:
   la chiave di `vitti` sull'area di `lella` risponde **404** -> l'admin NON vede
   i file degli altri, le due chiavi separate erano la strada giusta.
4. ✅ Codice fatto (vedi il diario di coding, voce 2026-08-05).
5. ✅ Traccia nel registro azioni: `vrp_insert_action('vrw','pulizia_nextcloud',...)`.
6. ✅ **Collaudo di Elena, la sera del 05/08: PASSATO.** Fatto in autonomia,
   partendo dal giorno `lella` 2026/08/01 e arrivando a ripulire tutti i giorni
   di tutt'e due gli account. Registro passato da 0 a 591 righe. Dettaglio e
   verifiche nel diario di coding, voce **2026-08-05 (4)**, che elenca anche i
   **tre difetti** che il collaudo ha fatto uscire (due nell'import, uno nell'UI)
   e il permesso sbagliato sulle cartelle `9999 Filmati`.

## 10. ✅ Il vincolo dei filmati nel cestino: SCIOLTO il 05/08

Erano il paletto che impediva di pulire l'account `vitti`. Confrontati tutti e
34 col contenuto di leNostre, per **dimensione esatta** e per nome:

- **33 su 34 non erano in archivio.** L'unico che c'era e' `26-03-11 15-37-37
  9907.mov`, cioe' proprio quello recuperato a mano il 02/08 - il che dimostra
  che il metro di misura funziona.
- I doppioni apparenti non erano tali: il telefono carica **due volte**, in
  `InstantUpload/Camera` e in `Photos`. I filmati distinti erano **18 di
  `vitti`** (3,13 GB) e **9 di `lella`**.
- Gli 8 di `lella` non archiviati sono roba minore: cinque sono 1920x1440 hevc
  di ~3 secondi, cioe' **clip di Live Photo** (la firma esatta), gli altri tre
  minuscoli (640x480, 848x478, uno da 3 decimi di secondo).

**I 18 di `vitti` sono stati rimessi su Nextcloud**, ciascuno nella sua
cartella-giorno, leggendo dal cestino e scrivendo via WebDAV (quindi Nextcloud
sa cosa ha ricevuto). Verificati: 18 su 18, dimensione identica al byte.
**Non si e' ripristinata la cartella-mese** dal cestino apposta: avrebbe
riportato su Nextcloud anche centinaia di foto gia' archiviate, cioe' il
contrario della pulizia.

⏳ **RESTA DA FARE**: importarli dal Wizard (11 cartelle-giorno nuove, il 28
giugno da solo ne ha 6). Finche' non e' fatto, **i cestini non si svuotano**:
sono ancora l'unica altra copia.

---

## 11. ✅ IL REGISTRO DEGLI IMPORT (05/08, pomeriggio) - la regola rivista

**Domanda di Vitti che ha aperto il punto:** «la scopetta controlla se le foto
sono state importate, ma se Elena dopo averle importate fa una cernita e ne
cancella alcune, o le sposta nella cartella definitiva, non le trovera' piu' e
non permettera' la cancellazione. E' cosi'?»

**Risposta: meta' si'.** Lo SPOSTAMENTO era gia' coperto (la ricerca guarda in
tutto l'archivio, non dove l'import aveva messo la foto: misurato sul giorno
2026/07/14, 18 foto ritrovate in `ANW/2026/0714 Secchiello Selvaggio...`). Ma la
CANCELLAZIONE no. E Vitti ha aggiunto il colpo di grazia: **«Elena usa spesso il
rename»** - se rinomina un FILE, il confronto per nome-di-destinazione salta.

E soprattutto: **«se esiste il cestino del Nextcloud + il cestino del VRW, mi
sembra che stiamo facendo il caso piu' grosso di quello che e'»**. Giusto: la
regola della sez. 2 era stata scritta immaginando che una cancellazione fosse
definitiva, ma ci sono **due reti** (il cestino di Nextcloud e il cestino
morbido del VRW). Si stava chiedendo alla scopetta di garantire una cosa gia'
garantita due volte.

### La domanda giusta

Non «questa foto e' in leNostre in questo momento?» - che cambia ogni volta che
Elena lavora - ma **«questa foto e' mai stata importata?»**, che e' un fatto che
non cambia piu'. E la risposta ce l'ha l'import, che e' l'unico a saperlo.

### Come e' fatto

Tabella **`vrp_auth.vrw_import`** (creata da Vitti il 05/08; l'utente
`vrp_auth_app` ha solo SELECT/INSERT/UPDATE/DELETE, non CREATE):

    id, session_id, acct, src_rel, src_size, esito, at
    KEY k_scopetta (acct, src_rel, src_size)
    FK session_id -> sessions(id) ON DELETE SET NULL

Disegno voluto da Vitti: **nella history (`sessions`) non cambia niente**, resta
la riga-riassunto («importate 237 foto da Nextcloud, account vitti»); i dettagli
file-per-file stanno qui e **li consulta solo la scopetta**. `session_id` lega le
due cose, per poter indagare in futuro.

Tre scelte da non tradire:

1. **NON si annota la destinazione.** Se il registro dicesse *dove* e' finita la
   foto, invecchierebbe al primo spostamento o rinomina - cioe' il male da cui
   deve salvare. Annota il FATTO che e' entrata.
2. **`src_size` e' la dimensione dell'ORIGINALE su Nextcloud** (`$src`, non
   `$ingestSrc`): un heic convertito in jpg pesa un'altra cosa.
3. **Due strade indipendenti, basta che una risponda si'**: il registro (copre
   il futuro, e regge a spostamenti/rinomine/cernite) e la ricerca in archivio
   (copre tutto cio' che e' stato importato PRIMA che il registro esistesse, di
   cui non sa nulla). Un file resta su Nextcloud solo se **nessuna delle due** sa
   dire di si'.

### La paura della crescita, misurata

Vitti: «ho paura che si riempia all'infinito». Numeri veri del 05/08:

| | righe | crescita |
|---|---|---|
| `sessions` (la history, gia' esistente) | 1.560 in 3 settimane, 640 KB | **~11 MB/anno** |
| `vrw_import` (la nuova) | cresce col materiale che passa | **~350 KB/anno** |

In leNostre entrano ~2.700 file l'anno (2023: 2.589 / 2024: 3.034 / 2025: 2.483
/ 2026: 2.530). Vent'anni starebbero in 7 MB. **La tabella nuova cresce trenta
volte piu' piano della history che c'e' gia'.**

### Collaudo (CLI, transazione annullata: zero righe lasciate)

- file mai importato e non in archivio -> **resta** (giusto);
- file nel registro -> **si puo' pulire**;
- **stesso file dopo rinomina/spostamento/cestino** (provato col caso peggiore,
  indice d'archivio VUOTO) -> **si puo' ancora pulire**: il registro regge;
- file NON nel registro -> **resta fuori** (non si allarga la mano);
- la strada vecchia non e' rotta: 2026/07/14 da' sempre 18 gia' archiviate.

---

## 12. ✅ L'ORDINE DEI CONTROLLI (05/08, sera) - il registro va guardato PRIMA

Difetto trovato rileggendo `vrw_nc_esame_giorno()` a registro gia' scritto: il
controllo sul TIPO del file stava **sopra** la consultazione del registro. Un
heic usciva sempre dalla porta «entra convertita in jpg, quindi l'originale non
si ritrova uguale» e non arrivava mai alla prima strada. Cioe': **per gli heic
il registro era codice morto**, e un heic davvero importato sarebbe rimasto su
Nextcloud per sempre pur essendo archiviato - il contrario di cio' che il
registro serve a garantire.

Oggi non fa danni (heic su Nextcloud: zero, misurato in sez. 8), ma e' il tipo
di difetto che si scopre quando qualcosa non si pulisce e non si capisce perche'.

### La regola

> Il **tipo** del file dice solo se ha senso cercare un gemello identico in
> archivio: riguarda la strada (b), non la (a). Il **registro** e' un fatto, e
> i fatti si guardano per primi.

Ordine nuovo:

1. **clip Live Photo** -> resta fuori, prima di tutto, **anche del registro**.
   In archivio non entra mai; se il registro dicesse il contrario, sarebbe lui a
   sbagliare. Cosi' il falso positivo noto di `vrw_is_live_photo()` (sez. 8bis,
   il `.MOV` MJPEG del 2011 con la jpg gemella) continua a sbagliare **dalla
   parte giusta**: il file si tiene, non si butta.
2. **registro** (strada a) -> si pulisce.
3. **heic / non-media** -> restano fuori (qui il tipo conta).
4. **ricerca in archivio** (strada b) -> invariata.

### Collaudo (CLI, cartella finta, nessun file vero toccato)

| file | nel registro? | esito |
|---|---|---|
| `a.jpg` | si' | **si pulisce** |
| `b.heic` | si' | **si pulisce** ← prima restava fuori |
| `c.heic` | no | resta (entra convertita in jpg) |
| `d.mov` + `d.jpg` gemella | si' | **resta** (clip di foto animata: vince il punto 1) |
| `e.txt` | no | resta (non e' foto ne' filmato) |
| `f.jpg` | no | resta (non importata, non ritrovata) |

`php -l` OK. Backup `vrw.php.bak_20260805_173425_preheic`.
