Operate
Security and compliance
Trust boundaries, safeguards, secret rotation, PHI handling, the compliance posture and the public-demo privacy gate.
Trust boundaries
- Browser to nginx: TLS terminates at nginx.
- Remote PACS to api-pacs and Orthanc: DIMSE over TCP; DICOM-TLS is supported by Orthanc but not enabled by default.
- Model containers run inference code isolated by Docker with no host filesystem mounts beyond the model cache and a read-only weights volume.
- Internal service traffic (api-pacs, study-service, Celery, Orthanc, Postgres, Redis, Elasticsearch) stays on
pacs-net; see the port matrix under Requirements for the ports the shipped compose files still publish and must be firewalled.
Technical safeguards
| Control | Implementation |
|---|---|
| Authentication | Firebase ID token verification on every request; sessions in Redis; adaptive login protection |
| Authorization | Three roles (OWNER, ADMIN, USER) enforced by Chi middleware |
| Multi-tenant isolation | Every record scoped to tenant_id; cross-tenant access blocked in the application layer |
| Privileged operations | Separate X-FB-SUDO-KEY superuser guard for owner provisioning and Kibana index sync; docs and expvar behind OPENAPI_DOCS_PASSWORD |
| Encryption in transit | TLS at nginx for browser and API traffic; DICOM-TLS customer-enabled when required |
| Encryption at rest | Delegated to host full-disk encryption (LUKS or cloud volume encryption), customer-owned; no Postgres TDE |
| Data minimization | 24-hour rolling DICOM cache, no long-term imaging storage |
| Audit logging | Eight event types indexed to Elasticsearch |
| Service-to-service auth | Three distinct bearer tokens between api-pacs and study-service |
| Secrets handling | Service-account JSON mounted from a host secrets directory, never committed |
| Input safety | Body-size, series-count and metadata limits enforced in nginx and api-pacs; per-user quotas and concurrency limits |
Secret rotation
| Secret | Where it lives | Rotation |
|---|---|---|
| Firebase service-account JSON | Mounted file at FIREBASE_CONFIG_FILE_PATH | Replace the file, restart api-pacs |
FIREBASE_SUPERUSER_KEY | .env | Regenerate the Web API key in Firebase or GCP Console, update .env, restart api-pacs |
| Postgres passwords | .env | Update .env, restart Postgres and its dependents (api-pacs, study-service) |
| Mailgun API key | .env | Update .env, restart api-pacs |
| Study-service tokens | .env on both sides | Rotate all three together; restart api-pacs and study-service |
| TLS certificate and key | nginx volume | Replace the files, docker compose restart nginx (brief downtime; use a maintenance window) |
Compliance posture
- The compliance program is in development with external counsel (HIPAA, GDPR, Quebec Law 25). No SOC 2, HITRUST or ISO 27001 attestation ships today; BAAs and DPAs are negotiated per engagement. The customer remains the data controller or covered entity; PACS-AI is a platform operated inside the customer compliance perimeter.
- The safeguards above support the HIPAA Security Rule technical safeguards (45 CFR 164.312): access control, audit controls, integrity, person or entity authentication, transmission security. Regional defaults relevant to reviews: timezone
America/Toronto, Firebase data residency follows the provisioned project, and imaging is held only in the 24-hour cache. - A privacy impact assessment under the Quebec Act respecting health and social services information found no structural barrier to compliance; see the EFVP page.
- Vulnerability management: critical CVEs (CVSS 9.0 or higher) patched within 14 days of NVD publication, high (7.0 to 8.9) within 30, medium (4.0 to 6.9) within 90, low best-effort with no SLA; base images refreshed at least quarterly; image scanning (Trivy or Docker Scout) in CI is on the roadmap and no
.github/workflowsexist today; a private security mailbox is planned. Report vulnerabilities to your named PACS-AI contact on Slack, not in public GitHub issues. - No third-party penetration test has been conducted yet; when one is, the executive summary is available to customers under NDA on request and full reports stay internal. Every pull request goes through code review on GitHub.
Public demo privacy gate
Studies deployed to the public demo must pass scripts/validate_demo_dicom.py, a read-only validator driven by docs/public-demo/dicom-deidentification-policy.json (DICOM PS3.15 Basic Application Confidentiality Profile as the baseline, stricter in places). A PASS requires an approved policy, an error-free metadata scan with zero violations, and a matching human pixel-review attestation for burned-in text; BurnedInAnnotation = NO alone is not sufficient evidence. Reports contain counts only, never DICOM values, UIDs, filenames or credentials.