What the platform does, stated plainly
This page describes mechanisms that exist in the product. It makes no certification or compliance claims, because we hold none — where that matters to you, ask and we will answer precisely.
Authentication and sessions
- Passwords
- Hashed with bcrypt. Plaintext is never stored, and a login for an unknown address performs the same work as one for a known address so the two cannot be told apart by timing.
- Sessions
- A signed, httpOnly, SameSite cookie. No token is placed in localStorage.
- Revocation
- Each account carries a token version; changing a password or signing out everywhere increments it and every existing session stops being accepted.
- Reset
- Single-use links, stored only as a hash, expiring in 30 minutes. Requesting one answers identically whether or not the address is registered.
- Rate limiting
- Per user or client address. Credential endpoints fail closed if the limiter itself is unavailable, so an outage cannot remove the only brake on guessing.
- Client address
- Taken from the entry the nearest trusted proxy wrote, not the one the caller claimed.
- Invitations
- The only route into an organisation for an outsider. Tokens are stored as hashes and shown once.
- Suspension
- A suspended or archived account cannot hold a session, checked on the same read as the token version.
Tenancy is structural, not conventional
Every project, document, chat, run and usage row belongs to exactly one workspace inside one organisation. Authorisation resolves from membership and role — never from who created a row.
The vector store is the one denormalised table, and it carries organisation and workspace on every chunk; the similarity search filters on them in the query. The retrieval function requires a workspace argument, so a caller who omits it fails to compile.
A resource in another workspace answers 404, not 403: a 403 would confirm that the id exists.
Access is membership, never row ownership: a colleague in the same workspace reaches its projects, and a resource in another workspace answers 404 rather than 403 — a 403 would confirm it exists.
One capability matrix, checked everywhere
Roles do not grant access by name anywhere in the codebase. Every guard asks for a capability, and the role-to-capability mapping is defined once.
Single gate
Project-scoped requests pass through one function that resolves the workspace, unions the caller's roles and requires the capability the operation needs.
Derived lists
Where a service needs a list of roles, it is derived from the matrix rather than hand-written beside it.
Custom roles
An organisation can define its own, but only from capabilities the author holds, and never including organisation ownership or deletion.
Audit and activity
Two different things: an append-only audit of privileged and state-changing actions, and a readable activity feed built from it.
- What is recorded
- The action, the actor, the organisation and workspace, the target, and the request's address and agent.
- What is not
- Values. The log records field names only — requirements, deliverable content, chat messages, billing addresses and spending limits stay out of it.
- Retention
- Append-only. Deleting a user or organisation nulls the reference rather than erasing the history.
Exports are audited specifically, because an export is the moment client-confidential material leaves the system: what was exported, in which format, how large — never the content.
Generation is recorded the same way. Every run leaves provider, model, tokens, duration and cost against the project and workspace it belongs to.
Keys, models and what leaves the deployment
Keys are never returned
No endpoint returns a provider key. Only its presence is reported, and masking happens on the server.
Your own providers
Providers are configured per deployment; the model is chosen per run. Enterprise deployments use their own keys entirely.
What is sent
A generation sends the brief, the retrieved passages, the dependency documents and the instruction to the provider you selected. Nothing else leaves.
No training on your material
Uploaded documents are extracted, embedded and stored inside their own workspace, and used only to ground that workspace's generations.
Controls that refuse rather than warn
A ceiling is only a control if something stops when it is reached.
- Where it is checked
- Before a pack run starts, before every document inside that run, before a single generation, and before a chat turn.
- What happens
- Generation is refused for every workspace in the organisation until the month rolls over or the limit is raised.
- How cost is computed
- From rates configured per provider and model, applied to the tokens each call actually used.
- Unpriced models
- Work on a model with no configured rate is reported as unpriced rather than counted as free, because a ceiling cannot see spend it never valued.
What we do not claim
A security page that only lists strengths is not a security page.
No certifications
We hold no SOC 2, ISO 27001 or equivalent attestation today, and will not imply otherwise.
Deployment-dependent
Encryption at rest, network policy and backup regime are properties of where you run it. Self-hosting puts those decisions with you.
Prompt injection
Uploaded material is delimited and budgeted, but a document that contains instructions is a known risk in every retrieval system, ours included.
Send us the security questionnaire
We would rather answer a specific question about a mechanism than publish a badge. Ask, and you will get the mechanism.