# Karapace Lock File Specification (v2) ## Overview The lock file (`karapace.lock`) captures the fully resolved state of an environment at build time. It ensures reproducible builds by pinning all dependency versions and the base image content digest. The environment identity (`env_id`) is computed from the **locked** state — resolved package versions and content digest — not from unresolved manifest data. This guarantees: same lockfile → same env_id → same environment. ## Format TOML with the following fields: | Field | Type | Description | |---|---|---| | `lock_version` | `u32` | Lock format version. Must be `2`. | | `env_id` | `string` | Full 64-character blake3 hex digest computed from locked state. | | `short_id` | `string` | First 12 characters of `env_id`. | | `base_image` | `string` | Base image identifier from manifest (e.g. `"rolling"`). | | `base_image_digest` | `string` | Blake3 content digest of the actual base image rootfs. | | `resolved_packages` | `array` | Sorted list of `{ name, version }` tables with pinned versions. | | `resolved_apps` | `string[]` | Sorted, deduplicated list of resolved GUI apps. | | `runtime_backend` | `string` | Normalized runtime backend name (lowercased). | | `hardware_gpu` | `bool` | Whether GPU passthrough is requested. | | `hardware_audio` | `bool` | Whether audio passthrough is requested. | | `network_isolation` | `bool` | Whether network is isolated. | | `mounts` | `array` | Sorted list of `{ label, host_path, container_path }` tables. | | `cpu_shares` | `u64?` | CPU shares limit (optional). | | `memory_limit_mb` | `u64?` | Memory limit in MB (optional). | ## Resolved Packages Each entry in `resolved_packages` is a table: ```toml [[resolved_packages]] name = "git" version = "2.44.0-1" [[resolved_packages]] name = "clang" version = "17.0.6-1" ``` Versions are queried from the actual package manager inside the base image during the resolve phase. This ensures identity is based on real installed versions, not just package names. ## Invariants - The lock file contains **content digests**, not tags or mutable references. - `base_image_digest` is a blake3 hash of the actual rootfs content, not a hash of the image tag name. - `env_id` is computed from all locked fields via `LockFile::compute_identity()`. - Verification is split into two checks: - **Integrity**: `verify_integrity()` — recomputes `env_id` and compares to the stored value. - **Manifest intent**: `verify_manifest_intent()` — checks that the manifest hasn't drifted from what was locked. ## Generation - Generated automatically by `karapace init` (with preliminary unresolved versions) and `karapace build` (with fully resolved versions). - Written atomically (tempfile + rename) to the same directory as the manifest. - Should be committed to version control for reproducible builds. ## Manual Override - The lock file can only be regenerated by re-running `karapace build`. - There is no `karapace lock --update` command; rebuilding is the only path. - `karapace verify-lock` checks both integrity and manifest consistency. ## Example ```toml lock_version = 2 env_id = "46e1d96fdd6fd988092fbcd19b1d89f2b080f3e74d0f4984b4ba45ca5b95e594" short_id = "46e1d96fdd6f" base_image = "rolling" base_image_digest = "a1b2c3d4e5f6..." runtime_backend = "namespace" hardware_gpu = true hardware_audio = false network_isolation = false [[resolved_packages]] name = "clang" version = "17.0.6-1" [[resolved_packages]] name = "git" version = "2.44.0-1" resolved_apps = ["debugger", "ide"] [[mounts]] label = "workspace" host_path = "./" container_path = "/workspace" ```