/** * Backup Archive Service (P0) * * Builds a portable workspace backup: a single `.tar.gz` containing a * top-level `manifest.json`, the captured `CREWLY_HOME` globals (under * `home/`), each project's `.crewly/` tree (under `projects//`), and * optionally `chat.db`. * * Runs locally with no Cloud dependency — `crewly backup create`. The Cloud * upload/park step (Pro-gated) is a later phase and consumes the archive this * service produces. See specs/2026-06-07-workspace-backup.md. * * @module services/backup/backup-archive.service */ import { type ComponentLogger } from '../core/logger.service.js'; import { type CreateBackupOptions, type CreateBackupResult, type ProjectFilesEstimate } from './backup.types.js'; /** * True for files excluded at any depth: JSONL transcripts, stray `*.log` * files (raw PTY output can carry secrets) and shell history files. * * @param name - File name (no directory) * @returns True when the file must not be archived */ export declare function isExcludedBackupFile(name: string): boolean; /** * Service that builds workspace backup archives. */ export declare class BackupArchiveService { private readonly logger; constructor(logger?: ComponentLogger); /** * Build a workspace backup archive. * * Captures CREWLY_HOME globals (exclude-based, so new data domains are * picked up automatically), each project's `.crewly/` tree (walked from * projects.json) with git provenance, and chat.db (unless excluded). Stages * everything into a temp dir, writes the manifest, and tars it to `outPath`. * * @param options - Build options (createdAt is required — no clock in lib code) * @returns The archive path, manifest, and total captured bytes * @throws If CREWLY_HOME does not exist or the tar write fails */ createArchive(options: CreateBackupOptions): Promise; /** * Recursively collect capturable global files under CREWLY_HOME (relative * paths). Exclude-based so new data domains are captured automatically. * * @param home - CREWLY_HOME absolute path * @returns Relative file paths (POSIX-style) to capture */ private collectGlobalFiles; /** * Estimate how much each project's source tree would add to an archive * built with `includeProjectFiles`, after excludes. Read-only; the CLI uses * it to print sizes and demand confirmation above the warning threshold. * * @param options - homePath override and exclude patterns (defaults as in createArchive) * @returns One estimate per project listed in projects.json whose path exists */ estimateProjectFiles(options?: { homePath?: string; projectFileExcludes?: string[]; }): Promise; /** * Walk a project's source tree depth-first, skipping excluded paths * (directories matching a pattern are pruned whole) and non-regular entries * (symlinks are not followed). * * @param projectPath - Absolute project root * @param filter - Exclude matcher * @param onFile - Called with (absolute path, project-relative POSIX path) per regular file */ private walkProjectFiles; /** * Walk projects.json and capture each project's `.crewly/` tree + git * provenance into staging/projects// — and, when `projectFilter` is * given, the project's own files into staging/projects//files/. * * @param home - CREWLY_HOME absolute path * @param staging - staging dir root * @param projectFilter - Exclude matcher for project files, or null to capture `.crewly/` only * @returns Project entries for the manifest */ private collectProjects; /** * Read `origin` remote + HEAD commit for a project dir (best-effort). * * The remote is read as configured in the repo (`git config`), not via * `git remote get-url`, which applies the host's `url..insteadOf` * rewrites. Those rewrites are machine-local (a mirror, a credentialed * https URL, a sandbox's ssh→https rule) and must not leak into a backup * that is restored, and re-cloned from, on another machine. * * @param projectPath - Absolute project path * @returns Git provenance (nulls when not a repo / unavailable) */ private readGitProvenance; /** * Capture chat.db via the SQLite online backup API (consistent snapshot of a * possibly-live DB). Degrades gracefully when chat.db is absent or the native * module can't load — the backup just omits it with a recorded reason. * * @param home - CREWLY_HOME absolute path * @param staging - staging dir root * @returns chat.db manifest record */ private captureChatDb; /** * Copy a source file into the staging archive layout, returning its manifest * entry (archive-relative path + sha256 + size). * * @param srcRoot - Root the relative path is resolved against * @param rel - Source path relative to srcRoot (POSIX-style) * @param staging - staging dir root * @param archivePath - Destination path inside the archive * @returns Manifest file entry */ private stageFile; /** * Read the running Crewly version (best-effort). Uses npm_package_version — * the same source as tracing.service.ts — which works under both the ESM * runtime and the CJS test runner (no import.meta / __dirname). * * @returns Version string or 'unknown' */ private readCrewlyVersion; } //# sourceMappingURL=backup-archive.service.d.ts.map