/** * HumanSession — bounded, consumable handle around a verified HumanDelegation. * * A HumanDelegation is the *signed consent payload*. A HumanSession is the * *runtime handle* that tracks what the agent has spent, how many calls * it has made, and whether the envelope has been exhausted or exceeded. * Separating the two matters because: * * - The delegation is immutable — once the human signs it, its envelope * is fixed. * - The session mutates on every action (budget drains, invocation * counter ticks, escalation flips). * * This module is pure in-memory. Persistence, IPC, and the HTTP surface * are the caller's problem — we only ship the state machine and the * enforcement primitives. That keeps it trivially unit-testable. * * Envelope enforcement is *strict* by default: a budget overdraft or * hitting max-invocations terminates the session. Callers who want * soft-limit behavior can wrap the registry. * * Cross-ref: `internal/active/session-mode-and-ceremony.md` §7.3. */ import type { AttestationVerifier, CeremonyTier, HumanDelegation } from './human-delegation.js'; import type { ActionClass, CeremonyPolicy } from './ceremony-policy.js'; import type { CryptoProvider } from '../core/crypto-provider.js'; import type { DidMethodRegistry } from '../core/did-method.js'; export type SessionStatus = 'active' | 'expired' | 'revoked' | 'budget-exhausted' | 'invocations-exhausted'; export interface HumanSession { sessionId: string; humanDid: string; agentEphemeralDid: string; tier: CeremonyTier; status: SessionStatus; startedAt: number; expiresAt: number; /** Remaining budget if a `budget` caveat was set, else null (unbounded). */ remainingCredits: number | null; /** Remaining invocations if `max-invocations` was set, else null. */ remainingInvocations: number | null; delegation: HumanDelegation; } export interface InvokeRequest { actionClass: ActionClass; /** Credits this action will consume. Must be ≥ 0. */ cost?: number; /** Optional host the action targets — checked against host-allowlist. */ host?: string; now: number; } export type InvokeResult = { ok: true; session: HumanSession; } | { ok: false; reason: string; session: HumanSession; }; /** * In-process registry of active HumanSessions. * * Not thread-safe across worker threads — Soma runtimes are single- * threaded per heart by design. A multi-process deployment needs its * own coordination layer on top (that's a ClawNet concern, not Soma's). */ export declare class HumanSessionRegistry { private readonly sessions; private readonly policy; private readonly verifier; private readonly provider; private readonly registry; constructor(opts: { attestationVerifier: AttestationVerifier; policy?: CeremonyPolicy; provider?: CryptoProvider; didRegistry?: DidMethodRegistry; }); /** * Verify + open a session from a signed HumanDelegation. Fails closed * on signature, attestation, or envelope errors. Idempotent by * `sessionId` — re-opening an already-active session returns the * existing handle rather than double-counting the envelope. */ open(delegation: HumanDelegation, now: number): InvokeResult; get(sessionId: string): HumanSession | undefined; /** * Attempt an in-session action. Walks the envelope caveats + policy * engine and, on success, mutates the session counters atomically. * On failure returns a reason string and leaves counters unchanged. */ invoke(sessionId: string, req: InvokeRequest): InvokeResult; revoke(sessionId: string): boolean; /** Drop terminated sessions — call from a periodic sweep. */ prune(now: number): number; get size(): number; } //# sourceMappingURL=human-session.d.ts.map