Security and trust
How your data is protected, what the platform records, and what crosses the boundary.
What leaves your environment
Documents you ingest are converted on the host and stored in your own database. Your content does not leave the network to be processed. Everything the platform stores, including its logs, stays in that same database.
The platform sends no telemetry, analytics or crash reports. It does not report usage or errors to any vendor, and it does not call home to us.
Inside the customer's network. nginx terminates TLS and routes
requests, in front of:
- Platform API: REST and events
- Agent tool surface: the MCP server
- Web and account API: REST
- Model gateway: routes every model call
- Background workers: no listening port
- Log shipper: logs into the database
- One database: control plane, data, logs and history in one instance; vector search required
- An optional in-network model host: which removes prompt egress entirely. A GPU is a choice, not a requirement.
On the host: document conversion, and a secrets master key supplied from the environment.
Reached by default: your chosen LLM provider (prompt content leaves, unless the in-network option is taken, and the destination is a registry row, so it is substitutable).
Off unless explicitly configured: other model providers (Groq, Together AI, DeepSeek, OpenRouter, Anthropic, OpenAI, Google) · Google Sheets, Drive, FCM push and Gemini · AWS S3 and Secrets Manager · data sources and brokers (OpenStreetMap, Crawl4AI, an MQTT broker, external MCP servers) · signed callbacks to webhook URLs you register (HMAC-SHA256).
No telemetry, analytics, crash reporting or phone-home of any kind. Nothing else crosses the line.
Services bind all interfaces, so inside your network they are reachable from the LAN unless you firewall them. Some outbound paths leave via spawned CLI subprocesses, not HTTP, so enforce the egress allow-list at the host or network layer, not in a proxy.
Every outbound path is off until you configure it. The model provider is the one exception: it is on by default. The architecture and deployment page describes how to close each path.
- Model providers decide whether your prompts leave. On the default production configuration, prompt content goes to a provider hosted in the United States. To keep prompt content inside your network, point the model registry at a model you host yourself.
- Amazon Web Services, in the Sydney region, carries object storage and a secrets manager when you configure them. It is also how we reach a deployment we operate.
- Google Workspace services carry a daily dispatch workbook and push notifications. This path is off until an integration is configured with a service account and a credential.
- Map tiles and web page fetches leave only when a feature that needs them is used. A map tile request names the customer in its user agent.
- No telemetry or analytics vendor appears on that list, because there are none.
What gets recorded
One traced request. A request arrives and a trace_id is minted;
every log line and every error carries it from that point on. Along the way a step runs, a model is
called where a rule dispatches one, a person decides only if the gate sends it there, and rows are
written to managed tables.
What it leaves behind, all reachable from that one identifier:
- Log lines, by trace:
trace_idplusspan_idon every line, shipped into the database. - Step snapshot:
workflow_step_executions, with the output written to workflow state. - Prompt and response: persisted per trace and span as artefacts, with the cost in
llm_usage_stats. - Decision event:
decision_events, kindhitl_resolved, so the person's decision is recorded inside the trail, not beside it. - History rows: a
platform_historyrow per change, carrying the author, the timestamp and the prior value. Soft delete only.
So "what happened, and why" is a query against one identifier, not a reconstruction.
Every table has a matching history table. You can ask what any record looked like at any moment, and who changed it. The fields that record who created and who last modified a row cannot be left empty. Deletes are soft: a deleted row is marked as deleted and stays in the table.
Every service writes structured logs. Each log line carries a trace id, a user id, a company id and a session id. The logs are shipped to the database and can be queried by trace, so one request can be followed end to end. Errors carry the same trace id and roll up into a daily and weekly ledger.
How access is controlled
Authorisation fails closed. A missing session, a session that cannot be resolved, an unknown event, a missing column and a database error each deny the request. None of them falls through to a default. Every tool call from a connected agent is permission gated, and the security categories in that gate cannot be bypassed.
Every row records the company that owns it. A session resolves that company before anything is read or written, so scoping is a property of the schema and not of a filter someone remembered to apply.
Passwords are hashed with Argon2id and a salt per password. API keys are 32 random bytes, stored only as a SHA-256 hash and shown to you once, when the key is issued.
What is encrypted
- In transit, the paths that reach outside are HTTPS. Every call to a model provider or a cloud service goes over HTTPS. The API terminates TLS.
- At rest, provider keys are encrypted with AES-256-GCM. The master key is supplied from the environment, never from the database, and the service refuses to start if the key is unset.
What is kept, and what can be deleted
Soft delete is the rule on every managed table. Transient data is purged on a schedule. For a set of tables where the intermediate versions carry nothing, history is collapsed to end-of-day.
- Assessment answers can be erased on request. If you ask us to delete the answers you gave the assessment on this site, a supported path deletes them immediately. It does not wait out the retention window, and it hard deletes the live rows and their history mirrors. This is the only sanctioned hard delete in the product, because the answer history should not outlive the answers.
How the code is built and checked
Every third-party library is vendored into the repository. A build does not depend on a package registry being available or unchanged. Deny-level compiler lints block the patterns that hide errors, so code that swallows a failure does not compile. A pre-commit compliance gate scans the code and blocks on a warning. We also scan the log store for secret-shaped patterns.