cosmian/kms/rust-signature-design

Claude Code and agent skill by cosmian/kms

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Classify Rust function parameters and the structs behind them to catch omitted, swapped, or drifting arguments while designing a signature. Use when defining a new function signature, adding or removing a parameter, a parameter list grows past ~4 entries, `clippy::too_many_arguments` fires, or the same parameter group reappears in more than one function.

Install

npx vskill@latest install cosmian/kms/rust-signature-design

SKILL.md

Rust Signature Design

Goal: make invalid or incomplete call states hard to represent — not merely shorten signatures. Companion to the "Refactor" step of the lint-suppression tree in `rust.instructions.md`: apply it instead of adding #[allow(clippy::too_many_arguments)] (forbidden on new code).

Step 1 — Classify every parameter

KindDefinitionKMS exampleTypical home
Entity stateDurable property of a domain objectUniqueIdentifier, Algorithm, object StateField on the entity/request struct
Operation stateExists only for one callcascade, compromise_occurrence_date, ids_to_skip in recursively_revoke_key (crate/server/src/core/operations/revoke.rs:80-89)Operation input struct, built per call
Environmental dependencyService/collaborator needed to actkms: &KMS, user: &UserId — in nearly every core/operations/*.rs handlerKeep explicit unless ≥3 collaborators travel together into a new struct — see Step 3.5
Derived valueCheaply computable from another argumentrevoked_state, computed from revocation_reason by revocation_target_state() (revoke.rs:381)Compute inside the function; never accept both the source and its derivative
Control parameterChanges behaviordisable_unwrapped_cache: bool, clear_db_on_start: bool (crate/server_database/src/core/mod.rs:118-126)Named enum once ≥2 control bools form one configuration

Step 2 — Match against defect patterns

bash
# Functions already fighting the lint — primary candidates
rg -n '#\[(allow|expect)\(clippy::too_many_arguments' --type rust <path>
# Same parameter pair/triple repeated verbatim across signatures
rg -n '^\s*kms: &KMS,$' -A1 --type rust <path> | rg -B1 'user: &UserId'
# Caller destructures a struct only to forward the fields individually
rg -n '\b(\w+)\.\w+,\s*&?\1\.\w+' --type rust <path>
PatternSignalFix
Repeated parameter clusterSame 2+ param names/types travel together across signaturesGroup into an existing or new struct (Step 3)
Field extraction then forwardingcallee(&req.a, &req.b, &req.c) right after destructuring reqPass &req or a narrow borrowed view
Argument omissionA multi-layer call chain drops a value an inner callee needs, forcing a re-derived or wrong default downstreamThread the owning struct through every layer instead of re-adding a discrete parameter at each layer
Argument swapping≥2 adjacent same-typed params (&str, &str, &str)Newtype each (rust-patterns Pattern 1) or a struct
Inconsistent reconstructionSame Struct { a: x.a.clone(), b: x.b, .. } literal appears at ≥2 call sitesMove behind a constructor / From impl on the owning type
Signature driftSibling functions (encrypt/decrypt, wrap/unwrap) carry non-identical param sets for the same conceptConfirm intentional; otherwise align via a shared context struct
Semantically-required Option<T>A field is Option only because some callers can't supply it, though the operation is unsound without itFallible constructor, or a distinct validated-state struct — not a permanent Option
Primitive-heavy signature≥2 bool/u8 control paramsEnum or policy struct
Struct exists but incompleteA domain struct and fields that belong to it are passed separately beside itAdd the field only if its lifecycle/invariants match the struct
Overloaded contextA large Context/Request is threaded everywhere though each callee touches 1–2 fieldsNarrow borrowed view or small dedicated struct, not a bigger bag

Step 3 — Pick the narrowest fix that applies

Try in order; stop at the first that fits:

  1. Reuse the existing request/entity struct — pass &Request instead of its fields. KMIP request types live in

crate/kmip/src/kmip_2_1/kmip_operations.rs and must match the KMIP 2.1 spec (`rust-kmip.instructions.md`) — never add internal-only state to a wire type.

  1. Add a field to an existing struct — only when the new field shares the struct's lifetime, invariants, and construction path.
  2. Narrow borrowed view — struct FooView<'a> { id: &'a KeyId, algorithm: Algorithm }, built via a .view()/.context() method, when the full struct is too broad or ownership shouldn't transfer.
  3. Operation input struct — group values that exist for one call only, e.g. struct RevokeInput { cascade: bool, ids_to_skip: HashSet<String> }, separate from durable entity state.
  4. Extend an existing collaborator — the service layer is KMS (crate/server/src/core/...) plus the ObjectsDb / PermissionsDb / Hsm traits (rust-patterns Pattern 4). Add a method there; never wrap KMS in a second service type.
  5. Keep explicit parameters — values are independent, used by one small function, or bundling would hide a dependency.

Precedent (crate/server_database/src/core/mod.rs:117): Database::instantiate keeps 9 explicit params behind a legacy #[allow(clippy::too_many_arguments)]. Do not copy it: on new code introduce a parameter struct (this skill's remedy) instead of adding the #[allow].

Before / after (illustrative)

rust
// Before — req.tenant_id exists but the middle layer doesn't forward it.
fn outer(req: &Request) -> KResult<()> {
inner(&req.key_id, &req.payload) // tenant_id silently dropped
}
fn inner(key_id: &KeyId, payload: &[u8]) -> KResult<()> { /* needs tenant_id too */ }
// After — the struct carries tenant_id through every layer; nothing to omit.
fn outer(req: &Request) -> KResult<()> {
inner(req)
}
fn inner(req: &Request) -> KResult<()> { /* req.tenant_id always present */ }

Do not

  • Invent a generic Params/Context/Data struct with no domain meaning just to cut a parameter count.
  • Add a field to a crate/kmip wire struct for internal bookkeeping — KMIP structs are spec-bound.
  • Turn a required value into Option<T> to avoid updating a constructor.
  • Mass-refactor the kms/user pair across core/operations/*.rs into a new wrapper struct — that spread is already deliberate (Step 3.5); only touch it where a concrete defect (Step 2) drives the change.
  • Add #[allow(clippy::too_many_arguments)] / #[expect] on new code — forbidden per rust.instructions.md.

Security

  • Security scanPassed, 98 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
363
Repository forks
41
7-day trend score
0

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/cosmian/kms/rust-signature-design/badge)](https://verified-skill.com/skills/cosmian/kms/rust-signature-design)

Something wrong with this skill or its page? Tell us.