vgi-bridge 0.16.0

The per-community VGI bridge: holds the community's forge credentials, takes git-ns/bridge jobs from its VTC over TSP or DIDComm, runs the forge adapters, reports results, events and drift, and posts the commit-trust check where no forge feature can be trusted to.
# VGI bridge configuration — one community, one bridge (design §5.7).
#
# You rarely need to start from this file: `vgi-bridge setup --vtc <VTC DID>
# --vta <VTA DID> --dir <folder> …` writes a complete bridge.toml in VTA mode
# — the registry and mediator read from the VTC's DID document, the
# verify-trust action pinned to its release commit, the web-flow key fetched,
# the VTA credential provisioned — plus a service file (docs/BRIDGE.md §2).
# This file documents every key, for editing that config or writing one by
# hand (docs/BRIDGE.md §8). Use absolute paths; the examples below use a
# folder in the operator's home, /home/ops/vgi-bridge.
#
# Nothing secret belongs in this file: keys, tokens and passwords live in the
# sealed store — or, in VTA mode (the `[vta]` section below), in the bridge's
# trust context of the VTC's VTA (`vgi-bridge secret set …`, the GitHub
# manifest flow). Unknown keys are refused at start-up.

# The one VTC this bridge serves. Jobs signed by any other DID are refused.
vtc_did = "did:webvh:QmVtcScid7:acme-vtc.example"
# The git-ns/bridge/event version sent to that VTC: "0.3" (the default; it
# reports the bridge's role map, BRIDGE.md §6c), or "0.2" / "0.1" until the
# VTC understands 0.3 (BRIDGE.md §7, "Event versions"). Set "0.4" — never by
# default — once the VTC lists git-ns/bridge/event/0.4 in its discovery
# answer: it adds the pull requests opened and reopened, which the VTC's
# pull-request gate decides on (BRIDGE.md §6d). Below 0.4 no pull request
# is reported.
# event_version = "0.3"
# The community's Trust Registry (for the bootstrap and the bridge's check):
# the TrustRegistry service of the VTC's DID document (setup reads it there).
trust_registry_did = "did:webvh:QmRegScid3:registry.acme-vtc.example"
# The mediator the bridge's DID is reachable through (the VTC's), for TSP
# and DIDComm alike: the TSPTransport / DIDCommMessaging service of the VTC's
# DID document (setup reads it there).
# The did:peer `vgi-bridge init` mints names it in the identifier: changing
# it later means minting a new identity and registering it at the VTC.
mediator_did = "did:web:mediator.acme-vtc.example"

# Where the forges reach the bridge, through the TLS proxy in front of it.
public_url = "https://bridge.acme-vtc.example/"
# Plain HTTP behind the proxy or tunnel: only it may reach this. Loopback
# with the proxy on the same host (what setup writes); all interfaces,
# "0.0.0.0:8080" (the built-in default), is right only inside a container
# whose port is published to the proxy alone.
listen = "127.0.0.1:8080"
# The state store (the built-in default, /var/lib/vgi-bridge, is the
# container image's volume).
data_dir = "/home/ops/vgi-bridge/data"

# Self-contained mode (`setup --self-contained`): the master key that seals
# every secret, an owner-only file (`init` creates it). Back it up apart from
# the data directory. Not used (and refused) in VTA mode.
master_key_file = "/home/ops/vgi-bridge/master-key"
# …or an environment variable instead:
# master_key_env = "VGI_BRIDGE_MASTER_KEY"

# VTA mode (recommended; BRIDGE.md §2a): the bridge's DID, keys, secrets and
# state live in its own trust context of the VTC's VTA, and this host holds
# only a context-scoped credential. Losing the host then loses nothing: issue
# a new credential and start the bridge on an empty data directory. Remove
# `master_key_file` / `master_key_env` when you turn it on.
# [vta]
# context = "vgi-bridge"
# # The credential bundle the VTA issued (JSON; owner-only file). setup
# # provisions it into the folder.
# credential_file = "/home/ops/vgi-bridge/vta-credential.json"
# # …or an environment variable (cleared once read):
# # credential_env = "VGI_BRIDGE_VTA_CREDENTIAL"
# # The bridge reaches the VTA over TSP when the VTA advertises it, else
# # DIDComm — never REST (the VTA releases keys only end to end); through
# # this mediator, by default the bridge's own.
# # mediator_did = "did:web:mediator.acme-vtc.example"
# # url = "https://vta.acme-vtc.example"
# # The bridge's DID; default: the context's DID.
# # did = "did:webvh:…"
# # How long start-up waits for an unreachable VTA, and how often the bridge
# # asks it whether its keys were rotated (at least 30; SIGHUP asks at once).
# # start_timeout_secs = 300
# # key_refresh_secs = 60
# # How long a newly listed signing key must be in the DID document before
# # the bridge signs with it (verifiers' cached copies must have it first).
# # signing_switch_after_secs = 86400

# How long a resolved DID document is trusted (the VTC's, the registry's,
# commit signers'), in seconds; a failure is re-checked against a fresh one.
# did_cache_ttl_secs = 60

