pub struct SecretsState {
pub nodes: HashMap<String, NodeIdentity>,
pub wrapped_dek: Option<WrappedDek>,
pub secrets: HashMap<String, ReplicatedSecret>,
pub revoked_tokens: HashMap<String, DateTime<Utc>>,
pub trusted_bundles: HashMap<String, TrustBundle>,
pub jwt_algorithm: JwtAlgorithm,
pub join_secret_wiped_at: Option<DateTime<Utc>>,
}Expand description
Snapshot of the cluster secrets state on this node.
Followers and the leader hold identical content. Snapshots (de)serialize through serde for openraft.
Fields§
§nodes: HashMap<String, NodeIdentity>Every node ever registered, keyed by node_id. Soft-revocation
is recorded inline (NodeIdentity::revoked_at); the entry is
kept so historical wraps in old WrappedDek generations can still
be referenced for audit.
wrapped_dek: Option<WrappedDek>Current cluster DEK envelope (per-node sealed-box wraps + generation).
None until the first RegisterNode + RotateDek pair lands.
secrets: HashMap<String, ReplicatedSecret>Replicated secrets, keyed by their storage_key ("{scope}:{name}").
revoked_tokens: HashMap<String, DateTime<Utc>>Revoked join tokens, keyed by token_hash (lowercase hex SHA-256
of the full token b64 envelope). Auto-pruned during apply: any
RevokeToken op also sweeps entries whose expires_at < now().
trusted_bundles: HashMap<String, TrustBundle>Trusted foreign-cluster trust bundles, keyed by cluster_domain.
Imported via SecretsRaftOp::ImportTrustBundle and consulted
by crate::cluster_signer::ClusterCa::verify_ca_cert when a
v=2 signed token carries a ca_chain whose cluster_domain
is not the local cluster’s.
#[serde(default)] so snapshots written before this field
existed restore with an empty map.
jwt_algorithm: JwtAlgorithmCluster-wide JWT algorithm policy. Drives which join-token
formats cluster_join accepts. Default Both for safety —
the daemon’s bootstrap may override based on whether
{data_dir}/join_secret is already present on first start.
#[serde(default)] so pre-Wave-11 snapshots restore cleanly.
join_secret_wiped_at: Option<DateTime<Utc>>Timestamp when WipeJoinSecret last applied (None = never).
Two daemon mechanisms consult this field:
- The apply-time wrapper in
zlayer_scheduler::raft::ClusterStatefiresNodeSideEffects::fire_wipe_join_secret, which the daemon’s watcher task drains to delete{data_dir}/join_secret. - The boot-time reconcile in
zlayer servechecks this field on startup; ifSome(_)and the file still exists locally (e.g. the node restored from a snapshot where the wipe already happened), the file is removed before the HS256 HMAC loader runs.
Both paths are idempotent.
#[serde(default)] for pre-Wave-11 snapshots.
Implementations§
Source§impl SecretsState
impl SecretsState
Sourcepub fn apply(&mut self, op: SecretsRaftOp) -> Result<(), SecretsError>
pub fn apply(&mut self, op: SecretsRaftOp) -> Result<(), SecretsError>
Apply a Raft op to local state.
Deterministic — every replica that sees the same op sequence must
end up with the same SecretsState. Returns an error only on
genuinely impossible inputs (e.g. DeleteSecret for an unknown
key); the leader’s orchestration is expected to ensure the inputs
are well-formed before proposing.
§Errors
SecretsError::Providerif the op references state that doesn’t exist (revoke unknown node, delete unknown secret).
Sourcepub fn snapshot(&self) -> Result<Vec<u8>, SecretsError>
pub fn snapshot(&self) -> Result<Vec<u8>, SecretsError>
Serialize the state for an openraft snapshot. Uses JSON for now; the consensus wire-up task may swap this for a more compact codec once it audits whatever the scheduler SM uses.
§Errors
SecretsError::Storageif serialization fails.
Sourcepub fn restore(bytes: &[u8]) -> Result<Self, SecretsError>
pub fn restore(bytes: &[u8]) -> Result<Self, SecretsError>
Restore from a snapshot blob produced by Self::snapshot.
§Errors
SecretsError::Storageif deserialization fails.
Sourcepub fn node_can_decrypt(&self, node_id: &str) -> bool
pub fn node_can_decrypt(&self, node_id: &str) -> bool
Convenience: is this node currently in the active recipient set for the current DEK generation?
Sourcepub fn token_revoked(&self, token_hash: &str) -> bool
pub fn token_revoked(&self, token_hash: &str) -> bool
Returns true if the given token hash is currently revoked.
Auto-pruning happens at apply time; callers can rely on the in-memory map being a tight view of un-expired revocations.
Sourcepub fn trust_bundle_for(&self, cluster_domain: &str) -> Option<&TrustBundle>
pub fn trust_bundle_for(&self, cluster_domain: &str) -> Option<&TrustBundle>
Look up a trusted foreign cluster’s bundle by domain.
Sourcepub fn jwt_algorithm(&self) -> JwtAlgorithm
pub fn jwt_algorithm(&self) -> JwtAlgorithm
Return the current JWT algorithm policy.
Sourcepub fn join_secret_wiped(&self) -> bool
pub fn join_secret_wiped(&self) -> bool
true if WipeJoinSecret has been applied at least once.
Trait Implementations§
Source§impl Clone for SecretsState
impl Clone for SecretsState
Source§fn clone(&self) -> SecretsState
fn clone(&self) -> SecretsState
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for SecretsState
impl Debug for SecretsState
Source§impl Default for SecretsState
impl Default for SecretsState
Source§fn default() -> SecretsState
fn default() -> SecretsState
Source§impl<'de> Deserialize<'de> for SecretsState
impl<'de> Deserialize<'de> for SecretsState
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for SecretsState
impl RefUnwindSafe for SecretsState
impl Send for SecretsState
impl Sync for SecretsState
impl Unpin for SecretsState
impl UnsafeUnpin for SecretsState
impl UnwindSafe for SecretsState
Blanket Implementations§
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> FromBase64 for Twhere
T: for<'de> Deserialize<'de>,
impl<T> FromBase64 for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more