import { type LoadedGraph, type ManifestSource } from "@telorun/analyzer"; import type { LocalManifestCacheSource } from "@telorun/kernel"; /** * True when `ref` names an OCI artifact by a **tag** rather than by content — * the only case a cached manifest can silently go stale. * * A `sha256:` *reference* addresses the OCI manifest directly and is immutable. * A tag the publisher can repoint is not, unless something else verifies the * bytes — which is what {@link isPinnedOciRef} covers separately, because the * pin does not survive into a resolved graph. */ export declare function isOciTagRef(ref: string): boolean; /** True when `ref` carries Telo's inline `#sha256-…` pin, which the cache source * and the OCI transport both verify the manifest bytes against on every read. * A moved tag therefore cannot be served undetected, so no `HEAD` is needed. * * This must be asked of the ref **as authored**: `OciTransport` strips the * fragment when it builds a module's canonical source, so a network-resolved * graph no longer remembers that the import was pinned. */ export declare function isPinnedOciRef(ref: string): boolean; /** Identity under which a mutable ref's origin digest is recorded: * `host/repo@tag`, independent of scheme spelling. */ export declare function originKey(ref: string): string; /** * Whether a cached manifest for `ref` may be served to `check` at all. * * The cache maps three key shapes, and only two of them address content that * cannot change under the key: * * - `oci` — the reference is either a `sha256:` digest or a tag. A tag is * mutable, which is what {@link revalidateMutableOciRefs} exists to catch, * so both are cacheable and freshness is settled separately. * - `registry` — `@`, always version-segmented. A published * version is immutable by convention, the same assumption npm makes, so * these are served without revalidation. This is a deliberate policy call, * not a gap: the registry origin has no cheap freshness probe (`digest()` * downloads the manifest to hash it), so revalidating would cost exactly * what re-fetching costs and buy nothing. * - `url` — an arbitrary HTTP(S) import. Its key carries **no version * segment**: one URL is one path forever, so a cached copy would be served * for the lifetime of the directory no matter what the server now returns. * `check` therefore never reads these from the cache and always re-fetches. * That costs one request — exactly what revalidating would cost, since * `RegistryTransport.digest` is a full GET — so the honest option is also * the cheap one. `telo run` keeps caching them; changing that is a separate * decision about `run`'s freshness model, not a property of this pass. */ export declare function isCacheableForCheck(ref: string, registryUrl: string): boolean; /** * Wraps a manifest source and records which request URLs it actually served, * and from which file on disk. * * The freshness pass needs both halves, and neither survives into the loaded * graph: once the cache serves a manifest the graph's canonical source is a * `file://` URL, so the `oci://` ref that asked for it is gone. Recording at * the source is also what makes a *relative* import inside an OCI module work * here — the loader resolves it to an absolute `oci://` ref before `read()`, * so this map holds the absolute ref even though no manifest ever spelled it. */ export declare class RecordingCacheSource implements ManifestSource { private readonly inner; private readonly registryUrl; /** Request URL → absolute path of the cache file that answered it. */ readonly served: Map; constructor(inner: LocalManifestCacheSource, registryUrl: string); supports(url: string): boolean; read(url: string): Promise<{ text: string; source: string; }>; resolveRelative(base: string, relative: string): string; } /** * Read the recorded origin digests for one cache root. * * A missing, unreadable, or version-mismatched record yields an empty map, * which makes every cached mutable ref count as *unverified* and therefore * stale. That is the conservative direction — the failure mode is one extra * fetch, never serving a manifest whose tag has moved. It is a cache miss in * the same sense `LocalManifestCacheSource` treats a failed `stat`, not a * suppressed error. */ export declare function readOriginDigests(manifestsDir: string): Promise>; /** Persist origin digests, merging over whatever the record already held so a * check of one entry never drops another's. */ export declare function writeOriginDigests(manifestsDir: string, digests: Map): Promise; export interface FreshnessResult { /** Cache files whose tag has moved (or was never verified) since they were * written. Deleting these and reloading is what makes the check honest. */ staleFiles: string[]; /** Current digest per origin key, to record once the load is trusted. */ digests: Map; } /** * Revalidate every **mutable** OCI ref this graph resolved, with one `HEAD` per * repository reference. * * `check` is the correctness command, so it must not report a clean bill of * health against a manifest whose tag has since moved. But re-pulling every * import to find that out is what made it slow, and a pinned ref — which is * what `telo install` writes and what every published manifest carries — needs * no network at all: its bytes are verified against the inline hash. So the * cost falls only on unpinned tags, and only one round trip each, against the * four a full re-pull would take. * * A ref fetched over the network during this load is fresh by construction and * is only recorded, never revalidated. */ export declare function revalidateMutableOciRefs(graph: LoadedGraph, served: Map, /** Recorded origin digests per cache root (keyed by its `manifests` dir). A * cached manifest is judged against the record of the root it was served * from, which is not necessarily the root this entry writes to: one loader * serves every input path, so a hit may land in a sibling's cache. */ originsByRoot: Map>, registryUrl: string, /** Digests already probed earlier in this invocation, keyed as {@link originKey}. * A tag verified once in a process is verified for the whole run, so checking * twenty manifests that share an import issues one `HEAD`, not twenty. * Mutated in place so later paths see what earlier ones learned. */ verified?: Map): Promise; //# sourceMappingURL=manifest-freshness.d.ts.map