Docs: Security & access model
Security & access model
On this page
The map is metadata
Maplith stores the *shape* of your data landscape — object names, field names, relation statistics, finding descriptions — never row-level data. Uploaded export files are inputs to a scan: they are deleted from storage after the scan completes, whether it succeeded or failed. PII *values* are minimised, not absent: findings quote evidence, and field descriptions can quote example values. Maplith tries to mask email local parts, Danish CPR numbers, IBANs and payment card numbers — when they are well-formed: a CPR number with a valid date, an IBAN or a card number that passes its checksum — before anything is sent to the model, and again in the descriptions and findings the model writes before they are stored. It also tries to mask the names of people it reads from your export's own name columns — first name, contact person and the like — wherever those names appear in what a build sends to the model and stores, and the phone number a helpdesk export declares on a contact; name masking is on by default, with a switch under Settings › Privacy & masking. It is a best-effort safeguard, not a guarantee. A workspace can add its own masking terms under Settings › Privacy & masking, and a build applies them wherever it applies the four; a term added later applies from the next build on, not to what is already stored. A name that appears only in free text, and any other phone number, are not masked unless you add them as masking terms. You decide what your export contains; leave out what must not be processed. PII *fields* carry a personal classification — contact, identity, financial, special category, other, or none, with where the verdict came from (the column name, the shape of the values as counts, or you) and how sure it is — set by the scan and corrected by a workspace admin under Business map › Personal data; a correction stays, and a later scan that reads the field differently asks first. pii is true for any category but none. A field the scan could not assess is shown as not checked, first in Business map › Personal data, until someone marks it.
Text already shaped like a masked value
Maplith tries to mask your masking terms, and the names of people it finds in your export's name columns, wherever they appear. It writes a masked value as its label, a space and three asterisks, all inside square brackets: [person ***], [member number ***]. Text that already has that shape is treated as masked and left as it is. That is deliberate: masking is applied at several steps in turn, and it only stays safe to do so if masking text that is already masked changes nothing.
The shape is exact: an opening square bracket; 1 to 40 characters that are only letters, spaces or hyphens; a space; three asterisks; a closing bracket. The shape also holds with a six-character code of the digits 0–9 and the lower-case letters a–f between the asterisks and the bracket, the form Maplith uses during a build. So if your export itself contains text such as [Pia Sørensen ***], a term inside that bracket (here "Pia Sørensen") is not masked there. The same term anywhere else in the text is handled as usual.
What this does not affect:
- Format terms. Every format holds at least one digit, and a digit cannot stand in that shape.
- Terms with a digit or with any character other than a letter, a space or a hyphen: an order number, an email address, a name with a full stop.
- The four identifiers masked without a term (email local parts, CPR numbers, IBANs, card numbers), for the same reason.
What you can do: you decide what the export contains. If your exports write names in that literal shape, change the export so they do not, or tell us and we will look at it with you.
Access control in two dimensions
Dimension 1 — roles. Organisation roles (owner, admin, member) govern the account. Workspace roles govern each map: admin (manage members, keys, integrations), builder (run scans, work with the map), viewer (read).
Dimension 2 — grants. Independently of role, a user can be narrowed to specific domains (e.g. Finance but not HR) or down to specific objects. A grant filters everything: objects, relations, search results and findings. A finance controller sees the Finance slice of the map and only the findings that touch it.
What each workspace role may do (enforced server-side on every action):
| Capability | viewer | builder | admin |
|---|---|---|---|
| Read the map, findings, processes, metrics (within grants) | ✓ | ✓ | ✓ |
| Upload exports, run scans, connect systems | — | ✓ | ✓ |
| Work with findings (change lifecycle status) | — | ✓ | ✓ |
| Manage members, roles and grants | — | — | ✓ |
| Issue and revoke agent keys; set agent policies | — | — | ✓ |
| Decide agent approval requests | — | — | ✓ |
An external consultant working across several customers is simply a member of each of those workspaces — typically as builder, optionally grant-narrowed. They can update what you let them touch, and can never delete, manage members or issue keys.
Member types. Every member carries a type, visible in the member list: employee (your own people), consultant (external, labeled so everyone can see it), or Maplith staff — our personnel, a label only we can set, so you always know when we are in your workspace. Type never grants capability; roles and grants do.
When Maplith staff look at your map. A support case can need one of us inside your workspace. That happens in one way only: a member of Maplith staff opens read-only access with a written reason, your organisation's owners — and your privacy or DPO contact, if you have registered one under Settings › Organisation — are emailed the moment it opens (which workspace, who, why, until when), and a notice with the same sits at the top of the workspace for everyone in it. The access sees what a viewer sees — never uploaded files, agent keys or connections — changes nothing, ends by itself four hours after it opened and cannot be extended; any admin of the workspace can end it sooner with one click. The opening, the notice, the first request and the end are recorded; reply to the notice email and we send you the record.
The same two dimensions apply to agent keys: scope (what the key sees) and policy (what it may do) — see Agent keys & policies.
Enforcement
All access control is enforced in the database layer (PostgreSQL row-level security) — not in application code that could be bypassed. Agent keys are stored as hashes. GitHub webhook deliveries are HMAC-verified before anything else happens. The hosted agent acts only in private repositories, only under an explicit policy, with hard daily caps.
Signing in
You sign in with a link sent to your email, or with Google, Microsoft or GitHub. Anyone can add two-factor authentication under Account security in the account menu: scan a code with an authenticator app (Google Authenticator, Microsoft Authenticator, 1Password and similar), and from then on Maplith asks for a fresh code from that app each time you sign in. Until the code is entered, the app shows no workspace page and accepts no change, and the database behind it refuses that session every read and change of your workspace data, even when asked directly rather than through the app. Only the checks of the session's own access to IDs it already holds still answer, such as whether it belongs to a workspace, its role there and which parts of the map it may see. So a stolen email or account login alone is not enough to reach your workspaces. Our authentication provider keeps the app you register, not Maplith's own tables. Removing an app needs a session that has already passed the code step.
Where your workspace enables Slack decisions, you can link your own Slack account after two-factor sign-in in the app. The linked account counts as your second factor for decisions in Slack; your workspace permissions still apply. Unlinking Slack or removing your last app factor revokes that link immediately. Each Slack decision records your linked Slack identity. In those workspaces, key, access and policy changes send an independent confirmation.
Keep a way back in: add the app on a second device too. There are no recovery codes; if you lose every device, write to [email protected] and we confirm it is you — by more than an email from the same address — before we turn two-factor off for your account.
Agent keys are separate credentials with their own scope and policy, so assistants connected with a key are not asked for a code. Connecting a new assistant does ask: the consent that issues its key is a sign-in like any other.
Hosting
Application, database and file storage are hosted in the EU (Supabase Frankfurt, Railway EU). Mail is delivered through Resend's EU infrastructure in Ireland, though Resend itself processes in the United States. Model inference is not in the EU: during a scan, file samples and, in the findings step, whole files go to Anthropic's API in the United States. The sub-processor list names every provider, where it processes and on what basis; the processing and security description states what each one receives and what is kept, for how long; the Data Processing Agreement and the privacy policy state the commitments and how to exercise your rights. Transactional mail is sent from an isolated subdomain. We are the product's own first customer — Maplith scans Maplith daily and publishes the discrepancies it finds about itself to our own ops channel.