docs

  zegit · proves

ZEGITFILE & config

Two files govern a repo: the ZEGITFILE (the governance contract) and .zegit/config.yaml (the validation pipeline). Both are written by zg init and are the source of the policy digest.

Documented from the implementation

Design documents describe a richer schema (roles, permissions, critical areas). This page documents the schema that zg init actually writes and zg and the gateway actually parse today.

ZEGITFILE

The governance contract: a tag_request block that controls release quorum, and an optional validation block that pins the validation pipeline. The shape below is modelled on zegit's own ZEGITFILE (which pins fourteen steps):

ZEGITFILEyaml
# ZEGITFILE — ZeGit Governance Contract
tag_request:
  # Minimum number of distinct approvals before a tag can be created.
  threshold: 1
  # Roles permitted to approve a Tag Request.
  approver_roles:
    - owner
    - maintainer
  # When true, the AoV signed by the TR creator counts as one approval,
  # enabling a solo-maintainer flow without a second identity. Default: false.
  allow_aov_self_approval: false
  # Tags governed by a Tag Request (globs, default ["v*"]). In git mode,
  # `git tag <name>` opens a TR when the name matches; other tags are plain git.
  release_tags:
    - "v*"

# Validation scope — generated by `zg policy scope`. Once the policy is
# activated, the gateway rejects an AoV that did not run exactly this
# .zegit/config.yaml with every listed step required and passed.
validation:
  config_digest: sha256:<hex digest of .zegit/config.yaml>
  required_steps:
    - fmt
    - lint
    - test
    - build
KeyTypeMeaning
tag_request.thresholdintDistinct approvals needed to finalize a tag.
tag_request.approver_roles[]stringRoles allowed to approve — owner, maintainer, developer.
tag_request.allow_aov_self_approvalboolLet the creator's own AoV count as one quorum vote (default false; zg init --solo writes true).
tag_request.release_tags[]globWhich tag names are release tags for the git-mode tag ceremony (default ["v*"]; ["*"] governs every tag).
validation.config_digeststringsha256 of the sanctioned .zegit/config.yaml. An AoV whose policy digest does not match is rejected on protected refs (ZG_ERR_AOV_SCOPE_MISMATCH).
validation.required_steps[]stringStep ids every attestation must carry as required-and-passed (ZG_ERR_AOV_STEP_MISSING otherwise).

Without a validation block the pin is advisory

zg validate prints a recommendation until the scope is pinned — a pipeline narrowed to fmt would still produce a valid ALLOW. Changing the pipeline afterwards is a policy change: re-run zg policy scope, commit, zg policy propose, owner approval.

The activated policy: refs/zegit/policy

The ZEGITFILE in the tree is the proposal source. What the gateway enforces is the policy activated at refs/zegit/policy — a signed statement carrying the same fields, proposed with zg policy propose, approved by owners, and activated once the owner quorum holds (two distinct owners; the first activation needs one). A repository with no activated policy refuses tag pushes. Organizations can additionally activate a baseline (zg policy propose --org): a floor on threshold, approver roles and self-approval that every repository may tighten but never loosen. A baseline never carries a validation scope — that pin is per repository.

.zegit/config.yaml

The validation pipeline that zg validate runs. Steps run in order; a required step exiting non-zero blocks the AoV.

.zegit/config.yamlyaml
version: 1
validate:
  - id: lint
    run: |
      gofmt -l . | grep . && exit 1 || exit 0
    required: true
  - id: test
    run: go test ./...
    required: true
KeyTypeMeaning
versionintSchema version — must be 1.
validate[].idstringStep identifier (required).
validate[].runstringShell to run (bash -c), required.
validate[].requiredboolWhether a non-zero exit blocks. Defaults to true when omitted.

The policy digest

Every AoV records a policy_ref.digest of the form sha256:<hex>, computed over the bytes of .zegit/config.yaml concatenated with ZEGITFILE (when present). An AoV without it is rejected on protected refs (ZG_ERR_AOV_MISSING_POLICY_DIGEST), and when the active policy pins a validation scope the gateway compares the digest against the committed files — which is how "policy cannot be weakened" becomes a cryptographic property rather than a process promise. Change either file and the digest changes, so a stale or hand-edited policy no longer matches.

Keep both files in version control. They are your governance — reviewed like code, and bound into every attestation.

Authoritative reference, generated from the component repos. Spot something stale? Tell us.