/** * @fileoverview Application list cache management. * * Why a cache: `app list` fetches the remote app list from the API, which * requires an extra HTTP call. For commands that need to resolve an app name * to an appCode (e.g. `dataset list --app mystagingapp`), we cache the * `/client/app/my-apps` response so subsequent calls don't hit the API again. * * Why keyed by accessKey fingerprint: different accessKeys may return different * app lists (tenant isolation). Caching by AK ensures each AK's app list is * stored separately and invalidated when the AK changes. * * Why 600 file permissions: config files contain access keys and should not * be readable by other users on the system. */ import type { RemoteAppItem } from "../../commands/app/remote-source.js"; /** * Cached app list stored in `~/.lovrabet/cache///my-apps.json`. */ export interface CachedAppList { env: "production" | "development" | "daily"; fetchedAt: string; source: "remote" | "mock"; items: RemoteAppItem[]; } /** * Creates a cache key from an accessKey. * * Why hash the AK: the cache path is stored in a world-readable directory (~). * Putting the raw AK in the path would expose it. Using a SHA-256 digest (first * 12 chars) provides anonymity while still distinguishing between AKs. * The last 6 chars of the raw AK are appended as a human-readable suffix so * operators can identify which cache entry belongs to which AK during debugging. */ export declare function fingerprintAccessKey(accessKey: string): string; /** Returns the absolute cache file path for a given env and accessKey. */ export declare function getAppCacheFilePath(env: "production" | "development" | "daily", accessKey: string): string; /** * Reads the cached app list for an accessKey, or `null` if absent / invalid. * * Why check for empty files and parse errors: a previous write might have * failed mid-flight, leaving a truncated file. We treat all read/parse errors * as cache miss and fall through to an API fetch rather than crashing. */ export declare function readCachedAppList(env: "production" | "development" | "daily", accessKey: string | undefined): CachedAppList | null; /** * Writes the app list to the cache file atomically (temp + rename). * Returns the cache file path on success. */ export declare function writeCachedAppList(env: "production" | "development" | "daily", accessKey: string, payload: CachedAppList): string; /** * Resolves an appName to an appCode using the cached remote app list. * * Why `name` is optional: callers may not have a name to resolve (already * have an appCode or using a different resolution path). Returning `undefined` * lets the caller fall through to other resolution strategies. * * Runtime safety: unpublished apps are intentionally ignored here so a * `defaultApp` cannot silently route data commands into an unpublished app. */ export declare function resolveCachedAppCode(name: string | undefined, env: "production" | "development" | "daily", accessKey: string | undefined): string | undefined;