Protect a secret ★¶
This is the tutorial that shows what TOVIO is for.
You will put a real secret — production credentials — into a repository, declare a one-line policy over it, and then prove something Git structurally cannot do: the secret stays encrypted to anyone without clearance, even when they clone the entire repository. Not because a server says no — the server never sees the plaintext — but because the math won't decrypt for the wrong identity.
By the end you'll have felt the aha that makes TOVIO worth adopting.
Runs today — this is the Phase 1 permission layer
The cryptographic permission layer (Tier-0/Tier-1 encryption, the policy language, the Key Authority) is built and runs today, proven offline and over real TLS. The commands and output below reflect a build you can actually run — declare a policy, commit, and watch the object land as ciphertext, exactly as shown. TOVIO is not generally available and its independent assurance gates remain open, so don't trust it with irreplaceable production secrets yet; the capability this tutorial demonstrates is real and runnable from source.
The problem, stated plainly¶
Every team has files that must live in version control for reproducibility — a .env.production, a
signing key, deploy credentials — but must not be readable by everyone who can clone the repo. In
Git the permission boundary is the whole repository: anyone with read access reads everything. So
teams reach for workarounds — a second private repo, submodules, an external secrets manager — all
routes around the VCS.
TOVIO fixes this at the architecture level. A file is either a clear object (anyone with repo access can read it) or a policy object (encrypted, so only identities whose attributes satisfy the policy can decrypt). Cloning gives you the ciphertext either way. The cryptography, not a server, decides what you can read.
Step 1 — A repo that will hold a secret¶
Because this repo will use policies, initialize it in Team Mode — that's what provisions the Key Authority that decides whose key may unwrap a protected file.
tovio init initializes the current directory, so make one and step into it first:
✓ Initialized empty TOVIO repository in /path/to/payments-service/.tovio
On branch main · current change chg:4npn81qsj40msxf16kr5vydtwr · mode: team
Identity did:key:8d015cc04085309a3ad5a7f7a29db1048c25b88257501ad9d2f43d3bfaf4e83a generated and sealed in your OS keychain.
Protect paths with `tovio policy set …` — matching files encrypt on the next commit.
→ Next: edit files, then `tovio commit -m "…"`
Recovery phrase written to /path/to/payments-service/.tovio/tovio-recovery-key.txt (owner-only, kept out of commits) — move it somewhere
safe (a password manager), then delete it. Losing BOTH your key and this phrase is unrecoverable.
Move the recovery phrase somewhere safe before you go on — it and the sealed key are the only two ways back to protected content.
Why Team Mode?
Simple Mode (solo, the default) is keyless: no identity, no Key Authority, and so nothing that can seal a protected path — encryption never appears. The moment you want path-scoped, cryptographically-enforced read access, you want the Key Authority that Team Mode sets up. It is an authorization oracle: it decides whose wrapped key gets included for a protected path. It never sees your plaintext and never holds the content key.
Step 2 — Write the secret¶
Create the file you need to protect. Right now it's just a normal file — plaintext, a clear object.
mkdir -p config/production
cat > config/production/api-keys.env <<'EOF'
STRIPE_SECRET_KEY=sk_live_DO_NOT_LEAK_ME
DATABASE_URL=postgres://prod-credentials
EOF
Step 3 — Declare a policy¶
Now the one line that changes everything. Attach a read policy to the path:
tovio policy set "config/production/**" \
--read "role=senior & clearance=secrets" \
--write "role=staff | role=security"
✓ Policy set for config/production/**
Files under config/production/** will be encrypted on the next commit.
You didn't generate a key, choose a cipher, or wrap anything by hand. You declared who should be
able to read — role=senior & clearance=secrets — and TOVIO does the cryptography for you.
Read it back in plain language
The policy says: to read these files you must have the senior role and secrets
clearance; to write them you must be staff or security. The policy manifest itself is
always clear-readable and version-controlled — what's secret is the file contents, not the rule.
Step 4 — Commit, and the encryption happens¶
When TOVIO snapshots a path that has a policy, it encrypts it at snapshot time, so plaintext never enters the tracked tree. The object that lands in the store is ciphertext.
Policy is enforced at snapshot, not after the fact
The plaintext never lands in a tracked object in the first place. There's no window where the secret sits in cleartext in the repo's history waiting to be scrubbed.
Step 5 — The proof: clone it, and try to read it¶
Here's the demonstration. Imagine a contractor — call them Dana — who has repo access but no
secrets clearance. Dana clones the whole repository — tovio clone names the relay, the
repository id (the blake3: address the Forge prints, not a human name), and the directory to
create:
# As Dana, on another machine — full clone, full history
tovio clone https://forge.example.dev \
blake3:0f5a2c7d91e34b86ac5f1d20e8b47c93a6d0f81b5e2947c3d6a08f14b7e2c5d9 \
payments-service
cd payments-service
Dana has every byte of the repository, including the protected object. But checking it out cannot produce the plaintext, so TOVIO writes a marker beside the path instead of the file:
TOVIO: protected file `config/production/api-keys.env` could not be decrypted (no reading key held).
The ciphertext is present in the object store; check it out again once a key is available.
The ciphertext is right there in Dana's object store; what is missing is a key that unwraps it. To understand why, Dana asks TOVIO:
config/production/api-keys.env (read policy: role=senior & clearance=secrets)
subject: did:key:12f43856165ea640b26f29aadc2c7c27b97d2bee163b7c5790716237e1874e23
[✗] role=senior
[✗] clearance=secrets
verdict: DENIED ✗ — obtain the missing attribute(s) above, or have an authorized identity grant you
This is the moment. Dana has the full clone and still can't read the file — and TOVIO names each
attribute that is missing, rather than a bare "denied." Dana can open a portable request for the
missing ones — --attr is repeatable, and this policy needs both — with
tovio access request "config/production/**" --attr role=senior --attr clearance=secrets, which an
authorized identity answers with tovio access grant.
Why a stolen clone or a compromised mirror doesn't help
The protection isn't a server check that an attacker could bypass — it's in the ciphertext. A compromised host, an untrusted mirror, or a leaked backup can all serve the protected object, but none of them can read it. Only an identity whose attributes satisfy the policy holds a key that can unwrap it. The math, not a server, enforces it.
Step 6 — Now as someone with clearance¶
For contrast: a senior engineer with secrets clearance clones the same repo and the file is simply there, in plaintext, transparently decrypted on read. No extra step, no separate secrets tool.
# As a senior engineer the owner enrolled with
# tovio access grant --identity alice.identity.pub \
# --attr role=senior --attr clearance=secrets
tovio access check config/production/api-keys.env
config/production/api-keys.env (read policy: role=senior & clearance=secrets)
subject: did:key:5c08b1e9d34f27a6b09e15c847d3f20a96e7b418c5d02f639a71e8b4c603d95f
[✓] role=senior
[✓] clearance=secrets
verdict: AUTHORIZED ✓
Same file, same policy, two different identities — and the DID on that subject: line is the whole
reason the verdicts differ.
Same repository. Same files. Two different realities, decided by the cryptography.
What you proved¶
- A secret can live inside a shared repo — same history everyone clones — yet be readable only by the right identities.
- The protection survives a full clone. It is enforced by mathematics, not by a server's access list, so it holds on a laptop, a peer, or an untrusted mirror.
- You never managed a key or chose a cipher. You declared who may read a path; TOVIO did the rest.
tovio access checkexplains every verdict attribute by attribute — never a bare "denied" — andtovio access requestturns a denial into something the Key Authority can answer.
This is the one capability that justifies a new version control system. One repo, not two; secrets in the open, readable only by the cleared.
Next¶
You've protected a secret from a human without clearance. The same mechanism bounds AI agents: TOVIO does not unwrap protected content for an agent identity that lacks both the required clearance and usable recipient key material. An authorized user, tool, runner, or model integration can still explicitly disclose plaintext outside that boundary. Teams can exchange the protected ciphertext through a Forge.
See it in the guided tutorial
tovio quickstart --topic policy walks the sealing half of this story in a throwaway scratch
repository: protect a path with one line, write a secret into it, commit it as ciphertext, and see
the 🔒 marker in tovio status. The full-clone proof above is the part you run yourself.
There's deeper coverage of the policy language and the Key Authority in the
guides.
Last reviewed September 9, 2026
Suggest an improvement to this page Not for security reports — see disclosure