1. Architettura attuale
1.1 Stack e entry point
- PHP 8 (strict types, namespaces). Nessun framework: core custom.
- MySQL/MariaDB con connessioni separate reader/writer (PDO).
- Frontend: HTML, Materialize CSS 1.0, JavaScript vanilla; AJAX con risposte JSON.
- Entry:
index.phplegge.env(BASE_URI), avvia sessione, caricabootstrap.php, registra error handler, instanziaRouter(BASE_URI)e fadispatch(). - Bootstrap: costanti
BASE_URI,APP_ENV,APP_READ_ONLY,ATLAS_PATH; autoload PSR-4;Database::getReader()/Database::getWriter().
1.2 Core
| Componente | Funzione |
|---|---|
| Router | Match path con BASE_URI; GET/POST; all’inizio di dispatch() chiama ReadOnlyGuard se APP_READ_ONLY è attivo. CSRF globale su POST (eccezioni in csrfExempt). |
| ReadOnlyGuard | Blocca mutazioni HTTP (POST non in whitelist, PUT/PATCH/DELETE, …) con risposta JSON o HTML dedicata; eccezioni minime per login, OTP, scelta/switch ruolo. |
| AuthGuard | requireAuth(), requireDoctor(), requireRole('admin'|'super_admin'|'reception'). Super_admin accede alle aree previste. |
| ErrorHandler | expectsJson(), jsonError(), eccezioni/errori/shutdown; log su system_errors in production. |
| BaseController | render(), redirect(), jsonResponse(), jsonError(). |
| Csrf | Token in sessione; verifica su POST. |
1bis. Modalità sola lettura (APP_READ_ONLY)
- Attivazione:
APP_READ_ONLY=truenel file.env. - Implementazione centralizzata:
Core\ReadOnlyGuard, invocato daRouter::dispatch()dopo la risoluzione del path. - POST ancora consentiti per il flusso di accesso:
/login,/verify-otp,/resend-otp,/auth/otp/resend,/choose-role,/switch-role. - Risposta blocco: HTTP 503; JSON con messaggio unificato; HTML tramite
Views/system/read-only-blocked.php; banner UI inViews/partials/read-only-banner.php.
1.3 Aree e ruoli
Aree: public, admin, doctor, reception, system (derivate da path e da redirect post-login).
Ruoli: admin, super_admin, reception, doctor. Sessione: auth_user_id, active_role, roles, doctor_id, otp_verified (doctor).
Gli account admin/reception con is_active = 0 non possono fare login (controllo in LoginController).
1.4 Controller (sintesi)
- Auth: Login (admin/reception/doctor + OTP per doctor), Logout, OTP verify/resend, SetPassword, RequestPasswordReset, ChangePassword, ChooseRole.
- Admin: Dashboard, Doctor (CRUD, toggle stato), DoctorLeave, DoctorSlotTemplate, Patient, Specialization, ChangePassword.
- Doctor: Dashboard, Patient, Visit, Report, Profile, ChangePassword.
- Reception: Dashboard, Appointments.
- System: SystemController, Setup, AdminUsers, SystemAccounts, ChangePassword, Audit, Commands, ErrorController, AccessController, SecurityEvents, Storage.
- Public: Home, Booking, Specialization, Doctor, Storage, Guida.
1.5 Modelli e servizi (sintesi)
Modelli dominio: AdminModel, DoctorModel, DoctorAccountModel, PatientModel, VisitModel, BookingModel, SpecializationModel, MedicalReportModel, ReceptionAppointmentModel, DoctorLeavePeriodModel, DoctorSlotTemplateModel, PasswordResetModel, AdminPasswordResetModel.
Modelli System: AdminUserModel, SystemAccessLogModel, SystemErrorModel, SystemDashboardModel, AuditTrailModel.
Servizi: SystemLogger, AuditTrailService, OtpService, SlotRecurringService, servizi Mail.
2. Moduli implementati
2.1 Periodi di assenza
Tabella doctor_leave_periods; model DoctorLeavePeriodModel; controller DoctorLeaveController; integrazione con slot e prenotazioni.
2.2 Slot ricorrenti (template + generazione)
Tabella doctor_slot_templates; DoctorSlotTemplateModel; SlotRecurringService (generazione 90 giorni); controller template e generazione.
2.3 Audit Trail
Tabella audit_trail (old/new, integrity_hash, chain_hash, previous_hash). Servizio e viste System per export e verifica catena. Dettaglio in docs/AUDIT_TRAIL_CHAIN.md.
3. Coerenza e convenzioni
Session: path cookie = BASE_URI; rigenerazione sessione; logout pulisce le chiavi. Logging: system_actions, audit_trail, system_access_logs, security_events. JSON: { success, message, data }. Retention: scripts/cron_retention_logs.php e comandi System.
4. Miglioramenti suggeriti (opzionali)
- AdminModel: uso coerente di reader/writer.
- Change password: logging tramite
SystemLoggerdove applicabile. - OtpService resend: cooldown e 429.
- CSRF exempt: allineamento completo ai POST pubblici senza sessione.
- AuditTrailService: estensione ad altre entità critiche.
- ReadOnlyGuard: estendere la whitelist POST solo se necessario in scenari di migrazione.
5. Riferimenti rapidi
Rotte: routes/*.php.
Layout: Views/layouts/ (public, admin, doctor, reception, system).
Guide: docs/Guida-Atlas-Medical.html, docs/Guida-Progettisti-Atlas-Medical.html, questo file; servite dall’app sotto /guide, /guide-progettisti, /guide-architettura.
Documentazione tecnica: docs/ATLAS_MEDICAL_EVOLUTION_ARCHITECTURE.md, docs/AUDIT_TECNICO_PRODUZIONE.md, docs/STORAGE_FLUSSO_E_PATCH.md.
Sola lettura: variabile APP_READ_ONLY; classe Core/ReadOnlyGuard.php.
Retention: script cron; tabelle system_actions, system_access_logs, audit_trail, security_events, system_errors.