/** * Federation index storage — per-user list of trusted federation peers. * * Persists to `~/.cleo/federation.json` (operator-managed, plain JSON, no * SQLite). The format is intentionally simple so the operator can hand-edit * the file when needed without booting CLEO. * * ## Wire shape * * ```json * { * "version": 1, * "entries": [ * { "url": "https://peer.example/", "trust": "verified", "addedAt": "2026-05-18T..." } * ] * } * ``` * * Validation invariants enforced by {@link addFederationPeer}: * * 1. `url` MUST parse as `http://` or `https://` — other schemes rejected. * 2. `trust` MUST be one of `'verified' | 'unverified' | 'blocked'`. * 3. URLs are normalised (lowercase scheme + host, trailing slash) so * `add` is idempotent regardless of casing / trailing-slash variance. * * @task T9729 * @epic T9571 * @saga T9560 * @architecture docs/architecture/SG-CLEO-SKILLS-architecture-v3.md §9 (federation) */ /** * Trust level associated with a federation peer. * * - `'verified'` — peer has passed handshake / signature validation. * - `'unverified'` — peer added without verification (default for `add`). * - `'blocked'` — peer explicitly denied; never resolved by lookups. */ export type FederationTrustLevel = 'verified' | 'unverified' | 'blocked'; /** * One entry in the federation index. * * `url` is the canonical (normalised) form — see {@link normaliseFederationUrl}. */ export interface FederationEntry { /** Normalised peer URL (always trailing-slashed, lowercase scheme/host). */ readonly url: string; /** Operator-assigned trust level — see {@link FederationTrustLevel}. */ readonly trust: FederationTrustLevel; /** ISO-8601 timestamp when the entry was added. */ readonly addedAt: string; } /** * On-disk shape of `~/.cleo/federation.json`. * * `version` is bumped on incompatible schema changes; readers MUST refuse * to parse a higher version than they understand. */ export interface FederationIndex { /** Schema version — currently `1`. */ readonly version: 1; /** All known peers, ordered by `url` ascending. */ readonly entries: readonly FederationEntry[]; } /** * Return the canonical filesystem path for the federation index. * * Always `~/.cleo/federation.json` — NOT the XDG `getCleoHome()` path, * because federation peers are explicitly operator-managed and the simple * `~/.cleo` location lets the user hand-edit without spelunking through * `~/.local/share`. * * @task T9729 */ export declare function getFederationIndexPath(): string; /** * Normalise a peer URL into the canonical on-disk form. * * Rules: * - Scheme + host lowercased. * - Default port stripped when it matches the scheme default. * - Path canonicalised; trailing `/` always present. * - Query string + fragment dropped (federation URLs don't carry them). * * @param raw - Caller-supplied URL string. * @returns The canonical form. * @throws {Error} If `raw` does not parse as a valid `http(s)://` URL. * * @task T9729 */ export declare function normaliseFederationUrl(raw: string): string; /** * Validate that `value` is one of the {@link FederationTrustLevel} literals. * * @param value - Anything (typically user input from the CLI). * @throws {Error} If `value` is not a recognised trust level. */ export declare function assertTrustLevel(value: unknown): asserts value is FederationTrustLevel; /** * Read the federation index from disk. * * Returns a fresh empty index when the file does not exist (first-run case). * Throws on JSON parse errors or schema-version mismatches — the operator * SHOULD see those loudly so corrupted state is not silently overwritten. * * @param path - Optional override (defaults to {@link getFederationIndexPath}). * @returns The validated index. * * @task T9729 */ export declare function readFederationIndex(path?: string): FederationIndex; /** * Atomically write the federation index to disk. * * Uses the tmp-then-rename pattern so a crash mid-write never leaves a * partial file. The parent directory (`~/.cleo`) is created on demand. * * @param index - The index to persist. * @param path - Optional override (defaults to {@link getFederationIndexPath}). * * @task T9729 */ export declare function writeFederationIndex(index: FederationIndex, path?: string): void; /** * Result of {@link addFederationPeer}. */ export interface AddFederationResult { /** The entry as persisted (post-normalisation). */ readonly entry: FederationEntry; /** `true` when the URL was already present and only the trust level changed. */ readonly updated: boolean; } /** * Add (or update) a federation peer. * * Idempotent on `url` — calling twice with the same normalised URL updates * the existing entry's `trust` and leaves `addedAt` unchanged. Returns * `updated: true` in that case. * * @param url - Caller-supplied URL (will be normalised). * @param trust - Trust level — defaults to `'unverified'`. * @param path - Optional override of the index file location (test hook). * @returns The persisted entry and a flag indicating insert-vs-update. * * @task T9729 */ export declare function addFederationPeer(url: string, trust?: FederationTrustLevel, path?: string): AddFederationResult; /** * Remove a federation peer by URL. * * @param url - Caller-supplied URL (will be normalised before lookup). * @param path - Optional override of the index file location (test hook). * @returns `true` when a row was removed; `false` when the URL was unknown. * * @task T9729 */ export declare function removeFederationPeer(url: string, path?: string): boolean; /** * List all federation peers. * * @param path - Optional override of the index file location (test hook). * @returns Entries in canonical sort order (by URL ascending). * * @task T9729 */ export declare function listFederationPeers(path?: string): readonly FederationEntry[]; //# sourceMappingURL=federation-store.d.ts.map