Brand logo
HomeLLMsData EngineeringAI ApplicationsPolicy & ComplianceOpen SourceGeneral
  1. Home
  2. /
  3. aiapplications
  4. /
  5. casecite-self-hosted-legal-ai-research-workspace

AIApplications Guide: Turning CaseCite Into a Day-to-Day Legal AI Research Workflow for AIdataNewsGlobal

When an organization asks whether generative AI can support contract review, case research, and document drafting without shipping the entire corpus to a vendor, the application design matters more than the label on the model. The pattern examined here is a private deployment: CaseCite stores the corpus, search index, conversations, and generated analyses inside the deploying firm’s own environment, while only the selected prompts and retrieved passages travel to external AI services configured by that firm. Nothing goes to the CaseCite maintainers, and there is no telemetry. The following guide explains how such a workspace enters a legal workflow, what leaves the network, how to stand it up, and where reviewers should remain cautious.

Application map: how the tools are used in daily legal work

Eight tools sit behind one login and all read the same document corpus, so an uploaded agreement, brief, or internal memo can drive research, drafting, and review without moving files among separate applications.

  • Research (/research): chat across the firm’s uploaded material. The application retrieves by meaning, rescoring candidates with keyword BM25, and returns inline citations to source text.
  • Documents (/documents): build and organize the private corpus. Teams can import from Google Drive, OneDrive, Box, Dropbox, iManage, NetDocuments, Filevine, or Clio through OAuth sync, or use a file picker when OAuth verification isn’t needed.
  • Contracts (/contracts): run a review pipeline over an indexed contract or pasted text. A reviewer can chat with one contract, compare 2–4 contracts clause by clause against a baseline, and export a redline, a draft, or the analysis.
  • Drafting (/drafting): generate a document grounded in up to four selected Knowledge Base documents, with server-side text extraction and PDF conversion. For long work such as a 30-page agreement, a target length is available: the user inspects a section plan first, then each section is drafted in its own context window while still referencing the full source set, and the result is reconciled. Edits to long drafts are limited to the sections they affect.
  • Case view (/case/:id): open a CourtListener opinion and converse with that opinion directly.
  • Authority map (/case-citations): trace which authorities are cited across selected documents.
  • Judge intel (/judge-intel): show Judge analytics obtained from CourtListener.
  • Legal tools (/tools): gather case lookup, citation check, precedents, dockets, oral arguments, and case-law trends. Citation check scans citing opinions for negative-treatment language; it is not a Shepard's or KeyCite substitute.

Practice context is not hard-coded. The user declares what they practice; CaseCite drafts a profile of what matters in that practice, and the user edits and owns that profile through Settings. The profile then travels with each review, redline, and draft as standing context.

Each AI answer, analysis, or draft carries a reminder to verify it against source documents and current law before it is relied upon. The workspace is a research aid, not a replacement for lawyer judgment or for a citator.

Where AI services touch the workflow, and what leaves the deployment

Documents, the vector index, chat history, and analyses stay only on the user deployment. AI features transmit content to third parties selected by the user:

  • Uploading a document sends its text to an embeddings provider. OpenAI is the default; Voyage or Cohere can be configured instead.
  • A question, analysis, or drafting request sends the question and the relevant document text to an LLM provider such as OpenAI, Anthropic, or Gemini.
  • Case-law functions send search queries and citations to CourtListener.

If a team wants document text to remain on its own network, it must run both model types itself: set OPENAI_BASE_URL for chat and EMBEDDING_BASE_URL for embeddings to OpenAI-compatible servers under the team’s control. Configuring only the chat endpoint still sends document text to OpenAI for embedding. The complete list of outbound flows and restriction methods is in docs/subprocessors.md.

Licensing posture for an internal application rollout

CaseCite uses the Elastic License 2.0. In plain terms: a firm may self-host it free for internal use and modify it for its own deployment; it may not offer CaseCite to third parties as a hosted or managed service; and it may not alter or remove licensing or copyright notices. Paid private installs, support contracts, or hosted-SaaS licensing are discussed in SUPPORT.md, and the project is available through GitHub. The project describes itself as Source-available, not OSI open source. Full terms are in LICENSE.

Step tutorial: private deployment, secrets, and first admin

Prerequisites

  • Docker and Docker Compose are needed.
  • Use openssl to generate secrets.
  • Have an AI provider API key. OpenAI is the simplest start because it covers both chat and embeddings. A server-level key is optional, because each user can save a key.

Run it as a self-contained stack

