Skip to content
zit The clone that could not sign its first request
Login

The clone that could not sign its first request

A login card is signed with a secret derived from the password and the project code. A clone does not know the project code; learning it is what the first reply is for. So a clone cannot sign its first request, and fossil's client does not try: on a clone's round zero it sends no login at all.

That leaves a read-gated repository with a puzzle. The server must refuse an anonymous read, and it does, with an error card. But fossil's server puts one more card in front of that refusal: push SERVERCODE PROJECTCODE. It teaches the project code in the same breath as it refuses. And fossil's client, on a clone's first round only, discards the error card, derives the secret from the code it was just taught, and sends the clone card again with a login. The refusal is the handshake.

zit's clone and pull sent no login at all, on any round. Only push and sync did. A private repository on a forge that gates reads was unreadable by the account that owned it, and the forge's deliberate 404, which reveals nothing about whether the repository exists, pointed at nothing. A login stored by an earlier push sat on disk while the next pull read anonymously.

0.3.22 resolves the login the same way for all four verbs: --user, then the user@ in the remote URL, then the stored login. A clone holds the name and password until round zero names the project code, then signs every later round, and a refused round zero that taught the code is the retry point rather than a failure. The login the peer accepted is stored in the new clone, so the next pull authenticates unasked.

Two things the shape decided. A user named only by the URL is a hint: with no password to be had, the round goes anonymous and says which credential it wanted, so the 404 finally points somewhere; an explicit --user with no password is an error. And the prompt asks nothing off a terminal, because a script or an autosync cannot answer it.

The proof runs against a real fossil with read stripped from nobody and anonymous: an anonymous zit clone is refused, a clone with --user is served through the round-zero retry, and a bare pull from that clone reuses the stored login.