• Customermates logo
    CustomermatesDocumentation
  • Introduction
Getting Started
  • Quickstart
  • Core Concepts
Connect your AI
  • Custom connector
  • CLI & editors
  • Rate limits
Integrations
  • MCP
  • Webhooks
  • OpenAPI 3.1.0
  • N8N
Self-Hosting
  • Get Started
  • Architecture & Security
App guide
  • Dashboard
  • Inbox
  • Records
  • Profile
  • Company
  • API Keys
  • Filter Syntax
  • Go back
  1. Introduction
  2. Architecture & Security

Architecture and security

How Customermates is built, how data is isolated, and how external AI access is controlled.

Customermates enforces a single-tenant-per-company data model at every layer. Every record is scoped to a company, API keys carry the owning user's identity, and agents see only what that user can see.

Stack

  • Next.js 16 (App Router, Turbopack): web app and API.
  • PostgreSQL: primary datastore. JSONB for custom column values and webhook payloads.
  • Prisma: ORM and migrations.
  • better-auth: sessions, social login, API keys, MCP OAuth.
  • mcp-handler: Model Context Protocol endpoint.
  • TypeScript end to end, Zod-validated at every boundary.

Tenancy

Every record belongs to a Company. The company id is enforced in three places:

  1. App layer: every interactor resolves the current user's company and filters by it.
  2. Prisma layer: queries include companyId in every where.
  3. Decorator layer: @TenantInteractor makes interactors that fail to scope throw at runtime.

Cross-tenant reads are not possible through the public surface. There is no admin panel that bypasses scope.

Authentication

Three ways to authenticate:

  • Session cookie (UI): signed, http-only, Secure under HTTPS.
  • API key: 64-character base62 token (a-z, A-Z, 0-9), issued by the better-auth apiKey plugin, hashed at rest, tied to a user. Sent in the x-api-key header.
  • OAuth 2.1 (MCP): remote MCP clients can authorize via better-auth and send a Bearer token instead of an API key.

All methods resolve to the same user and company context.

Authorization

Per-user and role-driven. Roles carry permissions on resources (contacts, organizations, deals, services, tasks) and actions (read, create, update, delete). Every interactor calls userService.hasPermissionOrThrow(resource, action) before acting.

API keys inherit the permissions of their owning user. There is no per-key scoping.

External AI access

MCP requests use the same authentication and authorization path. When an agent acts through MCP:

  • It calls /api/v1/mcp with an API key or an OAuth Bearer token.
  • The server resolves user and company from the credential.
  • Every tool call runs inside a tenant-scoped context.
  • Validation errors return structured messages with remediation hints and do not leak internal schema details.

The MCP surface adds input guardrails to keep tool calls safe:

  • Passing null on a relation array is rejected before it reaches the database.
  • Update tools targeting the wrong record type are rejected with a pointer to the correct tool.
  • Destructive tools require an explicit list of record ids. There is no delete-by-filter shortcut.

See MCP for the full tool catalog.

Data at rest

  • Postgres encryption depends on your provider. On the managed cloud, data lives in an EU region with disk-level encryption at rest.
  • Secrets in .env are never logged. The logger redacts anything that looks like a key, token, or password.
  • Webhook secrets are stored in Postgres because they must be retrievable to sign outgoing requests. To keep them elsewhere, self-host with your own secret manager.

Data in transit

  • HTTPS everywhere on the managed cloud.
  • On self-host, you provide the TLS. See self-hosting for the Caddy example.
  • Webhook deliveries only go to HTTPS URLs. HTTP is rejected at the schema layer.

Audit logging

Every write is logged with user, action, entity, and before and after values. It is queryable from the UI and exportable as JSON. Audit logging is included on every cloud plan. The self-hosted community edition does not include audit logging.

Reporting vulnerabilities

Please disclose responsibly to security@customermates.com. The PGP key is in the repository. We aim to acknowledge within 24 hours.

Next

  • Self-hosting: run Customermates yourself.
  • API keys: key hygiene rules.
  • MCP: how the AI surface is shaped.
Stack
Tenancy
Authentication
Authorization
External AI access
Data at rest
Data in transit
Audit logging
Reporting vulnerabilities
Next