Problem
Throughout crate/server/src/, 48+ call sites manually dispatch on a raw uid_or_tags: &str string using repeated ad-hoc patterns:
// Tag detection
let is_tag_query = uid_or_tags.starts_with('[');
// HSM detection (two variants)
if has_prefix(uid_or_tags).is_some() { … }
if uid_or_tags.starts_with("hsm::") { … }
// Otherwise: plain object UID
This leads to:
- Duplicated parsing logic across 48+ sites
- Easy-to-miss branches (e.g.
starts_with("hsm::") vs has_prefix() which also handles multi-segment prefixes)
- Stringly-typed APIs that cannot leverage the compiler for exhaustiveness checks
- Fragile manual
split_once("::") parsing of HSM UID components
Proposed solution
Define a typed enum in crate/server/src/core/uid_utils.rs:
pub(crate) enum ObjectHandle<'a> {
/// JSON tag array: `["tag1", "tag2"]`
Tags(Vec<&'a str>),
/// HSM-managed key: prefix (e.g. "hsm::softhsm2"), slot, key_id
Hsm { prefix: &'a str, slot: usize, key_id: &'a str },
/// Plain object UID (UUID or user-named)
Uid(&'a str),
}
impl<'a> ObjectHandle<'a> {
pub fn parse(s: &'a str) -> KResult<Self> { … }
}
Then refactor core functions to accept or produce ObjectHandle:
retrieve_object_for_operation
retrieve_eligible_keys
uids_from_unique_identifier
High-value refactor targets (inline branching → match arms)
| File |
Current pattern |
uid_utils.rs (L44–56, L110, L262) |
starts_with('[') + has_prefix() + starts_with("hsm::") |
rekey/common.rs (L130–134) |
let is_tag_query = uid_or_tags.starts_with('[') |
rekey/symmetric.rs (L42–53, L223–242) |
has_prefix(uid_or_tags).is_some() → HSM early return |
rekey/keypair.rs (L153–172) |
uid_or_tags.starts_with("hsm::") → error |
destroy.rs (L27–54) |
uids_from_unique_identifier() then per-UID has_prefix() |
revoke.rs (L28–99) |
Same as destroy |
wrapping/wrap.rs (L49–76) |
has_prefix(&uid_str).is_some() → oracle routing |
wrapping/unwrap.rs (L59) |
Same |
key_ops/crypto_op.rs (L344, L402, L528) |
3× has_prefix() + uids_from_unique_identifier() |
permissions.rs (L78, L231) |
has_prefix() for permission bypass |
locate.rs (L116) |
Per-result has_prefix() filtering |
attributes/set.rs (L83) |
has_prefix(owm.id()).is_some() post-retrieve |
retrieve_object_utils.rs (L283, L309) |
2× has_prefix(id).is_some() |
Benefits
- Compiler-enforced exhaustiveness on all UID dispatch sites
- Single canonical parser — no more subtle mismatches between
has_prefix() and starts_with("hsm::")
- Structured HSM UID components (prefix, slot, key_id) available without re-parsing
- Clearer function signatures:
fn foo(handle: ObjectHandle) vs fn foo(uid_or_tags: &str)
- Easier to add new handle variants in the future (e.g. keyset references like
name@latest)
Scope
~30 files touched. Should be a dedicated refactoring PR, not bundled with feature work.
Non-goals
- Does not change the database layer (
ObjectsStore trait) — only the server-side dispatch before DB calls.
- Does not change KMIP wire format — parsing happens after
UniqueIdentifier::as_str() extraction.
Problem
Throughout
crate/server/src/, 48+ call sites manually dispatch on a rawuid_or_tags: &strstring using repeated ad-hoc patterns:This leads to:
starts_with("hsm::")vshas_prefix()which also handles multi-segment prefixes)split_once("::")parsing of HSM UID componentsProposed solution
Define a typed enum in
crate/server/src/core/uid_utils.rs:Then refactor core functions to accept or produce
ObjectHandle:retrieve_object_for_operationretrieve_eligible_keysuids_from_unique_identifierHigh-value refactor targets (inline branching →
matcharms)uid_utils.rs(L44–56, L110, L262)starts_with('[') + has_prefix() + starts_with("hsm::")rekey/common.rs(L130–134)let is_tag_query = uid_or_tags.starts_with('[')rekey/symmetric.rs(L42–53, L223–242)has_prefix(uid_or_tags).is_some()→ HSM early returnrekey/keypair.rs(L153–172)uid_or_tags.starts_with("hsm::")→ errordestroy.rs(L27–54)uids_from_unique_identifier()then per-UIDhas_prefix()revoke.rs(L28–99)wrapping/wrap.rs(L49–76)has_prefix(&uid_str).is_some()→ oracle routingwrapping/unwrap.rs(L59)key_ops/crypto_op.rs(L344, L402, L528)has_prefix()+uids_from_unique_identifier()permissions.rs(L78, L231)has_prefix()for permission bypasslocate.rs(L116)has_prefix()filteringattributes/set.rs(L83)has_prefix(owm.id()).is_some()post-retrieveretrieve_object_utils.rs(L283, L309)has_prefix(id).is_some()Benefits
has_prefix()andstarts_with("hsm::")fn foo(handle: ObjectHandle)vsfn foo(uid_or_tags: &str)name@latest)Scope
~30 files touched. Should be a dedicated refactoring PR, not bundled with feature work.
Non-goals
ObjectsStoretrait) — only the server-side dispatch before DB calls.UniqueIdentifier::as_str()extraction.