Manuale per fornitori informatici
🖥️ Per i fornitori informatici
Banco della reception vuoto la sera
Manuale 3 di 5 · manuale per fornitori informatici · stato r396

Rosie — architettura, sicurezza, esercizio

Il riferimento tecnico per i fornitori informatici e i responsabili IT presso il cliente. Istanza svizzera, header di sicurezza, cache dell’app, notifiche web, migrazioni della banca dati, backup, osservabilità ed escalation — tutto tracciabile. I nomi dei fornitori compaiono qui di proposito, perché dovete impostare le abilitazioni del firewall e documentare l’esternalizzazione.

🖥️ IT 🇨🇭 Infomaniak (CH) 🔒 HSTS preload 📡 Web Vitals Stato r396
🏗️

Architettura del sistema

App web in JavaScript puro su un’istanza svizzera

Rosie è un’ app web progressiva in JavaScript puro. L’applicazione gira come processo Node su un’istanza Debian presso Infomaniak, in Svizzera, preceduta da Caddy come proxy inverso con gestione automatica dei certificati. La persistenza avviene tramite libSQL/SQLite sulla stessa istanza (modalità WAL), lo storage a oggetti tramite lo storage a oggetti compatibile S3 di Infomaniak. Il service worker lavora con un CACHE_PREFIX per ogni versione. Davanti al sito pubblico è posto un servizio di protezione — non conserva dati; l’interfaccia si rivolge direttamente all’istanza svizzera.

🖥️
Calcolo
Node su Debian presso Infomaniak (CH), Caddy come proxy inverso. Nessun server né macchina virtuale presso il cliente.
🗄️
libSQL / SQLite
Sulla stessa istanza, modalità WAL, backup cifrati fuori sede. Dati conservati in Svizzera.
📦
Storage a oggetti
Allegati e documenti nello storage a oggetti compatibile S3 di Infomaniak (Svizzera).
🤖
IA opzionale
Attivabile per mandante. Quale fornitore di IA venga impiegato è indicato nell’elenco dei subincaricati del contratto di trattamento — non in questo manuale, perché non diventi falso in caso di cambiamento.
ℹ️
Lo stack in sintesi: JavaScript puro · Node su Debian (Infomaniak CH) · Caddy · libSQL/SQLite · storage a oggetti compatibile S3 · service worker con prefisso di versione · notifiche web. Presso il cliente non c’è nulla da installare.
🌍

Compatibilità dei browser

Quali browser sono supportati
🟢
Chrome ≥ 90
Pienamente supportato, installazione dell’app compresa.
🦊
Firefox ≥ 88
Pienamente supportato.
🔷
Edge ≥ 90
Pienamente supportato, installazione dell’app compresa.
🧭
Safari ≥ 14.1
Installazione tramite «Aggiungi alla schermata Home».
⚠️
Internet Explorer: non supportato. Schermata di avvio iOS obbligatoriamente in PNG: dalla versione r168 il formato WebP NON è più accettato — le immagini di avvio per iOS DEVONO essere in PNG.
🌐

DNS e domini

Dominio principale, alias e sottodominio dell’app
  • Dominio principale: rosie-app.ch (incl. www).
  • Alias / mirror: rosie-planer.com — come reindirizzamento 301. Va considerata una finestra di cache di circa due minuti, che si risolve da sé. Verifica immediata dell’origine tramite ?cb=<random>.
  • Sottodominio dell’app: l’applicazione gira sotto un nome proprio che punta direttamente all’istanza svizzera («solo DNS», senza servizio intermedio).
  • Nessuna voce jolly. *.rosie-app.ch non esiste — un nome inventato non si risolve. È voluto ed esclude l’appropriazione di un sottodominio.
  • Servizio di protezione a monte solo per il sito pubblico; non conserva dati dei clienti.
💡
Finestra di cache del dominio alias: Dopo una messa in produzione il reindirizzamento 301 verso rosie-planer.com può provenire brevemente dalla cache del servizio a monte. Si risolve da sé. Per l’analisi: richiesta all’origine con parametro anti-cache.
🛡️

Header di sicurezza

