fangorn/ex_git_objectstore
public
feat(lfs): implement git-lfs-authenticate SSH handoff #65
Links
No links yet.
Problem
ex_git_objectstore ships the Git LFS HTTP API (Lfs.Batch, Lfs.Transfer, Lfs.Locks) but provides nothing for the SSH transport path. When a client’s remote is an SSH URL (git@host:repo.git), git lfs does not speak LFS over SSH — it first runs:
ssh git@host git-lfs-authenticate <path> <upload|download>
and expects a JSON blob back on stdout telling it where the HTTP LFS endpoint is and how to authenticate:
{ "href": "https://host/repo.git/info/lfs", "header": { "Authorization": "..." }, "expires_in": 3600 }
Only then does it run the Batch API over HTTP. With no handler for this command, SSH clients have no way to discover the LFS endpoint.
Root cause
The library is a transport-agnostic engine: it exposes protocol state machines (UploadPack/ReceivePack) and LFS HTTP handlers, and the consumer wires them to a transport. There is no module that produces the git-lfs-authenticate response, so a consumer’s SSH command dispatcher has nothing to call. Confirmed: rg git-lfs-authenticate lib test returns nothing.
Scope
- New pure module
ExGitObjectstore.Lfs.Authenticatewithhandle/3returning the spec JSON map (href,header,expires_in/expires_at). - Library does NOT invent an auth scheme: the consumer passes the
Authorizationtoken (or omits it) and the LFS base href; the module assembles and validates the response. Operation must beuploadordownload. - Reject unconfigured LFS (
lfs_storage: nil) and invalid operations. - Docs: how a consumer wires the SSH
git-lfs-authenticatecommand to this handler.
Acceptance criteria
Authenticate.handle/3returns a map JSON-encodable to exactly whatgit lfsaccepts (verified against git-lfs 3.7).- Unit tests cover: upload op, download op, invalid op, LFS-not-configured, header passthrough, expiry.
- Interop: real
git lfsdiscovers the endpoint via the handoff and completes a push/pull + a lock over an SSH-style remote (no explicitlfs.url). - CHANGELOG updated;
anvil requirement statuspasses.