Vai al contenuto

Manuale Operativo - Calendar Engine, Mobile e WebTop

Scopo

Questo manuale definisce come usare e rilasciare il nuovo motore calendario esterno in modo progressivo.

L'obiettivo operativo e avere un calendario unico consultabile da:

  • SafeOps;
  • WebTop su NethServer 8;
  • smartphone e tablet Android;
  • iPhone e iPad;
  • Outlook, Google Calendar e Apple Calendar tramite feed standard.

Regola Base

Il calendario mostra la pianificazione. La sorgente operativa resta il gestionale che ha creato il lavoro.

Esempi:

  • un ticket resta governato dal modulo Ticket;
  • un RAS resta governato dal workflow RAS;
  • un evento personale resta governato dal calendario utente;
  • il motore calendario normalizza, pubblica e sincronizza.

Fasi Operative

Fase 0 - Preparazione

Prima di attivare il motore:

  1. scegliere un tenant pilota;
  2. scegliere 2 o 3 utenti pilota;
  3. verificare che ogni utente abbia email e ruolo corretti;
  4. verificare timezone tenant, preferibilmente Europe/Rome;
  5. confermare l'host del motore calendario;
  6. preparare token interni tra SafeOps e motore.

Checklist:

  • [ ] tenant pilota definito;
  • [ ] utenti pilota definiti;
  • [ ] host motore definito;
  • [ ] backup DB SafeOps recente;
  • [ ] accesso WebTop disponibile;
  • [ ] DNS e certificato HTTPS pronti.

Configurazione SafeOps per tenant pilota:

CALENDAR_ENGINE_ENABLED=true
CALENDAR_ENGINE_BASE_URL=http://127.0.0.1:18092
CALENDAR_ENGINE_PUBLIC_BASE_URL=https://safeops.nxt-sense.eu/calendar-engine
CALENDAR_ENGINE_WEBTOP_BASE_URL=http://10.50.0.200:18080/calendar-engine
CALENDAR_ENGINE_SECRET=<segreto-condiviso-minimo-32-caratteri>
CALENDAR_ENGINE_TIMEOUT_SECONDS=8
CALENDAR_ENGINE_SCHEDULED_SYNC_ENABLED=true
CALENDAR_ENGINE_SCHEDULED_SYNC_MINUTE=17
CALENDAR_ENGINE_SCHEDULED_SYNC_HOUR=*
CALENDAR_ENGINE_SCHEDULED_SYNC_SOURCES=all
CALENDAR_ENGINE_SCHEDULED_SYNC_LIMIT=500
CALENDAR_ENGINE_SCHEDULED_SYNC_BATCH_SIZE=100

Configurazione motore:

CALENDAR_ENGINE_SECRET=<stesso-segreto>
CALENDAR_ENGINE_DB_PATH=/var/lib/safeops-calendar/calendar_engine.sqlite3
CALENDAR_ENGINE_DEFAULT_TZ=Europe/Rome
CALENDAR_ENGINE_PORT=18092
CALENDAR_ENGINE_FEED_PAST_DAYS=365
CALENDAR_ENGINE_FEED_FUTURE_DAYS=180
CALENDAR_ENGINE_FEED_MAX_EVENTS=5000

Controllo servizio:

curl http://127.0.0.1:18092/healthz
curl https://safeops.nxt-sense.eu/calendar-engine/healthz

Pagina admin SafeOps:

Configurazioni -> Calendar Engine

La pagina consente a un platform admin di modificare:

  • abilitazione motore;
  • URL interno API;
  • URL pubblico feed WebCal/ICS;
  • timeout chiamate;
  • giorni storico/futuro esposti nei feed;
  • limite massimo eventi per feed;
  • creazione feed tenant/utente;
  • revoca feed esistenti;
  • diagnostica runtime del motore;
  • stato sync automatico, tenant sincronizzati, fonti e limiti.

Il segreto HMAC non e modificabile dalla pagina admin e deve restare gestito da .env/deploy. I parametri feed richiedono il riavvio di safeops-calendar-engine.service. Il token feed completo viene mostrato solo al momento della creazione: copiarlo subito in WebTop o nel calendario mobile.

Unità systemd preparata:

deploy/systemd/safeops-calendar-engine.service

Installazione operativa, da eseguire solo al momento del deploy:

install -d /home/safeops/data/calendar_engine
cp deploy/systemd/safeops-calendar-engine.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable --now safeops-calendar-engine.service
systemctl status safeops-calendar-engine.service

