fossil-rfc

Documentation
Login

Documentation





Network Working Group                                    D. R. Hipp, Ed.
Internet-Draft                                                    Fossil
Intended status: Standards Track                                 S. Beal
Expires: 30 January 2027                                       libfossil
                                                              D. Shearer
                                                            29 July 2026


     The Fossil Distributed Version Control System: Artifact Format
                    draft-fossil-artifact-format-00

Abstract

   Fossil is a distributed version-control system that stores a
   project's entire state as a set of immutable, content-addressed
   artifacts.  The artifact format defines artifact naming, card syntax,
   structural artifact types and their validity rules, the two checksum
   computations, the hash policy for new artifact names, and the
   procedure for reconstructing the complete file set of a delta
   manifest.

Status of This Memo

   This Internet-Draft is submitted in full conformance with the
   provisions of BCP 78 and BCP 79.

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF).  Note that other groups may also distribute
   working documents as Internet-Drafts.  The list of current Internet-
   Drafts is at https://datatracker.ietf.org/drafts/current/.

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

   This Internet-Draft will expire on 30 January 2027.

Copyright Notice

   Copyright (c) 2026 IETF Trust and the persons identified as the
   document authors.  All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents (https://trustee.ietf.org/
   license-info) in effect on the date of publication of this document.
   Please review these documents carefully, as they describe your rights
   and restrictions with respect to this document.  Code Components



Hipp, et al.             Expires 30 January 2027                [Page 1]

Internet-Draft           Fossil Artifact Format                July 2026


   extracted from this document must include Revised BSD License text as
   described in Section 4.e of the Trust Legal Provisions and are
   provided without warranty as described in the Revised BSD License.

Table of Contents

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   4
   2.  Conventions and Terminology . . . . . . . . . . . . . . . . .   5
   3.  Artifact Naming . . . . . . . . . . . . . . . . . . . . . . .   6
     3.1.  Name Computation  . . . . . . . . . . . . . . . . . . . .   6
     3.2.  Hash Algorithms and Name Length . . . . . . . . . . . . .   7
     3.3.  Case Handling . . . . . . . . . . . . . . . . . . . . . .   7
     3.4.  Name Verification . . . . . . . . . . . . . . . . . . . .   7
     3.5.  ABNF  . . . . . . . . . . . . . . . . . . . . . . . . . .   8
     3.6.  Prefix Resolution . . . . . . . . . . . . . . . . . . . .   9
   4.  Card Syntax . . . . . . . . . . . . . . . . . . . . . . . . .   9
     4.1.  Artifact Framing  . . . . . . . . . . . . . . . . . . . .   9
       4.1.1.  Signature-Wrapper Removal . . . . . . . . . . . . . .  10
       4.1.2.  Sterilization . . . . . . . . . . . . . . . . . . . .  11
     4.2.  Line and Token Grammar  . . . . . . . . . . . . . . . . .  11
       4.2.1.  Exact Arity . . . . . . . . . . . . . . . . . . . . .  11
       4.2.2.  Closed Card Alphabet  . . . . . . . . . . . . . . . .  12
     4.3.  Character-Escape Encoding . . . . . . . . . . . . . . . .  12
       4.3.1.  Decoded Token Positions . . . . . . . . . . . . . . .  13
     4.4.  Card Ordering . . . . . . . . . . . . . . . . . . . . . .  13
     4.5.  Occurrence Classes and Intra-Type Ordering  . . . . . . .  14
       4.5.1.  Occurrence Classes  . . . . . . . . . . . . . . . . .  14
       4.5.2.  Intra-Run Ordering of Repeatable Cards  . . . . . . .  14
       4.5.3.  The Canonical Comparator  . . . . . . . . . . . . . .  15
     4.6.  Validity Predicates . . . . . . . . . . . . . . . . . . .  16
       4.6.1.  Simple-Pathname Predicate . . . . . . . . . . . . . .  16
       4.6.2.  Wiki-Name Predicate . . . . . . . . . . . . . . . . .  17
       4.6.3.  Reserved Filenames  . . . . . . . . . . . . . . . . .  17
       4.6.4.  Timestamps  . . . . . . . . . . . . . . . . . . . . .  18
     4.7.  Per-Card Grammars . . . . . . . . . . . . . . . . . . . .  19
       4.7.1.  Hash-Token Validation Map . . . . . . . . . . . . . .  19
       4.7.2.  A Card  . . . . . . . . . . . . . . . . . . . . . . .  20
       4.7.3.  B Card  . . . . . . . . . . . . . . . . . . . . . . .  21
       4.7.4.  C Card  . . . . . . . . . . . . . . . . . . . . . . .  21
       4.7.5.  D Card and E Card . . . . . . . . . . . . . . . . . .  21
       4.7.6.  F Card  . . . . . . . . . . . . . . . . . . . . . . .  22
       4.7.7.  G Card, H Card, and I Card  . . . . . . . . . . . . .  22
       4.7.8.  J Card  . . . . . . . . . . . . . . . . . . . . . . .  23
       4.7.9.  K Card  . . . . . . . . . . . . . . . . . . . . . . .  23
       4.7.10. L Card  . . . . . . . . . . . . . . . . . . . . . . .  23
       4.7.11. M Card  . . . . . . . . . . . . . . . . . . . . . . .  24
       4.7.12. N Card  . . . . . . . . . . . . . . . . . . . . . . .  24
       4.7.13. P Card  . . . . . . . . . . . . . . . . . . . . . . .  24



Hipp, et al.             Expires 30 January 2027                [Page 2]

Internet-Draft           Fossil Artifact Format                July 2026


       4.7.14. Q Card  . . . . . . . . . . . . . . . . . . . . . . .  25
       4.7.15. R Card  . . . . . . . . . . . . . . . . . . . . . . .  25
       4.7.16. T Card  . . . . . . . . . . . . . . . . . . . . . . .  25
       4.7.17. U Card  . . . . . . . . . . . . . . . . . . . . . . .  26
       4.7.18. W Card  . . . . . . . . . . . . . . . . . . . . . . .  26
       4.7.19. Z Card  . . . . . . . . . . . . . . . . . . . . . . .  27
   5.  Structural Artifact Types . . . . . . . . . . . . . . . . . .  27
     5.1.  Type Codes and Names  . . . . . . . . . . . . . . . . . .  27
     5.2.  Card Legality by Type . . . . . . . . . . . . . . . . . .  28
     5.3.  Type Determination  . . . . . . . . . . . . . . . . . . .  29
     5.4.  Per-Type Semantic Checks  . . . . . . . . . . . . . . . .  30
     5.5.  Well-Formedness Pre-Filter  . . . . . . . . . . . . . . .  31
   6.  Checksums . . . . . . . . . . . . . . . . . . . . . . . . . .  31
     6.1.  Digest Token Grammar  . . . . . . . . . . . . . . . . . .  31
     6.2.  Z Card: Artifact Self-Checksum  . . . . . . . . . . . . .  32
     6.3.  R Card: Aggregate Content Checksum  . . . . . . . . . . .  33
       6.3.1.  Parse-Time Handling . . . . . . . . . . . . . . . . .  33
       6.3.2.  R-Card Computation  . . . . . . . . . . . . . . . . .  33
       6.3.3.  Delta Manifests . . . . . . . . . . . . . . . . . . .  34
       6.3.4.  Emitted Form  . . . . . . . . . . . . . . . . . . . .  34
   7.  Hash Policy . . . . . . . . . . . . . . . . . . . . . . . . .  34
     7.1.  Policy Values . . . . . . . . . . . . . . . . . . . . . .  34
     7.2.  Default Policy  . . . . . . . . . . . . . . . . . . . . .  35
     7.3.  Assigning the Policy  . . . . . . . . . . . . . . . . . .  36
     7.4.  Automatic Promotion (Ratchet) . . . . . . . . . . . . . .  36
     7.5.  Cross-Algorithm Deduplication . . . . . . . . . . . . . .  37
     7.6.  Name Immutability . . . . . . . . . . . . . . . . . . . .  37
     7.7.  Synchronisation Behaviour . . . . . . . . . . . . . . . .  37
   8.  Delta Manifest Reconstruction . . . . . . . . . . . . . . . .  38
     8.1.  Preconditions . . . . . . . . . . . . . . . . . . . . . .  38
     8.2.  Full File-Set Enumeration (Merge-Walk)  . . . . . . . . .  38
     8.3.  Baseline Resolution . . . . . . . . . . . . . . . . . . .  39
     8.4.  Single-Name Lookup  . . . . . . . . . . . . . . . . . . .  40
     8.5.  Renderings That Intentionally Do Not Reconstruct  . . . .  40
   9.  Security Considerations . . . . . . . . . . . . . . . . . . .  40
   10. IANA Considerations . . . . . . . . . . . . . . . . . . . . .  42
   11. References  . . . . . . . . . . . . . . . . . . . . . . . . .  42
     11.1.  Normative References . . . . . . . . . . . . . . . . . .  42
     11.2.  Informative References . . . . . . . . . . . . . . . . .  43
   Appendix A.  Examples . . . . . . . . . . . . . . . . . . . . . .  44
     A.1.  Artifact Naming . . . . . . . . . . . . . . . . . . . . .  44
       A.1.1.  SHA-1 Example . . . . . . . . . . . . . . . . . . . .  44
       A.1.2.  SHA3-256 Example  . . . . . . . . . . . . . . . . . .  45
     A.2.  Z-Card Checksum . . . . . . . . . . . . . . . . . . . . .  45
     A.3.  R-Card Aggregate Checksum . . . . . . . . . . . . . . . .  46
     A.4.  Delta Manifest  . . . . . . . . . . . . . . . . . . . . .  47
       A.4.1.  Baseline Manifest . . . . . . . . . . . . . . . . . .  47
       A.4.2.  Example Delta Manifest  . . . . . . . . . . . . . . .  48



Hipp, et al.             Expires 30 January 2027                [Page 3]

Internet-Draft           Fossil Artifact Format                July 2026


       A.4.3.  Merge Algorithm . . . . . . . . . . . . . . . . . . .  48
       A.4.4.  R-card Over Reconstructed Set . . . . . . . . . . . .  49
   Appendix B.  ABNF . . . . . . . . . . . . . . . . . . . . . . . .  50
   Appendix C.  Anomalous artifacts and behaviours . . . . . . . . .  52
   Authors' Addresses  . . . . . . . . . . . . . . . . . . . . . . .  54

1.  Introduction

   Fossil is a distributed version control system.  A participant can
   verify what a project contained at any point in its history, then
   reconcile that history with other repository copies.  Fossil does
   this by storing project state as immutable, content-addressed
   _artifacts_. An artifact is a byte sequence named by the
   cryptographic hash of its content.  Repository state is the unordered
   set of artifacts it contains: addition order does not matter, and two
   repositories holding the same set represent the same project state.

   Artifacts are of two kinds.  A content artifact is an arbitrary byte
   sequence, such as the contents of a file under version control.  A
   structural artifact is a text document built from cards (Section 4)
   that records relationships among artifacts: a check-in, a wiki page,
   a ticket change, and the other types enumerated in Section 5.  Both
   kinds are named and stored the same way; a reader distinguishes them
   by attempting a structural parse.

   A repository also holds local state, such as user accounts,
   configuration settings, and the mapping from artifact names to local
   storage.  Local state is outside the artifact model and is not
   content-addressed.  This document specifies the artifact model only.
   Content may be held or transferred in delta-encoded form
   [FossilDelta]; delta encoding is a storage and transfer concern and
   does not change an artifact's bytes or its name.

   The artifact set has the properties of a grow-only set, a convergent
   replicated data type [GSET].  Artifacts are added but never modified
   or removed as part of normal operation; the name of an artifact is a
   function of its content, so an artifact received from any source is
   identical to the same artifact held locally.  Two repositories
   converge by exchanging the artifacts each lacks; the synchronisation
   procedure is specified in [FossilSync].

   The rules cover naming (Section 3), card syntax (Section 4),
   structural artifact types (Section 5), the Z card and R card
   checksums (Section 6), the hash policy for new artifact names
   (Section 7), and reconstruction of a delta manifest's file set
   (Section 8).  The appendices record divergent statements in existing
   documentation (Appendix C), give worked examples (Appendix A), and
   collect the ABNF (Appendix B).



Hipp, et al.             Expires 30 January 2027                [Page 4]

Internet-Draft           Fossil Artifact Format                July 2026


   The companion Fossil Repository State specification [FossilRepoState]
   defines the repository-state views computed over these artifacts.
   Those views are branch and tag membership, leaves, closed markers,
   and the current-trunk check-in.  This document defines the artifact
   bytes, cards, and checksums from which they are computed.

   The requirements appear in Section 3 through Section 8.

2.  Conventions and Terminology

   The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
   "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
   "OPTIONAL" in this document are to be interpreted as described in
   BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
   capitals, as shown here.

   These terms form the core artifact-model vocabulary for the Fossil
   specification suite.  The Fossil Delta Format [FossilDelta], the
   Fossil Sync Protocol [FossilSync], and the Fossil Repository State
   specification [FossilRepoState] reuse these terms without restating
   them.  Where one of those documents uses a term such as _artifact_,
   _card_, _manifest_, or _hash_ without defining it, the definition is
   here.

   The terms delta, source, and target are used as defined in
   [FossilDelta].

   Artifact:  An immutable byte sequence named by the cryptographic hash
      of its content.

   Hash (artifact name):  The cryptographic digest of an artifact's
      content that serves as the artifact's name.  The permitted
      algorithms, and the policy governing which hash algorithm names a
      new artifact, are specified in Section 3 and Section 7.

   Content artifact:  An artifact whose bytes carry no structure defined
      by this document.

   Structural artifact:  An artifact that parses as a sequence of cards
      under the rules of Section 4 and Section 5.

   Card:  One line of a structural artifact: a card-type letter followed
      by zero or more space-separated tokens.

   Token:  A maximal run of octets within a card containing neither
      space (0x20) nor LF (0x0A).

   Decoded form:  The value of a token after character-escape decoding



Hipp, et al.             Expires 30 January 2027                [Page 5]