HSTS preload, CSP, SRI, tracciabilità delle versioni
🔒
HSTS (preload)
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload — impostato dall’applicazione stessa, così l’header vale indipendentemente dal servizio a monte. L’invio su hstspreload.org avviene manualmente.
🧱
CSP rigorosa
Content Security Policy rigorosa, in produzione.
🧾
SRI
Controllo di integrità sugli script esterni.
🔖
X-Worker-Version / X-Request-Id
In ogni risposta. WORKER_VERSION = RELEASE, importato da shared/version.mjs (fonte unica).
ℹ️
Verificabile con un comando: curl -I https://rosie-app.ch mostra tutti gli header impostati, compresi HSTS, CSP, X-Worker-Version e X-Request-Id.
⚠️
Trappola: includeSubDomains vale per ogni sottodominio, compresi i nomi di test e di collaudo. E un header HSTS già consegnato resta valido nel browser fino a due anni — non si può ritirare a breve termine.
📦

Service worker, cache delle risorse

Prefisso di cache, cache a monte, caricamento differito, schermata iOS, risincronizzazione
  • sw.js con CACHE_PREFIX, marcato da shared/version.mjs (scripts/sync-version.mjs).
  • Cache a monte: circa due minuti di ritardo dopo la messa in produzione, che si risolve da sé.
  • immutableheader di cache per le risorse con versione.
  • Librerie caricate su richiesta tramite _loadVendor — XLSX, html2canvas.
  • Schermata di avvio iOS obbligatoriamente in PNG — WebP abbandonato dalla versione r168.
  • Nessuna sincronizzazione in background — di proposito: una riesecuzione senza scheda aperta non avrebbe un token valido e rischierebbe doppie registrazioni in mancanza di chiavi di idempotenza. La coda della chat si svuota solo con l’app aperta (v. docs/OFFLINE.md).
  • Notifiche web su iOS solo nell’app installata — imporre l’aggiunta alla schermata Home.
💡
Messa in produzione: RELEASE in shared/version.mjs poi npm run version:sync — CACHE_PREFIX in sw.js / src/constants.js vengono marcati automaticamente; nulla da aggiornare a mano.
📡

Notifiche web (RFC 8291)

VAPID, idempotenza, ore di silenzio, categorie
  • Chiavi VAPID (pubblica e privata) conservate come segreti sull’istanza, sotto /etc/rosie/env.
  • subscribeToPushNotifications è un UPSERT idempotente.
  • Le ore di silenzio sono rispettate.
  • Attivazione per categoria di allarme: bounty · planPublished · adminAlert · messages · absenceResult.
⚠️
La rotazione delle chiavi VAPID invalida tutte le sottoscrizioni alle notifiche (limite noto) — va pianificata con cura.
🔥

Firewall / rete

Abilitazioni, porte, interrogazione
  • Solo HTTPS in uscita sulla porta 443.
  • Abilitazione per rosie-app.ch e il sottodominio dell’app. Non servono altre destinazioni — l’app non richiama da sé alcun servizio presso il cliente.
  • Nessuna porta in entrata.
  • WebSocket non necessario — l’app interroga il server ogni 60 secondi.
📧

Sistema di posta elettronica

SMTP tramite casella svizzera, SPF/DKIM/DMARC

Invio tramite SMTP verso una casella svizzera presso Hostpoint. Il mittente di tutte le e-mail di sistema è support@rosie-app.ch — un indirizzo a cui si può rispondere, non un vicolo cieco. SPF, DKIM e DMARC sono impostati; consigliamo di provare una volta la consegna contro il filtro antispam del cliente dopo la prima configurazione.

💡
Se le e-mail di invito non arrivano: controllare prima la quarantena e il filtro antispam del cliente, poi consultare SPF/DKIM/DMARC per rosie-app.ch . Inserire l’indirizzo support@rosie-app.ch nella lista dei mittenti attendibili risolve la maggior parte dei casi.
📱

Mobile & MDM

iOS / Android, collegamenti web, installazione
  • iOS 14.5+, Android 8.0+.
  • App web — nessun pacchetto da store.
  • Il MDM può configurare il browser preferito, i collegamenti sulla schermata Home e i siti attendibili .
  • Da notare: Notifiche web su iOS richiede l’app installata; schermata di avvio iOS in PNG (non WebP).
🗃️

Migrazioni e versioni dello schema

Con versione, solo in avanti, verificate dopo ogni esecuzione

