specs/pf/specs/PF-100-platform-ambient-transcription-and-note-generation.md
Last Updated: 2026-04-22
Cross-core integration contract for PF-100. Captures the boundary between PF (capture, STT, LLM, template engine, evidence map, lifecycle) and consuming cores (CL, PM, HR, GR, CE, RH). All cross-core consumption is via @/platform/transcription — no direct module imports.
1. Pattern
This is a Pattern 1 (Platform Integration Layer) + Pattern 2 (Event Contracts) integration.- Layer:
@/platform/transcriptionexposes hooks, components, types. - Events:
pf.transcription.*event family published; cores subscribe via PF-66 realtime + edge-function subscriptions. - Tables:
pf_transcription_*owned by PF; cores own their domain tables (e.g.cl_progress_notes,hr_meeting_summaries) and link viasession_idUUID column (no cross-core FK except CL → PM encounter per ADR-002).
2. Scope of contract
3. Public API surface (@/platform/transcription)
See PF-100 spec §8.1 for full hook list. Core consumer pattern:
@/platform/ai directly for transcription concerns; the PF-100 layer wraps PF-27/PF-59 internally.
4. Event Contracts
All events published on the platform realtime + outbox pattern. Subscribers register via PF-66 (frontend) or via a database-trigger-driven edge subscription (backend).Consumed events
pf.consent.cl_consent.revoked(CL-11) — triggers session-revocation cascade for any active CL session referencing the consentpf.encounter.created(PM) — optional auto-link encounter for a clinical session in pre-record statepf.encounter.cancelled(PM) — cancels any in-progress capture for that encounter
5. Cross-core FK rules (ADR-002 compliance)
Per ADR-002 and constitution §5.2.7:pf_transcription_sessions.encounter_id— UUID column with no FK constraint topm_encounters.idat the database level (cross-core FK exception is reserved for CL→PM, not PF→PM).- Validation is enforced at the application layer (edge function
pf-transcription-start-sessionrejects sessions whoseencounter_iddoes not resolve to an existingpm_encounters.idin the sameorganization_idat session start). - No trigger-enforced FK is created; an earlier draft of spec §7.1 implied a trigger — that has been corrected.
- Validation is enforced at the application layer (edge function
pf_transcription_sessions.subject_of_record_id— polymorphic UUID; no FK.- CL projection layer (Phase 3):
cl_ambient_sessionsbecomes a VIEW overpf_transcription_sessions WHERE module_key='cl'. The CL→PM FK from CL-36-EN-01’s existing schema is preserved independently on the CL side (via a separatecl_ambient_session_encountersmaterialization or a CL-owned trigger that enforces the FK only whenmodule_key='cl' AND encounter_id IS NOT NULL). PF-100 itself does not own the CL→PM FK; the CL DX team retains that responsibility per ADR-002.
6. Vendor adapter contract
Each STT or LLM adapter implements a strict TypeScript interface insupabase/functions/_shared/transcription-vendors/. PF-100 spec §FR-2.3 defines the STT contract; the LLM adapter contract mirrors PF-27/PF-59.
Vendor BAA expiry monitor (
pf-transcription-vendor-baa-monitor cron) emits PF-91 evidence + alerts at 30 / 14 / 7 day thresholds.
7. CL-36 migration contract (Phase 3)
Non-breaking. Sequence:cl_ambient_sessionscontinues writing through CL-36 hooks; PF-100 hooks are added in parallel and wrap the same vendor calls.- CL backend swap:
cl_ambient_sessionsbecomes a VIEW overpf_transcription_sessions WHERE module_key='cl';cl_ambient_transcriptssimilarly overpf_transcription_segments. - CL-36 attribution overlay (
cl_ai_note_attributions) consumespf.transcription.draft.attestedevent withmodule_attest_payload.cl_progress_note_id. - CL-36 hooks become deprecated shims; deletion in next major release per constitution §8.4 deprecation policy.
8. PF-96 jurisdiction profile extension contract (PF-96-EN-RECORDING)
PF-100 requires PF-96 enhancement adding a new top-levelrecording_rules JSONB DEFAULT '{}' NOT NULL column to pf_jurisdiction_profiles (the policy_json column referenced by an earlier draft does not exist; the actual JSONB columns on the table are clinical_rules, billing_rules, compliance_rules, metadata). All recording-policy keys live under recording_rules.*.
Keys (see PF-100 spec §7.2 for the authoritative list):
recording_consent_modelwiretap_class_severityrecording_max_retention_days_part2recording_max_retention_days_general_clinicalrecording_max_retention_days_hrrecording_max_retention_days_grexternal_recorder_allowedexternal_recorder_forbidden_for_part2mental_health_record_retention_yearsrequires_visible_recording_indicatorrequires_per_participant_verbal_affirmationrecording_pause_resume_consent_threshold_seconds
specs/cross-cutting/MULTI-STATE-COMPLIANCE-ENHANCEMENT-CATALOG.md and authored at specs/pf/enhancements/PF-96-EN-RECORDING-recording-consent-jurisdiction-fields.md. PF-100 Phase 0 includes the corresponding migration.
8A. PF-71 dependency contract (patient-name list lookup)
Spec §FR-3.4 (co-attendee de-identification) requires a server-side patient-name list lookup to verify that AI-generated draft text does not leak names of patients who are NOT the subject of record (e.g. group-session co-attendees). Expected API (PF-71 to provide; consumed bypf-transcription-generate-note edge function):
- Returns first/last/preferred names + phonetic/common-misspelling variants for every patient in scope.
- Excludes the subject-of-record (caller passes
subject_of_record_idseparately). - Server-side only — never invoked from the browser.
- Names are used solely for redaction matching; PF-100 MUST NOT log returned names. Edge function logs only counts (
{ matched_count: N }).
pf_71_patient_name_list(). Tracked in PF-100-TASKS.md Phase 0 prerequisites.
9. PF-91 evidence emission contract
For every attested session, PF-100 emits structured evidence:- Part 2 control evidence (
is_part2_program=trueonly): consent record id + version, segregation hash (Part 2 KMS alias confirmation), retention proof, deletion proof. - All-party consent control evidence: per-participant consent acknowledgment timestamps, jurisdiction profile id, recording-indicator-shown proof.
- Retention control evidence: applied retention policy, scheduled deletion date, actual deletion timestamp.
- BAA-coverage control evidence: vendor id, BAA evidence id, model version, call counts.
pf_compliance_evidence (PF-91) with source='pf-100-transcription' and evidence_kind per row above.
10. Audit & enforcement
npm run audit:integration-contracts— verifies this file is referenced from PF-100 specnpm run audit:permissions— verifies all keys in PF-100 §6 are seedednpm run audit:routes-navigation— verifies any new routes (e.g./platform/transcription/sessions,/platform/transcription/review) are registered
11. Backlinks
- Spec: PF-100
- Predecessor: CL-36, CL-36-EN-01
- Predecessor integration:
CL-36-ai-documentation-INTEGRATION.md - Jurisdiction:
PF-96-medicaid-state-compliance-configuration-INTEGRATION.md - Cross-core matrix:
CROSS_CORE_INTEGRATIONS.md - Architecture decisions:
ADR-002-cl-pm-cross-core-foreign-keys.md
Activating a Vendor (Runbook)
Until these four steps are completed for at least one STT vendor, every call topf-transcription-stt-streamreturns409 vendor_baa_inactive. LLM note generation works today via Lovable AI Gateway (no BAA gate).
- Sign the BAA — paper artifact between the org and the vendor (Deepgram / AssemblyAI / AWS). Cannot be code-completed.
- Register the BAA row in
pf_transcription_vendor_baas:Use the Settings → Transcription → Vendors UI (VendorBaaTable) instead of raw SQL when possible. - Add the API key to PF-76 vault under the credential name expected by the adapter (e.g.
deepgram_api_key). The router callspf_retrieve_credential(org_id, name); missing keys surface asvendor_baa_inactivewithreason: 'missing_credential'. - (Optional) Add a routing rule in
pf_transcription_jurisdiction_routingso a specific(jurisdiction_code, recording_channel)resolves to this vendor instead of the org default.
JurisdictionRoutingDialog shows a live resolver preview so admins can confirm routing before saving. The VendorBaaTable displays a green/amber/red status dot per BAA so live status is visible at a glance.
PF-100-EN-01 — Ambient Vendor-BAA Enablement Runbook
PF-100-EN-01 is an operational enhancement to PF-100 (Platform Ambient Transcription & AI Note Generation) that adds the vendor-BAA procurement runbook: operators record executed BAA agreements intopf_transcription_vendor_baas, provision per-tenant AWS KMS aliases for Part-2 audio segregation, and complete the PF-96 recording-law jurisdiction profile so that the fail-closed vendor gate opens only for fully BAA-covered vendors. This enhancement operates entirely within the existing PF-100 integration surface documented above — it introduces no new cross-core contracts, no new events, and no new consumer-side APIs; all behavioural changes are internal to the PF transcription substrate.