Security & data handling

Meshie asks you to connect real, production credentials for systems you depend on. Before you do, here is exactly what we request, exactly what we do with it, and what we don’t touch. Where something isn’t built yet, it says so, rather than describing a policy that doesn’t match the product.

What we access, per system

Every connection below is read-only in practice: our code never calls an endpoint that would let it write to your systems, and never queries your business records. Where what we read goes beyond structure, it is spelled out below: Salesforce usernames and field-history counts, Snowflake session counts, and sample data that n8n can keep inside a workflow definition.

Salesforce

We retrieve your org’s metadata (object and field definitions, page layouts, flows, and other configuration) the same way the Salesforce CLI’s own metadata retrieve does. To make that retrieve cover your standard objects’ custom fields, we query the EntityDefinition and FieldDefinition setup objects (through the Tooling API) for object and field names. Separately, we query the ConnectedApplication setup object (id and name) to see what other tools are connected to your org. We never query Lead, Contact, Opportunity, Account, or any other business-record object.

To show what your integrations can change, and what they actually change, we look for integration users. We query User for the id and username of active users with an integration license, PermissionSetAssignment for the permission sets assigned to those users, and FieldPermissions for the custom fields those permission sets can edit. Each integration user’s username is kept, and appears in your workspace’s dependency map. For fields with history tracking turned on, we then run aggregate queries over the matching field history objects (for example AccountHistory or OpportunityFieldHistory), limited to those integration users and the last 90 days. Each result row is only a field name, the writing user’s id, a count of writes, and the date of the latest one. No record id, old value, or new value is requested or stored, and edits made by people rather than integration users are never counted.

On every rescan after the first, we also query the SetupAuditTrail setup object for the setup changes made since the previous scan, so the What changed card can say who made each change. We read only when each entry was made, who made it (their Salesforce user id and display name), and the entry’s section, action, and description. Entries about managing users, logins, passwords, and permission set assignments are discarded as soon as they are read. The rest are kept on the scanning server’s local disk, never in our database, and deleted when that scan’s changes are compared. What we store, next to a change, is only the Salesforce user id and display name of the admin matched to it, plus the audit trail’s section and action labels for that entry. The display name is shown to members of your workspace; Slack and email notifications say how many changes a named admin made, never who. If the connected user can’t read the audit trail, the scan continues without it and says so.

HubSpot

We call HubSpot’s property-schema and workflow-definition endpoints (/crm/v3/properties, /automation/v4/flows) to see how your objects and automations are configured. We never call an endpoint that returns Contact, Company, or Deal records.

Make

We list your scenarios and read each one’s blueprint: the modules and field mappings that make it up. We never see the actual data that flows through a scenario when it runs.

n8n

We read your workflow definitions (nodes, connections, and field references) from the instance URL you provide, through n8n’s workflow list endpoint. We don’t read execution history. We do store each workflow definition whole, as n8n returns it, so anything n8n keeps inside a definition is stored with it: node parameters, including any value typed directly into a node, and pinned sample data (n8n’s pinData), which can be copied from a real run. If a workflow has pinned data you don’t want us to hold, unpin it in n8n before you connect.

Snowflake

We query INFORMATION_SCHEMA.TABLES and .COLUMNS for your schema, and (when the connected role can read it) view/table dependency data from ACCOUNT_USAGE.OBJECT_DEPENDENCIES. When the role can read it, we also run one aggregate query over ACCOUNT_USAGE.SESSIONS: the number of sessions per client application over the last 90 days, to see which other tools connect to your account. It returns no user names and no query text. We never query the actual rows in any table.

BigQuery

For the one dataset you connect, we query INFORMATION_SCHEMA.TABLES and .COLUMNS for your schema, and (when the service account can read it) INFORMATION_SCHEMA.VIEW_TABLE_USAGE for which tables each view reads. We never query the actual rows in any table.

dbt platform (formerly dbt Cloud)

