Pre-Alpha Assessment · March 2026
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.
JWT-based auth via the jose library. Passwords hashed with bcryptjs. Session stored in httpOnly, secure, sameSite cookie. Login/logout endpoints functional.
All routes use UUIDs (patient IDs, session IDs), never patient names, DOB, or emails in URL parameters. Error responses return generic messages.
no-store, no-cache, must-revalidate headers set on all /api/patients, /api/intake-sessions, and /api/insurance routes.
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-log.ts defines 25+ audit actions, resource types, and a structured logging format including userId, userRole, practiceId, ipAddress, userAgent, timestamp, action, and success status.
Role hierarchy defined: OWNER > ADMIN > DENTIST > HYGIENIST > FRONT_DESK. Functions hasRole() and requireRole() implemented in auth.ts.
sanitize.ts implements sanitizeText (strips HTML), sanitizeEmail, sanitizePhone, sanitizeDateOfBirth, sanitizeRecord, and validateRequired.
session-timeout.ts implements 15-minute idle detection with warning modal and automatic logout.
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.
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.
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.
writeAuditLog() now writes to the prisma.auditLog table AND console. All 7 API routes plus login log every PHI access, modification, and authentication event.
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.
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.
No MFA implementation. Audit action enums for MFA_ENABLED/MFA_DISABLED exist but are unused. Single-factor (password only) authentication for all users.
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 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.
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.
Completed. All API routes now encrypt PHI on write and decrypt on read via AES-256-GCM.
Completed. JWT maxAge set to 900s with sliding window refresh on each authenticated request.
Completed. Production startup throws error if NEXTAUTH_SECRET is not set.
Completed. requireRole() enforced on every PHI route with appropriate role minimums.
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.
Completed. writeAuditLog() writes to prisma.auditLog table. All 7 API routes + login log access.
Completed. Login: 5/min. Uploads: 10/min. 429 responses with Retry-After headers.
Completed. Zod schemas + sanitizeText/sanitizeEmail/sanitizePhone on all POST/PATCH routes.
Completed. All 7 API routes + login now call writeAuditLog() on every PHI access.
Add TOTP-based MFA (Google Authenticator / Authy) as optional for all users, required for ADMIN and OWNER roles.
Add BAA document display during practice signup. Capture digital signature, timestamp, and IP address. Store acceptance record. Block access until BAA is signed.
Move PHI_ENCRYPTION_KEY to AWS KMS. Use envelope encryption (KMS generates data key, data key encrypts PHI). Implement key rotation (annual).
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.
Engage third-party security firm for HIPAA-focused pen test. Test for OWASP Top 10, authentication bypass, PHI exposure, injection attacks. Fix findings.
Engage advisory firm. Document all security controls, policies, and procedures. Prepare for 3–6 month observation period.
Conduct HIPAA-required risk assessment documenting all ePHI, threats, vulnerabilities, and mitigations. Update annually. Required by HIPAA Security Rule §164.308(a)(1).
| 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-Alpha — I still have my training wheels on, so tell me how I'm doing | Discover A.X.I.S. →