Skip to content

Check access

When an identity cannot read a file, TOVIO never leaves you guessing. tovio access check is the diagnostic that every permission message points at: it names the policy, walks each predicate the policy requires, and marks the ones the subject's attributes do not satisfy. No bare "permission denied" — always a named attribute and a next step.

Phase 1 — built today

Access diagnostics are part of the Phase 1 permission layer, which is done. tovio access check and the 🔒 protected-path indicator in tovio status are built and enforced today, offline and over TLS. Note the shape of the diagnostic in this build: run without --identity it evaluates the local repository identity as the repository owner, so it always answers AUTHORIZED. Pass --identity <file> to get the per-predicate verdict.

flowchart LR
    C["tovio access check <path><br/>[--identity &lt;file&gt;]"] --> P{"policy?"}
    P -- no --> OK([✓ clear])
    P -- yes --> O{"subject is the owner?"}
    O -- yes --> OW([✓ authorized])
    O -- no --> D{"attributes satisfy expression?"}
    D -- yes --> G([✓ authorized])
    D -- no --> M[["✗ marks each unsatisfied predicate"]]

More diagrams for the full permission and review flow: Permission & review workflows.

Diagnose one path

A path with no policy on it is answered in one line:

$ tovio access check src/app/main.ts
src/app/main.ts: clear — readable by anyone (no protective policy).

On a protected path, access check with no --identity evaluates this repository's own identity, which it treats as the repository owner — and the owner always qualifies for its own protected files, so the answer short-circuits without enumerating predicates:

$ tovio access check config/production/api-keys.env
config/production/api-keys.env  (read policy: role=senior & clearance=secrets)
  subject: did:key:559ebdc73461a50848b2020a2919dd25f973af54c00494114e46ea5976aa23fc (repository owner)
  verdict: AUTHORIZED ✓

The per-predicate diagnostic — the reason this command exists — appears when you check a different identity, by pointing --identity at the identity.pub they shared:

$ tovio access check config/production/api-keys.env --identity ./alice-identity.pub
config/production/api-keys.env  (read policy: role=senior & clearance=secrets)
  subject: did:key:69923b5cc15f6c2cea3df9a1db6d9fe7937ca8deadfd86efde547b8bf79b073e
    [✗] role=senior
    [✗] clearance=secrets
  verdict: DENIED ✗ — obtain the missing attribute(s) above, or have an authorized identity grant you

Read it top to bottom: the first line names the path and the policy it is governed by, the checklist marks each predicate the expression contains, and the verdict line says what to do about the ones marked ✗. Every denial names the attributes the subject is short of, so they can ask for exactly those:

$ tovio access request "config/production/**" --attr clearance=secrets

If a required attribute is held but its Key-Authority-signed certificate has lapsed, the check says so separately and points at TVO-KEY-001. The fix is for the Key Authority to re-issue that claim with tovio access grant — not tovio key renew, which only renews certificates this identity issued.

Check write access too

Read and write are separate planes, so check them separately. Add --write to diagnose whether an identity's attributes would satisfy the path's write policy when they push:

$ tovio access check config/production/api-keys.env --write --identity ./alice-identity.pub
config/production/api-keys.env  (write policy: role=staff | role=security)
  subject: did:key:69923b5cc15f6c2cea3df9a1db6d9fe7937ca8deadfd86efde547b8bf79b073e
    [✓] role=staff
    [✗] role=security
  verdict: AUTHORIZED ✓

The checklist marks every predicate in the expression, so under an | you will see satisfied and unsatisfied leaves side by side — the verdict line, not the individual marks, is the answer. --write combines with --identity exactly as the read check does, and follows the same owner short-circuit when you omit it.

Read access is enforced by encryption (you either hold a key or you do not); write access is checked by the relay when you sync, and a failure there is TVO-PERM-002. --write tells you the write verdict before a push is attempted.

policy test is the same evaluation

tovio policy test <path> --identity <file> performs the same offline evaluation and prints the same verdict; use whichever name reads better where you are. Both take a file path, never a DID string, and both fall back to this repository's identity when you omit it. Useful before you grant or revoke someone — see write a policy for more on policy test.

Protection indicators in status

You do not have to run a check to see what is protected. tovio status marks protected paths inline with a lock glyph, so you spot encryption at a glance in your everyday loop:

$ tovio status
  on main · chg:8k0cjrf4mca5akfhndvrd5rjrw
  modified (2 file(s))
    ~ src/app/main.ts
    ~ config/production/api-keys.env   🔒 protected

  1 active agent session(s):
    ⚡ cap_238545309b986bfda27a30da57bafafc  reviewer  model anthropic:claude-opus-4-8 · branches agent/reviewer/** · expires in ~1h

The 🔒 marks a policy-protected file; the ⚡ marks an active agent session, with its token id, scope, and expiry. (Under TOVIO_ASCII those degrade to (locked) and [agent].) tovio status is the single place repository state surfaces, so protection, conflicts, and expiring agent tokens all appear together. It reports that a path is protected — run tovio access check for the policy expression and the verdict.

When a command says an identity cannot read something

Any permission message in TOVIO points you straight here. Run tovio access check <path> --identity <file> and you get the named missing attributes — never a dead end. After a grant, re-run the check to confirm it took effect.

What this is not

tovio access check evaluates policy satisfaction offline — it tells you whether an identity's attributes meet the expression. It does not, by itself, fetch a content key or prove the relay will accept a write; those happen at read and push time. And it is not a substitute for actually attempting the read: the authoritative answer to "can this identity open the file" is whether a wrapped key for them exists on the object.

Next steps

Last reviewed September 9, 2026

Suggest an improvement to this page Not for security reports — see disclosure