module · canonical release 0.2

commonsformat-lockfile

version 0.1.1 · targets format 0.2

Lockfile generation and verification for Commons Format. Records the resolved state of a consumer's dependency tree — pinned commits, checksums, and verification results — so that subsequent operations are reproducible and tampering is detectable.

depends on github.com/commonsformat/commonsformat-format ^0.2.0
license MPL-2.0
verifies ./evals.toml

Premise

The lockfile records the resolved state of a consumer's dependency tree. It pins each transitive dependency to a specific commit SHA, records content checksums for tamper detection, and captures verification results so that subsequent regenerations or audits can confirm the same contract was used.

The lockfile structure is specified by format-spec §14. This module specifies the operations that produce and verify lockfiles.

There are two operations:

  • Generate: given a resolved dependency tree (modules at specific commits with their content), produce a lockfile.
  • Verify: given a lockfile and a set of fetched modules, confirm that the modules match the lockfile's recorded checksums and pinned commits.

Interface

A lockfile tool exposes two operations.

Generate takes:

  • A root module
  • The set of resolved dependencies (each with: spec URL, version, resolved commit SHA, fetched content)
  • Optionally, verification results from running eval suites against generated implementations
  • The deployment tier the consumer targeted

And produces:

  • A lockfile structure conforming to format-spec §14

Verify takes:

  • A lockfile structure
  • A set of currently-fetched modules (each with: spec URL, resolved commit SHA, fetched content)

And produces:

  • A verification result indicating whether each module matches the lockfile's recorded state, and which (if any) have diverged

The lockfile tool does not fetch (that is the fetcher's job), does not resolve (that is the resolver's job), and does not generate implementations. It records and verifies.

Schema

This module ships a schema.sql declaring the shape of its data. Per §8 this is a shape commitment, not a storage commitment — the generated implementation chooses a runtime representation appropriate to its intent.

-- This DDL describes data shape, not storage. Runtime representation
-- is implementation-defined; choose what is appropriate to the target
-- language and the module's intent. A lockfile is canonically a TOML
-- file on disk (per the intent and format-spec §14); the tables below
-- are the shape that TOML serializes, not a database the lockfile
-- tool maintains.

CREATE TABLE lockfiles (
    root_module_name     TEXT    NOT NULL PRIMARY KEY,
    root_spec_hash       TEXT    NOT NULL,
    lock_format_version  TEXT    NOT NULL,
    generated_at         TEXT    NOT NULL,
    generator_tool       TEXT    NOT NULL
);

CREATE TABLE locked_modules (
    root_module_name     TEXT    NOT NULL,
    spec_url             TEXT    NOT NULL,
    declared_version     TEXT    NOT NULL,
    resolved_commit_sha  TEXT    NOT NULL,
    fetched_from         TEXT    NOT NULL,
    content_checksum     TEXT    NOT NULL,
    fetched_at           TEXT    NOT NULL,
    PRIMARY KEY (root_module_name, spec_url),
    FOREIGN KEY (root_module_name) REFERENCES lockfiles (root_module_name)
);

CREATE TABLE module_verification (
    root_module_name     TEXT    NOT NULL,
    spec_url             TEXT    NOT NULL,
    deployment_tier      TEXT    NOT NULL CHECK (deployment_tier IN ('D0', 'D1', 'D2', 'D3')),
    PRIMARY KEY (root_module_name, spec_url),
    FOREIGN KEY (root_module_name, spec_url) REFERENCES locked_modules (root_module_name, spec_url)
);

CREATE TABLE module_verification_results (
    root_module_name     TEXT    NOT NULL,
    spec_url             TEXT    NOT NULL,
    generator_id         TEXT    NOT NULL,
    functional           TEXT    NOT NULL CHECK (functional IN ('pass', 'fail', 'skipped', 'unverified')),
    adversarial          TEXT    NOT NULL CHECK (adversarial IN ('pass', 'fail', 'skipped', 'unverified')),
    generator_adversary  TEXT    NOT NULL CHECK (generator_adversary IN ('pass', 'fail', 'skipped', 'unverified')),
    PRIMARY KEY (root_module_name, spec_url, generator_id),
    FOREIGN KEY (root_module_name, spec_url) REFERENCES locked_modules (root_module_name, spec_url)
);

CREATE TABLE module_prose_review (
    root_module_name     TEXT    NOT NULL,
    spec_url             TEXT    NOT NULL,
    reviewed             BOOLEAN NOT NULL,
    reviewed_at          TEXT,
    reviewer             TEXT,
    prose_hash           TEXT,
    PRIMARY KEY (root_module_name, spec_url),
    FOREIGN KEY (root_module_name, spec_url) REFERENCES locked_modules (root_module_name, spec_url)
);

