> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# AI-Assisted Clinical Documentation — Integration

> Feature ID: CL-36 Status: 📋 Specification Spec Reference: CL-36-ai-assisted-clinical-documentation.md Last Updated: 2026-03-31 Last Verified: —

**Feature ID:** CL-36\
**Status:** 📋 Specification\
**Spec Reference:** [CL-36-ai-assisted-clinical-documentation.md](../../../specs/cl/specs/CL-36-ai-assisted-clinical-documentation.md)\
**Last Updated:** 2026-03-31\
**Last Verified:** —

***

## Table of Contents

* [Overview](#overview)
* [Quick Reference](#quick-reference)
* [Integration Points](#integration-points)
* [Data Contracts](#data-contracts)
* [Event Contracts](#event-contracts)
* [Edge Function Contracts](#edge-function-contracts)
* [Security and RLS](#security-and-rls)
* [External Vendor Integration (Phase 3)](#external-vendor-integration-phase-3)
* [Common Mistakes](#common-mistakes)
* [Related Docs](#related-docs)

***

## Overview

CL-36 provides platform-level AI documentation capability across note types (CL-04 progress notes, CL-14 group notes, CL-24 telehealth notes). It creates AI session audit records (`cl_ai_documentation_sessions`) and per-note attribution records (`cl_ai_note_attributions`). AI vendor calls are made exclusively from edge functions — no PHI flows client-side to AI vendors. Org-level opt-in is required; 42 CFR Part 2 consent gate (CL-11) is enforced before any AI vendor call.

***

## Quick Reference

| Item               | Value                                                                                                                                          |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| Core tables        | `cl_ai_documentation_sessions`, `cl_ai_note_attributions`                                                                                      |
| Settings columns   | `cl_ai_documentation_enabled`, `cl_ai_ambient_vendor`, `cl_ai_data_residency`, `cl_ai_policy940_enforcement` on `cl_module_settings`           |
| Permission keys    | `cl.ai_documentation.use`, `cl.ai_documentation.admin`                                                                                         |
| 42 CFR Part 2 gate | `cl_check_sud_consent(chart_id, 'ai_documentation', auth.uid())` from CL-11 (three-argument signature; edge: use `p_requesting_user` from JWT) |
| AI platform layer  | `@/platform/ai` (PF-27) when available; edge function adapter otherwise                                                                        |
| Session lifecycle  | `initiated` → `draft_generated` → `attested` (or `cancelled`)                                                                                  |

***

## Integration Points

| From  | To                  | Pattern                                                             | Notes                                                                      |
| ----- | ------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| CL-36 | CL-04               | Data write (adds `cl_ai_note_attributions` linked to progress note) | Phase 1                                                                    |
| CL-36 | CL-14               | Data write (same attribution pattern for group notes)               | Phase 3                                                                    |
| CL-36 | CL-24               | Data write (same attribution pattern for telehealth notes)          | Phase 3                                                                    |
| CL-36 | CL-11               | Function call (`cl_check_sud_consent`)                              | Before every AI vendor call                                                |
| CL-36 | PF-27 (Platform AI) | Platform Layer                                                      | If/when PF-27 available; interim: direct edge function                     |
| CL-36 | PF-02 / PF-30       | Platform Layer (auth, RBAC, audit)                                  | Permission gate on `cl.ai_documentation.use`                               |
| CL-36 | pm\_encounters      | FK / Data Lookup                                                    | `cl_ai_documentation_sessions.encounter_id` → `pm_encounters.id` (ADR-002) |
| CL-36 | External AI Vendors | API (edge function only; Phase 3 for ambient)                       | BAA required; API keys in Supabase Vault                                   |

***

## Data Contracts

### `cl_ai_documentation_sessions` (audit log — immutable)

| Column                                                 | Type                  | Description                                                           |
| ------------------------------------------------------ | --------------------- | --------------------------------------------------------------------- |
| `id`                                                   | uuid PK               |                                                                       |
| `organization_id`                                      | uuid                  | Tenant anchor (RLS)                                                   |
| `user_id`                                              | uuid → pf\_profiles   | Clinician who initiated                                               |
| `chart_id`                                             | uuid → cl\_charts     | Patient chart                                                         |
| `encounter_id`                                         | uuid → pm\_encounters | Linked encounter                                                      |
| `note_id`                                              | uuid                  | Polymorphic; see `note_type`                                          |
| `note_type`                                            | text CHECK            | `'progress_note'` \| `'group_note'` \| `'telehealth_note'`            |
| `status`                                               | text CHECK            | `'initiated'` \| `'draft_generated'` \| `'cancelled'` \| `'attested'` |
| `draft_source`                                         | text CHECK            | `'structured_data'` \| `'ambient_voice'`                              |
| `ai_vendor`                                            | text                  | Vendor slug (ambient only); null for structured-data                  |
| `session_started_at`                                   | timestamptz           |                                                                       |
| `session_ended_at`                                     | timestamptz           | null if cancelled                                                     |
| `attestation_at`                                       | timestamptz           | Populated on attestation                                              |
| `attestation_by`                                       | uuid → pf\_profiles   |                                                                       |
| `custom_fields`                                        | JSONB                 |                                                                       |
| `created_at`, `updated_at`, `created_by`, `updated_by` | audit                 |                                                                       |

### `cl_ai_note_attributions`

| Column                                                 | Type                                   | Description                                    |
| ------------------------------------------------------ | -------------------------------------- | ---------------------------------------------- |
| `id`                                                   | uuid PK                                |                                                |
| `organization_id`                                      | uuid                                   | Tenant anchor (RLS)                            |
| `note_id`                                              | uuid                                   | Matches `cl_ai_documentation_sessions.note_id` |
| `note_type`                                            | text CHECK                             | Same values as sessions                        |
| `ai_session_id`                                        | uuid → cl\_ai\_documentation\_sessions |                                                |
| `ai_assisted`                                          | boolean                                |                                                |
| `attribution_label`                                    | text                                   | `'Drafted with AI assistance'` (default)       |
| `ai_attestation_at`                                    | timestamptz                            | Updated on attestation                         |
| `ai_attestation_by`                                    | uuid → pf\_profiles                    |                                                |
| `custom_fields`                                        | JSONB                                  |                                                |
| `created_at`, `updated_at`, `created_by`, `updated_by` | audit                                  |                                                |

***

## Canonical AI Draft Interfaces (Clarification #13)

The edge function uses canonical request/response interfaces for testability and minimum-necessary PHI enforcement. Vendor adapters map these to vendor-specific payloads.

```typescript theme={null}
interface AiDraftRequest {
  diagnosisCodes: string[];        // ICD-10 codes only
  assessmentScoreSummaries: string[]; // Numeric scores, not raw responses
  treatmentPlanGoalText: string[];
  priorNoteSummary: string | null; // AI-generated summary, not full text
  noteType: 'progress_note' | 'group_note' | 'telehealth_note';
  serviceType: string;
  encounterDate: string;           // ISO date
}

interface AiDraftResponse {
  draftText: string;
  confidenceMetadata?: Record<string, unknown>;
  tokenUsage?: { promptTokens: number; completionTokens: number };
}
```

### PHI Inclusion/Exclusion Lists (Clarification #19)

**Included** (minimum necessary): diagnosis codes (ICD-10), assessment instrument scores (numeric only), treatment plan goal summaries, prior note summary (AI-generated, not full text), service type, encounter date.

**Excluded** (never sent): patient name, DOB, SSN, address, phone, email, insurance IDs, financial data, photo/biometric data, SUD-specific identifiers beyond CL-11 consent gate. Edge function enforces both lists.

### API Key Model (Clarification #11)

Hybrid — platform-level default key with per-tenant override. Edge function checks `AI_VENDOR_{TENANT_ID}_API_KEY` first (where `TENANT_ID` is derived from **verifiedOrgId**), falls back to `AI_VENDOR_DEFAULT_API_KEY`. Tenant resolution uses **verifiedOrgId** from the verified JWT/user profile only. Any `organization_id`, `organizationId`, or similar field in the request body is **ignored server-side** to prevent tenant spoofing; clients must not rely on body org for tenancy or key selection.

### Concurrency Control (Clarification #16)

One active session per note at a time; multiple notes can generate concurrently. Edge function checks for existing session with `(note_id, note_type)` where `status = 'initiated'` within the timeout window; rejects with user-friendly message if in-flight.

### Session Update Scope (Clarification #14)

Only lifecycle fields may be updated after INSERT: `status`, `attestation_at`, `attestation_by`, `session_ended_at`, `updated_at`, `updated_by`. All other columns are immutable. Phase 1: application logic; Phase 2: trigger-based guard.

### Data Residency (Clarification #20)

Phase 1 (US only): contractual via BAA. Phase 3 (when EU added): edge function selects vendor's region-specific API endpoint based on `cl_ai_data_residency`. Adapter pattern supports per-vendor endpoint mapping.

***

## Event Contracts

CL-36 does not publish events in Phase 1 or 2. Phase 3 consideration: if AI draft generation failure needs to notify the clinician asynchronously, a `cl_ai_draft_failed` event may be added. No contract defined yet.

***

## Edge Function Contracts

### `cl-ai-generate-draft` (Phase 2)

Generates a note draft from structured encounter data. Called from the browser via authenticated Supabase client; does **not** send raw PHI to the AI vendor without first invoking `cl_check_sud_consent`.

**Request (from browser → edge function):**

JSON body includes note context only. Do **not** send `organization_id` for tenancy — the edge function derives org from the authenticated session (`verifiedOrgId`).

```json theme={null}
{
  "chart_id": "uuid",
  "encounter_id": "uuid",
  "note_id": "uuid",
  "note_type": "progress_note | group_note | telehealth_note"
}
```

**Response:**

```json theme={null}
{
  "session_id": "uuid",
  "draft": "string (AI-generated note text)",
  "attribution_label": "Drafted with AI assistance",
  "model_used": "vendor:model-slug"
}
```

**Error cases:**

* `403 SUD_CONSENT_NOT_CLEARED` — 42 CFR Part 2 gate triggered
* `403 AI_DOCUMENTATION_DISABLED` — org opt-in not enabled
* `503 AI_VENDOR_UNAVAILABLE` — graceful degradation; app continues without draft

**Edge function standards:**

* `Deno.serve()` only
* `getCorsHeaders(req.headers.get('origin'))` from `_shared/cors.ts`
* `createLogger` from `_shared/logger.ts`; no PHI in log messages
* JWT verified on every request; use **verifiedOrgId** from JWT/profile for RLS, session rows, and `AI_VENDOR_{TENANT_ID}_API_KEY` resolution — ignore any org id in the request body

***

## Security and RLS

* Both tables have RLS enabled via `cl_check_ai_session_access(session_org_id)` SECURITY DEFINER function
* No DELETE policy on either table (immutable audit records)
* AI vendor API keys stored in Supabase Vault; accessed only from edge functions
* No PHI stored in `cl_ai_documentation_sessions` beyond FKs; note text is never persisted to the audit log
* `cl_check_sud_consent()` from CL-11 must be invoked before every AI vendor call

***

## External Vendor Integration (Phase 3)

Ambient voice vendors (Nabla, Nuance DAX, Abridge, Suki) integrated via a common adapter pattern in a single edge function (`cl-ai-ambient-draft`). The vendor is determined by `cl_ai_ambient_vendor` on `cl_module_settings`. Each vendor implements the adapter interface:

```typescript theme={null}
interface AiVendorAdapter {
  healthCheck(): Promise<boolean>;
  generateDraft(context: EncounterContext): Promise<AiDraftResult>;
}
```

* **`healthCheck()`:** Each adapter must implement `healthCheck()` returning `true` when the vendor API is reachable, `false` otherwise. Used to fail fast before sending PHI.
* **Edge function behavior:** Before calling `generateDraft(context)`, the edge function must call `adapter.healthCheck()` (adapter selected from `cl_ai_ambient_vendor` via factory). If `healthCheck()` returns `false`, respond with `503 AI_VENDOR_UNAVAILABLE` instead of relying solely on exception handling; do not call `generateDraft` in that case. `generateDraft` implementations remain unchanged.
* **Adapter factory:** Any factory or selection code that returns adapters must ensure returned adapters implement the full interface including `healthCheck`.

Vendor SDK imports are confined to the edge function; no vendor SDKs in React components.

***

## Common Mistakes

| Mistake                                            | Mitigation                                                                   |
| -------------------------------------------------- | ---------------------------------------------------------------------------- |
| Sending PHI to AI vendor from browser              | All vendor calls must be in edge functions only                              |
| Not invoking `cl_check_sud_consent` before AI call | Required; hard block on failure                                              |
| Skipping BAA with AI vendor                        | BAA must be in place before any PHI flows to vendor                          |
| Using `note_type` as an unvalidated string         | Always use CHECK constraint values                                           |
| Allowing note finalize without attestation         | `cl_ai_note_attributions.ai_attestation_at` must be non-null before finalize |

***

## Related Docs

* [CL-36 Spec](../../../specs/cl/specs/CL-36-ai-assisted-clinical-documentation.md)
* [CL-04 Integration](./progress-notes-session-documentation-integration.md)
* [CL-11 Integration (42 CFR Part 2)](./consent-management-42cfr-part2-integration.md)
* [PF-27 Platform AI Layer](./PLATFORM_INTEGRATION_LAYERS.md#pf-27-platform-ai-integration-layer)
* [CROSS\_CORE\_INTEGRATIONS.md](./CROSS_CORE_INTEGRATIONS.md)
