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:


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 the preload directive. 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_dump pushed 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-origin
    • Permissions-Policy denying 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 \r with a ' so spreadsheet applications render them as text — the OWASP-standard defense).
  • Firmware .bin uploads (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 to firmware.bin are 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

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