Security and operations
Cortex runs on one AWS EKS cluster in two environments, with the controls a financial-software evaluation expects: tenant isolation by project, fail-closed access control shared by every service, attributed writes, per-project secrets, hardened pods, in-cluster image builds, health watchdogs with alerting, and a SOC 2 readiness programme documented on the trust center. This page summarises the operational and security posture; the technical detail behind each control is in the repository and on trust.tiva-ai.com.
Tenancy and isolation
- A project is the unit of tenancy. Its configuration lives in its own Dolt database, its engine objects on its own fork, its pipeline output in its own Postgres target, its application in its own containers. Per-organisation storage can override the platform default so that even object storage is credential-separated.
- An agent process is scoped to one fork by an opaque handle resolved server-side; it has no tools beyond its manifest and no shell or file access.
- App services run as their own Deployments with the image's own entrypoint, HTTP or TCP probes, a writable volume under
/data, resource limits, and the project's environment only. Platform configuration and platform secrets are never mounted into a customer's service. - The platform pods run as non-root users with read-only root filesystems and dropped capabilities; session state lives under
/tmp.
Identity and access
- People sign in to cortex (password or SSO through OpenID Connect) and receive a JWT. Roles are platform administrator, organisation administrator, member and application user.
- One pure access rule (
shared/access-policy.js) decides project access for the backend, the MCP session gate and the accounts service, so the three cannot drift. It fails closed on an unknown project, a lapsed membership or a lookup error. - Only administrators may author applications, agents, models and projects. Application users never reach project data; a shared application grants exactly the application's own surface.
- MCP access is OAuth 2.1: dynamic client registration, browser consent, non-expiring bearers stored in
cortex_opsand verified on every request, revocable by deletion. Access tokens for headless frameworks are minted by the person, labelled, listed by prefix and revoked from Settings. - Row and column data-access policies compile per request to a grant signed with a per-project HMAC secret; the engine treats an unsigned or invalid grant as strict.
Attribution and audit
- Every change to a project's configuration is a Dolt commit with the acting person's email as the author. Pipeline runs record the configuration commit they ran against.
- Agents acting through a person's chat commit as that person. Fleet jobs that act for a person carry that person's identity through an on-behalf-of bearer that can only narrow, never widen, access; a claim for a person who does not exist is refused rather than silently attributed to the worker.
- Guarded agent answers are recorded in a ledger with verdict, reason, checks, tool calls and the draft.
- Workflow definitions keep an append-only version history; a share surface cannot author, publish or restore.
- A SOC 2 audit module runs control checks per project on the fleet and files fix requests for auto-fixable findings, bounded to three rounds before a person is escalated to.
Secrets
- Per-project grant secrets are minted by the backend, pushed into the fork's environment as secure variables and rotated as an operation. Secure environment values are flagged and never printed.
- Test specifications never carry a credential; they read one from the target's own environment by key and skip when it is absent.
- Customer archives mint every credential per archive (operator login, JWT secret, store passwords, per-target role passwords), scrub platform passwords from the configuration dump, ship only reachable configuration, and are audited for key shapes before handover.
- Internal service hops require a shared internal secret header when configured.
Infrastructure and delivery of the platform
- Cluster, DNS, certificates, IAM, static sites and buckets are managed with Terraform from an operations jumpbox; Kubernetes configuration is applied from kustomize overlays. No one-off edits to live objects.
- Images are built by Bitbucket Pipelines (verify, nine parallel builds, roll) and pushed to ECR; the dev branch deploys to the dev namespace, the prod branch to production. The verify step runs the engine, accounts and backend test suites, a critical-severity dependency audit and a tracked-secret scan.
- Customer service images are built in-cluster by kaniko; a failed build fails loudly and the service keeps its previous image.
- Ingress is through the AWS load balancer controller with ACM certificates; applications are published under a wildcard applications domain or a customer's own hostname.
Observability and health
- The engine exports Prometheus metrics; services expose health endpoints; the cluster carries the usual logging.
- The tests watchdog runs every project's suite every 15 minutes and after each deploy, keeps one health verdict per project and posts to a Slack alerts channel on a transition (red, green, a different failing set, a runner crash). A red suite blocks promotion of a project copy.
- Fleet key health is probed independently of the fleet and alerted once per transition.
- The Status page of a project shows the latest verdict of every test with where and when it ran.
Compliance posture
The trust center publishes the security and compliance package: information security, access control, data protection, vulnerability management, secure development, incident response, business continuity, change management, vendor risk, retention, cloud infrastructure, penetration testing, a SOC 2 control matrix and the readiness findings report. It is management-prepared documentation on the road to a SOC 2 Type II report; it is not itself an audit report.
What is not yet in place
For completeness of an evaluation: refresh tokens are not implemented on the MCP OAuth server (bearers do not expire and are revoked by deletion); the Rust single-binary runtime is not the production runtime; an unregistered agent (one the registry has not yet synchronised) is visible to project members by a documented default flag.