Class KeyMetadata

java.lang.Object
co.ankatech.ankasecure.sdk.model.KeyMetadata

public final class KeyMetadata extends Object
Metadata for a cryptographic key in the ANKASecure platform.

This class provides a complete view of a key's identity, configuration, lifecycle, and usage statistics. It is returned by the read-only key query operations (listKeys / getKeyMetadata).

Key Type Detection:

  • Simple key: kty is "ML-KEM", "ML-DSA", "RSA", "EC", "oct", etc., and compositeMode is null
  • Composite key: kty is the single coarse token "COMPOSITE" for every pairing; alg names the pairing and compositeMode names the construction
  • Composite KEM: compositeMode is COMPOSITE_KEM_COMBINE
  • Composite Signature: compositeMode is COMPOSITE_SIGNATURE
  • Destroyed key (getStatus() is deleted_logical): no shape is reported. kty, alg and compositeMode are all null, so isComposite(), isCompositeKem() and isCompositeSignature() answer false whatever the destroyed key's shape was. Read the status first.

Destroyed keys (Deleted view)

The key list returns destroyed keys only when the status filter is deleted_logical (new KeyFilters(null, null, null, "deleted_logical")); every other listing, and KeyFilters.none(), holds only keys the tenant still has. A destroyed-key row is built from the key identity alone. It carries getKid(), getUuid(), getStatus() (deleted_logical), getCreatedAt() and getDeletedAt(). It reports no key type, algorithm, composite mode, KDF, exportability, origin, restriction, expiry or usage: each of those is null, never a default. getKeyOps() is an empty list on such a row, because the generated client materialises an absent list as an empty one.

A kid can be taken again after its key is destroyed, so a destroyed-key row can share its kid with a live key, and several destroyed-key rows can share one kid. getUuid() is the key's own identity, never reused, and is the member that tells such rows apart.

Usage Examples

Check Key Type


 KeyMetadata metadata = sdk.getKeyMetadata(kid);

 if (metadata.isComposite()) {
     System.out.println("Composite key: " + metadata.getKty());
     if (metadata.isCompositeKem()) {
         System.out.println("KDF used: " + metadata.getKdf());
     }
 } else {
     System.out.println("Simple key: " + metadata.getKty());
 }
 

Check Lifecycle Status


 System.out.println("Status: " + metadata.getStatus());
 System.out.println("Created: " + metadata.getCreatedAt());
 System.out.println("Expires: " + metadata.getExpiresAt());
 System.out.println("Usage: " + metadata.getUsageCount() + " / " + metadata.getMaxUsageLimit());
 

Lifecycle States

The getStatus() field carries the published key-status token. The vocabulary is closed and is exactly the enum the crypto specification publishes for KeySummaryResponse.status — the same token the ?status= filter of the key-list endpoint accepts:

  • active: Key is operational and can be used for cryptographic operations
  • pending_rotation: Rotation is scheduled but has not executed yet
  • rotated: Key material superseded by a newer version under the same kid
  • expired: Key past getExpiresAt() or its usage limit, cannot be used
  • revoked: Key explicitly revoked due to compromise or policy
  • archived: Retained for compliance and audit only, read-only
  • suspended: Temporarily blocked for incident investigation; reversible
  • pending_destruction: In a mandatory cooling-off period before logical deletion; reversible back to archived
  • deleted_logical: Logically deleted and hidden from standard queries

A status token this SDK release does not know is reported as STATUS_UNKNOWN. It names no lifecycle state: treat such a key as not usable, and upgrade the SDK to interpret it.

Thread Safety

Instances are immutable value objects safe to share across threads.

