Surface.

An AI document vault for Ontario lawyers. Upload legal documents, ask questions in plain English, and get answers with verbatim citations pointing to the exact source paragraph - plus e-signing, PDF tools, and client intake, all on Canadian servers.

Platform

Electron desktop (macOS + Windows)

Backend

Supabase edge functions

Retrieval

Cohere embed → pgvector → Claude

Data residency

ca-central-1 · Montreal

A thin client over a Canadian backend

Surface is a cross-platform Electron desktop app. The client itself is deliberately thin - a sandboxed React renderer talking to the main process only through a preload context bridge. Every piece of heavy or sensitive work (document ingestion, embeddings, RAG, e-signing, billing) runs in Supabase edge functions, so no API secret ever ships inside the app.

A lawyer signs in, connects their document and email accounts, and works inside matters. Questions are answered from the vault with citations, from live email context, or both - a Haiku router decides. The result is a tool that feels like chat but is auditable, scoped per matter, and compliant with the Law Society of Ontario's residency rules.

Desktop shell → Supabase edge

Main process

window · OS keychain

IPC

Preload bridge

context isolation

React renderer

HashRouter SPA

HTTPS · anon JWT, org-scoped

Edge functions

secrets stay server-side

Cohere · Claude

embed · answer

Postgres 17 + pgvector

Storage · Auth

The renderer runs with context isolation on and Node integration off. The main process holds the OAuth token and fetches raw mail; the edge functions hold the secrets that must never leave the server.

The RAG pipeline

01

Ingest

process-document extracts text via Claude native document input, chunks it, embeds each chunk with Cohere, and stores chunks + pgvector embeddings in Postgres.

02

Route

route-intent, a tiny Claude Haiku classifier, reads recent turns and routes the question to vault, live, both, or chat so follow-ups resolve correctly.

03

Retrieve

query-document embeds the question with Cohere, runs a pgvector search scoped to the caller’s org (from the JWT), and pulls the most relevant chunks.

04

Answer

Claude composes the answer with verified verbatim citations, injecting per-chat short-term history plus the matter’s long-term ai_context summary.

Conversation memory

Two layers, injected without touching the cached system prefix so prompt caching stays intact: short-term is the last ~5 raw turns; long-term is matters.ai_context, a running ≤300-word summary refreshed every ~10 messages. A brand-new chat still remembers earlier work in the same matter, with no bleed between clients.

Edge functions

process-document

Server-side ingestion: extract, chunk, embed, store.

query-document

RAG answer with org-scoped pgvector search + citations.

route-intent

Haiku classifier → vault / live / both / chat.

sync-emails / search-emails

30-day mail cache, embedded and searched server-side.

sign-session / sign-submit

Public signing flow for getsurface.ca/sign/[token].

generate-signed-pdf

pdf-lib stamps signatures + Certificate of Completion (SHA-256).

stripe-webhook

Source of truth for subscription state.

oauth-token

Proxies Google OAuth so the client never holds the secret.

Security & compliance

Canadian data residency

All documents and data live in a Supabase project in AWS ca-central-1 (Montreal). The only text that leaves Canada is the excerpts sent to Cohere and Anthropic at query time.

Per-matter isolation

Row-level scoping and audit logging are enforced at the database level for LSO compliance. Retrieval is scoped to the caller’s org via their JWT, never the request body.

Secrets never ship

The desktop client is a thin shell. API keys for Cohere, Claude, Stripe and OAuth live only in edge functions. OAuth session tokens are stored in the OS keychain, never on our servers.

Hardened Electron

Context isolation on, Node integration off, ASAR with hardened Fuses (cookie encryption, RunAsNode disabled). macOS builds are Developer-ID signed + notarized with auto-update.

Tech stack

Electron 35React 19TypeScriptVite + Electron ForgeTailwind CSSSupabasePostgres 17pgvectorCohereAnthropic ClaudeStripepdf-libPlaywright