We fetch the manifest from a job’s most recent successful run: model and source definitions and the dependency graph between them. We never trigger a job or read the data a model builds.

Fivetran

We list your connectors and read each one’s destination schema configuration: which tables and columns are actively enabled for sync. We never see the row data a sync moves.

Fivetran Activations (formerly Census)

We read your syncs’ configuration: which source column, constant, or template feeds which destination field, and the list of your sources and destinations so we can tell which system each sync writes to. Fivetran’s newer API does not say that yet, so when your token belongs to an organization admin, each scan also reads your workspaces’ API keys, uses them only for those same read calls to Fivetran’s older API, and never stores them. We never read the data a sync actually moves.

Hightouch

We read your syncs and models: which warehouse columns a sync depends on, which model it reads, and which destination it writes to. We never read the data a sync actually moves, and never the contents of your warehouse.

Workato

We read your recipes’ configuration: each step’s connector, the fields it maps, and which earlier step each value comes from. We never read the records a recipe moves between your apps.

An OAuth grant (Salesforce, HubSpot) is necessarily broader than the handful of endpoints we actually call. That’s how those platforms’ permission models work, not a scope we’ve hand-restricted. The commitment we can make and keep is about our own code: it doesn’t read or store your business records, and you can verify that’s exactly what each connection above says it does.

How your data is isolated and protected

The credentials we store, including OAuth tokens, API keys, and passwords for the systems you connect, are encrypted before they touch our database, not stored as plain text at rest, and none of them is ever shown back to anyone, including members of your workspace. Passwords for Meshie itself are hashed, never stored in plain text.

Every request to your workspace’s data is scoped by your membership in it, checked on every single API call, not by convention or by trusting the URL you happen to be on, with one narrow, disclosed exception: our own support staff, described below. We maintain an automated test suite whose entire job is trying to break this (reading or modifying one workspace’s data while authenticated as a member of a different one), and it has to show zero successful attempts before any change ships.

Staff impersonation, disclosed plainly

A small number of our own staff can start a support session against your workspace to help debug an issue. This is not a silent capability. A session is read-only: it can see what the least-privileged Member role can see, and every attempt to change anything is refused, including asking Ask AI questions, drafting a proposed change, creating a CLI token, connecting or disconnecting a system, inviting anyone, changing roles, and touching billing. A session expires automatically after 30 minutes and requires a staff member to state a reason before it starts. It also ends as soon as that staff member logs out, changes their password, or loses staff access. That reason, who started it, and when it ended are all recorded permanently.

You would see it happening: while a session is active, every member of your workspace sees a banner on every page saying that a Meshie staff member is viewing the workspace for support, and since when. Your workspace’s own audit log, described below, records the start of every session with its reason, every change it tried and was refused, and its end and what ended it when it is stopped by hand or ended by a logout, a password change or loss of staff access (a session that simply runs out its 30 minutes has no end entry), all attributed to “Meshie staff”. No standing account is created in your own Members list: the access exists only for that one session and disappears when it ends.

There is currently no workspace-level setting to require your explicit approval before a session like this can start. If that matters for your organization, tell us before you connect.

Connecting AI apps

Any member can connect an AI app, such as Claude or ChatGPT, to Meshie by signing in through OAuth instead of pasting a token. You approve each connection on a Meshie consent screen, for one workspace; it acts with your own role there and only the permissions you approved. Sign-in codes are only ever sent to a fixed list of redirect addresses we have checked for each supported app, plus addresses on your own computer for desktop and command-line apps, so an address someone else registered cannot capture your approval. Access tokens last one hour, are stored only as a hash, and stop working as soon as you revoke the connection under Settings, Connected AI apps, or leave the workspace. OAuth codes and tokens in sign-in requests are removed from our request logs.

What a connected AI app reads from Meshie goes to that app’s vendor, under your own account and their terms, not ours.

Audit log

