# CareCore — Security & AI Governance

**Product:** CareCore — AI operations and workforce coordination for domiciliary care
**Roles:** the care agency is the **data controller**; CareCore is the **processor**
**Document owner:** privacy@carecore.app · Security disclosures: security@carecore.app
**Version:** 1.0 · Last reviewed: August 2026

---

## 1. System Architecture

CareCore is a single multi-tenant web application with no separate admin binary.

| Layer | Technology | Notes |
|---|---|---|
| Front end | React 19 + TanStack Start (SSR) | Care console at `/console`, platform console at `/platform` |
| Application server | TanStack server functions (typed RPC) and server routes | Runs on managed edge/serverless workers |
| Database & auth | Managed PostgreSQL with Row-Level Security | Single database, tenant separated by `agency_id` |
| Telephony / messaging | Twilio (voice, WhatsApp) | Inbound via signed webhooks under `/api/public/twilio/*` |
| Speech-to-text | Deepgram | Call audio → transcript |
| AI reasoning | Lovable AI Gateway (Google Gemini; OpenAI TTS for speech) | Inference only, no training on customer content |
| File storage | Managed object storage (private buckets only) | Voice cache |

There are no publicly writable endpoints other than provider webhooks, and every
webhook validates the provider signature before any database write.

## 2. Data Flow

**Inbound phone call**
1. Twilio receives the call and posts a signed webhook to CareCore.
2. The number is matched to an agency; the caller is matched to a carer, client or family contact.
3. A recording/AI notice is spoken; audio is streamed to Deepgram for transcription.
4. Transcript text (not audio) is sent to the AI gateway to determine intent and urgency.
5. CareCore answers from approved knowledge, or creates the operational record (task, incident, escalation, cover request).
6. If a human is required, the assignee is notified in-app, then by WhatsApp, then by phone call.

**Inbound WhatsApp**
1. Signed Twilio webhook → sender identified against `client_contacts` / `carers`.
2. Message classified; CareCore replies in-thread or opens a record and escalates.
3. Coordinators reply from the Family Inbox; the reply is delivered over the same WhatsApp thread and stamped against the linked record.
4. If no human has replied by the first overdue tier, CareCore sends an automatic holding update to the family.

**Outbound sender integrity:** WhatsApp messages are sent from the agency's registered
WhatsApp sender (held in `telephony_numbers`), never from an unrelated line.

## 3. Data Storage

All application data is held in one managed PostgreSQL instance in the **United Kingdom
(London region)**, encrypted at rest, with automated backups and point-in-time recovery.

| Data class | Where it lives |
|---|---|
| Tenancy, staff, roles, invitations | `agencies`, `profiles`, `user_roles`, `agency_invites` |
| Service users and family contacts | `clients`, `client_contacts` |
| Workforce and availability | `carers`, `carer_availability`, `absence_reports` |
| Care delivery | `visits`, `cover_requests`, `cover_offers` |
| Communications | `calls`, `transcripts`, `conversations`, `conversation_messages` |
| Safeguarding and operations | `incidents`, `escalations`, `tasks`, `page_events`, `notification_events` |
| Governance | `audit_events`, `data_subject_requests`, `retention_policies`, `breach_events` |
| Knowledge | `knowledge_docs` (with vector embeddings) |

**Call audio is not stored in CareCore's database.** Twilio holds the media; CareCore
stores a reference and streams it through a proxy protected by a short-lived signed token.

## 4. Tenant Isolation

- Every tenant-scoped table carries `agency_id` and has Row-Level Security **enabled with explicit policies**; there is no "trusted" bypass path in application code for ordinary reads.
- Policies resolve the caller's tenant through the security-definer helper `current_agency_id()`, which reads the caller's own profile — a request cannot assert a tenant of its own choosing.
- A user cannot move themselves between tenants: `UPDATE` on `profiles` is granted **column by column** (name, email, phone, avatar only), so `agency_id` is not writable through the data API at all, and the `guard_profile_agency` trigger additionally rejects any change not made by an admin of that same agency.
- Internal/platform tables (`ai_usage_events`, `system_events`, `retention_runs`, `breach_events`, `platform_admins`, `platform_audit_events`, `sub_processor_changes`, `platform_support_sessions`) have all privileges revoked from application roles and are reachable only by the trusted server role.
- Inbound telephony is resolved to a tenant by the receiving number, so one agency's calls or messages cannot enter another agency's queues.

