SECURITY
Data Flows
Data Flows
Version: 1.0
Last updated: April 2026
Contact: security@gatewaychecker.co.uk
Overview
This document describes how personal data and customer content move through the Gatewaychecker platform. Each data flow identifies what data is involved, which systems handle it, and the applicable safeguards.
All flows operate over HTTPS (TLS 1.2+). All data at rest is encrypted with AES-256 via AWS KMS. No unencrypted personal data is transmitted between any system components.
Data Flow 1: User Registration and Authentication
Trigger: A new user signs up or an existing user signs in.
Data involved: Email address, one-time authentication token, organisation name (registration only).
Flow:
- User enters their email address at gatewaychecker.co.uk/login.
- The application calls Supabase Auth to send a magic link. Supabase generates a one-time token and sends a sign-in email via its internal email infrastructure.
- The user clicks the magic link. Their browser is redirected to
/auth/callbackwith the token. - The Next.js callback route exchanges the token with Supabase Auth for a signed JWT session.
- The JWT is stored in an httpOnly cookie scoped to gatewaychecker.co.uk. No session data is written to localStorage.
- For new users completing onboarding: the organisation name is written to the
organisationstable and linked to the user viaorganisation_members.
Systems involved: Supabase Auth (EU), Vercel (EU), customer's email provider.
Personal data stored: Email address in Supabase Auth. Organisation name in organisations table. No passwords are stored at any point.
Data Flow 2: Document Upload and Analysis
Trigger: An authenticated user submits documents for Gateway 2 analysis.
Data involved: PDF document content (may include duty holder names, building addresses, technical specifications), project name, extracted text.
Flow:
- User uploads a PDF or ZIP archive via the Gatewaychecker web interface.
- The file is sent over HTTPS to the Next.js
/api/extract(PDF) or/api/extract-zip(ZIP) route. - Text is extracted server-side using pdfjs-dist / unpdf. The raw file bytes are not stored; only extracted text is retained.
- Extracted text is written to the
documentstable in Supabase (PostgreSQL, AWS eu-west-1). Each document record is scoped to the submitting organisation viaorganisation_id. - The analysis job is dispatched by calling the Supabase Edge Function
analyse-submission. The Edge Function runs in the same AWS eu-west-1 region. - The Edge Function generates embeddings for each document chunk using the OpenAI embeddings API, storing vectors in
document_chunks. - For each criterion, the Edge Function sends a prompt containing the relevant document text to the Anthropic Claude Sonnet API via OpenRouter. The text transmitted to Anthropic is used solely for the inference call and is not retained, stored, or used for model training by Anthropic or OpenRouter. This is governed by Anthropic's API terms of service.
- Structured JSON findings are returned by Claude and written to the
findingstable in Supabase. - The UI polls
/api/submissions/[id]/statusevery 3 seconds. On completion, findings are fetched and displayed.
Data crossing EU boundary: Extracted document text is transmitted transiently to the Anthropic API (US) for AI inference. This transmission is covered by our Data Processing Agreement with OpenRouter. Anthropic's API terms prohibit training on submitted data.
Systems involved: Vercel (EU), Supabase (EU), Supabase Edge Functions (EU), OpenRouter (US — routing only), Anthropic (US — inference only).
Personal data stored: Extracted document text in documents table (Supabase, EU). No data is retained by Anthropic or OpenRouter after inference.
Data Flow 3: Collaborator Invitation
Trigger: An account owner or admin invites a team member to collaborate on a submission.
Data involved: Invitee email address, inviter name, submission reference.
Flow:
- The inviter enters the collaborator's email address in the Gatewaychecker workspace UI.
- The application writes a collaborator record to the
collaboratorstable with aninvite_token(cryptographically random UUID). - An invitation email is sent via the Resend API (EU). The email contains a unique acceptance link at
/invite/[token]. - When the invitee clicks the link, the token is validated server-side. If the invitee is not an existing user, they complete authentication via magic link before accepting.
- On acceptance, the
accepted_attimestamp is set on the collaborator record. The invitee gains access to the submission scoped by RLS.
Systems involved: Vercel (EU), Supabase (EU), Resend (EU).
Personal data stored: Invitee email address in collaborators table (Supabase, EU). Resend retains email delivery records per its data retention policy.
Data Flow 4: Report Generation and Download
Trigger: An authenticated user downloads a risk report for a completed submission.
Data involved: Project name, submission date, risk score, all findings (criterion IDs, evidence text, remediation recommendations).
Flow:
- User clicks "Download Report" (PDF) or "Download Word" (.docx) on the dashboard.
- For PDF: the report is generated client-side using jsPDF. No server call is made; no data leaves the browser.
- For Word (.docx): the browser calls
/api/report/[submissionId]/docx. The server-side route fetches findings from Supabase, generates the .docx using thedocxlibrary, and returns the file as a binary response. - The file is downloaded directly to the user's device.
Data leaving the platform: The report is downloaded to the user's local device. Gatewaychecker does not transmit or store the generated report on third-party services.
Systems involved: Vercel (EU), Supabase (EU), user's browser.
Data Flow 5: Shareable Report Link
Trigger: A user shares a read-only report link with an external party (e.g., a building control consultant).
Data involved: Risk score, findings, evidence text, remediation actions — all relating to a specific submission.
Flow:
- User clicks "Share Report" on the submission page. The URL
/report/[submissionId]is copied to clipboard. - The shared URL does not contain any personally identifiable information. The submission ID is a UUID with no connection to personal data.
- The
/report/[submissionId]route is publicly accessible without authentication. It fetches only non-personal submission data (score, rating, findings) from Supabase. - The shared page includes a prominent advisory disclaimer and no user account information.
PII in shared reports: Shared reports do not contain any user account information (email addresses, organisation names). They contain only the technical findings for the submission. If the customer's documents contain duty holder names and that information is cited in evidence text, it may appear in findings. Customers are advised to review findings before sharing.
Systems involved: Vercel (EU), Supabase (EU).
Data Flow 6: Billing
Trigger: A customer initiates a subscription or makes a payment.
Data involved: Billing name, billing email, payment card details, billing address.
Flow:
- The customer clicks "Upgrade" or selects a plan on the Gatewaychecker billing page.
- The application creates a Stripe Checkout session via the Stripe API and redirects the customer to a Stripe-hosted payment page.
- The customer enters their payment card details directly into Stripe's hosted page. Payment card data never passes through Gatewaychecker servers. Gatewaychecker receives only a Stripe customer ID and subscription status.
- Stripe sends webhook events (e.g.,
checkout.session.completed,invoice.paid) to the Gatewaychecker webhook endpoint. These events contain subscription metadata but no card data. - On successful payment, the organisation's
subscription_tierandsubscription_statusare updated in Supabase.
PCI-DSS: Payment card processing is handled entirely by Stripe (PCI-DSS Level 1 Service Provider). Gatewaychecker is out of PCI-DSS scope for cardholder data.
Systems involved: Vercel (EU), Stripe (EU + US), Supabase (EU).
Data Flow 7: Email Notifications
Trigger: A submission completes, a collaborator is invited, or a daily digest is due.
Data involved: Recipient email address, notification content (submission ID, project name, risk score summary).
Flow:
- On analysis completion, a notification record is written to the
notification_queuetable. - A Supabase Edge Function (scheduled notification runner) reads pending notifications and dispatches emails via the Resend API.
- For immediate notifications: the email is sent within minutes of the triggering event.
- For daily digest: the Edge Function runs at the user's configured digest time (UTC) and batches all pending notifications into a single email.
- Resend handles email delivery. Gatewaychecker receives delivery status webhooks.
Systems involved: Supabase Edge Functions (EU), Resend (EU), customer's email provider.
Personal data processed by Resend: Email address and email body content. See the Sub-processors page for Resend's DPA and compliance details.
Data Flow 8: SharePoint / OneDrive Integration (optional)
Trigger: A user connects their Microsoft 365 account and imports documents via the SharePoint browser.
Data involved: Microsoft account email, OAuth access and refresh tokens, SharePoint file metadata and PDF content.
Flow:
- User clicks "Connect Microsoft 365" in Settings. The application redirects to the Microsoft OAuth 2.0 authorization endpoint with the required scopes (
Files.Read.All,Sites.Read.All,offline_access). - The user authenticates with Microsoft and grants consent. Microsoft redirects back to
/api/auth/microsoft/callbackwith an authorization code. - The application exchanges the code for access and refresh tokens via Microsoft's token endpoint. Tokens are encrypted using AES-256-GCM (random IV per token) before storage in the
microsoft_connectionstable. The encryption key is held in Vercel environment variables. - When browsing SharePoint, the application calls the Microsoft Graph API using a valid access token. Only PDF files are listed; no file content is downloaded at browse time.
- When the user selects files to import, each PDF is downloaded via Graph API and text is extracted server-side. The imported document text follows the standard Document Upload and Analysis flow (Data Flow 2) from that point.
- The user may disconnect their Microsoft 365 account at any time from Settings. On disconnection, the
microsoft_connectionsrecord and all stored tokens are deleted immediately.
Systems involved: Vercel (EU), Supabase (EU), Microsoft Graph API (EU tenant — data location depends on the customer's Microsoft 365 tenancy).
OAuth token security: Tokens are encrypted at application layer (AES-256-GCM) and at infrastructure layer (AES-256 via AWS KMS). Microsoft access tokens are short-lived; refresh tokens are rotated on use.
Personal Data Summary
| Personal data | Source | Stored by | Shared with | Retention |
|---|---|---|---|---|
| Email address | Registration / login | Supabase Auth | Resend (delivery) | Account lifetime + 30 days |
| Organisation name | Onboarding | Supabase | None | Account lifetime + 30 days |
| Document text content | PDF upload | Supabase | Anthropic (transient, no retention) | Account lifetime + 30 days |
| Duty holder names (in documents) | Document content | Supabase | Anthropic (transient, no retention) | Account lifetime + 30 days |
| Risk findings and evidence | AI analysis | Supabase | None | Account lifetime + 30 days |
| Human override notes | Reviewer input | Supabase | None | Account lifetime + 30 days |
| Team member email addresses | Collaborator invite | Supabase | Resend (invite email) | Until removed from team |
| Payment card data | Stripe checkout | Stripe only | None | Never touches Gatewaychecker servers |
| Billing name and address | Stripe | Stripe | None | 7 years (accounting obligations) |
| Usage logs and IP addresses | Application | Supabase | None | 24 months |
| Microsoft 365 account email | OAuth consent | Supabase | Microsoft (API calls) | Until account disconnected |
| OAuth tokens (Microsoft) | OAuth exchange | Supabase (AES-256-GCM encrypted) | None | Until account disconnected |
Contact
Questions about data flows or personal data processing:
security@gatewaychecker.co.uk
privacy@gatewaychecker.co.uk
Questions about this document?
Contact security@gatewaychecker.co.uk