This bundled path provides the application with Postgres, Redis, and an HTTPS proxy. Use git to clone the CaseCite GitHub repository and enter the casecite directory. Copy .env.example to .env, then prepare the three REQUIRED secrets. The placeholders in .env.example intentionally refuse to boot.

  1. Create each secret with openssl rand -hex 32 for SECRET_KEY and AUDIT_HMAC_KEY, and with openssl rand -hex 16 for ENCRYPTION_SALT, then copy the values into .env.
  2. In .env, set OPENAI_API_KEY, or leave it empty and save a key under Settings after signing in. Uncomment and set DOMAIN, POSTGRES_PASSWORD, and REDIS_PASSWORD in the “Bundled production stack” section; the file includes generation hints, and DOMAIN=localhost can be used for a local trial. CORS_ORIGINS and ALLOWED_HOSTS default from DOMAIN. Also set REGISTRATION_BOOTSTRAP_TOKEN with openssl rand -hex 16, because it is needed to create the first account.
  3. Set DISK_ENCRYPTION_ACKNOWLEDGED=true in .env; booting requires it. The acknowledged point is that the application encrypts BYOK keys and uploaded documents at the application layer with AES-256-GCM, while derived text such as vector chunks, chat history, and analyses is stored in cleartext in the app, Postgres, and Redis volumes. Full-disk encryption of the host remains the user’s responsibility.
  4. Start the bundled stack, including Postgres, Redis, and Caddy, with docker compose -f docker-compose.prod.yml up -d.

Running python3 scripts/setup_production.py --create-env --domain <host> performs steps 1–2 automatically; it generates every secret and writes .env with mode 0600. Then open https://$DOMAIN, or https://localhost when DOMAIN=localhost.

On a localhost trial, Caddy redirects HTTP to HTTPS and serves a certificate from its own self-signed local CA, so the browser warning on the first visit is expected. See “TLS on Internal Networks” in docs/deployment.md to trust that CA or bring a certificate.

The first account registered becomes the admin, and registering it requires the REGISTRATION_BOOTSTRAP_TOKEN from .env, so another person who reaches a fresh instance cannot claim it. The exact command is under “Create the admin account” in docs/deployment.md. After that, colleagues can be invited from Settings → Users; self-service registration is off by default.

When deploying behind an existing reverse proxy such as Coolify or Traefik, use the root docker-compose.yml instead. That file expects external Postgres and Redis and declares the persistent data volume. Read deploy/COOLIFY-SETUP.md, and also set TRUSTED_PROXIES to the proxy subnet, because client IPs would otherwise collapse to one.

Key custody and cost attribution in BYOK deployments

Users supply AI provider keys through the Settings modal. Firm evaluators should understand these custody points:

  • Per-user keys are stored server-side, encrypted with AES-256-GCM using PBKDF2 key derivation and HKDF per-record separation, in a file store on the data volume.
  • Keys appear masked only and never go to the browser; the backend decrypts them on demand for each request.
  • Environment fallback keys, such as OPENAI_API_KEY in .env, are shared by all users of the installation; per-user cost attribution requires per-user BYOK keys.
  • ENCRYPTION_SALT can be rotated without losing stored keys: keep the old value in ENCRYPTION_SALT_PREVIOUS and run python -m app.utils.reencrypt inside the backend container. See docs/secret-rotation.md. SECRET_KEY cannot be rotated without making stored documents unreadable, so it must be kept safe and backed up off the server.

Configuration variables: required, lightly optional, and fully optional

Required environment variables

The stack fails closed at startup if any required variable is missing or left as a placeholder.

VariableApplication meaning
SECRET_KEYJWT/CSRF signing key and root of at-rest encryption. Generate with openssl rand -hex 32; never change after first run.
ENCRYPTION_SALTAt-rest encryption salt. Generate with openssl rand -hex 16; never change after first run except through the rotation procedure.
AUDIT_HMAC_KEYAudit-log chain key, at least 32 characters. Generate with openssl rand -hex 32.
POSTGRES_PASSWORDPassword for the bundled Postgres database.
REDIS_PASSWORDPassword for the bundled Redis service.
DOMAINPublic hostname, or localhost. CORS_ORIGINS and ALLOWED_HOSTS default from it.
DISK_ENCRYPTION_ACKNOWLEDGEDSet true to acknowledge that full-disk encryption of host volumes is the user’s responsibility. Application-layer AES-256-GCM covers BYOK keys and document originals, while derived text may be cleartext.
REGISTRATION_BOOTSTRAP_TOKENNeeded to register the first admin account. Generate with openssl rand -hex 16.

These variables are not required to boot, but the product does little without them:

VariableWhy it matters in use
OPENAI_API_KEY, or another provider keyA server-level provider key shared by all users. Without one, each user must save their own key under Settings before chat, analysis, or indexing works.
COURTLISTENER_API_TOKENCourtListener is the only case-law source in the application. Citation check requires a token; other case-law tools work without one but are heavily rate-limited. A free token is available from CourtListener.

