/** * Fetch + verify the signed update manifest. * * The manifest is a JSON envelope `{ manifest, sig }` where `sig` is a * detached Ed25519 signature of `canonicalJson(manifest)`. cadre-host only * trusts manifests whose signature matches the embedded release public key. * * Canonical serialization (`canonicalJson`) is shared from `@serfab/cadre-core` * so the seed-signing path and this manifest-signing path agree on the signed * byte representation; the shape we sign here is fixed (`UpdateManifest`). */ import { type KeyObject } from 'node:crypto'; import { ed25519FromRaw } from './release-key.js'; import { type SignedManifest, type UpdateManifest } from './types.js'; /** Default release-manifest URL. Overridable via env var on the caller. */ export declare const DEFAULT_MANIFEST_URL = "https://releases.serfab.io/cadre-host/latest.json"; export interface FetchManifestOptions { url: string; fetcher?: typeof fetch; /** Total fetch timeout (connect + read) in ms; default 10000. */ readTimeoutMs?: number; } /** * Fetch the manifest endpoint and validate the signature against the embedded * release public key (or `CADRE_HOST_UPDATE_DEV_KEY` if set). * * Throws `UpdateErrorException` on any failure (bad JSON, bad signature, * etc.). Network errors are *thrown* — the caller decides whether to log * them at debug (the cadence path) or surface them (the apply path). */ export declare function fetchManifest(opts: FetchManifestOptions): Promise; /** * Verify a parsed signed-manifest body. Pure (no network), so unit tests * exercise this directly. */ export declare function verifyManifest(body: unknown, env?: NodeJS.ProcessEnv): UpdateManifest; /** * Sign a manifest with the release private key, producing the `{ manifest, sig }` * envelope published as `latest.json`. This is the production signing operation: * it canonicalizes with the same `canonicalJson` that `verifyManifest` consumes * and emits a detached `ed25519:` signature. The private key never ships * in the binary — signing runs offline on the release operator's machine (see * `scripts/sign-manifest.mjs`). */ export declare function signManifest(manifest: UpdateManifest, privateKey: KeyObject): SignedManifest; /** Used by `apply.ts` to detect which key the signer matches. */ export declare function publicKeyMatchesEmbedded(rawBase64: string, env?: NodeJS.ProcessEnv): boolean; /** Wrapper for `getReleasePublicKey`, re-exported for parity with `ed25519FromRaw`. */ export { ed25519FromRaw }; /** * Field-level validation that goes beyond the structural `isUpdateManifest` * type guard: enforces semver on version strings, ISO-8601 round-tripping on * the publish timestamp, and the npm naming regex on the package name. A * signed-but-malformed manifest would otherwise surface as a confusing * `compareVersions` throw further downstream. * * Exported so the offline signing tool (`sign.ts` / `sign-manifest.mjs`) runs * the *exact same* rules before it signs — the signer can never emit a * manifest that `verifyManifest` would later reject as `manifest_invalid`. */ export declare function validateManifestFields(m: UpdateManifest): void; /** * Canonical JSON serializer used to define the signed byte representation. * The implementation lives in `@serfab/cadre-core` (cadre-host depends on * cadre-core); re-exported here so existing import sites stay stable. */ export { canonicalJson } from '@serfab/cadre-core';