# git-remote-entire: cache cluster->context binding after first success

`823f034`→[main](/content/gh/entireio/cli/commits/main/index.html)·

toothbrush·1mo ago·2 files·+57 added/-18 removed

Previously every git op against an entire:// cluster re-ran /.well-known
discovery, and successful lookups were never persisted. Bind the
clusterHost->context mapping into contexts.json on the first successful
scoped-token exchange, so subsequent invocations short-circuit on the
stored binding and skip discovery.

Conservative (post-success) variant: the bind fires only after the
cluster has provably authenticated the resolved context, so a host whose
/.well-known matches a local context but then fails to authenticate
leaves no stale binding. Resolution itself stays non-persisting;
makeBindHook (guarded by sync.Once on a freshly-constructed token cache)
owns the write.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

## Sessions

ff5ccce200c0View transcript

## Changes

2

- cmd/git-remote-entire
  
  - Mmain.go+42

- internal/entireclient/clusterdiscovery
  
  - Mresolve.go+15/-18

```
26 unmodified lines

37 unmodified lines

// makeBindHook returns a func that, on its first call, persists the
// clusterHost→contextName binding to contexts.json (and is a no-op
// thereafter). It is meant to fire after the first successful scoped-token
// exchange: at that point the context has provably authenticated against
the cluster, so the binding is safe to cache. A bind failure is logged,
// not fatal — the token exchange already succeeded, and the next
// invocation just pays the discovery round-trip again.
//
// Returns nil when contextName is empty (e.g. a future env-token flow with
// no named context to bind), so callers can skip the hook entirely.
//
// Relies on creds being a freshly-constructed (empty) cache per process:
// the first scoped-token call is therefore always a real exchange, never a
// cache hit, so "first call" == "first proven auth".
func makeBindHook(cfgDir, clusterHost, contextName string) func() {
	if contextName == "" {
		return nil
	}
	var once sync.Once
	return func() {
		once.Do(func() {
			if err := contexts.BindCluster(cfgDir, clusterHost, contextName); err != nil {
				debuglog.Printf("auto-bind %s -> %s failed: %v", clusterHost, contextName, err)
				return
			}
			debuglog.Printf("auto-bound %s -> %s after first successful exchange", clusterHost, contextName)
		})
	}
}

// gitActionFromRequest classifies a smart-HTTP request as "pull" or "push"
// so the right repo-scoped token can be minted. Returns "" when the
// endpoint isn't a recognised git smart-HTTP route.
```
