Data protection
This page is written for the person at a school who has to decide whether a counselor may put a caseload into this tool. It describes what is actually built, not an aspiration. Where we have not done something, it says so.
Isolation is enforced in the database
Every read and write goes through PostgreSQL row-level security. The rule about who may see a student record is a predicate attached to the table, evaluated by the database on every query, under the identity of the signed-in user. It is not a filter in application code and it is not a hidden button — a request that asks for a record it has no right to gets an empty result, whatever it was sent through.
That model, stated plainly:
- A counselor sees the students on their own roster. Another counselor at the same school does not, even inside the same institute.
- An institute admin sees every member counselor’s students, shortlists and notes. That is the oversight the role exists for, and it is the only cross-counselor visibility there is.
- A counselor’s private program notes and tags are owner-only, including from their institute admin. Oversight covers who a counselor is working with, not their private annotations.
- A student can never read the notes a counselor wrote about them. Not through the interface, and not through the API either — the policy has no branch that would allow it.
- A student sees their own shortlist and tracker only once the counselor shares it, and a guardian only once the counselor shares it with guardians. Those are separate grants, and view and edit are separate again.
The sharing switch is the database predicate, not the interface. Turning a share off does not hide a control; it changes what the database will return to that person. The same is true of the edit switch — a read-only share cannot be written through by any route.
Privileged writes are unreachable from the browser
A user’s role, their institute, and their institute role can only be set by the server’s privileged credential. A database trigger silently reverts any attempt to change those columns from a normal session, so a counselor cannot promote themselves to administrator even by calling the API directly with a hand-made request.
Internal database routines — the ones that mint credits, provision accounts, or complete a guardian link — live in a schema the public API does not serve at all. They are not merely permission-checked; there is no address at which a browser can reach them. Their public wrappers take no parameter that could turn a check off.
Server actions are treated as what they are: directly invocable endpoints. Every mutation re-checks the caller’s capability on the server, for the specific record, regardless of what the interface offered.
Authentication
- Email and password, with confirmation required — an unconfirmed address cannot sign in, and nothing of value is granted to an account until the address is proven.
- Passwords are stored hashed, never in recoverable form. Minimum length eight characters.
- Sessions use short-lived access tokens with refresh-token rotation and reuse detection, so a stolen refresh token is detectable and self-revoking.
- A bot check (Cloudflare Turnstile) guards registration, sign-in, password recovery and the institute request form. It fails closed: if the check cannot be completed, registration is refused rather than waved through.
- Re-authentication with the current password is required to change an email address, change a password, or delete an account — and the deletion check runs on the server, not in the browser.
- Changing an email address requires confirmation at both the old and the new address.
The one place a password is checked against someone else’s account is the optional path where a parent proves they hold their child’s login in order to link to it. That is a password oracle over a minor’s account, so it is treated as one: a per-address lockout, a per-IP cap, a global stuffing alert, padded response timing, and a single generic failure message for every pre-verification outcome, so the response cannot be used to test whether an address exists. Email addresses in that abuse ledger are stored salted-hashed rather than in the clear, so the ledger is not itself a list of addresses. Both the student and their counselor are emailed whenever a link is made or repeatedly attempted, and a counselor can switch the path off per student.
The public surface is one row set
Signed-out visitors can browse the program catalog. That is the only data readable without an account — globally published program records, and nothing else. Every other table keys its access rule off the signed-in user’s identity and returns nothing at all to an anonymous request, which is what makes the public preview read-only by construction rather than by hiding buttons. It is tested that way.
Encryption
- In transit: HTTPS/TLS for every connection — browser to application, application to database, and application to every third party listed below. Traffic is served over HSTS-eligible TLS by our hosting provider.
- At rest: the database, its backups and uploaded files (branding logos, program icons) are encrypted at rest by our database host’s platform-level disk encryption.
- Card data never reaches our servers. Payment details are entered directly into Stripe-hosted checkout and portal pages. We store a customer reference and a subscription status; we never see, transmit or store a card number.
Backups
Our database host takes automated backups of the production database on its own schedule, and we take a full snapshot immediately before any schema change, so a migration can be reversed. Snapshots contain student data, so they are held in controlled storage, are never committed to source control, and are not shared with anyone outside the people who operate the service.
The honest caveat about deletion: when you delete an account, the live records go immediately, but a copy can persist in a backup until that backup ages out of its retention window. It is not restored into the live service, and it is overwritten in the ordinary course. We cannot surgically erase a row from a historical snapshot without destroying the snapshot’s value as a recovery point.
The AI provider
AI recommendations are produced by a model hosted by Anthropic. What we send is deliberately narrow: grade, GPA, intended majors, activities, target colleges, budget, geography and format preference, together with summaries of the candidate programs to be ranked.
No name, no email address, no contact detail, and no counselor note is sent. The request carries an academic profile and nothing that identifies the student. The data is sent to produce that response, and is not used to train models. Every run is credit-metered and written to a ledger you can download, so there is a record of each one.
Error monitoring
When a page fails to render we record the error so we can fix it. The report contains the error type, a truncated message and stack trace, the browser user agent, and the path only — never the query string, because a query string on this product carries search terms and filter values. No record content is included.
Who else touches the data
The full subprocessor list, with what each one receives, is in the Privacy policy. In brief: our database and authentication host, our application host, our transactional email provider, our payment processor, the AI provider above, and the bot-check provider. There is no advertising network, no data broker and no third-party analytics attached to any part of this product.
Operational practice
- Access to production data is limited to the people who operate the service, and is used for support and incident response only.
- The privileged database credential is held server-side and never shipped to a browser. Reaching data as another user is not something an operator does casually — it goes through the same privileged path, deliberately.
- Changes go through source control, an automated test suite that includes tests written specifically to drive the access-control policies, and staged deployment. The isolation rules above are covered by integration tests that exercise them through real client sessions, not by inspection.
Incident response
If we become aware of a breach of personal data, we:
- contain it first — revoke credentials, close the path, and stop further exposure;
- establish what was reached, whose records were affected, and over what period, from database and application logs;
- notify affected account holders without undue delay, and where a school or district is the controller of the records involved, notify the school — within 72 hours of becoming aware, so it can meet its own notification duties. We will tell the school what happened even where our own count of affected records is still provisional;
- tell you what data was involved, what we have done, and what you should do — plainly, and without waiting until we have a complete picture;
- fix the cause and publish what changed.
We would rather over-report than under-report. If you believe an incident has occurred, write to privacy@summertrack.app and say so in the subject line.
Reporting a vulnerability
If you find a way to reach data you should not, please tell us before you tell anyone else: hello@summertrack.app, with enough detail to reproduce it. We will acknowledge it, keep you updated, and credit you if you would like to be credited.
Please do not access, modify or retain any record that is not your own while demonstrating a problem, do not run automated scanning against the production service, and give us a reasonable chance to fix it before publishing. We will not pursue a researcher who follows that. We do not currently run a paid bug bounty.
What we do not claim
We hold no third-party security certification — no SOC 2 report, no ISO 27001, no independent penetration test we can hand you. Saying so is more useful to you than a page of badges.
SummerTrack is a counselor workspace, not a compliance product. Your school or district remains the controller of its student records and remains responsible for deciding what may be entered here and who may see it. We will support a school’s own obligations — a data processing agreement, a record of what we hold, a deletion carried out on its instruction — and we will not pretend to discharge them on its behalf. Ask us at privacy@summertrack.app.