Skip to content

Refactor: introduce ObjectHandle enum to replace ad-hoc UID/tag/HSM string dispatch #1007

Description

@Manuthor

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) 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) 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions