Skip to main content
KaireonAI includes built-in compliance infrastructure for multi-tenant data isolation, immutable audit trails, data subject access requests (DSAR), PII masking, and configurable data retention. These features support GDPR, CCPA, and SOC 2 readiness out of the box.

Tenant Isolation

Every API request is scoped to a single tenant. Cross-tenant data access is architecturally prevented at the query layer. How it works:
  • Tenant resolution — Each request resolves a tenantId from either the JWT session (user.tenantId) or the X-Tenant-Id header (for API key auth). API key authentication binds the tenant to the key itself, ignoring any X-Tenant-Id header to prevent spoofing.
  • Database validation — The resolved tenant ID is validated against the Tenant table in the database. If the tenant does not exist, the request is rejected with 403 Forbidden. The system fails closed: if the database is unreachable during validation, the request is denied.
  • Query enforcement — The enforceTenantFilter() helper injects tenantId into every Prisma where clause. The withTenantScope() wrapper provides scoped findMany, findUnique, create, update, and delete methods that automatically include the tenant filter. Calling these helpers without a tenantId throws an error.
  • Single-tenant mode — For self-hosted deployments, set SINGLE_TENANT_MODE=true to bypass tenant resolution and use tenantId: "default" for all requests.
Every database query in every API route passes through tenant filtering. There is no “admin bypass” that returns data across tenants.

Audit Logging

All entity mutations (create, update, delete) are recorded in an immutable audit log with a cryptographic integrity chain.

What Gets Logged

Every write operation on platform entities produces an audit record with the following fields:
FieldDescription
actionThe operation: create, update, delete, or domain-specific actions like retention_config.upsert
entityTypeThe type of entity (e.g., Offer, DecisionFlow, RetentionConfig, dsar_request)
entityIdThe unique ID of the affected entity
entityNameA human-readable name for the entity
changesA JSON object capturing the before/after or the input data
userIdThe authenticated user who performed the action
userNameDisplay name of the user (defaults to "system")
tenantIdThe tenant scope
requestIdCorrelation ID for tracing across services
timestampWhen the event occurred
integrityHashSHA-256 hash of the record contents plus the previous hash (see Verification below)
prevHashThe integrity hash of the preceding audit record in the chain

Immutability

Audit logs cannot be modified or deleted through the API. The audit log endpoint explicitly rejects DELETE, PUT, and PATCH requests with a 405 Method Not Allowed response:
“Audit logs are immutable and cannot be deleted.”

Resilience

The audit system uses a circuit breaker pattern. If the database becomes temporarily unavailable, audit events are buffered in memory (up to 500 events) and flushed when connectivity is restored. A per-tenant mutex prevents hash chain forks from concurrent writes.

Querying Audit Logs

GET /api/v1/audit-logs
Headers: X-Tenant-Id or session cookie. Requires admin role. Query parameters:
ParameterDefaultDescription
entityTypeFilter by entity type
page1Page number
limit50Results per page (max 100)
Response:
{
  "logs": [ ... ],
  "total": 1234,
  "page": 1,
  "limit": 50
}

Audit Verification

Each audit log entry includes a SHA-256 integrity hash computed over its contents and the hash of the previous entry, forming a cryptographic chain. Tampering with any record breaks the chain from that point forward.

How the Hash Chain Works

  1. Each audit record’s hash is computed as: SHA-256(action + entityType + entityId + entityName + changes + userId + userName + tenantId + requestId + prevHash)
  2. The first record in the chain uses "genesis" as the previous hash.
  3. Each subsequent record references the integrityHash of the record before it.

Verification Endpoint

GET /api/v1/audit-logs/verify
Headers: X-Tenant-Id or session cookie. Requires admin role. Query parameters:
ParameterDefaultDescription
limitOnly verify the last N entries (quick check mode). Omit to verify the full chain.
Response:
{
  "intact": true,
  "verified": 847,
  "total": 847,
  "scanned": 847
}
If tampering is detected:
{
  "intact": false,
  "verified": 412,
  "total": 847,
  "scanned": 847,
  "brokenAtId": "clxyz...",
  "brokenReason": "hash_mismatch"
}
Broken reasons:
  • hash_mismatch — The recomputed hash does not match the stored integrityHash. The record’s contents were modified after creation.
  • chain_link_mismatch — The record’s prevHash does not match the integrityHash of the preceding record. A record was inserted or deleted in the middle of the chain.

Audit Export

