Security at HallPal
Architecture, controls, incident response·Source: docs/legal/SECURITY.md
Draft — pending final legal review. Text marked {{PLACEHOLDER}}is filled in by counsel before publication. Content shown here is a good- faith draft + reflects HallPal's current operational posture, but is not a substitute for legal advice.
Security at HallPal
Suggested public route: /security
Last reviewed: 2026-08-08
HallPal handles data about children in schools. That responsibility sets the bar high. This page describes the technical + operational controls we have in place to protect that data, and the mechanisms by which we tell you when something goes wrong.
For contract-level commitments, see:
- Privacy Policy — §12 short summary of measures
- Data Processing Addendum — Annex II detailed measures
- Student Data Agreement — §8 FERPA-scoped security duties
- Vulnerability Disclosure Policy — how to report a security issue
1. Architecture
Hosting + regions
- Web application (frontend + API routes): hosted on Vercel, in the {{VERCEL_REGIONS}} region(s).
- Database + real-time + authentication (Supabase): self-hosted by HallPal in {{DB_HOSTING_LOCATION}}, on Postgres 15.
- CDN + edge: Cloudflare (global).
- AI subprocessor (optional, when the chat assistant is enabled): Anthropic Claude models, US endpoints.
All Personal Data at rest stays in the United States. Cross-border transfers rely on the mechanisms described in DPA.md §10.
Multi-tenant isolation
- Every database table storing customer-scoped data is protected by Row-Level Security (RLS) at the Postgres layer. Every query is automatically filtered to the school(s) the requester belongs to. A misconfigured API route cannot bypass this — the isolation is enforced by the database itself.
- Server actions additionally include explicit
.eq('school_id', ...)filters on the requester's session-derived school ID, as a defense-in-depth layer. - Every mutation writes an immutable audit-log entry.
2. Data protection
Encryption
- In transit: TLS 1.2 or higher on every connection. HTTP
Strict Transport Security (HSTS) is sent on every response with a
1-year
max-age,includeSubDomains, and thepreloaddirective. Submission to the browser preload list has not yet been made, so treat HSTS as enforced on return visits rather than on a first-ever request. - At rest: database and file storage sit on self-hosted infrastructure whose disks are not yet encrypted at the storage layer. Full-disk encryption is scheduled work, not a control we have today, and we would rather say so than imply otherwise. Credentials inside the database are individually protected — device API keys and school API keys are stored only as bcrypt hashes, and invite tokens are single-use random values.
- Backups: automated offsite backups are not yet in
operation. The design — nightly
pg_dumppushed to encrypted offsite object storage, with the encryption key held separately from the backup medium — is specified and scheduled. Until it is running, recovery depends on the primary host.
Application security
- Content-Security-Policy on every response, with
default-src 'self', restricted script + style sources, and CSP violation reporting to a HallPal-controlled endpoint. - X-Frame-Options: DENY +
frame-ancestors 'none'— HallPal cannot be iframed, eliminating a class of clickjacking attacks. - X-Content-Type-Options: nosniff +
Referrer-Policy: strict-origin-when-cross-originPermissions-Policydenying access to camera / microphone / geolocation / accelerometer / gyroscope / magnetometer / payment / USB.
- Session cookies are
HttpOnly+Secure+SameSite=Lax.
Input handling
- Every server action + API route validates its input via Zod schemas at the boundary; a request that fails validation is refused with an explicit error.
- Every CSV export cell passes through a formula-injection filter
(prefixes strings starting with
=,+,-,@,\t, or\rwith a'so spreadsheet applications render them as text — the OWASP-standard defense). - Firmware
.binuploads (super-admin publisher only) are content-shape-checked against the ESP32 app-image magic byte (0xE9), chip-ID field, and app_desc magic (0xABCD5432). Arbitrary blobs renamed tofirmware.binare refused.
Authentication + session
- Sign-in via Supabase Auth — either an emailed magic link (default) or Google OAuth (opt-in per user). Passwords are not used, and are not accepted.
- Cloudflare Turnstile protects the magic-link send endpoint against automated abuse.
- Sessions auto-expire after 120 minutes of inactivity.
- Every authenticated route re-checks the user's allowlist status on every request. Revoking access at the database layer takes effect on the next request (no waiting for token expiry).
- Device-facing routes (Homebase / Pass) authenticate with per- device bearer tokens stored as bcrypt hashes on the server — plaintext is generated once at provisioning + shown only in the UI once. Rotation is a one-click admin action.
AI subprocessor (Anthropic Claude)
When a school enables the AI chat assistant:
- We send only the current user's message + minimal school context (school name, current period, roster count). We do NOT send full student names beyond first-name-plus-last-initial that appears elsewhere in the same admin's view.
- Under our commercial agreement, Anthropic does not use inputs or outputs to train its models.
- The assistant can be disabled per school from the settings page; when disabled, no data flows to Anthropic.
Full data-flow description: PRIVACY.md §6.
3. Access control
Personnel access
- Production access is limited to a small number of authorized engineers. MFA is required for every access channel to production infrastructure (SSH, database, Supabase Studio, Vercel dashboard, subprocessor admin panels).
- Every production access is logged. Access is granted per role, not per person; role-to-person mappings are reviewed at least quarterly.
- Personnel changes trigger a review of access + revocation of credentials on the same business day.
Customer access
- Role-based access control at the application layer:
platform.super,platform.admin,school_admin,teacher,device,anonymous. - Each capability is enumerated in a single-source-of-truth matrix maintained across the TypeScript + Postgres layers; drift between the two fails a mandatory smoke test.
- Session revocation is immediate on removal from the school allowlist.
Least privilege at the subprocessor layer
- Each subprocessor holds only the data required for its function (see SUBPROCESSORS.md).
- Subprocessors are onboarded only after a security review + are reviewed at least annually.
4. Monitoring + detection
- Application logging with tagged severity levels, emitted to the hosting platform's log stream. Centralised log aggregation and automated alerting are scheduled work, not yet in place — today a threshold breach is found by inspection rather than by a page to an on-call engineer. This is the control we consider most important to close before scale.
- Rate limiting on every authentication + sensitive route (magic-link send, OTP verification, device provision, card pair/unpair, RFID card lookup, chat). Trips are logged; automated alerting on them is part of the same scheduled work above.
- CSP violation reports are accepted at a HallPal-controlled endpoint and logged in a structured shape ready for a log drain. Scheduled review of them has not yet been established.
- Audit-log entries are immutable + retained per the customer's retention policy. The log surface is queryable by the school admin from within HallPal.
- Automated regression tests cover: database posture (row-level security enabled on every table, no permissive or anonymous-scoped policy, tenant foreign keys, privilege revocations), cross-tenant isolation, the permission matrix, accessibility (axe-core across every route in both themes), security headers, open-redirect regression, HMAC verification on the auth-email hook, formula-injection defenses on CSV exports, and firmware content validation. Linting, type-checking, the production build, and the database-posture check run on every merge; the remainder require a live environment and are run by an engineer before release.
5. Incident response
- HallPal maintains documented internal response procedures covering identification, containment, credential rotation, session revocation, and post-incident review. A formal incident-response plan reviewed against an external framework is scheduled and not yet complete.
- Detection to notification target: ≤72 hours for confirmed Security Incidents affecting customer Personal Data. Where a state or district requires a shorter window (e.g. some contracts stipulate 24 hours), the shorter window controls.
- The incident notification will include: nature of the incident, categories + approximate number of records affected, initial containment steps, contact point for follow-up, and the timeline for a written incident report (30 days from initial notice).
- HallPal cooperates with customer-initiated notifications to affected individuals + regulatory bodies as required by law.
Full commitments: STUDENT_DATA_AGREEMENT.md §9
- DPA.md §8.
6. Compliance + audits
Current status
- SOC 2 Type II: not currently certified, and no audit is in progress.
- ISO 27001: not currently pursued.
- Third-party penetration testing: none conducted to date. Security review to date has been internal.
- Accessibility: self-assessed against WCAG 2.2 AA with automated axe-core coverage across every route plus a documented manual-testing checklist. No third-party audit or VPAT has been produced yet.
Frameworks referenced
HallPal's security program references NIST Cybersecurity Framework (CSF) 2.0 as the guiding structure for control-family coverage. The same coverage supports compliance with:
- FERPA (US K-12 student records)
- COPPA (US children's online privacy)
- CCPA / CPRA (California privacy)
- GDPR + UK GDPR (EU / UK privacy)
- New York Ed Law § 2-d + Part 121
- Illinois SOPPA
- and additional state-specific student-privacy statutes covered in STATE_PRIVACY_RIDERS.md.
We are not currently able to sign a Business Associate Agreement (BAA) for HIPAA-covered PHI. HallPal is architected to refuse free-text student-medical inputs; if your use case would require PHI, please raise it before contracting so we can confirm we're the wrong fit or scope an exception.
7. Reporting a security issue
If you've found a vulnerability in HallPal — a way an attacker could access data they shouldn't, take over a session, escalate privilege, or break the system — please tell us. We take these seriously + will not pursue legal action against good-faith researchers acting within our Vulnerability Disclosure Policy.
- Email: security@hallpal.divz.io (encrypted mail preferred; PGP key fingerprint: {{PGP_KEY_FINGERPRINT}}).
- security.txt: hallpal.divz.io/.well-known/security.txt
- Response target: initial acknowledgment within 5 business days.
8. Contact
Security: security@hallpal.divz.io Privacy: privacy@hallpal.divz.io Legal + contracts: legal@hallpal.divz.io Trust + procurement questions: support@hallpal.divz.io