Law4All

Trust and security

Last verified 29 Oct 2026 at version 33b97ba: 16 of 16 controls passed. The tests are run by the developer before each release; there is no independent auditor yet.

ControlWhat it meansEnforced inTestsStatus
Each firm's data is isolated by the databasePostgres row-level security, forced on every firm table; the app role never owns tables.src/law2/schema/rls.pytest_rls_isolation.py, test_tenancy_end_to_end.pyPassed
A non-member learns nothing about a firmAny firm route answers 404 to a non-member, never 403, so firms cannot be enumerated.src/law2/api/deps.pytest_tenant_resolve.pyPassed
Signed-in changes are CSRF-protectedSigned-in requests that change data require a derived CSRF token, except the pre-sign-in forms (login, signup, password reset) and the email-provider webhook, which is verified by its own signature. A test walks every route.src/law2/api/csrf.pytest_api_mutations.pyPassed
A repeated request does not act twiceFirm POSTs require an Idempotency-Key, checked before any work, except sign-in, sign-out, accepting an invitation, client signup and staff sign-off, which repeat safely by design.src/law2/api/idempotency.pytest_api_idempotency.pyPassed
Sessions and invitations are stored hashedA leaked backup is not a set of live sessions or invitations.src/law2/auth/sessions.py, src/law2/auth/invitations.pytest_auth.py, test_email_tokens.pyPassed
Logins and lookups are rate-limitedPer IP and per account, with counters kept even when the request fails.src/law2/api/ratelimit.pytest_ratelimit.pyPassed
Law4All contacts only permitted hostsOne allowlist module holds every permitted host; a code scan fails if any other module names one.src/law2/acquire/allowlist.pytest_allowlist.pyPassed
A CAPTCHA is never solvedIf a court page shows a CAPTCHA, the fetch stops; nothing is solved, retried or queued for a person.src/law2/acquire/transport_browser.py, src/law2/acquire/case_details.pytest_transport_browser.py, test_case_details.pyPassed
The court's CAPTCHA-gated case-status page is not fetchedA person opens that page beside Law4All and pastes it; Law4All does not load, frame or proxy it. Separately, Law4All reads the court's case details only for cases on a published cause list it holds.src/law2/web/static/app.jstest_get_from_court.pyPassed
A client sees only what the firm sharesClient views are built from an allow-list of fields; firm notes, time entries and unshared documents do not reach them.src/law2/clients/projection.pytest_client_view.pyPassed
Facts drawn from a firm's documents stay with that firmRisk lines drawn from a firm's documents appear only in that firm's plan, notes and reports, not in a client's view or another firm's plan. (Where the files themselves are stored is listed below.)src/law2/strategy/doc_risks.pytest_doc_risks.pyPassed
Law4All never says 'not listed' for a day it does not holdNext-hearing statements carry how far the held cause lists reach.src/law2/api/next_scope.pytest_next_scope.pyPassed
A name match is never treated as the same personSame-name links are shown as name matches with their words; nothing is merged.src/law2/documents/party_links.pytest_party_links.pyPassed
Comparable-case figures carry their hand-checked precisionMatter-class comparables quote their measured precision from one table of hand-checked samples.src/law2/api/accuracy.pytest_matter_class.pyPassed
Court text is never rendered as HTMLThe interface builds pages with textContent only, under a strict content security policy.src/law2/web/static/app.jstest_web_ui.pyPassed
Published taxonomy versions are frozenEach published court-taxonomy version is a file pinned by its SHA-256; a test fails if one changes, and the build refuses to overwrite a published version.src/law2/api/taxonomy.py, src/law2/lake/taxonomy/build.pytest_taxonomy_api.py, test_taxonomy_build.pyPassed

Where data is held

WhatWhereNote
Application and APIVercel, Singapore (sin1)Development hosting; production moves to AWS Mumbai (ap-south-1) before paying users.
Database (firm data and the court record)Neon Postgres, Singapore (ap-southeast-1)Moves to AWS Mumbai with the application.
Private files (evidence copies, firm uploads)Backblaze B2, EU CentralMoves to India (AWS Mumbai) with the application.

Services that receive personal data

ServiceWhat it receives
docmaker (drafting service), Mumbai (bom1)Party names and addresses, and deed images, when a firm drafts with it; it stores no content.
Resend (email)Account holders' email addresses and the account emails sent to them.
Browser push services (Google, Mozilla, Apple, Microsoft)Notifications that name a case number, court, date, hall and item, never a party.

Certifications

No certification is held yet. ISO 27001:2022 is planned with the move to AWS Mumbai.