GDPR compliance statement
OMNIA Inclusion Ltd · Registered in England & Wales · Company no. 17228173 Last updated: 1 June 2026 · Version: 1.1 Applies to: UK GDPR, EU GDPR (Regulation (EU) 2016/679), and the Data Protection Act 2018 Audience: Data Protection Officers, school SLT, MAT procurement, ICO enquiries Contact: privacy@omnia-inclusion.com
This document maps each material GDPR obligation to the specific technical and organisational control inside OMNIA that enforces it. It is the canonical evidence trail for compliance reviews.
Related documents:
privacy.md— public privacy noticedpia.md— Data Protection Impact Assessmentsub-processors.md— current sub-processor listdata-residency-decision.md— hosting region rationaledata-retention.md— retention schedulebreach-sop.md— breach response procedurepdpl-dsr-runbook.md— data subject request runbook
1. Roles and lawful basis
| Role | Party |
|---|---|
| Data controller | The school or Multi-Academy Trust using OMNIA |
| Data processor | OMNIA (operating on Lovable Cloud) |
| Sub-processors | See sub-processors.md |
Lawful basis (Art. 6): Public task (Art. 6(1)(e)) for state schools discharging the SEND duty under the Children and Families Act 2014 and the SEND Code of Practice 2015.
Special category basis (Art. 9): Substantial public interest — safeguarding of children (Art. 9(2)(g), DPA 2018 Sch. 1 Pt. 2 para. 18).
2. Article-by-article mapping
Art. 5 — Principles
| Principle | Control in OMNIA |
|---|---|
| Lawfulness, fairness, transparency | Public privacy notice (privacy.md); in-app disclosures on pupil-voice and parent-voice capture |
| Purpose limitation | Data is scoped to SEND casework; no secondary use, no profiling for marketing |
| Data minimisation | PII scrubber on every AI Gateway call (@/lib/ai-gateway/scrub); sensitive columns (pin_hash, pin_salt, token_hash, webhook_secret, MIS api_key, api_key_ciphertext) have column-level SELECT revoked from authenticated/anon |
| Accuracy | DSAR export lets data subjects review; correction flows in admin UI |
| Storage limitation | Retention schedule in data-retention.md; "Erase pupil" server fn purges related rows |
| Integrity and confidentiality | See Art. 32 below |
| Accountability | This document, plus tamper-evident audit logs (see Art. 30) |
Art. 6 / Art. 9 — Lawful basis
See section 1.
Art. 12–14 — Transparency
privacy.mdis published at/privacyon the live site- Privacy notices for pupils and parents are surfaced inline at the point of voice capture
- Sub-processor changes use
subprocessor-change-template.mdfor 30-day notice
Art. 15 — Right of access (DSAR)
- DSAR export server function in
src/features/dsar/*.functions.ts - Restricted to roles
admin,senco,inclusion_lead(enforced by RLS + server-fn role check) - Tenant-scoped: caller can only export pupils where
school_id = caller.school_id - Returns machine-readable JSON covering profile, plans, targets, reviews, voice captures, audit trail
- Runbook:
pdpl-dsr-runbook.md
Art. 16 — Right to rectification
- Admin UI provides editing for pupil profile, plan, targets
- All mutations write to
audit_logswith before/after diff
Art. 17 — Right to erasure
- "Erase pupil" server function purges pupil row and cascades to plans, targets, voice captures, AI cache entries
- Restricted to
admin,senco,inclusion_lead - Erasure event is recorded in
system_audit_logs(tamper-evident) so the act of erasure remains provable after the underlying data is gone
Art. 18 — Right to restriction
- Pupil status field (
active/restricted/archived) blocks further processing without deleting - Restricted pupils are excluded from AI Gateway calls and analytics aggregates
Art. 20 — Right to data portability
- DSAR export is structured JSON, machine-readable, schema-stable
- Suitable for transfer to a successor system
Art. 21 — Right to object
- Documented in
privacy.mdwith controller contact route
Art. 22 — Automated decision-making
- OMNIA does not make solely automated decisions with legal or similarly significant effects
- AI-assisted suggestions (e.g. access arrangements) are always presented as recommendations for a human (SENCo/inclusion lead) to accept, edit, or reject
- This is enforced in the UI: no AI output is committed to a pupil record without an explicit human "Apply" action
Art. 25 — Data protection by design and default
- Multi-tenant isolation enforced two ways: Postgres Row-Level Security and explicit
.eq("school_id", schoolId)on every server-fn read/write (RLS alone is treated as insufficient) - Only superadmins can change
profiles.school_id, and never their own (enforced by triggertg_profiles_guard_school_id) — closes the self-reassign privilege-escalation path - New tables ship with RLS enabled and explicit
GRANTs in the same migration
Art. 28 — Processor obligations
- Data Processing Agreement provided to every school customer
- International transfer addendum:
dpa-international-addendum.md(IDTA + EU SCCs as appropriate) - Sub-processor list with 30-day change notice:
sub-processors.md,subprocessor-change-template.md
Art. 30 — Records of processing
audit_logsrecords all controller-relevant mutations (pupil, plan, target, voice, role)system_audit_logsrecords platform-level events (auth, role grants, erasure, key rotation)- Both tables are tamper-evident:
UPDATEandDELETEare denied forauthenticatedandanonviaUSING (false)RLS — onlysupabaseAdmin(server-side, service-role) can mutate. There is no in-app UI that writes these tables.
Art. 32 — Security of processing
| Control | Implementation |
|---|---|
| Encryption in transit | TLS 1.2+ on all endpoints |
| Encryption at rest | AES-256 (managed by AWS / Supabase) |
| MFA for privileged users | TOTP required for admin and superadmin — /admin and /superadmin shells gate on AAL2 + verified factor, redirect to /mfa otherwise |
| Magic-link safety | redirectTo validated against the request origin to prevent open-redirect / token theft |
| Public token endpoints | enforceRateLimit (per-IP + per-token buckets, backed by public.rate_limits) on pupil-voice, parent-voice, and plan-share; salted with RATE_LIMIT_SALT |
| AI Gateway | All outbound calls pass through callLovableAiChat, which scrubs PII via scrubPii/scrubMessages before the payload leaves the server |
| Cron / webhook endpoints | /api/public/hooks/* gated by CRON_SECRET bearer — never the publishable/anon key |
| Service-role key | Server-only; rotated on suspected exposure (last rotation: 2026-05-27) |
| Database access | No public Postgres endpoint; gated by Supabase Auth + RLS |
| Storage buckets | inspection-packs requires role check in addition to school-folder path match |
| Secret columns | pin_hash, pin_salt, token_hash, webhook_secret, api_key, api_key_ciphertext — column-level SELECT revoked; server reads via supabaseAdmin only |
Art. 33–34 — Breach notification
- Detection: audit log review + Supabase alerting
- Procedure:
breach-sop.md - Controller notification: within 24 hours of confirmation, well inside the 72-hour ICO window so the controller can meet their own obligation
Art. 35 — Data Protection Impact Assessment
- Project-wide DPIA:
dpia.md - Reviewed on material change (new sub-processor, new data category, new AI use case)
Art. 37–39 — DPO
- Lovable acts as processor; controller (the school/MAT) retains DPO duties
- Lovable provides reasonable assistance under Art. 28(3)(f)
Art. 44–49 — International transfers
- Primary hosting: AWS eu-west-1 (Ireland) — no transfer outside the EEA for the core database, storage, or auth
- AI Gateway (standard mode) routes to EU-resident model providers where available; payloads are PII-scrubbed before leaving the server regardless
- BYOK (Connected tier opt-in): schools may route AI traffic to their own Anthropic or Azure OpenAI tenancy in a region of their choice (e.g.
uksouth,uaenorth). Where the elected region sits outside the UK/EEA, the school is the controller of its provider relationship and is responsible for the transfer-impact assessment; PII scrubbing still applies before egress. API keys are AES-256-GCM encrypted at rest (BYOK_ENC_KEY). - Where a sub-processor operates outside the EEA, transfer is covered by IDTA / EU SCCs — see
dpa-international-addendum.md
3. Tenant isolation — the load-bearing control
The single most important GDPR control in a multi-tenant SEND platform is preventing one school's data from leaking to another. OMNIA enforces this with defence in depth:
- Postgres RLS on every table containing tenant data, scoped by
has_school_access(school_id)oris_superadmin() - Explicit
.eq("school_id", schoolId)on every server-function read and write — RLS is the backstop, not the gate - Staff admin server fns tenant-scope via
getAdminScope()+assertTargetInScope(); never callsupabaseAdmin.auth.admin.listUsers()unscoped profiles.school_idis locked — only superadmins can change it, and never on their own profile (trigger-enforced)- Audit trail records every cross-tenant action attempted by a superadmin
4. Data residency
- Primary region: AWS
eu-west-1(Dublin, Ireland) - Backups: retained within the same region
- Egress: outbound HTTPS only, to documented sub-processors
See data-residency-decision.md and data-residency-one-pager.md.
5. Operational guardrails — what keeps compliance "at all times"
Compliance is not a one-time architecture decision. The following operational rules are enforced on every change:
- Every new
publictable must ship with RLS enabled and explicitGRANTs in the same migration - Every new server-function read/write touching tenant data must include
.eq("school_id", schoolId) - Every new outbound AI call must go through
callLovableAiChat(which scrubs PII) — directfetchto a model provider is only permitted with an inlinescrubPiicall - Every new public endpoint must call
enforceRateLimitas the first line of the handler - Sensitive columns added to the schema must have column-level
SELECTrevoked fromauthenticated/anon - Migrations that touch RLS policies, role grants, or audit-log policies require a security review note in the PR
These rules are encoded in the project memory and applied to every change.
6. Contact
- Processor (Lovable): see
company-info.md - Controller (school/MAT): the customer's own DPO
For data subject requests, the data subject should contact their school's DPO in the first instance; the school then uses the in-app DSAR/erasure tools to fulfil the request.