Internet-Draft           Fossil Artifact Format                July 2026


      (Section 4.3).

   Stripped content:  The bytes of an artifact after signature-wrapper
      removal (Section 4.1.1).

   Manifest:  The structural artifact type that records a check-in.

   Baseline manifest:  A manifest without a B card; its F cards carry
      its complete file set.

   Delta manifest:  A manifest with a B card; its F cards record
      differences against the baseline manifest the B card names
      (Section 8).

   Check-in:  A snapshot of a project's files at one point in its
      history, together with the check-in's parent relationships.  A
      check-in is recorded by a manifest (Section 5).  The graph of
      check-ins, and the branch, tag, leaf, and current-trunk views
      derived from it, are specified in [FossilRepoState].

3.  Artifact Naming

3.1.  Name Computation

   An artifact's name is the cryptographic hash of the artifact's
   complete raw bytes, computed over the byte sequence as a single
   undifferentiated blob.  No prefixes, suffixes, or other information
   may be added to an artifact before its hash is computed, and no
   canonicalization, encoding transform, or signature stripping is
   applied: the bytes hashed MUST be exactly the artifact's stored
   bytes, undisturbed.  For a signed structural artifact the stored
   bytes include the signature wrapper (Section 4.1.1), so the name
   covers the wrapper.

   When content is ingested together with an already-known name, the
   receiver's storage operation uses that supplied name as the candidate
   storage name rather than first recomputing a new one.  Verifying that
   the candidate name matches the content is a distinct caller
   responsibility from assigning a name at ingest time (Section 3.4);
   the hash policy ratchet observes the candidate name selected for
   storage (Section 7.4), and Section 9 discusses the consequences when
   a receive path stores before it can verify.









Hipp, et al.             Expires 30 January 2027                [Page 6]

Internet-Draft           Fossil Artifact Format                July 2026


3.2.  Hash Algorithms and Name Length

   Exactly two artifact-name forms exist: a 40-hexadecimal-digit name,
   which denotes a SHA-1 hash [RFC3174], and a 64-hexadecimal-digit
   name, which denotes a SHA3-256 hash [FIPS202].  A candidate name of
   any other length MUST be rejected as invalid, and this length check
   applies before any character-class validation.  Because the two
   lengths are disjoint, the hash algorithm of any artifact name is
   fully determined by its length alone; validation, verification, and
   algorithm display all dispatch on length with no other algorithm
   indicator.

   The 64-character form is the SHA3-256 of [FIPS202] -- the variant
   with the 01 domain-separation padding, distinct from the original
   Keccak submission -- computed over the raw artifact bytes and encoded
   as lowercase hexadecimal.  The 40-character form is SHA-1 computed
   over the same bytes and encoded the same way.  Which algorithm names
   newly stored content is governed by the repository hash policy
   (Section 7).

3.3.  Case Handling

   Case handling is asymmetric between the producing and accepting
   sides.  Every name a conforming implementation computes and emits
   MUST use lowercase hexadecimal digits; the artifact name is the
   lowercase hexadecimal encoding of the raw artifact's hash.  A name
   that contains an uppercase hexadecimal digit is therefore invalid: no
   conforming artifact bears one, and such a token can never verify
   against content (Section 3.4).  Because a valid name is always
   lowercase, an implementation MAY reject an uppercase-hex token at
   name validation, or MAY accept it there and let it fail at
   verification; the two are interoperable, because conforming data
   never contains an uppercase name.  A parser that accepts uppercase
   hexadecimal at name validation MUST NOT case-normalize it there.

3.4.  Name Verification

   Verification of a name against content dispatches on length alone: a
   40-character name is compared against the SHA-1 digest of the
   content, a 64-character name against the SHA3-256 digest, and a name
   of any other length never verifies.  The comparison is a byte-for-
   byte match of the candidate name against the digest rendered as
   lowercase hexadecimal.  An uppercase-hexadecimal name is not a valid
   artifact name and never verifies against content.  A token-validation
   stage MAY reject it, or MAY accept it and let verification fail;
   every content-verification comparison is exact-lowercase, so an
   uppercase name cannot pass either way.




Hipp, et al.             Expires 30 January 2027                [Page 7]

Internet-Draft           Fossil Artifact Format                July 2026


   Verification yields a single undifferentiated failure signal: a wrong
   length, a non-hexadecimal character, and a digest mismatch are
   indistinguishable to the caller.

   Receive-side handling of a caller-supplied name follows this order:

   1.  The receiver parses the supplied token as an artifact name and
       selects it as the candidate storage name.

   2.  The normal non-clone sync file path, after reconstructing the
       full artifact bytes from any available delta source, verifies the
       candidate name before its storage call and before successful
       receive admission.  If verification fails, the receive path
       reports an error and the artifact MUST NOT be treated as verified
       under that name.  This is a caller-path responsibility, not
       behaviour supplied by the storage primitive.

   3.  Clone file, compressed cfile, and non-clone dangling-delta paths
       can store the candidate name without first verifying the complete
       reconstructed bytes.  Those paths rely on later reconstruction,
       recoverability, or commit-time checks when the required content
       becomes available.  Storage under a candidate name is not itself
       evidence that the supplied name has verified.

   4.  The storage operation then uses the selected candidate name for
       duplicate lookup, insertion or dephantomization, and any hash-
       policy ratchet described in Section 7.4.

3.5.  ABNF

   The canonical (writer) grammar and the parser accept-grammar are as
   follows:

   lhexdig        = DIGIT / %x61-66     ; 0-9 / a-f (lowercase)
   hexdig-ci      = DIGIT / %x41-46 / %x61-66 ; 0-9 / A-F / a-f

   ; Canonical form: what writers MUST produce
   artifact-name  = sha1-name / sha3-name
   sha1-name      = 40lhexdig
   sha3-name      = 64lhexdig

   ; Accept form: parser-tolerated (reference form); acceptance is not
   ; a conformance requirement -- see the prose above
   accepted-name  = 40hexdig-ci / 64hexdig-ci







Hipp, et al.             Expires 30 January 2027                [Page 8]

Internet-Draft           Fossil Artifact Format                July 2026


3.6.  Prefix Resolution

   This section is informative: prefix lookup is a local name-resolution
   convenience and is not part of the artifact wire format.

   Resolution of a hexadecimal name or name prefix to an artifact is
   uniform across both hash lengths.  A lookup accepts any hexadecimal
   string of 4 to 64 characters, lowercases it before matching (so
   uppercase input is canonicalized on the lookup path, in contrast to
   the parse path), and resolves it with a prefix-match query over
   artifact names that does not branch on the 40-versus-64 distinction.
   If more than one artifact matches the prefix, the lookup reports an
   ambiguous name; a cross-algorithm collision, where one matching
   artifact is SHA-1-named and the other SHA3-named, is reported
   identically to a same-algorithm collision.  Fossil also has a broader
   diagnostic collision helper that counts artifact names, ticket
   identifiers, and event-tag prefixes together, but that helper is
   separate from artifact prefix resolution.

4.  Card Syntax

   This section defines the syntax of structural artifacts: framing,
   signature-wrapper removal, the line and token grammar, the character-
   escape encoding, card ordering, occurrence rules, the validity
   predicates, and the per-card grammars.

4.1.  Artifact Framing

   A parser MUST evaluate the following gates, in this order, before
   interpreting any card:

   1.  The input MUST be non-empty and its final byte MUST be LF (0x0A).
       This gate is evaluated on the raw input bytes, before signature-
       wrapper removal; a signed artifact must therefore end its outer
       signature wrapper with LF.

   2.  Signature wrappers, when present, are removed (Section 4.1.1).
       When a trailing signature block is found and removed, the
       remaining content also ends in LF, because the truncation retains
       the LF immediately preceding the signature armor.

   3.  Line 1 of the stripped content is held to a stricter standard
       than the general card grammar: the stripped content MUST be at
       least 10 bytes long, its first byte MUST be an uppercase letter
       in the range A-Z, and its second byte MUST be a single space.  An
       argument-less first card is rejected here even though the general
       card grammar permits argument-less cards elsewhere.




Hipp, et al.             Expires 30 January 2027                [Page 9]

Internet-Draft           Fossil Artifact Format                July 2026


   4.  The Z card self-checksum of the stripped content is verified
       (Section 6.2).  A present-but-mismatched Z card MUST cause
       rejection; an absent Z card passes this gate (absence is caught
       later by the required-card rule of Section 5.2).

   After the card loop completes, any unconsumed bytes MUST cause
   rejection.

4.1.1.  Signature-Wrapper Removal

   A reader MUST remove both PGP clearsign wrappers (-----BEGIN PGP
   SIGNED MESSAGE----- ... -----BEGIN PGP SIGNATURE-----) and SSH signed
   wrappers (-----BEGIN SSH SIGNED MESSAGE----- ... -----BEGIN SSH
   SIGNATURE-----) before parsing.  The exact mechanics are:

   1.  Stripping occurs only when the first 34 bytes of the input, at
       offset 0, exactly match -----BEGIN PGP SIGNED MESSAGE----- or
       -----BEGIN SSH SIGNED MESSAGE-----.

   2.  The body begins at the first position preceded by a blank line,
       where "blank line" is detected as either LF LF or LF CR LF --
       this CR tolerance is the only CR handling anywhere in the parse
       pipeline.  If no blank line is found before end of input, the
       content is left wholly unstripped.

   3.  A backward scan truncates the content at the first occurrence of
       <LF>-----BEGIN PGP SIGNATURE----- or <LF>-----BEGIN SSH
       SIGNATURE-----, retaining the matched LF as the final byte.
       Absent a match, the content runs to end of input.

   The trailing-armor literals are 30 bytes, but only 29 bytes are
   compared, so an armor line one dash short (...SIGNATURE----) followed
   by any byte also matches.

   Compatibility note: Receivers that do not recognise the SSH prefix
   leave the leading -----BEGIN... bytes in place, so the artifact fails
   the line-1 gate of Section 4.1 and is treated as an opaque content
   artifact rather than a structural artifact.  The SSH armor is
   assembled around an external detached signature.  Existing
   documentation describes only the PGP form (Appendix C).











Hipp, et al.             Expires 30 January 2027               [Page 10]

Internet-Draft           Fossil Artifact Format                July 2026


4.1.2.  Sterilization

   This subsection is informative.  To render content deliberately
   unparseable as a structural artifact, a writer inserts a comment line
   beginning with # (of the form # Remove this line to create a well-
   formed Fossil artifact.) as the first line, which causes the line-1
   gate of Section 4.1 to fail.  For PGP- or SSH-signed content, the
   marker line is instead spliced in immediately before the signature
   block, with the boundary recomputed by the same wrapper-detection
   logic of Section 4.1.1, so the signature remains trailing.

   An implementation providing both a fast well-formedness probe and a
   full parser SHOULD ensure the two return identical verdicts on every
   input.

4.2.  Line and Token Grammar

   Cards are one per line, with a single exception: the W card body
   (Section 4.7.18) may contain embedded LF bytes.  The wire grammar of
   a card is:

   card        = card-letter ( SP card-args LF / LF )
   card-letter = %x41-5A          ; A-Z; 21 letters defined
   card-args   = token *( SP token )
   token       = 1*tchar
   tchar       = %x00-09 / %x0B-1F / %x21-FF
                 ; any octet except SP (0x20) and LF (0x0A)

   The byte immediately following the card-type letter MUST be exactly
   one space (0x20, arguments follow) or LF (argument-less card).  Any
   other second byte -- including tab (0x09) -- makes the card invalid.
   Tokens are split on space and LF only; tab is not a delimiter and is
   retained as literal token content.  Consequently a token can never
   contain an embedded space.  There is no CR (0x0D) handling in the
   card and token path -- a CR is an ordinary token byte; the sole CR
   tolerance in the pipeline is the blank-line detection of
   Section 4.1.1.

4.2.1.  Exact Arity

   Every card's positional grammar in Section 4.7 is exact, an upper
   bound as well as a minimum.  A card line that carries more tokens
   than its grammar defines MUST cause rejection of the whole artifact.
   This one rule enforces maximum arity for every fixed-arity card (a
   second token on B, C, G, H, I, K, L, N, R, U, W, or Z; a third on J;
   a third on the two-token form of Q; a fourth on A; a fifth on F) and
   equally rejects residual bytes after the final card.




Hipp, et al.             Expires 30 January 2027               [Page 11]

Internet-Draft           Fossil Artifact Format                July 2026


4.2.2.  Closed Card Alphabet

   Exactly 21 card letters are defined: A, B, C, D, E, F, G, H, I, J, K,
   L, M, N, P, Q, R, T, U, W, Z.  A card letter outside A-Z MUST be
   rejected; an in-range but undefined letter (O, S, V, X, Y) MUST be
   rejected.  The card alphabet is closed: there is no forward-
   compatibility acceptance path for unknown card letters.

4.3.  Character-Escape Encoding

   Tokens that carry free text are encoded so that they contain no
   delimiter bytes.  The decoder MUST recognise exactly eight backslash
   escape pairs, decoded in place:

                       +========+==================+
                       | Escape | Decoded octet    |
                       +========+==================+
                       | \n     | LF (0x0A)        |
                       +--------+------------------+
                       | \s     | SP (0x20)        |
                       +--------+------------------+
                       | \t     | TAB (0x09)       |
                       +--------+------------------+
                       | \r     | CR (0x0D)        |
                       +--------+------------------+
                       | \v     | VT (0x0B)        |
                       +--------+------------------+
                       | \f     | FF (0x0C)        |
                       +--------+------------------+
                       | \0     | NUL (0x00)       |
                       +--------+------------------+
                       | \\     | backslash (0x5C) |
                       +--------+------------------+

                                  Table 1

   For any other character following a backslash, the decoder discards
   the backslash and emits the following character unchanged.  A
   backslash followed by an unrecognised character C decodes to the
   single byte C.  No error is raised.  A backslash that is the final
   byte of a token has no following character and introduces no escape
   pair; the decoder emits the backslash (0x5C) unchanged.  As with an
   unrecognised escape, no error is raised.








Hipp, et al.             Expires 30 January 2027               [Page 12]

Internet-Draft           Fossil Artifact Format                July 2026


