ref:main

feat(lfs): implement git-lfs-authenticate SSH handoff #65

closed Opened by cole.christensen@gmail.com

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.Authenticate with handle/3 returning the spec JSON map (href, header, expires_in/expires_at).
  • Library does NOT invent an auth scheme: the consumer passes the Authorization token (or omits it) and the LFS base href; the module assembles and validates the response. Operation must be upload or download.
  • Reject unconfigured LFS (lfs_storage: nil) and invalid operations.
  • Docs: how a consumer wires the SSH git-lfs-authenticate command to this handler.

Acceptance criteria

  • Authenticate.handle/3 returns a map JSON-encodable to exactly what git lfs accepts (verified against git-lfs 3.7).
  • Unit tests cover: upload op, download op, invalid op, LFS-not-configured, header passthrough, expiry.
  • Interop: real git lfs discovers the endpoint via the handoff and completes a push/pull + a lock over an SSH-style remote (no explicit lfs.url).
  • CHANGELOG updated; anvil requirement status passes.