/** * Key Management State Machine * * Implements §5 of the RecourseOS Attestation Protocol. * Manages signing key lifecycle with 5-state model: * * pending → active → deprecated → retired * ↓ * compromised * * Any state may transition to `compromised` on security incident. */ /** * Key lifecycle states per §5.2 */ export type KeyState = 'pending' | 'active' | 'deprecated' | 'retired' | 'compromised'; /** * Metadata for a signing key per §5.1 */ export interface KeyMetadata { /** Unique key identifier (e.g., "recourse-prod-2026-001") */ key_id: string; /** Ed25519 public key in base64url encoding */ public_key: string; /** Current lifecycle state */ state: KeyState; /** ISO 8601 timestamp when key was created */ created_at: string; /** ISO 8601 timestamp when key was activated (if applicable) */ activated_at?: string; /** ISO 8601 timestamp when key was deprecated (if applicable) */ deprecated_at?: string; /** ISO 8601 timestamp when key was retired or compromised (if applicable) */ terminated_at?: string; /** Algorithm identifier (always "Ed25519" for v1) */ algorithm: 'Ed25519'; } /** * Key registry structure per §5.3 * Served at /.well-known/recourse-keys.json */ export interface KeyRegistry { /** Version of the registry format */ version: 1; /** ISO 8601 timestamp of last registry update */ updated_at: string; /** Monotonically increasing sequence number for rollback protection */ sequence: number; /** Array of all keys (active and historical) */ keys: KeyMetadata[]; } /** * Result of a state transition attempt */ export type TransitionResult = { success: true; key: KeyMetadata; } | { success: false; error: string; }; /** * Create a new key in pending state */ export declare function createKey(key_id: string, public_key: string): KeyMetadata; /** * Check if a state transition is valid */ export declare function isValidTransition(from: KeyState, to: KeyState): boolean; /** * Transition a key to a new state with validation */ export declare function transitionKey(key: KeyMetadata, to: KeyState): TransitionResult; /** * Activate a pending key */ export declare function activateKey(key: KeyMetadata): TransitionResult; /** * Deprecate an active key (begin rotation) */ export declare function deprecateKey(key: KeyMetadata): TransitionResult; /** * Retire a deprecated key (end rotation) */ export declare function retireKey(key: KeyMetadata): TransitionResult; /** * Mark a key as compromised (any state) */ export declare function compromiseKey(key: KeyMetadata): TransitionResult; /** * Check if a key can sign new attestations */ export declare function canSign(key: KeyMetadata): boolean; /** * Check if attestations signed by this key should be accepted * * Per §4.4: Keys in `pending` or `compromised` state fail verification. * Keys in `active`, `deprecated`, or `retired` state pass verification. */ export declare function canVerify(key: KeyMetadata): boolean; /** * Get the active key from a registry (for signing) */ export declare function getActiveKey(registry: KeyRegistry): KeyMetadata | undefined; /** * Get a key by ID from a registry (for verification) */ export declare function getKeyById(registry: KeyRegistry, key_id: string): KeyMetadata | undefined; /** * Create an empty key registry */ export declare function createRegistry(): KeyRegistry; /** * Add a key to the registry with sequence increment */ export declare function addKeyToRegistry(registry: KeyRegistry, key: KeyMetadata): KeyRegistry; /** * Update a key in the registry with sequence increment */ export declare function updateKeyInRegistry(registry: KeyRegistry, updated: KeyMetadata): KeyRegistry; /** * Cache entry for a key registry */ export interface CacheEntry { registry: KeyRegistry; fetched_at: string; etag?: string; } /** * Registry cache with rollback protection per §5.5 */ export declare class RegistryCache { private cache; /** * Get cached registry for a host */ get(host: string): CacheEntry | undefined; /** * Update cache with rollback protection * * @param host - The host this registry belongs to * @param registry - The new registry data * @param etag - Optional ETag for HTTP caching * @param forceRefresh - If true, bypass rollback protection (requires explicit operator action) * @returns true if update succeeded, false if rollback detected */ update(host: string, registry: KeyRegistry, etag?: string, forceRefresh?: boolean): boolean; /** * Force refresh the cache, bypassing rollback protection * This should be logged per §5.5.2 */ forceRefresh(host: string, registry: KeyRegistry, etag?: string): void; /** * Clear cache for a specific host */ clear(host: string): void; /** * Clear entire cache */ clearAll(): void; } /** * Perform key rotation: deprecate old key, add and activate new key * * This is a convenience function that performs the standard rotation sequence. * Both keys remain valid for verification during the overlap window. */ export declare function rotateKey(registry: KeyRegistry, newKeyId: string, newPublicKey: string): KeyRegistry; /** * Complete rotation: retire the deprecated key * * Call this after the overlap window has closed. */ export declare function completeRotation(registry: KeyRegistry, keyId: string): KeyRegistry; //# sourceMappingURL=key-management.d.ts.map