4.3.1.  Decoded Token Positions

   The decoder applies at exactly 12 token positions across 9 card
   letters: the A card filename and target (but not the source hash);
   the C card comment; the F card filename always, and the old-name when
   present (but never the hash or permission tokens); the H card thread
   title; the J card value only (not the field name); the L card wiki
   title; the N card mimetype; the T card value (if present) and tag
   name (but not the target hash); and the U card login, when non-empty.
   All hash and checksum tokens (B, the E card identifier, the F card
   hash, G, I, K, M, P, Q, R, the T card target, Z), both timestamps (D,
   E), and the W card size and body are never decoded.

   The A card target is the one hash-bearing position that is escape-
   decoded before validation, because the same position may
   alternatively hold an encoded wiki name (Section 4.7.2).  Validation
   applies to the decoded value, not the wire token.  Because an
   unrecognised escape decodes to the single character following the
   backslash, a wire token containing backslash escapes MAY decode to a
   value that is entirely hexadecimal; that decoded value is validated
   as an artifact hash exactly as an unescaped hexadecimal token would
   be.  A pure-hexadecimal wire token decodes to itself.

   The compatibility divergences around decoded token positions are
   recorded in Appendix C.

4.4.  Card Ordering

   Cards within a structural artifact MUST appear in non-decreasing
   lexicographic card-type order: each card's type letter MUST be
   greater than or equal to the previous card's type letter.  The
   rejection condition fires only when a card's letter sorts below the
   previous card's letter, so consecutive cards of the same type letter
   are permitted -- this is what allows repeatable card types.  The
   ordering is non-decreasing, not strictly increasing, at the card-type
   level.

   One compatibility exception is normative: an N card MAY appear
   immediately after a P card when the artifact has already presented a
   valid E card.  A parser MUST accept that sequence, and any other out-
   of-order card MUST be rejected.  The exception is observable at the
   moment the out-of-order N card is encountered: the artifact is a
   technote.  The historical divergence that motivates this exception is
   recorded in Appendix C.

   Two structural consequences follow:





Hipp, et al.             Expires 30 January 2027               [Page 13]

Internet-Draft           Fossil Artifact Format                July 2026


   *  *B precedes F.* Because B < F, any B card is always parsed before
      every F card in the same artifact.  The baseline reference is thus
      fully settled (present or absent) by the time each F card's
      conditional hash-required check runs, so the delta/baseline
      distinction is decidable in a single forward pass.

   *  *Nothing follows Z.* Z is the lexicographically last defined
      letter, the ordering rule admits no letter after it (the N-after-P
      exception does not involve Z), and the checksum-verification
      framing fixes the Z card as occupying exactly the final 35 bytes
      of the stripped content: Z, space, 32 hexadecimal digits, LF.  The
      Z card's must-be-last property is enforced structurally -- by
      ordering plus byte-position framing -- rather than by an explicit
      last-card check in the Z card grammar, which validates only token
      syntax.

4.5.  Occurrence Classes and Intra-Type Ordering

4.5.1.  Occurrence Classes

   Twenty of the 21 card types divide into two classes:

   *  *Single-occurrence* (a duplicate MUST be rejected): A, B, C, D, E,
      G, H, I, K, L, N, R, U, W.

   *  *Repeatable* (each occurrence appends to the artifact's growing
      list for that type): F, J, M, T, P, Q.

   It is not the case that any duplicate card type is a syntax error;
   the rule is per-class as above.

   The Z card, the 21st letter, belongs to neither class.  It has no
   duplicate guard, and the ordering rule permits equal consecutive
   letters.  No separate rule requires the Z card to be exactly one and
   last; that property follows from the framing.  Checksum verification
   examines only the final 35 bytes of the stripped content
   (Section 4.4), so any earlier Z line is simply content covered by the
   final checksum.

4.5.2.  Intra-Run Ordering of Repeatable Cards

   The repeatable card types carry distinct per-list sort rules, each
   enforced with the byte-wise comparator of Section 4.5.3:








Hipp, et al.             Expires 30 January 2027               [Page 14]

Internet-Draft           Fossil Artifact Format                July 2026


      +======+=====================================================+
      | Type | Intra-run rule                                      |
      +======+=====================================================+
      | F    | Strictly ascending by decoded filename (equal or    |
      |      | descending rejected)                                |
      +------+-----------------------------------------------------+
      | J    | Strictly ascending by field name (equal or          |
      |      | descending rejected)                                |
      +------+-----------------------------------------------------+
      | M    | Strictly ascending by hash (equal or descending     |
      |      | rejected)                                           |
      +------+-----------------------------------------------------+
      | T    | Two-level ascending by (tag name, then target       |
      |      | hash); equal names require strictly increasing hash |
      +------+-----------------------------------------------------+
      | P    | Not sorted or deduplicated; order is semantic       |
      |      | (primary parent first)                              |
      +------+-----------------------------------------------------+
      | Q    | No duplicate guard or ordering check; unordered-    |
      |      | repeatable                                          |
      +------+-----------------------------------------------------+

                                 Table 2

   F card ordering in detail: entries MUST be in strict ascending sort
   order by the decoded filename within a single manifest or delta
   manifest.  The check rejects both duplicates and descending pairs and
   runs on the post-decode filename, not on the raw wire-encoded token
   (decoding happens before the sort check).  This per-list ordering is
   independent of, and in addition to, the card-type ordering of
   Section 4.4; it underlies the binary search into a baseline's file
   list and the merge walk that materializes a delta manifest against
   its baseline (Section 8.2).

4.5.3.  The Canonical Comparator

   A single comparison function governs the F, J, M, and T sort checks,
   the delta-baseline merge walk (Section 8.2), and single-name search
   (Section 8.4): a raw-byte comparison in which octets are compared as
   unsigned values, locale-independent, with no Unicode normalisation
   and no case folding.  A shorter string sorts before any extension of
   itself, and an absent value sorts before any present value.  The
   directory separator / (0x2F) receives no special treatment.

   The R card has no comparator role: it is a single 32-character
   hexadecimal token with no ordering semantics.  "Filename order" in
   the R card computation (Section 6.3) means the file-enumeration order
   under this same comparator.



Hipp, et al.             Expires 30 January 2027               [Page 15]

Internet-Draft           Fossil Artifact Format                July 2026


   Writers emit F cards by iterating files in the same ascending byte-
   wise pathname order the parser enforces, and independent
   implementations agree on unsigned-octet, locale-free, case-sensitive
   ordering.

4.6.  Validity Predicates

   Three predicates named by the per-card grammars are defined here.
   Each operates on the decoded form of its token, treated as a sequence
   of unsigned octets.

4.6.1.  Simple-Pathname Predicate

   The pathname predicate applies to the A card filename and to the F
   card filename and old-name.  A parser MUST reject the decoded name if
   and only if any of the following holds:

   *  it is empty;

   *  its first byte is /;

   *  the whole string is . or ..;

   *  it begins with ./ or ../;

   *  it contains //;

   *  it ends with /;

   *  any path element equals . or .. -- that is, it contains /./ or
      /../, or ends with /. or /...

   The predicate imposes no other byte-content restriction: backslashes,
   spaces (reachable via \s decoding), control bytes, and arbitrary or
   invalid UTF-8 sequences all pass.  Accept or reject is decidable from
   the separator structure alone.

   A writer is held to a stricter profile when creating new filenames.
   In addition to the rules above, a writer MUST NOT emit a filename
   containing a backslash, and MUST emit valid UTF-8, excluding: invalid
   or stray continuation bytes, overlong encodings, characters above
   U+FFFF, surrogates U+D800 through U+DFFF, private-use characters
   U+E000 through U+F8FF, and the noncharacters U+FDD0 through U+FDEF
   and U+FFFE through U+FFFF.  A validator of existing artifacts MUST
   apply only the parser rules; the writer profile does not constrain
   acceptance.





Hipp, et al.             Expires 30 January 2027               [Page 16]

Internet-Draft           Fossil Artifact Format                July 2026


4.6.2.  Wiki-Name Predicate

   The wiki-name predicate applies to the L card title and to the A card
   target in its wiki-name alternative.  A parser MUST reject the
   decoded name if and only if any of the following holds:

   *  its first byte is less than or equal to 0x20 (this rejects the
      empty string, a leading space, and any leading control byte);

   *  any subsequent byte is less than 0x20 (all control bytes,
      including tab and LF);

   *  two consecutive space bytes (0x20 0x20) appear anywhere;

   *  its final byte is a space (0x20);

   *  its total length in bytes is outside 1 through 100 inclusive.

   All bytes greater than or equal to 0x21 are otherwise unconstrained:
   0x7F and all bytes at or above 0x80 are accepted, no UTF-8 validity
   check is performed, and length is counted in bytes, not characters.

4.6.3.  Reserved Filenames

   A decoded current F-card filename is reserved if and only if the
   following deterministic predicate matches:

   1.  Start with the decoded filename.  If it ends, case-insensitively,
       with exactly one of -wal, -shm, or -journal, strip that one
       suffix for the rest of this predicate and record that a sidecar
       suffix was stripped.

   2.  The remaining string ends, case-insensitively, with either
       _FOSSIL_ (8 bytes) or .fslckout (9 bytes).

   3.  At least one of the following is true: the reserved tail is the
       entire remaining string; the byte immediately before the tail is
       /; or a sidecar suffix was stripped in step 1.

   A tail match that satisfies none of step 3, such as x_FOSSIL_, is not
   reserved.  A sidecar-suffix match such as x_FOSSIL_-wal or
   dir/.fslckout-journal is reserved because step 1 stripped a suffix.
   The predicate is limited to Fossil repository metadata filenames; it
   does not include platform checkout filters or Windows device names
   such as CON.






Hipp, et al.             Expires 30 January 2027               [Page 17]

Internet-Draft           Fossil Artifact Format                July 2026


   This rule applies only to the current filename field of an F card,
   after escape decoding.  The old-name field is not tested by this
   reserved-name rule.

   An F card whose decoded current filename is reserved MUST be silently
   dropped, not rejected.  Dropping removes the card from the effective
   file set.  In the Fossil reference parser, the drop occurs before the
   F card sets the artifact type to MANIFEST.  A reserved-name F card
   therefore does not itself make an otherwise untyped artifact a
   manifest; such an artifact can later fall through to another type and
   fail the allowed-card or required-card checks.  Such names leaked
   into historical manifests, and existing documentation contains no
   mention of this behaviour (Appendix C); the drop alters the effective
   file set of affected historical manifests (Section 9).

   Sequencing: the F card sort check (Section 4.5.2) runs before the
   reserved-name drop, so a reserved-named F card must itself be in sort
   position relative to the previously retained entry, and the next F
   card is compared against that same retained entry.  The dropped name
   never becomes the comparison anchor.  A validator that checks order
   before dropping reproduces this behaviour exactly.

4.6.4.  Timestamps

   The D and E card timestamps are each a single raw (never decoded)
   token.  A writer emits the combined date-time form:

   timestamp = date %x54 time [ frac ]   ; %x54 = "T"
   date      = 4DIGIT "-" 2DIGIT "-" 2DIGIT
   time      = 2DIGIT ":" 2DIGIT ":" 2DIGIT
   frac      = "." 1*DIGIT

   A parser accepts a broader set of forms.  The accepted grammar for
   the token is:

   1.  A date-time: an optional leading -, then YYYY-MM-DD, then one or
       more separator bytes each of which is either a whitespace-class
       byte or the uppercase letter T, then HH:MM, HH:MM:SS, or
       HH:MM:SS. followed by one or more digits, then an optional
       timezone of optional whitespace plus +HH:MM, -HH:MM, Z, or z.
       Lowercase t as the separator is rejected.  Because the token is
       space-delimited on the wire and never decoded, T is the only
       usable date-time separator in an artifact (a literal tab inside
       the token would also satisfy the whitespace class).

   2.  A date only: optional leading -, then YYYY-MM-DD.





Hipp, et al.             Expires 30 January 2027               [Page 18]

Internet-Draft           Fossil Artifact Format                July 2026


   3.  A time only: HH:MM, optionally :SS and a fraction, interpreted as
       a time on 2000-01-01.

   4.  The literals now, subsec, or subsecond, case-insensitive.

   5.  A bare decimal number, treated as a Julian day number when its
       value r satisfies 0 < r < 5373484.5.  Field constraints, with
       exact digit counts: the year is exactly 4 digits, the month
       exactly 2 digits in 01-12, the day exactly 2 digits in 01-31 with
       no calendar-aware check (2024-02-31 is accepted), the hour 2
       digits in 00-24, the minute and second 2 digits each in 00-59,
       and the fraction one or more digits.

   Finally: a date or date-time token MUST denote a date strictly after
   -4713-11-24 -- its (year, month, day) lexicographically greater than
   (-4713, 11, 24), independent of any time-of-day component -- and a
   bare Julian-day-number token MUST be greater than zero.
   Equivalently, the numeric token 0 and every date at or before
   -4713-11-24 are rejected.

   Compatibility admission is broader than interoperable output.  For
   stored structural artifacts whose D or E card timestamp can feed
   repository-state ordering, a producer MUST emit the absolute date-
   time form above.  A reader MAY accept the broader forms in items 2
   through 5 for compatibility.

   In particular, now, subsec, and subsecond are resolved against parse-
   time clock state rather than denoting a stable instant in the
   artifact bytes.  Two ingestions of identical bytes can therefore
   yield different stored mtime values.  The ordering rules in
   [FossilRepoState] apply to the stored numeric mtime produced by
   parsing, not to the literal token text, so these relative literals
   are parser-compatibility admissions outside conforming repository-
   state semantics.

4.7.  Per-Card Grammars

4.7.1.  Hash-Token Validation Map

   Every artifact-hash-bearing position -- the A card target (as one of
   its two alternatives), the A card source, B, the E card identifier,
   the F card hash, G, I, M, each P card token, both Q card tokens (the
   first after stripping its + or - sign), and the T card target (unless
   it is the literal *) -- MUST be exactly 40 or 64 case-insensitive
   hexadecimal characters (Section 3.5).  Two exceptions:






Hipp, et al.             Expires 30 January 2027               [Page 19]

