Securitate & protecție date
Ultima actualizare: 28.04.2026
ClinicOS stochează date medicale sensibile. Securitatea nu e o opțiune premium — e fundație, aplicată pe toate planurile fără diferențiere. Această pagină explică cum, fără jargon de marketing.
1. Multi-tenancy: izolare totală între cabinete
Folosim schema-per-tenant (django-tenants). Concret:
- Fiecare cabinet are propriul „spațiu" (schemă PostgreSQL) — un namespace separat în baza de date.
- Query-urile sunt scope-uite automat la schema cabinetului prin middleware (derivat din subdomain). Imposibil să returnezi date dintr-un alt cabinet.
- Fișierele media (logo cabinet, documente PDF pacienți) sunt izolate per cabinet pe disk:
media/<schema>/.... Acces servit prin view Django care verifică tenantul curent — nu prin nginx static (defense in depth). - Ștergerea unui cabinet (GDPR Art. 17) execută
DROP SCHEMA CASCADE— datele dispar complet, inclusiv media, cu backup final automat în arhivă.
Test în continuu: avem teste end-to-end care verifică că o cerere
pe cabinetA.clinicos.ro/media/<file> de la cabinetB.clinicos.ro
întoarce HTTP 404. Cross-tenant access = imposibil prin design, nu prin obscuritate.
2. Criptare
2.1 Per-tenant DEK (Data Encryption Key)
Fiecare cabinet primește la creare o cheie unică Fernet (256-bit AES)
generată din os.urandom. Această cheie e stocată în DB criptată
cu un master KEK (Key Encryption Key) ținut în .env server-side.
Beneficiu: dacă ar exista vreodată un leak al unei chei de cabinet, datele celorlalte cabinete rămân indecriptabile — fiecare are propria cheie izolată.
2.2 Field-level encryption pe câmpuri sensibile
Câmpuri marcate ca foarte sensibile (ex: notițe confidențiale despre pacient
— antecedente psihiatrice, HIV etc.) sunt criptate cu DEK-ul cabinetului
înainte de a fi scrise în DB. În baza de date apar ca ciphertext
Fernet (gAAAAA...), nu plaintext. Decriptarea se face automat la read,
doar pentru userii cabinetului care le-a scris.
2.3 HTTPS forțat + HSTS preload
- Redirect HTTP→HTTPS la nivel de nginx + Django
SECURE_SSL_REDIRECT. - HSTS 1 an cu
includeSubDomains; preload— browserele forțează HTTPS chiar înainte de prima conexiune. - Certificat wildcard Let's Encrypt cu auto-renew prin DNS-01 (Cloudflare API).
3. Backup off-site encrypted
Backup-ul cloud nu e add-on premium — e activ pe toate cabinetele, indiferent de plan. Detalii tehnice:
- Frecvență: zilnic la 03:30 (după backup-ul local de 02:00).
- Conținut: pg_dump per schemă (+gzip) + tar al fișierelor media per cabinet.
- Tool: restic 0.18.x — encrypt & deduplicate la nivel de chunk.
- Encryption: client-side cu master password 48 chars random, cunoscut DOAR de operatorul ClinicOS. Furnizorul de stocare cloud (provider terț) NU poate citi datele.
- Stocare: off-site, la alt provider de UE (România) — separat fizic de VPS-ul de producție.
- Retenție automată: 7 zile (daily) + 6 luni (1 per lună) + 2 ani (1 per an) ≈ 16 puncte de restore active simultan.
- Dedup: chunk-uri identice se urcă o singură dată — backup-urile incremenetale sunt extrem de rapide.
- Restore test: verificat lunar cu
diff -rbyte-perfect între snapshot recuperat și sursă.
Note pentru DR (Disaster Recovery): chiar dacă VPS-ul de producție arde complet, backup-ul rămâne disponibil pe stocarea off-site. RTO țintă pentru restore complet (DB + media): < 4 ore.
4. Autentificare & sesiuni
- Hashing parole: Django PBKDF2-SHA256 cu 600.000 iterații (default 4.2). Imposibil de inversat practic.
- Sesiuni: cookie HttpOnly + Secure + SameSite=Lax, semnate criptografic.
- Rate limiting: 5 încercări login eșuate / 15 min per IP. Signup public 5/h. Contact form 10/h.
- Email-based password reset cu token signed expirable (24h).
- Onboarding nou cabinet: userul admin e creat inactiv; primește email cu link signed (24h) pentru setare parolă; abia după aceea contul devine activ.
5. Audit & observabilitate
- Audit log (tabela
AuditLog) — orice acțiune sensibilă (vizualizare CNP, export pacient, ștergere, schimbare permisiuni etc.) e înregistrată cu user, IP, user-agent, timestamp. - Retenție 7 ani conform legislației medicale RO. Arhivare automată lunară a log-urilor mai vechi (CSV gz off-line).
- Logging server aplicat strict pe ce-i necesar pentru debugging — fără PII (date personale identificabile).
- Suspendare automată cabinet expirat: trecere în mod read-only (POST blocat). Nu pierdere de date.
6. Defense in depth
- Django admin BLOCAT pe tenant subdomain. 3 nivele: (1) URL config nu îl include, (2) middleware Http404 explicit pe
/admin*, (3) sidebar fără link. Asta previne ca un superuser de cabinet să ocolească audit log-ul + encryption modificând direct tabelele DB. - Honeypot pe formularele publice (signup, contact) — câmp invizibil pentru useri, dar bot-urile îl completează automat.
- Domenii throwaway (mailinator, guerrillamail etc.) blocate la signup.
- CSP (Content Security Policy) permițând doar resurse de pe clinicos.ro + js.stripe.com pentru checkout.
- CSRF protection pe toate POST-urile (Django default).
- SQL injection exclus prin folosirea exclusivă a Django ORM (queries parametrizate). Niciun raw SQL cu user input.
7. GDPR & drepturile tale
- Drept de acces / portabilitate: super-admin poate genera oricând un export complet (zip cu pg_dump + tar media + plan info) — răspuns < 30 zile.
- Drept la ștergere: management command
gdpr_deletecare face backup final, anulează abonamentul Stripe, executăDROP SCHEMA CASCADEși salvează un audit record (DeletionLog) cu cine, ce, când. - Sub-procesatori transparenți: lista completă în Politica de confidențialitate.
- DPA (Data Processing Agreement) pre-semnat disponibil la /dpa/.
8. Incident response
În caz de breach (acces neautorizat, leak de date), activăm procedura GDPR Art. 33-34:
- 72 ore: notificare ANSPDCP cu detalii.
- Notificare clienți afectați direct prin email + dashboard banner.
- Post-mortem public pe clinicos.ro cu cauza, fix-ul, lessons learned.
- Contact urgent: dpo@clinicos.ro (răspuns < 24h în zilele lucrătoare).
9. Open-source & auditabilitate
Implementarea ClinicOS folosește componente open-source bine cunoscute (Django, PostgreSQL, restic, Fernet/cryptography). Pentru clienți Enterprise care vor audit independent, putem facilita acces la documentația arhitecturală sub NDA.
Ai întrebări tehnice de securitate sau vrei un audit? Scrie la dpo@clinicos.ro. Pentru vulnerabilități, te rugăm responsible disclosure — ne dai 30 zile să fixăm înainte de publish, recunoaștem efortul tău cu mențiune publică (cu acordul tău).