Assessment Date: March 31, 2026
Version: Pre-Alpha (v0.x)
Assessed By: A.X.I.S. Automated Review
15Controls Implemented
4Critical Gaps
10Roadmap Items
~20hrsEstimated to P1 Complete

1. Where We Are

Implemented & Working

Security Headers (Middleware)

HSTS, X-Frame-Options: DENY, X-Content-Type-Options: nosniff, X-XSS-Protection, Referrer-Policy, Permissions-Policy, and Content Security Policy. All enforced via Next.js middleware on every response.

Authentication System

JWT-based auth via the jose library. Passwords hashed with bcryptjs. Session stored in httpOnly, secure, sameSite cookie. Login/logout endpoints functional.

No PHI in URLs or Error Messages

All routes use UUIDs (patient IDs, session IDs), never patient names, DOB, or emails in URL parameters. Error responses return generic messages.

Cache-Control on PHI Routes

no-store, no-cache, must-revalidate headers set on all /api/patients, /api/intake-sessions, and /api/insurance routes.

Encryption Module Built (AES-256-GCM)

encryption.ts fully implements AES-256-GCM with proper IV handling, auth tags, and field-level encryption for patient PHI and insurance PHI. Functions: encryptPHI(), decryptPHI(), encryptPHIFields(), decryptPHIFields().

Audit Logging Module Built

audit-log.ts defines 25+ audit actions, resource types, and a structured logging format including userId, userRole, practiceId, ipAddress, userAgent, timestamp, action, and success status.

RBAC Module Built

Role hierarchy defined: OWNER > ADMIN > DENTIST > HYGIENIST > FRONT_DESK. Functions hasRole() and requireRole() implemented in auth.ts.

Input Sanitization Module Built

sanitize.ts implements sanitizeText (strips HTML), sanitizeEmail, sanitizePhone, sanitizeDateOfBirth, sanitizeRecord, and validateRequired.

Client-Side Session Timeout

session-timeout.ts implements 15-minute idle detection with warning modal and automatic logout.

PHI Encryption Enforced

All API routes now encrypt PHI on write and decrypt on read via AES-256-GCM. encryptPHIFields() called in every POST/PATCH route, decryptPHIFields() in every GET route. Graceful fallback in dev mode if no encryption key is set.

RBAC Enforced on All Endpoints

requireRole() checks enforced on every PHI route. FRONT_DESK minimum for reads, ADMIN for edits, DENTIST for clinical review. Patient intake (public-facing) bypasses auth as designed.

Input Validation (Zod + Sanitization)

All POST/PATCH routes validate request bodies with Zod schemas and sanitize all string inputs via sanitizeText, sanitizeEmail, and sanitizePhone. Invalid requests rejected with structured error responses.

Audit Logs Persisted to Database

writeAuditLog() now writes to the prisma.auditLog table AND console. All 7 API routes plus login log every PHI access, modification, and authentication event.

Rate Limiting

Login endpoint limited to 5 requests/minute. Upload endpoints limited to 10 requests/minute. Exceeded limits return 429 responses with Retry-After headers. In-memory store for alpha, Redis-ready for production.

15-Minute Server-Side Session Timeout

Server-side JWT maxAge reduced to 900 seconds (15 minutes). Sliding window refreshes the cookie on each authenticated request. JWT secret throws an error in production if NEXTAUTH_SECRET is not set.

2. Where We Are Not

Remaining Gaps

No Multi-Factor Authentication (MFA)

No MFA implementation. Audit action enums for MFA_ENABLED/MFA_DISABLED exist but are unused. Single-factor (password only) authentication for all users.

SQLite Database (Not HIPAA-Eligible)

Current database is SQLite via better-sqlite3. SQLite has no built-in encryption at rest, no access auditing, no role-based database access, and is not suitable for production PHI storage. Note: PostgreSQL migration config is ready (Dockerfile, CloudFormation template) but not yet deployed.

No BAA Acceptance Flow

No Business Associate Agreement workflow in the application. No signature capture, no consent tracking, no BAA document served during practice signup. Marketing footer links to “#” for BAA.

No Encryption Key Management (AWS KMS)

PHI encryption key expected as a plain environment variable (PHI_ENCRYPTION_KEY). No HSM, no AWS KMS, no key rotation policy. Note: CloudFormation template includes KMS configuration but not yet deployed.

3. Where We Need to Go

