import { type SpaceAuth } from "@cotal-ai/core"; import { type Check, type DialPolicy, type JoinTarget, type MeshEntry, type MeshTarget, type PreflightFailure, type UserBundle } from "@cotal-ai/workspace"; export { assertPinnedFetchUrl, checkUserBundle, pinnedFetch, pinnedFetchProbe, type Check, type UserBundle } from "@cotal-ai/workspace"; /** Is this path a directory? `existsSync` is not the question: a regular FILE named `.cotal` would * pass it and record a root whose `.cotal/auth` and `.cotal/agents` can never exist. `statSync` * follows symlinks, so a symlinked project dir keeps working. */ export declare function isDir(path: string): boolean; /** * The broker URL, checked before it is probed, printed or persisted. * * Credentials embedded in the URL are refused for the same reason a manifest refuses them * (`validateBroker`): this record is written to disk and echoed back by `add` and `meshes`, so an * inline password would be copied into the registry and onto the operator's screen. No message * here repeats the input — the commonest malformed broker URL is a half-typed credential one. * * `what` names where the URL came from (`--server`, or the document that carried it), because a * refusal that blames a flag the operator never typed sends them looking in the wrong place. */ export declare function checkServer(raw: string, what: string): Check; /** * May this machine send its credentials to that address? * * Registering a mesh is how a machine joins a broker it does not run, and every later command then * dials that address with an agent credential in the CONNECT line. NATS sends the initial INFO in * plaintext and unauthenticated, so an on-path attacker forges one that does not set * `tls_required` and reads the credential; the client side is the only fence. The address class * and the RECORDED TLS INTENT together are the gate: see {@link classifyJoinTarget} for the * ranges, why hostnames need required TLS, and why RFC1918 is refused in both modes. * * `policy.tlsRequired` is the strictness this registration will record — sourced from `--tls` or * a `tls://` scheme ({@link tlsIntent}) — and it is what the dial will ENFORCE, because the * candidate target and the written record carry the same value and preflight requires the * handshake off it. * * This is a SAFETY rule, not a liveness check, which is why it sits with {@link checkServer} above * the `--force` branch rather than inside it. `--force` exists to register a mesh that is *down* * right now; it must not double as permission to ship credentials across an untrusted network, * where there is nothing to verify later and no error to come back and fix. */ export declare function checkDialPolicy(server: string, policy: DialPolicy): Check; /** The TLS intent this registration records, from its two sources: the explicit `--tls` flag, or * a `tls://` scheme. The scheme is typed intent — and today nats.js connects PLAINTEXT to * `tls://host` with empty options, so honoring it here is what converts typed-but-unenforced * intent into enforcement: the record carries `tlsRequired: true`, and every dial resolved * through it requires the handshake rather than tolerating plaintext. */ export declare function tlsIntent(server: string, tlsFlag: boolean): boolean; /** Where this mesh's local trust + personas live. An explicit path must be an existing directory * (the record's whole job is to point at `.cotal/auth` and `.cotal/agents` under it). With no * flag, the nearest genuine project up-tree — and `findCotalRoot` returns its STARTING directory * when it finds none, so the inferred case must prove the `.cotal` is really there. */ export declare function checkRoot(flag: string | undefined, cwd: string): Check; /** The recorded auth mode: what the operator said, or what `--root` proves. A root holding this * space's account record means auth; anything else is an open broker. `--mode user` is permitted * IFF the pinned trust was SUPPLIED (`userTrustSupplied`) — the old blanket refusal reasoned * that IdP pins must be established, never guessed, and supplying them (a bundle exported where * the mesh runs, or a confirmed HTTPS discovery document) satisfies exactly that reasoning. */ export declare function checkMode(space: string, root: string, accounts: string[], flag: string | undefined, userTrustSupplied?: boolean): Check; /** For an AUTH registration the root must yield trust that actually COMPOSES. An account record on * disk only proves the space was known here: `loadSpaceAuth` still returns undefined when the * broker record or the signing material is missing, and recording that as `auth` produces a record * whose probe ran credlessly and whose every later use fails at resolution. */ export declare function checkTrust(mode: MeshEntry["mode"], root: string, space: string): Check; /** What the broker ENFORCES, asked with no credential at all. * * A NATS broker with no auth configured accepts a CONNECT that carries credentials and ignores * them — so "my creds were accepted" says nothing about enforcement, and recording `auth` off that * promises JWT/ACL protection that is not there. An auth broker refuses a bare connect; an open * one lets us straight in. */ export declare function probeEnforcement(server: string): Promise<"auth" | "open" | "unreachable">; /** The claimed mode must match what the broker actually enforces, in both directions. The USER * arm reads the refusal as the evidence: a user-mode target has no probe credential by design, * so a credless probe against a user-auth broker reporting auth-required IS the pass — the one * fact a bare connect can prove about a broker whose admission runs through the callout. */ export declare function checkEnforcement(mode: MeshEntry["mode"], enforces: "auth" | "open" | "unreachable", server: string, space: string, root: string): Check; /** The issuer a space's exchange answers /health with — the auth daemon's own token issuer, a * stable URN derived from the space (auth's `spaceIssuer`), deliberately NOT the IdP issuer: * the IdP names who vouches for humans, this names the exchange minting for the space. The cli * package carries no runtime dependency on @cotal-ai/auth, so the derivation is restated here * and the user-bundle smoke pins the two against each other across the package boundary. */ export declare function userExchangeIssuer(space: string): string; /** The user arm of trust composition: the pinned exchange must ANSWER, and answer as itself. * `/health` must report the pinned issuer (a base that answers with a foreign issuer is a * different authority, however reachable) and `/jwks` must serve a non-empty key set (the * verification material the pins promise). Nothing here trusts the response beyond consistency * with the pins the operator supplied. */ export declare function verifyUserExchange(base: string, issuer: string): Promise>; /** Land the sentinel and write the remote user entry — ONE writer for both front ends, so the * wizard cannot drift from the flag form on what a remote record looks like. The sentinel blob * goes into a 0600 file under the entry's own root (its space-scoped user-auth state dir) and * the record carries the PATH: the registry document is echoed by `cotal meshes` and `status`, * and secret material must never ride a file that gets printed. */ export declare function persistRemoteUserEntry(space: string, server: string, root: string, bundle: UserBundle, tlsRequired: boolean, overlayConsent: boolean): ReturnType; /** {@link persistRemoteUserEntry} without the selection: lands the sentinel and returns the entry * to record. */ export declare function remoteUserEntry(space: string, server: string, root: string, bundle: UserBundle, tlsRequired: boolean, overlayConsent: boolean): MeshEntry; /** The target this registration would resolve to. `flag-server` is the source that can never * classify as a prune — nothing is recorded yet, so no entry may be blamed for a failure. */ export declare function candidateTarget(space: string, server: string, root: string, mode: MeshEntry["mode"], auth: SpaceAuth | undefined, tlsRequired: boolean): MeshTarget; /** The registration-time wording for a failed probe. Deliberately NOT the shared preflight copy: * that speaks to a mesh already in the registry ("stale entry", "re-run `cotal up`"), and here * nothing is recorded yet — the operator is being told what to fix in the command they just ran. */ export declare function verifyFailureMessage(kind: PreflightFailure, space: string, server: string, root: string): string; /** Probe the candidate for real (liveness + credentials), after {@link checkEnforcement} has * settled what the broker is. */ export declare function verifyTarget(target: MeshTarget): Promise>; /** Write the record. Returns whether it became the default — same policy as `cotal up`: adopt only * when there is no usable one, and never silently redirect a default that still resolves. */ export declare function writeRecord(entry: MeshEntry): { adoptedCurrent: boolean; keptCurrent?: string; }; /** * The spaces this root holds account records for — the candidates a guided registration offers, * and the evidence the mode is inferred from. * * An enumeration failure is REPORTED, never flattened to "none". `listSpaceAccounts` throws when * the auth dir cannot be read (EACCES, a corrupt record), and treating that as an empty inventory * would infer `open` for a root whose trust merely could not be read — recording a credless connect * against a mesh whose credentials are sitting right there, unreadable. The pre-refactor call let * that throw reach the operator; so does this. */ export declare function spacesAtRoot(root: string): Check; //# sourceMappingURL=meshes-add.d.ts.map