## 5. Authentication & RBAC

- Email/password and Google sign-in via managed authentication; sessions are JWT-based with rotating refresh tokens. Anonymous sign-up is disabled.
- Registration requires either a valid, unexpired, email-matched **invitation** or a new agency name — accounts cannot self-attach to an existing tenant.
- Roles are held in a dedicated `user_roles` table (never on the profile), and are evaluated only through the security-definer functions `has_role()` / `has_any_role()`. Client-side state is never trusted for authorisation.

| Role | Scope |
|---|---|
| `admin` | Full agency configuration, team access, retention, integrations |
| `coordinator` | Operational console: calls, inbox, rota, incidents, escalations, tasks |
| `carer` | Own profile, own visits, own availability, cover offers, announcements |
| `auditor` | Read-only across the agency, including the audit trail |

Platform staff are a separate identity set (`platform_admins`), checked via
`is_platform_admin()`, which is not executable by unauthenticated visitors.

## 6. MFA

Time-based one-time-password (TOTP) multi-factor authentication is available to every
user and is managed from the console (Settings → security). Agencies should require it
for all `admin` and `coordinator` accounts, as those roles can read special-category
care data. Factor enrolment and challenge state are held by the managed auth service,
not in application tables.

## 7. Encryption

- **In transit:** TLS 1.2+ for all browser, API, database and sub-processor traffic; HSTS on the published domain.
- **At rest:** AES-256 for the database, backups and object storage.
- **Secrets:** provider credentials (Twilio, Deepgram, AI gateway, service keys) are held in the managed secret store and injected into the server runtime only. They are never bundled into browser code, never logged, and the service-role key is not retrievable by the agency or by CareCore staff through the product.
- **Recording access:** playback URLs are signed, expire after 30 minutes, and are bound to the requesting call record.

## 8. AI Processing

CareCore's AI performs four narrow jobs:

1. **Transcription** of call audio (Deepgram).
2. **Classification** of intent, urgency and sentiment from transcript or message text.
3. **Retrieval-augmented answering** strictly from the agency's own indexed knowledge documents (vector search over `knowledge_docs`).
4. **Drafting** of replies and summaries, and selection of the correct operational record type.

The AI does **not** make decisions about a person's care package, medication,
eligibility or employment. There is no automated decision-making with legal or
similarly significant effect, and no profiling of individuals.

## 9. AI Risk Controls

- **Grounded answers only.** Family and carer questions are answered from the live rota or from approved knowledge; the model is not permitted to give open-ended medical advice.
- **Configurable autonomy.** Each agency chooses per-behaviour whether CareCore may answer, raise a record, or must always defer to a human (`channel_automations`, `tenant_flags`).
- **Hard guardrails.** Emergency, safeguarding, clinical and complaint signals bypass automation and page a human. Unknown senders receive an acknowledgement with no care information disclosed.
- **Confidence and fallback.** Low-confidence classification, provider failure or any unhandled error results in an escalation to a named human plus a holding message to the sender — never silence.
- **Minimisation at the boundary.** Only transcript or message text and retrieved policy extracts are sent to the AI gateway; audio, addresses and contact directories are not.
- **Escalation floors.** Platform-level minimum wait times prevent an agency from configuring notification storms, and quiet hours suppress voice calls for non-critical work.
- **Cost and usage visibility.** Every AI call is metered in `ai_usage_events` for anomaly detection.

## 10. Human Oversight

- Every AI-handled interaction produces a human-reviewable record with a reference (e.g. `TSK-0007`, `ESC-0011`) and a visible workflow trail.
- Escalation is tiered: in-app queue → personal WhatsApp → phone call, with a function/on-call rota fallback so no item can sit unowned.
- Coordinator replies from the Family Inbox stamp the linked record as acknowledged — stopping the escalation clock — but do **not** close it; closure requires an outcome.
- A **reply-before-resolve guard** prevents closing a thread while a family member is still awaiting an answer, unless the outcome is sent to them in the same action.
- Agencies can review, correct or override anything CareCore did; the AI never has the last word.

## 11. Audit Logging

