Skip to main content
This page is written for the person who has to sign off on running Datris. It states the model once and links to the detailed page for each control. Nothing here is aspirational: every control named is in the current release, and the last section lists what is not.

Deployment model

Datris is fully self-hosted. It runs as a set of containers on infrastructure you operate — on-prem, in your cloud account, or on a laptop. There is no managed service, no hosted control plane, no support tunnel, and no subprocessor: no customer data reaches Datris.ai the company.

Trust boundaries

The diagram does not draw two exits you configure yourself: the AI provider in each AI slot, and the agent you connect with an API key. Every request follows the same path: the key identifies the caller, the capability check decides whether the route is allowed at all, the agent policy decides whether it runs now, waits for a person, or is refused, and only then does the server consult Vault for the credential the run needs. Policy is evaluated before Vault is touched.

Where data can go

Your data goes only where you send it. Besides the destinations your pipelines write to, data leaves the perimeter only to the AI provider you choose for each AI slot, to the agents you connect, and, if you turn them on, to web search and a GitHub repository for scripts. The chat assistants need a cloud AI provider, while code generation and embeddings can run on local models. Data Flows lists, for row values, schemas, credentials, provider keys, logs and scripts, every place each can go and the setting that changes it.

Identity and authorization

  • Humans log in to the UI with a username and password (BCrypt, cost 12). The first boot creates an admin account with a random bootstrap password, printed once to the server log (docker compose logs datris | grep "Bootstrap login"); change it at first login. Sessions are opaque random tokens in an HttpOnly, SameSite=Strict cookie with an 8-hour TTL. Three roles — admin, editor, viewer. With OIDC_ENABLED=true, people can instead sign in with SSO through your identity provider (OpenID Connect authorization code flow with PKCE; ID tokens checked for signature, issuer, audience, expiry and nonce, RS256/ES256 only); they become ordinary Datris users with one of the three roles, and the built-in admin account can never be reached through SSO. See User Authentication and Single sign-on (OIDC).
  • Programmatic clients — the CLI, MCP agents, scripts — each hold their own labeled API key, sent as x-api-key and validated against Vault. Every key carries an explicit list of capabilities (resource:action[:scope]); a call outside that list returns 403, and the MCP tool catalog an agent sees is filtered to match. Templates (read-only, rag-builder, reporting, ops) cover the common shapes. Keys are stored hashed, shown once, and revocable individually. See API Keys.
  • Tap scripts never receive a platform key. Each run gets a short-lived, read-only token for the platform API that the tap wrapper attaches automatically.
User login, API keys, the audit log and the agent policy ship in the open-source build and are off in the shipped defaults so that existing deployments are unchanged; they are switched on for production. A new install does it in one step with the installer option DATRIS_GOVERNED=1; an existing install adds USE_USER_AUTH=true, USE_API_KEYS=true, USE_AUDIT_LOG=true and USE_AGENT_POLICY=true to .env (see Switch on the governance controls). The governance.controls doctor check names any of the four that is off.

Credentials

  • HashiCorp Vault holds every secret — source and destination credentials, AI provider keys, the platform’s own service passwords. The platform never persists a secret to disk outside Vault, and API responses mask sensitive fields.
  • Agents never hold a key. An agent references a secret by name (create_tap_secret, list_tap_secrets, get_tap_secret_fields returns key names only). The value is delivered to the tap at run time as environment variables inside the runner and to the destination writer inside the server. It never appears in an agent’s config, prompt, or tool result.
  • Agents can only touch their own secrets. Secrets created through MCP are tagged as tap secrets; an agent cannot modify or delete a secret a person created in the UI.
  • Secrets are masked in logs. Tap stderr is scrubbed before it is logged.

Agent governance

  • Agent Policy decides, per action, whether an agent runs it unattended, waits for a person to approve it, or is refused. It is enforced by the platform on every client — the in-platform Assistant, Claude, Cursor, the CLI, any script — and an agent cannot edit the policy or decide an approval, whatever its key holds. An approval executes exactly what was proposed; if the resource changed in between, it is refused as stale. See Agent Policy.
  • Audit log (with the audit log on, USE_AUDIT_LOG=true) records every platform write, best effort by default and without loss in strict mode — create, change, run, delete, login, key rotation, denied request — attributed to a login, an API key, or the Assistant acting on a user’s behalf. Agents can attach a one-line reason to any change and it is stored with the entry. Entries are queryable in the UI and over REST, exportable as CSV, and mirrored line-by-line to the server log (JSON under the production profile) so an existing log pipeline or SIEM receives the trail with no extra integration. See Audit Log.
  • Provenance, with stamping on for a pipeline, stamps every landed row (XML sources excepted; a run that cannot be stamped fails in strict mode) with the run, config version, tap run, script commit, and declared source; get_provenance resolves a stamp back to its origin, and vector-search results carry the same fields per chunk so a RAG answer can cite where its context came from. See Provenance, Lineage & Discovery.
  • Versioning. Every pipeline and tap definition change is snapshotted; restores are append-only. Tap scripts can be stored in a git repository you own. See Tap GitHub Storage.
  • Recovery agent actions pass through the same policy gate; under propose mode everything it wants to do queues for approval. See Incidents.