Internet-Draft           Fossil Artifact Format                July 2026


   *  The K card ticket identifier is pinned to the 40-character SHA-1
      length and can never be 64 characters, regardless of hash policy.
      Its canonical writer form is 40 lowercase hexadecimal digits, and
      a conforming implementation MUST emit lowercase; a parser MAY
      accept 40 upper- or lowercase hexadecimal digits on input, the
      same canonical-versus-parser-tolerant split used for artifact
      names (Section 3).

   *  The R card and Z card checksum tokens MUST be exactly 32
      hexadecimal characters (MD5, Section 6).

   None of these hash or checksum tokens is escape-decoded, with the
   single A card target carve-out of Section 4.3.1.

4.7.2.  A Card

   a-card = %x41 SP filename SP target [ SP source ] LF   ; "A"

   An attachment card.  An attachment artifact carries exactly one A
   card; a second A card is a syntax error.  The card describes one
   attachment operation on one target object.

   Parse-time acceptance is syntactic only.  It does not resolve the
   target to an object.

   *  The filename is escape-decoded and MUST pass the pathname
      predicate (Section 4.6.1).  Only its final path component is
      retained as the stored attachment name; any directory prefix is
      discarded.

   *  The target is escape-decoded and MUST be syntactically either a
      valid artifact hash or a well-formed wiki name (Section 4.6.2).
      Parse-time acceptance checks this shape only.  It does not confirm
      that the target names an existing object.

   *  The source, when present, is a raw (never decoded) artifact hash
      validated per the hash map.  When absent, the source field is
      empty.













Hipp, et al.             Expires 30 January 2027               [Page 20]

Internet-Draft           Fossil Artifact Format                July 2026


   Target resolution happens at crosslink time.  The decoded target is
   classified against the repository in a fixed precedence: a forum
   post, then a ticket, then a wiki page, then a technote.  A hash-
   shaped target binds to the artifact that hash names, which is a
   ticket, technote, or forum post.  A wiki-name-shaped target binds to
   the wiki page of that name.  When the decoded target is syntactically
   valid for more than one family, the first match in that precedence
   order is used.  When the target resolves to no known object, because
   it is not present in this repository or names an unsupported kind,
   the attachment is still recorded and is treated as a generic artifact
   reference.  This is not an error and is not deferred.

   The source field carries the operation's behaviour, not only a field
   shape.  A present, non-empty source names the content being attached,
   and the operation adds that attachment.  An absent source deletes the
   attachment association for the (target, retained filename) pair.  An
   attachment is identified by that (target, filename) pair, and the
   operation with the greatest modification time is the one in effect: a
   later add with the same pair supersedes an earlier one, and an absent
   source deletes the association regardless of any earlier add.

4.7.3.  B Card

   b-card = %x42 SP hash LF                               ; "B"

   The baseline card.  Exactly one hash token, validated per the hash
   map; at most one B card.  Its presence marks the artifact as a delta
   manifest (Section 8).  A writer MUST name a baseline manifest, not
   another delta manifest, when emitting a B card.  The Fossil reference
   parser does not reject a delta manifest merely because its resolved
   baseline is itself a delta manifest; consumers that need the complete
   file set can fail later if baseline resolution does not produce the
   expected baseline file list.  Ordering guarantees relative to F cards
   are given in Section 4.4.

4.7.4.  C Card

   c-card = %x43 SP comment LF                            ; "C"

   The comment card.  Exactly one required token, escape-decoded;
   single-occurrence; a C card with no token MUST be rejected.  The
   decoded comment content is otherwise unvalidated.  The C card never
   assigns the artifact type; its presence participates in type
   resolution only through the fallback of Section 5.3.

4.7.5.  D Card and E Card





Hipp, et al.             Expires 30 January 2027               [Page 21]

Internet-Draft           Fossil Artifact Format                July 2026


   d-card = %x44 SP timestamp LF                          ; "D"
   e-card = %x45 SP timestamp SP technote-id LF           ; "E"

   The date card and the technote card.  Each timestamp is a single raw
   token validated per Section 4.6.4.  The E card additionally requires
   a second token -- a technote identifier validated per the hash map --
   and marks the artifact as a technote (EVENT type).

4.7.6.  F Card

   f-card = %x46 SP filename                              ; "F"
            [ SP hash [ SP perm [ SP old-name ] ] ] LF

   A file-list entry.  The filename is always escape-decoded and MUST
   pass the pathname predicate (Section 4.6.1); the old-name (fourth
   position) is decoded when present and held to the same predicate; the
   hash and permission tokens are never decoded.  Constraints:

   *  *Sort order:* strict ascending by decoded filename; duplicates
      rejected (Section 4.5.2).

   *  *Hash presence:* in a baseline manifest, every F card MUST carry a
      hash.  In a delta manifest, the hash MAY be omitted; a hash-less F
      card carries a null hash and is interpreted by the merge walk as a
      file-deletion marker relative to the baseline (Section 8.2).  A
      hash-less F card is therefore permitted only when a B card is
      present.

   *  *Permission token:* for interoperability a producer SHOULD emit
      only w, x, or l.  When an old-name is present in conforming
      output, a producer MUST emit an explicit permission token so the
      old-name remains in the fourth positional field defined by the
      grammar; in the regular-file case that token SHOULD be w.  A
      reader MUST parse any third positional token as the raw permission
      token, never as old-name, and MUST accept it without parse-time
      validation against {w,x,l}. Only the fourth positional token, when
      present, is old-name.  A raw permission token containing x marks
      the entry executable; otherwise, a token containing l marks it as
      a symbolic link; all other raw permission tokens yield regular-
      file behaviour.

   *  *Reserved names:* an F card whose decoded current filename is
      reserved MUST be silently dropped, after sort checking, per
      Section 4.6.3.  The old-name field is not tested by that rule.

4.7.7.  G Card, H Card, and I Card





Hipp, et al.             Expires 30 January 2027               [Page 22]

Internet-Draft           Fossil Artifact Format                July 2026


   g-card = %x47 SP hash LF                               ; "G"
   h-card = %x48 SP threadtitle LF                        ; "H"
   i-card = %x49 SP hash LF                               ; "I"

   The forum cards.  Each is single-occurrence with exactly one required
   token, and each marks the artifact as a forum post.  The G card
   carries a raw (never decoded) artifact hash, validated per the hash
   map, identifying the thread-root post.  The I card carries a raw
   artifact hash identifying the post being replied to.  The H card
   carries an escape-decoded thread title with no content validation --
   any decoded string is accepted (in contrast to the L card below).  An
   artifact MUST NOT contain both an H card and an I card (Section 5.4).

4.7.8.  J Card

   j-card = %x4A SP fieldname [ SP value ] LF             ; "J"

   A ticket field-change card.  Repeatable, strictly ascending by field
   name (Section 4.5.2).  The value is escape-decoded; the field name is
   stored verbatim, including any leading +. An absent value defaults to
   the empty string, not null.  How a consumer applies J cards to ticket
   state -- including the +-prefix append rule and tolerance of unknown
   field names -- is ticket-processing semantics, which the current
   Fossil specification set does not define (ticket semantics are a
   separate, forthcoming concern); at the artifact layer a J card is
   exactly the grammar given here.

4.7.9.  K Card

   k-card = %x4B SP ticket-id LF                          ; "K"

   The ticket card.  A single raw ticket identifier of exactly 40
   hexadecimal characters (Section 4.7.1); single-occurrence; marks the
   artifact as a ticket change.  The identifier is pinned to the
   40-character SHA-1 length; a 64-character SHA3-length identifier is
   always invalid.  Its canonical writer form is lowercase, and a
   conforming implementation MUST emit lowercase; a parser MAY accept
   uppercase, mirroring the artifact-name split of Section 3.

4.7.10.  L Card

   l-card = %x4C SP wikititle LF                          ; "L"

   The wiki-title card.  A single escape-decoded title token that MUST
   pass the wiki-name predicate (Section 4.6.2); single-occurrence;
   marks the artifact as a wiki page.





Hipp, et al.             Expires 30 January 2027               [Page 23]

Internet-Draft           Fossil Artifact Format                July 2026


4.7.11.  M Card

   m-card = %x4D SP hash LF                               ; "M"

   A cluster member.  Repeatable; each occurrence carries a hash
   validated per the hash map; runs MUST be strictly ascending by hash
   (Section 4.5.2).  Marks the artifact as a cluster.

4.7.12.  N Card

   n-card = %x4E SP mimetype LF                           ; "N"

   The mimetype card.  A single escape-decoded mimetype token with no
   mime-syntax validation; single-occurrence.  Per-type semantics
   diverge: on a check-in manifest the N card is grammatically legal but
   functionally inert -- no implementation has interpreted it, and
   comments are rendered as Fossil wiki text regardless; on wiki,
   technote, and forum artifacts it names the W card body's mimetype,
   defaulting to text/x-fossil-wiki when omitted; on an attachment it
   names the C card comment's mimetype, defaulting to text/plain -- both
   a different default and a different target field than the other
   types.

4.7.13.  P Card

   p-card = %x50 *( SP hash ) LF                          ; "P"

   The parent card.  Zero or more hash tokens on one line, each
   validated per the hash map.  An empty P card (zero tokens) MUST be
   accepted: the initial empty check-in historically has an empty P
   card.  Tokens are neither sorted nor deduplicated; their order is
   semantic.  Per-type meanings (parsed identically): on a manifest, the
   first token is the primary ancestor and remaining tokens are merge
   parents; on a wiki page, the prior version or versions; on a
   technote, a single prior technote with the same technote identifier
   being edited (an edit-chain link, not a merge); on a forum post, a
   single prior version of the same post.

   On a check-in manifest, the P-card tokens define the check-in's
   parent and merge-parent references as artifact syntax only.  The
   check-in ancestry graph built from those references, and the branch,
   leaf, and current-trunk semantics computed over it, are specified in
   [FossilRepoState].

   For interoperability a producer SHOULD emit at most one P card.
   Existing receiver behaviour for a repeated P card is a compatibility
   divergence recorded in Appendix C; this section does not strengthen
   the parse-time receiver rule for repeated P cards.



Hipp, et al.             Expires 30 January 2027               [Page 24]

Internet-Draft           Fossil Artifact Format                July 2026


4.7.14.  Q Card

   q-card = %x51 SP q-sign hash [ SP hash ] LF            ; "Q"
   q-sign = "+" / "-"

   The cherry-pick card.  The + (cherry-pick into) or - (backout of)
   sign is concatenated without a space onto the first hash, inside a
   single token: the sign byte is checked, then the remainder is
   validated per the hash map.  Contrast the T card, where the sign is
   on the name.  The optional second token is a plain unprefixed hash
   naming the baseline of the range; when omitted, the documented
   default is the target's primary parent, but that default is not
   resolved at parse time -- the field is left null.  Q cards are
   unordered-repeatable: no duplicate guard and no ordering check.
   Receivers that do not recognise the Q card reject manifests
   containing it.

4.7.15.  R Card

   r-card = %x52 SP md5-token LF                          ; "R"

   The repository checksum card.  A single checksum token of exactly 32
   hexadecimal characters; single-occurrence; never decoded.  Its
   computation and verification are specified in Section 6.3.  An R card
   may appear only in a manifest (Section 5.2) and is never required.

