Security
Last Updated: April 17, 2026
This page describes our current security practices. It is descriptive, not a warranty, and practices may change as our infrastructure evolves. Our binding legal commitments are set out in our Terms of Service and Privacy Policy.
Firm Data Isolation
Every piece of data in KPI Scribe is scoped to a single firm. There is no shared data and no cross-firm access.
Row-Level Security (RLS) is enforced at the database level on every table that holds firm data. PostgreSQL evaluates a firm identifier check on every query. The architecture is designed so that even if application code has a bug, the database itself prevents cross-firm data access. This is not application-level filtering; it is enforced by the database engine.
All nine Clio data tables (matters, contacts, activities, bills, allocations, bank transactions, users, practice areas, and bank accounts) have RLS policies with forced row-level security enabled, meaning even database administrators are subject to the same rules when querying through the application.
AI Report Builder Security
When a user asks KPI Scribe to build a report, the AI generates a SQL query. That query goes through multiple layers of validation before it ever touches firm data.
What the AI sees
By design, the AI receives only the user's natural-language report description, prior messages in the conversation, and a system prompt containing the database schema (table and column structure only), query instructions, and basic firm configuration (such as available billing hours). Actual firm data — client names, financial figures, matter details — is not sent to the AI. It generates a SQL query, which is then executed locally against the firm's database.
No model training
KPI Scribe uses the Anthropic commercial API. Anthropic does not use commercial API data to train, fine-tune, or improve their models. Firm data does not enter any training pipeline, and as noted above, firm data is not sent to the API in the first place.
Multi-layer SQL validation
Every AI-generated query passes through six independent server-side validation checks before execution. These checks restrict what types of operations can run, which tables can be accessed, and how much data can be returned. Queries that fail any check are rejected before reaching the database.
Database role restrictions
AI-generated queries execute under a dedicated database role that:
- Has SELECT-only permissions. It lacks write grants and cannot modify data, even if other validation layers fail
- Can only access the nine analytics views and their underlying source tables, with no access to firm records, billing data, OAuth tokens, or team member information
- Cannot log in directly. It exists only as an execution context within a server-managed transaction
- Runs with a 10-second timeout. Queries that take too long are automatically terminated
Transaction-scoped firm isolation
Each query executes inside a database transaction that sets the firm context at the start. Row-Level Security policies use this value to filter all data. The setting is automatically discarded when the transaction ends and cannot leak between requests.
Adversarial testing
We maintain an automated test harness that runs adversarial scenarios against the live AI model. These tests exercise the complete pipeline from prompt through validation and firm isolation, using the real model rather than mocks.
Encryption
| Layer | Method | Details |
|---|---|---|
| In transit | TLS 1.2+ | Enforced by Vercel (application) and Supabase (database). No unencrypted connections. |
| At rest: database | AES-256 | Supabase encrypts all database storage at the infrastructure level. |
| At rest: Clio tokens | AES-256-GCM | Application-level encryption with per-token random initialization vectors, on top of infrastructure encryption. |
| At rest: passwords | bcrypt | Managed by Supabase Auth. Passwords are hashed, never stored in plaintext. |
Authentication and Authorization
KPI Scribe uses email and password authentication with secure HTTP-only session cookies. Server-side JWT verification uses cryptographic signature validation on every request, with no network calls to external auth services.
All application routes are protected by default. A proxy layer intercepts every request and redirects unauthenticated users. Only explicitly allowlisted routes bypass this check.
Three roles control access: Owner (full control including billing and Clio connection), Admin (report creation and team management), and Viewer (read-only dashboard and export). Role authorization is enforced server-side on actions and API routes.
Clio Credential Protection
When a firm connects their Clio account, KPI Scribe receives OAuth access and refresh tokens. These are protected with:
- AES-256-GCM encryption before database storage, with a unique random initialization vector per token
- Encryption key stored as a server-side environment variable, not in code or version control
- Automatic token refresh before expiration, so firms never need to reconnect manually
- Immediate deletion on disconnect. Tokens are removed, not archived
Webhook Security
Clio sends real-time data updates via webhooks. Incoming webhook payloads are verified with HMAC-SHA256 signature verification using timing-safe comparison, designed to prevent replay or tampering attacks. A handshake protocol is completed before webhooks are activated to reject unauthorized sources.
Stripe payment webhooks are similarly verified using Stripe's built-in signature verification.
Data Lifecycle
- Clio disconnect: All synced data and OAuth tokens are deleted immediately. Report configurations are preserved (they contain no sensitive data).
- Subscription cancellation: Access to existing reports is preserved in read-only mode, and a warning is shown that data is no longer syncing. Data is retained until the firm reactivates, disconnects Clio, or deletes the account — it is not automatically deleted on cancellation.
- Account deletion: When a firm owner requests deletion, access is revoked immediately and the account enters a 30-day recovery window during which the owner can cancel deletion and restore access. After the recovery window, all data is permanently removed — including synced Clio data, reports, settings, team memberships, and connection records.
- Clio record deletion: When Clio sends a delete notification, the record is hard-deleted immediately. Data is removed from the database, not flagged as inactive.
Infrastructure
| Component | Provider | Purpose |
|---|---|---|
| Application | Vercel (US) | Hosting, serverless functions, cron jobs |
| Database | Supabase (US) | PostgreSQL: all firm data, user accounts, application state |
| AI | Anthropic (US) | Report query generation (no firm data sent) |
| Payments | Stripe (US) | Subscription billing (no firm data shared) |
| Resend (US) | Transactional emails | |
| Error tracking | Sentry (US) | Server-side error monitoring (no user PII) |
All data resides in US data centers. No data is replicated to or processed in other regions.
Design Commitments
- By design, firm data is not sent to the AI. The AI receives only the database schema and the user's request, not actual client names, financial figures, or matter details.
- The Clio connection is read-only. KPI Scribe does not modify firm Clio data.
- Firm data is not shared between firms. Every table is scoped to a single firm with database-enforced isolation.
- Passwords are not stored in plaintext. Password hashing is handled by the authentication provider.
- Secrets — API keys, encryption keys, and database credentials — are server-side only and not included in the client-side JavaScript bundle.
- After the applicable recovery or retention window described above, firm data is removed, not archived.
- The AI has no ability to modify data. The query executor role is SELECT-only, without write, update, or delete grants.
Security Questions or Concerns
If you have questions about our security practices or want to report a security issue, contact us at support@kpiscribe.com. For information about how we collect, use, and protect your data, see our Privacy Policy.