Last Audit: 2026-01-24 Classification: For Enterprise Sales & Compliance Review Version: 2.0.0
Protocol Guide implements enterprise-grade security suitable for handling medical/emergency services data. The application follows OWASP best practices, employs defense-in-depth strategies, and has been hardened based on comprehensive security audits.
| Category | Score | Status |
|---|---|---|
| Authentication | 9/10 | ✅ Excellent |
| Authorization | 8/10 | ✅ Strong |
| Data Protection | 9/10 | ✅ Excellent |
| API Security | 9/10 | ✅ Excellent |
| Infrastructure | 8/10 | ✅ Strong |
| Monitoring | 8/10 | ✅ Strong |
- Provider: Supabase Auth (built on GoTrue)
- Protocols: OAuth 2.0 + PKCE flow
- Supported Providers: Google, Apple Sign-In
- Session Management: JWT-based with secure cookie storage
| Control | Implementation | Status |
|---|---|---|
| CSRF Protection | Double-submit cookie pattern with constant-time comparison | ✅ |
| OAuth State Validation | Cryptographic state with 10-minute expiry | ✅ |
| Token Revocation | Redis-based blacklist with 7-day TTL | ✅ |
| Multi-Device Logout | Force logout from all devices on password change | ✅ |
| Rate Limiting | 5 auth attempts per 15 minutes | ✅ |
| Session Cookies | HttpOnly, Secure, SameSite=Strict | ✅ |
- Passwords handled entirely by Supabase Auth (industry-standard Argon2)
- Minimum 8 characters enforced
- Current password required for password change
- All sessions invalidated on password change
| Role | Capabilities |
|---|---|
| User | Query protocols, view history, manage profile |
| Pro | All user features + enhanced limits, cloud sync |
| Enterprise | All Pro features + team management, custom protocols |
| Admin | Full system access, user management, analytics |
// Server-side tier validation with atomic race-condition protection
const { allowed, newCount } = await db.incrementAndCheckQueryLimit(userId, tierLimit);- Atomic increment-and-check prevents TOCTOU vulnerabilities
- Subscription status validated on every paid-tier request
- Tier downgrades handled gracefully on payment failure
Supabase RLS policies enforce data isolation:
- Users can only access their own data
- Service role bypass for server operations only
- Query analytics isolated to admin roles
Whitelist-based CORS (not wildcard):
const CORS_WHITELIST = [
"https://protocol-guide.com",
"https://www.protocol-guide.com",
"https://protocol-guide.netlify.app",
"https://protocol-guide-production.up.railway.app",
];- No
Access-Control-Allow-Origin: * - Credentials only with whitelisted origins
- Preflight caching (24 hours)
Redis-backed distributed rate limiting with tier awareness:
| Endpoint Type | Free Tier | Pro Tier | Enterprise |
|---|---|---|---|
| Public APIs | 100/min | 100/min | 100/min |
| Search | 30/min | 100/min | 500/min |
| AI Queries | 10/min | 50/min | 200/min |
| Auth | 5/15min | 5/15min | 5/15min |
- Input Validation: Zod schemas on all tRPC procedures
- Request Size Limits: 10MB max body
- Timeout Protection: 30-second request timeout
- SQL Injection: Prevented via Drizzle ORM parameterized queries
| Setting | Value |
|---|---|
| Protocol | TLS 1.2+ (via Railway/Netlify) |
| HSTS | Enabled (1 year, includeSubDomains, preload) |
| Certificate | Auto-renewed via platform |
All requests include comprehensive security headers via Helmet:
// Content Security Policy
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "nonce-based"],
imgSrc: ["'self'", "data:", "blob:", "https://*.supabase.co"],
connectSrc: ["'self'", "https://*.supabase.co"],
frameSrc: ["'none'"],
objectSrc: ["'none'"],
upgradeInsecureRequests: true, // Force HTTPS
// Additional Headers
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=(self)| Data Type | Classification | Protection |
|---|---|---|
| User credentials | Critical | Supabase Auth (not stored locally) |
| Session tokens | High | HttpOnly cookies, Redis blacklist |
| Protocol content | Medium | Encrypted at rest (Supabase) |
| Query history | Medium | User-isolated via RLS |
| Analytics | Low | Anonymized, no PHI |
PHI Exclusion from Logs:
// HIPAA COMPLIANCE (2026-01-23):
// This table intentionally does NOT store PHI.
// REMOVED: userAge, impression (clinical codes)- No Protected Health Information in logs
- Integration logs anonymized
- Audit trail maintained without PHI
| Layer | Method |
|---|---|
| At Rest | AES-256 (Supabase managed) |
| In Transit | TLS 1.2+ |
| Secrets | Environment variables (not in code) |
- PCI Compliance: Level 1 (via Stripe)
- Payment Data: Never touches our servers
- Webhook Security: HMAC signature verification
// Webhook signature verification
const event = constructWebhookEvent(rawBody, signature);
// Idempotency protection
const existingEvent = await db.query.stripeWebhookEvents.findFirst({
where: eq(stripeWebhookEvents.eventId, eventId),
});- Stripe handles all card data
- Webhooks process subscription changes
- Automatic tier downgrade on payment failure
- Provider: Sentry
- Coverage: Server + Client errors
- PII Scrubbing: Enabled by default
// Distributed tracing with request IDs
logger.info({
requestId: ctx.trace.requestId,
userId: user?.id,
action: "query_submitted",
}, "Protocol query processed");| Endpoint | Purpose |
|---|---|
/api/health |
Overall system health |
/api/ready |
Kubernetes readiness probe |
/api/live |
Kubernetes liveness probe |
/api/resilience |
Circuit breaker status |
Production Dependencies: ✅ No known vulnerabilities
Development Dependencies:
- All in dev-only packages (vitest, vite, esbuild, drizzle-kit)
- Do not affect production runtime
- Fix available via major version upgrades
- Regular
npm auditscans - Automated security advisories via GitHub
- Lock file integrity verification
| Component | Provider | Certifications |
|---|---|---|
| Backend | Railway | SOC 2 Type II |
| Frontend | Netlify | SOC 2 Type II |
| Database | Supabase | SOC 2 Type II, HIPAA |
| Payments | Stripe | PCI DSS Level 1 |
| CDN | Netlify Edge | Enterprise DDoS protection |
- No hardcoded secrets in codebase
- Environment variables via platform secret stores
.envin.gitignore, not tracked in git- Secrets never logged
Immediate revocation capability for security incidents:
await revokeUserTokens(userId, "security_incident", {
reason: "Suspicious activity detected",
revokedBy: "admin",
});All security-relevant events logged:
- Login/logout events
- Permission changes
- Subscription changes
- Admin actions
| Standard | Status | Notes |
|---|---|---|
| OWASP Top 10 | ✅ Addressed | See controls above |
| SOC 2 | ✅ Via platforms | Railway, Netlify, Supabase |
| HIPAA | ✅ Compliant | PHI excluded from logs |
| PCI DSS | ✅ Via Stripe | Payment data never touches servers |
| GDPR | ✅ Ready | Data deletion, export available |
- Security Issues: security@protocol-guide.com
- Bug Bounty: Not currently active
- Responsible Disclosure: 90-day policy
- ✅ CSRF protection migrated to tRPC double-submit pattern
- ✅ OAuth state validation implemented
- ✅ Token blacklist with Redis backend
- ✅ Comprehensive security headers (Helmet)
- ✅ PHI removed from integration logs
- ✅ HIPAA compliance review completed
- ✅ Rate limiting with tier awareness
- ✅ Stripe webhook idempotency
- Enable MFA for admin accounts (Supabase supports TOTP)
- Configure WAF rules at CDN level for additional protection
- Schedule quarterly security reviews
- Implement SOC 2 continuous monitoring (if pursuing certification)
Document Classification: Internal / Customer-Facing Next Review Date: 2026-04-24 Approved By: Security Team