Roadmap to Compliance

P0 Before ANY Real Patient Data Enters the System

P0 1. Wire Encryption Into All API Routes · DONE

Completed. All API routes now encrypt PHI on write and decrypt on read via AES-256-GCM.

P0 2. Reduce Server Session Timeout to 15 Minutes · DONE

Completed. JWT maxAge set to 900s with sliding window refresh on each authenticated request.

P0 3. Remove Hardcoded JWT Secret · DONE

Completed. Production startup throws error if NEXTAUTH_SECRET is not set.

P0 4. Add RBAC to All PHI Endpoints · DONE

Completed. requireRole() enforced on every PHI route with appropriate role minimums.

P1 Before Beta / External Users

P1 5. Migrate to PostgreSQL · ~2–4 hours

Switch from SQLite to PostgreSQL (AWS RDS with encryption at rest enabled). Dockerfile and CloudFormation config are ready — deploy and update Prisma connection. Enable SSL connections.

P1 6. Persist Audit Logs to Database · DONE

Completed. writeAuditLog() writes to prisma.auditLog table. All 7 API routes + login log access.

P1 7. Add Rate Limiting · DONE

Completed. Login: 5/min. Uploads: 10/min. 429 responses with Retry-After headers.

P1 8. Connect Input Validation · DONE

Completed. Zod schemas + sanitizeText/sanitizeEmail/sanitizePhone on all POST/PATCH routes.

P1 9. Add Audit Logging to Every PHI Route · DONE

Completed. All 7 API routes + login now call writeAuditLog() on every PHI access.

P2 Before Production / Real Practices

P2 10. Implement MFA · ~8–12 hours

Add TOTP-based MFA (Google Authenticator / Authy) as optional for all users, required for ADMIN and OWNER roles.

P2 11. BAA Acceptance Workflow · ~4–6 hours

Add BAA document display during practice signup. Capture digital signature, timestamp, and IP address. Store acceptance record. Block access until BAA is signed.

P2 12. AWS KMS for Encryption Keys · ~4–6 hours

Move PHI_ENCRYPTION_KEY to AWS KMS. Use envelope encryption (KMS generates data key, data key encrypts PHI). Implement key rotation (annual).

P2 13. Audit Log Retention & Immutability · ~2–3 hours

Configure 7-year retention policy. Use append-only storage (DynamoDB with no delete permissions, or CloudWatch Logs with resource policy). Block deletion of audit records.

P2 14. Penetration Testing · External engagement

Engage third-party security firm for HIPAA-focused pen test. Test for OWASP Top 10, authentication bypass, PHI exposure, injection attacks. Fix findings.

P2 15. SOC 2 Type II Preparation · 6–12 months post-launch

Engage advisory firm. Document all security controls, policies, and procedures. Prepare for 3–6 month observation period.

P2 16. Formal Risk Assessment · Ongoing (annual)

Conduct HIPAA-required risk assessment documenting all ePHI, threats, vulnerabilities, and mitigations. Update annually. Required by HIPAA Security Rule §164.308(a)(1).

4. Quick Reference — HIPAA Security Rule Checklist

HIPAA Requirement Rule Reference Status
Access Controls §164.312(a)(1) ✅ Auth + RBAC enforced
Audit Controls §164.312(b) ✅ Persisted to database, all routes logged
Integrity Controls §164.312(c)(1) ✅ Zod validation + sanitization connected
Transmission Security (TLS) §164.312(e)(1) ✅ HSTS enforced, TLS required
Encryption at Rest §164.312(a)(2)(iv) ✅ AES-256-GCM on all PHI fields
Automatic Logoff §164.312(a)(2)(iii) ✅ 15-minute server-side timeout with sliding window
Authentication §164.312(d) ⚠️ Password + session, no MFA yet
Risk Assessment §164.308(a)(1) ❌ Not conducted
Workforce Training §164.308(a)(5) ❌ Not applicable yet (no workforce)
Contingency Plan §164.308(a)(7) ❌ No backup/disaster recovery plan
BAA §164.308(b)(1) ❌ No BAA workflow
Facility Access §164.310(a)(1) N/A (cloud-hosted)
Device Controls §164.310(d)(1) N/A (SaaS, no physical devices)

Powered by A.X.I.S. Pre-AlphaI still have my training wheels on, so tell me how I'm doing  |  Discover A.X.I.S. →