Nota esposizione rete:

  • l'unita fornita ascolta su 127.0.0.1:18092;
  • per WebTop esterno usare reverse proxy HTTPS verso 127.0.0.1:18092;
  • aprire direttamente 0.0.0.0:18092 solo in rete interna controllata e con firewall esplicito.

Path pubblico consigliato:

/calendar-engine/

Esempio health via reverse proxy:

curl https://safeops.nxt-sense.eu/calendar-engine/healthz

Fase 1 - Feed ICS Read-Only

Questa e la prima fase da usare in produzione.

Il motore espone un feed ICS per utente o per tenant. WebTop sottoscrive il feed come calendario Internet.

Stato implementativo attuale:

  • gli appuntamenti RAS creati o aggiornati da SafeOps vengono pubblicati verso Calendar Engine quando il flag e attivo;
  • ticket appointment ed eventi personali hanno adapter pronti e sono inclusi nel sync schedulato;
  • il backfill manuale puo pubblicare ticket, eventi personali e RAS esistenti tramite CLI;
  • lo sync automatico Celery pubblica periodicamente ticket, eventi personali e RAS per i tenant con modulo calendario abilitato;
  • ogni utente attivo abilitato al modulo calendario puo vedere in SafeOps il link WebTop personale;
  • il feed ICS del motore resta read-only.

Sync automatico in produzione:

  • task Celery: app.tasks.calendar_engine_scheduled_sync;
  • schedule predefinita: ogni ora al minuto 17;
  • tenant: derivati da user_role_profile_assignment attivi e filtrati da modulo calendar;
  • fonti: all, cioe personali, RAS e ticket;
  • limite predefinito: 500 record per sorgente/tenant;
  • batch predefinito: 100 eventi per chiamata al motore.

Primo sync reale o riallineamento manuale:

python -c "from dotenv import load_dotenv; load_dotenv('.env'); from app import app; from app.services.calendar_engine_sync import run_calendar_engine_scheduled_sync; ctx=app.app_context(); ctx.push(); print(run_calendar_engine_scheduled_sync(sources='all', limit=500, batch_size=100, dry_run=False)); ctx.pop()"

Backfill iniziale in dry-run:

flask --app app calendar_engine_sync --tenant-key tenant_demo --source all --limit 100

Backfill effettivo:

flask --app app calendar_engine_sync --tenant-key tenant_demo --source all --limit 100 --apply

Sorgenti disponibili:

  • ticket
  • personal
  • ras
  • all

Per il primo collaudo usare sempre --source ras e --limit 20, verificare il JSON prodotto, poi ripetere con --apply.

Flusso:

SafeOps -> Calendar Engine -> feed ICS -> WebTop -> smartphone/tablet

Procedura:

  1. aprire Calendario Globale in SafeOps con un utente abilitato al modulo calendario;
  2. copiare il link WebTop personale mostrato nella pagina;
  3. aprire WebTop;
  4. creare un calendario Internet di tipo WebCal/ICS;
  5. incollare l'URL del feed;
  6. impostare sincronizzazione automatica;
  7. verificare gli eventi su WebTop;
  8. verificare la comparsa su telefono/tablet.

Per admin o casi speciali si puo ancora generare un token feed dalla pagina /admin/calendar-engine/ o via CLI.

Creazione token feed tramite API interna firmata:

POST /api/v1/feed-tokens

Payload minimo:

{
  "tenant_key": "tenant_demo",
  "scope": "user",
  "user_id": 7,
  "label": "SafeOps - Mario Rossi",
  "sources": ["ticket_appointment", "ras_appointment", "user_calendar_event"]
}

Creazione token tramite CLI SafeOps:

flask --app app calendar_engine_feed_create \
  --tenant-key tenant_demo \
  --scope user \
  --user-id 7 \
  --label "SafeOps - Mario Rossi" \
  --source ras_appointment \
  --source ticket_appointment \
  --source user_calendar_event

La risposta contiene:

  • feed_url: URL interno generato dal motore;
  • public_feed_url: URL pubblico pronto per WebTop/mobile, se CALENDAR_ENGINE_PUBLIC_BASE_URL e configurato.

Usare public_feed_url in WebTop come calendario Internet WebCal/ICS.

Revoca token:

flask --app app calendar_engine_feed_revoke --token <token-originale>

Controlli:

  • l'utente vede solo il proprio perimetro;
  • gli eventi privati non appaiono a utenti non proprietari;
  • gli eventi RAS non sono duplicati;
  • gli orari sono corretti su mobile;
  • evento cancellato o annullato non resta attivo.

