Technical Overview of §164.312(b) Audit Controls
Under the HIPAA Security Rule (45 CFR § 164.312(b)), covered entities and business associates must:
“Implement hardware, software, and/or procedural mechanisms that record and examine activity in information systems that contain or use electronic protected health information (ePHI).”
To pass a HIPAA audit, log entries must be immutable, tamper-evident, and retain records for a minimum of 6 years (per §164.316(b)(2)(i)).
1. Required Audit Event Schema
Every read, write, export, or deletion of ePHI must capture the 6 mandatory audit fields:
- Timestamp: ISO 8601 UTC string with millisecond precision.
- Actor Identifier: User ID, service account, or role triggering the request.
- Action Performed:
READ,CREATE,UPDATE,DELETE,EXPORT, orAUTH_FAILURE. - Target Resource: Unique ID and entity type of the ePHI (e.g.,
patient_record:10492). - Tenant / Organization ID: Multi-tenant isolation boundary.
- Origin & Network Context: IP address, user agent, and request ID.
TypeScript Schema & Cryptographic Chaining
import { createHash } from 'crypto';
export interface AuditLogEntry {
id: string;
tenantId: string;
actorId: string;
actorRole: string;
action: 'PHI_READ' | 'PHI_CREATE' | 'PHI_UPDATE' | 'PHI_DELETE' | 'PHI_EXPORT' | 'AUTH_FAILURE';
resourceType: string;
resourceId: string;
timestamp: string;
ipAddress: string;
userAgent: string;
previousHash: string; // Enables tamper-evident hash chaining
entryHash: string; // SHA-256 (ID + Timestamp + Actor + Action + Target + PrevHash)
}
export class ImmutableAuditLogger {
private lastHash: string = 'GENESIS_BLOCK_HASH_00000000000000000000000000000000';
/**
* Generates a tamper-evident audit record with SHA-256 chain verification
*/
public createAuditEntry(
params: Omit<AuditLogEntry, 'id' | 'timestamp' | 'previousHash' | 'entryHash'>
): AuditLogEntry {
const id = crypto.randomUUID();
const timestamp = new Date().toISOString();
const previousHash = this.lastHash;
const rawPayload = `${id}|${params.tenantId}|${params.actorId}|${params.action}|${params.resourceType}:${params.resourceId}|${timestamp}|${previousHash}`;
const entryHash = createHash('sha256').update(rawPayload).digest('hex');
const entry: AuditLogEntry = {
...params,
id,
timestamp,
previousHash,
entryHash,
};
// Update chain state
this.lastHash = entryHash;
return entry;
}
}
2. Immutable Storage Architecture
Audit logs must never be stored in the same primary database table as standard operational data. If an attacker gains SQL write access, they could alter audit records.
+------------------+ +-------------------+ +-------------------------+
| App Service | ---> | Audit Middleware | ---> | Write-Once S3/WORM Bucket|
| (API / GraphQL) | | (Hash Chain) | | (Object Lock Enforced) |
+------------------+ +-------------------+ +-------------------------+
AWS S3 Object Lock Policy (WORM - Write Once, Read Many)
Enforce AWS S3 Object Lock in Compliance Mode for 6 years to prevent log deletion or modification—even by root AWS accounts:
{
"ObjectLockConfiguration": {
"ObjectLockEnabled": "Enabled",
"Rule": {
"DefaultRetention": {
"Mode": "COMPLIANCE",
"Years": 6
}
}
}
}
3. Automated Chain Integrity Verification Routine
To verify during an auditor inspection that no records have been altered or deleted:
export function verifyAuditChain(logs: AuditLogEntry[]): { valid: boolean; brokenAt?: string } {
let expectedPrevHash = 'GENESIS_BLOCK_HASH_00000000000000000000000000000000';
for (const log of logs) {
if (log.previousHash !== expectedPrevHash) {
return { valid: false, brokenAt: log.id };
}
const rawPayload = `${log.id}|${log.tenantId}|${log.actorId}|${log.action}|${log.resourceType}:${log.resourceId}|${log.timestamp}|${log.previousHash}`;
const computedHash = createHash('sha256').update(rawPayload).digest('hex');
if (computedHash !== log.entryHash) {
return { valid: false, brokenAt: log.id };
}
expectedPrevHash = log.entryHash;
}
return { valid: true };
}
Checklist for HIPAA Audit Log Readiness
- All ePHI access events (GET, POST, PUT, DELETE) generate an audit log.
- Logs are stored in an isolated WORM (Write-Once-Read-Many) storage container.
- Retention rules strictly set to >= 6 years (2,190 days).
- Log streams are integrity-checked using SHA-256 hash chaining.
- Real-time alerts trigger on mass ePHI export attempts or repetitive auth failures.