/** * @fileoverview BrightTrustStateMachine implementation. * * Central coordinator for the BrightTrust system. Manages operational mode, * epoch lifecycle, proposal/vote orchestration, and delegates to * SealingService for cryptographic operations. * * @see Requirements 1-8, 10-13 */ import { Member, PlatformID } from '@digitaldefiance/ecies-lib'; import { BrightTrustOperationalMode } from '../enumerations/brightTrustOperationalMode'; import { IGossipService } from '../interfaces/availability/gossipService'; import { BrightTrustEpoch } from '../interfaces/brightTrustEpoch'; import { BrightTrustMetrics } from '../interfaces/brightTrustMetrics'; import { IBanConfig } from '../interfaces/network/banConfig'; import { Proposal, ProposalInput } from '../interfaces/proposal'; import { IBrightTrustDatabase } from '../interfaces/services/brightTrustDatabase'; import { BrightTrustMemberMetadata, SealedDocumentResult } from '../interfaces/services/brightTrustService'; import { IBrightTrustStateMachine } from '../interfaces/services/brightTrustStateMachine'; import { RedistributionConfig } from '../interfaces/services/redistributionConfig'; import { VoteInput } from '../interfaces/vote'; import { AliasRegistry } from './aliasRegistry'; import { AuditLogService } from './auditLogService'; import { BanListCache } from './banListCache'; import { SealingService } from './sealing.service'; /** * BrightTrustStateMachine is the central coordinator for the BrightTrust system. * * It manages: * - Operational mode (Bootstrap / BrightTrust / TransitionInProgress) * - Epoch lifecycle * - Document sealing/unsealing with mode-aware delegation * - Metrics collection * * @template TID - Platform ID type for frontend/backend DTO compatibility */ export declare class BrightTrustStateMachine implements IBrightTrustStateMachine { private readonly db; private readonly sealingService; private readonly gossipService; private readonly auditLogService?; private readonly aliasRegistry?; private mode; private currentEpochData; private configuredThreshold; private initialized; private readonly checksumService; private readonly banConfig; private readonly banListCache; private readonly banProposalValidator; private metricsData; constructor(db: IBrightTrustDatabase, sealingService: SealingService, gossipService: IGossipService, auditLogService?: AuditLogService | undefined, aliasRegistry?: AliasRegistry | undefined, banConfig?: Partial); /** * Initialize the BrightTrust system. * * - Checks for persisted operational state first (restore on restart). * - If TransitionInProgress is detected, triggers rollback recovery. * - Otherwise, determines mode based on member count vs threshold. * - Persists the operational state and creates epoch 1. */ initialize(members: Member[], threshold: number): Promise>; /** * Rollback a transition that was interrupted (crash recovery or failure). * * For each journal entry, restores the document's old shares, member IDs, * and threshold from the journal. Then deletes all journal entries and * resets operational state to Bootstrap mode. * * @param epochNumber - The epoch number to rollback * @param emitAudit - Whether to emit a transition_ceremony_failed audit entry (false during crash recovery in initialize) */ private rollbackTransition; /** Ensure the state machine is initialized before operations. */ private ensureInitialized; /** Ensure operations are not blocked by a transition ceremony. */ private ensureNotTransitioning; /** * Create the next epoch with incremented epoch number. * * 1. Gets the current epoch number * 2. Creates a new epoch with epochNumber = current + 1 * 3. Saves the epoch to the database * 4. Updates the operational state with the new epoch number * 5. Updates the cached currentEpochData * 6. Returns the new epoch * * @param memberIds - Active member IDs for the new epoch * @param threshold - Threshold for the new epoch * @param mode - Operational mode for the new epoch * @param previousEpochNumber - Optional override for the previous epoch number * @returns The newly created BrightTrustEpoch */ private createNextEpoch; /** * Emit an audit log entry. * * If an AuditLogService is configured, routes through it for chain linking * and signing. Otherwise, writes directly to the database. * * @param eventType - The type of audit event * @param details - Additional event-specific details * @param targetMemberId - Optional target member ID */ private emitAuditEntry; /** * Resolve IBrightTrustMember records into Member objects suitable for SealingService. * * Creates Member instances with only public keys (no private keys) from * the database member records. These are sufficient for encrypting new shares. * * @param brightTrustMembers - Database member records to resolve * @returns Array of Member objects with public keys */ private resolveMembersFromRecords; /** * Perform batched share redistribution for all documents in a given epoch. * * Processes documents in pages using `listDocumentsByEpoch`, decrypts shares * from threshold members, calls `redistributeShares`, updates documents, * and saves them back to the database. * * @param fromEpochNumber - The epoch whose documents need redistribution * @param thresholdMembers - Members with private keys to decrypt existing shares * @param newMembers - The new member set for re-encryption * @param newThreshold - The new threshold for shares * @param oldSharingConfig - The old sharing configuration (totalShares, threshold) * @param config - Redistribution configuration (batch size, progress, continue-on-failure) * @returns Array of failed document IDs */ private redistributeDocuments; /** * Get the current operational mode. * Restores from persisted state on first call if needed. */ getMode(): Promise; /** * Initiate a transition ceremony from Bootstrap to BrightTrust mode. * * Flow: * 1. Verify members >= threshold, set mode to TransitionInProgress * 2. Emit transition_ceremony_started audit entry * 3. Block seal/unseal/submitProposal (via ensureNotTransitioning) * 4. For each bootstrap-sealed document (paginated): * a. Save journal entry with old shares/members/threshold/epoch * b. Redistribute shares to full member set with configured threshold * c. Update document in database * 5. On success: create new epoch in BrightTrust mode, delete journal entries, * emit transition_ceremony_completed, unblock * 6. On failure: rollback from journal, reset to Bootstrap, delete journal * entries, emit transition_ceremony_failed */ initiateTransition(): Promise; /** * Create a new epoch for a completed transition ceremony. * * Called by the transition ceremony logic (Task 10) when all documents * have been successfully re-split. Creates a new epoch in BrightTrust mode * with the full member set and configured threshold. * * @param memberIds - The full member set after transition * @param threshold - The configured quorum threshold * @returns The new BrightTrustEpoch in BrightTrust mode */ createTransitionEpoch(memberIds: TID[], threshold: number): Promise>; /** * Add a new member to the BrightTrust. * * Saves the member, increments the epoch, triggers batched share * redistribution for all documents in the previous epoch, and emits * audit entries for member_added and share_redistribution_*. * * @param member - The member to add * @param metadata - Metadata for the member * @param redistributionConfig - Optional redistribution configuration * @returns The new BrightTrustEpoch after member addition */ addMember(member: Member, metadata: BrightTrustMemberMetadata, redistributionConfig?: Partial): Promise>; /** * Remove a member from the BrightTrust. * * Validates remaining count >= threshold, removes the member, * increments the epoch, triggers share redistribution with fresh * polynomial coefficients, and emits audit entries for member_removed * and share_redistribution_*. * * @param memberId - ID of the member to remove * @param redistributionConfig - Optional redistribution configuration * @returns The new BrightTrustEpoch after member removal * @throws BrightTrustError with InsufficientRemainingMembers if removal would drop below threshold * @throws BrightTrustError with MemberNotFound if the member is not in the current epoch */ removeMember(memberId: TID, redistributionConfig?: Partial): Promise>; /** * Maximum allowed description length for proposals. */ private static readonly MAX_DESCRIPTION_LENGTH; /** * Member count threshold above which inner brightTrust routing is used. */ private static readonly INNER_BRIGHT_TRUST_MEMBER_THRESHOLD; /** * Action types considered routine for inner brightTrust routing. * When member count > 20 and an inner brightTrust exists, these use the inner quorum threshold. */ private static readonly ROUTINE_ACTION_TYPES; /** * Determine the required threshold for a proposal based on inner brightTrust routing. * * When member count > 20 and the current epoch has innerBrightTrustMemberIds, * routine operations use the inner brightTrust size as threshold, * while critical operations use the full membership threshold. * * @param actionType - The proposal action type * @returns The required vote threshold */ private getRequiredThreshold; /** * Submit a proposal for BrightTrust voting. * * Validates the proposer is an active member, validates description length, * validates IDENTITY_DISCLOSURE has an attachment, assigns a unique ID, * stores as pending, announces via gossip, and emits audit entry. * * @param proposal - The proposal input * @returns The created Proposal with assigned ID and status * @throws BrightTrustError with MissingAttachment if IDENTITY_DISCLOSURE lacks attachmentCblId */ submitProposal(proposal: ProposalInput): Promise>; /** * Submit a vote on a pending proposal. * * Validates the proposal exists and is pending, validates the voter is an * active member, checks for duplicate votes, stores the vote, announces * via gossip, emits audit entry, and triggers vote tallying. * * @param vote - The vote input * @throws BrightTrustError with ProposalExpired if proposal is not pending * @throws BrightTrustError with DuplicateVote if voter already voted * @throws BrightTrustError with VoterNotOnProposal if voter is not an active member */ submitVote(vote: VoteInput): Promise; /** * Tally votes for a proposal. * * Counts approve and reject votes. If approve count >= threshold, marks * the proposal as approved and dispatches the action. If reject count * makes approval impossible, marks the proposal as rejected. * * @param proposal - The proposal to tally votes for */ private tallyVotes; /** * Mark a proposal as expired and emit audit entry. * * @param proposal - The proposal to expire */ private expireProposal; /** * Execute the action associated with an approved proposal. * * Dispatches to the appropriate handler based on ProposalActionType. * Simple actions are fully implemented; complex ones are stubs that log. * * @param proposal - The approved proposal whose action to execute */ private executeProposalAction; /** * 11.8.1 ADD_MEMBER — stub that calls addMember with payload data. */ private executeAddMember; /** * 11.8.2 REMOVE_MEMBER — stub that calls removeMember with payload data. */ private executeRemoveMember; /** * 11.8.3 CHANGE_THRESHOLD — update threshold and trigger share redistribution. */ private executeChangeThreshold; /** * 11.8.5 UNSEAL_DOCUMENT — stub (collect shares, unseal). */ private executeUnsealDocument; /** * 11.8.6 IDENTITY_DISCLOSURE — check statute of limitations, reject if expired/deleted. * * When the target IdentityRecoveryRecord has expired or been deleted by the * expiration scheduler, throws IdentityPermanentlyUnrecoverable (Req 17.6). */ private executeIdentityDisclosure; /** * 11.8.7 REGISTER_ALIAS — delegate to AliasRegistry.registerAlias(). */ private executeRegisterAlias; /** * 11.8.8 DEREGISTER_ALIAS — delegate to AliasRegistry.deregisterAlias(). */ private executeDeregisterAlias; /** * 11.8.9 EXTEND_STATUTE — update expiresAt on the target IdentityRecoveryRecord. */ private executeExtendStatute; /** * 11.8.10 CHANGE_INNER_BRIGHT_TRUST — update innerBrightTrustMemberIds on current epoch. */ private executeChangeInnerBrightTrust; /** * 11.8.11 CUSTOM — log approval without automated execution. */ private executeCustomAction; /** * Execute a BAN_MEMBER proposal. * * Sets the target member's status to Banned, creates a ban record with * approval signatures from the proposal's votes, persists it, updates * the local ban list cache, and emits an audit log entry. * * If the target is a BrightTrust member, also triggers removal logic * (share redistribution). */ private executeBanMember; /** * Execute an UNBAN_MEMBER proposal. * * Restores the target member's status to Active, removes the ban record, * updates the local ban list cache, and emits an audit log entry. */ private executeUnbanMember; /** * Get a proposal by its ID. */ getProposal(proposalId: TID): Promise | null>; /** * Seal a document using the appropriate mode (bootstrap or brightTrust). * * In bootstrap mode: delegates to brightTrustSealBootstrap with effective threshold = member count. * In BrightTrust mode: delegates to brightTrustSeal with configured threshold. * Tags document with epoch number and sealedUnderBootstrap flag. * * @throws BrightTrustError with TransitionInProgress if a transition ceremony is active */ sealDocument(agent: Member, document: T, memberIds: TID[], sharesRequired?: number): Promise>; /** * Unseal a document. * * Verifies checksum (SHA-3) and creator signature using constant-time * comparison before delegating to SealingService. * Returns generic error on failure without revealing which check failed (Req 8.4-8.6). */ unsealDocument(documentId: TID, membersWithPrivateKey: Member[]): Promise; /** Get the current epoch. */ getCurrentEpoch(): Promise>; /** Get a specific epoch by number. */ getEpoch(epochNumber: number): Promise | null>; /** Get brightTrust system metrics for monitoring. */ getMetrics(): Promise; /** Get the configured threshold for this brightTrust. */ getConfiguredThreshold(): number; /** Get the ban list cache for enforcement point checks. */ getBanListCache(): BanListCache; /** Get the ban configuration. */ getBanConfig(): IBanConfig; } //# sourceMappingURL=brightTrustStateMachine.d.ts.map