e7027c8ccc
Fixes #77 ## Why Each upstream 401 re-ran the full token-endpoint request, even though a single Docker pull triggers many blob/manifest requests sharing one scope. ## Changes - Add Redis `GetToken`/`SetToken`. - `fetchBearerToken` now also parses `expires_in` and returns a TTL. - New `Engine.cachedBearerToken` reuses a cached token keyed by remote + challenge (hashed), caching for `expires_in` minus a safety margin (default 60s when absent). ## Validation - `make e2e` passes. Reviewed-on: #92 Co-authored-by: Ben Vincent <ben@unkin.net> Co-committed-by: Ben Vincent <ben@unkin.net>