- `audit_events` records who did what, to which record, and when, for every state change in the console. It is append-only to application roles — no update or delete privileges exist.
- `notification_events` and `page_events` record every nudge, WhatsApp message and call attempt, including provider IDs, failures and acknowledgements.
- `platform_audit_events` records CareCore staff actions, including support access, with a stated reason.
- `system_events` captures operational and integration failures for reliability review.
- Logs are visible to the agency's `admin` and `auditor` roles and are retained on the audit schedule below (default 7 years).

## 12. Data Retention

Retention is configured per agency (`retention_policies`) and enforced automatically by a
scheduled database routine (`apply_retention`), with each run recorded in `retention_runs`.

| Data | Default window | Effect of expiry |
|---|---|---|
| Call recordings | 90 days | Recording reference cleared — audio no longer reachable |
| Transcripts | 365 days | Verbatim speech deleted |
| Call records | 730 days | Record deleted |
| Audit events | 2,555 days (7 years) | Record deleted |

Care records themselves follow the controller's statutory schedule (typically 8 years
after the end of care, or a child's 25th birthday). Erasure of an individual is
implemented as irreversible pseudonymisation: identifiers and verbatim speech are
removed while clinical and audit records remain intact.

## 13. Call Recording & Transcription

- Every inbound call opens with a spoken notice that the call is answered by an AI operator, is recorded and transcribed, and that a human can be requested at any time by saying "coordinator".
- Audio is held by Twilio; CareCore holds a reference plus the transcript. Playback is signed, time-limited and audit-logged.
- Transcripts are the highest-sensitivity free text in the system and carry the shortest configurable retention window after recordings.
- Recordings and transcripts are never sent to any AI provider for storage or training; only transcript text is sent for classification.

## 14. WhatsApp Data

- WhatsApp is used for family and carer conversations and for personal notification of assignees. CareCore does not send SMS.
- Stored per message: sender number, message text, direction, timestamp, provider message ID, delivery status, and the classification/actions taken (`conversations`, `conversation_messages`).
- Message content is subject to the same tenant isolation, audit logging and retention controls as call data.
- Unverified or unknown senders receive an acknowledgement only — no care information is disclosed until the contact is matched and verified.
- Message content passes through Meta's WhatsApp infrastructure by nature of the channel; agencies are advised not to send detailed clinical content over WhatsApp, and CareCore's replies are written accordingly.

## 15. Third-Party Sub-processors

| Sub-processor | Purpose | Data shared | Location | Safeguard |
|---|---|---|---|---|
| Managed cloud platform (PostgreSQL, auth, object storage on AWS) | Database, authentication, file storage | All application data | AWS eu-west-2 (London, United Kingdom) — confirmed on the project record | No international transfer for the primary data store; provider states AES-256 at rest and TLS in transit; DPA with UK Addendum |
| Twilio | Voice telephony, call recording media, WhatsApp and SMS | Phone numbers, call audio, message content | Twilio US region (global default). Recording media is stored in the US unless the account is migrated to the Ireland (IE1) region | Twilio DPA incorporating EU SCCs + UK International Data Transfer Addendum |
| Meta / WhatsApp Business Platform (reached via Twilio) | WhatsApp message delivery | Phone numbers, message content | Meta global infrastructure — not region-pinned | Meta and Twilio DPAs with SCCs + UK Addendum; agencies are advised not to send detailed clinical content over WhatsApp |
| Deepgram | Speech-to-text transcription | Call audio, resulting transcript | United States | SCCs + UK Addendum; requests are sent with `model_opt_out=true`, so audio is not used for Deepgram model training |
| AI gateway (Google Gemini for classification and drafting, OpenAI for speech and embeddings) | Intent triage, reply drafting, neural speech | Transcript/message text, the client's own visit context, retrieved policy extracts | EU/US depending on the model routed to | SCCs + UK Addendum; inference only, no training on content |
| Hosting/edge provider | Application delivery | Request metadata only | Provider edge network — request served from the nearest region | SCCs + UK Addendum |

Notes on accuracy: the database region and the Twilio account region are deployment
settings, not product code. Both must be verified against the live project before either
is presented to a customer or regulator as a residency guarantee.


