/** * Federation install gate — first-install confirmation prompt + sha256 * checksum validation for skills installed from federation peers. * * Composes BEFORE the skills-guard trust gate (T9730) so the install * pipeline is: * * 1. resolve source (caamp parser) * 2. clone / fetch (github / federation client) * 3. federation-install-gate (this module — first-install + checksum) * 4. skills-guard trust-gate (T9730 — verdict + INSTALL_POLICY) * 5. fs.copy (canonical store + symlinks) * * Each gate runs BEFORE any disk write so a blocked install has zero * side-effects on the canonical store. * * @task T9732 * @epic T9564 * @saga T9560 */ import { type FederationEntry } from './federation-store.js'; /** * Outcome of {@link evaluateFederationInstallGate}. * * `decision` semantics: * - `'allow'` — proceed to the next gate (skills-guard). * - `'block-checksum'` — manifest declares a checksum and the * downloaded artefact does not match. Caller * MUST surface `E_FEDERATION_CHECKSUM_MISMATCH`. * - `'prompt-first-install'` — federation URL has never been installed * from before. Caller MUST surface the y/N * prompt (or `E_FEDERATION_UNKNOWN_SOURCE_INTERACTIVE_REQUIRED` * in non-TTY mode without `--allow-new-source`). */ export type FederationInstallDecision = 'allow' | 'block-checksum' | 'prompt-first-install'; /** * Composite decision returned by {@link evaluateFederationInstallGate}. */ export interface FederationInstallGateResult { /** Final action — see {@link FederationInstallDecision}. */ readonly decision: FederationInstallDecision; /** Human-readable rationale (safe to surface in CLI / envelopes). */ readonly reason: string; /** Matched federation peer when the source is a known URL. */ readonly peer: FederationEntry | null; /** Whether the source resolves to a federation peer at all. */ readonly isFederationSource: boolean; /** Computed sha256 of the artefact (when supplied). */ readonly computedChecksum: string | null; /** Expected checksum from the manifest (when supplied). */ readonly expectedChecksum: string | null; } /** * Options accepted by {@link evaluateFederationInstallGate}. */ export interface FederationInstallGateOptions { /** Caller-supplied source identifier (URL, owner/repo). */ readonly source: string; /** * Absolute path to the downloaded artefact (tarball OR cloned skill dir). * When `undefined`, checksum validation is skipped. */ readonly artefactPath?: string; /** Expected sha256 from the manifest (lowercase hex, no `sha256:` prefix). */ readonly expectedChecksum?: string | null; /** * Bypass the first-install prompt — set by the caller after the operator * has explicitly approved via `--allow-new-source` or an interactive yes. */ readonly approveNewSource?: boolean; /** Optional override for the federation index path (test hook). */ readonly federationIndexPath?: string; } /** * Compute the sha256 of a file or directory. * * For directories, hashes every regular file in sorted order so the result * is stable across runs. Returns the hex digest WITHOUT the `sha256:` * prefix for direct equality comparison against manifest fields. */ export declare function computeArtefactChecksum(path: string): string; /** * Evaluate the federation install gate against the supplied source + * downloaded artefact. * * Returns: * - `allow` — non-federation source, OR federation URL * that has been seen before AND checksum * matches (or no checksum given). * - `block-checksum` — checksum mismatch — caller MUST refuse * install and surface `E_FEDERATION_CHECKSUM_MISMATCH`. * - `prompt-first-install` — federation URL with NO prior install. * Caller MUST gate on a y/N prompt or the * `--allow-new-source` flag. * * @param opts - See {@link FederationInstallGateOptions}. * @returns Composite gate result. * * @task T9732 */ export declare function evaluateFederationInstallGate(opts: FederationInstallGateOptions): FederationInstallGateResult; /** * Test convenience: tell whether the install would require interactive * confirmation. Used by CLI command logic to decide between prompt and * `E_FEDERATION_UNKNOWN_SOURCE_INTERACTIVE_REQUIRED`. * * @param decision - The decision returned by {@link evaluateFederationInstallGate}. */ export declare function requiresInteractiveConfirmation(decision: FederationInstallDecision): boolean; //# sourceMappingURL=federation-install-gate.d.ts.map