Le migrazioni si trovano sotto database/migrations/ , numerate progressivamente, e vengono applicate solo in avanti. Lo stato attuale è nella cartella stessa — questa pagina non indica di proposito alcun numero, che sarebbe sbagliato già alla versione successiva. Dopo ogni esecuzione segue una verifica dello schema. Le migrazioni sono costruite in modo da poter ricostruire per intero una banca dati vuota.

ℹ️
Le migrazioni vengono eseguite con la messa in produzione e non richiedono interventi presso il cliente. Non è previsto alcun percorso a ritroso — la via del ritorno passa dal ripristino (vedi Backup & Ripristino).
💾

Backup & Ripristino

Backup cifrati, punti di ripristino, esportazione
  • Backup automatici della banca dati, cifrati e depositati fuori sede.
  • Finestra di ripristino di 30 giorni con punti di ripristino ogni ora (perdita massima di dati: un’ora).
  • Storage a oggetti viene sottoposto a backup separato.
  • Esportazione completa dei dati per mandante, in qualsiasi momento dall’interfaccia di amministrazione.
  • Nessuna ridondanza geografica. Si gestisce di proposito una sola istanza di produzione: un riavvio o un aggiornamento comporta una breve interruzione. È un compromesso noto e accettato, recuperabile senza cambiare l’architettura.
⚠️
I tempi di ripristino non fanno parte di questo manuale. Fa fede unicamente il contratto di servizio.
↩️

Ripristino della versione precedente

Etichette di versione, procedura d’emergenza

A ogni versione corrisponde un’etichetta checkpoint-rNNN-deployed nel sistema di gestione del codice sorgente. Si può così dimostrare in ogni momento quale versione era in produzione e quando.

ℹ️
Ripristino della versione precedente: La versione precedente resta disponibile sull’istanza e si può riattivare in pochi minuti. Una migrazione della banca dati non torna indietro — chi deve risalire oltre passa dal ripristino.
Procedura d’emergenza
1
Segnalare al fornitore
I ripristini sull’istanza li esegue il fornitore — con numero di versione e orario tratti dal quadro dell’errore.
2
Svuotare la cache del browser
Ricaricamento forzato, se necessario aggiornare il service worker.
3
Verificare gli header
curl -I → X-Worker-Version da controllare.
🏢

Isolamento dei mandanti

Filtro lato server, azzeramento al logout
  • Filtro dei mandanti lato server — tenant_id in ogni interrogazione.
  • Le variabili globali del mandante in memoria vengono svuotate al logout tramite _resetTenantCalendarData() (sei variabili del calendario).
  • I test sulle fughe fra mandanti sono fissati da casi di regressione.
  • Attivazione del salvataggio tramite marcatore del mandante companySettingsDirty.
📊

Osservabilità & Registri

Versione, identificativo della richiesta, Web Vitals, filtro dei dati personali
  • X-Worker-Version (r166 A10), X-Request-Id in ogni risposta.
  • Web Vitals → /api/analytics, invio in keepalive, segnale «Do Not Track» rispettato.
  • Filtro dei dati personali prima di ogni analisi.
  • k-anonimato ≥ 4 per i grafici aggregati.
  • Registri si trovano sull’istanza (systemd/journald) e vengono analizzati dal fornitore; un monitoraggio esterno controlla la raggiungibilità e allerta.
⚠️
Correzione rispetto al vecchio manuale: l’osservabilità NON è disattivata — è attiva, con filtro dei dati personali e rispetto del segnale «Do Not Track».
⚡

Budget di prestazione

LCP / CLS / INP, caricamento differito, risparmio batteria
  • Obiettivi LCP / CLS / INP come budget di prestazione.
  • Correzione dello spostamento visivo: width / height sui tag <img>.
  • Librerie caricate su richiesta tramite _loadVendor — XLSX / html2canvas.
  • Risparmio batteria: l’interrogazione si sospende quando document.hidden (pausa alla perdita di visibilità).
🔌

Principali endpoint API

Rotte con header di versione
👥
Dati di base & Piano
/api/staff · /api/shift-assignments · /api/vacations
🤒
Assenze
/api/absences · /api/absences/:id/{approve,reject,cancel} · /api/absence-approval-config
💬
Comunicazione
/api/messages · /api/suggestions
📄
QMS
/api/qms/documents
📋
Compiti
/api/tasks · /api/tasks/templates · /api/tasks/:id/qms-links (PATCH) · /api/tasks/audit
🔄
Mutazioni / avvio
/api/mutations · /api/onboarding/:step
📊
Analisi / registro
/api/analytics · /api/log
👤
Profilo
/api/profile
🔐
Chiusura mensile
/r163-monatsabschluss · /r163-monatsabschluss/:year_month (POST / DELETE)
📰
Proxy dei feed
/api/feed-proxy
ℹ️
Ogni risposta porta un header di versione (X-Worker-Version) e un identificativo della richiesta (X-Request-Id).
🤖

