import type { Provider } from "../types.js"; import type { CredentialRankingContext, CredentialRankingStrategy, UsageReport } from "../usage.js"; import type { RankingStrategyResolver } from "../usage/registry.js"; import type { CredentialPool } from "./pool.js"; import type { AuthCredentialStore } from "./store.js"; import type { UsageCache, UsageRequestDescriptor } from "./usage-cache.js"; import type { AuthCredential, BlocksApi, StoredCredentialBlock } from "./types.js"; /** Default block when no provider reset time is known; used by selectors and rate limits. */ export declare const DEFAULT_BLOCK_MS = 60000; /** Composite key for round-robin tracking: ":oauth" or ":api_key". */ export declare function providerTypeKey(provider: string, type: AuthCredential["type"]): string; /** Scoped backoff map key used by the credential block store. */ export declare function scopedBackoffKey(providerKey: string, blockScope: string | undefined): string; /** Authentication backoffs apply to every model and cannot be healed by quota evidence. */ export declare const AUTH_BLOCK_SCOPE = "auth"; /** Account-policy backoffs apply to every model and survive quota resets. */ export declare const ACCOUNT_POLICY_BLOCK_SCOPE = "account-policy"; /** Scope key for one model-specific account-policy block, shared by selectors and rate limits. */ export declare function modelAccountPolicyBlockScope(provider: string, modelId: string | undefined): string | undefined; /** Scope keys that a request must check, including model-policy constraints. */ export declare function credentialBlockScopesForRequest(provider: string, strategy: CredentialRankingStrategy | undefined, rankingContext: CredentialRankingContext, blockScope: string | undefined): readonly string[]; /** Latch for unrecoverably corrupt persisted block stores, shared with the credential pool. */ export declare class BlockStoreHealth { #private; constructor(sourceLabel: string | undefined); get damaged(): boolean; handle(err: unknown): boolean; assertWritable(): void; } /** Dependencies for persisted rate-limit blocks and usage-report healing. */ export interface CredentialBlocksDeps { store: AuthCredentialStore; pool: CredentialPool; health: BlockStoreHealth; usageCache: UsageCache; strategies: RankingStrategyResolver; } /** Temporary rate-limit blocks: id-keyed in memory, mirrored to the store, healed by live usage. */ export declare class CredentialBlocks implements BlocksApi { #private; constructor(deps: CredentialBlocksDeps); /** Returns block expiry timestamp for a credential, checking unscoped and scoped blocks. */ blockedUntil(provider: string, providerKey: string, credentialIndex: number, blockScopeOrScopes?: string | readonly string[] | undefined): number | undefined; /** Checks if a credential is temporarily blocked due to usage limits. */ isBlocked(provider: string, providerKey: string, credentialIndex: number, blockScope?: string | readonly string[] | undefined): boolean; /** * Whether the in-memory block currently sitting at exactly `deadline` for * this credential was written with provider-stated timing. Mirrors the * scope enumeration of {@link CredentialBlocks.blockedUntil}. * A deadline with no matching in-memory entry came from the persisted * store, which carries no provenance — a stale persisted heuristic guess * (pre-restart hintless response) must not outrank a fresh complete usage * report, so persisted-only deadlines count as untimed. Persisted * deadlines longer than this call's own request still win through the * merged `blockedUntilMs` comparison, which needs no provenance. */ isTimed(providerKey: string, blockScopeOrScopes: string | readonly string[] | undefined, credentialId: number, deadline: number): boolean; /** * Marks a credential as blocked until the specified time. `providerTimed` * records whether the requested deadline comes from provider-stated * timing (a parsed retry hint or a usage-report reset) rather than a * heuristic/default guess; the stored block keeps the provenance of * whichever deadline wins the longest-wins merge. */ mark(provider: string, providerKey: string, credentialIndex: number, blockedUntilMs: number, blockScope?: string | undefined, providerTimed?: boolean): void; /** * Lift any temporary backoff blocks on one credential (across the bare * `provider:oauth` key and its scoped `\0`-suffixed derivatives). Called * after a saved reset is redeemed so the just-reset account is immediately * selectable again instead of being skipped/under-ranked by a stale block * that `markUsageLimitReached` set for the now-obsolete reset time. */ clearAll(provider: string, credentialId: number): void; /** Clear exactly one quota scope, preserving unrelated account and model blocks. */ clearScope(provider: string, credentialId: number, providerKey: string, blockScope: string | undefined): boolean; /** Providers whose stale usage-limit blocks a healthy live report may clear. */ supportsHealing(provider: Provider): boolean; /** * Whether a fresh report could lift what currently blocks this credential. * * Claude reports can heal legacy account-wide quota blocks too. Explicit * auth/account-policy blocks never justify a usage probe. */ canHeal(provider: Provider, providerKey: string, credentialIndex: number, blockScopeOrScopes: string | readonly string[] | undefined): boolean; /** * Self-heal stale usage-limit blocks: when a fresh live usage report says a * scope is below every limit gating it, drop its persisted and in-memory * blocks so credential selection re-includes the recovered account before * the block expires by clock. Providers declare their scopes and any meter * verdicts via {@link CredentialRankingStrategy.healableBlockScopes}. */ reconcile(provider: Provider, credentialId: number, report: UsageReport): void; reconcileRequest(request: UsageRequestDescriptor, report: UsageReport): void; reconcileReports(reports: UsageReport[]): void; /** * Broker-server seam: list non-expired persisted blocks for snapshot entries. */ list(credentialIds: readonly number[]): StoredCredentialBlock[]; /** * Broker-server seam: persist one credential block and notify snapshot waiters. */ upsert(block: StoredCredentialBlock): void; /** Broker-server seam: clear exactly one persisted and local block and notify snapshot waiters. */ delete(credentialId: number, providerKey: string, blockScope: string, invalidateUsage?: boolean): void; deleteAll(credentialId: number): void; }