Security & trust

How PEMAX keeps every workspace apart.

PEMAX is multi-tenant from the first line of code. This page sets out how workspaces are isolated, how your keys are held, where data lives, who can get in, how AI is used, and what we do not claim yet.

Isolation
Row-level security enabled and forced on every table
Your keys
Bring your own, sealed per workspace
Hosting
In the EU: Frankfurt and the Netherlands
Access
TOTP MFA, a login trail, audited staff access

01 · Tenant isolation

Isolation lives in the database, and is checked twice.

A workspace's data is fenced off by Postgres row-level security keyed on the verified workspace claim of each transaction. The application's data plane enforces the same boundary in code, so a bug in one layer still meets the other.

  1. Browser01
    • Signed-in session
    • No database key
    • No provider key
  2. PEMAX web02
    • Acts as the user
    • Verified claims: workspace, role, markets, scope
    • No service-role key
  3. Data plane03
    • Every query scoped to the workspace
    • By-id reads assert ownership
    • Cache keys carry the workspace
  4. Postgres04
    • RLS enabled and forced on every table
    • Policies keyed on the verified claim
    • No app role bypasses RLS
Rows of your own workspace: returned
Rows of any other workspace: 0 rows, writes refused
  • Forced on every tableEvery table that holds workspace data carries a workspace id that cannot be empty, and every table has row-level security enabled and forced, so even the table owner is subject to it. No PEMAX database role can bypass it.
  • A denial matrix in CIOn every pull request, the people of one test workspace (owner, market admin, editor, viewer, own-scope rep) try to read and write another workspace's rows. One leak fails the build, and a structural check fails it if any table lacks forced RLS.
  • Ownership on every by-id readA request for one record asserts both its id and its workspace, on top of RLS. Cache keys carry the workspace id, and rotation of mailboxes or numbers never falls back to another workspace.
  • No service-role key in a request pathThe web app acts as the signed-in user and the database scopes what that user may see. The browser never holds a database key.
CI · rls-denial

$ node scripts/rls-denial-matrix.mts

fresh Postgres · every migration in order · two mirrored workspaces

PASS read-denial a_owner · prospects (0 rows of B)

PASS read-denial a_admin_nl · messages (0 rows of B)

PASS read-denial a_viewer · compliance_settings (0 rows of B)

PASS read-denial a_editor_own · call_recordings (0 rows of B)

PASS write-denial a_owner · INSERT prospect with tenant_id=B

PASS write-denial a_owner · UPDATE-move prospect A1 → tenant B

PASS own-scope · own1 UPDATE colleague's prospect A4 → 0 rows

PASS structural · every public table has RLS enabled AND forced

PASS structural · no PEMAX app role has BYPASSRLS

…

0 failed · any leak exits non-zero and blocks the merge

02 · Keys and credentials

Your keys, sealed per workspace.

PEMAX ships no shared vendor account. Each workspace connects its own mailboxes, telephony, data source, AI provider and CRM, under its own contracts. When you leave, your keys leave with you.

An admin enters

Your provider key

Apollo, Twilio, an LLM key. Held as a pending row for at most 15 minutes; the web app has no read on it.

The worker seals

AES-256-GCM

With this workspace's own data key, bound to the workspace and the credential: a copied blob does not decrypt.

The database stores

Ciphertext only

Never shown again in the app. Revealed only on the worker, per job, and every reveal is audited.

Each workspace's data key is wrapped by a key-encryption key that lives in Google Secret Manager (europe-west4) and is granted to the worker's runtime identity, never to the web.

The web plane never holds the key-encryption key. A lint boundary keeps the crypto out of its code and a boot gate refuses to start with it in its environment.

Bring your own key, for every outside service.

  • Platform secrets are kept in Google Secret Manager, never in code, config or an env file. The web app's share is copied into Vercel's encrypted environment at each approved deploy.
  • A provider key is entered once, by an admin, and never shown again.
  • Inbound webhooks are matched to their workspace before any signature is checked.
  • Decrypted values are never written to logs or error messages.
  • Google Workspace mailboxes

    Each rep connects their own mailbox through Google sign-in.

    Held: Tokens sealed per workspace. A revoked mailbox fails loudly instead of silently.

  • Twilio

    Your own account and numbers; PEMAX sets up its calling app on it.

    Held: Credentials sealed per workspace. Callbacks are matched to the workspace before their signature is checked.

  • Apollo

    Your API key and your credits.

    Held: Sealed by the worker, never shown again, metered against your budget.

  • LLM provider

    Your own API key, per workspace or per market.

    Held: Sealed by the worker; the gateway resolves it per workspace on every call.

  • Your CRM

    An HTTPS endpoint and its signing secret.

    Held: Qualified leads go out as signed webhooks with retries, dead letters and replay.

