Security and trust
Every claim on this page names the place it is enforced
Written for whoever is going to review this: your IT team, your counsel, or the union representative who is going to ask what a supervisor can see. What we do not have is in the second section, ahead of any of the claims.
The summary, in five lines
To paste into an email without reading the rest.
- Two separate databases, with no key between them and no shared identifier.
- Each anonymous event carries six fields and a timestamp truncated to the hour — never finer.
- One read path, with a minimum cell size of 10 that goes up but never down.
- A crisis-flagged tap writes no row on any plane. There is nothing to count.
- Zero third-party code on the public experience. No analytics, no pixels, no remote fonts.
Start here. This is the section you were going to ask for
It comes second, not last. A reader who finds this section after the claims has already been misled by the page.
- We do not have SOC 2, an ISO certification, or a HIPAA business associate agreement — and we will not imply otherwise.
- No independent penetration test has been done, and none is scheduled yet.
- No independent accessibility audit has been completed. It is scheduled before first release.
- The legal documents have not yet been reviewed by counsel, and every one of them says so on its own page.
- Subprocessors are described by role, because the contracts are not signed. The product has not launched.
None of this is a promise that it is coming. It is the actual state, and we would rather you knew before signing than after.
The two planes, and the wall
Anonymous data and identifying data live on separate instances with separate credentials. This is not a separation by convention; it is one you can check.
- No foreign key between the planes, and no shared identifier of any kind.
- No service holds credentials to both.
- CI fails the build if any file imports both packages, or if one package depends on both.
- The CI job that verifies the wall holds no contact-plane credentials — the job that checks the wall cannot cross it.
The standard: somebody with full read access to both databases still cannot join them.
One stored event, in full
Organisation, site, audience pack, topic, truncated hour, language. That is all of it. No session, no device, no cookie, no IP in any form, no user agent, no sequence number, and no free text. The event tables have no primary key, and the adversarial suite asserts it.
The test: two taps by the same person must be indistinguishable from two taps by two different people. If you can tell them apart, the schema is wrong.
One read path
There is one function. No raw query interface, no export, no admin mode, and no second function “for support”.
- The connection handle is not exported and is unreachable through the package’s exports map.
- The build fails if a second path appears — including a named export added “for tests”, which has its own failing-case test.
- The cell floor is enforced in the query layer, so a naive query gets a refusal rather than a leak.
- A filtered dimension counts as a grouped dimension. You cannot dodge a refusal by moving the topic into the filter.
Subtracting two permitted answers
The attack that matters asks for nothing forbidden: it asks two permitted questions and subtracts. There is a suite of fifteen such attacks. Twelve of the fifteen succeeded against the previous implementation without ever asking a question the system refused — recovering a six-person language cell, a three-person campus, and a three-tap month. All fifteen now fail.
What is still open, said here rather than hidden: subtracting two cuts that do not nest exposes the difference between two protected quantities. It exposes no cell and no person. The closure is a fixed catalogue of cuts instead of an open query surface, and it is scheduled.
The crisis path counts nothing
A crisis-flagged tap writes no row on any plane — not anonymously, not aggregated, not counted. The server returns the same status code as an ordinary tap, so a network observer cannot tell them apart. An unknown topic is treated as crisis: it fails closed.
Yes, that means leaders never see how many times it was tapped. That is deliberate: a leader’s dashboard is worth less than one person’s belief that tapping that button was safe. Crisis resources are configurable per organisation, but can never be removed or hidden.
When somebody does ask to be contacted
That lives on the other plane: encrypted, on a separate instance, visible only to the person your organisation designated as the recipient — never to your leadership. It is purged on a schedule set in the contract, and that period can be shortened but not lengthened. It never enters analytics, a dashboard, or an aggregate.
Zero third-party code
No Google Analytics, no PostHog, no Segment, no session replay, no advertising pixels, no social embeds, and no error tracking that captures request context on a public route. CI fails the build if any analytics SDK is imported into the public experience.
Both typefaces are served from our own domain. A font CDN would learn the IP address of every visitor to a page whose entire argument is that we do not collect one.
Single sign-on
SAML 2.0 and OIDC for the console and the studio — the surfaces administrative staff work in. Decided, not yet built, and marked that way on the features page.
And the request we refuse: sooner or later somebody will ask to have people sign in with their institutional account so participation can be tracked. That request is refused. It is the mandate question wearing an SSO costume, and a sign-in is a list of who used it.
How to check this yourself, in about ten minutes
None of this requires taking our word for it.
- Open the demonstration and try to break it. Group, filter, shorten the window, lower the floor. See what the system hands you.
- Open developer tools and watch the network tab. Our own code requests nothing from another domain. If the CDN in front of us tries to inject something — and today it injects its own analytics script — the security policy blocks it, and you can watch the block happen in the console.
- Read the seven legal documents. Each one says what it does not promise, and why.
- Ask us the question your reviewer is going to ask. If the answer is “not yet”, that is the answer you will get.