/**
 * Durable "unlocked session" store (macOS).
 *
 * The secrets broker (agent.ts) holds unlocked bundles only in RAM, so an
 * `agents secrets unlock` grant is lost whenever that process dies: on an
 * agents-cli upgrade (the postinstall bounces the daemon) and on system SLEEP.
 * This module persists the resolved bundle+env of an unlocked bundle as a
 * NO-ACL keychain item — the `set-no-acl` write path, `kSecAttrAccessibleAfter-
 * FirstUnlockThisDeviceOnly`, whose reads never pop Touch ID — so the broker can
 * REHYDRATE it on start and reads can FALL BACK to it when the broker RAM misses.
 *
 * Split-default posture: `sleepPersist` is false by default — the item is deleted
 * on SLEEP so the bundle re-locks on sleep but survives restart/upgrade; the
 * `--durable` flag sets it true so it survives sleep too. Both expire at the TTL.
 *
 * Cross-platform: a NO-OP off macOS. Linux (secret-service) and Windows
 * (Credential Manager) have no broker and resolve secrets durably from the OS
 * store on every read with no prompt (see agent.ts:onDarwin gates) — there is no
 * ephemeral unlock to persist.
 *
 * NEVER enumerate session items: once keychain-name hashing (#316) is active a
 * `list('agents-cli.session.')` matches nothing. All I/O is by KNOWN name — one
 * fixed-name index item lists the held bundles + their metadata, and one blob per
 * bundle holds the env. Every adapter call is best-effort and never throws;
 * persistence is an optimization, not a correctness dependency.
 */
import type { SecretsBundle } from './bundles.js';
import type { SecretLease } from './lease.js';
/** Prefix for all durable session items (device-local, no-ACL). */
export declare const SESSION_ITEM_PREFIX = "agents-cli.session.";
/** Fixed-name index item — the ONLY thing we ever need to find without a known
 * bundle name, so it is read/written by this exact name (never enumerated). */
export declare const SESSION_INDEX_ITEM = "agents-cli.session.index";
/** One persisted unlocked bundle (mirrors the broker's StoredBundle + posture). */
export interface SessionEntry {
    bundle: SecretsBundle;
    env: Record<string, string>;
    /** epoch ms; the entry is dead once Date.now() passes this. */
    expiresAt: number;
    /** true only for `--durable` unlocks — survives SLEEP. */
    sleepPersist: boolean;
    harness?: string;
    lease?: SecretLease;
}
/** Metadata for one held bundle, kept in the index so we can rehydrate / prune
 * without reading every blob. */
export interface SessionIndexMeta {
    expiresAt: number;
    sleepPersist: boolean;
    harness?: string;
}
export interface SessionIndex {
    bundles: Record<string, SessionIndexMeta>;
}
/** The bundle names in the index that are still within their TTL at `now`. */
export declare function selectRehydratable(index: SessionIndex, now: number): string[];
/** Split an index on a SLEEP event: keep `sleepPersist` entries, report the rest
 * (which the caller deletes from the keychain). Default entries re-lock on sleep. */
export declare function pruneOnSleep(index: SessionIndex): {
    survivors: SessionIndex;
    deletedNames: string[];
};
/** Drop entries past their TTL; report which were dropped so the caller can
 * delete their blobs. */
export declare function pruneExpired(index: SessionIndex, now: number): {
    survivors: SessionIndex;
    expiredNames: string[];
};
/** Insert/replace one bundle in the index (pure). */
export declare function upsertEntry(index: SessionIndex, name: string, meta: SessionIndexMeta): SessionIndex;
/** Remove one bundle from the index (pure). */
export declare function removeEntry(index: SessionIndex, name: string): SessionIndex;
/** Read the session index by its fixed name. `{bundles:{}}` when absent/unreadable. */
export declare function readIndex(): SessionIndex;
/** Persist the index as a no-ACL item. Deletes the item when empty (tidy). */
export declare function writeIndex(index: SessionIndex): void;
/** Persist one unlocked bundle: write its blob no-ACL and record it in the index. */
export declare function saveSession(name: string, entry: SessionEntry): void;
/**
 * Read a session honoring the scope chain: the caller's own harness first, then
 * the global grant (see bundleScopeChain in scope.ts). This is the durable-store
 * twin of the broker's `get` — both must resolve identically, or a bundle would
 * be readable from RAM but not after a restart.
 */
export declare function resolveSession(name: string, now?: number, harness?: string): {
    entry: SessionEntry;
    harness: string;
} | null;
/** Read one session blob by known name. Null when absent/expired/malformed. */
export declare function loadSession(name: string, now?: number, harness?: string): SessionEntry | null;
/** Remove every persisted harness grant for one bundle. */
export declare function deleteBundleSessions(name: string): void;
/** Delete one bundle's session blob and prune it from the index. */
export declare function deleteSession(name: string, harness?: string): void;
export declare function deleteLeaseSession(leaseId: string): number;
/** Delete every session blob + the index (for `secrets lock --all`). */
export declare function deleteAllSessions(): void;
/** Rehydrate every unexpired session into `[name, entry]` pairs for the broker to
 * load on start; prunes expired index entries + blobs as a side effect. Survives
 * upgrade/restart. Empty off darwin or when nothing is held. */
export declare function rehydrateSessions(now?: number): Array<{
    name: string;
    entry: SessionEntry;
}>;
/** On a SLEEP event: delete every non-`--durable` session (blob + index entry),
 * keep the durable ones. Default bundles thus re-lock on sleep. */
export declare function pruneSessionsOnSleep(): void;
