Skip to main content

Module plan

Module plan 

Source
Expand description

GitHub’s bootstrap plan (§5.3) and the files it commits.

The order is load-bearing: files go in first, then the variables, then the protection. The ruleset has no bypass actors — the bridge included — so after it exists every change to the default branch goes through a pull request and the check.

The pull request must not be able to satisfy its own check (§9). A pull_request workflow runs from the pull request’s own files, so the plan takes one of two guards, chosen per namespace (CheckGuard):

  • CheckGuard::RequiredWorkflow (organisations with org rulesets): the check is not committed to the repository at all. It lives in the bridge-managed <org>/.vgi repository and an org ruleset requires it at a pinned commit, so nothing in the pull request changes what runs. The DIDs and the exempt keyring are written into that workflow, not read from the repository under test.

  • Elsewhere (personal accounts, organisations without org rulesets) the workflow is committed to the repository, with the DIDs as literals:

    • CheckGuard::OwnerReview, two or more owners: CODEOWNERS makes every change under .github/ — the workflow, the keyring, CODEOWNERS itself — need another owner’s approving review, which the ruleset requires (dismissed by later pushes, never the last pusher’s own).
    • CheckGuard::SoloOwner, one owner: no review requirement, only the check. The owner could weaken their own workflow; accepted (the user’s decision), since they control the repository anyway.

    In both, repository writers are trusted not to forge a “Verify commit trust” check run from a workflow on another branch; only the required workflow closes that.

  • CheckGuard::BridgePosted (the same namespaces, when the adapter is configured with crate::GitHubConfig::bridge_checks): no workflow at all. The bridge runs verify-trust itself on every pull request and merge group and posts the check as the community’s App; the ruleset requires the check from that App’s integration id, which no workflow can post as. This is what closes the forged-check gap outside a required workflow (§9, decided 2026-09-23).

Enums§

CheckGuard
How the plan keeps the pull request away from its own check (§9).

Constants§

CENTRAL_REPO
The bridge-managed repository in an organisation that holds the required workflow. Public, so the workflow may run on repositories of any visibility (a private source repository’s workflow may run only on private repositories); it holds nothing secret.
CODEOWNERS_LOCATIONS
Every place GitHub looks for a CODEOWNERS file; the first one found is the only one used.
CODEOWNERS_PATH
Where the managed code-owner rules are committed. GitHub reads .github/CODEOWNERS ahead of CODEOWNERS and docs/CODEOWNERS.
GUARDED_PATH
The paths owner review guards: everything a workflow run reads from the repository under test to decide how to check it.
KEYRING_PATH
Where the exempt platform keyring is committed.
MANAGED_BEGIN
First line of the managed block in a CODEOWNERS file.
MANAGED_END
Last line of the managed block.
ORG_RULESET_NAME
Name of the org ruleset that requires the namespace workflow.
RULESET_NAME
Name of the ruleset the adapter manages. Found by name on re-runs.
VAR_REGISTRY
Registry DID variable.
VAR_VTC
VTC DID variable.
WORKFLOW_PATH
Where the workflow is committed (in the repository, or in .vgi).

Functions§

github_plan
Build the plan. Validates everything that ends up in a file or a variable, so a bad config fails here rather than half-way through.
managed_rules
The managed block of a CODEOWNERS file, if it is there and nothing but comments follows it: (pattern, owners, 1-based line) per rule.
render_codeowners
A CODEOWNERS file: community_rules (the file’s own rules, the managed block removed), then the managed block last, so it wins for paths (the last matching pattern takes precedence). logins are resolved from numeric ids at run time.
render_required_workflow
The required workflow held in <org>/.vgi. It runs in the context of the repository under test (its GITHUB_REPOSITORY, its pull request), but everything that decides how to check is fixed here, at the pinned commit:
render_workflow
The workflow committed to the repository (outside a required-workflow namespace). Differs from the dormant one in the runbook: there is no if: vars.TRUST_REGISTRY_DID != '' guard (a skipped required job counts as passing), and the DIDs are literals rather than vars.*, which any repository admin could change.
strip_managed
text without the managed block (so re-rendering keeps only the community’s own rules).