Skip to content
Security & data protection

An alumni database is one of the most sensitive lists you keep

Names, contact details, employment history, donations, sometimes health or accessibility notes — held for decades, about people who did not choose to be marketed to. Metrolo was built with those obligations in the foundations rather than added when a customer's legal team asked.

How it is built

Six decisions that shape everything else

One database per organisation

Metrolo is single-tenant. There is no shared members table with a tenant column, no query that could return another organisation's records if a filter were forgotten, and no noisy-neighbour risk. Your deployment can sit in whichever jurisdiction your legal team prefers.

Authorisation on the server, every time

Permission checks live in the API, not in the interface. Hiding a button is presentation; refusing the request is security. Every endpoint re-checks the grant, and the ownership fallback is applied in the same place rather than being reimplemented per screen.

Sessions in HttpOnly cookies

Authentication uses HttpOnly, Secure, SameSite cookies. There is no access token in localStorage for a cross-site script to lift, and the browser never holds a credential JavaScript can read.

Member-controlled visibility

Each profile field carries its own tier — public, members-only, private or hidden — chosen by the member. The tier is applied when the record is loaded, so a hidden field is absent from the response rather than merely absent from the page.

Uploads treated as hostile input

Files are type-sniffed on the server rather than trusted by extension, stored outside the webroot where no URL can reach them directly, and served only through short-lived signed links.

Rich text sanitised before storage

Anything a member or admin writes in a rich-text editor passes through one sanitiser with a closed allow-list before it is stored — not on the way out, and not in fifteen different places.

GDPR

Data-subject rights are features, not promises

Each of these is something a member can exercise from their own account, or your team can action on their behalf — not a process that lives in someone's inbox.

  • Right of access and portability

    A member requests an export from their own settings and receives an archive of everything held about them — profile, registrations, payments, posts, consents — in a machine-readable form.

  • Right to erasure

    A deletion request starts a 30-day window, then purges. Records that must survive for accounting or governance — a payment line, a vote count, an attendee total — are anonymised rather than orphaned, so your books still balance.

  • Consent, recorded and versioned

    Consent is captured at sign-up against a specific policy version. Publish a new privacy policy or terms and members are asked to accept again at their next login. What they agreed to, and when, is on the record.

  • Accountability and audit

    Every administrative action on member data is written to an append-only audit log as it happens — actor, action, record and timestamp — filterable when someone asks you to demonstrate what was done and by whom.

  • Rectification

    Members correct their own records directly. Where an administrator makes a correction on their behalf, the change is logged with the administrator's identity attached.

Operations

What runs, and how it is looked after

Deployment

  • Nginx and PHP-FPM in front of the API, a Node process serving the front end
  • TLS terminated at the edge; HTTP is redirected, never served
  • A queue worker for anything slow enough to make a request wait
  • A scheduler for reminders and for completing erasure requests on time

Data handling

  • Provider credentials and two-factor secrets encrypted at rest with the deployment key
  • Database backups on a schedule you set, plus the private upload disk
  • No third-party analytics on member-facing surfaces by default
  • A full export of every table and file on request, at any time

Development practice

  • Strict typing on both sides of the wire; validated payloads at every boundary
  • A feature test per endpoint covering the happy path, auth failure and validation failure
  • Dependency audits in the pipeline for both the PHP and JavaScript trees
  • One sanitiser, one payment predicate, one permission layer — shared, not copied
Responsible disclosure

Found something? Tell us before you tell anyone else.

Email security@metrolo.io with what you found and how to reproduce it. We will acknowledge within two working days, keep you updated while we fix it, and credit you if you would like to be credited. We will not take legal action against anyone who reports in good faith and does not access data that is not theirs.

Send us your security questionnaire

Procurement usually arrives with a spreadsheet. Send it over — we would rather answer it properly now than discover a blocker three weeks into onboarding.