Skip to content

Security & LGPD

DELPHOS is built with privacy and security at its foundation. Every layer of the platform — from API authentication to database queries — enforces strict tenant isolation, data minimization, and audit logging. The architecture is designed to comply with LGPD (Lei Geral de Proteção de Dados) and international healthcare data protection standards.

Key Security Features

FeatureDescription
Tenant isolationRow-level security at the database layer
No patient namesSHA-256 hashes only — names never stored in plaintext
Audit loggingEvery data access logged with actor and timestamp
API key scopingKeys bound to tenants with granular permissions
Soft deletesRecords deactivated, never physically deleted
Encrypted transitTLS for all API communication
On-premise optionFull deployment within your infrastructure
Rate limitingTwo-layer protection against abuse
Audio privacyIn-memory only — no audio written to disk

Authentication

DELPHOS uses API key-based authentication. Every request must include a valid key in the x-api-key header.

Key format

Keys follow a structured format that encodes the tenant and environment:

delphos_{tenant-slug}_{environment}_{random}
SegmentExamplePurpose
delphos_Fixed prefixIdentifies DELPHOS keys in logs and secrets managers
{tenant-slug}clinica_auroraTies key to a specific tenant
{environment}prod, stg, devSeparates production from test traffic
{random}128-bit randomCryptographic entropy ensuring uniqueness

Key storage

Plaintext keys are never stored. On creation, keys are hashed with an industry-standard one-way hashing algorithm (cost factor 12). The only time a client sees the full key is at the moment of creation.

Key validation uses constant-time comparison to prevent timing attacks — an attacker cannot infer partial key correctness from response latency.

Key capabilities

Each API key supports:

CapabilityDescription
Environment bindingKey works only in its designated environment (production, staging, development)
Granular permissionscan_read, can_write, can_delete, can_admin — independently toggleable
Expiration dateOptional TTL; expired keys are rejected automatically
RevocationKeys can be revoked with a reason string for audit purposes
Status trackingactive, expired, revoked — only active keys authenticate

Key caching

To avoid hitting the database on every request, validated keys are cached in an in-memory store with a 5-minute TTL. If the cache is unavailable, authentication falls back gracefully to a direct database lookup — the system never rejects requests due to a cache failure.


Authentication Flow

The complete authentication and tenant-resolution flow for every API request:

+------------------+
| Incoming Request |
+--------+---------+
|
+--------v---------+
| Extract x-api-key |
+--------+---------+
|
+--------v---------+
| Rate limit check |
| 300 req/min / IP |
+--------+---------+
|
+------------v-------------+
| Validate key |
| 1. Check cache |
| 2. Fallback to DB lookup |
+------------+-------------+
|
+------------v-------------+
| Resolve tenant context |
| slug, plan, rate_limits |
+------------+-------------+
|
+------------v-------------+
| SET LOCAL app.current_ |
| app_id = tenant UUID |
+------------+-------------+
|
+------------v-------------+
| RLS filters ALL queries |
+------------+-------------+
|
+------------v-------------+
| Process request |
+--------------------------+

Row-Level Security (RLS)

Row-Level Security is the cornerstone of DELPHOS tenant isolation. Every tenant-scoped table has RLS policies enforced at the PostgreSQL level — not in application code.

How it works

  1. Middleware extracts the tenant from the authenticated API key
  2. A SET LOCAL statement sets app.current_app_id to the tenant’s UUID
  3. PostgreSQL RLS policies on every tenant-scoped table filter rows to match only app_id = current_setting('app.current_app_id')
  4. The session variable is transaction-scoped and auto-cleared

Tables with RLS policies

TableData protected
appsTenant configuration
api_keysKey metadata and permissions
documentsUploaded documents and attachments
knowledge_collectionsKnowledge base collections
usage_trackingAPI usage and quota counters
Patient data tablesAll clinical and personal health records

RLS in practice

Every database connection sets the tenant context before executing any query. This is enforced by middleware — individual route handlers never set or clear the context manually.

