pub trait Forge: Send + Sync {
Show 17 methods
// Required methods
fn kind(&self) -> ForgeKind;
fn host(&self) -> &str;
fn capabilities(&self, ns: &Namespace) -> Capabilities;
fn begin_bind<'life0, 'async_trait>(
&'life0 self,
req: BindRequest,
) -> Pin<Box<dyn Future<Output = Result<BindStep>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn complete_bind<'life0, 'async_trait>(
&'life0 self,
cb: BindCallback,
) -> Pin<Box<dyn Future<Output = Result<NamespaceBinding>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn begin_account_link<'life0, 'life1, 'async_trait>(
&'life0 self,
member: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<LinkStep>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn complete_account_link<'life0, 'async_trait>(
&'life0 self,
cb: LinkCallback,
) -> Pin<Box<dyn Future<Output = Result<ForgeAccount>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn inspect<'life0, 'life1, 'async_trait>(
&'life0 self,
repo: &'life1 Resource,
) -> Pin<Box<dyn Future<Output = Result<RepoState>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn create_repo<'life0, 'life1, 'async_trait>(
&'life0 self,
spec: &'life1 RepoSpec,
) -> Pin<Box<dyn Future<Output = Result<RepoState>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn archive_repo<'life0, 'life1, 'async_trait>(
&'life0 self,
repo: &'life1 Resource,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn apply_roles<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
repo: &'life1 Resource,
desired: &'life2 [RoleAssignment],
unlisted: Unlisted,
) -> Pin<Box<dyn Future<Output = Result<ApplyReport>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn bootstrap_plan(
&self,
repo: &RepoSpec,
cfg: &VgiConfig,
) -> Result<Vec<BootstrapStep>>;
fn run_step<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
repo: &'life1 Resource,
step: &'life2 BootstrapStep,
) -> Pin<Box<dyn Future<Output = Result<StepOutcome>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn parse_event(
&self,
headers: &HeaderMap,
body: &[u8],
) -> Result<Option<ForgeEvent>>;
// Provided methods
fn normalize(&self, raw: &str) -> Result<Resource> { ... }
fn map_role(
&self,
ns: &Namespace,
rights: EffectiveRights,
map: &RoleMap,
) -> ForgeRole { ... }
fn diff(&self, observed: &RepoState, desired: &Projection) -> Vec<Drift> { ... }
}Expand description
One forge implementation. Stateless apart from its credentials and the namespaces it has been told about; the core owns all desired state and hands the adapter a plan.
Object-safe (through async-trait) so a bridge can hold one
Box<dyn Forge> per forge host and dispatch on a resource’s host. Methods
with a sensible forge-neutral answer have a default; an adapter overrides
only what its forge does differently.
Required Methods§
Sourcefn host(&self) -> &str
fn host(&self) -> &str
The forge host this adapter serves (github.com, a GHES host,
codeberg.org). Every resource it accepts starts with it; a
resource on another host is refused rather than sent to the wrong
forge.
Sourcefn capabilities(&self, ns: &Namespace) -> Capabilities
fn capabilities(&self, ns: &Namespace) -> Capabilities
What this forge, and this namespace on it, can do. The core and the
UX branch on this, never on Forge::kind.
Sourcefn begin_bind<'life0, 'async_trait>(
&'life0 self,
req: BindRequest,
) -> Pin<Box<dyn Future<Output = Result<BindStep>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn begin_bind<'life0, 'async_trait>(
&'life0 self,
req: BindRequest,
) -> Pin<Box<dyn Future<Output = Result<BindStep>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Start binding a namespace: where to send the admin.
Sourcefn complete_bind<'life0, 'async_trait>(
&'life0 self,
cb: BindCallback,
) -> Pin<Box<dyn Future<Output = Result<NamespaceBinding>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn complete_bind<'life0, 'async_trait>(
&'life0 self,
cb: BindCallback,
) -> Pin<Box<dyn Future<Output = Result<NamespaceBinding>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Finish a bind from the forge’s callback. Validates the state nonce and that the credential landed on the expected owner.
Sourcefn begin_account_link<'life0, 'life1, 'async_trait>(
&'life0 self,
member: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<LinkStep>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn begin_account_link<'life0, 'life1, 'async_trait>(
&'life0 self,
member: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<LinkStep>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Start linking a member’s forge account. member is their DID, for
the adapter’s audit trail; nothing forge-side sees it.
Sourcefn complete_account_link<'life0, 'async_trait>(
&'life0 self,
cb: LinkCallback,
) -> Pin<Box<dyn Future<Output = Result<ForgeAccount>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn complete_account_link<'life0, 'async_trait>(
&'life0 self,
cb: LinkCallback,
) -> Pin<Box<dyn Future<Output = Result<ForgeAccount>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Finish linking: the account’s numeric id and current login.
Sourcefn inspect<'life0, 'life1, 'async_trait>(
&'life0 self,
repo: &'life1 Resource,
) -> Pin<Box<dyn Future<Output = Result<RepoState>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn inspect<'life0, 'life1, 'async_trait>(
&'life0 self,
repo: &'life1 Resource,
) -> Pin<Box<dyn Future<Output = Result<RepoState>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Observe a repository’s current state.
Sourcefn create_repo<'life0, 'life1, 'async_trait>(
&'life0 self,
spec: &'life1 RepoSpec,
) -> Pin<Box<dyn Future<Output = Result<RepoState>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn create_repo<'life0, 'life1, 'async_trait>(
&'life0 self,
spec: &'life1 RepoSpec,
) -> Pin<Box<dyn Future<Output = Result<RepoState>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Create a repository. Refuses one that already exists with
ForgeError::AlreadyExists — adopting it is a separate, elevated
decision (§5.6), not something a retry should do silently.
Sourcefn archive_repo<'life0, 'life1, 'async_trait>(
&'life0 self,
repo: &'life1 Resource,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn archive_repo<'life0, 'life1, 'async_trait>(
&'life0 self,
repo: &'life1 Resource,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Archive a repository. Idempotent.
Sourcefn apply_roles<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
repo: &'life1 Resource,
desired: &'life2 [RoleAssignment],
unlisted: Unlisted,
) -> Pin<Box<dyn Future<Output = Result<ApplyReport>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn apply_roles<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
repo: &'life1 Resource,
desired: &'life2 [RoleAssignment],
unlisted: Unlisted,
) -> Pin<Box<dyn Future<Output = Result<ApplyReport>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Converge people’s direct roles on a repository to desired.
Collaborators desired does not mention are handled per unlisted.
Sourcefn bootstrap_plan(
&self,
repo: &RepoSpec,
cfg: &VgiConfig,
) -> Result<Vec<BootstrapStep>>
fn bootstrap_plan( &self, repo: &RepoSpec, cfg: &VgiConfig, ) -> Result<Vec<BootstrapStep>>
The steps that turn commit trust on for this forge’s CI.
Sourcefn run_step<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
repo: &'life1 Resource,
step: &'life2 BootstrapStep,
) -> Pin<Box<dyn Future<Output = Result<StepOutcome>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn run_step<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
repo: &'life1 Resource,
step: &'life2 BootstrapStep,
) -> Pin<Box<dyn Future<Output = Result<StepOutcome>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Run one step, check-then-apply.
Sourcefn parse_event(
&self,
headers: &HeaderMap,
body: &[u8],
) -> Result<Option<ForgeEvent>>
fn parse_event( &self, headers: &HeaderMap, body: &[u8], ) -> Result<Option<ForgeEvent>>
Verify and translate a webhook. Ok(None) for a verified delivery
the core has no use for; Err for one that failed verification —
which must not be acted on.
Provided Methods§
Sourcefn normalize(&self, raw: &str) -> Result<Resource>
fn normalize(&self, raw: &str) -> Result<Resource>
Canonical form of a forge path. The default applies the
owner[/repo] grammar GitHub and Forgejo share and refuses a
resource on another host.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".