import type { SessionAuthContext } from "#channel/types.js"; import type { AuthorizationChallenge } from "#harness/authorization.js"; import type { SessionStateMap } from "#harness/types.js"; type ApprovalCandidateStatus = "pending" | "authorization-required" | "allowed" | "rejected" | "failed" | "timed-out" | "stale"; /** What a responder submitted: a candidate settles its request this way once allowed. */ export type ApprovalCandidateDecision = "approve" | "cancel"; interface ApprovalCandidateAuditRecord { readonly candidateId: string; readonly decision: ApprovalCandidateDecision; readonly requestId: string; readonly responder: ApprovalResponderIdentity; readonly status: ApprovalCandidateStatus; readonly createdAt: number; readonly completedAt?: number; readonly expiresAt?: number; readonly reason?: string; } export interface ApprovalResponderIdentity { readonly authenticator: string; readonly issuer?: string; readonly principalId: string; readonly principalType: string; } export interface ApprovalSettlementAuditRecord { readonly actor: ApprovalResponderIdentity; /** The approver's full auth, which the approved call runs as. Present only when allowed. */ readonly approver?: SessionAuthContext; /** `unavailable`: the request's entry was gone, so its call is reported unavailable, never run. */ readonly outcome: "allowed" | "cancelled" | "unavailable"; readonly requestId: string; readonly settledAt: number; readonly candidateId?: string; } export interface ActiveApprovalCandidate { readonly candidateId: string; readonly decision: ApprovalCandidateDecision; readonly requestId: string; readonly responder: SessionAuthContext; readonly status: "pending" | "authorization-required"; readonly createdAt: number; readonly expiresAt: number; readonly authorizationChallenges?: readonly AuthorizationChallenge[]; } interface ApprovalStateTransition { readonly changed: boolean; readonly state: SessionStateMap | undefined; } /** Creates or deduplicates one responder's candidate decision for a pending request. */ export declare function createApprovalCandidate(input: { readonly candidateIdPrefix: string; readonly createdAt: number; readonly decision: ApprovalCandidateDecision; readonly expiresAt: number; readonly requestId: string; readonly responder: SessionAuthContext; readonly state: SessionStateMap | undefined; }): ApprovalStateTransition; /** Marks a candidate as waiting on a private authorization challenge. */ export declare function markApprovalCandidateAuthorizationRequired(input: { readonly authorizationChallenges: readonly AuthorizationChallenge[]; readonly candidateId: string; readonly expiresAt?: number; readonly state: SessionStateMap | undefined; }): SessionStateMap | undefined; /** Finishes one candidate without settling the shared request. */ export declare function finishApprovalCandidate(input: { readonly candidateId: string; readonly completedAt: number; readonly reason?: string; readonly state: SessionStateMap | undefined; readonly status: Exclude; }): SessionStateMap | undefined; /** Expires active candidates whose deterministic deadline has passed. */ export declare function expireApprovalCandidates(input: { readonly now: number; readonly state: SessionStateMap | undefined; }): SessionStateMap | undefined; /** * Atomically settles a request with an allowed candidate's decision; every * losing candidate becomes stale. */ export declare function settleAllowedCandidate(input: { readonly candidateId: string; readonly settledAt: number; readonly state: SessionStateMap | undefined; }): ApprovalStateTransition; /** * Settles a request whose entry is gone, which no response can approve and no call can run: the * candidate fails with `reason`, its competitors go stale, and the call is reported unavailable. */ export declare function settleUnavailableCandidate(input: { readonly candidateId: string; readonly reason: string; readonly settledAt: number; readonly state: SessionStateMap | undefined; }): ApprovalStateTransition; /** Atomically settles a direct authenticated approval response. */ export declare function settleDirectApprovalResponse(input: { readonly actor: SessionAuthContext; readonly outcome: "allowed" | "cancelled"; readonly requestId: string; readonly settledAt: number; readonly state: SessionStateMap | undefined; }): ApprovalStateTransition; /** Returns one active candidate by id. */ export declare function getActiveApprovalCandidate(state: SessionStateMap | undefined, candidateId: string): ActiveApprovalCandidate | undefined; /** Returns a copy of the durable candidate/audit state for inspection and replay. */ export declare function getApprovalAuditState(state: SessionStateMap | undefined): { readonly activeCandidates: readonly ActiveApprovalCandidate[]; readonly candidateHistory: readonly ApprovalCandidateAuditRecord[]; readonly settlements: readonly ApprovalSettlementAuditRecord[]; }; export declare function sameResponder(a: Pick, b: Pick): boolean; /** * The held turn moved on, steered or cancelled: the responders still checking one of its * approvals stop, their candidates stale. */ export declare function retireActiveCandidates(state: SessionStateMap | undefined, input: { readonly completedAt: number; readonly reason: string; }): SessionStateMap | undefined; /** The full auth of whoever approved `requestId`, when it was allowed. */ export declare function approverOfRequest(state: SessionStateMap | undefined, requestId: string): SessionAuthContext | undefined; export {};