swarm-secret-client: derive Kind's segment strings via strum instead of a hand-written match

This commit is contained in:
damocles 2026-09-11 20:41:52 +02:00
commit 0d6c003fa8
4 changed files with 41 additions and 9 deletions

View file

@ -25,19 +25,28 @@ pub const ROOT: &str = "swarm";
/// misspelled kind is a 403 at provision time rather than anything a compiler
/// sees. [`Kind::ALL`] exists so a test can enumerate the set instead of
/// restating it.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
///
/// The segment string lives once, on the variant itself
/// (`#[strum(serialize = "...")]`), rather than a second time in a
/// hand-written `as_str()` match — [`strum::IntoStaticStr`] derives that
/// conversion, so the attribute is the only place a segment is spelled.
#[derive(Debug, Clone, Copy, PartialEq, Eq, strum::IntoStaticStr)]
pub enum Kind {
/// One agent container's own secrets.
#[strum(serialize = "agents")]
Agent,
/// One hive's secrets, held on behalf of whatever runs there. An identity
/// minted per hive rather than per agent lands here even though an agent
/// is what uses it.
#[strum(serialize = "hives")]
Hive,
/// One swarm service — the things a swarm runs beside the controller.
#[strum(serialize = "services")]
Service,
/// The controller itself. There is one per swarm, so the name segment
/// below it does not vary; the shape stays uniform anyway, because one
/// grant pattern over `<kind>/<name>` is cheaper than a special case.
#[strum(serialize = "controller")]
Controller,
}
@ -47,15 +56,11 @@ impl Kind {
pub const ALL: [Kind; 4] = [Kind::Agent, Kind::Hive, Kind::Service, Kind::Controller];
/// The path segment, which is also what the store's grant is written
/// against.
/// against. Thin wrapper over the derived `Into<&'static str>` so call
/// sites keep the same method-call shape as before.
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Kind::Agent => "agents",
Kind::Hive => "hives",
Kind::Service => "services",
Kind::Controller => "controller",
}
pub fn as_str(self) -> &'static str {
self.into()
}
/// What to call the name in an error — singular, because the message reads