Fase 2 - Calendario Globale SafeOps via Motore

Solo dopo Fase 1 stabile.

Procedura:

  1. abilitare flag per tenant pilota;
  2. aprire Calendario Globale in SafeOps;
  3. confrontare eventi con calendario legacy;
  4. verificare filtri per sorgente;
  5. verificare filtri per utente;
  6. mantenere fallback al calendario legacy.

Rollback:

  1. disabilitare flag motore;
  2. riaprire Calendario Globale;
  3. verificare che SafeOps legga di nuovo dalle tabelle locali.

Fase 3 - Scrittura Controllata

Da attivare solo dopo collaudo.

Operazioni abilitate:

  • nuovo appuntamento personale;
  • spostamento appuntamento personale;
  • aggiornamento appuntamento personale;
  • eventuale ripianificazione RAS tramite adapter SafeOps.

Regole:

  • ogni modifica deve avere audit;
  • ogni modifica deve verificare membership tenant;
  • le modifiche da WebTop restano disabilitate finche non viene attivato CalDAV bidirezionale.

Fase 4 - CalDAV

CalDAV serve per sincronizzazione piu efficiente rispetto al feed ICS.

Da usare quando:

  • i feed ICS diventano troppo pesanti;
  • serve sync differenziale;
  • serve preparare modifiche bidirezionali controllate.

Procedura:

  1. creare endpoint CalDAV del motore;
  2. configurare WebTop come calendario remoto CalDAV;
  3. verificare sync incrementale;
  4. confrontare eventi con feed ICS;
  5. dismettere feed ICS solo quando CalDAV e stabile.

Fase 5 - Bidirezionale WebTop

Non attivare in automatico.

Prima servono:

  • matrice permessi;
  • regole di conflitto;
  • mapping completo source -> gestionale;
  • audit visibile;
  • test su tenant pilota.

Regole minime:

  • un evento RAS modificato da WebTop deve aggiornare SafeOps solo se l'utente puo gestire quel RAS;
  • un ticket appointment modificato da WebTop deve aggiornare il ticket relativo;
  • eventi completati o firmati non devono essere spostati senza ruolo admin;
  • ogni conflitto deve essere bloccato o marcato come needs_review.

Integrazione WebTop NethServer 8

WebTop su NethServer 8 supporta:

  • ActiveSync;
  • CalDAV;
  • CardDAV;
  • calendari remoti WebCal/ICS.

Per Release 1 usare WebCal/ICS.

Configurazione WebTop

  1. Accedere a WebTop con l'utente interessato.
  2. Aprire Calendario.
  3. Clic destro su calendari personali.
  4. Selezionare aggiunta calendario Internet.
  5. Scegliere WebCal/ICS.
  6. Inserire URL feed generato dal motore.
  7. Salvare.
  8. Impostare sincronizzazione automatica ogni 15, 30 o 60 minuti.

Configurazione Mobile

Opzione consigliata:

  1. sincronizzare il dispositivo con WebTop via ActiveSync;
  2. abilitare il calendario remoto nel profilo WebTop;
  3. verificare colore, nome calendario e orari.

Opzione alternativa:

  1. iscrivere direttamente il telefono al feed ICS;
  2. usare questa opzione solo per utenti pilota o calendari read-only.

Naming Feed

Usare nomi chiari.

Esempi:

  • SafeOps - Mario Rossi
  • SafeOps - Tecnici tenant_safecondo
  • SafeOps - RAS tenant_besant
  • SafeOps - Multi Tenant Direzione

Sicurezza Operativa

Regole obbligatorie:

  • non inviare URL feed in chat pubbliche;
  • revocare il token se un dispositivo viene perso;
  • non creare feed tenant per utenti non admin;
  • non usare un feed multi-tenant senza motivazione operativa;
  • non usare token permanenti per test.

Rotazione:

  • token utente: rinnovo consigliato ogni 180 giorni;
  • token tenant/admin: rinnovo consigliato ogni 90 giorni;
  • token test: scadenza massima 7 giorni.

Troubleshooting

Health motore

Controllare prima questi endpoint:

curl http://127.0.0.1:18092/healthz
curl http://127.0.0.1:18080/calendar-engine/healthz
curl https://safeops.nxt-sense.eu/calendar-engine/healthz

Risposta attesa:

{"ok": true, "service": "calendar-engine"}

Se HTTPS funziona ma locale no, verificare porta e systemd. Se locale funziona ma HTTPS no, verificare reverse proxy NethSecurity sul path /calendar-engine.

