vgi_forge_forgejo/lib.rs
1//! Forgejo adapter for VGI git namespaces.
2//!
3//! Implements [`vgi_forge::Forge`] for a Forgejo instance (and Gitea, best
4//! effort), acting as **one community's bot user** on it (§5.9 of the
5//! design). Forgejo has no GitHub-App equivalent, so the differences are
6//! about identity, merges and self-hosting:
7//!
8//! - **Identity.** A dedicated bot user with an access token scoped to
9//! [`BOT_TOKEN_SCOPES`]. It is long-lived, so it is held as a [`Secret`]
10//! (zeroized, never printed), swappable in place, and rotated by the
11//! bridge in two phases ([`ForgejoForge::mint_token`], then
12//! [`ForgejoForge::retire_token`] once the new one is persisted) — which needs the bot's
13//! password, because Forgejo mints tokens only under basic auth. Whether
14//! the bridge holds that password is an explicit choice
15//! ([`TokenRotation`]).
16//! - **Capabilities by probing.** [`ForgejoForge::connect`] reads
17//! `/api/v1/version` and switches off what the instance lacks
18//! (fast-forward-only merges, the Actions variables API) before a plan is
19//! built, rather than failing half-way through one.
20//! - **Binding.** The admin signs in through the bridge's OAuth2 app
21//! (authorisation code + PKCE). The bridge confirms they own the org,
22//! uses that one-time token to put the bot in a `vgi-bridge` team (admin,
23//! "create repositories") and to create the org webhook, then wipes it.
24//! - **Roles.** Owner → `admin` collaborator; maintainer → `write` **and**
25//! the default branch's merge allow-list; committer → nothing (or `write`
26//! by opt-in). Logins are looked up fresh by numeric id before each change.
27//! - **Bootstrap.** Fast-forward-only merges, the workflow at
28//! `.forgejo/workflows/verify-trust.yml` (action by full URL, pinned by
29//! SHA, `version` and `sha256` pinned), the variables, and a branch
30//! protection that lets nobody push, applies to admins, requires the
31//! check's status context, restricts merging to the allow-list, and
32//! protects the workflow paths so no PR can rewrite its own check.
33//! - **Webhooks.** `X-Forgejo-Signature` (or `X-Gitea-Signature`), hex
34//! HMAC-SHA256 of the raw body, checked in constant time before parsing.
35//!
36//! The HTTP layer is a thin reqwest client, like the GitHub adapter's:
37//! redirects off, a configurable base URL, and the credential named on
38//! every request.
39
40mod api;
41mod config;
42mod forge;
43mod oauth;
44pub mod plan;
45mod secret;
46pub mod version;
47pub mod webhook;
48
49pub use config::{
50 Credentials, DEFAULT_ACTIONS_BASE, DEFAULT_CHECKOUT_ACTION, DEFAULT_RUNS_ON, DEFAULT_TEAM,
51 ForgejoConfig, MergeFallback, TokenRotation,
52};
53pub use forge::{
54 BOT_TOKEN_SCOPES, ForgejoForge, MintedToken, RefreshReport, TOKEN_NAME_PREFIX, TokenRef,
55};
56pub use secret::Secret;
57pub use version::{Features, Flavor, InstanceInfo};