SOC 2 Controls Mapping
This document maps all Devotel technical controls to the AICPA SOC 2 Trust Services Criteria. Each control is linked to the relevant infrastructure, application, or operational mechanism within the Devotel CPaaS platform.Security (CC6) — Common Criteria
CC6.1 — Logical Access Controls
The entity implements logical access security measures to protect against unauthorized access.| Control | Implementation | Evidence |
|---|---|---|
| Role-Based Access Control (RBAC) | Five-tier role system: owner, admin, developer, viewer, billing. Every API endpoint declares required permissions. Enforced via requireRole() middleware. | packages/auth/src/middleware.ts, packages/database/src/schema/public/permissions.ts |
| API Key Authentication | Server-to-server access via X-API-Key header. Keys are SHA-256 hashed at rest; plain-text shown only once at creation. Supports live/test mode separation with dv_live_sk_* / dv_test_sk_* prefixes. | packages/auth/src/api-keys.ts, packages/database/src/schema/public/api-keys.ts |
| JWT Bearer Authentication | Dashboard users authenticate via Clerk with JWT Bearer tokens. Tokens are verified on every request via authMiddleware. | packages/auth/src/middleware.ts, Clerk integration |
| Multi-Factor Authentication | Supported via Clerk — users can enable TOTP-based 2FA. MFA status tracked in users.two_factor_enabled. | packages/database/src/schema/public/users.ts |
| Session Management | Sessions managed by Clerk with configurable idle and absolute timeouts. Session tokens stored securely with Redis-backed session cache. | packages/database/src/schema/public/sessions.ts |
| Tenant Isolation | Multi-tenant architecture with dedicated PostgreSQL schemas per tenant (tenant_{uuid}). tenant_id is resolved from middleware — never accepted from client input. | packages/database/src/tenant.ts, apps/api/src/plugins/tenant.ts |
CC6.2 — Boundary Protection
The entity implements controls to protect system boundaries and restrict unauthorized network access.| Control | Implementation | Evidence |
|---|---|---|
| Virtual Private Cloud (VPC) | All services run within a GCP VPC in europe-west1. Internal services communicate via private IPs only. | infrastructure/terraform/ |
| Cloud Armor WAF | Google Cloud Armor policies protect public endpoints against DDoS, SQL injection, XSS, and other OWASP Top 10 threats. | GCP Cloud Armor policy configuration |
| Kubernetes Network Policies | Pod-to-pod traffic restricted via Kubernetes NetworkPolicies. Only explicitly allowed service-to-service communication is permitted. | infrastructure/k8s/network-policies/ |
| IP Allowlisting | Organizations can restrict API access to specific IP addresses/CIDR ranges via the IP allowlist feature. | apps/api/src/routes/settings/settings-security.service.ts |
| Rate Limiting | Per-organization rate limits enforced at the API gateway layer. Headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. | apps/api/src/plugins/rate-limit.ts |
| Cloud SQL Private IP | PostgreSQL database accessed exclusively via private IP through Cloud SQL Proxy. No public IP exposure. | GKE Autopilot + Cloud SQL configuration |
CC6.3 — Encryption
The entity implements encryption to protect data at rest and in transit.| Control | Implementation | Evidence |
|---|---|---|
| Encryption at Rest | All data encrypted at rest using Google-managed encryption keys (AES-256). Cloud SQL, Cloud Storage, and persistent disks use default encryption. | GCP default encryption |
| HIPAA PHI Encryption | When HIPAA mode is enabled, message content is additionally encrypted with AES-256-GCM at the application layer with per-org keys. | apps/api/src/routes/settings/hipaa.service.ts |
| Encryption in Transit | All external traffic encrypted with TLS 1.3. Internal gRPC traffic uses mTLS. | GKE Ingress, Cloud Load Balancer |
| Secret Management | All secrets stored in GCP Secret Manager with IAM-controlled access. Environment variables use DEVOTEL_ prefix and are injected via Kubernetes secrets. | packages/shared/src/env.ts, GCP Secret Manager |
| API Key Hashing | API keys are hashed with SHA-256 before storage. Only the prefix and last 4 characters are stored in plain text for identification. | packages/auth/src/api-keys.ts |
CC6.6 — System Monitoring
The entity implements monitoring to detect anomalies, vulnerabilities, and security events.| Control | Implementation | Evidence |
|---|---|---|
| Application Performance Monitoring | Datadog APM with distributed tracing across all services. Custom metrics for message throughput, latency percentiles, and error rates. | packages/monitoring/, Datadog dashboards |
| Error Tracking | Sentry integration for real-time error alerting with release tracking. Source maps uploaded on every deployment. | packages/monitoring/src/sentry.ts |
| Structured Logging | All backend services use the shared pino-based logger with mandatory fields: requestId, tenantId, service. PII is masked. | packages/shared/src/logger.ts |
| Audit Logging | Every security-relevant action (login, API key creation, settings changes, role changes) is recorded in the audit_logs table with actor, action, resource, and IP address. | apps/api/src/lib/audit.ts, packages/database/src/schema/public/audit-logs.ts |
| PHI Access Logging | When HIPAA mode is active, all access to protected health information is logged with reason codes. | apps/api/src/routes/settings/hipaa.service.ts |
| Cloud Logging | All container logs forwarded to Google Cloud Logging with 90-day retention. Loki for aggregation. | GKE logging configuration |
CC6.7 — Change Management
The entity implements controls over changes to system components.| Control | Implementation | Evidence |
|---|---|---|
| Version Control | All code in Git (GitHub). Branch protection on main requires PR approval. | GitHub branch protection rules |
| Code Review | CodeRabbit AI review on all PRs, plus manual review for security-sensitive changes. | GitHub PR workflow |
| CI/CD Pipeline | Automated pipeline: lint → type-check → unit tests → Docker build → canary deploy → E2E tests → progressive rollout (10% → 50% → 100%). | .github/workflows/, infrastructure/cloudbuild/ |
| Database Migrations | Schema changes managed via Drizzle Kit migrations. Migrations run as Kubernetes Jobs — never in web pods. | packages/database/drizzle/, migration Jobs |
| Feature Flags | All new features deployed behind LaunchDarkly flags. Flags cleaned up within 30 days of 100% rollout. | LaunchDarkly configuration |
| Conventional Commits | Commit messages follow Conventional Commits format (feat|fix|chore|docs|refactor|test|ci(scope): description). | Git history |
Availability (A1)
A1.1 — Processing Capacity
The entity maintains, monitors, and evaluates current processing capacity and usage of system components to manage capacity demand.| Control | Implementation | Evidence |
|---|---|---|
| GKE Autopilot | Kubernetes cluster with automatic node scaling. Autopilot manages node provisioning based on pod resource requests. | infrastructure/terraform/gke.tf |
| Horizontal Pod Autoscaler (HPA) | All stateless services configured with HPA based on CPU and custom metrics (request rate). Min replicas ensure baseline availability. | infrastructure/k8s/hpa/ |
| Pod Disruption Budgets (PDB) | PDBs configured for critical services to ensure availability during rolling updates and node maintenance. | infrastructure/k8s/pdb/ |
| Resource Requests/Limits | Every pod defines CPU and memory requests/limits (GKE Autopilot requirement). Prevents resource contention. | Kubernetes deployment manifests |
| Queue-Based Load Leveling | BullMQ + Redis for async processing (webhooks, message delivery). Queue depth monitored with alerting. | apps/webhook-worker/, Redis configuration |
A1.2 — Recovery
The entity authorizes, designs, develops, implements, operates, approves, maintains, and monitors environmental protections, software, data backup and recovery infrastructure, and plans to meet its objectives.| Control | Implementation | Evidence |
|---|---|---|
| Database Backups | Cloud SQL automated daily backups with 30-day retention. Point-in-time recovery (PITR) enabled with 7-day transaction log retention. | Cloud SQL backup configuration |
| Vector Database Snapshots | Qdrant deployed with 3 replicas across availability zones via StatefulSet. Regular snapshots for disaster recovery. | infrastructure/k8s/qdrant/ |
| Redis Persistence | Memorystore Redis with RDB snapshots and AOF persistence. Cross-zone replication for high availability. | Memorystore configuration |
| Multi-Zone Deployment | All critical services deployed across multiple availability zones within europe-west1. | GKE Autopilot multi-zone |
| Disaster Recovery Plan | Documented DR procedures with RTO < 4 hours and RPO < 1 hour for production data. | Internal DR documentation |
Confidentiality (C1)
C1.1 — Data Classification
The entity identifies and classifies confidential information.| Control | Implementation | Evidence |
|---|---|---|
| PII Masking | Phone numbers and email addresses are masked in all log output (e.g., +90555****567). Dedicated masking functions in the shared logger. | packages/shared/src/logger.ts |
| PHI Encryption | HIPAA mode provides application-layer AES-256-GCM encryption for message content containing protected health information. | apps/api/src/routes/settings/hipaa.service.ts |
| API Key Redaction | API keys are never logged or returned in full after creation. Only prefix and last 4 characters are stored for identification. | packages/auth/src/api-keys.ts |
| Tenant Data Isolation | Per-tenant PostgreSQL schemas prevent cross-tenant data access. Schema name validated against [a-z0-9_] regex to prevent SQL injection. | packages/database/src/tenant.ts |
| RBAC for Sensitive Data | Access to billing, audit logs, team management, and security settings restricted to appropriate roles via requireRole() middleware. | packages/auth/src/middleware.ts |
C1.2 — Disposal
The entity disposes of confidential information to meet the entity’s objectives.| Control | Implementation | Evidence |
|---|---|---|
| Data Retention Policies | Configurable per-organization data retention periods. When HIPAA mode is active, automatic deletion is enforced after the configured period. | apps/api/src/routes/settings/hipaa.service.ts |
| GDPR Right to Erasure | Contact data supports soft-delete with deleted_at timestamp. Hard delete available for GDPR Article 17 requests. Consent records tracked per channel. | packages/database/src/schema/tenant/, consent_records table |
| Audit Log Retention | Audit logs retained for 90 days by default. Export available in CSV/JSON format for long-term archival. | apps/api/src/routes/settings/settings.service.ts |
| Secure Secret Rotation | API keys can be revoked at any time. GCP Secret Manager supports automatic rotation. | packages/auth/src/api-keys.ts, GCP Secret Manager |
Evidence Collection
For audit purposes, the following evidence artifacts are available:- Access Reviews — Export team members and roles via
GET /api/v1/settings/team - Audit Log Export — Download audit logs via
GET /api/v1/settings/audit-logs/export?format=csv&date_range=90d - Change History — Git commit history and PR review records on GitHub
- PHI Access Log — Export PHI access log via
GET /api/v1/settings/hipaa/phi-access-log - API Key Inventory — List all API keys via
GET /api/v1/settings/api-keys - Infrastructure Configuration — Terraform state files and Kubernetes manifests in
infrastructure/
Last reviewed: April 2026 Next review: July 2026