Protect a lane and configure the landing gate¶
This guide shows how to make a shared lane — main, a release line — refuse anything that would
break it. A protected lane declaring a review requirement becomes Forge-advanced only: the ref
moves solely through an approved proposal the Forge itself lands, so the gate can't be slipped past by
pushing directly.
Built and tested; release evidence remains open
The Forge collaboration server (proposals, review, lane protection, connection ACL, authenticated
REST, locking, webhooks) is built and passes its hermetic --features tls test suite. Production
binaries passed the distinct-Docker-host exercise under a real operator CA; public-release,
broader HA/load, hosted-parity, and external evidence remain Phase 5 gates.
flowchart LR
L["tovio land --into main"] --> G{"gate:<br/>conflict-free +<br/>required_checks +<br/>min_approvals +<br/>cleared reviewer +<br/>write_policy"}
G -- pass --> OK([✓ landed])
G -- block --> X[["✗ structured reason + next step"]]
More diagrams for the full team collaboration flow: Team workflows.
What a protected lane guarantees¶
A protected lane is one your repository declares as required to stay conflict-free — always
buildable — optionally with extra landing requirements. The conflict-free and check levers are applied
by the client at land; the review requirement is stronger still. A lane that declares one advances
only through the Forge's own land of an approved proposal — the ref authority refuses every wire
register for such a lane, on push and on any later convergent pull, regardless of the register's
clock. You can't route around it by pushing.
Sensible default
Protect main on a team repository. A solo repo has no protected lanes unless you declare one.
Declare protection¶
Lane protection lives in the repository's policy manifest as a set of protected-lane declarations. You
author them with tovio policy protect <pattern>:
$ tovio policy protect "main" --require-review --min-approvals 2 --required-checks build-check
$ tovio policy protect "release/**" --reviewers "role=release-manager"
$ tovio policy protect "main" --remove
Each declaration carries a lane-name glob plus its levers:
require_conflict_free(defaults totruewhen a protection is authored) — a change whose tree still has unresolved conflict objects cannot advance the lane. Conflicts may exist in changes in flight; they may never land here.required_checks(--required-checks, comma-separated or repeatable) — named checks that must be passing before a land is accepted, the equivalent of a required status check.require_review(--require-review, implied by--min-approvals/--reviewers/--reviewer) — the lane becomes Forge-advanced only, and lands need an approved proposal that clears the reviewer requirement below.write_policy— restricts landing onto the lane to identities whose write proof satisfies it. Omit it and the effective path write policy applies. It is a manifest field with nopolicy protectflag of its own today.
Protection can't be quietly removed
Changing protection is a write to the policy manifest, gated by the manifest's own write policy. Nobody can silently drop protection to slip a conflicted change in, then restore it.
The semantic-check gate has no CLI flag yet
A protection can also declare semantic_check = required, which refuses a land that introduces a
semantic conflict or a breaking interface change (TVO-SEM-004) instead of leaving the
semantic layer advisory. It is a manifest field, not a name you put in
required_checks, and tovio policy protect always writes it as absent — so today it can only be
set by the tooling that builds the manifest.
Who counts as an approver¶
The review requirement carries two repo-authoritative tunables, and the Forge derives both from the served manifest at land time — never from a field in the request body, so a proposer can't relax their own gate:
min_approvals(--min-approvals, default1;0is refused) — how many distinct eligible approvals a land needs. The author is excluded from the count: you cannot approve yourself through the gate.required_reviewers(--reviewersfor a policy expression,--reviewerfor a named approver DID, repeatable) — who is eligible at all. A policy expression is matched against the approver's Key-Authority claims; named DIDs are a roster in the style of a code-owners file. Declare neither and any repository reader is eligible.
Path-scoped change control¶
Lane protection triggers on the lane name. Its sibling triggers on the changed-path set: a change-control rule requires an approved proposal for any change touching a path glob, on any served lane — so a sensitive file is guarded no matter which lane it moves through.
$ tovio policy change-control "crates/**/crypto*" --reviewers "role=security" --min-approvals 2
$ tovio policy change-control "SECURITY.md" --reviewer did:key:z6Mk… --required-checks build-check
$ tovio policy change-control "SECURITY.md" --remove
A direct land or push of a change touching a controlled path is refused at the Forge edge and routed to
a proposal (TVO-FORGE-080). Unlike read policy — where the most specific declaration wins — change-control
rules accumulate: a change touching several controlled paths must satisfy every rule it matched.
The landing gate in action¶
When all the gate's conditions are met, the change lands and rebases its descendants so a stack stays intact — Change IDs preserved throughout.
When a condition isn't met, landing is refused with a clear reason, not a fatal:. The most common is
an unresolved conflict:
$ tovio land my-lane --into main
✗ Cannot land: 1 unresolved conflict(s)
`main` requires conflict-free landings, and this change still carries an open conflict.
See where the branch stands:
tovio health
List the conflicts:
tovio status --conflicts
[TVO-CONFLICT-003]
The gate composes. A protected lane with a review requirement and required checks refuses until all of: the change is conflict-free, every required check is passing, the proposal has enough distinct eligible approvals (author excluded), and — for protected paths — an approving reviewer can actually read them. Each gate is evaluated independently and each blocks on its own.
Cleared-reviewer coverage for protected paths¶
Although the Forge object store holds ciphertext for protected payloads, it can evaluate bounded policy metadata to compute who could read each changed path from the served manifest and the signed reviewer roster. On a review-requiring lane, every protected path the land would newly introduce must be approved by at least one reviewer who is a recipient of it. That keeps a protected-path change from landing reviewed only by people who never saw its contents.
The coverage is computed entirely server-side, over the proposal's pinned reviewed base and commit, and across the whole base-to-commit diff — so a protected path smuggled in through a stacked ancestor is caught, not just one the reviewed commit's own parent diff shows. The reviewer's own report of what they covered is display only; the gate ignores it.
If a protected path has no cleared approver, the transition is blocked. The message names the offending policy id — never the path plaintext, never the contents:
✗ Landing blocked: a protected path has no reviewer cleared to read it
proposal `prop:42` would advance a require_review lane to a commit that
introduces a path governed by the protected policy `sec`, but none of its
approving reviewers is a recipient of that path (none holds the roster
clearance the policy's read_policy requires). A reviewer who cannot read a
protected path may not approve or land a change that puts it on the lane.
Have a reviewer who IS a recipient of that path approve the proposal, or
grant an existing approver the required clearance: tovio access grant …
Confirm who can read the path: tovio access check …
[TVO-FORGE-011]
Every way of failing to establish coverage blocks: an uncovered path, an unparseable read policy, a
reviewed commit the Forge can't resolve, a manifest or roster that won't load. There is no implicit
"covered". A land also re-checks that the lane hasn't advanced underneath the review (TVO-FORGE-013),
so an approval can't be replayed against a lane that has moved.
How this connects to the rest of review¶
Lane protection is the gate; propose and review is how a change earns its
way through it. The proposal lifecycle (approve, request-changes, re-open on amend) and the redacted
review of protected files both feed the coverage check described here.
Recap¶
tovio policy protect <lane-glob>declares protection; protectmainon a team repo.- Levers:
require_conflict_free,required_checks,require_review,write_policy. - A review-requiring lane is Forge-advanced only — a direct push can't advance it at all.
- Reviewer counts and rosters are read from the served manifest, and the author is excluded from the approval count.
tovio policy change-control <path-glob>guards a path on any lane, and those rules accumulate.- Protected paths need an approver cleared to read them; the block names the policy id, never the path plaintext or its contents.
Where to next¶
- Gating the edge rather than the target: lane workflows declares which
(source → target)transitions are legal at all — the rule "a feature lane may not land ontomain", which protection cannot express because it is a fact about the pair, not aboutmain. - The review side of the gate: propose and review.
- CI checks that feed
required_checks: see the migration & CI/CD guides. - Issuing scoped tokens to CI runners and agents: the agents guides.
Last reviewed September 9, 2026
Suggest an improvement to this page Not for security reports — see disclosure