Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Ensure HIPAA compliance when handling PHI (Protected Health Information). Use when writing code that accesses user health data, check-ins, journal entries, or any sensitive information. Activates for audit logging, data access, security events, and compliance questions.
.claude/skills/hipaa-compliance/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-07 | ✗→✓ | ▲ Improved | — | — |
| case-12 | ✗→✓ | ▲ Improved | — | — |
| case-01 | ✗→✓ | ▲ Improved | — | — |
| case-18 | ✗→✓ | ▲ Improved | — | — |
| case-03 | ✗→✓ | ▲ Improved | — | — |
This skill helps you maintain HIPAA compliance when developing features that handle Protected Health Information (PHI).
| Data Type | PHI Status | Handling | |-----------|------------|----------| | Check-in mood/cravings | PHI | Audit all access | | Journal entries | PHI | Audit all access | | Chat conversations | PHI | Audit all access | | User profile (name, email) | PHI | Audit modifications | | Sobriety date | PHI | Audit access | | Emergency contacts | PHI | Audit access | | Usage analytics (aggregated) | NOT PHI | No audit needed | | Page views (no content) | NOT PHI | No audit needed |
Always log these operations:
Use the audit logging utilities in src/lib/hipaa/audit.ts:
typescriptimport { logPHIAccess, logPHIModification, logSecurityEvent, logAdminAction } from '@/lib/hipaa/audit'; // Viewing PHI await logPHIAccess( userId, 'checkin', // targetType checkinId, // targetId AuditAction.PHI_VIEW ); // Modifying PHI await logPHIModification( userId, 'journal', journalId, AuditAction.PHI_UPDATE, { field: 'content' } // Never include actual content! ); // Security event await logSecurityEvent( userId, AuditAction.RATE_LIMIT, { path: '/api/chat', attempts: 60 } ); // Admin action await logAdminAction( adminId, AuditAction.ADMIN_USER_VIEW, 'user', targetUserId );
The audit system automatically sanitizes, but be explicit:
typescript// BAD - Contains PHI await logPHIAccess(userId, 'journal', id, action, { content: journalEntry.content // NEVER DO THIS }); // GOOD - Only metadata await logPHIAccess(userId, 'journal', id, action, { wordCount: journalEntry.content.length, hasAttachments: false });
password, token, secret, keyauthorization, cookie, sessioncredential, content, message, notesFrom src/lib/auth.ts:
typescriptimport { getSession, requireAuth } from '@/lib/auth'; import { logPHIAccess } from '@/lib/hipaa/audit'; export async function GET(request: Request) { const session = await getSession(); if (!session) { return Response.json({ error: 'Unauthorized' }, { status: 401 }); } // Fetch the data const data = await fetchUserData(session.userId); // Log the access await logPHIAccess( session.userId, 'userdata', session.userId, AuditAction.PHI_VIEW ); return Response.json(data); }
typescript'use client'; import { useEffect } from 'react'; export function JournalViewer({ entryId }: { entryId: string }) { useEffect(() => { // Log view on mount (server-side preferred, but client backup) fetch('/api/audit/log', { method: 'POST', body: JSON.stringify({ action: 'PHI_VIEW', targetType: 'journal', targetId: entryId }) }); }, [entryId]); // ... render }
Before shipping any feature that touches PHI:
audit_log table in databaseFor emergency situations, use break-glass access:
typescriptimport { requestBreakGlassAccess } from '@/lib/hipaa/break-glass'; // This creates enhanced audit trail const access = await requestBreakGlassAccess( adminId, targetUserId, 'Emergency support required - user reported crisis' );
Break glass access:
docs/INCIDENT-RESPONSE-PLAN.mddocs/SECURITY-HARDENING.md| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-07 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +55 percentage points is the difference between those two pass rates over the 22 comparable cases.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.