CREATE TABLE module_applied_packs (
    root_module_name     TEXT    NOT NULL,
    spec_url             TEXT    NOT NULL,
    pack_name            TEXT    NOT NULL,
    pack_version         TEXT    NOT NULL,
    pack_commit_sha      TEXT    NOT NULL,
    PRIMARY KEY (root_module_name, spec_url, pack_name),
    FOREIGN KEY (root_module_name, spec_url) REFERENCES locked_modules (root_module_name, spec_url)
);

CREATE TABLE module_applied_overrides (
    root_module_name     TEXT    NOT NULL,
    spec_url             TEXT    NOT NULL,
    element_path         TEXT    NOT NULL,
    override_value       TEXT    NOT NULL,
    PRIMARY KEY (root_module_name, spec_url, element_path),
    FOREIGN KEY (root_module_name, spec_url) REFERENCES locked_modules (root_module_name, spec_url)
);

CREATE TABLE verify_results (
    root_module_name     TEXT    NOT NULL,
    spec_url             TEXT    NOT NULL,
    status               TEXT    NOT NULL CHECK (status IN ('match', 'content-tampered', 'commit-moved', 'missing')),
    detail               TEXT,
    PRIMARY KEY (root_module_name, spec_url)
);

CREATE INDEX locked_modules_by_commit ON locked_modules (resolved_commit_sha);

What the lockfile tool must do

  • canonical-output — lockfile generation is deterministic. The same inputs (modulo timestamps) produce byte-identical lockfile output
  • record-pinned-commits — every transitive dependency has its resolved commit SHA recorded, regardless of whether the original declaration used a tag, branch, or SHA
  • record-checksums — each module's content checksum is computed and recorded, allowing later detection of tampered content
  • record-verification-axes — verification results (eval depth, generator diversity, runtime diversity, applied eval packs) are recorded per format-spec §14
  • detect-tampered-content — verification compares fetched content against recorded checksums; mismatches are reported
  • detect-pinned-commit-mismatch — if a tag has moved since the lockfile was created (resolved commit differs from recorded), this is reported
  • preserve-verification-claims — claims about verification (deployment tier, eval depth achieved) survive in the lockfile and are not silently dropped during regeneration

What the lockfile tool must NOT do

  • Fetching content. The lockfile tool operates on already-fetched modules.
  • Resolving dependencies. The resolver produces the resolved tree that becomes lockfile input.
  • Verifying implementations against eval suites. The eval runner does that. The lockfile tool records the runner's results.
  • Updating itself silently. If a consumer's dependency state has changed, the lockfile tool reports the change; updating the lockfile is an explicit operation, not a side effect.
  • Hiding override applications. Overrides applied during merging are visible in the lockfile per format-spec §11.5.

Lockfile format

The lockfile structure is fully specified in format-spec §14. Implementations of this module produce and verify lockfiles conforming to that specification.

The lockfile is itself a TOML file (§4 subset). It is hand-readable in principle — for audit and debugging — but is generated and modified by tooling, not edited directly by consumers.

Threat model

The lockfile is a trust-critical artifact. Its purpose is detecting unauthorized changes to dependency content. Specific threats:

  • A dependency repository whose content was tampered with after the lockfile was generated. Detected by content checksum mismatch on verify.
  • A tag that was moved to point at a different commit. Detected by resolved-commit mismatch on verify.
  • A lockfile from a different consumer's project being submitted in place of the legitimate one. Detected by root_hash mismatch if the lockfile records the root module's hash.
  • A modified lockfile (an attacker editing recorded checksums to match tampered content). The lockfile itself can be tracked in the consumer's version control; commit-level diffs reveal unauthorized modifications.

The lockfile does not defend against:

  • A compromised generator. Recorded checksums confirm content is unchanged since fetch, but if the original fetched content was malicious, the lockfile will faithfully record that malicious content.
  • A compromised verifier. The runner's verification results are recorded as the runner reported them; the lockfile cannot validate the runner.

These limits mean the lockfile is one layer of defense, not the only one. Consumers at higher deployment tiers should combine lockfiles with multi-generator conformance, signature verification, and source review.

Verification

This module's eval suite tests lockfile generation against known inputs (does the produced lockfile have the right structure and content?) and verification against synthetic divergent states (does verify catch a tampered checksum, a moved tag, etc.?).

A consumer generating a lockfile implementation iterates against this eval suite. Once it conforms, the implementation can be composed with the consumer's resolver and fetcher to produce a complete dependency-management toolchain.

describes commonsformat-lockfile 0.1.1 · targets commons format 0.2 · generated from release 0.2 · 2026-05-28