How your data is protected

Every statement on this page was checked against the code before it was written, and anything that could not be checked was left off rather than softened. What is not here is listed at the end.

One organization cannot reach another's data

  • Every stored record carries the organization it belongs to, and every query is filtered by the organization of the caller rather than by an identifier taken from the request.
  • A request for a record belonging to another organization is answered as not found, in the same words as a request for a record that does not exist. It never reports that access was refused, because that would confirm the record exists.
  • A test suite runs every read and write entry point across two organizations against a real database, and a release does not pass without it.
  • Inside an organization there is a second boundary: an engagement can be restricted to named participants, and a requirement can be marked confidential. What is outside your reach is absent from lists, from search results and from the counts on dashboards, rather than shown and locked.

What someone may do is a role and a permission, checked in one place

  • There are six roles — Viewer, Contributor, Reviewer, Approver, Administrator and Agent — and each maps to an explicit list of permissions. A capability is granted by naming it, never by seniority.
  • Every interface endpoint passes through one authorization wrapper, which resolves who is calling and what they hold before any handler runs.
  • Roles and membership are read from the database on every request, so removing someone or changing their role takes effect on their next action. Nobody is asked to sign out and back in for a permission change to apply.

Every change is recorded, and the record cannot be edited

  • Each change to a field, a state, a link, an approval or a decision writes an entry naming the actor, the time, and what the value was before and after — in the same database transaction as the change, so a change without its entry cannot be committed.
  • The record is append-only, enforced twice: a database trigger refuses any update or delete of an entry, and the application's database client refuses to issue one.
  • An agent acts under its own identity, so its actions are in the same record as a person's and are told apart from them.
  • The record is searchable by actor, action, subject and date, and exports as a file you keep.
  • Nothing governed is ever deleted. A requirement is withdrawn, retired or superseded and stays readable at every version it passed through. The only things the interface will delete at all are personal preferences — a saved view and a notification watch — neither of which is content.

A token reaches less than the person who issued it, and stops when they do

  • An access token is bound to one organization, carries one role no higher than its creator's own, and expires — by default after ninety days and at most after a year.
  • A token stops working the moment it is revoked, and also the moment its owner stops being a member of the organization. Someone is always accountable for a credential, including an agent's.
  • Secrets are shown once and stored only as a keyed hash, so reading the database yields nothing you can authenticate with. Each carries a recognisable prefix so a leaked one can be searched for.
  • A credential calling faster than its rate allows is refused with a response saying when to retry, so a leaked token is slowed wherever it is used from rather than served at full speed until somebody notices. If the counter itself cannot be read, requests are served rather than refused — a brake that fails should not become an outage.
  • One credential cannot be stored as a hash, because signing a delivery needs it back: the secret an event subscription's deliveries are signed with. The application seals it with a key held outside the database before storing it, so reading the database alone does not yield it, and that key can be replaced without any subscriber re-registering. Whether the database's own storage is protected by its host is a separate question, and one this page does not yet answer.
  • An agent is a registered identity with an explicit list of what it may do, which can only narrow what its role allows and never widen it. The list is read on every request, so tightening or suspending an agent takes effect on its next call.
  • An agent proposes; a person decides. It cannot approve, transition, baseline or decide anything, and it cannot accept its own proposal — enforced by the permissions it does not hold and again by the one module allowed to change a record's state.

How people authenticate

  • People sign in with an email address and a password of at least ten characters, hashed with scrypt and a per-password salt. The password itself is never stored.
  • A session is an opaque secret held in a cookie that scripts cannot read, is not sent on cross-site requests, and is sent only over a secure connection in production. It lasts thirty days, and signing out revokes it on the server rather than only clearing the cookie.
  • Failed sign-ins are counted twice over — against where they came from and against the account that was tried — and further attempts are refused for a period once either is spent. A failure against an address that does not exist is counted exactly like one against an address that does, so being refused says nothing about whether an account is real.
  • An invitation is a single-use secret with its own expiry, stored the same way, and an administrator can revoke one before it is accepted.

Where the service runs

  • ClarixERR runs as a web application on Vercel, with its data in a managed Postgres database operated by Neon. Nothing in the product reaches another organization's database or another product's data.

Your data leaves the way it came in

  • The requirements catalogue exports as a file with the columns you choose, including relationships, and the audit record exports the same way.
  • Motivation elements, requirements and their relationships export in the Open Group's ArchiMate model exchange format, validated against the published schema.
  • Everything the interface does, the interface does through a documented API that describes itself, so nothing is reachable only by a person clicking.

What this page does not claim

  • ClarixERR holds no certification or attestation — no SOC 2, no ISO 27001, no independent audit — and claims none.
  • No third-party penetration test has been carried out.
  • Single sign-on and multi-factor authentication are not available; sign-in is an email address and a password.
  • The general request limit is counted by each running instance rather than shared between them, so a caller spread across several gets a multiple of it. Failed sign-ins are counted in shared storage and are not affected by this.

And what it does not yet state

  • Where data is physically held, and whether it can be pinned to a region.
  • Whether data is encrypted at rest, by whom, and with whose keys.
  • How far back the database can be restored, what the recovery objectives are, and when a restore was last exercised.

These are not omissions of convenience. Each is unanswered in writing today, so it is not stated here; ask and we will tell you where it stands.

Reporting a security concern

If you find a weakness in ClarixERR, write to us before disclosing it anywhere else. We will confirm receipt and tell you what we are doing about it.

hello@clarix.app
How your data is protected — ClarixERR