import { type BrokerTransport, type AuthPrepared, type ChannelRegistryFile, type ParsedArgs, type FlagSpec, type CompletionResult } from "@cotal-ai/core"; import { type MeshEntry, type MaintenanceLock } from "@cotal-ai/workspace"; import { type PreparedManifest } from "../lib/manifest/index.js"; import { type ExistingStorePin, type StackUpNative } from "./stack-up.js"; import { type PreparedRestore } from "../lib/restore.js"; /** What a guarded restore returned, for `backup restore` to report as its own receipt. `up --restore` * never sets a sink and its output is unchanged. Delivered only after the native activation wrote * the active journal; every earlier failure still throws through the same restore guards. */ export interface RestoreStartupResult { attemptId: string; space: string; root: string; server: string; mode: PreparedRestore["mode"]; selection: PreparedRestore["selection"]; targetPath: string; runtime: string; brokerPid: number; delivery: boolean; authService: boolean; controlPlane: boolean; manager: boolean; } /** Run the guarded `up --restore` startup and return its result instead of printing it. The * restore inputs and fences are exactly `up --restore`'s; this adds no route, flag or authority. */ export declare function startRestore(values: { restore: string; "restore-only"?: string; "accept-missing-source"?: boolean; "store-dir"?: string; }): Promise; /** `cotal up` flags — colocated with the command (like `spawnFlags`) so its completion can read them. */ export declare const upFlags: FlagSpec[]; /** Completion for `cotal up` — `--runtime ` offers `pty` + installed runtime providers (the same * offline source `spawn` uses; a never imports or probes). Run `cotal runtimes` to also see the * official ones that aren't installed yet. Declared flags are offered only while options remain open. */ export declare function upComplete(argv: string[]): CompletionResult; /** Launch intent is checked by the kernel before seed or effect preparation. A recovery * re-entry supplies its recorded mode explicitly rather than inheriting the new public default. */ export declare function validateUpArguments(args: ParsedArgs): void; /** An explicit root is an existing local workspace, not a hint to find another ancestor or * create trust in an arbitrary directory. Validation runs before the dispatcher seeds extensions. */ export declare function preparedUpRoot(value: string): string; /** Foreground controller stack: the terminal holds the stack's lifetime until SIGINT or SIGTERM, * which runs the same guarded whole-stack stop as bare `down`. `start`, when given, is the startup * this terminal already holds: a signal during it lets the start settle, then runs that stop. A * failed start still runs the stop, and its failure is thrown once the stop returns. The hold's end * sets the exit code: 0 when another command completed the stop or preserve, 130 or 143 after a * signal, whatever the start receipt set. */ export declare function holdForegroundStack(root: string, start?: () => Promise): Promise; /** The registered `up` command. When a background run is the main process of a systemd unit, it * names that unit and the `--foreground` remedy once startup returns: controller stack, retained * launcher, refresh and restore alike. It never changes the run's mode. Internal callers of * {@link up} print nothing. */ export declare function upCommand(args: ParsedArgs): Promise; /** `inheritedLock` is the root maintenance lock a recovery re-entry hands down (see the re-entry * below). Ownership transfers with it: this call releases it at its own release point. */ export declare function up(args: ParsedArgs, inheritedLock?: MaintenanceLock, freshTeamBoot?: boolean, restoreSink?: (result: RestoreStartupResult) => void): Promise; /** Every fresh-boot input a controller team boot freezes before its first effect. It holds no * credential, trust material or launch spec; those are produced only after this plan exists. */ export interface FreshTeamBootPlan { root: string; space: string; server: string; /** The declared bind host, or undefined when the manifest left it unset (loopback default). */ host: string | undefined; mode: "open" | "auth" | "user"; idp: string | undefined; runtime: string; manifestPath: string; prepared: PreparedManifest; transport: BrokerTransport; maxSessions: number | undefined; } /** The fresh boot's read-only preparation, shared by the controller team boot. It runs the same * manifest load, override, mode agreement, ownership, bind, runtime, reachability and connector * refusals as the retained `upManifest` fresh path, in the same order, and writes nothing. */ export declare function prepareFreshTeamBoot(file: string, opts: { space: string; transport: BrokerTransport; server?: string; host?: string; runtime?: string; open?: boolean; userAuth?: boolean; idp?: string; maxSessions?: number; }): Promise; /** A team boot that resumes one exact stopped controller stack whose manager was never attempted. * The same manifest load, agreement, durable-on-open, runtime, reachability and connector refusals * as {@link prepareFreshTeamBoot}, without the fresh zero-instance ownership gate: that gate is * replaced by the stopped-stack eligibility the caller binds under its lock. The manifest may not * move the recorded broker: its server must equal the recorded one, and a declared bind host must * equal the recorded host. Writes nothing. */ export declare function prepareResumeTeamBoot(file: string, opts: { space: string; transport: BrokerTransport; recorded: { server: string; mode: "open" | "auth" | "user"; host?: string; }; }): Promise; /** The recorded broker transport of a prepared root, decided without persisting anything: a team * boot names no TLS flags, so it inherits the root's recorded policy exactly as a bare `up` does. */ export declare function recordedBrokerTransport(root: string): BrokerTransport; /** Recheck, under the fresh boot's own lock, the ownership and bind refusals that a concurrent * writer could have invalidated after {@link prepareFreshTeamBoot}. */ export declare function recheckFreshTeamBoot(plan: FreshTeamBootPlan, own?: { deploymentId: string; }): Promise; /** The native callbacks a controller stack start uses, shared by `cotal up` and a controller team * boot so both prepare, seed and record through the same native path. */ export declare function controllerStackNative(): StackUpNative; export interface DetachOpts { /** * The listener's transport, resolved and validated by the CALLER. * * NON-OPTIONAL. This function used to re-derive it here from `opts`, which never carried * `--tls-cert`/`--tls-key` — so `cotal up --detach --tls-cert …` validated the pair, dropped it at * this boundary, fell through to the recorded policy (absent on a first enable), and served * PLAINTEXT while printing `✓ mesh up`. Re-deriving a decision in the callee is what let the * caller's copy be silently unused; the fix is that there is one decision and it arrives as an * argument. */ transport: BrokerTransport; server?: string; storeDir?: string; /** A store that must already exist with this identity. Preparation rechecks it instead of * creating the directory, and refuses a missing, replaced or relinked store. */ existingStore?: ExistingStorePin; /** JetStream file storage cap in bytes (`--max-file-store`), rendered and recorded by this boot. */ maxFileStore?: number; space?: string; open?: boolean; /** USER MODE: enable per-user auth (presence = on; `idpUrl` pins the IdP on first enable). */ userAuth?: { idpUrl?: string; }; /** Rotate the space's system account before rendering the broker config, re-minting the two $SYS * creds against the successor. Only this boot (and the foreground one) may set it: rotation is * complete only when the broker it starts is the one carrying the rewritten config. */ rotateSys?: boolean; channels?: string; host?: string; /** Channel-registry seed in memory (the `cotal up -f` manifest path), used instead of reading a * `--channels` file. Takes precedence over {@link channels}. */ seed?: ChannelRegistryFile; /** Live boot lines, tailed from the server's log file (safe for a detached child). */ onLine?: (line: string) => void; /** PUBLIC-exchange daemon argv (`--exchange-public-port` et al), threaded verbatim to the * auth-service daemon when THIS boot starts it. */ publicExchange?: string[]; /** Manifest launch (`cotal up -f`): the ONE control-plane manager started alongside the broker * carries this runtime + resolved launch-spec path — never a second supervise (singleton lease). */ runtime?: string; launch?: string; resumeAttempt?: string; resumeCommit?: { path: string; sha256: string; }; maxSessions?: number; /** #1417 broker-only boot (`--no-manager`): no manager starts with this broker. An `up -f` under * the flag boots the broker + channels and launches NO agents from this host — a manifest's * agents are booted by its manager, so a launch spec under `--no-manager` would promise a boot * nothing can deliver. Refused at the flag level; carried here so every path is explicit. */ noManager?: boolean; /** Fresh-team human report owns stdout; omit helper progress notes, retain stderr failures. */ quietBoot?: boolean; /** Maintenance-bound listener (restore target or ordinary-resume source): named spawn, durable * ownership bind immediately after, wire verification after readiness. */ boundListener?: { serverName: string; serverNonce: string; onSpawn(pid: number, startedAt: string): void; verify(): Promise; }; } /** Prepare the existing broker's local trust, configuration and launch inputs without starting a * listener, auth service, delivery daemon or manager. This is an explicit mutating phase, not a * dry-run or service-adapter planning hook. Its returned setup includes private authority material * for the coordinating caller only; it must not be logged or serialized into a public receipt. */ export declare function prepareBrokerStart(opts: DetachOpts): Promise<{ root: string; server: string; space: string; useAuth: boolean; storeDir: string; seedFile: ChannelRegistryFile | undefined; host: string; transport: BrokerTransport; setup: { confPath: string; creds: string; wsPort: number; prepared?: AuthPrepared; stateDir?: string; } | undefined; confPath: string; args: string[]; bin: string; source: "path" | "bundled"; }>; /** * Open the detached broker's log with {@link openPrivateAppend}: created `0600` whatever the umask, * never through a symlink, and an earlier log this user owns set to `0600`. A symlink, a log another * user owns or a name that is not a regular file is refused and left unchanged. */ export declare function openBrokerLog(path: string): number; /** * Start a background nats-server (JetStream), wait until it's reachable, pre-create the * space's streams, and leave it running detached (pid in `.cotal/nats.pid`). Used by * `up --detach`. When `onLine` is given, boot output is tailed from the * log file and forwarded — the child writes to the file (not a pipe), so it survives the * parent exiting. */ export declare function startMeshDetached(opts: DetachOpts): Promise<{ server: string; pid: number; source: string; controlPlane: boolean; authService: boolean; deliveryResponderBound: boolean | null; delivery: boolean; manager: boolean; }>; /** A space name maps to one mesh in the registry (the key `--space`/`use`/`down` act on). Before * starting a broker, refuse to reuse a space already claimed by a DIFFERENT live mesh — a stale/dead * holder is reclaimed, and said so when it was another root's, unless that root still holds a * maintenance journal. Re-`up`ping the same mesh (same server + root) is a refresh (port-reachable * path). NOTE: this is a best-effort sequential guard — two `cotal up --space X` racing from * different roots within the same instant can both pass the check before either records; that * concurrent case is out of scope (a single-operator CLI action), not synchronized with a lock. */ export declare function claimSpace(space: string, server: string, root: string): Promise; /** * The manager attach/console BIND host for a launch into `space`. * * Exposure is an operator DECISION, made at `up --host` and recorded on the mesh entry. Every later * launch for the same mesh — a same-root repair, adopting a preserved or restored listener, a * manifest deploy — has no `--host` of its own to consult, so it reads the decision back. Without * this a replacement manager falls to loopback and remote `cotal attach` dies at the first repair, * silently: the broker and every agent stay up, only the terminal face moves. * * An explicit host on THIS invocation always wins, so an operator can widen or narrow exposure by * saying so. Absent both, undefined — the manager's own loopback default, unchanged. */ export declare function attachHostFor(space: string, explicit?: string): string | undefined; /** * The manager live-session ceiling for a launch into `space`. * * Like {@link attachHostFor}, this is an operator DECISION (`--max-sessions`), not something later * commands can reconstruct. Every later manager launch — same-root repair, resume, `spawn -f` — * has no flag of its own unless the operator typed one, so it reads the decision back. Without * this a replacement manager silently falls to 64 and the next console pane past that is refused. * * An explicit value on THIS invocation always wins. Absent both, undefined — the plane's own * default of 64, unchanged, and nothing is recorded as though chosen. */ export declare function maxSessionsFor(space: string, explicit?: number): number | undefined; /** * Did THIS launch bring the broker up, or is it re-recording one that was already there? * * The distinction is provenance, and it has to come from the call site because it cannot be * observed here: `started` covers the paths that spawned the broker or proved a listener this * attempt owns, and stamps `origin: "up"` — a record this machine can always write back, so the * liveness sweep and `cotal down` may drop it. `refresh` is the "a broker is already on this port" * branch, which concludes the mesh is up from reachability alone and starts nothing; stamping `up` * there would silently convert a hand-registered record into one the next sweep may delete, so it * keeps whatever origin the record already had. */ type Provenance = "started" | "refresh"; /** {@link recordOurMesh} under a name that says it is a test seam: the origin rule it enforces is * asserted directly by the registry smoke, since reaching each branch through a full `up` would * need a live broker per case. */ export declare const recordOurMeshForTest: (m: MeshEntry, provenance: Provenance) => void; export {}; //# sourceMappingURL=up.d.ts.map