03 · Where data lives

EU hosting, component by component.

The database, the web app, the worker and the platform's secrets all run in the European Union: Frankfurt for the database and the web app, the Netherlands for the worker and the secrets.

  • Application databaseSupabase (Postgres)Frankfurt · eu-central-1

    Every workspace's data, each row carrying its workspace id. Provider credentials as ciphertext only.

  • Sign-inSupabase AuthFrankfurt · eu-central-1

    Accounts, sessions and second factors.

  • File storageSupabase StorageFrankfurt · eu-central-1

    Exports and uploaded files such as voicemail drops.

  • Job queuePostgres, same projectFrankfurt · eu-central-1

    Background jobs. A job carries a workspace id, not the workspace's data.

  • Web appVercel FunctionsFrankfurt · fra1

    Requests in memory only; no data store. TLS ends at Vercel's nearest edge location.

  • WorkerGoogle Cloud RunNetherlands · europe-west4

    Sending, inbox sync, call callbacks, sweeps. In memory only.

  • Platform secretsGoogle Secret ManagerNetherlands · europe-west4

    Database logins, signing keys and the key-encryption key, in their own Google project. Never your provider keys.

Sub-processors Mape Media engages

  • SupabaseDatabase, sign-in and file storage · Frankfurt
  • VercelHosting of the web app · functions in Frankfurt
  • Google CloudThe worker and the platform's secrets · the Netherlands

Services you bring

Google Workspace, Twilio, Apollo, your LLM provider and your CRM process data under your own contracts with them, on your keys. Call transcription is not switched on for client workspaces: no call audio leaves for transcription until the provider's data processing agreement is confirmed.

04 · Access control

Who can get in, and the trail they leave.

  • Two-step sign-in, failing closedTOTP second factors, required for admins by default or for every member in one click. The check sits where each request gets its authority; when it cannot decide, it asks for the code.
  • Roles with a rankViewer, editor, admin and owner, with admins per market or for the whole workspace. Nobody grants above their own rank, and own-scope reps see only their own prospects. Roles in detail.
  • A login trailSign-ins, sign-outs and password and second-factor changes, with IP address and user agent. Failed sign-ins are counted, rate-limited per IP and never tied to an account.
  • Audited staff accessMape staff act inside a workspace only for support. Every entry and exit is audited and shown to the owner, and resetting a lost second factor needs a reason and tells the member.
  • A fence on removalRemoving or suspending a member ends their sessions in that workspace. An access token already issued lives at most ten minutes; role changes apply at the next refresh.
Workspace security trail
  • 09:12Signed in, second factor verifiedInge Mulder
  • 09:31Invited femke.bos@… as Editor, own scopeJoost Hendriks
  • 10:02Mape staff entered the workspaceStaff · support
  • 10:19Mape staff left the workspaceStaff · support
  • 11:40Opened the transcript of a call by Pieter VosJoost Hendriks
  • 12:05Removed Pieter Vos, work handed to JoostJoost Hendriks

Sign-ins, second-factor changes, team changes, erasures, recording and transcript reads, and every staff act-as.

05 · Data lifecycle

Kept as long as it is needed, then gone.

Each kind of record has a window, set per workspace. A nightly sweep per workspace applies them, respects legal hold and writes one audit row with what it removed.

Retention by class

Transcripts and AI call summaries
90 days
AI triage results
180 days
Per-person attribution
365 days
Warmup texts, webhook payloads
30 days
Lawful basis evidence
24 months
Security audit rows
730 days

Defaults as shipped; each class has its own floor and ceiling. All limits

Erasure that sticks