4.7.16.  T Card

   t-card   = %x54 SP tag-sign tagname                    ; "T"
              SP ( hash / "*" ) [ SP value ] LF
   tag-sign = "+" / "-" / "*"

   The tag card.  The sign prefix is embedded in the name token.  Tokens
   are read in order name, target, value, and validated as follows: the
   value (if present) is escape-decoded; the target MUST be a valid
   artifact hash or the exact one-character literal * denoting a self-
   referential tag (carried with a null target); the name is escape-
   decoded, its first character MUST be +, -, or *, and the remainder
   after the prefix MUST NOT consist entirely of hexadecimal digits, at
   any length -- a tag name must remain distinguishable from a hash
   prefix.  The target token is never decoded.  An absent value yields
   null (unlike the J card's empty-string default).  Intra-run ordering
   is the two-level rule of Section 4.5.2; the name used as the primary
   ordering key is the full name token including its leading sign
   character (+, -, or *), not the sign-stripped tag name.






Hipp, et al.             Expires 30 January 2027               [Page 25]

Internet-Draft           Fossil Artifact Format                July 2026


   At parse time, T validity ends with this token syntax, the intra-run
   ordering rule, the per-type legality table, and the self-referential-
   tag checks in Section 5.4.  Repository-state effects are applied
   later when a stored structural artifact is crosslinked.  Crosslink
   processing maps the decoded name prefix to a tag operation: + applies
   a singleton tag to the target only, * applies a propagating tag
   through primary child links until blocked, and - cancels or blocks
   the tag.  The target is the named artifact hash, or the artifact
   carrying the card when the target token is *; the stored tag name is
   the decoded name with the prefix removed.

   Branch, ordinary tag, closed-leaf, and current-trunk views are
   derived from those crosslinked tag records, not from T parsing alone.
   In canonical artifacts, T *branch * NAME supplies the propagating
   branch property, T *sym-NAME * supplies a symbolic tag, T +closed *
   marks a closed leaf, and T -closed * cancels that closed marker.  A
   leaf is a check-in with no child on the same branch; a check-in with
   no branch tag uses the repository's main branch name, whose default
   is trunk.  Open-leaf, closed-marker, and current-trunk answers are
   therefore repository views over the check-in DAG, the branch tag
   value, symbolic tags, and the closed tag.  Current-trunk additionally
   depends on the repository-local main-branch setting that selects
   which branch name to resolve, so it is not a pure function of the
   artifact set; its full definition, including that local input, is in
   [FossilRepoState].  This document defines the artifact syntax and
   routes those effects to repository crosslink/tag-state processing,
   which is specified in [FossilRepoState]; [FossilSync] owns discovery,
   transfer, phantom/delta convergence, and the point at which a sync
   participant may rely on the derived views.

4.7.17.  U Card

   u-card = %x55 [ SP [ login ] ] LF                      ; "U"

   The user card.  A single escape-decoded login token; single-
   occurrence.  When a U card is present but carries an empty or omitted
   login token -- a bare U line, or a U followed by an empty token --
   the reader MUST substitute the literal string anonymous.  This card's
   grammar, with its optional and possibly-empty login token, governs
   the U card and takes precedence over the general requirement that a
   card argument be a non-empty token.  This substitution never fires
   for a wholly absent U card: absence is governed by the per-type
   required-card rule of Section 5.2 (a wiki artifact lacking a U card
   is rejected there; see also Appendix C).

4.7.18.  W Card





Hipp, et al.             Expires 30 January 2027               [Page 26]

Internet-Draft           Fossil Artifact Format                July 2026


   w-card = %x57 SP size LF body LF                       ; "W"
   size   = "0" / ( nonzero-digit *DIGIT )
   nonzero-digit = %x31-39
   body   = <size> OCTET

   The body card.  Writer form: a producer MUST emit the size as
   canonical decimal ASCII digits with one or more digits and no sign,
   leading padding, or suffix bytes.  The size token is followed,
   starting immediately after its terminating LF, by the raw body of
   exactly size octets.  The body is opaque bytes: it is located by the
   byte count that precedes it, it MAY contain the byte 0x0A and any
   other byte, and it is not line-split.  The W card is the sole
   exception to the one-card-per-line rule.  The byte immediately after
   the declared-length body MUST be exactly LF, and the position one
   past that byte MUST remain within the artifact.

   Reader acceptance is wider than the writer form.  A reader
   accumulates only leading decimal digits from the size token, stops at
   the first non-digit byte, and does not re-check that the remainder of
   that token is empty.  Accumulator overflow MUST be detected and
   rejected.  A reader MUST bound the resulting size against the
   remaining artifact length before consuming the body, MUST consume
   exactly that many body bytes by counting, and MUST NOT scan the body
   for a card boundary.  Therefore a token such as 12x is accepted only
   if exactly 12 content bytes and then LF follow.  A token with no
   leading digit, such as abc, parses as zero and is accepted only in
   the narrow case where the next byte is immediately LF and the
   surrounding artifact otherwise satisfies all card and type rules.

4.7.19.  Z Card

   z-card = %x5A SP md5-token LF                          ; "Z"

   The self-checksum card.  A checksum token of exactly 32 hexadecimal
   characters, never decoded, structurally last: it occupies exactly the
   final 35 bytes of the stripped content (Section 4.4).  Its
   verification is specified in Section 6.2.

5.  Structural Artifact Types

5.1.  Type Codes and Names

   Every structural artifact is classified as exactly one of eight
   types.  Each type has a stable numeric code and an external name --
   the name emitted on machine-readable (JSON/API) surfaces:






Hipp, et al.             Expires 30 January 2027               [Page 27]

Internet-Draft           Fossil Artifact Format                July 2026


                   +======+============+===============+
                   | Code | Type       | External name |
                   +======+============+===============+
                   | 1    | MANIFEST   | checkin       |
                   +------+------------+---------------+
                   | 2    | CLUSTER    | cluster       |
                   +------+------------+---------------+
                   | 3    | CONTROL    | tag           |
                   +------+------------+---------------+
                   | 4    | WIKI       | wiki          |
                   +------+------------+---------------+
                   | 5    | TICKET     | ticket        |
                   +------+------------+---------------+
                   | 6    | ATTACHMENT | attachment    |
                   +------+------------+---------------+
                   | 7    | EVENT      | technote      |
                   +------+------------+---------------+
                   | 8    | FORUM      | forumpost     |
                   +------+------------+---------------+

                                  Table 3

   Code 0 is a sentinel meaning "type not yet determined"; it exists
   only transiently during parsing, is consumed by the fallback of
   Section 5.3, and is never a valid final classification.

   Note (informative): diagnostic text in existing implementations uses
   a second vocabulary that differs for two types: MANIFEST appears as
   manifest and FORUM as forum post (with an embedded space); the six
   other names are identical in both vocabularies.  The two vocabularies
   are not interchangeable and readers are cautioned not to conflate
   them.

5.2.  Card Legality by Type

   Each artifact type has a fixed set of allowed card letters and a
   fixed subset of required card letters:














Hipp, et al.             Expires 30 January 2027               [Page 28]

Internet-Draft           Fossil Artifact Format                July 2026


      +======+============+=======================+================+
      | Code | Type       | Allowed cards         | Required cards |
      +======+============+=======================+================+
      | 1    | MANIFEST   | B C D F N P Q R T U Z | D Z            |
      +------+------------+-----------------------+----------------+
      | 2    | CLUSTER    | M Z                   | M Z            |
      +------+------------+-----------------------+----------------+
      | 3    | CONTROL    | D T U Z               | D T U Z        |
      +------+------------+-----------------------+----------------+
      | 4    | WIKI       | C D L N P U W Z       | D L U W Z      |
      +------+------------+-----------------------+----------------+
      | 5    | TICKET     | D J K U Z             | D J K U Z      |
      +------+------------+-----------------------+----------------+
      | 6    | ATTACHMENT | A C D N U Z           | A D Z          |
      +------+------------+-----------------------+----------------+
      | 7    | EVENT      | C D E N P T U W Z     | D E W Z        |
      +------+------------+-----------------------+----------------+
      | 8    | FORUM      | D G H I N P U W Z     | D U W Z        |
      +------+------------+-----------------------+----------------+

                                 Table 4

   An artifact MUST NOT contain any card whose letter is outside its
   type's allowed set, and MUST contain every card in its type's
   required set.  A parser MUST reject an artifact that violates either
   rule.  Both checks run after the type is finalized (Section 5.3).

   Consequences worth stating plainly: a manifest requires only the D
   and Z cards, so the C and U cards are optional on a manifest; a wiki
   artifact lacking a U card is rejected here; and the Z card is
   required for every artifact type, even though the checksum-
   verification gate of Section 4.1 tolerates its absence -- an artifact
   with no Z card passes that gate and is rejected by this rule instead.

5.3.  Type Determination

   The artifact's type is determined during the single pass over the
   cards.  Thirteen card letters are type-setting; each unconditionally
   assigns the artifact type when processed, with no guard against a
   previously assigned value:











Hipp, et al.             Expires 30 January 2027               [Page 29]

Internet-Draft           Fossil Artifact Format                July 2026


                      +=============+===============+
                      | Card letter | Type assigned |
                      +=============+===============+
                      | A           | ATTACHMENT    |
                      +-------------+---------------+
                      | B, F, Q, R  | MANIFEST      |
                      +-------------+---------------+
                      | E           | EVENT         |
                      +-------------+---------------+
                      | G, H, I     | FORUM         |
                      +-------------+---------------+
                      | J, K        | TICKET        |
                      +-------------+---------------+
                      | L           | WIKI          |
                      +-------------+---------------+
                      | M           | CLUSTER       |
                      +-------------+---------------+

                                  Table 5

   The eight remaining card letters (C, D, N, P, T, U, W, Z) never set
   the type.  Because card ordering is non-decreasing (Section 4.4),
   when cards with multiple distinct type-setting letters are present,
   the type that survives MUST be that of the alphabetically latest --
   that is, last-processed -- type-setting card.  L, the wiki title
   card, is itself a direct type-setter; only the W body card is type-
   implicit for wiki artifacts.

   If, after all cards are processed, no type-setting card was seen, the
   type MUST be resolved by fallback: the artifact is a MANIFEST if a C
   card was present, or if any F card file entries were recorded, or if
   any P card parents were recorded; otherwise it is a CONTROL artifact.
   In practice this fallback is reachable via the C card or P card, and
   also after a reserved-name F card has been dropped before setting the
   type (Section 4.6.3).  The allowed-card and required-card checks of
   Section 5.2 run strictly after this fallback finalizes the type, and
   are the effective disambiguator that rejects any artifact whose card
   set does not match its implied type.

5.4.  Per-Type Semantic Checks

   Beyond card legality, four semantic checks apply after the type is
   finalized, and a parser MUST enforce them:

   1.  A CONTROL artifact MUST NOT contain a self-referential T card.

   2.  In an EVENT (technote) artifact, every T card MUST be self-
       referential and every T card MUST carry the + prefix.



Hipp, et al.             Expires 30 January 2027               [Page 30]

Internet-Draft           Fossil Artifact Format                July 2026


   3.  A FORUM artifact MUST NOT contain both an H card and an I card.

   4.  A FORUM artifact's P card MUST NOT list more than one parent,
       since forum posts cannot be merged.

   A G card is valid when its token satisfies the hash grammar of
   Section 4.7.1.  Conformance of a forum artifact does not depend on
   any cross-artifact consistency check over the G, I, and P chains;
   following the I chain to the thread root and that root's P chain to
   its initial version need not yield the artifact named by G.

5.5.  Well-Formedness Pre-Filter

   This subsection is informative.  A fast pre-filter for well-
   formedness may reject any input whose first card letter falls in N
   through Z -- narrower than the line-1 gate's bound of A through Z --
   before full parsing is attempted.  The Fossil reference pre-filter
   also performs a second-card plausibility check before invoking the
   full parser.  The narrower first-card range is sound given the per-
   type card tables: for every artifact type the lexicographically
   smallest allowed card letter is less than or equal to M (minima:
   MANIFEST B, CLUSTER M, CONTROL D, WIKI C, TICKET D, ATTACHMENT A,
   EVENT C, FORUM D), and non-decreasing card ordering guarantees the
   smallest present card appears first.

6.  Checksums

   Structural artifacts carry two MD5-based [RFC1321] checksum cards:
   the R card, an aggregate checksum over the check-in's tracked file
   content, and the Z card, a self-checksum over the artifact text
   itself.  Both cards carry a fixed-width 32-character hexadecimal MD5
   digest token.

6.1.  Digest Token Grammar

   r-card    = %x52 SP md5-token LF        ; "R"
   z-card    = %x5A SP md5-token LF        ; "Z", emitted form
   md5-token = 32hexdig-ci

   At parse time the digest token of both cards MUST be exactly 32
   characters and MUST consist only of hexadecimal digits; the parse-
   accept grammar is case-insensitive, admitting both 0-9a-f and A-F.
   Case-insensitivity applies only to structural acceptance: as
   specified below, checksum verification is byte-exact against
   lowercase renderings, so digests are effectively lowercase-only
   wherever their values are actually checked.  There is no case-folding
   or canonicalization of artifact bytes anywhere in the parse path.




Hipp, et al.             Expires 30 January 2027               [Page 31]

Internet-Draft           Fossil Artifact Format                July 2026


6.2.  Z Card: Artifact Self-Checksum

   Let n be the length in bytes of the artifact text after any PGP or
   SSH signature wrapper has been stripped (Section 4.1.1); the wrapper
   removal procedure there defines the byte range this section operates
   on.  A Z card, when present, occupies the tail of the artifact: the
   marker Z followed by a space begins at offset n-35, the 32 digest
   bytes occupy offsets n-33 through n-2, and offset n-1 holds the
   artifact's terminating byte.

   Verification MUST proceed as follows:

   1.  Compute the MD5 digest over exactly the first n-35 bytes of the
       (wrapper-stripped) artifact text -- all bytes strictly before the
       Z marker.

   2.  Render the digest as 32 lowercase hexadecimal characters.

   3.  Compare it byte-for-byte against the 32 stored digest bytes at
       offsets n-33 through n-2.

   The outcome is one of three states:

         +==========+================================+==========+
         | State    | Condition                      | Action   |
         +==========+================================+==========+
         | absent   | no Z card present, or artifact | continue |
         |          | too short to hold one          | parsing  |
         +----------+--------------------------------+----------+
         | match    | stored token equals recomputed | continue |
         |          | digest                         | parsing  |
         +----------+--------------------------------+----------+
         | mismatch | Z card present but token       | abort    |
         |          | differs                        | parsing  |
         +----------+--------------------------------+----------+

                                 Table 6

   A parser MUST reject an artifact whose Z card is present but
   mismatched.  The verification stage MUST NOT itself reject an
   artifact for lacking a Z card; absence is instead rejected by the
   required-card rule of Section 5.2, which includes Z for every
   artifact type.








Hipp, et al.             Expires 30 January 2027               [Page 32]

Internet-Draft           Fossil Artifact Format                July 2026


   Because the comparison in step 3 is byte-exact against a digest that
   is always rendered in lowercase, Z card verification is case-
   sensitive: a Z card whose token contains any uppercase hexadecimal
   digit MUST fail verification even if it is numerically the correct
   digest, despite having been accepted by the case-insensitive
   structural grammar.

   Z card verification never reads byte n-1 (the artifact's terminating
   byte); a conformant verifier neither checks nor requires any
   particular value at that offset as part of Z card verification.  The
   requirement that an artifact end with a final LF is the artifact-
   level framing rule of Section 4.1, imposed on the raw, wrapper-
   inclusive bytes before signature removal.  Producers MUST emit the Z
   card in the form shown in the grammar above -- the literal Z, one
   space, the 32-character lowercase digest, and a terminating LF.

   Note (informative): existing implementations verify the Z card
   unconditionally; no supported configuration disables the check.
   Implementations SHOULD NOT be designed on the assumption that any
   deployed configuration skips Z card verification.

6.3.  R Card: Aggregate Content Checksum

6.3.1.  Parse-Time Handling

   At parse time the R card is validated structurally only -- the
   32-character length and hexadecimal-digit checks of Section 6.1.  A
   parser MUST NOT be expected to recompute the R card's value against
   file content during parsing; the parse path never does so.  Semantic
   verification of the R card value is a separate, writer-side operation
   performed at commit time against the working checkout.  An R card may
   appear only in a manifest and is never required (Section 5.2).

6.3.2.  R-Card Computation

   The R card value is the MD5 digest of a single running hash context
   fed, for every tracked file in filename order, with the following
   byte sequence per file:

   1.  the filename text;

   2.  a single space, then the file's size in bytes rendered as
       canonical minimal decimal ASCII -- no leading zeros, no sign, no
       digit separators -- then a LF;

   3.  the raw file content bytes.

   Equivalently:



Hipp, et al.             Expires 30 January 2027               [Page 33]

Internet-Draft           Fossil Artifact Format                July 2026


   ctx = MD5-Init()
   for each tracked file f, in filename order:
       MD5-Update(ctx, name(f))
       MD5-Update(ctx, SP || decimal(size-in-bytes(f)) || LF)
       MD5-Update(ctx, content(f))
   r-value = lowercase-hex(MD5-Final(ctx))

   The checksum covers filename plus size-header plus content for each
   file, concatenated across all files -- not merely the concatenation
   of raw file bytes.  "Filename order" is the byte-wise unsigned-octet
   order of the canonical comparator (Section 4.5.3), identical to the
   file-enumeration order; / receives no special collation treatment.

6.3.3.  Delta Manifests

   For a delta manifest, the R card MUST be computed over the fully
   reconstructed file set obtained by merging the delta with its
   baseline (Section 8.2) -- iterating the merged file list and skipping
   entries that carry no hash (delete markers) -- and NOT over the delta
   manifest's literal F cards.

6.3.4.  Emitted Form

   The writer emits the R card as exactly the literal R, one space, the
   checksum bytes, and LF -- nothing else -- and the checksum value is
   always rendered as exactly 32 lowercase hexadecimal digits.  The
   emitted form is strictly lowercase even though the parse-accept
   grammar is case-insensitive.  The commit-time self-consistency check
   compares byte-exactly against an always-lowercase recomputed digest,
   so an uppercase R card -- although accepted at parse time -- fails
   that check.  Value correctness of the R card is checked only at
   commit time, never during artifact parsing.

7.  Hash Policy

   A repository carries a hash policy that governs which hash algorithm
   names newly stored artifacts and whether a secondary algorithm may be
   consulted when storing or resolving content.  The policy is a per-
   repository, purely local concern: it shapes how names are assigned
   going forward, and it never alters names already assigned.

7.1.  Policy Values

   Five policy values are defined.  Value strings MUST be matched case-
   sensitively and exactly; an unrecognised value is a fatal error.  The
   ordinal column gives each policy's stable numeric encoding (0 through
   4, in the order listed).




