/** * backup-unpack.ts — Bundle extraction and integrity verification for .cleobundle.tar.gz. * * Implements the unpack + verify half of the T311 import lifecycle. * Extracts a .cleobundle.tar.gz (or .enc.cleobundle.tar.gz) to a staging * directory and verifies all 6 integrity layers defined in ADR-038 §4.2. * * The caller is responsible for cleaning up the staging directory via * {@link cleanupStaging} after processing. Restore-to-disk is the * responsibility of T361 (CLI import handler). * * Verification layers (executed in strict order): * Layer 1 — AES-256-GCM auth tag (encrypted bundles only) * Layer 2 — Manifest self-hash (SHA-256 with placeholder substitution) * Layer 3 — Manifest JSON Schema validation (bundled schemas/manifest-v1.json) * Layer 4 — Per-file SHA-256 checksums * Layer 5 — SQLite PRAGMA integrity_check * Layer 6 — Schema version comparison (warnings only, never blocks) * * @task T350 * @epic T311 * @why ADR-038 — the unpack + verify half of the T311 import lifecycle. * Restore-to-disk is the responsibility of T361 (CLI import handler); * this module stops after verification and returns a staging dir path. * @module store/backup-unpack */ import type { BackupManifest } from '@cleocode/contracts'; /** * Input parameters for {@link unpackBundle}. * * @task T350 * @epic T311 */ export interface UnpackBundleInput { /** Absolute path to the .cleobundle.tar.gz (or .enc.cleobundle.tar.gz) file. */ bundlePath: string; /** Required if the bundle is encrypted. */ passphrase?: string; } /** * Schema compatibility warning for a database whose version differs from local. * * Warnings do NOT abort the import — they are collected and returned * in the result for the caller to surface (spec §9, Q5=C best-effort). * * @task T350 * @epic T311 */ export interface SchemaCompatWarning { /** Logical database name as it appears in the manifest. */ db: string; /** schemaVersion recorded in the bundle manifest. */ bundleVersion: string; /** Current local schema version (from migration records). */ localVersion: string; /** Direction of the version skew. */ severity: 'older-bundle' | 'newer-bundle'; } /** * Result of a successful {@link unpackBundle} call. * * The caller MUST call {@link cleanupStaging} with `stagingDir` after * processing, regardless of what they do with the contents. * * @task T350 * @epic T311 */ export interface UnpackBundleResult { /** Absolute path to the extracted staging directory. Caller must clean up. */ stagingDir: string; /** Parsed and validated manifest.json from the bundle. */ manifest: BackupManifest; /** Per-layer verification results. */ verified: { /** true if AES-GCM auth tag was valid (or N/A for unencrypted bundles). */ encryptionAuth: boolean; /** true if manifest.json matched the bundled JSON Schema. */ manifestSchema: boolean; /** true if all files' SHA-256 matched checksums.sha256. */ checksums: boolean; /** true if all .db files passed PRAGMA integrity_check. */ sqliteIntegrity: boolean; }; /** Schema version warnings — never block the import. */ warnings: SchemaCompatWarning[]; } /** * Error thrown by {@link unpackBundle} when any integrity layer fails. * * Exit codes: * - `70` `E_BUNDLE_DECRYPT` — decryption or passphrase failure * - `71` `E_BUNDLE_SCHEMA` — manifest.json failed JSON Schema validation * - `72` `E_CHECKSUM_MISMATCH` — SHA-256 checksum did not match * - `73` `E_SQLITE_INTEGRITY` — SQLite PRAGMA integrity_check failed * - `74` `E_MANIFEST_MISSING` — manifest.json absent from archive * - `75` `E_SCHEMAS_MISSING` — schemas/manifest-v1.json absent from archive * * @task T350 * @epic T311 */ export declare class BundleError extends Error { readonly code: number; readonly codeName: string; /** * @param code - Numeric exit code (70–75). * @param codeName - Symbolic constant name, e.g. `'E_BUNDLE_DECRYPT'`. * @param message - Human-readable error description. */ constructor(code: number, codeName: string, message: string); } /** * Extract a `.cleobundle.tar.gz` to a temp staging directory and verify all * 6 integrity layers in strict sequence (ADR-038 §4.2). * * On any failure AFTER the staging directory is created, the staging directory * is cleaned up before the {@link BundleError} is thrown. * * The caller MUST call {@link cleanupStaging} with the returned `stagingDir` * after it is done processing. * * @param input - Bundle path and optional passphrase. * @returns Verification result with staging dir, manifest, layer flags, and warnings. * @throws {BundleError} On any integrity failure (exit codes 70–75). * * @task T350 * @epic T311 */ export declare function unpackBundle(input: UnpackBundleInput): Promise; /** * Remove the staging directory created by {@link unpackBundle}. * * Safe to call on a path that no longer exists (idempotent). * * @param stagingDir - Absolute path returned in {@link UnpackBundleResult.stagingDir}. * * @task T350 * @epic T311 */ export declare function cleanupStaging(stagingDir: string): void; //# sourceMappingURL=backup-unpack.d.ts.map