Skip to content
zit Update of ”rfc-vector-ledger”
Login

Update of ”rfc-vector-ledger”

Overview

Artifact ID: 8a9c72085c56093ce592bcae38dd7787c49175acd9d2efcb71e13ba05eb2a352
Page Name:rfc-vector-ledger
Date: 2026-08-25 21:26:53
Original User: dmestas
Mimetype:text/x-markdown
Content

The RFC vector ledger pollution

What was wrong

Fossil treats any blob that parses as an artifact as a real one. The RFC conformance vectors in src/rfc_vectors/ are artifact text — that is the whole point of them — so committing them as files handed Fossil 21 live artifacts. Content addressing means the vector file and the artifact were never two things: they were one blob wearing a filename.

The consequences, all of which were visible in this repository:

The last item mattered beyond tidiness. Under draft-fossil-submanifests-00 §8.2 a repository holding an S-bearing artifact is a disposable test fixture, so this repository was formally un-propagatable. And zit import-fossil --submanifest refused to convert it: the rebirth path cannot re-mint a source that already contains tree manifests, and it failed with an exit code and no diagnostic at all.

The fix, in two halves

Guard (check-in 32ef56aaf418, merged as ca7453995e). Every vector gains a leading # block. # is not in the card alphabet, so the bytes no longer parse and Fossil carries them as inert content. src/rfc_vectors.zig strips the block at comptime, so callers still see the exact RFC bytes and every recorded artifact name still verifies. A guarded array holds each vector raw so the tests can assert it fails the §4.1 framing gates.

The guard is not what removes the old artifacts. It is what decouples the working files from them: once a vector hashes differently, the contaminated blob is reachable only from historical revisions, and can be removed without taking the file at tip with it. Renaming the files would not have helped — a blob is named by its content, and the filename lives in the F card.

Shun. The 21 artifact-shaped blobs, then the 2 orphaned phantoms, then fossil rebuild to reclaim. Ordering is not negotiable: shunning before the guard lands destroys the files at tip, which was confirmed experimentally before any of this was applied to a real repository.

Four vectors were left alone. sync_a1_round1_reply, sync_a1_round2_file_cards, sync_a1_round2_reply and sync_a2_reply are wire payloads, not artifacts; they never parsed and were never contaminating anything.

Result

before after blobs 3232 3209 phantoms 2 0 drh timeline 3 0

fossil test-integrity: 3209 non-phantom blobs out of 3209 total, 0 errors.

What it costs

Revisions of those 21 vector files from before the guard commit can no longer be checked out. Their current content is intact and byte-identical to the RFC text once the guard is stripped. Nothing else in the history is affected.

How to not do this again

A file whose bytes are artifact text cannot be committed unguarded. If a new conformance vector is added, it goes through src/rfc_vectors.zig and gets the # block, and the test that asserts every entry of guarded fails the framing gates is what enforces it.