# DPass 61I5 — Correzione conferma parziale

## Evidenza e perimetro
La risposta effettiva osservata ha success=true, schema_version=1.0, stesso
UUID del lotto e contatori interi 100/99/1. L’unica differenza dalla specifica
è lo stato partial anziché confirmed. Il controllo 61I4 respingeva la risposta
come ACK_MISMATCH e disabilitava il collegamento.

La 61I5 accetta confirmed come prima e, soltanto per una richiesta locale
partial con almeno un rifiuto, accetta anche partial. Tutti gli altri confronti
restano rigorosi: UUID, success, versione, conteggi e relativi tipi JSON.
Non accetta stati pending/failed/completed né contatori convertiti da stringa.
Questo è un adeguamento esplicito al comportamento remoto osservato, non la
cancellazione del controllo. Nessuna modifica al progetto Ditech Management.

Dopo un ACK valido external_ack_status diventa confirmed, ma ack_response
conserva partial come realmente ricevuto. Lo stato locale completed_with_errors
rimane e il record errato non diventa un pagamento valido. Il vecchio metadata
ack_mismatch resta come prova STORICA: per lo stato corrente leggere
external_ack_status e ack_confirmed_at.

## Applicazione in locale
Base del modulo importazioni: 61I4 (comprende la continuazione 61I3).
Non richiede moduli ospiti, API o report non pertinenti.

```bash
(
  set -e
  cd ~/progetti/dpass
  PATCH_DIR="$(mktemp -d /tmp/dpass_patch_61I5.XXXXXX)"
  unzip -q /mnt/c/Users/massi/Downloads/dpass_patch_61I5_fix_ack_parziale.zip -d "$PATCH_DIR"
  bash "$PATCH_DIR/apply_patch.sh" "$PWD"
)
```

Esito: [61I5] PATCH 61I5 APPLICATA E VERIFICATA.
Preflight: bash apply_patch.sh ~/progetti/dpass --check
Ripristino locale: bash apply_patch.sh ~/progetti/dpass --rollback [backup]
Il ripristino interessa solo file, non annulla operazioni remote o importazioni.
L’installer verifica hash/prerequisiti, crea backup, copia atomicamente ed esegue
test isolati. In caso di test falliti tenta il ripristino; non sovrascrive file
modificati dopo la base prevista. Nessuna importazione reale durante i test.

## Riavvio in produzione: due passi indispensabili
1. Sospendere temporaneamente il cron della sola installazione da aggiornare,
   attendere esecuzioni in corso e non avviare importazioni manuali insieme.
2. Dopo collaudo locale, caricare dal locale l’unico file indicato nell’elenco
   produzione, conservando una copia del precedente. Controllare contenuto,
   dimensione e presenza del metodo acceptedAckStatuses.
3. Aprire Fonti delle soste / Parcometri / Configura webservice e token.
   Selezionare **Abilita il collegamento** e salvare. Il file NON riabilita da
   solo un collegamento già disattivato. Non cambiare token, Comune remoto,
   codice client, ID fonte o ID collegamento.
4. Attendere l’eventuale Prossimo tentativo. Il salvataggio senza modifica del
   token non azzera il backoff: non forzare lock o date con SQL.
5. Con cron sospeso fare un solo Importa un lotto. E’ una chiamata REALE: ritenta
   prima lo stesso ACK pendente e poi può prelevare nuovi dati.
   In alternativa riattivare direttamente il cron e attendere; non fare entrambi
   contemporaneamente.
6. Verificare conferma remota confirmed del lotto precedente e riattivare il
   cron dopo il test manuale. Comando e --execute restano invariati.

Il lotto può restare completed_with_errors; il record con date errate può
restare rejected. Non significano che il flusso sia fermo. Con max-batches=1 si
preleva un lotto per esecuzione. Se la sorgente ripropone soltanto gli stessi
scarti, il ciclo termina senza disabilitare il collegamento e riprova al cron
successivo: non marca mai lo scarto accettato per liberare la sorgente.

## Dati da conservare
NON cancellare il lotto, le 99 soste, i record o gli ACK. NON rieseguire script
per cancellare prove. NON forzare confirmed/completed con SQL. I dump ricevuti
con alias b/c sono esportazioni diagnostiche e non vanno reimportati.
Nessuna migration, SQL di modifica, Composer/NPM, .env, nuova cache o cron.
Query di verifica facoltativa inclusa: è soltanto lettura, dopo il tentativo.

## Differenza rispetto al contratto
La specifica API 1.0 mostra status=confirmed nella risposta; la produzione
osservata usa partial per la risposta alla conferma parziale. La compatibilità
è limitata a quel caso e documentata in questo rilascio. Tutte le installazioni
che restituiscono confirmed mantengono il comportamento precedente.
