Secrets, Service Setup & Materializer
Trinity stores every API key, token, and config file your project needs in one encrypted store. The full management surface lives in Project Settings → Secrets, which splits into three sub-tabs:
- Overview — a glance card with counts (configured / needs setup), a pending-setup list per service, and a "Re-sync files" button for materializable rows.
- Shared — project-wide secrets visible to teammates (tier 3/4). Table view, filters, bulk
.envimport, per-target editing. - Yours — your personal overrides for this project (tier 1/2). Same editor, scoped to your account; teammates never see these rows.
End-to-end encryption
Every secret is encrypted and decrypted on your own devices — the server stores and serves only ciphertext. There is no server-side key: nobody without one of your enrolled devices can read your values, including Trinity.
Two key boundaries decide who can decrypt a row:
- Your personal key encrypts everything scoped to you — Yours rows and your team-wide personal keys. Teammates can never decrypt these, even though the rows live in the shared team workspace.
- The team key encrypts shared rows (project-shared and team defaults). Only devices belonging to current team members hold it, and removing a member rotates it — see Teams.
A device only holds keys once it's been approved. Rows your device can't decrypt show as locked rather than exposing anything. Manage devices, approvals, and your recovery code in App Settings → Profile → Devices.
Where secrets land on disk
Most secrets are environment variables — they get injected into the agent's process at execution time and never touch your filesystem. A handful (like dexie-cloud.json or .env.local) need to live as files inside your project — Trinity writes those into your repo under a managed .gitignore block so they never get committed. See The materializer below.
The Shared and Yours editors
Open Project Settings → Secrets and pick Shared or Yours. You'll see a table grouped by key name. A key with two target overrides shows up as one row that expands to reveal the per-target values.
What each row tells you
| Column | Meaning |
|---|---|
| Key name | The env var name (e.g. STRIPE_SECRET_KEY) |
| Target | Which target this row binds to. "Project-wide" if it applies to every target. |
| Service | The service that owns this key (e.g. stripe, dexie-cloud) |
| Purpose | runtime (env var), provider (AI provider key), file (materializes to disk) |
| Value | Masked. Click the eye icon to reveal — your device decrypts it locally and shows briefly. |
| Updated | Last write time |
Filters
- Search — substring match on key name
- Targets — filter by one or more targets. "Project-wide" is its own toggle.
- Purpose — narrow to runtime, provider, or file-purpose secrets
Adding a secret
Click Add secret. The dialog asks for:
- Key name — the env var name (e.g.
STRIPE_SECRET_KEY) - Value — what you're storing. Sensitive by default; the input masks the value as you type.
- Targets — pick one or more targets, or leave as "Project-wide" for cascade fallback. One key can fan out to multiple targets in a single submit.
- Purpose — defaults to
runtime. Pickproviderfor AI provider keys,filefor config files (file purpose adds a destinations field — see The materializer). - Sensitive — UI dimension only; controls whether the value is masked by default. Every row is encrypted at rest regardless.
Trinity infers sensitive from the key name (*_SECRET, *_KEY, *_TOKEN, *_PASSWORD default to true) when you don't override.
Editing a secret
Click any row to open the edit dialog. You can change the value, retarget the binding (move from project-wide to target-specific or vice versa), update the label, or delete the entry.
The cascade resolution rule means: if you have a project-wide value for DATABASE_URL and a target-specific value for the same key on the api target, the API target gets its own value and every other target gets the project-wide one. No manual fan-out needed.
Permissions
Who can edit, reveal, or delete a secret depends on the row's tier and the team's Manage Secrets permission setting.
| Tier | Edit / reveal / delete |
|---|---|
| Project-shared (Shared) | Owner / manager always. Members pass when the team's Manage Secrets permission is set to "all", blocked when set to "owner". |
| Project per-user (Yours) | Each user only. Pinned to your account — teammates never see, edit, or reveal your Yours rows. |
| Team default (team-wide) | Owner / manager only. Members can read masked values and use them at runtime, but cannot write or reveal plaintext. |
User team-wide (your /me row) |
Each user only. Same isolation as project per-user — teammates can't see your team-wide personal keys. |
Configure the Manage Secrets permission in Team Settings → Access Control → Permissions, with optional per-project overrides in Project Settings → Permission Overrides. The default is "owner only". Personal scope has no permission gates — everything is yours.
Bulk .env import
Click Import .env to paste a .env file. Trinity:
- Parses the file (handles quoted values, escaped newlines, inline comments)
- Runs the sensitivity heuristic per key
- Lets you pick which targets each key binds to (or all → project-wide)
- Picks a conflict policy: keep existing, overwrite, or skip
- Submits everything in one transactional write — the whole batch rolls back on any failure
Per-row conflict overrides are available if you want different behavior for some keys. Result rows report created | updated | skipped | error so you can see exactly what happened.
Provider keys
The Project Settings → Provider Keys card is a focused view of purpose='provider' rows for AI providers (Anthropic, DeepSeek, Moonshot, Z.ai, Qwen, Ollama). Same encrypted store underneath; the card just narrows the table to provider rows.
You can also set provider keys globally (across all your projects) in App Settings → AI Models. Cascade rule: project-scoped wins over global.
The materializer
Some setup flows produce config files Trinity needs to write to disk — dexie-cloud.json, .env.local, certificates, or project-specific YAML. These get stored as purpose='file' secrets with destinations (where on disk to write them):
- target — inside the consuming app's directory (e.g.
apps/web/.env.localfor a turborepo target) - repo — at the repo root (e.g.
dexie-cloud.jsonnext topackage.json) - trunk — at your workspace root (project-wide config)
Trinity's materializer is what writes these files. It runs:
- Right after a worktree is created (so every parallel story sees the right files)
- After the setup runner finishes capturing values from a CLI
- After successful story commits (so freshly-written secrets land before the next phase reads them)
- On demand via Project Settings → Re-sync files
.gitignore management
Every materialized file gets added to a Trinity-managed block in your repo's .gitignore:
# === Trinity-managed (do not edit between markers) ===
.env.local
config/dexie-cloud.json
# === /Trinity-managed ===
Don't edit between the markers — Trinity will overwrite. Anywhere else in the file is yours to manage. If you delete a file-purpose secret, Trinity unlinks the file and prunes the line from the block on the next materializer pass.
How agents see your secrets
When a story executes, Trinity assembles the env var bag from:
- Target-specific rows for the story's target
- Project-wide rows (cascade fallback)
- Global rows (across all your projects)
The first hit wins per key name. Multi-target stories that don't have a clear target binding raise a gate so you can split the secret per-target or mark it project-wide.
For file-purpose secrets, agents just see the file on disk — the materializer wrote it before the agent ran.
Service setup gates
If you start a story that needs a service Trinity sees as unconfigured, the story pauses at a service setup required gate. The gate dialog has the setup runner pre-bound to the right target — finish the flow and the story resumes automatically. Agents can also raise this gate mid-execution via the signal_service_required tool when they hit a missing service that wasn't on Trinity's radar.
See Execution Gates for the full gate catalogue.