Trust

How the record holds, and where it stops.

Auditably exists to make a disclosure defensible, so a page that overstated its own guarantees would be self-defeating. Everything below was checked against the live database on 13 August 2026. Where something is not in place, it says so.

The audit trail

Append-only is a database grant, not a setting.

The activity log is protected by what the database will accept, not by application code that could be bypassed or a flag an administrator could switch off. These are the actual privileges on public.activity_log:

RoleReadAppendModifyDelete row Empty tableWhat it is
anonyesnono nono The key published in our browser code. Any visitor holds it.
authenticatedyesno nonono A signed-in customer. Cannot write to the log at all.
service_roleyesyes nonono Our own application key. It can add entries. It cannot alter or remove one.
postgresyesyes yesyesyes The database owner. Read the section below.

You can confirm the middle rows yourself: the proof page sends real UPDATE, DELETE and INSERT statements and prints the database's refusal, including the SQLSTATE.

One change we made because of this page

Writing this, we checked the grants rather than trusting our own documentation, and found service_role still held TRUNCATE. It could not have altered or deleted any individual entry, but it could have emptied the table, which is not what we say here. Nothing in the product used it. It was revoked on 13 August 2026 and the revocation is recorded as a database migration so it cannot quietly come back.

The boundary

What a database owner can do.

The postgres role owns the database and can do anything to it, including modifying or deleting log entries. That is true of every Postgres database in existence, ours included, and any vendor implying otherwise is describing their application layer rather than their database.

So the honest statement of the guarantee is this. The append-only log removes an entire class of quiet change: a user editing a figure after approval, an application bug overwriting history, a compromised browser key planting an entry. It does not remove the operator from your threat model, and no software sold to you as a service can.

If your assurance provider needs a record outside operator control, the answer is an external attestation or a customer-held export taken on a schedule, not a stronger promise from us. We would rather tell you that than let you discover it during a review.

Evidence handling

Hashed on the way in.

Every uploaded file has a SHA-256 digest computed at upload and stored alongside it, with the filename, the user who filed it, a timestamp and the figure it supports. The digest is recomputed when the file leaves in an assurance export, so a reviewer can confirm the document they are reading is the document that was filed.

Verified in the schema: every evidence record currently stored carries a 64-character hash, which is SHA-256 in hexadecimal.

evidence_items
column file_hashtext, 64 chars, SHA-256 hex
column uploaded_by / uploaded_at who filed it, and when
column data_point_id / disclosure_id the figure the file supports

Tenant isolation

Row-level security on every table.

All fifteen tables in the application schema have row-level security enabled, so a query carrying one organisation's credentials cannot return another organisation's rows. Isolation is enforced by the database on every query rather than by a filter the application has to remember to apply.

Four of those tables hold no customer records at all: they back the anonymous readiness diagnostic and the rate limiter for the public proof page. They have row-level security enabled with no permissive policy, which denies access by default.

Subprocessors

Who else holds anything.

Supabase
Managed Postgres and file storage. Holds the application database and every uploaded evidence file.
Cloudflare
Static site hosting, DNS, and the worker that serves the public proof endpoint. Holds no customer records.
Paddle
Merchant of record for subscriptions. Handles payment details, which never reach our systems.

We do not currently publish a data residency commitment, because we have not verified one we could stand behind. If your procurement requires a specific region, ask before you buy rather than after.

Stated plainly

What we do not have.

SOC 2: in progress, not certified

We are working toward SOC 2 and we are not certified. There is no report to send you, and any date we gave would be a guess. If your procurement requires a completed SOC 2 today, we do not meet that bar and you should know now.

Role separation: built, not yet in use

The data model carries organisation membership, and preparer, reviewer and approver are recorded against each disclosure version. Distinct permission levels per role, including a read-only auditor login, are not yet enforced in the product. We are at design-partner stage and no customer organisation is running them, so claiming a working role model here would be describing an intention.

No uptime commitment

We do not publish an availability target or an incident response time, because we do not operate a formal on-call rota and a number we could not honour would be worth less than this sentence.

Reporting a problem

Security contact.

If you find a vulnerability, email [email protected] with enough detail to reproduce it. We will confirm receipt, and we will not pursue anyone who reports a genuine issue in good faith and does not access or alter another customer's data while finding it.

We do not run a paid bounty. We will credit you if you want the credit.

Check it yourself

Do not take our word.

The proof page runs real statements against the live database and prints what comes back. It is open, needs no account, and the rejection is not simulated.

Test the log →