import { type GovernanceAttachmentBrokerLifecycleEvent } from './attachment-broker-controller.js'; import { type GovernanceCapabilityGrantRegistryOptions, type IssuedGovernanceCapabilityGrant, type IssueGovernanceCapabilityGrantOptions } from './capability-grant.js'; import type { GovernanceDaemonControlPort, GovernanceDaemonShutdownNotice } from './daemon-control.js'; import { type GovernanceDecisionContextProvider } from './project-service.js'; interface GovernanceProjectServerOptions { readonly projectRoot: string; readonly projectId: string; readonly resolveDecisionContext?: GovernanceDecisionContextProvider | undefined; readonly grantRegistry?: Omit | undefined; readonly daemonControl?: GovernanceDaemonControlPort | undefined; readonly onDaemonShutdownResponseFlushed?: ((notice: GovernanceDaemonShutdownNotice) => void) | undefined; /** * Idle window in milliseconds; defaults to {@link GOVERNANCE_DEFAULT_IDLE_MS}. * * A constructor option rather than an environment variable on purpose: * `governanceDaemonEnvironment()` passes the child an ALLOWLIST (PATH, TMP, * TZ, …), so a `WRONGSTACK_*` knob would be stripped before the daemon ever * read it — and widening that allowlist would loosen a deliberate * sanitization boundary. Threading it through the bootstrap request instead * would mean versioning the IPC protocol. This keeps both untouched and is * what lets tests drive a short window. */ readonly idleMs?: number | undefined; /** * Called once the server has been idle for {@link idleMs}. The daemon wires * this to its own `stop(0)`. When omitted NO idle timer is armed at all, so * a server constructed without it behaves exactly as before. */ readonly onIdle?: (() => void) | undefined; } export declare class GovernanceProjectServer { readonly projectRoot: string; readonly projectId: string; readonly endpoint: string; readonly databasePath: string; private readonly options; private readonly sockets; private readonly pendingSockets; private state; private listener; private store; private authenticated; private grants; private lastListenerError; private idleTimer; private lastActivityAt; private startPromise; private closePromise; constructor(options: GovernanceProjectServerOptions); get storageOpen(): boolean; get ready(): boolean; get listenerError(): Error | null; start(): Promise; private requireStarting; private startOnce; issueGrant(options: IssueGovernanceCapabilityGrantOptions): IssuedGovernanceCapabilityGrant; revokeGrant(grantId: string, reason?: string): boolean; recordAttachmentBrokerEvent(event: GovernanceAttachmentBrokerLifecycleEvent): void; close(): Promise; private closeOnce; /** * Arm the idle shutdown. NEVER re-arms an already-armed timer. * * The `this.idleTimer` guard matters: re-arming from a caller that runs more * often than the window resets the countdown forever, which is exactly how * the mailbox and kanban daemons ended up never idling out. The only place * that re-arms here is the timer's own callback, after it has decided the * daemon is still busy — so the interval between arms is always `idleMs`. * * "Busy" is three things, in order: a request is in flight (`sockets`), a * usable credential grant exists (its rotation is the session's heartbeat), * or the activity clock moved since this timer was armed. */ private scheduleIdleStop; private ensureEndpointParent; private listen; private onConnection; private accept; private handleLine; private send; private persistGrantAuditEvent; private persistDaemonShutdownAudit; private closeListener; } export {}; //# sourceMappingURL=project-server.d.ts.map