Last updated: August 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 is built to operate under the "school official" exception defined in 34 CFR § 99.31(a)(1)(i)(B), and our Data Processing Agreement is written to establish that designation. To be precise about status: that exception attaches once an institution designates us in a signed written agreement, and no institution has been onboarded yet — so today students share their own records with us directly, under their own consent, rather than a school disclosing records to us. Under either arrangement 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. Your deployment would be the first execution of this designation.
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. Two disclosures for completeness, neither of them an advertising integration: the public marketing homepage embeds an introductory video via YouTube, which sets Google cookies for visitors to that page; and video lessons in the Boards & Tests classroom are hosted on YouTube. The classroom player is click-to-load — a lesson shows a placeholder card and requests nothing at all from Google until a student presses play, at which point it loads through youtube-nocookie.com. You can verify that claim yourself in a browser network panel.
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. Every piece of student text is scrubbed before it reaches the model, at one of two strengths. Uploaded documents — transcripts, resumes, and other files — have contact details and the student's name redacted, because a name is noise in a document we are parsing for courses and dates. Text the student types — personal statements, interview reflections, the experience-discovery chat — has Social Security numbers, email addresses, phone numbers and ID numbers redacted, while proper nouns are deliberately preserved: an essay stripped of "Mayo Clinic" and the mentor who taught them cannot be coached. Text is also length-capped per surface, from 3,000 characters for an uploaded document to 6,000 for a personal-statement draft. We do not use student data to fine-tune or train models.
Transactional email is implemented against Resend and sends from a verified sending domain we control, whitecoatworld.org, with SPF and DKIM published for it. Flows that email a third party — faculty .edu verification, invitations, supervisor hour-verification requests, and survey and review reminders — are available. Each of them still checks the configured sender before doing anything and returns an explicit operator error rather than attempting a delivery that would fail, so a misconfiguration surfaces as a refusal instead of as silence. No student PII appears in an email body beyond first name and the specific section a review was requested for, and 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.
Server-side product analytics — which features are used and how often — captured without personally identifiable information. It records product events, not student academic content: no transcript, GPA, personal statement, experience, or advising material is sent to PostHog. Listed here so that this page, the Privacy Policy and the Data Processing Agreement name exactly the same set of sub-processors.
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.
YouTube appears in two places. On the public marketing homepage an introductory video is embedded directly, so it loads for anonymous visitors before any account exists and sets Google cookies for that page. In the Boards & Tests classroom, video lessons are hosted on YouTube and played through youtube-nocookie.com — but the player is click-to-load: until a student presses play on a specific lesson, the page contains no YouTube iframe, no YouTube script, and not even a thumbnail, so nothing whatsoever is requested from Google. That is deliberate and it is verifiable: open a chapter page with the network panel filtered to google, youtube, ytimg or googlevideo and it stays empty until you click. Neither embed is an advertising or tracking integration, and no student record, answer, or score is ever transmitted to YouTube — the only thing sent when a student presses play is the video ID they chose to watch. The one other in-browser third party anywhere in the product is the Google Places autocomplete described above, which runs on a signed-in page but only for the optional location field.
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 through their institution’s identity provider where one is configured, or with Google OAuth 2.0 or 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, and multiple institutions can be federated at once, each with its own isolated identity namespace. 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 means supplying a provider identifier, display name, issuer URL, client ID, and client secret; the client secret is encrypted at rest with AES-256-GCM under a key held outside the database, so a database-only compromise does not yield it. Native SAML 2.0 is not supported — see the note below. Being precise about status: no institution has been onboarded yet, and this path has not yet completed an end-to-end login against a live identity provider, so your deployment would be the first exercise of it 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. Administrator is never self-assignable. The remaining roles are self-declared when an account is created, and declaring one confers no access to anyone else's data on its own: a faculty account reaches a student's record only after its institutional email address is verified, the account is approved by us, and the student has separately granted consent; institutional and organizational accounts require our verification on the same basis. Switching an existing account to a different role is refused. We are moving the institutional roles to explicit provisioning ahead of our first institutional deployment.
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 through our contact form before public disclosure, choosing "Legal notice" as the subject. Reports filed there raise an alert immediately, and for those 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: https://whitecoatworld.org/contact — choose "Legal notice" as the subject, and include a description of the vulnerability, steps to reproduce, your assessment of impact, and an address we can reply to. We also publish security@whitecoatworld.org for reviewers whose process requires an address on file; inbound delivery to it is still being provisioned, so until that is live the form is the channel the commitment above attaches to. 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 use our contact form. We also publish security@whitecoatworld.org for review processes that require an address on file, though inbound delivery to it is still being provisioned.