/** * Durable record of every account the agent created in the owner's name. * * Autonomous signup without this file is invisible sprawl: accounts nobody can * enumerate, audit, or revoke. Everything the agent signs up for lands here, at creation * time, before the credential is even stored. * * What is NOT here: the credential. Only `credentialSecretKey`, the NAME of the entry in * the secret store that holds it. This registry is a plain JSON file; a password in it * would be a password on disk in the clear. `record()` rejects secret-looking text in * every field, and there is a test asserting the credential value never reaches the file. * * Follows the platform registry conventions, caller-supplied store path, versioned * store file, defensive parse, atomic write, with one deliberate divergence noted at * `readStore`. * * The store path and the secret-shaped-text predicate both arrive from the caller. * The path, because where a product keeps its state is the product's decision. The * predicate, because "what looks like a credential" is a policy each surface already * owns, and quietly shipping a second copy of those patterns here would let the two * drift, a value this registry accepted would then be one the surface's own memory * guard rejected, or worse, the other way round. */ export interface AgentAccountRecord { readonly id: string; /** Registered domain of the service, normalized. */ readonly serviceDomain: string; /** The page the account was created at. */ readonly serviceUrl: string; /** The per-signup alias minted by `signup-address.ts`. */ readonly aliasAddress: string; readonly createdAt: string; readonly purpose: string; /** * The NAME of the secret-store entry holding the credential. Never the credential. * Revocation starts here: look up this key, rotate or delete it. */ readonly credentialSecretKey: string; } export interface AgentAccountCreateInput { readonly serviceDomain: string; readonly serviceUrl: string; readonly aliasAddress: string; readonly purpose: string; readonly credentialSecretKey: string; readonly now?: Date; } export interface AgentAccountSweepInput { readonly now?: Date; /** * Keys the secret store actually holds. When supplied, records pointing at a key that * no longer exists are orphans and get dropped, the credential is already gone. */ readonly knownSecretKeys?: readonly string[]; /** When supplied, records older than this are dropped. */ readonly maxAgeDays?: number; } export interface AgentAccountSweepResult { readonly removed: readonly AgentAccountRecord[]; readonly remaining: number; } export interface AgentAccountSnapshot { readonly path: string; readonly accounts: readonly AgentAccountRecord[]; /** Records dropped by the last read because they failed validation. */ readonly droppedOnRead: number; } /** Bound on persisted records. Sprawl has a ceiling, and hitting it is loud. */ export declare const MAX_ACCOUNT_RECORDS = 500; /** * "Does this text look like a credential rather than a name?" * * Supplied by the caller; see the module header for why it is not defined here. */ export type SecretLikeTextPredicate = (text: string) => boolean; /** * The path segments below a surface's own storage root that this registry occupies. * * Exported so a product composes its own root with these rather than inventing a * second layout: `resolveUserPath(, ...ACCOUNT_REGISTRY_PATH_SEGMENTS)`. */ export declare const ACCOUNT_REGISTRY_PATH_SEGMENTS: readonly string[]; /** * Supplies the owner's real delivery address when no mail account is configured. * * A registered reader rather than an import of `platform/owner-profile`: this * module is reachable from surfaces that never load a profile, and it has to keep * working there unchanged. With nothing registered, {@link resolveSignupBaseAddress} * returns exactly what its caller passed in. */ export type SignupBaseAddressSource = () => string | undefined; /** Register (or clear, with `null`) the profile-backed base-address fallback. */ export declare function registerSignupBaseAddressFallback(source: SignupBaseAddressSource | null): void; /** * The base address every minted alias resolves back to, "the owner's real * delivery address this alias resolves to", in `signup-address.ts`'s own words. * * A configured mail account always wins. The profile's `contact.email` fills the * gap, which is the point of wiring it: without it, an autonomous signup on a * machine with no mail account configured has nowhere to send the confirmation * and cannot proceed, even though the owner told the runtime their address * weeks ago. * * `signup-address.ts` is untouched by this. It is alias-minting machinery, not a * store of owner facts, and it stays a pure function of the base address it is * handed. * * Note what this deliberately does NOT feed: `security/owner-identity.ts`'s * `resolveOwnerAddresses()`. That set gates the one exemption to the * content-taint rule and reads configuration only, on purpose, see * `owner-profile/consumers.ts` for the reasoning. */ export declare function resolveSignupBaseAddress(configuredMailAddress?: string | undefined): string | undefined; export interface AgentAccountRegistryOptions { /** Absolute path to the registry's JSON store. */ readonly storePath: string; /** See `SecretLikeTextPredicate` and the module header. */ readonly containsSecretLikeText: SecretLikeTextPredicate; } export declare class AgentAccountRegistry { private readonly storePath; private readonly containsSecretLikeText; constructor(options: AgentAccountRegistryOptions); snapshot(): AgentAccountSnapshot; list(): readonly AgentAccountRecord[]; get(id: string): AgentAccountRecord | null; /** Record an account the agent just created. Call this before storing the credential. */ record(input: AgentAccountCreateInput): AgentAccountRecord; forget(id: string): AgentAccountRecord; /** * Reap expired and orphaned entries and compact the file. * * With no arguments this still rewrites the store from the validated read, which drops * malformed and duplicate entries that a hand edit may have introduced. */ sweep(input?: AgentAccountSweepInput): AgentAccountSweepResult; private nextId; /** * Divergence from `calendar-registry.ts`: that registry throws when the store cannot be * read. This one must not. A corrupt accounts file would otherwise take down every * caller that just wants to enumerate what the agent signed up for, which is exactly * when enumeration matters most. Unreadable content yields an empty, still-writable * store; malformed records are dropped individually and counted in `droppedOnRead`. */ private readStore; private writeStore; } //# sourceMappingURL=account-registry.d.ts.map