Overview
Matcher’s security architecture is built on several layers. Every API request passes through multiple security checkpoints before reaching your data.
1
First, TLS encrypts the connection.
2
Then authentication verifies who you are:
- Tenant isolation ensures you only see your own data.
- RBAC checks whether you’re allowed to perform the action.
3
Finally, the system logs everything for audit purposes.
Layer protection
Authentication
Matcher uses the shared
lib-auth library for JWT-based access control. Matcher delegates all cryptographic JWT validation to an external auth provider and holds no local JWT secret of its own.
Configuration
These environment variables control authentication:AUTH_ENABLED and AUTH_SERVICE_ADDRESS are accepted as legacy aliases for PLUGIN_AUTH_ENABLED and PLUGIN_AUTH_ADDRESS. Setting both an alias and its current form to conflicting values is rejected at boot.PLUGIN_AUTH_ENABLED=false (development only), Matcher uses a default tenant ID (11111111-1111-1111-1111-111111111111) and skips authorization checks.
JWT token structure
WithAUTH_PROVIDER=plugin-auth, cryptographic validation is delegated to the plugin-auth service; with AUTH_PROVIDER=workos, Matcher verifies WorkOS access-token JWTs locally against the cached JWKS. Either way, the token must include tenant identification claims:
Required headers
All API requests must include authentication:Token validation
Matcher validates tokens on every request:- Signature verification: Delegated to the configured auth provider (
plugin-authservice, or WorkOS JWKS) — Matcher holds no local signing secret - Expiration check: Rejects expired tokens (
expclaim) - Not-before check: Rejects tokens used before their
nbftime - Tenant extraction: Extracts
tenant_idto resolve the tenant’s database pool
Authorization (RBAC)
Role-based access control protects all API endpoints. Matcher delegates authorization to an external auth service via
lib-auth. Permissions are granular and follow the two-part pattern resource:action.
Permission structure
contexts:create— Create reconciliation contextsmatch-runs:run— Execute match runsexceptions:resolve— Resolve exceptions
Complete permission list
Matcher defines a flat set of roughly 35 resources — there is no grouping into domains. Each endpoint requires a specificresource:action permission checked against the external authorization service. The tables below are grouped only for readability; the slugs themselves carry no domain qualifier.
Configuration
Ingestion
Matching
Exceptions and disputes
Inbound external-system callbacks are authenticated by an opaque bearer token, not by RBAC, so there is no
callbacks:process permission. The callback-credentials:* permissions gate only the JWT-protected surface that mints, rotates, lists, and revokes those tokens.Reporting and analytics
Governance and privacy
Discovery
System
Role management
The external authorization service manages roles, not Matcher itself. Configure roles and their associated permissions in your identity provider or auth service. Matcher checks permissions on each request by calling the auth service with the required resource and action.Tenant isolation
Matcher uses pool-per-tenant isolation in PostgreSQL: each tenant’s data lives in its own database, providing strong data separation between tenants.
How it works
When a request arrives, Matcher extracts the tenant ID from the JWT token (never from query parameters or headers you control). It then resolves the dedicated connection pool for that tenant’s database, so every query runs against that tenant’s own database in complete isolation. There is no shared-schema switching — noSET search_path.
Because each tenant’s data lives in a physically separate database, a bug in the application layer still cannot reach another tenant’s data.
- Tenant ID from JWT only: Never accepted from request parameters
- Automatic pool resolution: The tenant’s database connection pool is resolved from context
- Physical isolation: Each tenant’s queries run against its own database, not a shared one
- No cross-tenant access: Physically separate databases enforce isolation
Isolation guarantees
Audit trail
Matcher records all actions in an immutable, append-only audit log for compliance and forensics.
Audited events
Query audit logs
Use the governance audit log endpoints to retrieve audit records:Verify audit log integrity
Audit logs form a tamper-evident hash chain per tenant. Use the verification endpoint to re-verify the chain — it returns a structured verdict (whether the chain is intact, how many records were verified, and the first broken sequence when a break is found). The check is strictly read-only and never mutates an audit record.Actor mappings and privacy
Actor mappings associate system identifiers (such as JWT
sub claims) with human-readable display names and email addresses. This improves audit log readability without storing personal data in every log entry.
Manage actor mappings
The actor ID path parameter accepts up to 255 characters (matching the database column constraint). Leading and trailing whitespace is trimmed automatically. Values exceeding this limit are rejected with a400 Bad Request error.
cURL
GDPR pseudonymization
To comply with right-to-erasure requests, pseudonymize an actor to replace their personal data with[REDACTED]. Pseudonymization is not reversible from the application; underlying records may be retained per compliance and audit policy.
cURL
Audit log archives
Historical audit logs are periodically compressed and moved to long-term storage. Use the archive endpoints to list and download archived data for compliance reviews.cURL
Data encryption
Encryption in transit
TLS encrypts all data transmitted to and from Matcher.Encryption at rest
Encryption at rest is a deployment-environment responsibility: in a BYOC deployment, your infrastructure — not Matcher itself — provides these controls. A production deployment should provide:SOX compliance
Matcher maintains records for SOX (Sarbanes-Oxley) audit requirements.
SOX control features
API security
Rate limiting
Some endpoints include additional rate limiting to protect against abuse:SSRF protection
Matcher blocks outbound HTTP requests to private IP ranges when dispatching exceptions to external systems. This prevents Server-Side Request Forgery (SSRF) attacks. Blocked ranges include10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8, and IPv6 equivalents.
Webhook signature verification
Matcher signs outbound webhook payloads with HMAC-SHA256 using a per-target shared secret. The signature appears in theX-Signature-256 header, formatted as sha256=<hex-digest>, allowing receivers to verify authenticity. (Dispatch also sets an X-Idempotency-Key header for at-most-once delivery.)
Best practices
Use least privilege access
Use least privilege access
Grant users only the permissions they need. Start with minimal access and add permissions as needed.
Rotate credentials regularly
Rotate credentials regularly
Implement automatic rotation for service credentials. Use short-lived tokens where possible.
Enable audit logging
Enable audit logging
Keep audit logs enabled and review them regularly. Set up alerts for suspicious activity.
Use rate limiting
Use rate limiting
Keep default rate limits enabled to protect against abuse. Adjust thresholds based on expected traffic patterns.
Review access regularly
Review access regularly
Conduct periodic access reviews. Remove access promptly when users change roles or leave.
Verify webhook signatures
Verify webhook signatures
Always validate HMAC-SHA256 signatures on webhook payloads to confirm they originate from Matcher.
Monitor security events
Monitor security events
Set up real-time monitoring and alerting for security events. Investigate anomalies promptly.
Next steps
Match rules
Configure matching rules securely.
Exception routing
Set up secure exception workflows.

