# Requirements of draft-fossil-sync-protocol-01, written from the draft text.
# Each requirement names the role it binds: "Client:", "Server:", "Sender:"
# (whichever end emits the card) or "Receiver:" (whichever end parses it).
# Format: <id>\t<section>\t<requirement>[\t<scope note>]
# Skipped, with reasons, in the suite's report: §12 (IANA), §11.2 (deployment
# advice), §4 SSH and User-Agent details (no SSH transport), §7.6 SYNC_IFABLE
# (no autopush mode in the library), §8.2 "MUST NOT infer count" and §8.8
# non-persistence (not observable), §10.2 display, §8.6.1 (repo-state draft).
# The -01 errata are applied in the draft; they are pinned for the fossil(1) 2.28
# behavior they record, which the cases for SP-5.1-3 and SP-5.1-4 depart from.
# draft	draft-fossil-sync-protocol-01.txt	b19c7cfc8f69bb41008138aab6400c3382a0f85ff9587268e5b879d7e8f09b32
# erratum	sync-protocol-01-s5.1-truncated-payload-receiver.md	0e08208def3084ac18abe552c2dcd96fb6e0fcdf151d8e93b777e3b223478dfc
# erratum	sync-protocol-01-s5.3-errors-count.md	752da0b6944f341a650861b0423b7960df054db3e76a5485efe7b1d745c20573
# erratum	sync-protocol-01-s6.6-file-card-after-refused-push.md	5857e99624ece02cbf15be63f5476c54b1a4f29e5fd28cc682653059e9bbcae4
SP-3.2-1	3.2	Client: every request carries pragma client-version.
SP-3.2-2	3.2	Client: pragma client-version precedes every content-requesting card (gimme, uvgimme, reqconfig) in the request.
SP-3.2-3	3.2	Client: every request ends with a comment line of random bytes.
SP-3.2-4	3.2	Client: in private sync, pragma send-private precedes client-version in the first request and follows it in later requests.
SP-3.2-5	3.2	Client: a push, pull or sync session carries its push and/or pull card in every request until Section 10.2 suppresses push.
SP-3.2-6	3.2	Client: a returned state cookie follows the fixed operation card, or client-version when there is none.
SP-3.2-7	3.2	Server: a completed reply ends with the "# timestamp DATETIME errors N" comment.
SP-3.2-8	3.2	Server: pragma server-version precedes every clone-specific card in a clone reply.
SP-3.3-1	3.3	Receiver: igot HASH creates a phantom only when HASH is absent and the current direction lets the receiver obtain it (client pull or clone, server push).
SP-3.3-2	3.3	Receiver: a delta file or cfile whose DELTASRC is absent stores the delta, deletes HASH's phantom, creates a DELTASRC phantom and sets the content-received flag; no per-artifact received state is kept, and HASH is not requested again.
SP-3.3-3	3.3	Client: the phantom scan requests no hash the peer asked for this round, no shunned name and no private hash unless private sync is on.	the peer-lacks filter is not covered: fossil(1) 2.28 asks again for a hash the last reply gimme-d
SP-3.3-4	3.3	Receiver: a gimme for content the current direction may not send produces neither content nor an error and is not deferred.
SP-3.3-5	3.3	Receiver: a gimme for an absent hash is silently skipped.
SP-3.3-6	3.3	Receiver: a gimme for held content that direction and policy permit is answered with that content in this or a later message.
SP-3.6-1	3.6	Client: a received cookie card replaces the stored cookie.
SP-3.6-2	3.6	Server: does not depend on a cookie and tolerates foreign and repeated cookie cards.
SP-3.7-1	3.7	Client: continues when stored content or an igot-created phantom leaves the phantom table non-empty (limb a).
SP-3.7-2	3.7	Client: continues when processing the reply appended file or delta content to the next request, or the UV upload phase is selected (limb b).
SP-3.7-3	3.7	Client: continues once when, without private sync, the first round's reply was answered by appending at least one igot HASH 1 for a gimme of private content (limb c).	no case: needs a server that answers a private gimme with igot HASH 1 to the first request
SP-3.7-4	3.7	Client: continues for uvgimme as limb d states: sent uvgimme with a uvfile reply or round below 3, or a uvgimme appended.
SP-3.7-5	3.7	Client: a modern clone continues after the first round, after a round that stored content, or while a positive sequence and the raw artifact count advance (limb e).
SP-3.7-6	3.7	Client: remaining phantoms alone neither continue the session nor cause an error.
SP-3.7-7	3.7	Client: with no continuation condition true, the session stops without another request.
SP-3.9-1	3.9	Sender: never emits a card with a seventh token.
SP-3.9-2	3.9	Receiver: tokens beyond the sixth are invisible to card handlers and create no other card condition.
SP-4-1	4	Client: posts to the repository URL path unchanged and never appends /xfer.
SP-4-2	4	Client: every request carries an exact Content-Length and a nonempty body.
SP-4-3	4	Server: a POST with Content-Type application/x-fossil or application/x-fossil-debug dispatches to sync whatever its path.
SP-4-4	4	Client: follows at most 19 redirects with status 301, 302, 307 or 308, re-posting the same request body; the twentieth is fatal.	the twentieth redirect being fatal is not covered
SP-4-5	4	Client: refuses a redirect from HTTPS to HTTP.
SP-4-6	4	Client: strips one trailing /xfer, if present, from a redirect target before using it as the new base.
SP-4-7	4	Client: only HTTP 200 is a protocol reply; any other non-redirect status aborts before card parsing.
SP-4-8	4	Client: a reply without Content-Type is compressed; an x-fossil-debug or x-fossil-uncompressed prefix is uncompressed; an x-fossil prefix is compressed; any other type is rejected.
SP-4.1-1	4.1	Sender: the compressed container is the 4-byte big-endian actual input length followed by a zlib stream.
SP-4.1-2	4.1	Client: production requests use application/x-fossil, never application/x-fossil-debug.
SP-4.1-3	4.1	Receiver: the advertised container length is a capacity; a shorter decoded body is not rejected for that alone.
SP-4.1-4	4.1	Receiver: bytes after a successfully decoded zlib stream are ignored.
SP-4.1-5	4.1	Server: a clone version 3 reply is sent as application/x-fossil-uncompressed.
SP-4.1-6	4.1	Receiver: decodes the container whatever DEFLATE level it was compressed at.
SP-4.2-1	4.2	Client: a reply that ends without a terminal card is complete, not an error.
SP-5.1-1	5.1	Receiver: a byte-counted payload ends only at its declared count and may contain LF and card-like text.
SP-5.1-2	5.1	Sender: a cfile payload not ending in LF is followed by one padding LF, which the receiver consumes as an empty line.
SP-5.1-3	5.1	Server: a payload cut short by the end of the body is not stored; the card is a validation failure of its handler, with error malformed file line, malformed cfile line or malformed uvfile line.
SP-5.1-4	5.1	Client: a payload cut short by the end of the reply is not stored; the client stops reading the reply at that card and keeps the prefix it processed.
SP-5.2-1	5.2	Sender: emits canonical cards: one SP between tokens, no leading or trailing whitespace, one LF.
SP-5.2-2	5.2	Receiver: accepts canonical cards and splits tokens on at most SP, HTAB, VT, FF and CR runs.	other bytes, including UTF-8 spaces, stay in the token
SP-5.2-3	5.2	Receiver: defossilizes fossilized arguments.
SP-5.2-4	5.2	Server: an unknown operator resets accumulated output, emits error with fossilized TEXT "bad command: LINE" and continues with later request cards.
SP-5.2-5	5.2	Client: an unknown operator records a local warning, sends no error, and ends the reply-card loop; earlier cards stay effective and continuation is evaluated.
SP-5.2-6	5.2	Server: a defined operator with the wrong arity or received in the wrong direction (including client-sent error and clone_seqno) gets error bad command and later cards are processed.
SP-5.2-7	5.2	Server: a file, cfile or uvfile handler validation failure resets output, emits the handler's fossilized error, counts it and stops request parsing.
SP-5.2-8	5.2	Client: a malformed defined card records a warning and ends the reply-card loop; earlier cards stay effective and continuation is evaluated.
SP-5.2-9	5.2	Receiver: private ignores visible surplus tokens and still sets the marker.
SP-5.2-10	5.2	Receiver: igot accepts at least two visible tokens; a third token of exactly 1 marks it private, any other third token public, and later tokens are ignored.
SP-5.2-11	5.2	Receiver: imposes no maximum line length before LF.
SP-5.3-1	5.3	Receiver: a line beginning with # is not dispatched as a card.
SP-5.3-2	5.3	Server: the timestamp comment is "# timestamp YYYY-MM-DDTHH:MM:SS errors N" in UTC with N canonical decimal.
SP-5.3-3	5.3	Server: answering req-clusters, a nonempty run of public cluster igot cards is enclosed by # sending-clusters and # end-of-clusters, and an empty run by neither.
# SP-5.3-4 is FAILING: Tracked in #374.
SP-5.3-4	5.3	Server: N counts the errors raised while handling the request, including those whose cards a later reset discarded; the unknown-operator error, the private-content refusal and the SHA3 version refusal are not counted.	the SHA3 version refusal is not covered
SP-5.3-5	5.3	Receiver: does not act on N.
SP-6.1-1	6.1	Sender: the login card is login USER NONCE SIGNATURE with USER fossilized and NONCE and SIGNATURE 40 lowercase hex characters.
SP-6.1-2	6.1	Server: a second login in one request is fatal: output is reset and an error emitted.
SP-6.2-1	6.2	Client: NONCE is the SHA-1 of every decompressed body byte after the login line's LF.
SP-6.3-1	6.3	Client: the shared secret is SHA1(project-code "/" login "/" password) in lowercase hex.
SP-6.4-1	6.4	Client: SIGNATURE is SHA1 of the NONCE hex followed by the shared-secret hex.
SP-6.4-2	6.4	Server: nobody and anonymous logins succeed without a signature check.
SP-6.4-3	6.4	Server: a named login succeeds when SHA1(NONCE || stored credential) equals SIGNATURE, compared case-sensitively.
SP-6.4-4	6.4	Server: when that fails and the stored credential is not exactly 40 bytes, the secret is derived from the stored cleartext and retried.
SP-6.4-5	6.4	Server: NONCE must equal the SHA-1 of the body after the login line, compared case-sensitively.
SP-6.4-6	6.4	Server: a failed login keeps HTTP 200, discards staged output, emits error login failed and ends card processing without rolling back the request.
SP-6.4-7	6.4	Server: a successful login only adds capabilities to the request's baseline.
# SP-6.4-8 is FAILING: Tracked in #374.
SP-6.4-8	6.4	Server: after a failed login, the end-of-request steps still run for a direction an earlier card established, and the reply ends with the timestamp comment.
SP-6.5-1	6.5	Client: once the recorded server version passes the gate (VERSION >= 22700 and DATE/TIME at or after 20250727 110500), login goes in Cookie: x-f-l-c=login+USER+NONCE+SIGNATURE and no body login is sent.
SP-6.5-2	6.5	Client: before server-version is seen, or when the gate is false, a named login uses the body card and never the cookie.
SP-6.5-3	6.5	Server: accepts body login whatever the gate.
SP-6.5-4	6.5	Server: accepts a login carried in the x-f-l-c cookie through the body-login path.
SP-6.6-1	6.6	Server: each card is checked against its capability (o read, i write, g clone, x private, a admin) and an error is emitted when it is lacking.	Admin is checked by the case for SP-9.3-6
SP-6.6-2	6.6	Server: a push without Write after an accepted pull gets message "pull only - not authorized to push" without a reset; otherwise output is reset and error not authorized to write is emitted; neither ends card processing.
# SP-6.6-3 is FAILING: Tracked in #374.
SP-6.6-3	6.6	Server: while push is not enabled, the first file or cfile card is refused with reset output and error not authorized to write, ends card processing, and end-of-request steps for an earlier direction still run.
SP-7.1-1	7.1	Receiver: file HASH SIZE and file HASH DELTASRC SIZE carry exactly SIZE payload bytes with no trailing separator.
SP-7.1-2	7.1	Sender: push and pull transfer content with file cards, not cfile.
SP-7.2-1	7.2	Receiver: cfile HASH [DELTASRC] USIZE CSIZE carries exactly CSIZE payload bytes.
SP-7.2-2	7.2	Receiver: USIZE is parsed but not validated against the payload at the transfer layer.
SP-7.2-3	7.2	Server: a clone cfile payload is the repository's stored compressed blob, retransmitted verbatim.
SP-7.2-4	7.2	Server: clone version 3 transfers content with cfile cards only.
SP-7.3-1	7.3	Receiver: uvfile NAME MTIME HASH SIZE FLAGS has a fossilized NAME, carries SIZE payload bytes unless FLAGS has 0x0001 or 0x0004, and HASH is a hash or -.	NAME fossilization is not covered: fossil(1) refuses an unversioned name that needs escaping
SP-7.3-2	7.3	Receiver: rejects negative FLAGS and ignores reserved FLAGS bits.
SP-7.3-3	7.3	Sender: emits a deletion as HASH -, SIZE 0 and FLAGS with 0x0001 set, and clears reserved FLAGS bits.
SP-7.3-4	7.3	Receiver: HASH - with a positive SIZE and no payload-suppressing flag is rejected without storing or deleting.
SP-7.3-5	7.3	Receiver: before applying a uvfile, recomputes its status from the current row: statuses 3 to 5 change nothing and status 2 updates MTIME only.
SP-7.3-6	7.3	Receiver: content omitted by FLAGS 0x0004, or SIZE 0, is stored with size zero and NULL content.
SP-7.3-7	7.3	Server: a client uvfile requires UV write permission, and an unauthorized one is an error.
SP-7.3-8	7.3	Server: a uvgimme for an absent NAME emits no card.
SP-7.3-9	7.3	Server: a uvgimme is answered with uvfile FLAGS 0 for a live file or HASH - SIZE 0 FLAGS 1 for a tombstone.
SP-7.3-10	7.3	Receiver: for status 0 or 1, a uvfile creates or replaces the row with the received NAME, MTIME, HASH and content.
SP-7.3-11	7.3	Server: a uvgimme from a requester without Read permission emits neither content nor error.
SP-7.3-12	7.3	Server: for the uvgimme Read check, Clone permission implies Read.
SP-7.4-1	7.4	Receiver: a card for an already verified HASH is consumed and ignored and never replaces or downgrades it; delta-source handling may run first or be skipped.
SP-7.4-2	7.4	Receiver: for an unverified target with a missing DELTASRC, the delta is kept under HASH and the DELTASRC phantom carries the card's private classification.
SP-7.5-1	7.5	Client: private marks the next file or cfile; repetition, comments, other cards and uvfile do not consume it, and it survives a reply boundary.
SP-7.5-2	7.5	Server: private sets the marker only for a sender with Private capability; otherwise it emits the private authorization error and leaves no marker.
SP-7.5-3	7.5	Receiver: entering the file or cfile handler clears the marker, so it applies to one card.
SP-7.5-4	7.5	Sender: never sends a delta against a private basis to a peer without private authorization; it sends full content.
SP-7.5-5	7.5	Receiver: an unauthorized igot HASH 1 is not an error and creates no phantom, but reclassifies a held HASH or phantom as private.
SP-7.5-6	7.5	Server: private content is sent only after a successful send-private.
SP-7.6-1	7.6	Sender: to a peer whose recorded VERSION is below 20000, a SHA3 file or cfile, or a uvfile with a 64-hex HASH, is replaced by error Fossil version 2.0 or later required., and the rest of the message is still built.
SP-7.6-2	7.6	Server: the client VERSION is 0 until pragma client-version arrives.
SP-7.6-3	7.6	Client: the recorded server VERSION starts as the client's own release and is replaced by server-version.
SP-7.7-1	7.7	Receiver: a non-clone file whose target is in the shun table is consumed and discarded with no error, no content-received and no mutation.
SP-7.7-2	7.7	Receiver: a cfile with a shunned target is discarded after its payload, even in a clone.
SP-7.7-3	7.7	Receiver: admission applies to the target hash, not the DELTASRC.
SP-7.7-4	7.7	Receiver: before commit, every newly stored artifact whose bytes are available is hashed and a mismatch aborts the commit.
SP-8-1	8	Client: a clone starts with client-version, clone 3 1 and randomness, and no login card.
SP-8.1-1	8.1	Server: an authorized three-token clone with integer VERSION >= 2 and a digit-only SEQNO of 0 clears output, rolls back, emits error invalid clone sequence number and stops parsing.
SP-8.2-1	8.2	Server: an accepting clone reply sends cfile cards in RID order from SEQNO, skipping gaps, then clone_seqno NEXT, then push SERVERCODE PROJECTCODE; NEXT 0 marks exhaustion.
SP-8.2-2	8.2	Client: records a digit-only NEXT; a nondecimal NEXT leaves the sequence unchanged and does not stop parsing.
SP-8.2-3	8.2	Server: a clone authorization refusal resets output and emits push SERVERCODE PROJECTCODE then error, with no cfile and no clone_seqno.
SP-8.2-4	8.2	Client: reissues clone 3 NEXT only when the reply carried a well-formed push and NEXT is positive; otherwise it sends the operation-less cleanup.
SP-8.2-5	8.2	Client: after NEXT 0 no clone, pull or push card is sent; cleanup carries no operation card.
SP-8.2-6	8.2	Server: in a directionless request, gimme yields neither file, cfile nor error.
SP-8.2-7	8.2	Server: accepts and ignores igot cards received without push enablement.
SP-8.3-1	8.3	Client: an error in the first clone reply is not fatal: later cards are parsed, a later push is recorded and the second clone request is made.
SP-8.4-1	8.4	Client: reqconfig and uv-hash are deferred until after clone round 0.	no case: go-libfossil's Clone sends no reqconfig or uv-hash in any round, having no option for either, so there is nothing to defer
SP-8.4-2	8.4	Server: with UV sync enabled, an authorized clone reply carries pragma uv-pull-only and the full UV catalog.
SP-8.5-1	8.5	Server: a push or pull whose PROJECTCODE differs from the repository's is refused.
SP-8.5.1-1	8.5.1	Client: the UV send table starts with every local row whose hash is non-NULL; tombstones are excluded.
SP-8.5.1-2	8.5.1	Client: pragma uv-hash is sent exactly once, in the first eligible round, never in clone round 0.
SP-8.5.1-3	8.5.1	Sender: the UV catalog hash is the SHA-1 of "NAME SP YYYY-MM-DD SP HH:MM:SS SP HASH LF" for each non-tombstone row, sorted by name bytes.
SP-8.5.1-4	8.5.1	Server: a matching uv-hash gets no catalog; a mismatch with Read gets uv-push-ok or uv-pull-only and one uvigot per entry, tombstones as HASH -.
SP-8.5.1-5	8.5.1	Client: each uvigot is classified into status 0 to 5 and handled as Table 6 states.
SP-8.5.1-6	8.5.1	Client: after uv-pull-only, status 4 and 5 names are removed from the send table.
SP-8.5.1-7	8.5.1	Client: never sends uvigot, neither the well-formed form nor the short tombstone form.	the well-formed form is not covered: the case checks only for the short form fossil(1) 2.28 sends
SP-8.6-1	8.6	Client: under private sync, lists its private inventory as igot HASH 1 in every request that carries push, starting with the first, with no peer-date check.	no case
# SP-8.6-2 is FAILING: Tracked in #375.
SP-8.6-2	8.6	Sender: without private sync, a gimme for private content is answered with igot HASH 1 only when the peer's date is 2020-04-13 or later, and with nothing otherwise.
SP-9-1	9	Receiver: an unknown pragma name is ignored silently, whatever its arguments.
SP-9-2	9	Receiver: a known pragma received in the wrong direction is ignored and changes no state.
SP-9-3	9	Server: a bare pragma with no NAME gets error bad command and later cards are processed.
SP-9.1-1	9.1	Server: a full client-version replaces the peer VERSION, DATE and TIME and is answered with a full server-version; a short one updates VERSION only and gets no reply.
SP-9.1-2	9.1	Client: a full server-version replaces the peer VERSION, DATE and TIME; a short one updates VERSION only.
SP-9.2-1	9.2	Server: on a uv-hash mismatch with Read, sends uv-push-ok when the principal may write unversioned files, otherwise uv-pull-only, exactly once.
SP-9.3-1	9.3	Server: reqconfig without Read is silently ignored.
SP-9.3-2	9.3	Server: reqconfig for a name matching no group emits no config card and no error.
SP-9.3-3	9.3	Sender: a scalar setting is config /config SIZE whose payload is MTIME 'NAME' value 'VALUE', followed by one LF.
SP-9.3-4	9.3	Receiver: consumes one byte after a config payload without checking that it is LF.
SP-9.3-5	9.3	Server: a config card whose SIZE is signed or not decimal takes the bad command path.
SP-9.3-6	9.3	Server: a config card requires Admin; otherwise it emits error not authorized to push configuration and applies nothing.
SP-9.4-1	9.4	Server: ci-lock for a hash held by a different client emits ci-lock-fail LOGIN MTIME; the same client gets no reply; no live lock writes one, unacknowledged.	the lock row written when none is live is not covered
SP-9.4-2	9.4	Server: ci-unlock CLIENT-ID deletes that client's locks and emits nothing.
SP-9.5-1	9.5	Server: send-private without Private capability appends error not authorized to sync private content without resetting output, and parsing continues.
SP-9.5-2	9.5	Client: sends pragma send-private in every private round.
SP-9.5-3	9.5	Server: emits no link pragma in reply to a request without req-links.
SP-9.5-4	9.5	Receiver: stores a link's ARG defossilized and verbatim, and never parses, alters or echoes it.	no case: go-libfossil has no link handling, so no API reaches a received link
SP-10.1-1	10.1	Client: a server error outside the first clone reply ends the reply-card loop; earlier cards stay committed and continuation is evaluated.
SP-10.1-2	10.1	Server: at wrong-project, authorization, duplicate-login and unknown-card errors, partial output is discarded before the error, except for the push refusal's message form.
SP-10.1-3	10.1	Server: the SHA3 gate and unauthorized send-private append their error without reset, and parsing continues.
SP-10.1-4	10.1	Server: card errors keep HTTP status 200.
SP-10.1-5	10.1	Server: only invalid clone sequence number and invalid config record roll back the request; other card errors keep earlier mutations.
SP-10.2-1	10.2	Receiver: message takes exactly two visible tokens, its TEXT is defossilized and it is not fatal.
SP-10.2-2	10.2	Client: with push enabled, a message matching "pull only *" clears push: later gimme cards in that reply append no content and later requests omit push.
SP-10.2-3	10.2	Client: any other message changes no state.
SP-11.4-1	11.4	Sender: never truncates, renames or re-identifies a SHA3 name as SHA1.
