Pannello amministratore
Stai completando un recupero password. Scegli la tua nuova password.
Obbligatoria per gli account amministratori. Consigliamo il gestore password già integrato nel telefono — su iPhone l'app Password, su Android Google Password Manager — si sblocca con impronta/Face ID e spesso scrive da solo il codice, senza dover cambiare app. Va bene comunque qualsiasi app authenticator (Microsoft Authenticator, Google Authenticator, ecc.), se ne usi già una.
Non riesci a scansionare né ad aprire il link? Inserisci manualmente questo codice:
Salvali in un posto sicuro (es. password manager). Ognuno si usa UNA sola volta al posto del codice a 6 cifre, se perdi l'accesso all'app authenticator. Dopo aver chiuso questa finestra non potrai più rivederli.
Inserisci il codice a 6 cifre dalla tua app authenticator, oppure un codice di backup (formato XXXX-XXXX).
Istituti e licenze
Caricamento...
Crea l'account amministratore per una scuola esistente. L'admin riceverà un'email con il link per impostare la propria password e accedere a SostiTU, dove potrà configurare plessi, orari e referenti.
Sostituisce l'admin di una scuola esistente con una nuova persona/email. Crea il nuovo account (email di accesso inviata subito) e disattiva quello vecchio, che perde l'accesso a SostiTU.
Crea l'account DS per una scuola esistente (utile anche solo per testare la Dashboard DS senza creare una scuola da zero). Il DS accede a /ds con l'email e la password provvisoria che scegli qui sotto, ed è obbligato a cambiarla al primo accesso — stessa logica dei docenti dell'App Permessi.
Reimposta subito la password di un referente, admin, DS o docente App Permessi — funziona per tutti, senza inviare nessuna email (quella di Supabase si è rivelata inaffidabile). Comunica tu la nuova password: dovrà cambiarla al prossimo accesso.
Seleziona un istituto o clicca Aggiorna.
Allinea gli account Supabase Auth con la tabella docenti: crea gli account per i nuovi docenti, disattiva quelli usciti, aggiorna le email cambiate. Da eseguire dopo ogni aggiornamento annuale dei docenti. L'operazione è sicura e ripetibile.
➕ Onboarding nuova scuola
Segui i 4 passi per configurare una nuova scuola. I dati vengono memorizzati ad ogni passo — puoi tornare indietro senza perdere nulla.
Crea l'account amministratore che gestirà SostiTU per questa scuola. Riceverà un'email con il link per impostare la propria password.
Caricamento...
Il prezzo dipende dalla fascia di docenti (comunicata dalla scuola). Il Modulo Permessi è un'integrazione opzionale.
🧮 Calcolatore preventivo
Listino completo
| Fascia | Docenti | SostiTU base | + Permessi | Completo |
|---|---|---|---|---|
| Piccola | fino a 60 | 390€ | +120€ | 510€ |
| Media | 61–120 | 590€ | +150€ | 740€ |
| Grande | 121–200 | 790€ | +190€ | 980€ |
| Molto Grande | oltre 200 | 990€ | +220€ | 1.210€ |
Prezzi annui, IVA esclusa. I plessi sono illimitati in tutte le fasce. Il numero di docenti è dichiarato dalla scuola in fase di preventivo.
Documento di nomina a Responsabile del trattamento (DPA) da far firmare a ogni scuola cliente al momento dell'attivazione della licenza. Scarica la versione Word, completa i dati e fai firmare al Dirigente Scolastico.
Nomina a Responsabile del trattamento ai sensi dell'art. 28 del Regolamento UE 2016/679 (GDPR)
L'Istituto Scolastico [NOME ISTITUTO], con sede in [INDIRIZZO], C.F. [CODICE FISCALE], codice meccanografico [CODICE MECCANOGRAFICO], in persona del Dirigente Scolastico pro tempore [NOME DIRIGENTE], di seguito "Titolare del trattamento" o "Scuola";
[DATI FORNITORE — nome/ragione sociale, P.IVA/C.F., sede], fornitore del servizio software "SostiTU" per la gestione delle sostituzioni e dei permessi del personale scolastico, di seguito "Responsabile del trattamento" o "Fornitore";
Art. 1 — Oggetto e durata
Il presente accordo disciplina il trattamento dei dati personali effettuato dal Responsabile per conto del Titolare nell'ambito dell'erogazione del servizio SostiTU. L'accordo ha la stessa durata del contratto di licenza e cessa con la sua risoluzione.
Art. 2 — Tipologie di dati e categorie di interessati
Categorie di interessati: personale docente e ATA della Scuola.
Tipologie di dati trattati: dati anagrafici (nome, cognome), dati di contatto (email, telefono), dati relativi al rapporto di lavoro (plesso, qualifica, tipo di contratto, orario di servizio), dati relativi a presenze, assenze, permessi e sostituzioni.
Il servizio non è destinato al trattamento di categorie particolari di dati (art. 9 GDPR). Eventuali dati relativi alla salute contenuti nelle richieste di permesso (es. certificati) sono trattati esclusivamente su iniziativa e responsabilità del Titolare.
Art. 3 — Finalità del trattamento
I dati sono trattati al solo fine di erogare le funzionalità del servizio: organizzazione delle sostituzioni, gestione delle richieste di permesso, generazione della relativa modulistica e comunicazioni operative al personale. Il Responsabile non utilizza i dati per finalità proprie.
Art. 4 — Obblighi del Responsabile
Il Responsabile si impegna a:
Art. 5 — Sub-responsabili
Il Titolare autorizza il Responsabile ad avvalersi dei seguenti sub-responsabili per l'erogazione del servizio:
Il Responsabile informerà il Titolare di eventuali modifiche relative ai sub-responsabili, dando al Titolare la possibilità di opporsi.
Art. 6 — Ubicazione dei dati e trasferimenti
I dati sono ospitati su server ubicati nell'Unione Europea (Irlanda). Non sono previsti trasferimenti di dati al di fuori dello Spazio Economico Europeo. Qualora tali trasferimenti dovessero rendersi necessari, saranno effettuati nel rispetto del Capo V del GDPR.
Art. 7 — Diritti degli interessati
Il Responsabile assiste il Titolare nel rispondere alle richieste degli interessati relative ai diritti di accesso, rettifica, cancellazione, limitazione, portabilità e opposizione, entro 30 giorni dalla richiesta del Titolare.
Art. 8 — Violazioni dei dati (data breach)
Il Responsabile notifica al Titolare senza ingiustificato ritardo, e comunque entro 48 ore, ogni violazione dei dati personali di cui venga a conoscenza, fornendo le informazioni necessarie affinché il Titolare possa adempiere agli obblighi di notifica al Garante.
Art. 9 — Conservazione e cancellazione
I dati sono conservati per la durata del servizio. Al termine, su richiesta del Titolare, il Responsabile provvede alla cancellazione dei dati entro 30 giorni, salvo obblighi di conservazione previsti dalla legge. È attivo un sistema di backup con conservazione delle versioni precedenti.
Art. 10 — Legge applicabile e foro competente
Il presente accordo è regolato dalla legge italiana. Per ogni controversia è competente il Foro di [FORO COMPETENTE].
Luogo e data: ___________________
Il Titolare del trattamento
(Il Dirigente Scolastico)
Luogo e data: ___________________
Il Responsabile del trattamento
(Il Fornitore SostiTU)
Riferimento tecnico e operativo per la gestione di SostiTU. Da consultare in caso di domande o problemi delle scuole clienti.
index.html, permessi.html, admin.html) deployati su Cloudflare Workers da GitHub (spezialiale/SostiTU). Ogni push su main aggiorna automaticamente il sito._worker.js), che gestisce la sessione con cookie httpOnly invece che in localStorage — miglioramento di sicurezza contro il furto di sessione via XSS.mailto: o compose Gmail), è l'utente a premere invio.sostitu.it su Aruba, nameserver Cloudflare.docenti_permessi (vedi sezione 5.2bis)Contratto completo (autorizzazione, formato richiesta/risposta, casi limite) di crea-referenti e sincronizza-docenti-auth: vedi CONTRATTI-EDGE-FUNCTIONS.md nella root del repository — da tenere aggiornato ogni volta che si modifica una di queste funzioni su Supabase.
Non c'è upload Excel: è un wizard manuale, un passo alla volta. Crea un solo account admin per la scuola — se ci sono più plessi con referenti diversi, vanno aggiunti singolarmente dopo (tab Docenti/Utenti), non in blocco da qui.
admin.istituti, la riga in licenze, chiama l'Edge Function crea-referenti per l'account Auth dell'admin, invia automaticamente l'email di reset password a quell'indirizzo, e infine prova a creare anche l'account Dirigente Scolastico (ruolo ds) usando l'email raccolta al Passo 1 — vedi sezione 4.6. Se questo ultimo passaggio fallisce, scuola e admin sono comunque creati correttamente: l'esito compare separato nel messaggio finale.Procedura dettagliata, sempre verificata sul codice reale: vedi ONBOARDING-NUOVA-SCUOLA.md nella root del repository.
Nel tab 📄 Licenze ogni riga ha un tasto ✏️ Modifica. Puoi cambiare: tipo licenza, numero massimo plessi, data scadenza, modulo permessi incluso (Sì/No). Le modifiche sono immediate.
Quando una licenza scade, l'utente vede un modal di upgrade e non può accedere alle funzioni. Per rinnovarla: ✏️ Modifica → cambia la data scadenza → Salva.
Codice licenza: ICBONFIGLI. istituto_id: 8c08811b-f9d9-48c2-b500-d23ae9ae605b. Licenza gratuita a tempo indeterminato. Non modificare la scadenza.
sostitu.it/ds (pagina dedicata ds.html, non index.html): vede SOLO la propria Dashboard DS (KPI, andamento mensile, classifiche, stampa singolo plesso o aggregato tutta la scuola), nessun'altra funzione del gestionale. Vedi sezione 4.6 per crearlo.Il referente usa il link Password dimenticata? nella schermata di login → riceve email Supabase con link reset. Se l'email non arriva: controlla spam, verifica che l'email sia corretta in Supabase → Authentication.
Per forzare il cambio password al prossimo login di un referente (es. se la password provvisoria è stata compromessa):
UPDATE utenti SET primo_accesso = true WHERE email = 'email@scuola.it';
Da Supabase → Authentication: elimina l'utente da auth.users. Poi esegui:
DELETE FROM utenti WHERE email = 'email@scuola.it';
Tab 👥 Utenti → ✏️ Modifica admin scuola: seleziona l'istituto, inserisci la nuova email admin. Il sistema crea il nuovo account (email di accesso inviata subito) e disattiva quello vecchio, che perde l'accesso — la disattivazione avviene solo dopo che il nuovo admin è pronto, per non restare mai senza nessun admin funzionante se qualcosa fallisce a metà.
Caso "email già registrata": se la nuova email appartiene già a un account Supabase Auth esistente (es. un docente o un referente della stessa persona) — Supabase impone email univoca per l'intero progetto, non per ruolo/tabella — il pannello lo rileva da solo e assegna il ruolo admin a quell'account già esistente invece di provare (e fallire) a crearne uno nuovo. In questo caso non arriva nessuna email di reset: la persona accede subito con la password che già usa per l'altro ruolo.
Tab 👥 Utenti → 📈 Crea account Dirigente Scolastico: email DS + istituto. Comoda anche solo per testare la Dashboard DS senza creare una scuola nuova. Stessa logica "email già registrata" della sezione 4.5: se l'email appartiene già a un account esistente, gli viene assegnato il ruolo ds invece di crearne uno nuovo, nessuna email di reset in quel caso.
Il DS accede da sostitu.it/ds, non da index.html/admin.html.
Dal 18 ago 2026, login con password non basta più per admin e superadmin: al primo accesso (fresco, non al ripristino di una sessione già aperta) viene richiesto anche un codice a 6 cifre da un'app authenticator (TOTP, gestito internamente da Supabase Auth — nessuna colonna nuova su utenti). Consigliata l'app Password già integrata nel telefono (iPhone/Android), che offre l'autofill del codice; va bene comunque qualunque app authenticator.
Al primo enrollment, subito dopo aver confermato il primo codice, vengono generati 10 codici di backup monouso (mostrati una sola volta, con pulsanti Copia/Scarica file) — utilizzabili al posto del codice a 6 cifre se si perde l'accesso all'app authenticator.
Recupero se un admin/superadmin resta bloccato (nessun codice di backup salvato, app authenticator persa): esegui in SQL editor, poi fai rifare l'enrollment da capo:
DELETE FROM auth.mfa_factors WHERE user_id = (SELECT id FROM auth.users WHERE email = 'email@scuola.it'); DELETE FROM mfa_backup_codes WHERE user_id = (SELECT id FROM auth.users WHERE email = 'email@scuola.it');
App separata su sostitu.it/permessi. Ogni docente ha un account individuale su Supabase Auth (email + password proprie, non condivise): lo username nome.cognome inserito in login è solo una scorciatoia — dietro le quinte il sistema risale all'email del docente (RPC get_docente_by_username) e fa login con quella. Non esiste una password unica condivisa da tutto l'istituto: tutti i docenti sono ormai migrati a questo meccanismo (non esiste più il vecchio confronto password in chiaro sulla tabella, rimosso il 13 agosto 2026 come falla di sicurezza).
Il docente inserisce il proprio username nella schermata di login e preme Password dimenticata? — il sistema risale all'email registrata e invia il link di reset lì. Funziona per tutti i docenti, essendo tutti ormai su Supabase Auth.
Se il docente non ha un'email registrata (quindi il link non può essere inviato), va prima sistemata l'anagrafica in docenti_permessi, poi rifatta la sincronizzazione (5.2bis) prima di poter usare "Password dimenticata?".
A settembre, dopo aver aggiornato la tabella docenti_permessi (nuovi docenti inseriti, usciti marcati attivo=false):
select dp.username, dp.email, au.email as auth_email, au.email_confirmed_at,
case
when dp.user_id is null then 'mai sincronizzato su Auth'
when au.id is null then 'user_id orfano (utente Auth cancellato)'
when lower(dp.email) <> lower(au.email) then 'email disallineata'
when au.email_confirmed_at is null then 'email Auth non confermata'
end as problema
from docenti_permessi dp
left join auth.users au on au.id = dp.user_id
where dp.attivo = true
and (dp.user_id is null or au.id is null or lower(dp.email) <> lower(au.email) or au.email_confirmed_at is null);
get_docente_by_username è una stringa esatta, blocca login e reset allo stesso modo di un account disallineato):
select username, nome, cognome, email from docenti_permessi where attivo = true and username ~ '\s'; -- fix in blocco, sicuro: allinea sempre alla parte prima della @ nell'email UPDATE docenti_permessi SET username = replace(username, ' ', '') WHERE username ~ '\s';
Il nome utente è nome.cognome in minuscolo senza spazi. Se il cognome ha apostrofo (es. MALA') l'username è monica.mala'. Verificare su Supabase → docenti_permessi il campo username esatto.
Le bozze vengono create solo dopo l'approvazione da parte del referente. Verificare su Supabase → permessi_assenze_sostitu se esistono righe per quel permesso_id. Se mancano, il permesso non è stato approvato o l'approvazione ha avuto un errore.
Se il docente lavora in due plessi lo stesso giorno/ora (compresenza, 8 set 2026), servono due prese visione — una per ogni referente coinvolto — prima che il permesso risulti davvero approvato: permessi.stato resta inviata e permessi_assenze_sostitu resta vuota finché non arriva anche la seconda. Verificare su permessi_approvazioni quante righe con plesso diverso esistono per quel permesso_id (una riga con plesso IS NULL è un admin/superadmin, e da sola copre tutti i plessi coinvolti). Una volta completo, vengono create due righe in permessi_assenze_sostitu, una per plesso.
Verificare che l'email sia corretta. Se il problema persiste: Supabase → Authentication → trovare l'utente → Send password recovery. Per i docenti App Permessi usare la query SQL di reset (sezione 5.2).
Entrambe le strade passano dallo stesso controllo lato codice (docente.user_id && docente.email): se falliscono tutte e due insieme, quasi sempre l'account Auth del docente è disallineato — email sbagliata/vuota in docenti_permessi, oppure user_id che punta a un utente Auth cancellato. Diagnosi:
select dp.username, dp.email, dp.attivo, dp.primo_accesso,
au.email as auth_email, au.email_confirmed_at
from docenti_permessi dp
left join auth.users au on au.id = dp.user_id
where dp.username = 'nome.cognome';
Se email e auth_email non combaciano (o auth_id è nullo): correggi prima l'email in docenti_permessi, poi rilancia 👥 Utenti → 🔄 Sincronizza account docenti (sezione 5.2bis) per propagarla su Auth. Una volta che email e auth_email combaciano, se il docente resta comunque senza una password funzionante (caso tipico: account esistente da prima, quindi la sync non gli assegna la password provvisoria come fa per i nuovi), puoi impostargliela direttamente allineandola alla procedura standard di tutti i nuovi docenti:
update auth.users
set encrypted_password = extensions.crypt('Bonfigli2027', extensions.gen_salt('bf'))
where email = 'email.corretta@scuola.it';
Con primo_accesso già a true, al login con questa password provvisoria il docente vede la stessa schermata "Imposta la tua password" di qualsiasi account nuovo — nessuna procedura diversa dal resto della scuola. (Se extensions.crypt dà errore "function does not exist", riprova senza il prefisso: crypt(...) / gen_salt(...).)
Supabase è la fonte di verità — cloudLoad sovrascrive sempre il localStorage. Se i dati spariscono: verificare che il plesso attivo in Config corrisponda al plesso dell'utente. Controllare la tab ☁ Backup per ripristinare uno snapshot precedente.
Verificare su Supabase → tabella rec se esiste una riga con plesso = 'default'. Se sì, eliminarla:
DELETE FROM rec WHERE plesso = 'default';
Aprire la console del browser (F12) e cercare il messaggio di errore. Gli errori più comuni sono: variabile non inizializzata (aggiornare permessi.html), jsPDF non caricato (problema di connessione), dati_extra mancanti (il permesso non ha tutti i campi obbligatori compilati).
Il referente deve fare logout e login per ricaricare i dati della licenza. Se il problema persiste: verificare la data scadenza nella tabella licenze — deve essere in formato YYYY-MM-DD.
Verificare nella tabella utenti che il campo plesso del referente sia corretto. Se è vuoto o errato:
UPDATE utenti SET plesso = 'NomePlesso' WHERE email = 'email@scuola.it';
Per SostiTU: verificare primo_accesso nella tabella utenti. Per App Permessi: verificare primo_accesso nella tabella docenti_permessi. In entrambi i casi:
-- SostiTU UPDATE utenti SET primo_accesso = false WHERE email = 'email@scuola.it'; -- App Permessi UPDATE docenti_permessi SET primo_accesso = false WHERE username = 'nome.cognome';
Vedi sezione 4.7 per la query di sblocco (DELETE FROM auth.mfa_factors + mfa_backup_codes). Prima di usarla, chiedi se ha i 10 codici di backup salvati — con quelli può sbloccarsi da solo nella schermata di login, senza intervento SQL.
Il deploy non passa da GitHub Actions (non esiste una pipeline CI in questo repo): è Cloudflare che builda automaticamente ad ogni push su main — verificare lo stato su dash.cloudflare.com → Workers & Pages → progetto sostitu → Deployments. Se fallisce, il log è lì. Il sito si aggiorna entro 1-2 minuti dal push. Fare hard refresh (Cmd+Shift+R) per svuotare la cache del browser — i file statici non hanno nomi con hash, quindi il browser potrebbe tenerne una copia vecchia in cache anche dopo il deploy.
| GitHub repo | github.com/spezialiale/SostiTU (privato) |
| Upload file | github.com/spezialiale/SostiTU/upload/main |
| Supabase dashboard | supabase.com/dashboard/project/jwoqmnwvaufzfqladxwe |
| Supabase URL (produzione) | jwoqmnwvaufzfqladxwe.supabase.co |
| Supabase URL (staging) | krcuztpqxfcahfwexayh.supabase.co |
| Sito staging | staging.sostitu.it — pubblicato con caricamento diretto (drag&drop) sul progetto Cloudflare sostitu-staging, non da GitHub |
| IC Bonfigli istituto_id | 8c08811b-f9d9-48c2-b500-d23ae9ae605b |
| IC Bonfigli codice licenza | ICBONFIGLI |
| Superadmin email | speziali.ale@gmail.com |
| Password provvisoria sync docenti Bonfigli | Bonfigli2027 — usata solo per creare in blocco i nuovi account (sez. 5.2bis); ogni docente la cambia al primo accesso, non è una password condivisa permanente |
| Brand colors | Blu #185FA5 · Blu scuro #123E6B · Verde #3B6D11 · Verde chiaro #8CC63F |
| Cloudflare nameserver | Aruba → Cloudflare |