See Also:
  • Field Details

    • STATUS_UNKNOWN

      public static final String STATUS_UNKNOWN
      The getStatus() token for a status the server returned that this SDK release does not know. Upgrade the SDK to interpret it. It is not a published token, so KeyFilters refuses it as a status filter.
      See Also:
  • Constructor Details

  • Method Details

    • getKid

      public String getKid()
      Returns the key identifier (kid) the key is addressed by.

      A kid can be taken again after its key is destroyed, so on a destroyed-key row (deleted_logical) it does not identify the row on its own: use getUuid().

      Server-supplied and unrendered: display it through InertText.text(String).

      Returns:
      key identifier (never null)
    • getUuid

      public String getUuid()
      Returns the key's own identity.

      Assigned when the key is created, kept across every rotation of its kid, and never reused: a kid taken again after its key is destroyed belongs to a key with a new identity. It is the only member that tells apart rows sharing a kid: a live key and the destroyed-key row of a key that once held the same kid, or two destroyed-key rows of a kid reused twice.

      Server-supplied and unrendered: display it through InertText.text(String).

      Returns:
      the key identity as a UUID string; the server states it on every row of the key list and on the key-metadata read
    • getKty

      public String getKty()
      Returns the key type.

      Examples: "ML-KEM", "ML-DSA", "RSA", "EC", "oct", and the single coarse token "COMPOSITE" for every hybrid pairing. A composite key's construction is reported by getCompositeMode() and its exact pairing by getAlg().

      Server-supplied and unrendered: display it through InertText.text(String).

      Returns:
      key type, or null on a destroyed-key row (deleted_logical), which reports no shape
    • getCompositeMode

      public CompositeMode getCompositeMode()
      Returns how a composite key's components are combined.

      Every composite key publishes the coarse key type COMPOSITE, so this value — not getKty() — is what distinguishes a hybrid KEM from a hybrid signature. It is null for a simple key, where that absence means "not composite". It is also null on a destroyed-key row (deleted_logical), where it means "no shape reported", not "simple".

      Returns:
      the composite construction, CompositeMode.UNKNOWN for one this SDK release does not declare, or null for a simple key and for a destroyed-key row
    • getCompositeModeAsString

      public String getCompositeModeAsString()
      Returns the composite construction as the server sent it.

      For a declared construction, its name (COMPOSITE_KEM_COMBINE, COMPOSITE_SIGNATURE). For one a later server added, the server's value verbatim, while getCompositeMode() reads CompositeMode.UNKNOWN.

      Server-supplied and unrendered: display it through InertText.text(String).

      Returns:
      the wire value, or null when the server sent none (a simple key, a destroyed-key row)
    • getAlg

      public String getAlg()
      Returns the algorithm identifier.

      For simple keys: Single algorithm (e.g., "ML-KEM-768", "RSA-4096")
      For composite keys: Combined algorithms (e.g., "X25519+ML-KEM-768", "Ed25519+ML-DSA-44")

      Server-supplied and unrendered: display it through InertText.text(String).

      Returns:
      algorithm identifier, or null on a destroyed-key row (deleted_logical)
    • getKdf

      public String getKdf()
      Returns the key derivation function for composite KEM keys.

      Only present when getCompositeMode() is COMPOSITE_KEM_COMBINE. Common values: "HKDF-SHA256", "HKDF-SHA512"

      Server-supplied and unrendered: display it through InertText.text(String).

      Returns:
      KDF identifier, or null if not a composite KEM key and on a destroyed-key row (deleted_logical)
    • getKeyOps

      public List<String> getKeyOps()
      Returns the permitted key operations.

      Common values: "encrypt", "decrypt", "sign", "verify", "wrapKey", "unwrapKey"

      Server-supplied and unrendered: display each element through InertText.text(String).

      Returns:
      unmodifiable list of operations; an empty list on a destroyed-key row (deleted_logical), which states no operations (the generated client materialises the absent member as an empty list)
    • getExportable

      public Boolean getExportable()
      Returns whether the key can be exported.
      Returns:
      true if exportable, false otherwise; null on a destroyed-key row (deleted_logical), which has no exportability to report
    • getOrigin

      public KeyOrigin getOrigin()
      Returns the key origin.
      Returns:
      key origin (GENERATED, IMPORTED), KeyOrigin.UNKNOWN for one this SDK release does not declare; null on a destroyed-key row (deleted_logical), which states no provenance
    • getOriginAsString

      public String getOriginAsString()
      Returns the key origin as the server sent it.

      For a declared origin, its name (GENERATED, IMPORTED). For one a later server added, the server's value verbatim, while getOrigin() reads KeyOrigin.UNKNOWN.

      Server-supplied and unrendered: display it through InertText.text(String).

      Returns:
      the wire value, or null when the server sent none (a destroyed-key row)
    • getRestricted

      public Boolean getRestricted()
      Returns whether the key is restricted (legacy format).
      Returns:
      true if restricted, false otherwise; null on a destroyed-key row (deleted_logical)
    • getStatus

      public String getStatus()
      Returns the current lifecycle status, as the published key-status token.

      The vocabulary is closed and is exactly the enum the crypto specification publishes for KeySummaryResponse.status: active, pending_rotation, rotated, expired, revoked, archived, suspended, pending_destruction, deleted_logical. It is the same token the ?status= filter of the key-list endpoint accepts, so a listed status can be passed back as a filter. deleted_logical marks a destroyed-key row, the one row that reports no shape, material or usage.

      Returns:
      the published status token, or STATUS_UNKNOWN for one this SDK release does not declare (never null)
    • getStatusAsString

      public String getStatusAsString()
      Returns the lifecycle status as the server sent it.

      For a declared status, the same token as getStatus(). For one a later server added, the server's value verbatim, while getStatus() reads STATUS_UNKNOWN.

      Server-supplied and unrendered: display it through InertText.text(String).

      Returns:
      the wire value (never null on a key the server returned)
    • getCreatedAt

      public ZonedDateTime getCreatedAt()
      Returns the key creation timestamp.
      Returns:
      creation timestamp (never null)
    • getExpiresAt

      public ZonedDateTime getExpiresAt()
      Returns the hard expiration timestamp.
      Returns:
      expiration timestamp, or null if no expiration is set and on a destroyed-key row (deleted_logical)
    • getSoftLimitExpiration

      public ZonedDateTime getSoftLimitExpiration()
      Returns the soft expiration (warning threshold) timestamp.
      Returns:
      soft limit timestamp, or null if no soft limit is set and on a destroyed-key row (deleted_logical)
    • getDeletedAt

      public ZonedDateTime getDeletedAt()
      Returns when the key was destroyed.
      Returns:
      destruction timestamp on a destroyed-key row (deleted_logical); null on every key the tenant still holds
    • getUsageCount

      public Integer getUsageCount()
      Returns the current usage counter.
      Returns:
      usage count, or null on a destroyed-key row (deleted_logical)
    • getSoftUsageLimit

      public Integer getSoftUsageLimit()
      Returns the soft usage limit (warning threshold).
      Returns:
      soft usage limit, or null if no soft limit is set and on a destroyed-key row (deleted_logical)
    • getMaxUsageLimit

      public Integer getMaxUsageLimit()
      Returns the hard usage limit.
      Returns:
      maximum usage limit, or null if no limit is set and on a destroyed-key row (deleted_logical)
    • isComposite

      public boolean isComposite()
      Checks if this is a composite key.

      A destroyed-key row (getStatus() is deleted_logical) reports no key type, so this answers false there even when the destroyed key was composite: false on such a row means "shape not reported", not "simple".

      Returns:
      true if kty is the coarse composite token COMPOSITE
    • isCompositeKem

      public boolean isCompositeKem()
      Checks if this is a composite KEM key.

      Decided by getCompositeMode(), never by the key type: every composite key publishes the same coarse kty, so a key-type comparison could only answer "composite", never "which construction". A destroyed-key row reports no construction, so this answers false there (see isComposite()).

      Returns:
      true if the composite construction is COMPOSITE_KEM_COMBINE
    • isCompositeSignature

      public boolean isCompositeSignature()
      Checks if this is a composite signature key.

      Decided by getCompositeMode(), for the same reason as isCompositeKem(), and false on a destroyed-key row for the same reason as isComposite().

      Returns:
      true if the composite construction is COMPOSITE_SIGNATURE