# lpm.lockb format (/docs/reference/lockb-format)



`lpm.lockb` is a generated binary companion to [`lpm.lock`](/docs/reference/lockfile-format). It stores the subset of lockfile metadata that fits the current fixed-width wire format, so tools can validate or inspect that subset without parsing TOML.

`lpm.lock` is always the authoritative install input. When a lockfile carries TOML-only metadata that `lpm.lockb` cannot represent, LPM CLI skips the binary write and removes any stale `lpm.lockb` from a previous install.

Commit `lpm.lockb` when LPM CLI writes it. Mark it as binary in `.gitattributes` — `lpm init` does this automatically:

```text title=".gitattributes"
lpm.lockb binary
```

## File location [#file-location]

`<project-root>/lpm.lockb`

## Layout (v3) [#layout-v3]

```text
[Header: 16 bytes]
  magic              [u8; 4]  = b"LPMB"
  version            u32 LE   = 3
  package_count      u32 LE
  string_table_off   u32 LE   — byte offset where the string table starts

[PackageEntry × N: 36 bytes each, sorted by name]
  name_off           u32 LE   — offset into the string table
  name_len           u16 LE
  version_off        u32 LE
  version_len        u16 LE
  source_off         u32 LE   — 0 = None
  source_len         u16 LE
  integrity_off      u32 LE   — 0 = None
  integrity_len      u16 LE
  deps_off           u32 LE   — offset into the deps table
  deps_count         u16 LE
  tarball_off        u32 LE   — 0 = None  (v2+)
  tarball_len        u16 LE                (v2+)

[DepsEntry × total_deps: 6 bytes each]
  str_off            u32 LE   — offset into the string table
  str_len            u16 LE

[ProvenanceEntry × M: 68 bytes each, sparse]
  package_index       u32 LE   — index into PackageEntry table
  publisher           (u32 off, u16 len)
  workflow_path       (u32 off, u16 len)
  workflow_ref        (u32 off, u16 len)
  cert_sha256         (u32 off, u16 len)
  subject_name        (u32 off, u16 len)
  subject_sha512      (u32 off, u16 len)
  log_id              (u32 off, u16 len)
  bundle_sha256       (u32 off, u16 len)
  integrated_time     u64 LE
  rekor_log_index     i64 LE

[ProvenanceFooter: 8 bytes]
  magic              [u8; 4]  = b"PRV3"
  evidence_count     u32 LE

[String table]
  packed UTF-8, no NUL terminators
```

All numeric fields are little-endian. Packages are sorted by their package identity so reads can binary-search the entry table. The provenance section is sparse: packages without verified evidence do not pay a 68-byte per-package cost.

## Wire-format version [#wire-format-version]

Current: `v3` ([`BINARY_VERSION`](https://github.com/lpm-dev/rust-client/blob/main/crates/lpm-lockfile/src/binary.rs)). The `1 → 2` bump appended `(tarball_off, tarball_len)` to every `PackageEntry`. The `2 → 3` bump added the sparse provenance section and its `PRV3` footer without changing the 36-byte package entry. A v3 file with no provenance therefore costs only the 8-byte footer over v2; each evidence record costs 68 bytes plus its unique strings. This binary wire version is independent from the TOML `lockfile-version`, which is currently `7`.

The binary reader rejects any file whose header `version` is not exactly `BINARY_VERSION` — strict by design. Layout differs across versions, so interpreting one version as another could produce garbage or drop security evidence. `lpm.lock` remains the authoritative input; the next compatible `write_all` rewrites `lpm.lockb` as the current version.

## Sentinel for optional fields [#sentinel-for-optional-fields]

Optional string fields (`source`, `integrity`, `tarball`, and the optional provenance identity fields) use `(off=0, len=0)` to mean `None`.

To keep this sentinel unambiguous, the writer **rejects empty strings at insert time**: an empty source URL, integrity hash, or tarball URL is nonsensical input regardless. Failing loud is correct.

## What's NOT stored in the binary lockfile [#whats-not-stored-in-the-binary-lockfile]

The binary format is intentionally smaller than the TOML format. These fields are not represented:

* **`alias-dependencies`** — npm-alias edges
* **`importers`** — manifest snapshots used by frozen installs
* **`patches`** — patch paths and patch-file SHA-256 records
* **`root-aliases`** — root-level npm-alias map
* **`ambient-peer-installs`** — root-level auto-installed peer links
* **`peers`** — per-package resolved peer pinning
* **`catalogs`** — catalog protocol snapshots
* **`auto-isolated-peer-conflicts`** — linker orchestration state
* **`os` / `cpu` / `libc` / `optional` / `node-engine`** — platform, optional-reachability, and dependency engine state
* **`registry-signatures` / `registry-published-at`** — npm registry signature evidence

Lockfiles that use any unsupported field are written as TOML-only — the binary file is skipped entirely, and any stale binary file is removed. This is an explicit safety check ([`binary_format_supports`](https://github.com/lpm-dev/rust-client/blob/main/crates/lpm-lockfile/src/binary.rs)) — silently dropping metadata would produce a binary lockfile that disagrees with the reviewer-visible TOML lockfile.

Verified provenance itself is supported by v3. If the same project also uses frozen-install importer snapshots, npm aliases, peer pinning, dependency engine constraints, platform-specific optional packages, catalogs, or registry signatures, seeing only `lpm.lock` is still correct.

## Reading the file [#reading-the-file]

The reader [`BinaryLockfileReader`](https://github.com/lpm-dev/rust-client/blob/main/crates/lpm-lockfile/src/binary.rs) `mmap`s the file once, parses the header, validates the magic + version, and exposes by-name lookup via binary search over the entry table. No allocation per entry; string slices borrow directly from the mmap.

For projects whose lockfile fits the binary subset, this keeps generated-cache validation cheap. Projects outside that subset read the authoritative TOML lockfile instead.

## See also [#see-also]

* [`lpm.lock` format](/docs/reference/lockfile-format) — the canonical TOML lockfile
* [Lockfile concept](/docs/packages/lockfile) — design overview
* [`lpm install`](/docs/packages/install) — what reads each file