# Oldest job accepted, in seconds (plus a minute of clock skew).
# max_job_age_secs = 300
# Largest request body read, in bytes.
# max_body_bytes = 2097152
# Drift sweep for forges without webhooks, and the result/event retry.
# drift_sweep_secs = 3600
# resend_secs = 60
# How long a bind or account link waits for the person.
# flow_ttl_secs = 900

[verify_trust]
# What the bootstrap writes into repositories (and the required workflow).
# setup pins this to the commit of its own release tag; by hand:
#   gh api repos/OpenVTC/verifiable-git-infrastructure/commits/<version> --jq .sha
action = "OpenVTC/verifiable-git-infrastructure/.github/actions/verify-trust@<40-hex commit>"
version = "v0.16.0"
# Required by the Forgejo plan: SHA-256 of the release tarball.
# sha256 = "<64 hex>"
# required_check = "Verify commit trust"
# The Trust Registry binding: auto (default; no fallback), tsp, didcomm, or
# https. auto is TSP, then DIDComm, then HTTPS, whichever the registry
# advertises first — for the written workflows and for the check the bridge
# posts itself (which queries as the bridge's own DID, over its mediator
# link). Use "https" while the
# registry's mediator does not admit a CI run's throwaway DID
# (docs/RUNBOOK.md, "Registry discovery") or the bridge's DID.
# transport = "auto"

[checks]
# The check the bridge posts itself (GitHub, outside a required workflow).
# max_commits = 250
# max_signers = 16
# git = "git"
# fetch_timeout_secs = 120
# max_fetch_bytes = 67108864
# concurrency = 4

[resign]
# The Dependabot re-sign (docs/BRIDGE.md §6a): the committer on re-signed
# commits. The signer is the bridge's DID, named in the Signed-by-DID trailer.
# committer_name = "VGI bridge"
# committer_email = "vgi-bridge@noreply.invalid"

# Which forge role each repository right gets (docs/BRIDGE.md §6c). The
# defaults are shown; [github.role_map], [github.namespaces.<owner>.role_map]
# and [github.namespaces.<owner>.repos.<name>.role_map] (and the same under
# [forgejo…]) override them field by field, most specific first. Must stay
# own >= maintain >= commit, with commit at most "write", and only own may be
# "admin" (a map giving maintain or commit "admin" fails the start). There is
# no key for git.ns.admin: a namespace admin never gets a forge role.
[role_map]
# own = "admin"
# maintain = "maintain"     # on Forgejo: write + the merge allow-list
# commit = "none"           # "write" lets committers push branches

# One [[github]] entry per organisation (or account) the community binds:
# GitHub installs a private App only on its owner, so each organisation gets
# its own App — registered with one click each — and this one bridge holds
# them all, keyed by (host, app_owner). Copy the entry for another org with
# its own app_owner and app_name.
[[github]]
host = "github.com"
# The App the manifest flow registers. Unique per GitHub instance: every
# entry names its own.
app_name = "acme-vgi-bridge"
# Required: the org the App is registered under (and owned by). For a
# personal account, name it and set app_owner_is_user = true.
app_owner = "acme"
# app_owner_is_user = false
# Optional: GitHub's web-flow key, the exempt keyring for commits GitHub
# signs (web-UI merges, merge queues). The bridge-posted check works without
# it (such commits then fail); the in-repo and required-workflow plans need it,
# and the Dependabot re-sign checks Dependabot's commits against it (without
# it, nothing is re-signed).
# setup fetches it; by hand:
#   curl -fsSL https://github.com/web-flow.gpg > /home/ops/vgi-bridge/web-flow.asc
platform_keyring_file = "/home/ops/vgi-bridge/web-flow.asc"
# Post the check from the bridge where no org required workflow is
# available (personal accounts, orgs without org rulesets). Leave on.
# bridge_checks = true
# Dependabot's account, as GitHub reports it (GET /users/dependabot[bot]).
# These are github.com's; a GHES instance has its own id.
# dependabot_login = "dependabot[bot]"
# dependabot_id = 49699333
# Re-signing Dependabot pull requests is on for every namespace; turn it off
# for one by its owner's login (lowercase):
# [github.namespaces.acme]
# resign_dependabot = false
# Role-map overrides for one namespace, and for one repository in it:
# [github.namespaces.acme.role_map]
# maintain = "write"
# [github.namespaces.acme.repos.widgets.role_map]
# commit = "write"

# [[forgejo]]
# base_url = "https://codeberg.org/"
# bot_login = "acme-vgi-bot"
# oauth_client_id = "<the bridge's OAuth2 application on the instance>"
# rotate_token_days = 30
# instance_signing_key_fallback = false
# The runner label the bootstrap's workflow asks for (runs-on:). Default
# "docker"; the job image needs glibc 2.39+.
# runs_on = "docker"
# Maintainers as plain write on this instance, without the merge allow-list:
# [forgejo.role_map]
# maintain = "write"