pub trait DeployerCredentials:
Debug
+ Send
+ Sync {
// Required methods
fn required_capabilities(&self) -> Vec<Capability>;
fn validate(&self, ctx: &ValidationContext<'_>) -> RequirementsReport;
fn bootstrap(
&self,
input: &BootstrapInput<'_>,
) -> Result<BootstrapOutcome, BootstrapError>;
// Provided methods
fn requires_credentials_material(&self) -> bool { ... }
fn rollback_bound_material(&self, _env_id: &EnvId) { ... }
fn rotate_at(&self, _material: &str) -> Option<DateTime<Utc>> { ... }
fn rotation_due(&self, material: &str, now: DateTime<Utc>) -> bool { ... }
}Expand description
Contract a deployer env-pack handler implements to surface its
credentials story to the gtc op credentials CLI.
Object-safe so the env-pack registry can return &dyn. Implementations
must be Send + Sync because the registry is shared across the
operator’s request handlers.
Required Methods§
Sourcefn required_capabilities(&self) -> Vec<Capability>
fn required_capabilities(&self) -> Vec<Capability>
The set of capabilities the deployer’s credentials must satisfy.
Order is stable — the CLI renders this as the column order in
gtc op credentials requirements output. Used both as the
declaration of what would be checked (--schema-like surface) and
as the iteration order for validate.
Sourcefn validate(&self, ctx: &ValidationContext<'_>) -> RequirementsReport
fn validate(&self, ctx: &ValidationContext<'_>) -> RequirementsReport
Sourcefn bootstrap(
&self,
input: &BootstrapInput<'_>,
) -> Result<BootstrapOutcome, BootstrapError>
fn bootstrap( &self, input: &BootstrapInput<'_>, ) -> Result<BootstrapOutcome, BootstrapError>
Run the deployer’s bootstrap path against ephemeral admin credentials.
Implementations with no admin escalation (e.g. the local-process
deployer — there are no IAM roles or cluster RBAC to provision
locally) MUST return BootstrapError::NotApplicable with a
message telling the user to run requirements instead. Returning
Ok with an empty outcome would be dishonest (no admin was
actually consumed) and would leave a sentinel credentials_ref
pointing at nothing.
Provided Methods§
Sourcefn requires_credentials_material(&self) -> bool
fn requires_credentials_material(&self) -> bool
Whether this deployer requires real credential material at all.
Deployers that run purely locally (e.g. local-process — no IAM
roles, no cluster RBAC, no cloud credentials) return false.
When false:
validate_requirementsskips theNoCredentialsRefrejection for envs that have nocredentials_ref.bootstrapshould returnBootstrapError::NotApplicable.
Default is true, preserving Phase D AWS/K8s/GCP/Azure behavior.
Sourcefn rollback_bound_material(&self, _env_id: &EnvId)
fn rollback_bound_material(&self, _env_id: &EnvId)
Best-effort compensating cleanup for a bootstrap that wrote durable
credential material to a REMOTE backend (e.g. the K8s --bind path
writes the minted bearer into an in-cluster Secret) but then failed a
later persistence step. Without this a failed bootstrap could leave a
live bearer in the backend while the env stays unbound. The CLI calls it
on the bootstrap error path; the delete is idempotent (a never-written
Secret 404s harmlessly), so an unconditional call is safe.
Default is a no-op — deployers that bind no remote material (the local-process / render-only paths) have nothing to undo. Implementations MUST NOT panic; cleanup failures are swallowed (the caller already has a bootstrap error to report). It does NOT cover a hard process crash between the remote write and the local commit — short-lived bound tokens
- rotation are the systemic mitigation for that residual window.
Sourcefn rotate_at(&self, _material: &str) -> Option<DateTime<Utc>>
fn rotate_at(&self, _material: &str) -> Option<DateTime<Utc>>
The absolute time the given bound credential material should be
rotated, derived from the material’s own self-reported lifetime (e.g.
the K8s projected-ServiceAccount-token JWT’s iat/exp claims).
Returns None when the lifetime can’t be determined.
Default is None: deployers that mint no time-bounded material (the
render-only / local paths, and AWS until its STS producer lands) have
no rotation point to compute. Backends that mint bounded credentials
override this to decode their own material format — the rotation
policy (rotate at 80% of lifetime) stays shared in
[rotate::rotate_at_from_window], only the decode varies.
Sourcefn rotation_due(&self, material: &str, now: DateTime<Utc>) -> bool
fn rotation_due(&self, material: &str, now: DateTime<Utc>) -> bool
Whether the given bound material is at/past its rotation point.
Fails OPEN: material whose lifetime can’t be decoded
(rotate_at returns None) is treated as due, so
op credentials rotate --if-needed errs toward rotating rather than
letting an opaque token silently lapse. The policy lives here; only the
per-backend rotate_at decode is overridden, so impls should not need
to override this.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".