Hipp, et al.             Expires 30 January 2027               [Page 34]

Internet-Draft           Fossil Artifact Format                July 2026


         +===========+=========+==============+==================+
         | Value     | Ordinal | Primary hash | Alternative hash |
         +===========+=========+==============+==================+
         | sha1      | 0       | SHA-1        | SHA3-256         |
         +-----------+---------+--------------+------------------+
         | auto      | 1       | SHA-1        | SHA3-256         |
         +-----------+---------+--------------+------------------+
         | sha3      | 2       | SHA3-256     | SHA-1            |
         +-----------+---------+--------------+------------------+
         | sha3-only | 3       | SHA3-256     | disallowed       |
         +-----------+---------+--------------+------------------+
         | shun-sha1 | 4       | SHA3-256     | disallowed       |
         +-----------+---------+--------------+------------------+

                                  Table 7

   The primary hash is the algorithm used to name newly stored content.
   Under sha1 and auto the primary hash MUST be SHA-1; under sha3,
   sha3-only, and shun-sha1 it MUST be SHA3-256.  The alternative hash
   is a second algorithm that MAY be consulted to detect whether
   identical content is already stored under the other algorithm's name.
   The alternative hash is permitted only under sha1 and auto (where it
   is SHA3-256) and under sha3 (where it is SHA-1).  Under sha3-only and
   shun-sha1, a request for the alternative hash MUST fail, yielding a
   failure indication and an empty result rather than a hash value.

   sha3-only and shun-sha1 are indistinguishable in local hash selection
   and deduplication; they diverge only in sync-admission behaviour,
   specified in [FossilSync].

7.2.  Default Policy

   A repository with no assigned hash-policy setting MUST derive its
   effective policy as follows:

   1.  If the repository already contains any SHA3-named artifact (a
       name longer than 40 hexadecimal characters), or contains no SHA-
       1-named artifact (40 hexadecimal characters) at all -- including
       the case of an empty repository -- the default is sha3.

   2.  Otherwise -- only when at least one SHA-1 artifact exists and
       zero SHA3 artifacts exist -- the default is auto.

   This derivation never yields shun-sha1.







Hipp, et al.             Expires 30 January 2027               [Page 35]

Internet-Draft           Fossil Artifact Format                July 2026


7.3.  Assigning the Policy

   The policy is repository-local state, persisted as a single
   configuration value.  Administrative surfaces for viewing or
   assigning the hash policy (the command line fossil hash-policy ?NEW-
   POLICY?; web setup pages) are operational interfaces outside this
   format specification.

   Two properties of assignment deserve emphasis:

   *  *No demotion guard.* Nothing prevents an operator from explicitly
      setting the policy back to sha1; the automatic forward ratchet
      (Section 7.4) applies only while the effective policy is auto.

   *  *Set-time coercion of auto.* Requesting auto when the repository
      already holds a SHA3-named artifact silently stores sha3 instead.
      Once a SHA3 artifact exists, auto is unreachable via assignment.

7.4.  Automatic Promotion (Ratchet)

   While the effective policy is auto, the content-storage operation
   first selects the name it is actually going to assign -- either a
   computed name or a caller-supplied candidate name -- and then MUST
   promote the repository to sha3, persisting the new policy immediately
   as part of that same write, whenever that selected name exceeds 40
   characters.  This ratchet decision happens before duplicate lookup,
   insertion or dephantomization, crosslink processing, or commit-time
   recoverability verification.  If a caller verifies a supplied name
   and rejects it before invoking storage, that failed candidate causes
   no ratchet; if a receive path stores a 64-character supplied name
   before it can verify the reconstructed bytes, the ratchet observes
   the supplied name.

   Under auto the primary hash for fresh local naming is SHA-1, whose
   names are exactly 40 characters, so the trigger is reachable in
   exactly two ways:

   1.  a caller-supplied 64-hexadecimal SHA3-256 name accepted for
       storage during transfer or ingest; or

   2.  locally created content whose auxiliary SHA3-256 hash (computed
       as the alternative hash under auto) matches an artifact already
       present, causing the existing 64-hexadecimal name to be reused
       (Section 7.5).

   The promotion is a silent side effect of a content write: hash-policy
   state can ratchet forward from auto to sha3 without any explicit
   administrative action.



Hipp, et al.             Expires 30 January 2027               [Page 36]

Internet-Draft           Fossil Artifact Format                July 2026


7.5.  Cross-Algorithm Deduplication

   When content is stored without an externally supplied name, the
   storage operation MUST first compute the alternative-algorithm hash
   (where the policy permits one) and look it up; only if that lookup
   misses does it fall back to naming the content with the primary hash.
   Combined with an early return when the computed name already exists
   as a fully present artifact, this guarantees that content already
   stored under the other algorithm's name keeps its existing name and
   is never inserted a second time: under sha1, auto, and sha3, the same
   bytes never acquire two names through local writes.

   *Exception under sha3-only and shun-sha1.* Because these policies
   disallow the alternative hash, the pre-check cannot discover an
   existing SHA-1 name for the same bytes.  New artifacts MUST be named
   with SHA3-256 even when identical content already carries a SHA-1
   name, deliberately accepting that some content ends up stored twice
   -- once under each name -- with delta compression [FossilDelta]
   relied upon to mitigate the size cost.  This is the one exception to
   the never-two-names behaviour above.  The failed alternative-hash
   request is absorbed silently: the flow falls back to the primary hash
   with no diagnostic, making the disallowed-alternative case
   behaviourally indistinguishable from a legitimate lookup miss.

7.6.  Name Immutability

   Artifact names are immutable once assigned.  A name is assigned only
   when content is first stored; subsequent writes to the same artifact
   update only ancillary storage state, never the name.  Assigning a new
   hash policy writes only the policy value.  Changing the hash policy
   therefore MUST NOT retroactively rename or rehash any stored
   artifact: policy affects only subsequently stored content, and
   historical artifacts keep their historical names.

7.7.  Synchronisation Behaviour

   Ordinary artifact exchange does not negotiate hash policy: each side
   applies its own local policy independently to its own artifact reads
   and writes.  The hash-policy setting is repository configuration and
   can be communicated by Fossil configuration exchange, but that
   movement of configuration is distinct from per-artifact transfer and
   does not select an algorithm for the peer during a content exchange.
   The cross-peer capability signal relevant to artifact transfer is a
   client-version announcement, used purely as a SHA3-capability gate:
   when the remote version predates SHA3 support and a local artifact's
   name exceeds 40 characters, the sender refuses to transmit that
   artifact -- with an explicit error, never by converting, downgrading,
   or silently omitting it.  The mechanism is part of the sync protocol



Hipp, et al.             Expires 30 January 2027               [Page 37]

Internet-Draft           Fossil Artifact Format                July 2026


   [FossilSync].

   Receive-side admission of SHA-1-named artifacts under shun-sha1 is
   sync-protocol behaviour, specified in [FossilSync]; within this
   document shun-sha1 affects only local name selection.

8.  Delta Manifest Reconstruction

   A manifest is a delta manifest if and only if it contains a B card;
   otherwise it is a baseline manifest.  Every consumer pivots on
   exactly this predicate: no other property (file count, presence of an
   R card, emptiness) participates in the classification.  A delta
   manifest does not carry the complete file set of its check-in; its F
   cards record only differences against the baseline manifest named by
   its B card (Section 4.7.3).  Consumers that need the full file set
   MUST derive it by merging the delta's F cards with the baseline's, as
   specified in this section.

   A delta manifest is distinct from the delta encoding of artifact
   content: [FossilDelta] specifies how an artifact's bytes may be
   stored or transferred as a delta against another artifact's bytes, a
   layer below this one.  The file content named by an F card hash may
   itself be held in that encoded form; reconstruction here operates on
   cards, not on content bytes.

8.1.  Preconditions

   The merge walk requires both file lists sorted by decoded filename
   under the canonical comparator (Section 4.5.3).  That sortedness is a
   parse-time invariant (Section 4.5.2): every successfully parsed
   manifest satisfies it, so the precondition holds for any manifest
   obtained from a conforming parser.

   A delete marker is an F card that carries no hash.  It is permitted
   only in a delta manifest -- in a baseline manifest every F card MUST
   carry a hash (Section 4.7.6) -- and it carries a null hash,
   interpreted by the merge walk as removal of the named file from the
   baseline's set.

8.2.  Full File-Set Enumeration (Merge-Walk)

   To enumerate the complete file set of a delta manifest, an
   implementation MUST perform a filename-ordered merge-walk over two
   cursors: one over the baseline's file list and one over the delta's.
   Filenames are compared byte-wise on their decoded form
   (Section 4.5.3).  At each step:





Hipp, et al.             Expires 30 January 2027               [Page 38]

Internet-Draft           Fossil Artifact Format                July 2026


   1.  If both cursors name the same file and the delta entry carries a
       hash, the delta entry replaces the baseline entry: both cursors
       advance and the delta entry is emitted.

   2.  If both cursors name the same file and the delta entry carries no
       hash (a delete marker), the file is removed: both cursors advance
       and no entry is emitted.

   3.  If the names differ, the entry that sorts first is emitted and
       only its cursor advances.  A delta delete marker whose name is
       not present in the baseline (an unmatched deletion) is emitted
       here like any other sorts-first entry, but because it carries no
       hash it adds no file to the reconstructed set.  An unmatched
       deletion is therefore a no-op for materialization, not an error.

   Enumeration terminates only when both cursors are exhausted.  Once
   either list runs out, the remaining entries of the other list are
   emitted verbatim -- including any delete markers remaining in the
   delta's tail.  Consumers of the merged stream MUST therefore filter
   out entries whose hash is absent when computing derived results, as
   the aggregate-checksum computation over the merged file set does
   (Section 6.3.3).

8.3.  Baseline Resolution

   The baseline identified by the B card hash is resolved lazily: it is
   located and parsed as a manifest artifact the first time the baseline
   is needed.  When the baseline cannot be located, or the located
   artifact is not a manifest, resolution follows one of two
   disciplines:

   *  *Hard failure*, for the file-enumeration entry points: beginning
      full file-set enumeration, and single-name search (Section 8.4),
      MUST treat an unresolvable baseline as a fatal error of the
      enumeration.

   *  *Soft failure*, for consumers that can defer: a parent-child file
      difference walk or post-parse relationship processing MAY instead
      record the gap -- keyed by the dependent artifact and the missing
      baseline hash, inserted idempotently -- report failure to the
      caller, and retry when the baseline arrives.

   Per-step enumeration reports no error for an unresolved baseline: an
   enumeration begun without resolving the baseline silently degrades to
   delta-only enumeration.  Implementations MUST therefore ensure the
   baseline is resolved, under the hard-failure discipline, before
   iteration begins rather than relying on per-step error reporting.




Hipp, et al.             Expires 30 January 2027               [Page 39]

Internet-Draft           Fossil Artifact Format                July 2026


8.4.  Single-Name Lookup

   When resolving a single filename against a delta manifest, an
   implementation MUST search the delta's own F cards first, and best-
   match (closest-name) lookup MUST be suppressed for delta manifests
   even when the caller requests it.  If the delta contains an entry for
   the name whose hash is absent (a delete marker), the lookup MUST
   report not-found without consulting the baseline.  Only when the name
   is entirely absent from the delta is the baseline resolved and
   searched.

8.5.  Renderings That Intentionally Do Not Reconstruct

   This subsection is informative; it describes an existing rendering
   surface rather than a requirement on the artifact format.

   The JSON rendering of a manifest artifact traverses the manifest's
   own F card list directly rather than the merged enumeration.  A delta
   manifest's JSON rendering therefore shows only its literal, authored
   F cards -- not the derived full file set.  This is a deliberate
   exception for that one rendering surface, in contrast with consumers
   such as the aggregate-checksum computation, which operate on the
   fully merged file set.

9.  Security Considerations

   An artifact's name is the hash of its content, so a reader detects
   any alteration of an artifact's bytes by recomputing the hash and
   comparing it to the name.  This binding is only as strong as the
   hash.  SHA-1 [RFC3174] has known collision attacks: a party able to
   construct two byte sequences with the same SHA-1 digest could offer
   either under one name.  SHA3-256 [FIPS202] is not subject to these
   attacks and is the default for new artifacts in most repository
   states (Section 7).  A SHA-1 artifact's name continues to verify its
   content against accidental corruption; existing implementations
   compute SHA-1 through a collision-detecting implementation, and the
   shun-sha1 policy lets a repository decline SHA-1-named artifacts
   arriving through synchronisation ([FossilSync]).

   The Z and R cards use MD5 [RFC1321], which is not collision-
   resistant.  They detect accidental corruption within an artifact and
   across a file set; they are not integrity guarantees against a
   deliberately constructed artifact, which the artifact name provides.

   Three distinct operations apply to a stored artifact, each over a
   different byte extent (Section 4.1.1): name computation covers the
   complete stored bytes, including any signature wrapper; Z card
   verification covers the stripped card stream from which the wrapper