Sistema di IA & Firewall per la protezione dei dati

Limite di frequenza, filtro dei dati personali, riconoscimento vocale nel browser
  • Fornitore di IA: attivabile per mandante; un servizio fisso per ogni scopo, senza servizio di riserva automatico. Quale fornitore venga impiegato è indicato nell’elenco dei subincaricati del contratto di trattamento — non qui, perché questa pagina non diventi falsa in caso di cambiamento.
  • Limite di frequenza: 30 richieste all’ora per utente.
  • Il filtro dei dati personali rimuove indirizzo e-mail, numero AVS, IBAN, telefono e data prima di ogni chiamata al servizio di IA.
  • Attività pianificate dell’IA 0 2 / 0 4 per l’apprendimento dei modelli dei compiti — richieste senza staff.id.
  • Riconoscimento vocale: gestito dal browser (Web Speech API); a seconda del browser o del sistema operativo, la registrazione viene inviata al suo servizio di riconoscimento vocale — ROSIE non riceve né conserva alcuna registrazione audio. Per il riconoscimento del comando, solo il testo riconosciuto va al servizio di IA, con consenso (art. 6 cpv. 6 nLPD).
💡
Firewall per la protezione dei dati: richieste anonimizzate senza identificativi; numero di telefono, numero AVS, IBAN, indirizzo e-mail e data vengono rimossi prima dell’invio, i nomi no. Per le abilitazioni del firewall presso il cliente: le chiamate al servizio di IA partono dall’istanza, non dalla postazione. Il riconoscimento vocale invece viene chiamato dal browser dalla postazione, presso il servizio del suo fornitore.
🧩

Sistema di moduli

Moduli opzionali per mandante

Moduli opzionali: Gestione della qualità (QMS), Voice-to-Schedule, Preparazione salari & finanze, Smart Matchmaker, Radar di carico, Rete regionale. Attivazione per mandante tramite Amministrazione → Strumenti.

♿

Accessibilità & Lingue

Esc e trappola del focus, ARIA, quattro lingue dell’interfaccia
  • Tasto Esc globale e trappola del focus .
  • Barra di avanzamento ARIA .
  • Quattro lingue dell’interfaccia: DE / FR / IT / EN.
  • 14 lingue nella chat per la comunicazione interna — la traduzione avviene sul dispositivo.
🔑

Gestione dei segreti

Segreti sull’istanza · rotazione · hashing delle password
  • I segreti si trovano in /etc/rosie/env sull’istanza, leggibili solo dall’utente di servizio: chiave di firma delle sessioni, coppia di chiavi VAPID, credenziali per lo storage a oggetti, l’SMTP e il servizio di IA.
  • Rinnovare ogni anno la chiave di firma.
  • La rotazione delle chiavi VAPID invalida le sottoscrizioni alle notifiche (limite noto).
  • Hashing delle password: PBKDF2-SHA-256 con sale, in quattro passaggi concatenati da 100 000 iterazioni ciascuno (400 000 in totale).
🚀

Prima configurazione lato informatico

Che cosa fare presso il cliente — e che cosa no

La creazione di un mandante avviene presso il fornitore, sull’istanza svizzera. Presso il cliente non serve alcuna installazione — nessun server, nessun agente, nessuna porta in entrata. Quel che segue è l’elenco dei punti che spettano davvero al cliente.

Dopo l’avvio
1
Verificare la raggiungibilità
curl -I sull’indirizzo dell’app — header, compreso X-Worker-Version da controllare.
2
Provare la consegna delle e-mail
Inviare un invito a un indirizzo del cliente e controllare la quarantena; support@rosie-app.ch da abilitare.
3
Firmare il contratto di trattamento
Concludere il contratto di trattamento con Digital Passion GmbH — è fornitore e responsabile del trattamento allo stesso tempo.
4
Creare l’account di amministrazione
Primo amministratore del mandante.
🛠️

Risoluzione dei guasti & Assistenza

