// Copyright © StellaOps. All rights reserved.
// SPDX-License-Identifier: AGPL-3.0-or-later
// Sprint: SPRINT_20260112_018_CRYPTO_key_escrow_shamir
// Tasks: ESCROW-003, ESCROW-004
namespace StellaOps.Cryptography.KeyEscrow;
///
/// Service for key escrow operations using Shamir's Secret Sharing.
///
public interface IKeyEscrowService
{
///
/// Escrow a key by splitting it into shares and distributing to agents.
///
/// Identifier for the key being escrowed.
/// The key material to escrow.
/// Escrow configuration options.
/// Cancellation token.
/// Result containing share IDs and metadata.
Task EscrowKeyAsync(
string keyId,
byte[] keyMaterial,
KeyEscrowOptions options,
CancellationToken cancellationToken = default);
///
/// Recover a key from escrow using collected shares.
///
/// Recovery request with authorization details.
/// Decrypted shares from custodians.
/// Cancellation token.
/// Result containing recovered key material.
Task RecoverKeyAsync(
KeyRecoveryRequest request,
IReadOnlyList shares,
CancellationToken cancellationToken = default);
///
/// Get escrow status for a key.
///
/// Key identifier.
/// Cancellation token.
/// Escrow status or null if not escrowed.
Task GetEscrowStatusAsync(
string keyId,
CancellationToken cancellationToken = default);
///
/// List all escrowed keys.
///
/// Cancellation token.
/// List of escrowed key summaries.
Task> ListEscrowedKeysAsync(
CancellationToken cancellationToken = default);
///
/// Revoke escrow for a key (delete all shares).
///
/// Key identifier.
/// Reason for revocation.
/// Cancellation token.
/// True if revocation succeeded.
Task RevokeEscrowAsync(
string keyId,
string reason,
CancellationToken cancellationToken = default);
///
/// Re-escrow a key with new shares (after recovery or rotation).
/// Invalidates previous shares.
///
/// Key identifier.
/// Key material to re-escrow.
/// New escrow options (or null to use previous).
/// Cancellation token.
/// Result containing new share IDs.
Task ReEscrowKeyAsync(
string keyId,
byte[] keyMaterial,
KeyEscrowOptions? options = null,
CancellationToken cancellationToken = default);
}
///
/// Options for key escrow operations.
///
public sealed record KeyEscrowOptions
{
///
/// Minimum shares required for recovery (M in M-of-N).
///
public required int Threshold { get; init; }
///
/// Total shares to create (N in M-of-N).
///
public required int TotalShares { get; init; }
///
/// Days until shares expire.
///
public int ExpirationDays { get; init; } = 365;
///
/// IDs of agents to distribute shares to.
/// Must have at least TotalShares agents.
///
public IReadOnlyList? AgentIds { get; init; }
///
/// Whether to require dual-control ceremony for recovery.
///
public bool RequireDualControl { get; init; } = true;
///
/// Metadata to attach to the escrow record.
///
public IReadOnlyDictionary? Metadata { get; init; }
}
///
/// Status of a key's escrow.
///
public sealed record KeyEscrowStatus
{
///
/// Key identifier.
///
public required string KeyId { get; init; }
///
/// Whether the key is currently escrowed.
///
public required bool IsEscrowed { get; init; }
///
/// Threshold for recovery.
///
public int Threshold { get; init; }
///
/// Total shares created.
///
public int TotalShares { get; init; }
///
/// Number of shares still valid (not expired or revoked).
///
public int ValidShares { get; init; }
///
/// When the escrow was created.
///
public DateTimeOffset? CreatedAt { get; init; }
///
/// When shares expire.
///
public DateTimeOffset? ExpiresAt { get; init; }
///
/// Whether recovery is currently possible.
///
public bool CanRecover => ValidShares >= Threshold;
///
/// Custodians holding shares.
///
public IReadOnlyList? CustodianIds { get; init; }
}
///
/// Summary of an escrowed key.
///
public sealed record KeyEscrowSummary
{
///
/// Key identifier.
///
public required string KeyId { get; init; }
///
/// Threshold for recovery.
///
public required int Threshold { get; init; }
///
/// Total shares.
///
public required int TotalShares { get; init; }
///
/// When escrowed.
///
public required DateTimeOffset CreatedAt { get; init; }
///
/// When shares expire.
///
public required DateTimeOffset ExpiresAt { get; init; }
///
/// Escrow metadata.
///
public IReadOnlyDictionary? Metadata { get; init; }
}