Hipp, et al.             Expires 30 January 2027               [Page 40]

Internet-Draft           Fossil Artifact Format                July 2026


   has been removed; and signature verification, when performed, covers
   the complete stored bytes before stripping.  Implementations MUST
   keep these operations separate: the input to Z card verification MUST
   NOT include wrapper bytes, and the input to name computation MUST
   include them.  A signed artifact and its unsigned inner content are
   distinct artifacts with distinct names and MUST be handled
   independently.

   The presence of a recognised signature wrapper indicates the byte-
   level structure of the artifact only.  This document specifies which
   byte extents are used for naming, card parsing, and Z card
   verification; it does not mandate signature verification, and it does
   not define signer trust or authorization, certificate management,
   revocation, freshness, or replay prevention.  The presence of a
   wrapper is not evidence that the signature has been verified, that
   the signer is authorized, or that the artifact is protected against
   replay.  Implementations that verify signatures do so through
   mechanisms outside the scope of this document.

   Name assignment on ingest can use a supplied candidate name
   (Section 3.1).  The integrity consequence is separate from the
   storage timing: a receiver that admits content as verified under a
   supplied name without comparing that name to the reconstructed bytes
   (Section 3.4) breaks the integrity binding above for every downstream
   consumer of that repository.  The normal non-clone file receive path
   verifies the reconstructed content before successful admission and
   reports a receive error if the supplied name does not match.  Clone
   file, compressed cfile, and dangling-delta paths may store a
   candidate name before complete verification is possible; such storage
   MUST NOT be treated as evidence that the supplied name matched the
   eventual reconstructed bytes.  Later recoverability or verification
   is still required before derived repository state is relied upon.

   Verification comparisons are exact-lowercase (Section 3.4,
   Section 6.2).  An uppercase-hexadecimal name or digest is invalid and
   can never verify; a token-validation stage MAY reject it or MAY defer
   the failure to verification.  Implementations MUST NOT treat token-
   validation acceptance as evidence of verified integrity.

   The reserved-filename drop (Section 4.6.3) removes only matching
   current F-card filenames from the effective file set, after decoded-
   name sort checking, and does not fail the parse.  The artifact's name
   covers the dropped bytes, so two readers disagree about an affected
   manifest's file set only if one omits the drop; a conformant reader
   applies the same deterministic predicate.  Implementations comparing
   file sets across readers of unknown provenance should account for
   this carve-out.




Hipp, et al.             Expires 30 January 2027               [Page 41]

Internet-Draft           Fossil Artifact Format                July 2026


   The W card body is located by byte count (Section 4.7.18).  A reader
   MUST use the size value obtained by the reader-acceptance rule, MUST
   NOT scan the body for card boundaries, MUST bound the declared size
   against the remaining artifact length before consuming it, and MUST
   reject size-token accumulator overflow.  A parser MUST NOT read
   beyond the end of the artifact buffer under any malformed input.

   A repeated Z line earlier in an artifact is ordinary content covered
   by the final checksum (Section 4.5.1); only the final 35 bytes
   participate in self-checksum verification.  Tools that scan artifacts
   textually for a Z card can be misled; verification MUST use the byte-
   position framing of Section 6.2.

   The artifact set is grow-only: reconstructing the file set of a delta
   manifest, or verifying any artifact, requires that the referenced
   artifacts (the baseline of a delta manifest, the source of a delta,
   the parents of a check-in) be present.  A reader that lacks a
   referenced artifact cannot complete these operations and treats the
   reference as unresolved until the artifact is obtained (Section 8.3);
   [FossilSync] specifies how missing artifacts are requested.

10.  IANA Considerations

   This document has no IANA actions.

11.  References

11.1.  Normative References

   [FIPS202]  National Institute of Standards and Technology, "SHA-3
              Standard: Permutation-Based Hash and Extendable-Output
              Functions", FIPS 202, DOI 10.6028/NIST.FIPS.202, August
              2015, <https://nvlpubs.nist.gov/nistpubs/FIPS/
              NIST.FIPS.202.pdf>.

   [FossilDelta]
              Hipp, D. R., Ed., Beal, S., and D. Shearer, "The Fossil
              Delta Format", Work in Progress, Internet-Draft, draft-
              fossil-delta-format-00, 2026,
              <https://datatracker.ietf.org/doc/html/draft-fossil-delta-
              format-00>.










Hipp, et al.             Expires 30 January 2027               [Page 42]