Request arrives
-> Middleware authenticates key
-> Middleware calls SET LOCAL app.current_app_id = '<tenant-uuid>'
-> Route handler executes queries (all filtered by RLS)
-> Transaction commits
-> Session variable auto-cleared

Rate Limiting

DELPHOS applies rate limiting at two independent layers to protect against abuse and ensure fair resource allocation.

Layer 1 — Authentication rate limit

A fixed-window counter limits all incoming requests to 300 per minute per IP address, enforced before any key validation occurs.

PropertyValue
Window1 minute, fixed
Limit300 requests per IP
CounterAtomic increment in cache
IP resolutionX-Forwarded-For aware (respects reverse proxies)
RejectionHTTP 429 Too Many Requests with Retry-After header

Layer 2 — Tenant quota limits

After authentication, resource-intensive endpoints enforce per-tenant quotas. These are configured per plan and can differ by endpoint.

Endpoints with quota enforcement:

EndpointResource type
/v1/chat/completionsAI inference
/v1/ocrDocument processing
/v1/rag/*Knowledge base operations
/v1/consultation/*Clinical consultation AI

Quotas support multi-window limits — the same tenant can have separate caps for minute, hour, day, and month windows. Enterprise plans can be configured to bypass quota limits entirely.

Rate limit headers

All responses include standard rate limit headers:

HeaderDescription
X-RateLimit-LimitMaximum requests allowed in current window
X-RateLimit-RemainingRequests remaining in current window
X-RateLimit-ResetUTC epoch seconds when the window resets
Retry-AfterSeconds to wait (included only on 429 responses)
HTTP/1.1 200 OK
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 247
X-RateLimit-Reset: 1713100860

CORS Configuration

Cross-Origin Resource Sharing is configurable per deployment via the CORS_ALLOWED_ORIGINS environment variable.

SettingValue
Default originshttp://localhost:* (development only)
ConfigurationComma-separated list of allowed origins
CredentialsAllowed (Access-Control-Allow-Credentials: true)
Error responsesInclude CORS headers (global exception handlers ensure browsers receive CORS headers even on 4xx/5xx)
Terminal window
# Example: allow your production frontend and staging
CORS_ALLOWED_ORIGINS=https://app.clinica-aurora.com.br,https://staging.clinica-aurora.com.br

Audit Logging

Every security-relevant event is recorded in the security_audit_log table. Audit logging is asynchronous — events are dispatched via background tasks so they never block the request that triggered them.

Event types

EventSeverityTrigger
CROSS_TENANT_ATTEMPTCRITICALA request attempted to access a resource belonging to another tenant
ACCESS_DENIEDWARNINGAuthorization check failed (insufficient permissions)
AUTHENTICATION_FAILEDWARNINGInvalid, expired, or revoked API key presented
RATE_LIMIT_EXCEEDEDWARNINGRequest rejected by rate limiter
KNOWLEDGE_QUERYINFOKnowledge base search executed
COLLECTION_CREATEDINFONew knowledge base collection provisioned
DOCUMENT_INGESTEDINFODocument added to a collection

Audit record fields

Every audit entry includes:

FieldTypeDescription
event_typestringOne of the event types listed above
app_iduuidTenant that generated the event
attempted_resourcestringResource path or identifier
ip_addressstringClient IP (proxy-aware)
user_agentstringClient user-agent string
detailsjsonbStructured metadata specific to the event type
severitystringCRITICAL, WARNING, or INFO
timestamptimestamptzUTC timestamp of the event

LGPD Compliance

DELPHOS is designed to comply with the Lei Geral de Proteção de Dados (LGPD, Lei 13.709/2018), Brazil’s comprehensive data protection law. The following measures address specific LGPD requirements for the processing of sensitive health data.

Data minimization (Art. 6, III)

Patient names are stored as cryptographic hashes only — plaintext names are never persisted in the database. This ensures that even in the event of a database breach, patient identities cannot be directly recovered from DELPHOS data alone.

Sensitive health data protection (Art. 11)

Health data is classified as dados pessoais sensíveis under LGPD. DELPHOS applies additional protections:

  • Tenant isolation via RLS — clinical data cannot be accessed across organizational boundaries
  • Patient identifiers in POST bodies only — never in URL paths, to prevent leakage in server access logs, browser history, or proxy logs
  • Soft deletes — records are deactivated rather than physically deleted, preserving audit trail integrity while removing data from active queries
  • Audio processing in memory only — voice data is processed entirely in RAM; no audio files are written to disk at any point; memory is cleared immediately after transcription completes

Audit trail (Art. 37)

LGPD requires data controllers to maintain records of processing activities and demonstrate compliance upon request. DELPHOS satisfies this through:

  • Security audit log — every data access, modification, and security event is recorded with actor, timestamp, and details
  • Right to information — audit logs track exactly who accessed what data and when, enabling responses to data subject requests
  • Non-blocking logging — audit records are written asynchronously so they never impact clinical workflow performance

Tenant isolation as data sovereignty

Each tenant (clinic, hospital, or health organization) has its data completely isolated via Row-Level Security. This architectural guarantee means:

  • One organization cannot access another’s patient data
  • Data controllers maintain sovereignty over their data
  • Multi-tenant deployments meet the same isolation standard as dedicated databases

On-premise deployment

For organizations that require data to never leave their infrastructure, DELPHOS supports full on-premise deployment. In this model:

  • All services run within the organization’s own network
  • No data is transmitted to external servers
  • The organization maintains full physical and logical control over data storage
  • AI inference runs locally on the organization’s hardware

Log privacy

Clinical log aggregation is bound to localhost only — log data is never exposed on external network interfaces, preventing accidental exposure of operational metadata.


Network Security

DELPHOS follows a minimal-exposure network architecture:

LayerPolicy
Public surfaceOnly the API gateway port (8000) is exposed to the network
Internal servicesAll AI engines, databases, and support services listen on localhost only
Secrets managementPostgreSQL superuser password injected via Docker secrets; application credentials migrating from environment variables to secrets
TLS terminationHandled by a reverse proxy (nginx, Caddy, or cloud load balancer) in front of the API gateway
Internet
|
+-----v------+
| TLS Proxy | (port 443 -> 8000)
+-----+------+
|
+-----v------+
| API Gateway | (port 8000, only public service)
+-----+------+
|
+------------+------------+
| | |
localhost localhost localhost
:8001 :8002 :5432
AI Engine AI Engine PostgreSQL

Security Headers

All API responses include security-relevant headers:

HeaderWhen includedPurpose
X-RateLimit-LimitEvery responseCurrent window limit
X-RateLimit-RemainingEvery responseRemaining requests
X-RateLimit-ResetEvery responseWindow reset time
Retry-After429 responsesSeconds until retry is allowed
WWW-Authenticate: ApiKey401 responsesIndicates required auth scheme
Access-Control-Allow-OriginCORS requestsPermitted origin
Access-Control-Allow-CredentialsCORS requestsCredentials policy

Security Checklist for Integrators

If you are integrating with the DELPHOS API, follow these practices:

  1. Store API keys securely — use a secrets manager or encrypted environment variables; never commit keys to source control
  2. Use environment-specific keys — production keys should never be used in development or staging
  3. Set key expiration — rotate keys periodically and set expiration dates as a safety net
  4. Send patient IDs in request bodies — never include patient identifiers in URL paths or query parameters
  5. Monitor rate limit headers — implement exponential backoff when approaching limits
  6. Enable TLS — always connect over HTTPS in production
  7. Restrict CORS origins — configure CORS_ALLOWED_ORIGINS to your specific frontend domains
  8. Monitor audit logs — set up alerts for CROSS_TENANT_ATTEMPT and AUTHENTICATION_FAILED events
  9. Prefer on-premise for sensitive deployments — if regulatory requirements demand it, deploy DELPHOS within your own infrastructure