If using root docker-compose.yml with external database and Redis rather than bundled stack, set DATABASE_URL, REDIS_URL, CORS_ORIGINS, and ALLOWED_HOSTS directly, and set DB_SSL=require for a managed database.

Optional environment variables

VariableDefaultApplication effect
ANTHROPIC_API_KEY—Claude access.
VOYAGE_API_KEY—Voyage AI legal embeddings.
OPENAI_BASE_URL—OpenAI-compatible endpoint for chat, using a self-hosted model or gateway.
EMBEDDING_BASE_URL—OpenAI-compatible endpoint for embeddings. Set it with OPENAI_BASE_URL to keep document text on the user network.
VECTOR_DBchromaUse chroma locally, or pinecone to store document text with Pinecone.
TRUSTED_PROXIES127.0.0.1Reverse-proxy IP or CIDR; required behind a proxy.
REQUIRE_MFAfalseRequire every password account to enrol TOTP MFA.
SESSION_ABSOLUTE_TIMEOUT_HOURS and SESSION_IDLE_TIMEOUT_MINUTES8 / 120Session lifetime and idle timeout.
ALLOW_REGISTRATIONfalseAllow self-service sign-up after the first account.
SENDGRID_API_KEY—Enables password-reset emails; change-password works without SendGrid.

The .env.example file documents every setting.

Connector notes

The sync API imports one folder using folder_id, or the whole account when sync_all is explicit. The UI has no folder picker yet. Clicking Sync Now imports the whole connected account after a second confirmation that says so. Use the file pickers to bring in selected files. Clio’s listing is account-wide, so Clio cannot sync a single folder.

Filevine uses one firm-wide API key, so it remains off until FILEVINE_ENABLED=true, and then it is available only to admins.

The iManage and NetDocuments connectors are implemented against the vendors’ published APIs but have not been validated against a live tenant. Test them in your environment before relying on them.

Microsoft and Google connections request read-only scopes. Connections made before this release keep their broader grant until reconnected.

CourtListener API token

Legal tools, Judge intel, Case view, and the case-law side of the strategy engine all read from CourtListener. CourtListener is the only case-law source in the application. The app starts without a token, but the case-law half is not usable without one:

  • Citation check hard-fails without a token. validate_citation refuses to run and returns a “token required” error that names where to set the token, _check_token in backend/app/services/courtlistener_client.py.
  • Every other CourtListener call falls back to anonymous access, which is rate-limited hard enough that research features become unusable under any real load.

A free token can be obtained from CourtListener. Set COURTLISTENER_API_TOKEN in .env, or save it instance-wide as an admin through Settings → API Keys, or use POST /api/v1/admin/integrations/courtlistener. The stored token overrides the .env value at runtime without a restart.

Repository shape: where application logic lives

The repository is organized around backend, frontend, scripts, docs, and Docker files.

  • backend/ contains app/. main.py runs the FastAPI app with middleware and health endpoints; config.py uses Pydantic settings; routers/ hold API routers; services/ contain the RAG pipeline, the ChromaDB or Pinecone abstraction, multi-provider embeddings, JWT auth, Matter strategy briefs, and the CourtListener API. middleware/ handles security and CSRF, and migrations/ contains Alembic migrations.
  • frontend/ contains src/ with App.tsx, per-domain API clients, page views, Zustand stores, shared components and modals, and the app shell layout.
  • scripts/ include backup and restore, production setup, key rotation, and the NOTICE generator.
  • docs/ cover deployment, data flows, secret rotation, incident response, and ADRs.
  • Dockerfile builds one unified image for frontend and backend. docker-compose.prod.yml bundles Caddy, Postgres, Redis, and backend. docker-compose.yml is intended for use behind an existing proxy such as Coolify or Traefik, with external Postgres and Redis. docker-compose.dev.yml supports local development.

API-only capabilities before the UI

These functions are implemented and reachable over the API, but the frontend does not expose them yet. Treat them as preview:

  • Matters (/api/v1/matters) manage matter records, membership, and sharing of documents and chats between members. Creating matters and changing membership requires the matters.manage permission.
  • Strategy briefs (/api/v1/strategy) search each proposition on CourtListener, read candidate opinions, and keep a citation only when a verbatim quote can be located in the real opinion text. Unsupported citations are dropped rather than shown.
  • Azure AD SSO performs backend token exchange only, and there is no sign-in button. SAML, generic OIDC, and SCIM are not supported.

Everything else described above, plus user administration and the audit log available only to admins under Settings, has a UI.

