commonsformat-lockfile
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.
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 outputrecord-pinned-commits— every transitive dependency has its resolved commit SHA recorded, regardless of whether the original declaration used a tag, branch, or SHArecord-checksums— each module's content checksum is computed and recorded, allowing later detection of tampered contentrecord-verification-axes— verification results (eval depth, generator diversity, runtime diversity, applied eval packs) are recorded per format-spec §14detect-tampered-content— verification compares fetched content against recorded checksums; mismatches are reporteddetect-pinned-commit-mismatch— if a tag has moved since the lockfile was created (resolved commit differs from recorded), this is reportedpreserve-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.