vgi_forge_github/lib.rs
1//! GitHub adapter for VGI git namespaces.
2//!
3//! Implements [`vgi_forge::Forge`] for github.com and GitHub Enterprise
4//! Server, acting as **one community's own GitHub App** (§5.7 of the design:
5//! no shared operator, one App and one bridge per community).
6//!
7//! - **Auth.** The App key signs a nine-minute RS256 JWT
8//! ([`jwt::app_jwt`]) through an [`AppKeySigner`] — in-process
9//! ([`InProcessKey`]) or an enclave. Every operation then mints its own
10//! installation token, scoped to the one repository and the permissions
11//! that operation needs, and drops it on return. Nothing long-lived is
12//! cached.
13//! - **Registration.** [`manifest`] builds the App manifest with the fixed,
14//! reviewed permission set and exchanges GitHub's code for the App's
15//! credentials ([`manifest::AppCredentials`], zeroized, never printed).
16//! - **Binding.** [`vgi_forge::Forge::begin_bind`] sends the admin to the
17//! App's install page with a `state` nonce; `complete_bind` checks it in
18//! constant time and confirms the installation is this App's, on the
19//! expected owner.
20//! - **Accounts.** Members link through the OAuth device flow; the bridge
21//! keeps the numeric id and login and discards the user token.
22//! - **Repos.** Create (organisations only — a personal account reports
23//! `bot_can_create_repos: false`, §8), inspect, archive, converge roles,
24//! and the §5.3 bootstrap with a ruleset that has no bypass actors. So that
25//! a pull request cannot satisfy its own check (§9), an organisation with
26//! org rulesets runs verify-trust as a **required workflow** from the
27//! bridge-managed `<org>/.vgi` at a pinned commit; elsewhere the workflow
28//! is committed to the repository and, with two or more owners, guarded
29//! by `CODEOWNERS` plus code-owner review; a solo repository gets the
30//! check alone ([`plan::CheckGuard`]).
31//! - **Webhooks.** `X-Hub-Signature-256` verified in constant time before
32//! parsing; repository, member, membership, ruleset and installation
33//! events become [`vgi_forge::ForgeEvent`]s.
34//! - **Bridge-posted checks.** With [`GitHubConfig::bridge_checks`], a
35//! namespace without an org required workflow gets no workflow at all:
36//! the bridge runs verify-trust on each pull request and posts the check
37//! as the App ([`checks`]), and the ruleset requires it from the App's own
38//! integration id, which no workflow can post as (§9).
39//! - **Pull-request gate.** `pull_request` `opened` / `reopened` become
40//! [`vgi_forge::ForgeEventKind::PullRequestOpened`] (who and where, never
41//! what), and the four [`vgi_forge::Forge`] pull-request calls read a pull
42//! request, find the App's own comment, comment and close, for the
43//! bridge's `closePullRequest` job (needs `pull_requests: write`).
44//! - **Dependabot re-sign.** `push` deliveries (who moved which branch) and
45//! a per-repository push token, for the bridge to re-sign Dependabot pull
46//! requests with its own DID on signed provenance ([`resign`]).
47//!
48//! The HTTP layer is a thin reqwest client ([`api`]) rather than octocrab:
49//! see the crate README for why.
50
51mod api;
52pub mod checks;
53mod config;
54mod forge;
55pub mod jwt;
56pub mod manifest;
57pub mod plan;
58mod pulls;
59pub mod resign;
60mod secret;
61pub mod webhook;
62
63pub use api::API_VERSION;
64pub use checks::{CheckConclusion, CheckTrigger, CheckTriggerKind, Comparison, PullRequestInfo};
65pub use config::{DEFAULT_CHECKOUT_ACTION, GitHubConfig, JwtIssuer};
66pub use forge::{GitHubForge, RequiredWorkflowPin, ruleset_body, ruleset_satisfies};
67pub use jwt::{AppKeySigner, InProcessKey};
68pub use resign::PushEvent;
69pub use secret::Secret;