Docs
Security

Security model, for developers.

How TokenFluid keeps agent work contained, observable, and reversible. The sandbox, the patch approval flow, the audit trail, API key handling, and authentication. If you are evaluating TokenFluid for a sensitive codebase, this is the page to read.

Sandbox model

The mounted working set is a real directory on disk, but it is isolated from your working tree. The agent reads, writes, and edits files inside .tokenfluid/sessions/<id>/working_set. Those changes stay inside the sandbox until you approve a patch. Nothing propagates back to your real repository automatically.

Path traversal attempts are rejected at the boundary. TokenFluid validates every read and every write against the working set's root, canonicalizes the path, and refuses anything that tries to escape via .. or symlink tricks. The agent can do a lot inside the sandbox; it cannot read or write outside it.

The sandbox is a real directory because real directories work with real tools. The agent does not learn a virtual filesystem API — it uses rg, cat, sed, head, tail, and find against a path. You can inspect the sandbox with the same tools before approving anything. If you do not like what you see, you discard the session.

Patch approval flow

The patch approval flow is the central safety mechanism. Every change the agent proposes lands in front of you as a unified diff before it applies. You see exactly which files were touched, which lines were added or removed, and the surrounding context. You approve or you reject. There is no auto-apply.

patch-approval-flow.txt
11. Agent calls submit_patch with a unified diff.
22. TokenFluid stages the diff in .tokenfluid/sessions/<id>/patches/.
33. TokenFluid surfaces the diff in the dashboard, with file/line context.
44. You review: approve or reject.
5 ├─ reject: the agent retries, usually with a narrower diff.
6 └─ approve: the diff applies to your real working tree.
75. The decision is logged in .tokenfluid/sessions/<id>/audit.jsonl.

The flow is intentionally synchronous for the user: nothing happens behind your back. The agent is blocked on your decision. If you walk away, the patch waits. If you reject, the agent retries with a different approach. Every decision is logged locally so you can reconstruct the session afterwards.

This is why TokenFluid exists. The alternative — letting an agent write directly to your working tree — is the failure mode the product is built to prevent. The whole architecture is structured around giving the agent room to work inside the sandbox while keeping you as the gatekeeper for any change that lands in your real code.

Audit trail

Every meaningful action is logged locally in a per-session audit log. Session start and end, files selected for the working set, files touched inside the sandbox, patches proposed, patches approved, and patches rejected all land in the log. The log is append-only JSON Lines.

The log lives at .tokenfluid/sessions/<id>/audit.jsonl. You can grep it, tail it, or pipe it into another tool. Nothing in this log is uploaded to the cloud — it stays on your machine and you control it. The cloud gets aggregated counts only.

audit.jsonl
1{"ts":"2026-07-12T14:03:11Z","event":"session_started","task":"refactor auth login"}
2{"ts":"2026-07-12T14:03:14Z","event":"working_set_mounted","files":12,"path":".tokenfluid/sessions/abc/working_set"}
3{"ts":"2026-07-12T14:04:02Z","event":"file_touched","file":"app/services/auth.py","action":"read"}
4{"ts":"2026-07-12T14:06:18Z","event":"patch_proposed","files":["app/services/auth.py","app/services/sessions.py"]}
5{"ts":"2026-07-12T14:08:45Z","event":"patch_approved","files":["app/services/auth.py","app/services/sessions.py"]}

If a session goes wrong, the audit log tells you what the agent saw and what it did. If a change breaks something in production, the audit log tells you which patch introduced it. If you want to reconstruct a session a week later, the audit log is the source of truth. Keep it for as long as your team needs it; we do not delete it on your behalf.

API key security

API keys are generated using crypto.randomBytes (or the equivalent in the server runtime), producing 32 bytes of entropy encoded as a prefixed string. The full key is shown to you exactly once at creation time. After that, we cannot recover it.

We store the SHA-256 hash of the key plus a short displayable prefix (the first few characters, so you can identify the key in the dashboard). The hash is one-way: even if our database were compromised, the raw keys could not be recovered from it. Keys are transmitted over HTTPS as a Bearer header.

Keys are scoped to one of four scopes: read:sessions, write:sessions, read:usage, and admin:org. Scopes are checked on every request. Keys can be revoked at any time; revocation is immediate — the next request with a revoked key is rejected at the auth layer.

We track last_used_at per key so you can identify stale keys before rotating them, and so you can spot a key that is suddenly being used from a new location. The dashboard shows last-used timestamps and a usage sparkline per key. Rotate keys regularly; treat them like passwords.

Authentication

Account authentication uses NextAuth.js with the credentials provider. Passwords are hashed with bcrypt at a work factor of 10 before being stored. We never store plaintext passwords and we never log password values, even in error paths. The hash is one-way; we cannot recover your password from it.

Sessions are JWT-based, signed with a server-side secret, and rotated on sensitive actions (password change, key revocation, role change). The admin role is granted by configuration: the email in TOKENFLUID_ADMIN_EMAIL becomes the admin user at signup. There is no privilege escalation path — you either signed up with the admin email or you did not.

OAuth providers are not enabled in the beta. They will be added post-beta alongside SSO for Team plans. Until then, the credentials provider is the only way in, and password reset flows through the contact form during beta. SSO will land with SCIM provisioning for orgs that need it.

What TokenFluid does NOT do

TokenFluid does not execute arbitrary shell commands on your behalf. The agent's tools run inside the sandbox; TokenFluid itself never runs your build, your tests, or your deploy. If a command needs to run, you run it.

TokenFluid does not store your source code in the cloud, in any mode. Cloud-orchestrated mode stores metadata only — repo hash, file paths, task type, privacy mode, token estimates. Full repositories, SQLite indexes, and working set contents are never uploaded. The API validators enforce this in code.

TokenFluid does not store secrets, .env files, private keys, or any kind of credential. The sandbox may read files that contain secrets while the agent is working — that is unavoidable if your agent needs to understand the code — but those reads stay on your machine. The cloud never sees them; the audit log only records file paths, not file contents.

TokenFluid does not collect telemetry beyond explicit usage events. No session recordings, no keystroke tracking, no analytics beyond the counts you see in your dashboard. If we add a feature that needs more data, we will say so explicitly, and it will be opt-in.

Responsible disclosure

If you find a vulnerability, please report it to security@tokenfluid.dev. Do not file security issues in public — coordinated disclosure gives us time to fix the issue before details are released. We will credit researchers in release notes unless they prefer to remain anonymous.

We acknowledge every security report within 48 hours. We provide an initial assessment and a fix or mitigation timeline within 5 business days, typically faster for high-severity issues. A PGP key for encrypting sensitive reports will be published before paid plans launch; during the beta, plain email is acceptable for reports that do not include exploit payloads.

For reports that do include exploit payloads, please use an encrypted attachment or a private link that expires. We will coordinate disclosure timing with you and we will not publish details until you are ready (or until a reasonable deadline has passed, typically 90 days).