Procedure, livelli di escalation

Esistono procedure per: errori di accesso · errori della banca dati · errori di messa in produzione · consegna delle e-mail · guasto dell’IA · consegna delle notifiche · errori di migrazione.

ℹ️
Assistenza: support@rosie-app.ch. I tempi di reazione sono regolati dal contratto di servizio, non da questo manuale. Per le segnalazioni di sicurezza vale il canale indicato sotto /.well-known/security.txt.
Livelli di escalation
1️⃣
1° livello
Browser / cache / app.
2️⃣
2° livello
Rete, consegna delle e-mail, MDM — tutto ciò che spetta al cliente.
3️⃣
3° livello
Fornitore: registri del server, banca dati, versione. Segnalare con X-Request-Id e l’orario.
🔒

Verifica della protezione dei dati

TLS / AES / hosting / contratto / autenticazione unica
  • TLS 1.3.
  • AES-256 a riposo. I campi di testo libero particolarmente degni di protezione sono inoltre cifrati singolarmente.
  • Conservazione dei dati in Svizzera (Infomaniak): potenza di calcolo, banca dati, storage a oggetti e backup. Il servizio di protezione posto davanti al sito pubblico e il fornitore dei pagamenti sono nominati nell’elenco dei subincaricati del contratto di trattamento.
  • Contratto di trattamento disponibile.
  • Nessun cookie, nessun tracciamento — il segnale «Do Not Track» è rispettato.
  • Distruzione delle chiavi come revoca operativa; cancellazione entro 30 giorni dalla fine del contratto, con attestato scritto.
  • L’SSO (SAML/OIDC) è non disponibile ed è in valutazione; non esiste una data vincolante. Accesso con e-mail e password, con TOTP opzionale.
❓

Domande frequenti per l’informatica

Le domande informatiche più frequenti, in breve
Dove sono conservati i dati?▶
In Svizzera, presso Infomaniak: banca dati (libSQL/SQLite) e storage a oggetti compatibile S3. Cifrati in transito (TLS 1.3) e a riposo (AES-256). Il quadro contrattuale è regolato dal contratto di trattamento; l’elenco dei subincaricati vi nomina tutti i soggetti coinvolti.
Quali regole di firewall servono?▶
Solo HTTPS in uscita sulla porta 443. Nessuna porta in entrata. Basta un’abilitazione per rosie-app.ch e il sottodominio dell’app — le chiamate al servizio di IA partono dall’istanza, non dalla postazione.
Esiste il Single Sign-On (SSO)?▶
No. L’SSO (SAML/OIDC) non è disponibile ed è in valutazione; non esiste una data vincolante. Accesso con e-mail e password, con TOTP come secondo fattore opzionale.
L’osservabilità è disattivata?▶
Correzione: l’osservabilità è ATTIVA — con filtro dei dati personali e rispetto del segnale «Do Not Track». Vengono rilevati esclusivamente dati aggregati e anonimizzati.
Come vengono cifrate le password?▶
PBKDF2-SHA-256 con sale, in quattro passaggi concatenati da 100 000 iterazioni — 400 000 in totale.
Perché sulla schermata di avvio iOS non è ammesso il WebP?▶
iOS accetta solo il PNG per le schermate di avvio. Dalla versione r168 il WebP è stato abbandonato per queste immagini — la schermata di avvio iOS DEVE essere in PNG.
Come funzionano le notifiche su iOS?▶
Le notifiche web su iOS funzionano solo nell’app installata. Raccomandazione MDM: imporre un collegamento sulla schermata Home.
Perché rosie-planer.com è brevemente obsoleto dopo una messa in produzione?▶
Il reindirizzamento 301 del dominio alias si trova dietro il servizio di protezione e può provenire brevemente dalla cache. Si risolve da sé. Analisi: richiesta all’origine con parametro anti-cache (?cb=<random>).
Come identifico la versione in esecuzione durante un incidente?▶
curl -I sul dominio — l’header X-Worker-Version indica il numero di versione attivo, X-Request-Id la singola richiesta, per la correlazione nei registri del server.

Rosie — manuale per fornitori informatici · versione 9.9 · r396
Fornitore e responsabile del trattamento: Digital Passion GmbH, Haldenstrasse 16, 4600 Olten · CHE-154.512.796
Domande? support@rosie-app.ch · rosie-app.ch
← Torna alla panoramica