Controllers are notified at least 30 days before a sub-processor is added or replaced and
may object; changes are recorded in `sub_processor_changes`. No analytics, advertising or
session-replay tooling is present in the console.

## 16. Business Continuity

- Managed PostgreSQL with automated daily backups and point-in-time recovery; target RPO 15 minutes, RTO 4 hours.
- Stateless application servers behind a managed edge platform — no server holds durable state, so instances can be replaced without data loss.
- Provider degradation is contained: if transcription, AI or messaging fails, CareCore falls back to raising an escalation and paging a human rather than dropping the interaction.
- Telephony failover: if a call cannot be connected to a coordinator, the caller is told and the on-call chain is notified with a call-back instruction.
- Integration health and failures are surfaced on the platform health page and recorded in `system_events`.

## 17. Incident Response

1. **Detect** — automated error capture, integration health checks and provider failure alerts.
2. **Triage** — severity assigned; a `breach_events` record opened for anything touching personal data.
3. **Contain** — revoke credentials or disable the affected path; rotate secrets as needed.
4. **Assess** — determine data categories, individuals affected and risk of harm.
5. **Notify** — inform the affected controller **without undue delay and within 24 hours** of confirming a personal-data breach, so the controller can meet its own 72-hour ICO obligation. Regulator notification is the controller's decision; CareCore supplies the evidence.
6. **Remediate and review** — fix, record remediation, and feed lessons into controls.

Security disclosures to security@carecore.app are acknowledged within one working day.

## 18. UK GDPR / Data Protection

- **Roles:** agency = controller, CareCore = processor acting only on documented instructions. A processor agreement meeting Article 28 is in place.
- **Lawful bases:** contract and legitimate interests for operational data; Article 9(2)(h) (health/social care) for special-category care data; Article 9(2)(b) for sickness absence; legal obligation for safeguarding and CQC-related records.
- **Article 30 record of processing** is maintained and rendered live in the Compliance Centre.
- **Data subject rights** are supported in-product: export (access/portability) and erasure (pseudonymisation) for clients and carers, with every request logged in `data_subject_requests` and a statutory one-month due date tracked.
- **International transfers** are covered by EU SCCs with the UK International Data Transfer Addendum.
- **Data minimisation:** the AI receives only the text needed to classify and answer; families are never sent care detail they are not entitled to.

## 19. DPIA Considerations

A DPIA is required because the platform processes special-category health data at scale
using AI. Key assessed risks and mitigations:

| Risk | Mitigation |
|---|---|
| Wrong-person disclosure over phone/WhatsApp | Contact matching plus verification flag; unknown senders get no care information |
| AI giving unsafe or clinical advice | Retrieval limited to approved knowledge; clinical/urgent signals escalate to a human |
| Missed urgent message or call | Tiered escalation with platform-enforced floors, function/on-call fallback, automatic holding updates |
| Silent automation (family left unanswered) | Reply-before-resolve guard and automatic holding message on first overdue tier |
| Cross-tenant leakage | RLS on every tenant table, column-level grants on `profiles`, tenant resolved server-side |
| Excessive retention of speech | Shortest configurable window on recordings and transcripts, automated sweep with evidence log |
| Sub-processor exposure | Minimised payloads, no training on content, SCCs + UK Addendum, 30-day change notice |
| Staff/admin over-reach | Least-privilege roles, MFA, append-only audit trail, time-boxed support access |

Residual risk is assessed as **low-to-moderate** and acceptable with the controls above,
subject to annual review or on material change.

## 20. Support/Admin Access

- CareCore staff have no standing access to tenant data. Support access is granted as an explicit, **time-boxed** session (`platform_support_sessions`) with a recorded admin identity, target agency, stated reason and expiry, and can be revoked at any time.
- Every platform action is written to `platform_audit_events`, visible on the platform audit page.
- Platform-admin status lives in a separate table checked server-side; it cannot be self-granted, and the check is not callable by unauthenticated visitors.
- Production database credentials and the service-role key are held only in the managed secret store; they are not retrievable through the product by agency users or by CareCore staff.
- Agencies control their own team access: invitations are email-bound and expiring, roles are assignable only by an agency `admin`, and every change is audited.

---

*This document describes CareCore's design and operating controls and is provided for
supplier due diligence. It is not a contract; the Data Processing Agreement governs.*