Internet-Draft           Fossil Artifact Format                July 2026


   [FossilRepoState]
              Hipp, D. R., Ed., Beal, S., and D. Shearer, "The Fossil
              Distributed Version Control System: Repository State and
              Check-in Resolution", Work in Progress, Internet-Draft,
              draft-fossil-repo-state-00, 2026,
              <https://datatracker.ietf.org/doc/html/draft-fossil-repo-
              state-00>.

   [FossilSync]
              Hipp, D. R., Ed., Beal, S., and D. Shearer, "The Fossil
              Distributed Version Control System: Sync Protocol", Work
              in Progress, Internet-Draft, draft-fossil-sync-protocol-
              00, 2026, <https://datatracker.ietf.org/doc/html/draft-
              fossil-sync-protocol-00>.

   [RFC1321]  Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321,
              DOI 10.17487/RFC1321, April 1992,
              <https://www.rfc-editor.org/rfc/rfc1321>.

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119,
              DOI 10.17487/RFC2119, March 1997,
              <https://www.rfc-editor.org/rfc/rfc2119>.

   [RFC3174]  Eastlake 3rd, D. and P. Jones, "US Secure Hash Algorithm 1
              (SHA1)", RFC 3174, DOI 10.17487/RFC3174, September 2001,
              <https://www.rfc-editor.org/rfc/rfc3174>.

   [RFC5234]  Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax
              Specifications: ABNF", STD 68, RFC 5234,
              DOI 10.17487/RFC5234, January 2008,
              <https://www.rfc-editor.org/rfc/rfc5234>.

   [RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
              2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
              May 2017, <https://www.rfc-editor.org/rfc/rfc8174>.

11.2.  Informative References

   [GSET]     Shapiro, M., Preguica, N., Baquero, C., and M. Zawirski,
              "A comprehensive study of Convergent and Commutative
              Replicated Data Types", INRIA RR-7506, January 2011,
              <https://hal.inria.fr/inria-00555588>.

   [RFC8792]  Watsen, K., Auerswald, E., Farrel, A., and Q. Wu,
              "Handling Long Lines in Content of Internet-Drafts and
              RFCs", RFC 8792, DOI 10.17487/RFC8792, June 2020,
              <https://www.rfc-editor.org/rfc/rfc8792>.



Hipp, et al.             Expires 30 January 2027               [Page 43]

Internet-Draft           Fossil Artifact Format                July 2026


Appendix A.  Examples

   The examples in this appendix are non-normative.  Each subsection
   shows a complete artifact or exact byte sequence sufficient to
   reproduce the name, checksum, or merge result stated there.  In every
   case, the artifact name, checksum, and byte-count claims shown here
   recompute from the exact displayed byte sequence.

   Some literal lines exceed the width available here and are folded
   using the single-backslash strategy of [RFC8792]; a block containing
   folded lines carries the header that the strategy prescribes.  No
   unfolded artifact line ends in a backslash, so unfolding is
   unambiguous.

A.1.  Artifact Naming

   A Fossil artifact name is the lowercase hexadecimal encoding of
   either the SHA-1 or SHA3-256 cryptographic hash of the artifact's raw
   bytes, with no length prefix, framing, or modification.

   Artifacts created before the SHA3 transition carry 40-character
   names; those created afterward carry 64-character names.  Both
   families are stored and retrieved identically.

A.1.1.  SHA-1 Example

   The following is a complete check-in manifest with a 40-character
   (SHA-1) name.  Every byte shown is part of the artifact as stored; no
   bytes are omitted.

   C initial\sempty\sbaseline
   D 2007-07-21T14:09:59
   P
   R d41d8cd98f00b204e9800998ecf8427e
   U drh
   Z c62e3619f7c41ee77b33f00df8ec26f4

   Artifact name: a28c83647dfa805f05f3204a7e146eb1f0d90505

   SHA-1 of the 127 bytes above equals this name exactly.

   This artifact also demonstrates the empty-P-card tolerance: the P
   card is present but carries no arguments (the line reads P followed
   immediately by a newline).  The artifact is the root check-in of the
   repository, which has no parent.  The R card value
   d41d8cd98f00b204e9800998ecf8427e is the MD5 of an empty file tree.





Hipp, et al.             Expires 30 January 2027               [Page 44]

Internet-Draft           Fossil Artifact Format                July 2026


A.1.2.  SHA3-256 Example

   The following is a complete technote (event) artifact with a
   64-character (SHA3-256) name.

   NOTE: '\' line wrapping per RFC 8792

   C Test\stech-note
   D 2017-12-06T15:36:24.287
   E 2013-08-26T07:35:00 bfdf42305400f6caa441fa816cb89231e90f8c82
   P 94694585cd2f85f75b4316515bbb09aa7e9acaa5
   N text/x-fossil-wiki
   T +bgcolor * #c0f0ff
   U drh
   W 415
   This technote is only for test-purposes.

   The original version of this technote had an empty C-card \
     demonstrating that the C-card in event artifacts are optional. \
     Even when doing a "fossil rebuild" using fossil version \
     1.22, this events displays fine. Of course, making the \
     Timeline Comment non-empty would be better. But nothing \
     in Fossil prevents leaving this line empty, so the C-card \
     could as well be left out.

   Z a7789c6da4c12b8feb6e290f3083f5f0

   Artifact name:
   2fa494a18a766efe9a8ba706d669b7157d5329e1fbcc2a6d6c15a386d113218d

   SHA3-256 of the 655 bytes above equals this name exactly.  The
   SHA3-256 variant used is the standardized Keccak-based function, not
   SHA2-256.

   This artifact also illustrates the P-before-N ordering tolerance: the
   N card (MIME type) appears after the P card even though N sorts
   before P in ASCII order.  This is accepted because the E card has
   already been parsed when N is encountered; see Appendix C.

A.2.  Z-Card Checksum

   The Z card value is the lowercase hexadecimal MD5 of all bytes that
   precede the Z line in the artifact.  The checksum covers from the
   very first byte of the artifact through the newline terminating the
   last card before Z.

   Using the SHA-1 artifact above:




Hipp, et al.             Expires 30 January 2027               [Page 45]

Internet-Draft           Fossil Artifact Format                July 2026


                                             byte offsets
    C initial\sempty\sbaseline\n                   0 ..  26  (27 bytes)
    D 2007-07-21T14:09:59\n                       27 ..  48  (22 bytes)
    P\n                                           49 ..  50  ( 2 bytes)
    R d41d8cd98f00b204e9800998ecf8427e\n          51 ..  85  (35 bytes)
    U drh\n                                       86 ..  91  ( 6 bytes)
                                             -------- 92 bytes checksummed
    Z c62e3619f7c41ee77b33f00df8ec26f4\n          92 .. 126

   MD5(bytes 0 through 91) = c62e3619f7c41ee77b33f00df8ec26f4

   This value matches the Z card exactly.

   The Z card is always the last card in the stripped artifact.  A
   recognised signature wrapper (PGP-cleartext or SSH-signed envelope),
   when present, is an outer envelope around the card stream; wrapper
   bytes are stripped before Z-card verification and are not part of the
   checksum input.

A.3.  R-Card Aggregate Checksum

   The R card value is the lowercase hexadecimal MD5 of a byte string
   formed by concatenating one record per tracked file, in lexicographic
   order of the file path.  Each record is:

   <path> SP <decimal-byte-count> LF <file-content-bytes>

   The decimal byte count is the count of the file content bytes only;
   the header line is not counted.

   The following example uses a check-in with three files:

   NOTE: '\' line wrapping per RFC 8792

   C Add\sthree\stest\sfiles
   D 2026-07-02T11:18:42.940
   F alpha.txt \
     a8009a7a528d87778c356da3a55d964719e818666a04e4f960c9e2439e35f138
   F beta.txt \
     1f6ecac38305308107bc78753cec3b4c390c80e6c1660ac9b5de3273ff479d01
   F gamma.txt \
     67cef386c3cfbb45365917c591deeca9b5c668da781bc743a5f9157ab8f1ac56
   P 9cacef5c0b7713741534ed096e934d0c95d71db734ba569dbcfe70edf798df2f
   R 95feb799536dc053e7968efb7cdd3ec3
   U drh
   Z bbc0f8f7d682cf02ebcea0ece47347f6

   The three file contents and their byte counts are:



Hipp, et al.             Expires 30 January 2027               [Page 46]

Internet-Draft           Fossil Artifact Format                July 2026


           +===========+============+==========================+
           | Path      | Byte count | Content                  |
           +===========+============+==========================+
           | alpha.txt | 12         | hello world\n            |
           +-----------+------------+--------------------------+
           | beta.txt  | 23         | fossil artifact format\n |
           +-----------+------------+--------------------------+
           | gamma.txt | 12         | R card test\n            |
           +-----------+------------+--------------------------+

                                  Table 8

   The R-card input string (85 bytes total) is:

   alpha.txt 12\nhello world\n
   beta.txt 23\nfossil artifact format\n
   gamma.txt 12\nR card test\n

   (Here \n represents a literal newline byte; the above is shown as
   human-readable text.)

   MD5 of these 85 bytes = 95feb799536dc053e7968efb7cdd3ec3, which
   matches the R card.

A.4.  Delta Manifest

   A delta manifest contains a B card identifying a baseline manifest.
   F cards list only those files that differ from the baseline.  Files
   absent from the delta's F cards are inherited unchanged from the
   baseline.

A.4.1.  Baseline Manifest

   NOTE: '\' line wrapping per RFC 8792

   C Baseline:\sthree\sfiles
   D 2026-07-02T11:21:49.651
   F file-a.txt \
     b3cd28e8bc79c1cb9876e546eccbbab42df7b0f77c341b4aa5367ea7fa440ac0
   F file-b.txt \
     780ac49d69af62510e0f2e60ae74457665ababd0ca4acf2a6e61cbce1e86bcec
   F file-c.txt \
     a37be80eddab7fdecfc07fe68d898788b14b3d54d8fd077b5188be57bd397c70
   P 3dc18da551fbdcf5805cb04fb2adf4debf9f12faaaaa66cca9a383d788bfc7f0
   R 06173855f6d58f175132e78ff021ce3a
   U drh
   Z 9456a4a7d875ac24816ce3189b19458b




Hipp, et al.             Expires 30 January 2027               [Page 47]

Internet-Draft           Fossil Artifact Format                July 2026


   This is a full manifest tracking three files.  Its name (SHA3-256) is
   24b831afb9fff3d3ada94e6d3d3731bd04632e3780ded71a668aa174968a30d2.

A.4.2.  Example Delta Manifest

   The following check-in modifies file-a.txt, deletes file-c.txt, and
   adds file-d.txt. file-b.txt is unchanged.

   NOTE: '\' line wrapping per RFC 8792

   B 24b831afb9fff3d3ada94e6d3d3731bd04632e3780ded71a668aa174968a30d2
   C Delta:\sadd\sD,\smodify\sA,\sdelete\sC
   D 2026-07-02T11:21:57.150
   F file-a.txt \
     a61d8bf8fcc44bce875134b1cc61107b3c5dc60411330f11a2b4dc124ebec989
   F file-c.txt
   F file-d.txt \
     4ff0cf8db40756aaae1eba29e028087ae34bfc678c0d0f1429f481939b752ca6
   P 24b831afb9fff3d3ada94e6d3d3731bd04632e3780ded71a668aa174968a30d2
   R 0d7675864b46dd3f197e988759ac2dfa
   U drh
   Z 7d5f4990cfbfb088a1c585be1979d377

   Artifact name:
   66b56d2cd770c9ffa4ed9c93498c1c8312fe791cd580c148ed799bfc57d962e3

A.4.3.  Merge Algorithm

   To reconstruct the complete file tree from a delta manifest, an
   implementation applies the following rules, processing the baseline's
   F cards and the delta's F cards together:




















Hipp, et al.             Expires 30 January 2027               [Page 48]

Internet-Draft           Fossil Artifact Format                July 2026


   +==========================================+=======================+
   | Condition                                | Interpretation        |
   +==========================================+=======================+
   | F card in delta with a UUID; path not in | *ADD* -- file is new  |
   | baseline                                 |                       |
   +------------------------------------------+-----------------------+
   | F card in delta with a UUID; path exists | *MODIFY* -- replace   |
   | in baseline with a different UUID        | baseline file content |
   +------------------------------------------+-----------------------+
   | F card in delta with no UUID argument    | *DELETE* -- file is   |
   | (bare path only)                         | removed from the tree |
   +------------------------------------------+-----------------------+
   | Path in baseline; absent from delta's F  | *CARRY FORWARD* --    |
   | cards                                    | file unchanged        |
   +------------------------------------------+-----------------------+

                                 Table 9

   Applied to the example above:

    +============+===============+========================+==========+
    | File       | Baseline UUID | Delta F card           | Result   |
    +============+===============+========================+==========+
    | file-a.txt | b3cd28e8...   | a61d8bf8... (new UUID) | MODIFIED |
    +------------+---------------+------------------------+----------+
    | file-b.txt | 780ac49d...   | _(absent)_             | CARRY    |
    |            |               |                        | FORWARD  |
    +------------+---------------+------------------------+----------+
    | file-c.txt | a37be80e...   | F file-c.txt _(no      | DELETED  |
    |            |               | UUID)_                 |          |
    +------------+---------------+------------------------+----------+
    | file-d.txt | _(absent)_    | 4ff0cf8d...            | ADDED    |
    +------------+---------------+------------------------+----------+

                                 Table 10

   The reconstructed file set is file-a.txt (new content), file-b.txt
   (unchanged), and file-d.txt (new file).

A.4.4.  R-card Over Reconstructed Set

   The R card in a delta manifest covers the full reconstructed file
   set, not merely the files listed in the delta's own F cards.

   Reconstructed set and content bytes:






Hipp, et al.             Expires 30 January 2027               [Page 49]

Internet-Draft           Fossil Artifact Format                July 2026


   +============+============+=====================+==================+
   | File       | Byte count | UUID                | Content bytes    |
   +============+============+=====================+==================+
   | file-a.txt | 27         | a61d8bf8fcc44bce... | modified content |
   |            |            |                     | of file A\n      |
   +------------+------------+---------------------+------------------+
   | file-b.txt | 18         | 780ac49d69af6251... | content of file  |
   |            |            |                     | B\n              |
   +------------+------------+---------------------+------------------+
   | file-d.txt | 11         | 4ff0cf8db40756aa... | new file D\n     |
   +------------+------------+---------------------+------------------+

                                 Table 11

   The exact R-card preimage is the following 98-byte sequence.  Here \n
   denotes one LF byte, and the three display lines abut directly; do
   not insert quotes, indentation, wrapping, or any other separator
   bytes:

   file-a.txt 27\nmodified content of file A\n
   file-b.txt 18\ncontent of file B\n
   file-d.txt 11\nnew file D\n

   The computed MD5 is 0d7675864b46dd3f197e988759ac2dfa, which matches
   the R card.

Appendix B.  ABNF

   The following grammar is in ABNF [RFC5234].  Card letters and escape
   sequences are case-sensitive and are given as numeric values where
   the quoted-string form would be case-insensitive.  The W card body
   and the byte-counted payloads are opaque bytes located by count
   (Section 4.7.18) and are shown as counted rules rather than by
   content.  The grammar gives the canonical writer wire syntax only;
   ordering (Section 4.4), occurrence (Section 4.5.1), per-type legality
   (Section 5.2), the validity predicates (Section 4.6), checksum
   verifications (Section 6), and reader compatibility acceptances are
   specified in the body.

   In particular, size = "0" / ( nonzero-digit *DIGIT ) is the writer
   form for a W card size token.  Reader acceptance of suffix-bearing or
   no-leading-digit size tokens is the compatibility behaviour specified
   in Section 4.7.18, not a permission for writers to emit those forms.








Hipp, et al.             Expires 30 January 2027               [Page 50]

Internet-Draft           Fossil Artifact Format                July 2026


 artifact    = 1*card
               ; final byte of the artifact is LF

 card        = a-card / b-card / c-card / d-card / e-card /
               f-card / g-card / h-card / i-card / j-card /
               k-card / l-card / m-card / n-card / p-card /
               q-card / r-card / t-card / u-card / w-card /
               z-card

 a-card      = %x41 SP filename SP target [ SP hash ] LF
 target      = hash / wikiname
 b-card      = %x42 SP hash LF
 c-card      = %x43 SP comment LF
 d-card      = %x44 SP timestamp LF
 e-card      = %x45 SP timestamp SP hash LF
 f-card      = %x46 SP filename
               [ SP hash [ SP perm [ SP old-name ] ] ] LF
 g-card      = %x47 SP hash LF
 h-card      = %x48 SP token LF
 i-card      = %x49 SP hash LF
 j-card      = %x4A SP token [ SP token ] LF
 k-card      = %x4B SP 40hexdig-ci LF  ; parser-tolerated/reference form
 l-card      = %x4C SP wikiname LF
 m-card      = %x4D SP hash LF
 n-card      = %x4E SP token LF
 p-card      = %x50 *( SP hash ) LF
 q-card      = %x51 SP q-sign hash [ SP hash ] LF
 q-sign      = "+" / "-"
 r-card      = %x52 SP md5-token LF
 t-card      = %x54 SP tag-sign token SP ( hash / "*" )
               [ SP token ] LF
 tag-sign    = "+" / "-" / "*"
 u-card      = %x55 [ SP [ token ] ] LF
 w-card      = %x57 SP size LF body LF
 size        = "0" / ( nonzero-digit *DIGIT )
 nonzero-digit = %x31-39
 body        = *OCTET
               ; exactly <size> octets; MAY contain LF;
               ; located by count, not by scanning
 z-card      = %x5A SP md5-token LF

 token       = 1*tchar
 tchar       = %x00-09 / %x0B-1F / %x21-FF
               ; any octet except SP (0x20) and LF (0x0A)
 comment     = token          ; escape-decoded
 filename    = token          ; escape-decoded; pathname predicate
 old-name    = token          ; escape-decoded; pathname predicate
 perm        = token          ; old-name requires perm; SHOULD be w/x/l



Hipp, et al.             Expires 30 January 2027               [Page 51]

Internet-Draft           Fossil Artifact Format                July 2026


 wikiname    = token          ; escape-decoded; wiki-name predicate

 hash        = 40hexdig-ci / 64hexdig-ci
 md5-token   = 32hexdig-ci
 hexdig-ci   = DIGIT / %x41-46 / %x61-66
 lhexdig     = DIGIT / %x61-66

 timestamp   = date %x54 time [ frac ]    ; writer form; %x54 = "T"
 date        = 4DIGIT "-" 2DIGIT "-" 2DIGIT
 time        = 2DIGIT ":" 2DIGIT ":" 2DIGIT
 frac        = "." 1*DIGIT

 ; Artifact names
 artifact-name = sha1-name / sha3-name    ; writer form
 sha1-name     = 40lhexdig
 sha3-name     = 64lhexdig
 accepted-name = 40hexdig-ci / 64hexdig-ci  ; parser-tolerated/reference
                                            ; form, not required

 SP          = %x20
 LF          = %x0A
 DIGIT       = %x30-39
 OCTET       = %x00-FF

Appendix C.  Anomalous artifacts and behaviours

   The following statements in existing Fossil documentation, or in text
   accompanying existing implementations, do not match the behaviour
   specified in the body of this document.  The body is definitive; the
   divergent statements are recorded here for reference.

   *Manifest required cards.* The file-format documentation presents the
   C and U cards as mandatory on a manifest, implying a required set of
   {C, D, U, Z}. The enforced required set is {D, Z} (Section 5.2): the
   C and U cards are optional on a manifest, a relaxation retained for
   compatibility with historical artifacts.

   *Z card on manifests.* One passage accompanying an existing
   implementation states that the Z card is required for all artifact
   types except manifests.  A manifest lacking a Z card is rejected; the
   Z card is required for every artifact type (Section 5.2).










Hipp, et al.             Expires 30 January 2027               [Page 52]

Internet-Draft           Fossil Artifact Format                July 2026


   *Wiki user card.* The file-format documentation recommends accepting
   a wholly missing U card on a wiki artifact as an alias for the user
   nobody.  That recommendation is unimplemented: a wiki artifact
   lacking a U card is rejected by the required-card rule (Section 5.2),
   and a present-but-empty U card defaults to anonymous
   (Section 4.7.17).  Three mutually distinct behaviours -- reject,
   nobody, anonymous -- appear across documentation and behaviour; the
   body specifies the first and third.

   *G card chain invariant.* The file-format documentation states that a
   forum post whose G card does not match the thread root reached via
   its I and P chains is invalid and should be ignored.  No parser
   enforces this cross-artifact property, and this document does not
   require it (Section 5.4).

   *Timestamp separator.* Passages accompanying existing implementations
   render the D and E card timestamp separator as a lowercase t (YYYY-
   MM-DDtHH:MM:SS).  The accepted separator is uppercase T only
   (Section 4.6.4); a lowercase t is rejected.

   *Signature wrappers.* The file-format documentation describes only
   the PGP clearsign wrapper.  SSH signed wrappers are also removed
   (Section 4.1.1); their acceptance had been undocumented behaviour,
   made explicit by this document.

   *J card encoding.* The file-format documentation states that the J
   card field name and value are both escape-encoded.  Only the value is
   decoded; the field name is stored verbatim (Section 4.7.8).  Existing
   implementations differ here, one siding with the documentation.

   *Decoded-token positions.* Existing implementations differ at two
   decoded token positions: one does not decode the N card mimetype, and
   one decodes the J card field name.  The body's decode map is the
   operative rule (Section 4.3.1).

   *N-after-P ordering exception.* The parser accepts an N card
   immediately after a P card once a valid E card has made the artifact
   a technote.  That compatibility exception is part of the ordering
   rule; other out-of-order cards remain rejected (Section 4.4).












Hipp, et al.             Expires 30 January 2027               [Page 53]

Internet-Draft           Fossil Artifact Format                July 2026


   *F permission-token receiver divergence.* Existing implementations
   historically differed on parse-time validation of the third F-card
   positional field.  One stores any raw token verbatim and later
   searches it for x (executable) or l (symlink), with everything else
   resolving to a regular file; another accepts only absent, w, x, or l
   at parse time.  The body settles the interoperable public rule: third
   position is always the raw permission token, fourth position (when
   present) is old-name, and producers still SHOULD emit w, x, or l
   (Section 4.7.6).

   *P-card multiplicity divergence.* The ordering rule permits a second
   P card, because equal consecutive type letters pass the non-
   decreasing check.  One parser concatenates the tokens of repeated P
   cards into a single parent list; another rejects a second P card.
   The body gives interoperable producer guidance without converting
   that divergence into a stronger receiver requirement
   (Section 4.7.13).

   *Reserved filename drop.* The file-format documentation's F card
   description contains no mention of the reserved-name silent drop
   (Section 4.6.3), which alters the effective file set of affected
   historical manifests.

   *Default hash policy.* Some user documentation states that the
   default hash policy for new repositories is shun-sha1.  The default
   derivation (Section 7.2) never produces shun-sha1; for an empty or
   new repository it produces sha3.

Authors' Addresses

   D. Richard Hipp (editor)
   Fossil


   Stephan Beal
   libfossil


   Dan Shearer
   Email: dan@shearer.org
   URI:   https://shearer.org










Hipp, et al.             Expires 30 January 2027               [Page 54]