Security and data flow
The boundary is explicit.
A Jern Cloud session runs the open-source Jern runtime on a machine created for one attempt and destroyed afterwards. This page describes what runs where, what is encrypted, who can see what, and what the design does not defend against. Every statement is checked against the code and updated in the same change that alters the behaviour.
- What runs where
- One attempt, step by step
- What is encrypted
- Who can see what
- Limits we enforce
- Honest limits
- Reporting a vulnerability
What runs where
| Component | Where | Holds |
|---|---|---|
| Jern Cloud control plane | Fly.io, one region | Session records, encrypted evidence, the inference gateway, GitHub App credentials |
| Runner machine | Fly.io, one per attempt, destroyed afterwards | A pinned checkout, the open-source runtime, short-lived credentials for that attempt only |
| Your repository | GitHub | The protected policy baseline and the pull requests Jern opens |
| Model provider | Anthropic, OpenAI, Google, or Fireworks, whichever key the workspace holds | Prompts and completions for the attempt, forwarded by the gateway |
One attempt, step by step
- You send a message in a session. The session already pins the repository revision, the policy baseline by digest, the environment revision, the model, and the token cap. None of these can change during the session.
- The control plane reserves a fresh machine and issues it a single-use credential valid for fifteen minutes. That credential can claim exactly one task and nothing else.
- The machine checks out the pinned revision with a read-only GitHub token that is erased immediately after the fetch, then verifies the policy baseline's digest.
- If the environment declares a setup command, it runs in its own process and network domain that can reach only the declared package registries. That domain is destroyed before the agent starts.
- The agent runs as an unprivileged user inside a private network namespace whose only route is a local relay to the Cloud gateway. It cannot reach GitHub, package registries, or the internet, except public hosts the baseline names, reached over HTTPS through the runner's proxy with every connection counted. It holds no credential of yours: model calls go to the gateway under a run-scoped token, and the gateway holds the provider key.
- The gateway enforces the admitted model and the token cap, meters usage from the provider's own response, and rejects anything over budget.
- When the agent finishes, the runner verifies that the repository's
.gittree is unchanged, that every changed path is inside the baseline's editable paths, and that no live credential appears in the tree. - The runner uploads the trace, which is encrypted before it reaches the database. Only then does it obtain a publication token, commit on the session's branch, push, and open or update the pull request. Jern never merges.
- The machine is destroyed. Nothing from the attempt persists on it.
What is encrypted, what is not
Encrypted before persistence, with versioned keys held in AWS KMS: traces, workspace snapshots, dependency caches, and any provider credential you give us. The database never holds the plaintext of these. The run identifier is bound to the ciphertext so evidence cannot be reassigned to another run.
Stored in plaintext columns: your messages, the agent's final replies, and task prompts, so the dashboard can show your conversation. They are redacted in place once older than your evidence retention window. Retention is enforced by an hourly sweep and can also be run on demand from Settings.
Never stored: GitHub user tokens, installation tokens, runner credentials, or provider keys in plaintext. Only SHA-256 digests of one-time and session credentials are kept.
Who can see what
- Repository access always comes from GitHub. A person sees only the repositories the Jern Cloud App grants them at sign-in, re-checked on every read.
- Workspace membership grants visibility of the workspace, not of repositories or evidence.
- The decrypted trace is returned by exactly one endpoint, to a person already authorized to read that run, and is marked not to be cached.
- Every organization event that matters for audit is recorded and exportable as newline-delimited JSON.
- Request logs carry a request id, method, path, status, and timing. They never contain prompts, traces, or credentials.
Limits we enforce
| Limit | Value |
|---|---|
| Tokens per attempt | The session cap, metered by the gateway |
| Agent phase | The workspace's time limit per attempt, 30 minutes by default, up to the plan's ceiling |
| Whole machine | The time limit plus setup and publication, behind a 25-hour guard |
| Setup command | 10 minutes |
| Processes per domain | 128 |
| Agent output | 10 MiB per phase |
| Attempts per task | 3 |
Honest limits
- Isolation relies on Fly.io's guest boundary and on Linux namespaces and seccomp inside the guest. An independent test of that boundary is planned; until it is published, treat the guest boundary as the vendor's claim rather than ours.
- The orchestration side of the runner runs as root inside the guest by design. The agent does not.
- Conversation text is redacted by retention, not encrypted at rest. Do not put secrets in messages.
- Jern Cloud does not currently claim compliance certification, customer-managed encryption keys, or data residency.
- Jern governs Jern runtime sessions, not sessions from other coding-agent products.
- A pull request is still code you have not read. Review it as you would any contribution.
Reporting a vulnerability
Write to security@jern.ai or use GitHub private vulnerability reporting. A machine-readable contact is published at api.jern.ai/.well-known/security.txt. The runtime security model, policy implementation, receipt derivation, and trace vocabulary are public under Apache-2.0.
Last updated: September 6, 2026.