Isolation of agent-written code

Taps are Python that agents (or people) write and Datris runs. On Docker Compose the isolated runner is on by default: tap code executes in a separate datris-tap-runner container that holds no platform credentials and sits on a network with no route to the config store, the object store, or Vault. It can reach its data source, install the packages it declares into a throwaway environment, call back into the Datris API with its per-run read-only token, and return records. The server refuses to start with isolation on and a missing or default runner token. See Tap Execution & Isolation.

Transport and storage

  • TLS terminates at a reverse proxy you place in front of the server (nginx, Caddy, Traefik). Do not expose port 8080 directly. Container-to-container traffic inside the Compose network is plaintext; the host network is the trust boundary.
  • External databases. With DATRIS_ENV=production the server refuses to start if a JDBC URL points at an external Postgres host without sslmode=require or stricter.
  • At rest. Datris does not enforce encryption at rest on Postgres, MongoDB, MinIO, or Kafka; enable it per store for production.
  • Multi-tenancy, when enabled, isolates tenants at the database level — separate Postgres databases and separate object-store buckets.

Air-gapped operation

Every store Datris depends on is bundled or pointable at one you already run. For the AI features, local models through Ollama cover code generation and the one-shot helpers (profiling, fix suggestions, tap diagnosis), and the bundled bge-m3 embedding server covers embeddings. The chat assistants (the Assistant, Search chat, Catalog chat, the Configuration assistant, Ops chat and the recovery agent) need one of the supported cloud providers today, so an air-gapped deployment runs without them. See No cloud exit. The bundled embedding model downloads once on first start; pre-pull the images and the model on a connected machine and move them across. Add DATRIS_UPDATE_CHECK=0 to .env so datris doctor does not try to reach datris.ai (without a route out the attempt only times out after 3 s and is reported as skipped).

No telemetry

The platform sends no usage data, crash reports, or license checks. There is no beacon in the server, the UI, the MCP server, or the installer, and no install id or other identifier is created. Verify it yourself:
The second command prints two lines, one for each outbound request Datris can make. These are the only two; links to the documentation site (docs.datris.ai) are shown to you, never fetched. Datris uses the update check to count the versions in use by distinct source address. Nothing is stored on your machine. The documentation site you are reading measures page views; the platform does not.

Vulnerability handling

Private reporting, response targets, advisories, SBOMs, and dependency scanning are on Vulnerability Disclosure.

What Datris does not do

Stated so you can plan around it rather than discover it:
  • No built-in MFA. MFA comes from your identity provider through OIDC single sign-on (OIDC_ENABLED=true, see Single sign-on (OIDC)): people who sign in with SSO get whatever MFA, password rules and lockout the provider enforces. Local accounts, including the admin recovery account, still have a minimum password length only and no complexity rules or lockout.
  • No SAML, and no group-to-role mapping from the identity provider yet: an SSO user’s role is set on the Users screen (or OIDC_DEFAULT_ROLE for new people).
  • No built-in rate limiting or WAF — put one in front of production deployments.
  • No enforced encryption at rest — enable it per store.
  • CORS allowed origins default to * for development — set cors.allowedOrigins to your real origins in production.
  • No SOC 2 report. In a self-hosted deployment no customer data reaches Datris.ai, so most trust-services criteria fall on your environment; the controls that do apply to the vendor — secure development and vulnerability handling — are described above.

Operator checklist for production

  1. Run Vault in non-dev mode with sealed root tokens.
  2. Put a TLS-terminating reverse proxy in front of the server; do not expose 8080.
  3. Switch on the governance controls: DATRIS_GOVERNED=1 on a new install, or USE_USER_AUTH=true and USE_API_KEYS=true (with the agent policy and audit log in step 5) in .env; change the admin bootstrap password immediately; issue one scoped key per agent.
  4. Turn on SSO (OIDC_ENABLED=true with your identity provider’s issuer and client) so people sign in with their company account and its MFA; keep the admin password for recovery. See Single sign-on (OIDC).
  5. Turn on USE_AGENT_POLICY=true and start from Use recommended; turn on USE_AUDIT_LOG=true and ship the log line to your aggregator. datris doctor shows governance.controls as ok once all four are on.
  6. Keep the isolated tap runner on (the Compose default).
  7. Set DATRIS_ENV=production, sslmode=require on external Postgres, and cors.allowedOrigins.
  8. Enable encryption at rest on the stores; rotate API keys periodically.
  9. Run the doctor self-check before every upgrade.
If you run separate dev, QA and production installs, give QA the same governance settings as production (DATRIS_GOVERNED=1, SSO, the agent policy and the audit log), so that permission and policy problems show up in QA before a catalog reaches production. See Dev, QA and production.