Last updated: July 2026 · For institutional partners and IT security reviewers.
FERPA Aligned
34 CFR § 99.31
HECVAT (in prep)
Full v3.x
SOC 2 Type II
via Vercel + Supabase
TLS 1.3 + HSTS
2-year preload
White Coat World operates under the "school official" exception defined in 34 CFR § 99.31(a)(1)(i)(B). We access student education records only with a legitimate educational interest and never sell, rent, or otherwise disclose student PII to third parties for commercial purposes.
The platform is 100% ad-free. No advertising networks, tracking pixels, retargeting scripts, or marketing cookies are loaded anywhere in the application. Student browsing behavior and profile data are never shared with advertisers — a hard requirement for FERPA-aligned deployments. One disclosure for completeness: the public marketing homepage embeds an introductory video via YouTube, which sets Google cookies for visitors to that page. It is not an advertising integration, and it does not appear on any authenticated page.
Our security controls are designed to satisfy the Higher Education Community Vendor Assessment Toolkit (HECVAT Full v3.x). A completed HECVAT questionnaire is in preparation; institutional IT security reviewers can contact us for current status.
We collect only the information necessary for the advisory and admissions-preparation workflow. Faculty members are granted field-level access scoped to what is relevant for their advisory role: they see the academic record they are advising on, including test scores, because an advisor cannot judge school fit without them. Supervisor contact details from a student's logged experiences are excluded from the faculty view, and faculty access is limited to students who have explicitly consented to share with that institution.
All traffic is encrypted using TLS 1.3. HTTP Strict Transport Security (HSTS) is enforced with a 2-year max-age and includes subdomains, enabling HSTS preloading.
All data is stored in Supabase (PostgreSQL), which provides AES-256 encryption at rest on all database volumes and object storage.
Every API endpoint validates input against strict Zod schemas before any database interaction. All database queries use parameterized statements (no raw string interpolation), preventing SQL injection (OWASP A03). String fields are sanitized against regex allowlists to prevent XSS (OWASP A03/A07).
All responses include: Content-Security-Policy (CSP) with allowlisted sources, X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, and Permissions-Policy disabling camera, microphone, and geolocation.
Two sign-in methods are supported (NextAuth v5, JWT strategy): Google OAuth 2.0, and email with a password. Google's OAuth sub is hashed into a deterministic UUID before storage, preventing user enumeration attacks. Passwords are never stored in recoverable form — only an Argon2id hash (19 MiB memory cost, 2 iterations) is written to the database, and email addresses must be verified before the first password sign-in. New and changed passwords are checked against the Have I Been Pwned breach corpus using k-anonymity: only the first five characters of the password's SHA-1 digest leave our servers, never the password itself.
Time-based one-time password (TOTP) two-factor authentication is available to every account type — student, faculty, school, organization, and administrator — from the account Security tab, and works with any standard authenticator app. TOTP secrets are encrypted at rest with AES-256-GCM under a key held outside the database, and each code is single-use (a replay guard rejects a time step that has already been consumed). Ten single-use recovery codes are issued at enrollment and stored only as SHA-256 hashes.
All credential tables — password hashes, TOTP secrets, recovery-code hashes, email-verification and password-reset tokens, and one-time-code records — have Row-Level Security enabled with no policies granted to the anon or authenticated roles, making them unreadable by any client-side connection and reachable only by the server's service role. Verification and reset tokens are stored as SHA-256 hashes with short expiry windows (24 hours and 1 hour respectively); the plaintext token exists only in the emailed link.
All uploaded files are validated against their magic bytes (not just MIME headers) using the file-type library, capped at 10 MB, and scanned for PII before storage. Allowed types: PDF, JPEG, PNG, WebP.
Students explicitly opt into data sharing with their institution before any faculty member can access their profile. Consent is institution-scoped, immediately revocable at any time, and preserves a soft-deleted audit trail so revocation history is never lost.
Students may request permanent deletion of all their data at any time. The erasure endpoint hard-deletes their records across every table in FK-safe order, writes an anonymized audit entry, then terminates the session. No soft-delete fallback — erasure is permanent. Three narrow categories are excluded by design, each disclosed in the Privacy Policy retention table: the account-closure audit entry, anonymous benchmark contributions that contain no PII, and the record that an agreement was accepted, whose identifiers are erased while the acceptance itself is retained. Encrypted disaster-recovery backups retain a copy for up to 7 days before ageing out.
Sensitive operations are written to an immutable audit_log table: faculty views of student profiles, consent grants and revocations, admin approvals of faculty accounts, and account deletions. Logs are retained and readable only by platform administrators.
Non-erasure deletions (reports, experiences, etc.) use a soft-delete pattern (deleted_at timestamp). Row-Level Security policies filter soft-deleted rows from all queries, enabling data recovery and audit trails without exposing deleted records to users.
Faculty at Institution A cannot access students from Institution B. Isolation is enforced server-side at the API layer — every request is authenticated and scoped to the caller's institution and consent grants — with Postgres Row-Level Security as an additional defense-in-depth layer.
White Coat World is deployed on Vercel, which holds SOC 2 Type II and ISO 27001 certifications. All environment secrets are stored in Vercel's encrypted secret vault — no credentials are committed to source code.
Our PostgreSQL database and object storage are hosted on Supabase, which holds SOC 2 Type II certification. Supabase provides automatic point-in-time recovery, geographic redundancy, and continuous database backups.
AI gap analysis and writing assistance is powered by Google Gemini Flash. Student-submitted text is capped at 3,000 characters per prompt and passed through a PII scrubber before reaching the model. We do not use student data to fine-tune or train models.
Faculty notification emails are sent via Resend using our verified institutional domain. No student PII is included in email bodies beyond first name and the specific section a review was requested for. Account emails (verification and password reset) carry a single-use, short-lived token.
Rate-limit counters and the session-version cache are held in Upstash Redis. Keys are derived from IP addresses, user IDs, and — for the one-time-code limiter — phone numbers. No academic profile content, application materials, or uploaded documents are stored there; entries are short-lived and expire automatically.
SMS delivery of one-time codes is implemented against Twilio. It is not active in the current configuration: no Twilio credentials are provisioned, so no SMS is sent and no phone number is transmitted to Twilio today. We list it because enabling SMS delivery would engage Twilio as a sub-processor, and institutions should evaluate it as part of the review rather than be surprised by it later.
Application error reporting is instrumented against Sentry with personally identifiable information collection disabled and an additional scrubbing pass applied to every event before transmission. Like SMS, this integration is currently inactive — no Sentry DSN is configured, so no error data leaves the application.
When a password is created or changed, we check it against the Have I Been Pwned breach corpus using the k-anonymity range API. Only the first five characters of the password's SHA-1 digest are transmitted; the password, the full digest, and the user's identity are never sent, and the service cannot determine which password was checked.
The optional location field in the social layer uses Google Places for autocomplete, which sends the text a user types in that field to Google from their browser. It is used only for that field and is not part of the academic profile or advising workflow.
The public marketing homepage embeds an introductory video via YouTube, which sets Google cookies for visitors to that page. This is the one third-party embed on the site and it is disclosed for completeness: it loads for anonymous visitors before any account exists, and it is not present on any authenticated page or anywhere student data is handled. It is not an advertising or tracking integration.
Academic profiles, experiences, reports, and uploaded documents are retained until the student permanently deletes their account. Soft-deleted records (e.g., removed experiences) are automatically purged within 30 days. Audit log entries are retained for 12 months then automatically rolled off. Legal acceptance records — which agreement, which version, when, and a digest of the published text — are retained after deletion with the signer's identifiers erased. Anonymous benchmark contributions contain no PII and are retained indefinitely. The full schedule is in the Privacy Policy.
Students may trigger a permanent, irreversible hard delete of all their data directly from Settings → Privacy. The erasure endpoint deletes their records across every table in FK-safe order, writes one final audit log entry before deletion, and terminates the session. No soft-delete fallback — data is gone from live systems immediately, subject only to the three exclusions and the backup window described below.
Three things outlive an account, all disclosed in the Privacy Policy retention table. The account-closure audit entry (an identifier and a timestamp) rolls off after 12 months. Anonymous benchmark contributions carry no PII by construction. And the record that the account accepted a given agreement is retained — the IP address and browser details are erased, but the acceptance itself is kept as proof that an agreement whose indemnity and dispute-resolution terms survive termination was in fact formed. That record is append-only and cannot be edited or deleted, including by us: it is enforced by a database trigger rather than by permissions, because our own service credentials bypass row-level security.
Deleted records are removed from the Supabase PostgreSQL database and object storage (Supabase Storage). Supabase performs secure data disposal at the infrastructure layer in compliance with their SOC 2 Type II controls. Backups containing deleted student data age out within Supabase's point-in-time recovery window (7 days on the standard tier).
A scheduled job runs nightly to permanently delete records that have been soft-deleted for more than 30 days. This ensures no orphaned PII lingers in the database beyond the retention window.
Users sign in with Google OAuth 2.0 or with an email address and password (NextAuth v5, JWT strategy). Both paths support TOTP two-factor authentication, and Google accounts additionally inherit Google Workspace MFA enforcement, which universities can require for their domain. See section 2 for how credentials are hashed, encrypted, and isolated.
Generic OIDC federation is implemented and driven entirely by configuration — no code change or deploy is required to onboard an institution. Any OIDC-compliant identity provider works, including Microsoft Entra ID (Azure AD), Okta, Google Workspace for Education, and Shibboleth deployments fronted by an OIDC bridge. Enabling it for your institution means supplying five values: a provider identifier, display name, issuer URL, client ID, and client secret. No institution has been onboarded yet, so your deployment would be the first configuration of this path rather than a change to an existing one.
Automatic email-based account linking is deliberately disabled. A user who already holds a personal Google account under the same email address is never silently merged into the institutional identity — the two remain distinct until deliberately reconciled. This prevents an institutional SSO deployment from retroactively absorbing accounts your institution does not control.
We do not support native SAML 2.0. Institutions standardized on SAML typically federate through an OIDC bridge at their identity provider, which the integration above supports. If native SAML is a hard requirement for your review, contact us so we can scope it honestly rather than list it as available.
The platform enforces distinct roles stored in the user_roles table — including Student, Faculty, Admin, and several institutional/organizational roles for schools, healthcare organizations, and pre-health programs. Each role's access is enforced server-side on every API request, with database Row-Level Security policies as defense-in-depth. Role assignment requires explicit provisioning — roles cannot be self-granted.
Sessions use HttpOnly, Secure, SameSite=Lax cookies. JWT sessions expire after 7 days, with the token refreshed at most once every 24 hours of activity. Because JWT sessions are stateless, we implement server-side revocation through a per-user session version stamped into each token and re-validated periodically: incrementing it invalidates every outstanding session for that user on every device. It is incremented on password reset and on disabling two-factor authentication. Revocation propagates within 5 minutes rather than instantly — the version is cached to keep the re-check off the database on every request, and that cache window is the latency. The check deliberately fails open on an infrastructure error, so a cache or database outage degrades to "no revocation this cycle" rather than signing out the entire userbase. We do not currently enforce a per-user concurrent-session cap.
If you discover a security vulnerability in White Coat World, please report it to our security team before public disclosure. We commit to: acknowledging your report within 48 hours, providing a status update within 7 days, and crediting reporters who follow responsible disclosure practices.
Security reports: security@whitecoatworld.com. Please include a description of the vulnerability, steps to reproduce, and your assessment of impact. We do not pursue legal action against good-faith researchers.
If you represent a university Technology Transfer, IT Security, or Compliance office and need a completed HECVAT questionnaire, a Data Processing Agreement (DPA), or a security review call, please contact security@whitecoatworld.com.