Security controls and limits that affect adoption

  • Password sign-in uses PBKDF2-SHA256 and supports optional or mandatory TOTP MFA plus recovery codes. Password reset is available by email, and change-password is available in the application.
  • JWT access tokens use rotating refresh tokens in httpOnly cookies, with JTI revocation in Redis, required in production, and a “sign out everywhere” action.
  • Sessions are capped at 5 per user, with an 8-hour absolute lifetime and an idle timeout.
  • Role-based permissions, controlled by require_permission, are adjustable per role by an admin.
  • Every document, chat, and analysis can be scoped per user and also per matter.
  • CSRF double-submit cookies are HMAC-signed; per-IP rate limiting and account lockout are enabled.
  • AES-256-GCM at-rest encryption protects uploaded originals, API keys, connector tokens, and MFA secrets. The vector index and database depend on disk encryption provided by the user.
  • CSP, HSTS, X-Frame-Options, and Permissions-Policy headers are set.
  • The audit log uses HMAC-SHA256 chain hashing and is verified at startup and on demand.
  • CaseCite holds no security certification: no SOC 2, no ISO 27001, and no HIPAA certification. SECURITY.md describes what it does and does not do, and explains how to report a vulnerability; ROADMAP.md lists known gaps.

Contributing path

See CONTRIBUTING.md. Pull requests are welcome for the source-available product. Contributions are licensed under Elastic License 2.0.

Common misconceptions to resolve before rollout

Application reviewers often confuse convenience with privacy, or confuse a local demo with production trust. The most important corrections are:

  • A free internal deployment is not permission to resell CaseCite as a hosted or managed service.
  • Citation check is useful for negative-treatment scanning, but it is not a Shepard's or KeyCite substitute and does not remove the need to verify law.
  • Changing OPENAI_BASE_URL for chat is not enough to keep document text on your network if embeddings still go to OpenAI.
  • Server-level API keys share usage across users; per-user cost attribution needs per-user BYOK keys.
  • A localhost certificate warning can be expected because Caddy uses a self-signed local CA; it does not automatically mean the deployment is wrong.
  • iManage and NetDocuments connectors have not been validated against a live tenant, so they must be tested before reliance.
  • Sync Now is broad: with no folder picker in the UI, it imports the whole connected account after a second confirmation.
  • Matters, strategy briefs, and Azure AD SSO are API-only preview capabilities, not finished UI functions.
  • Self-hosting does not create a certified cloud service; CaseCite does not hold SOC 2, ISO 27001, or HIPAA certification.

Action suggestions: evaluation, deployment, and everyday use

For teams reading this as an AIApplications use case, the next step is to map the product facts to a concrete pilot:

  • Decide the data boundary first: list which documents may be embedded by OpenAI, Voyage, or Cohere, and which may need self-hosted models through OPENAI_BASE_URL and EMBEDDING_BASE_URL.
  • Choose the provider posture: server-level key for simplicity, or per-user BYOK keys for accountability and cost attribution.
  • Use localhost only as a trial, then follow docs/deployment.md and the TLS guidance before any internal production use.
  • Protect secrets carefully, especially SECRET_KEY, and test the documented ENCRYPTION_SALT rotation procedure before relying on it operationally.
  • Begin with a bounded corpus: import selected files through file pickers where broad sync is not desired, and avoid full Clio or account-wide connectors until folder behavior is understood.
  • Obtain a CourtListener token before load-testing citation check or research features; anonymous fallback is rate-limited.
  • Enable the controls that match the pilot, such as REQUIRE_MFA, ALLOW_REGISTRATION=false, session timeouts, and TRUSTED_PROXIES behind a proxy.
  • Have legal reviewers validate drafts against source documents and current law, treating the output as a research aid.
  • Review Elastic License 2.0 before proposing any external offering, because hosted or managed resale is not allowed.
  • Track gaps and security details through SECURITY.md and ROADMAP.md rather than assuming certifications exist.

Conclusion: an application pattern, not a blind automation

As an applied legal-AI pattern, this private workspace makes sense when the team needs AI assistance inside document review and drafting, but needs to keep the source corpus, answers, and history under its own administrative control. Its usefulness comes from connecting research, contracts, drafting, citations, and judge analytics to one indexed corpus, while its limits come from clear operational conditions: outbound provider traffic, license constraints, connector caveats, secret management, and the need for lawyer-level verification. Used with those conditions visible, it can support practical legal workflows without pretending to replace professional judgment.

Brand logo

AI & Data News

Frontier Reporting on Foundation Models & Data Engineering

LLMsData EngineeringAI ApplicationsPolicy & ComplianceOpen SourceGeneralGlobal SaaSManager

© 2026 AI & Data News.

Cookie Notice

We use cookies to improve your experience and analyze website traffic. Read our Privacy Policy to learn more.