An admin erases a prospect: personal fields, message bodies, call details, transcripts, enrichment and the raw provider record are cleared or anonymised, recordings are deleted at the provider, and audit rows naming the person are scrubbed.

The suppression entry for the email, phone and LinkedIn address stays, so a later import or sequence never reaches that person again. Erased data can never be exported.

Export, gated and counted

Admins export the workspace's data per dataset. Every member can take a personal export of their own data, three a day, each one audited.

Reading a call transcript or summary is gated like listening to the recording, and logged.

06 · AI

AI on your key, under your review.

PEMAX uses a language model to draft, classify and summarise. How it does so is set by rules in the product, not by a promise on this page.

  • Keys resolved per workspace

    The AI gateway looks up the key for each call: your own key for the market, then for the workspace. The platform's key is used only for workspaces on a staff allow-list, and stays unavailable to client workspaces until the provider's commercial terms are confirmed.

  • Reviewed by default

    An AI-drafted sequence step waits in Review before it is sent, in every market, unless the workspace owner switches that off. A failed draft falls back to the step a person wrote.

  • Marked, even after edits

    Every email whose first draft came from AI carries the machine-readable header X-AI-Generated: true, whether a person edited and approved it or not.

  • No emotion from voices

    Only the words in a transcript are analysed. A guard test fails the build if code asks the transcription provider for sentiment, emotion or tone from audio.

  • Triage, not decisions

    Reply labels sort the inbox; a person acts on them and can correct them, and the corrected label is the one every count uses.

  • Metered and capped

    AI use is metered per workspace. Platform-key use has a monthly cap that only staff raise; with your own key, your own caps apply.

Coming soon

Interactive drafting on your own LLM key. Today your own key runs PEMAX's background AI work, such as drafting sequence steps and summarising calls. Drafting with it from the composer in your browser needs a round trip to the worker that is not built yet, because the web app never decrypts keys.

07 · Engineering practice

Rules that fail the build when they are broken.

Security that depends on remembering does not last. Where we can, a rule is a test, a guard or a gate that stops the change.

  • Verified on a fresh database

    Every migration is applied in order to an empty Postgres and the suites run against it, so nothing passes because of state left behind.

  • Gates on every pull request

    Type checks, lint, unit tests, the cross-tenant denial matrix, a behaviour suite per work package and an end-to-end scenario of a full rep's day.

  • No side door around a rule

    Columns that only a rule-checking database function may write are guarded on 42 tables. A CI inventory fails on any new column a tenant role could write past its rule.

  • No public database API

    Supabase's REST interface is switched off. The browser never talks to the database; the web app holds no service-role key.

  • Production behind approvals

    Migrations and deploys run only from a workflow behind a protected production environment, each step approved by a person. Deploy-time credentials in a runtime environment stop the boot.

  • Infrastructure as code

    Cloud resources live in Terraform, validated in CI. Secrets are looked up by name; Terraform never creates or reads their values.

  • Pinned supply chain

    Every CI action is pinned to a commit, updates arrive as reviewed pull requests, and the images run as a non-root user.

  • Reviewed adversarially

    Each work package is reviewed by someone trying to break it before it is merged, and findings are fixed as a class, not one instance.

08 · What we do not claim

What we do not claim yet.

No third-party certification yet

  • No ISO 27001 certificate and no SOC 2 report.
  • No external penetration test so far.
  • No uptime SLA and no bug bounty programme.
  • No promise that your outreach is lawful: PEMAX enforces rules, and you remain the controller of your prospect data.
  • No EU-only AI inference: a model runs where the provider whose key is in use runs it.

PEMAX is in its first phase: Mape Media's own sales team is the first workspace, and new workspaces are invite-only. Everything above is how the product is built; ask us for the details behind any line.

Security questions and responsible disclosure

Questionnaires, architecture questions or a vulnerability you found: mail us. For a vulnerability, include the steps to reproduce it, do not access data that is not yours, and give us a fair chance to fix it before you publish.

contact@mapemedia.com

PEMAX is built and run by Mape Media, Eindhoven, The Netherlands.

Ask us the hard security questions.

Thirty minutes with the people who build PEMAX. Bring your questionnaire: we walk through isolation, keys, access and data flows on a real workspace and answer line by line.

Invite-only workspaces · Hosted in the EU · Bring your own keys