Bulk export of audit logs for regulatory reporting and SOC 2 evidence collection.
GET /api/v1/audit-export
Headers: X-Tenant-Id or session cookie. Requires admin role. Rate limited to 10 requests per minute. Query parameters:
ParameterDefaultDescription
formatjsonExport format: json, csv, or soc2
startDateISO date string for range start
endDateISO date string for range end
entityTypeFilter by entity type
actionFilter by action (create, update, delete)
limit10000Max records (capped at 10,000)
offset0Pagination offset
The csv format returns the export as a downloadable file with a Content-Disposition header. You can also verify chain integrity through the export endpoint:
POST /api/v1/audit-export
Content-Type: application/json

{
  "action": "verify_integrity",
  "startDate": "2026-01-01T00:00:00Z",
  "endDate": "2026-03-01T00:00:00Z"
}

DSAR (Data Subject Access Requests)

The DSAR endpoint supports GDPR right-of-access and right-to-erasure requests. DSAR processing is asynchronous — the API accepts the request immediately and processes it in the background via a job queue.

Submitting a DSAR

POST /api/v1/dsar
Content-Type: application/json

{
  "requestType": "export",
  "subjectId": "cust-12345",
  "subjectType": "customer_id"
}
Headers: X-Tenant-Id or session cookie. Requires admin role. Rate limited to 10 requests per minute. Parameters:
FieldRequiredDescription
requestTypeYes"export" (data access) or "delete" (erasure)
subjectIdYesThe customer ID or email to look up
subjectTypeNo"customer_id" (default) or "email"
Response (202 Accepted):
{
  "requestId": "dsar-abc123",
  "status": "queued"
}
The request is enqueued for asynchronous processing. The DSAR creation itself is audit-logged.

Checking DSAR Status

GET /api/v1/dsar?status=completed&limit=50
Query parameters:
ParameterDefaultDescription
statusFilter by status: queued, processing, completed, failed
limit50Max results (capped at 200)

PII Masking

Data pipelines include two built-in transforms for protecting sensitive data before it reaches analytics tables or export targets.

Hash Transform

Replaces field values with a one-way cryptographic hash. Useful for pseudonymization where you need consistent identifiers without exposing the original value. Configuration:
  • Fields to Hash — One or more source fields to hash
  • AlgorithmSHA-256 (recommended), SHA-512, or MD5

Mask PII Transform

Applies pattern-based masking that preserves partial information for operational use while hiding sensitive details. Masking patterns are applied automatically based on detected data formats:
Data TypeBeforeAfter
SSN123-45-6789***-**-6789
Emailuser@example.comu***@example.com
Phone(555) 123-4567(***) ***-4567
Configuration:
  • Fields to Mask — One or more source fields to apply masking to

When to Use

  • Before loading to analytics — Mask PII fields in your ETL pipeline before data lands in reporting tables
  • Before export — Hash or mask sensitive fields before sending data to external systems
  • Pseudonymization — Use the hash transform to create consistent non-reversible identifiers for analytics
Both transforms are available as pipeline nodes in the visual pipeline editor under the “Transform” category.

Data Retention

Configurable retention policies control how long different classes of data are kept. Retention configs are per-tenant and per-data-class.

Retention Config Endpoint

GET /api/v1/admin/retention-configs
Returns all retention policies for the current tenant. Requires admin role.

Creating or Updating a Retention Policy

POST /api/v1/admin/retention-configs
Content-Type: application/json

{
  "dataClass": "interactions",
  "retentionDays": 365,
  "legalHold": false
}
Parameters:
FieldRequiredDescription
dataClassYesOne of: interactions, decisions, metrics, audit
retentionDaysYesNumber of days to retain (1 to 36,500)
legalHoldNoWhen true, prevents automatic purging regardless of retention period
Data classes:
ClassWhat It Covers
interactionsCustomer interaction history and response records
decisionsDecision trace records from the recommendation engine
metricsBehavioral metrics and pipeline execution metrics
auditAudit log entries (subject to legal hold considerations)
Retention policy changes are themselves audit-logged with action retention_config.upsert (or retention_config.legal_hold when a legal hold is applied).

Encryption

Data in Transit

All connections to the KaireonAI platform are over HTTPS. The playground deployment at playground.kaireonai.com enforces TLS.

Data at Rest

  • Connector credentials — The authConfig field on connector records stores sensitive connection parameters (passwords, API keys, access tokens). These are stored as encrypted JSON in the database.
  • API keys — Platform API keys (krn_ prefix) are validated against hashed values in the database.

Session Security

Authentication uses JWT-based sessions via NextAuth. Session tokens are HTTP-only cookies with secure flags in production.