Browse documentation

AI Services

RankFlow AI — Medical Compliance & Safety Guardrails

Version: 2.0.0

docs/specs/ai/ai-services-06-compliance.md
On this page

Version: 2.0.0 Date: 2026-06-16 Scope: Medical compliance filters, safety guardrails, banned phrase detection, content approval gates, HIPAA considerations, disclaimer system, and audit trails Target Audience: AI Engineers, Compliance Officers, Content Strategists, Legal Team Service Path: src/server/services/ai/compliance/, src/server/services/ai/safety/


1. Compliance Philosophy#

1.1 Non-Negotiable Rules#

# Rule Enforcement
1 No medical claims without evidence Auto-reject + flag
2 No guaranteed cure promises Auto-reject + alert
3 Medical content requires disclaimer Auto-append if missing
4 Medical content requires human review 24h approval queue
5 All banned phrases are blocked Regex + keyword scan
6 All compliance failures are logged Permanent audit trail
7 No PHI in AI prompts PII detection + sanitization
8 AI-generated medical content is advisory only Disclaimer system

1.2 Compliance Layers#

┌─────────────────────────────────────────────────────────────┐
│                    COMPLIANCE DEFENSE IN DEPTH              │
│                                                              │
│  Layer 1: Prompt-Level Prevention                            │
│  ├─ System prompt includes compliance rules                  │
│  ├─ Negative constraints ("Do NOT use...")                    │
│  └─ Example: "Never claim guaranteed cures"                 │
│                                                              │
│  Layer 2: Generation-Time Filtering                            │
│  ├─ Banned phrase regex scan (fast, < 1ms)                   │
│  ├─ Medical keyword detection                               │
│  └─ Real-time blocking of problematic content               │
│                                                              │
│  Layer 3: Post-Generation Compliance Check                   │
│  ├─ LLM-as-judge compliance evaluation                       │
│  ├─ Medical claim verification                              │
│  └─ False claim detection                                    │
│                                                              │
│  Layer 4: Human Review Gate                                  │
│  ├─ All medical content queued for 24h review               │
│  ├─ Admin approval required before publish                   │
│  └─ Rejection triggers regeneration                          │
│                                                              │
│  Layer 5: Publication Safeguards                              │
│  ├─ Disclaimer auto-appended to medical content              │
│  ├─ No-edit protection (content can't be modified post-approval)│
│  └─ Version control (all changes tracked)                    │
│                                                              │
│  Layer 6: Monitoring & Audit                                 │
│  ├─ Real-time compliance metrics dashboard                   │
│  ├─ Alert on any compliance failure                          │
│  └─ Monthly compliance audit report                          │
└─────────────────────────────────────────────────────────────┘

2. Medical Compliance Framework#

2.1 Medical Practice Categories#

All practices are categorized by medical sensitivity:

Category Examples Compliance Level Human Review Required
High-Risk Hospitals, Surgical Centers, Oncology Strict Always (24h queue)
Medium-Risk Dental Clinics, Dermatology, Physiotherapy Standard Yes (if medical claims)
Low-Risk General Clinics, Wellness Centers, Ayurveda Standard Yes (if medical claims)
Non-Medical Restaurants, Retail, Schools, IT Services Minimal No (unless edge case)

2.2 Medical Practice Detection#

// src/server/services/ai/compliance/detection.ts

// Medical practice detection based on category and keywords:
const MEDICAL_CATEGORIES = [
  "CLINIC", "HOSPITAL", "DOCTOR", "DENTAL", "DENTIST",
  "PHYSIOTHERAPY", "PHYSIOTHERAPIST", "DERMATOLOGY", "DERMATOLOGIST",
  "ONCOLOGY", "ONCOLOGIST", "CARDIOLOGY", "CARDIOLOGIST",
  "ORTHOPEDICS", "ORTHOPEDIST", "PEDIATRICS", "PEDIATRICIAN",
  "GYNECOLOGY", "GYNECOLOGIST", "OPHTHALMOLOGY", "OPHTHALMOLOGIST",
  "ENT", "ENT_SPECIALIST", "NEUROLOGY", "NEUROLOGIST",
  "PSYCHIATRY", "PSYCHIATRIST", "PSYCHOLOGY", "PSYCHOLOGIST",
  "AYURVEDA", "AYURVEDIC", "HOMEOPATHY", "HOMEOPATH",
  "NATUROPATHY", "WELLNESS", "REHABILITATION", "DIAGNOSTIC_CENTER",
  "PATHOLOGY", "RADIOLOGY", "PHARMACY", "MEDICAL_STORE",
  "NURSING_HOME", "CARE_CENTER", "MATERNITY",
];

const MEDICAL_KEYWORDS = [
  "treatment", "cure", "medicine", "medication", "diagnosis",
  "surgery", "operation", "procedure", "therapy", "therapeutic",
  "healing", "patient", "doctor", "physician", "specialist",
  "prescription", "drug", "dose", "dosage", "side effect",
  "symptom", "disease", "condition", "disorder", "syndrome",
  "chronic", "acute", "severe", "mild", "moderate",
  "recovery", "rehabilitation", "prognosis", "diagnosis",
];

function isMedicalPractice(practice: Practice): boolean {
  // Check category
  if (MEDICAL_CATEGORIES.includes(practice.category.toUpperCase())) {
    return true;
  }
  
  // Check service names
  if (practice.services.some(s => 
    MEDICAL_KEYWORDS.some(kw => s.name.toLowerCase().includes(kw))
  )) {
    return true;
  }
  
  // Check brand keywords
  if (practice.brandKeywords.some(kw =>
    MEDICAL_KEYWORDS.some(mk => kw.toLowerCase().includes(mk))
  )) {
    return true;
  }
  
  return false;
}

// Content-level medical detection:
function containsMedicalClaims(content: string): boolean {
  const medicalPatterns = [
    /\b(treat|treatment|treating)\b.*\b(cure|curing|heal|healing)\b/,
    /\b(diagnose|diagnosis|diagnosing)\b/,
    /\b(surgery|surgical|operation|operative)\b/,
    /\b(medicine|medication|drug|prescription)\b/,
    /\b(side effect|side effects|adverse effect)\b/,
    /\b(symptom|symptoms|sign|signs)\b/,
    /\b(disease|diseases|condition|conditions|disorder)\b/,
  ];
  
  return medicalPatterns.some(pattern => pattern.test(content.toLowerCase()));
}

3. Banned Phrase Detection#

3.1 Banned Phrase Registry#

// src/server/services/ai/compliance/banned-phrases.ts

interface BannedPhrase {
  phrase: string;
  severity: "CRITICAL" | "HIGH" | "MEDIUM" | "LOW";
  category: "medical_claim" | "guarantee" | "false_promise" | "superlative" | "sensitive";
  action: "REJECT" | "FLAG" | "WARN";
  reason: string;
  alternatives?: string[]; // Suggested alternatives
}

const BANNED_PHRASES: BannedPhrase[] = [
  // CRITICAL: Medical claims without evidence
  { phrase: "guaranteed cure", severity: "CRITICAL", category: "medical_claim", action: "REJECT", reason: "Cannot guarantee medical outcomes" },
  { phrase: "100% success", severity: "CRITICAL", category: "guarantee", action: "REJECT", reason: "No medical procedure has 100% success rate" },
  { phrase: "permanent fix", severity: "CRITICAL", category: "guarantee", action: "REJECT", reason: "Medical outcomes are not permanent guarantees" },
  { phrase: "no side effects", severity: "CRITICAL", category: "false_promise", action: "REJECT", reason: "All medical procedures have potential side effects" },
  { phrase: "miracle treatment", severity: "CRITICAL", category: "medical_claim", action: "REJECT", reason: "Miracle claims are unsubstantiated" },
  { phrase: "instant results", severity: "CRITICAL", category: "false_promise", action: "REJECT", reason: "Medical results take time" },
  { phrase: "never fails", severity: "CRITICAL", category: "guarantee", action: "REJECT", reason: "No treatment never fails" },
  { phrase: "completely safe", severity: "CRITICAL", category: "false_promise", action: "REJECT", reason: "No procedure is completely risk-free" },
  { phrase: "risk-free", severity: "CRITICAL", category: "false_promise", action: "REJECT", reason: "Medical procedures carry risks" },
  { phrase: "doctor recommended", severity: "CRITICAL", category: "medical_claim", action: "REJECT", reason: "Must attribute to specific doctor if used" },
  
  // HIGH: Strong superlatives without evidence
  { phrase: "best in", severity: "HIGH", category: "superlative", action: "FLAG", reason: "Superlative requires evidence", alternatives: ["highly rated", "well-regarded", "trusted by many"] },
  { phrase: "most advanced", severity: "HIGH", category: "superlative", action: "FLAG", reason: "Requires evidence of advancement", alternatives: ["modern", "up-to-date", "latest technology"] },
  { phrase: "most experienced", severity: "HIGH", category: "superlative", action: "FLAG", reason: "Requires evidence of experience", alternatives: ["experienced", "skilled", "well-trained"] },
  { phrase: "number one", severity: "HIGH", category: "superlative", action: "FLAG", reason: "Requires ranking evidence", alternatives: ["leading", "top-rated", "highly recommended"] },
  { phrase: "top-rated", severity: "HIGH", category: "superlative", action: "FLAG", reason: "Requires rating evidence", alternatives: ["well-rated", "positively reviewed", "appreciated by patients"] },
  
  // MEDIUM: Potentially misleading
  { phrase: "cheap", severity: "MEDIUM", category: "sensitive", action: "WARN", reason: "May imply low quality", alternatives: ["affordable", "cost-effective", "budget-friendly"] },
  { phrase: "discount", severity: "MEDIUM", category: "sensitive", action: "WARN", reason: "May devalue services", alternatives: ["special offer", "promotion", "limited-time savings"] },
  { phrase: "free consultation", severity: "MEDIUM", category: "sensitive", action: "WARN", reason: "Ensure consultation is truly free", alternatives: ["complimentary consultation", "no-obligation consultation"] },
  { phrase: "quick fix", severity: "MEDIUM", category: "false_promise", action: "WARN", reason: "Medical issues require proper treatment", alternatives: ["effective treatment", "efficient care", "timely solution"] },
  
  // LOW: Style preferences
  { phrase: "in today's world", severity: "LOW", category: "sensitive", action: "WARN", reason: "Generic opening phrase", alternatives: ["nowadays", "currently", "in modern practice"] },
  { phrase: "we are a", severity: "LOW", category: "sensitive", action: "WARN", reason: "Generic AI-sounding opening", alternatives: ["At [Practice Name], we", "[Practice Name] offers"] },
];

// Regex compilation for fast matching:
const BANNED_PHRASE_REGEX = new RegExp(
  BANNED_PHRASES.map(bp => `\\b${bp.phrase.replace(/\s+/g, '\\s+')}\\b`).join('|'),
  'gi'
);

3.2 Banned Phrase Detection Algorithm#

// Fast detection (< 1ms for typical content):
function detectBannedPhrases(content: string): DetectionResult {
  const matches: BannedPhraseMatch[] = [];
  
  for (const phrase of BANNED_PHRASES) {
    const regex = new RegExp(`\\b${phrase.phrase.replace(/\s+/g, '\\s+')}\\b`, 'gi');
    const match = regex.exec(content);
    
    if (match) {
      matches.push({
        phrase: phrase.phrase,
        severity: phrase.severity,
        category: phrase.category,
        action: phrase.action,
        reason: phrase.reason,
        position: match.index,
        alternatives: phrase.alternatives,
      });
    }
  }
  
  const hasCritical = matches.some(m => m.severity === "CRITICAL");
  const hasReject = matches.some(m => m.action === "REJECT");
  
  return {
    matches,
    passed: !hasReject,
    severity: hasCritical ? "CRITICAL" : matches.some(m => m.severity === "HIGH") ? "HIGH" : "MEDIUM",
    requiresAction: hasReject || matches.some(m => m.action === "FLAG"),
  };
}

// Auto-correction (for non-critical matches):
function autoCorrectBannedPhrases(content: string): string {
  let corrected = content;
  
  for (const phrase of BANNED_PHRASES) {
    if (phrase.action === "WARN" && phrase.alternatives) {
      const regex = new RegExp(`\\b${phrase.phrase.replace(/\s+/g, '\\s+')}\\b`, 'gi');
      corrected = corrected.replace(regex, phrase.alternatives[0]);
    }
  }
  
  return corrected;
}

4. Content Approval Gates#

4.1 Approval Gate Architecture#

┌─────────────────────────────────────────────────────────────┐
│                    CONTENT APPROVAL GATES                   │
│                                                              │
│  Gate 1: Auto-Generation (AI)                                │
│  ├─ Content generated by AI                                  │
│  ├─ Initial quality score calculated                        │
│  └─ Compliance check performed                              │
│                                                              │
│  Gate 2: Auto-Evaluation (Automated)                         │
│  ├─ Banned phrase scan → PASS / FAIL                        │
│  ├─ Medical claim detection → PASS / FLAG                   │
│  ├─ Quality score → ≥ 70 PASS, < 70 QUEUE                   │
│  └─ Compliance status → PASS / WARN / FAIL                  │
│                                                              │
│  Gate 3: Auto-Approval (Non-Medical)                         │
│  ├─ If non-medical + score ≥ 70 → AUTO-PUBLISH              │
│  ├─ If non-medical + score 60-69 → AUTO-PUBLISH + FLAG      │
│  └─ If non-medical + score < 60 → QUEUE for review           │
│                                                              │
│  Gate 4: Medical Review Queue (Medical)                      │
│  ├─ If medical content → ALWAYS queue for 24h review        │
│  ├─ Admin receives notification (email + Slack)              │
│  ├─ Admin reviews in dashboard                               │
│  └─ Admin approves / rejects / edits                        │
│                                                              │
│  Gate 5: SLA Auto-Resolution                                 │
│  ├─ If 24h passes and no admin action:                       │
│  │   ├─ Score ≥ 80 → AUTO-PUBLISH                           │
│  │   └─ Score < 80 → AUTO-REJECT + ALERT                    │
│  └─ Admin can override auto-resolution                       │
│                                                              │
│  Gate 6: Publication                                         │
│  ├─ Content published to platform (GBP, social, website)     │
│  ├─ Disclaimer auto-appended (if medical)                    │
│  └─ Audit log created                                         │
└─────────────────────────────────────────────────────────────┘

4.2 Approval State Machine#

// Content approval states:
enum ContentApprovalStatus {
  DRAFT = "draft",                    // AI generated, not yet evaluated
  PENDING_EVALUATION = "pending_evaluation", // Automated evaluation in progress
  PENDING_REVIEW = "pending_review", // Queued for human review
  APPROVED = "approved",              // Human approved
  REJECTED = "rejected",              // Human rejected or auto-rejected
  AUTO_PUBLISHED = "auto_published",   // Auto-published (non-medical, score ≥ 70)
  SLA_AUTO_PUBLISHED = "sla_auto_published", // Auto-published after 24h SLA
  SLA_AUTO_REJECTED = "sla_auto_rejected", // Auto-rejected after 24h SLA (score < 80)
  PUBLISHED = "published",            // Live on platform
  EDITED = "edited",                  // Edited after approval, needs re-review
  ARCHIVED = "archived",              // No longer active
}

// State transitions:
// DRAFT → PENDING_EVALUATION (auto)
// PENDING_EVALUATION → PENDING_REVIEW (if medical or score < 70)
// PENDING_EVALUATION → AUTO_PUBLISHED (if non-medical and score ≥ 70)
// PENDING_REVIEW → APPROVED (admin action)
// PENDING_REVIEW → REJECTED (admin action)
// PENDING_REVIEW → SLA_AUTO_PUBLISHED (24h passed, score ≥ 80)
// PENDING_REVIEW → SLA_AUTO_REJECTED (24h passed, score < 80)
// APPROVED → PUBLISHED (auto, after approval)
// AUTO_PUBLISHED → PUBLISHED (auto)
// PUBLISHED → EDITED (if content modified)
// EDITED → PENDING_REVIEW (re-queue for review)

4.3 Approval SLA Configuration#

const APPROVAL_SLA = {
  medical: {
    reviewWindow: 24 * 60 * 60 * 1000, // 24 hours
    autoPublishThreshold: 80, // Score ≥ 80 auto-publishes after SLA
    autoRejectThreshold: 60,  // Score < 60 auto-rejects after SLA
    notifyBefore: 4 * 60 * 60 * 1000, // Notify 4 hours before SLA
    escalationAfter: 12 * 60 * 60 * 1000, // Escalate to manager after 12h
  },
  nonMedical: {
    reviewWindow: 24 * 60 * 60 * 1000, // 24 hours (optional review)
    autoPublishThreshold: 70, // Score ≥ 70 auto-publishes immediately
    autoPublishWithFlag: 60,  // Score 60-69 auto-publishes with flag
    queueBelow: 60,         // Score < 60 queues for review
  },
};

// Notification schedule for medical content:
// - T+0: Content queued, notification sent (email + Slack)
// - T+4h: Reminder notification (if not reviewed)
// - T+12h: Escalation notification (to manager + admin)
// - T+20h: Final reminder (before SLA auto-resolution)
// - T+24h: Auto-publish (if score ≥ 80) or auto-reject (if score < 80)

5. Medical Disclaimer System#

5.1 Disclaimer Templates#

// src/server/services/ai/compliance/disclaimers.ts

interface DisclaimerTemplate {
  id: string;
  name: string;
  content: string;
  applicableTo: string[]; // Categories or task types
  placement: "beginning" | "end" | "inline";
  priority: number;
}

const DISCLAIMER_TEMPLATES: DisclaimerTemplate[] = [
  {
    id: "medical-general",
    name: "General Medical Disclaimer",
    content: "This information is for educational purposes only and does not constitute medical advice. Consult a qualified healthcare professional for personalized diagnosis and treatment.",
    applicableTo: ["CLINIC", "HOSPITAL", "DOCTOR", "DENTAL", "DENTIST"],
    placement: "end",
    priority: 1,
  },
  {
    id: "medical-treatment",
    name: "Treatment Disclaimer",
    content: "Individual results may vary. The effectiveness of treatment depends on various factors including individual health conditions. Consult your doctor for personalized advice.",
    applicableTo: ["CLINIC", "HOSPITAL", "DOCTOR"],
    placement: "end",
    priority: 2,
  },
  {
    id: "dental-general",
    name: "Dental Disclaimer",
    content: "Dental procedures and outcomes vary by individual. This information is for general awareness only. Please consult a licensed dentist for a proper evaluation and treatment plan.",
    applicableTo: ["DENTAL", "DENTIST"],
    placement: "end",
    priority: 1,
  },
  {
    id: "ayurveda-general",
    name: "Ayurveda Disclaimer",
    content: "Ayurvedic treatments are complementary wellness practices. They are not a substitute for modern medical care. Consult a qualified physician for serious health conditions.",
    applicableTo: ["AYURVEDA", "AYURVEDIC"],
    placement: "end",
    priority: 1,
  },
  {
    id: "wellness-general",
    name: "Wellness Disclaimer",
    content: "Wellness programs and advice are for general health improvement. They are not medical treatments. Consult a healthcare provider for medical conditions.",
    applicableTo: ["WELLNESS", "NATUROPATHY", "REHABILITATION"],
    placement: "end",
    priority: 1,
  },
  {
    id: "pharmacy-general",
    name: "Pharmacy Disclaimer",
    content: "Medication information is for educational purposes. Always consult a pharmacist or doctor before taking any medication. Do not self-medicate.",
    applicableTo: ["PHARMACY", "MEDICAL_STORE"],
    placement: "end",
    priority: 1,
  },
];

// Disclaimer auto-appending logic:
function appendDisclaimer(content: string, practice: Practice): string {
  const template = DISCLAIMER_TEMPLATES.find(t => 
    t.applicableTo.includes(practice.category.toUpperCase())
  );
  
  if (!template) return content;
  
  // Check if content already has disclaimer
  if (content.includes(template.content.substring(0, 50))) {
    return content; // Already has disclaimer
  }
  
  // Append disclaimer
  if (template.placement === "end") {
    return `${content}\n\n---\n\n**Disclaimer:** ${template.content}`;
  }
  
  if (template.placement === "beginning") {
    return `**Disclaimer:** ${template.content}\n\n---\n\n${content}`;
  }
  
  return content;
}

5.2 Disclaimer Placement Rules#

Content Type Disclaimer Placement Required?
Landing Page Hero End of page Yes (if medical)
Landing Page About End of section Yes (if medical)
Landing Page Services End of each service description Yes (if treatment-related)
Landing Page FAQ End of each medical answer Yes (if medical)
Blog Post End of article Yes (if medical)
GBP Post End of post Yes (if medical)
Social Post Last sentence or comment Yes (if medical)
Review Reply Not needed (reply is not medical advice) No
Citation Description Not needed (directory listing) No
Email End of email Yes (if medical)

6. HIPAA & Data Privacy#

6.1 HIPAA Considerations#

// HIPAA compliance for AI content generation:

// 1. NO PHI in AI prompts
// - Never include patient names, addresses, phone numbers, emails
// - Never include medical record numbers, insurance IDs
// - Never include specific diagnosis or treatment details of real patients
// - Use synthetic/fictional examples only

// 2. Prompt Sanitization
function sanitizePromptForHIPAA(prompt: string): string {
  // Remove potential PHI patterns:
  const phiPatterns = [
    /\b\d{3}-\d{2}-\d{4}\b/g, // SSN
    /\b\d{10}\b/g, // Phone numbers (10 digit)
    /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g, // Emails
    /\b[A-Z]{2}\d{6}\b/g, // Indian PIN codes (might be part of address)
    /\bpatient\s+(?:name|id|number|record)\s*:?\s*\w+/gi, // Patient references
  ];
  
  let sanitized = prompt;
  for (const pattern of phiPatterns) {
    sanitized = sanitized.replace(pattern, "[REDACTED]");
  }
  
  return sanitized;
}

// 3. Data Handling
// - AI provider APIs (OpenAI, Anthropic, Google) are HIPAA-compliant?
//   → No, they are NOT HIPAA-compliant by default
//   → Solution: Use Business Associate Agreements (BAAs) if required
//   → Alternative: Self-hosted models (if HIPAA compliance is mandatory)
//   → Current approach: No PHI in prompts, so HIPAA compliance is not required
//     for AI generation. PHI is handled in the application layer (database),
//     which is HIPAA-compliant.

// 4. Audit Trail
// - All AI interactions are logged (without PHI)
// - Logs include: task type, model, cost, timestamp, practice ID (not patient ID)
// - Logs are retained for 6 years (HIPAA requirement)

6.2 Data Privacy in AI Generation#

Data Type In AI Prompt? Risk Level Mitigation
Practice name Yes Low Public information
Practice address Yes Low Public information
Practice phone Yes Low Public information
Practice services Yes Low Public information
Patient names No High Never include
Patient contact info No High Never include
Patient medical history No High Never include
Reviewer names (from reviews) Yes Medium Public, but anonymize if sensitive
Review content Yes Medium Public, but sanitize if contains PHI
Appointment details No High Never include
Payment information No High Never include

7. Compliance Evaluation Pipeline#

7.1 Compliance Pipeline Steps#

┌─────────────────────────────────────────────────────────────┐
│                    COMPLIANCE EVALUATION PIPELINE            │
│                                                              │
│  Step 1: Fast Heuristic Checks (local, no LLM)              │
│  ├─ Banned phrase scan (regex, < 1ms)                       │
│  ├─ Medical keyword detection (< 1ms)                        │
│  ├─ Length and format validation (< 1ms)                     │
│  ├─ Disclaimer presence check (if medical, < 1ms)          │
│  └─ Superlative detection (< 1ms)                            │
│  If any CRITICAL fail → REJECT immediately                   │
│  If any HIGH/MEDIUM fail → FLAG for review                   │
│                                                              │
│  Step 2: LLM-as-Judge Compliance Check                        │
│  ├─ Model: Claude Haiku (~$0.002)                            │
│  ├─ Evaluates:                                              │
│  │   ├─ Medical claim accuracy                              │
│  │   ├─ False promise detection                             │
│  │   ├─ Superlative substantiation                          │
│  │   ├─ Cultural sensitivity                                 │
│  │   └─ Overall compliance score                             │
│  └─ Output: Compliance score (0-100) + issues list          │
│                                                              │
│  Step 3: Auto-Correction (for non-critical issues)           │
│  ├─ Replace banned phrases with alternatives                 │
│  ├─ Add disclaimer if missing (medical content)             │
│  ├─ Adjust superlatives ("best" → "highly rated")          │
│  └─ Re-evaluate after correction                            │
│                                                              │
│  Step 4: Decision                                            │
│  ├─ Compliance score ≥ 90 + no CRITICAL → PASS              │
│  ├─ Compliance score 70-89 + no CRITICAL → PASS with WARN   │
│  ├─ Compliance score 60-69 → QUEUE for human review          │
│  └─ Compliance score < 60 or CRITICAL → REJECT               │
│                                                              │
│  Step 5: Audit & Logging                                       │
│  ├─ Log compliance score and issues                          │
│  ├─ Log any auto-corrections made                            │
│  └─ Update compliance metrics dashboard                      │
└─────────────────────────────────────────────────────────────┘

7.2 Compliance Judge Prompt#

## TASK: Compliance Evaluation

Evaluate the following content for legal and medical compliance.

### Content:
"""{{content}}"""

### Context:
- Practice: {{practiceName}} ({{category}})
- Medical Content: {{isMedical}}
- Target Audience: {{targetAudience}}

### Evaluation Criteria:

#### 1. Banned Phrases (CRITICAL)
- Does the content contain any banned phrases?
- Banned phrases include: "guaranteed cure", "100% success", "permanent fix", "no side effects", "miracle treatment", "instant results", "never fails", "completely safe", "risk-free"
- Score: 100 if none, 0 if any present

#### 2. Medical Claims (HIGH)
- Does the content make unsubstantiated medical claims?
- Does it claim to treat, cure, or diagnose conditions without evidence?
- Does it mention specific medications or treatments without context?
- Score: 100 if no claims, 50 if claims are vague, 0 if claims are specific and unsubstantiated

#### 3. Superlatives (MEDIUM)
- Does the content use superlatives ("best", "most advanced", "top-rated") without evidence?
- Are superlatives substantiated with data or attribution?
- Score: 100 if no superlatives or substantiated, 50 if unsubstantiated superlatives, 0 if misleading

#### 4. Disclaimers (HIGH for medical)
- Does medical content include appropriate disclaimers?
- Is the disclaimer visible and clear?
- Score: 100 if disclaimer present, 0 if missing (for medical content)

#### 5. Cultural Sensitivity (MEDIUM)
- Is the content culturally appropriate for the target audience?
- Does it avoid stereotypes or insensitive references?
- Score: 100 if appropriate, 50 if minor issues, 0 if major issues

#### 6. False Promises (CRITICAL)
- Does the content make promises that can't be kept?
- Does it set unrealistic expectations?
- Score: 100 if no false promises, 0 if any present

### Output Format (JSON):
{
  "bannedPhrases": { "score": 100, "issues": [] },
  "medicalClaims": { "score": 100, "issues": [] },
  "superlatives": { "score": 100, "issues": [] },
  "disclaimers": { "score": 100, "issues": [] },
  "culturalSensitivity": { "score": 100, "issues": [] },
  "falsePromises": { "score": 100, "issues": [] },
  "overall": 100,
  "status": "PASS | WARN | FAIL",
  "action": "AUTO_PUBLISH | QUEUE | REJECT",
  "issues": []
}

8. Alert & Escalation System#

8.1 Alert Thresholds#

Alert Type Threshold Channel Recipients Action
CRITICAL: Banned Phrase Any CRITICAL match Slack + Email Admin + Compliance Officer Auto-reject + investigate
HIGH: Compliance Score < 60 Content score < 60 Slack Admin Queue for review
MEDIUM: Compliance Score 60-70 Content score 60-70 Email Admin Flag for review
MEDIUM: Missing Disclaimer Medical content without disclaimer Slack Admin Auto-append + notify
LOW: Superlative Unsubstantiated "Best" without evidence Log only Flag in dashboard
SLA: Review Pending > 20h 20 hours without review Slack + Email Admin + Manager Escalate
SLA: Review Pending > 24h 24 hours without review Slack + Email + SMS Admin + Manager + On-call Auto-resolve + alert
SYSTEM: Compliance Rate < 95% System-wide compliance < 95% Slack Admin + Engineering Investigate
SYSTEM: Banned Phrase Rate > 1% > 1% of content triggers banned phrases Slack Admin + Compliance Review templates

8.2 Escalation Matrix#

┌─────────────────────────────────────────────────────────────┐
│                    ESCALATION MATRIX                         │
│                                                              │
│  Level 1: Automated Alert                                    │
│  ├─ Channel: Slack (#ai-compliance)                          │
│  ├─ Recipients: Content Admin                               │
│  └─ Action: Auto-reject, queue for review, or flag            │
│                                                              │
│  Level 2: Admin Notification (4 hours)                       │
│  ├─ Channel: Email + Slack                                   │
│  ├─ Recipients: Content Admin + Practice Manager            │
│  └─ Action: Reminder to review pending content                │
│                                                              │
│  Level 3: Manager Escalation (12 hours)                       │
│  ├─ Channel: Email + Slack + In-app                           │
│  ├─ Recipients: Content Admin + Department Manager            │
│  └─ Action: Escalation, request immediate attention           │
│                                                              │
│  Level 4: Auto-Resolution (24 hours)                          │
│  ├─ Channel: Email + Slack                                    │
│  ├─ Recipients: All above + On-call Engineer                │
│  └─ Action: Auto-publish (score ≥ 80) or auto-reject         │
│                                                              │
│  Level 5: Critical Incident (> 5 compliance failures/hour)  │
│  ├─ Channel: PagerDuty + Slack + Email + SMS                │
│  ├─ Recipients: On-call + Engineering Lead + Compliance Officer│
│  └─ Action: Emergency review, potential system pause          │
└─────────────────────────────────────────────────────────────┘

8.3 Alert Messages#

// Slack alert for banned phrase detection:
const BANNED_PHRASE_ALERT = {
  text: "🚨 CRITICAL: Banned Phrase Detected",
  attachments: [
    {
      color: "danger",
      fields: [
        { title: "Practice", value: "{{practiceName}}", short: true },
        { title: "Task", value: "{{taskType}}", short: true },
        { title: "Phrase", value: "{{bannedPhrase}}", short: false },
        { title: "Severity", value: "{{severity}}", short: true },
        { title: "Action", value: "{{action}}", short: true },
        { title: "Content Preview", value: "{{contentPreview}}", short: false },
      ],
      actions: [
        { name: "review", text: "Review Content", type: "button", url: "{{reviewUrl}}" },
        { name: "regenerate", text: "Regenerate", type: "button", url: "{{regenerateUrl}}" },
      ],
    },
  ],
};

// Slack alert for SLA breach:
const SLA_BREACH_ALERT = {
  text: "⚠️ SLA Breach: Content Review Pending > 24h",
  attachments: [
    {
      color: "warning",
      fields: [
        { title: "Practice", value: "{{practiceName}}", short: true },
        { title: "Content Type", value: "{{contentType}}", short: true },
        { title: "Queued At", value: "{{queuedAt}}", short: true },
        { title: "Auto-Action", value: "{{autoAction}}", short: true },
      ],
      actions: [
        { name: "review", text: "Review Now", type: "button", url: "{{reviewUrl}}" },
        { name: "override", text: "Override Auto-Action", type: "button", url: "{{overrideUrl}}" },
      ],
    },
  ],
};

9. Compliance Audit Trail#

9.1 Audit Trail Requirements#

Every compliance-related action is logged with:

Field Description Retention
Timestamp When the action occurred 6 years
Action What was done (reject, approve, flag, auto-correct) 6 years
Content ID Which content was affected 6 years
Practice ID Which practice 6 years
User ID Who performed the action (or "system") 6 years
Reason Why the action was taken 6 years
Original Content The content before action (first 500 chars) 6 years
Compliance Score Score at the time of action 6 years
Issues List of compliance issues found 6 years
Model Used Which AI model generated the content 6 years
Prompt Version Which prompt template was used 6 years

9.2 Audit Trail Queries#

// Common audit queries:

// 1. All compliance failures in the last 30 days:
// SELECT * FROM ai_compliance_audit 
// WHERE action IN ('REJECT', 'FLAG') 
// AND created_at > NOW() - INTERVAL '30 days'
// ORDER BY created_at DESC;

// 2. Compliance rate by practice:
// SELECT 
//   practice_id,
//   COUNT(*) as total,
//   SUM(CASE WHEN action = 'REJECT' THEN 1 ELSE 0 END) as rejected,
//   (1 - SUM(CASE WHEN action = 'REJECT' THEN 1 ELSE 0 END)::float / COUNT(*)) * 100 as compliance_rate
// FROM ai_compliance_audit
// WHERE created_at > NOW() - INTERVAL '30 days'
// GROUP BY practice_id;

// 3. Most common banned phrases:
// SELECT issue, COUNT(*) as count
// FROM ai_compliance_audit
// WHERE action = 'REJECT'
// AND created_at > NOW() - INTERVAL '30 days'
// GROUP BY issue
// ORDER BY count DESC
// LIMIT 10;

// 4. SLA breach analysis:
// SELECT 
//   practice_id,
//   COUNT(*) as breaches,
//   AVG(EXTRACT(EPOCH FROM (resolved_at - created_at))/3600) as avg_resolution_hours
// FROM ai_compliance_audit
// WHERE sla_breached = true
// AND created_at > NOW() - INTERVAL '30 days'
// GROUP BY practice_id;

9.3 Monthly Compliance Report#

┌─────────────────────────────────────────────────────────────┐
│  Monthly Compliance Report (June 2026)                       │
│                                                              │
│  OVERVIEW                                                    │
│  Total Generations: 1,234                                    │
│  Compliance Pass Rate: 97.8% (▼ 0.5% from May)             │
│  Banned Phrase Detections: 12 (1.0%)                        │
│  Medical Content Reviewed: 156 (100% of medical content)    │
│  SLA Breaches: 3 (1.9% of queued content)                   │
│                                                              │
│  BANNED PHRASE BREAKDOWN                                     │
│  Phrase                    │ Count │ Action                  │
│  ──────────────────────────┼───────┼───────────────────────│
│  "best in"                 │ 4     │ FLAG → Alternative      │
│  "guaranteed cure"         │ 1     │ REJECT → Regenerate   │
│  "100% success"            │ 2     │ REJECT → Regenerate   │
│  "no side effects"         │ 1     │ REJECT → Regenerate   │
│  "quick fix"               │ 4     │ WARN → Alternative      │
│                                                              │
│  COMPLIANCE BY PRACTICE TYPE                                 │
│  Type          │ Generations │ Pass Rate │ Avg Score       │
│  ─────────────┼─────────────┼───────────┼─────────────────│
│  Dental        │ 456         │ 98.2%     │ 85.3            │
│  Hospital      │ 123         │ 96.8%     │ 82.1            │
│  Clinic        │ 234         │ 97.4%     │ 84.5            │
│  Ayurveda      │ 89          │ 95.5%     │ 81.2            │
│  Non-Medical   │ 332         │ 99.1%     │ 88.7            │
│                                                              │
│  IMPROVEMENTS MADE                                          │
│  1. Updated banned phrase list (added 3 new phrases)        │
│  2. Improved dental disclaimer template                     │
│  3. Recalibrated compliance judge for medical claims       │
│  4. Added cultural sensitivity check for vernacular content │
│                                                              │
│  RECOMMENDATIONS                                            │
│  1. Review "best in" template usage (4 flags this month)      │
│  2. Add "quick fix" to auto-correction list                 │
│  3. Improve Ayurveda compliance (lowest pass rate)          │
│  4. Reduce SLA breaches (target: < 1%)                     │
└─────────────────────────────────────────────────────────────┘

10. Database Schema#

-- Compliance Audit Log
CREATE TABLE ai_compliance_audit (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  
  -- Content reference
  content_id UUID NOT NULL,
  content_type VARCHAR(50) NOT NULL,
  practice_id UUID NOT NULL REFERENCES practices(id) ON DELETE CASCADE,
  task_type VARCHAR(50) NOT NULL,
  
  -- Action details
  action VARCHAR(20) NOT NULL, -- REJECT, FLAG, WARN, APPROVE, AUTO_CORRECT, AUTO_PUBLISH, AUTO_REJECT
  reason TEXT NOT NULL,
  
  -- Compliance details
  compliance_score INTEGER,
  banned_phrases JSONB, -- Array of {phrase, severity, position}
  medical_claims_detected BOOLEAN DEFAULT FALSE,
  superlatives_detected JSONB, -- Array of {phrase, position}
  disclaimer_present BOOLEAN DEFAULT FALSE,
  
  -- Content snapshot
  content_preview TEXT NOT NULL, -- First 500 chars
  original_content TEXT, -- Full content if needed
  corrected_content TEXT, -- If auto-corrected
  
  -- AI metadata
  model VARCHAR(50) NOT NULL,
  prompt_version VARCHAR(20) NOT NULL,
  
  -- User/System
  performed_by VARCHAR(50) NOT NULL, -- user_id or "system"
  
  -- SLA
  sla_breached BOOLEAN DEFAULT FALSE,
  sla_deadline TIMESTAMP,
  resolved_at TIMESTAMP,
  
  -- Timestamps
  created_at TIMESTAMP DEFAULT NOW(),
  
  INDEX idx_practice_created (practice_id, created_at),
  INDEX idx_action (action),
  INDEX idx_compliance_score (compliance_score)
);

-- Banned Phrase Detection Log
CREATE TABLE banned_phrase_detections (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  audit_id UUID NOT NULL REFERENCES ai_compliance_audit(id) ON DELETE CASCADE,
  
  phrase VARCHAR(200) NOT NULL,
  severity VARCHAR(20) NOT NULL,
  category VARCHAR(50) NOT NULL,
  action VARCHAR(20) NOT NULL,
  position INTEGER,
  
  suggested_alternative VARCHAR(200),
  auto_corrected BOOLEAN DEFAULT FALSE,
  corrected_to VARCHAR(200),
  
  created_at TIMESTAMP DEFAULT NOW()
);

-- Content Review Queue (medical and flagged content)
CREATE TABLE content_review_queue (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  content_id UUID NOT NULL,
  content_type VARCHAR(50) NOT NULL,
  practice_id UUID NOT NULL REFERENCES practices(id) ON DELETE CASCADE,
  
  -- Content snapshot
  content_preview TEXT NOT NULL,
  full_content TEXT,
  
  -- Generation metadata
  generated_at TIMESTAMP NOT NULL,
  model VARCHAR(50) NOT NULL,
  quality_score INTEGER,
  compliance_score INTEGER,
  
  -- Compliance details
  compliance_issues JSONB,
  banned_phrases JSONB,
  medical_claims_detected BOOLEAN DEFAULT FALSE,
  
  -- Review status
  status VARCHAR(20) NOT NULL DEFAULT "pending", -- pending, approved, rejected, edited, auto_published, auto_rejected
  reviewed_by UUID REFERENCES users(id),
  reviewed_at TIMESTAMP,
  
  -- Human feedback
  human_compliance_score INTEGER,
  human_feedback TEXT,
  edited_content TEXT,
  
  -- SLA
  sla_deadline TIMESTAMP NOT NULL,
  sla_breached BOOLEAN DEFAULT FALSE,
  auto_publish_on_breach BOOLEAN DEFAULT FALSE,
  auto_reject_on_breach BOOLEAN DEFAULT FALSE,
  
  created_at TIMESTAMP DEFAULT NOW()
);

-- Disclaimer Usage Log
CREATE TABLE disclaimer_usage (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  content_id UUID NOT NULL,
  content_type VARCHAR(50) NOT NULL,
  practice_id UUID NOT NULL REFERENCES practices(id) ON DELETE CASCADE,
  
  disclaimer_template_id VARCHAR(50) NOT NULL,
  disclaimer_content TEXT NOT NULL,
  placement VARCHAR(20) NOT NULL, -- beginning, end, inline
  
  auto_appended BOOLEAN DEFAULT FALSE,
  manually_added BOOLEAN DEFAULT FALSE,
  
  created_at TIMESTAMP DEFAULT NOW()
);

-- Compliance Metrics (aggregated)
CREATE TABLE compliance_metrics (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  date DATE NOT NULL,
  practice_id UUID REFERENCES practices(id) ON DELETE CASCADE, -- NULL = system-wide
  
  total_generations INTEGER NOT NULL DEFAULT 0,
  pass_count INTEGER NOT NULL DEFAULT 0,
  reject_count INTEGER NOT NULL DEFAULT 0,
  flag_count INTEGER NOT NULL DEFAULT 0,
  warn_count INTEGER NOT NULL DEFAULT 0,
  auto_correct_count INTEGER NOT NULL DEFAULT 0,
  
  banned_phrase_count INTEGER NOT NULL DEFAULT 0,
  medical_claim_count INTEGER NOT NULL DEFAULT 0,
  superlative_count INTEGER NOT NULL DEFAULT 0,
  disclaimer_missing_count INTEGER NOT NULL DEFAULT 0,
  
  sla_breach_count INTEGER NOT NULL DEFAULT 0,
  avg_resolution_hours DECIMAL(5, 2),
  
  avg_compliance_score DECIMAL(5, 2),
  
  UNIQUE(date, practice_id)
);

End of Medical Compliance & Safety Guardrails Documentation — RankFlow AI v2.0.0