Every workspace has an audit log. Owners and admins can read it under Settings, filter it by action, and export it as a CSV file. Each entry records when it happened, who did it (their email address, the name of the CLI token or connected AI app they used, or “Meshie staff” for a support session), the action, and what it applied to.

It records member role changes and removals; invites sent, revoked and accepted; every system connected or disconnected; scans started by a person or a CLI token (scheduled rescans are not listed); CLI tokens created or revoked, with their name and scopes; AI apps connected or disconnected; AI provider keys added or removed, by provider; notification destinations added or removed, by type; changes to the Unused checklist; outcomes recorded for proposed changes; requests to delete the workspace; the start of Meshie support sessions, their end when one is ended before it runs out, and any change a support session tried and was refused. Questions asked in Ask AI and changes drafted with Propose are kept in their own history, not in the audit log.

Entries can’t be edited or deleted by anyone through the app. They never contain passwords, API keys, tokens, OAuth data, or webhook addresses, and for an email notification destination only the domain is recorded. Entries are kept for as long as the workspace exists and are deleted along with it.

Disconnecting and deleting your data

Disconnecting a system deletes the credential we stored for it (for Fivetran, both the API key and the secret) and permanently deletes everything we retrieved through that specific connection: the stored configuration snapshot and our record of it. Data from any other system you still have connected is untouched.

Disconnecting does not yet revoke the OAuth grant on the vendor’s side for Salesforce or HubSpot. Without the stored token we can no longer use it, but to remove the grant itself, revoke it yourself: in Salesforce, under Setup, Connected Apps OAuth Usage; in HubSpot, under Connected apps in your account settings. For systems connected with an API key or token, delete or rotate that key in the vendor’s settings.

An owner can permanently delete the entire workspace (every connection, every retrieved snapshot, every chat message, every member’s access to it) from the workspace’s Danger zone settings page. It’s a hard delete with no grace period: there’s no trash to restore it from in the app, and it requires typing the workspace’s slug to confirm before anything happens. Any active subscription is cancelled as part of the same action. This deletes the workspace, not your login: if you belong to other workspaces, your access to them is untouched.

We keep database backups for disaster recovery, so data you delete (a disconnected system’s snapshot or a whole workspace) can still exist in a backup taken before you deleted it. Backups are kept for 30 days and then deleted automatically, so deleted data ages out of them on the same schedule.

Roles and access within your workspace

Three roles, no custom permission builder. Owner can do everything an Admin can, plus manage billing, delete the workspace, and grant or remove the Owner role. Admin can connect and disconnect systems, run scans, set up AI providers, and invite, remove, or change the role of members and other admins. Member can explore the map, search, check impact, and use Ask AI, but can’t connect systems or manage people. Who can connect or disconnect a system, and who can just look, is enforced the same way tenant isolation is: on every request, not just in the interface.

Hosting and subprocessors

The app and its database run on Fly.io, in the iad region (Ashburn, Virginia, US East). Database backups are stored separately, in Tigris, an S3-compatible object store.

We use a small, fixed set of subprocessors to run the Service:

  • Fly.io, hosting for the app and its database.
  • Tigris, storage for database backups.
  • Anthropic, for the AI features: answering questions you ask Ask AI (in the app or through a connected AI app), and drafting and classifying changes you request with Propose. An Ask request includes your question and the dependency-map details the assistant looks up to answer it, which can include Salesforce integration usernames. A Propose request includes the text of the change you asked for. A workspace can use its own Anthropic API key instead of ours.
  • Stripe, to process payment for paid plans.
  • PostHog, for product analytics (session replay is switched off).
  • Resend, to deliver account-related email (password resets, workspace invites). Email delivery is not switched on yet: until it is, these emails are not sent and no data goes to Resend.

Every one of these is also named on our Privacy Policy.

Compliance

SOC 2 is not yet in progress. If that’s a requirement for your organization today, tell us before you connect. Better to know now than to find out it matters after the fact.