Sync automatico fermo

Controllare:

systemctl is-active safeops-celery.service
systemctl is-active safeops-celery-beat.service

Poi aprire:

/admin/calendar-engine/

La sezione Sync automatico deve mostrare:

  • stato Attivo;
  • tenant sincronizzati non vuoti;
  • fonti all;
  • limiti coerenti con .env.

WebTop non mostra eventi

Controllare:

  1. URL feed corretto;
  2. token non scaduto o revocato;
  3. HTTPS valido;
  4. range eventi (CALENDAR_ENGINE_FEED_PAST_DAYS e CALENDAR_ENGINE_FEED_FUTURE_DAYS);
  5. log accesso feed;
  6. timezone evento;
  7. sync automatico attivo;
  8. presenza eventi preparabili nella dry-run.

Eventi duplicati

Cause comuni:

  • RAS esposto sia come ras_appointment sia come ticket_appointment;
  • stesso feed aggiunto due volte in WebTop;
  • cambio source_id durante import.

Azione:

  1. verificare source_system/source_type/source_id;
  2. controllare deduplica RAS;
  3. rimuovere calendari duplicati da WebTop.

Orario errato

Controllare:

  1. timezone tenant;
  2. timezone WebTop;
  3. timezone dispositivo;
  4. conversione starts_at_utc;
  5. evento all-day trattato come evento orario.

Utente vede eventi non suoi

Bloccare subito:

  1. revocare il token feed;
  2. verificare membership tenant;
  3. controllare visibility;
  4. controllare calendar_event_share;
  5. aprire audit sicurezza.

Collaudo Minimo

Per ogni tenant pilota:

  1. creare un appuntamento personale privato;
  2. creare un appuntamento personale team;
  3. creare un appuntamento condiviso con un solo utente;
  4. verificare un ticket appointment;
  5. verificare un RAS appointment;
  6. verificare una data corso formazione;
  7. esportare feed ICS utente;
  8. importare feed in WebTop;
  9. verificare su iPhone/iPad;
  10. verificare su Android;
  11. revocare token;
  12. confermare che il feed non risponde piu.

Rollback

Fase 1:

  • revocare token feed;
  • rimuovere calendario Internet da WebTop;
  • lasciare SafeOps invariato.

Fase 2:

  • disabilitare flag motore calendario;
  • usare Calendario Globale legacy;
  • lasciare motore in sola lettura per diagnostica.

Fase 3 o successive:

  • bloccare scritture dal motore;
  • mantenere read-only;
  • riconciliare eventi con audit prima di riattivare.

Responsabilita

Operatore:

  • verifica appuntamenti e segnala anomalie.

Admin tenant:

  • gestisce feed tenant e utenti pilota;
  • revoca token;
  • pulisce dal motore i token gia revocati;
  • controlla visibilita.

Tecnico:

  • usa calendario su mobile;
  • non modifica eventi da WebTop finche il bidirezionale non e abilitato.

Sviluppo:

  • mantiene adapter;
  • monitora import;
  • gestisce conflitti e audit.

Stato Attuale

Stato al 2026-08-03:

  • Calendar Engine attivo su 127.0.0.1:18092;
  • bridge SafeOps attivo su /calendar-engine;
  • URL pubblico HTTPS attivo su https://safeops.nxt-sense.eu/calendar-engine;
  • URL LAN WebTop validato su http://10.50.0.200:18080/calendar-engine;
  • feed personali WebTop provisionati per gli utenti attivi dei tenant calendario;
  • sync schedulato Celery attivo ogni ora al minuto 17;
  • sync reale ricorrente completato con 73 eventi pubblicati e 0 errori;
  • pagina admin con ultima sync registrata, analisi dry-run e pulizia sicura dei feed revocati;
  • feed ICS con metadati WebCal completi, ETag, Last-Modified e cache privata breve;
  • WebTop resta in modalita read-only tramite ICS/WebCal.

Operazioni Admin Aggiunte

La pagina /admin/calendar-engine/ mostra:

  • ultima sync registrata con data, tenant, fonti, scansionati, preparati, pubblicati, scartati, batch ed errori;
  • analisi dry-run manuale senza pubblicare eventi;
  • feed attivi/revocati con filtri per stato, ambito e ricerca utente/anagrafica;
  • azione Pulisci revocati, che elimina definitivamente solo i token gia revocati nel motore esterno.

La pulizia non revoca feed attivi e non tocca link WebTop ancora funzionanti.