package main // What claude-code does on a node, written against what it is handed — a way to ask a tool on the bus, its // own state, a way to write a managed file — so every path is tested without a bus (novox/hq design 36, // ADR 0183, ADR 0201, ADR 0206). // // Over NATS, and nothing an event: what is current is state, and a secret only ever travels on a request, // sealed to its one recipient. // - What this node holds is the module's `holdings` state, one key per node: the account, the kind, // fingerprints and expiries — never a token. Written at start and on every change of the credentials // file, so the licence manager learns a login, or a node already logged in, from the state alone. // - The grant itself leaves only when the manager asks `claude_code_grant`, sealed to the key it gives. // - What this node should hold is the manager's `bindings` state; a newer generation for this node is // fetched with the seat's `current` verb, sealed to this module's key, and written access-token-only. // - An MCP server registered through this module is a key in its `servers` state — `all.` for // every node, `.` for one — which every node watches. import ( "crypto/sha256" "encoding/hex" "encoding/json" "errors" "fmt" "os" "path/filepath" "sort" "strings" "sync" "time" ) // Seat is the licence manager's role, and Manager the module whose `bindings` state this one reads. const ( Seat = "anthropic-licence-manager" Manager = "claude-licence-manager" ) // SeatVerb is a seat's verb as the runtime addresses it: a role, not a module. func SeatVerb(verb string) string { return "seat:" + Seat + "." + verb } // Fingerprint names a token without being one: the first 16 hex of its SHA-256, as the manager computes it. func Fingerprint(s string) string { sum := sha256.Sum256([]byte(s)) return "sha256:" + hex.EncodeToString(sum[:])[:16] } // Paths are where this node's files are, from the module's words (ADR 0192). type Paths struct { State, Facts, Settings, Home, Node string } // PathsFrom reads them, or answers false outside a launch. func PathsFrom(env func(string) string) (Paths, bool) { p := Paths{State: env("MESH_CLAUDE_CODE_STATE"), Facts: env("MESH_CLAUDE_CODE_FACTS"), Settings: env("MESH_CLAUDE_CODE_SETTINGS"), Home: env("MESH_OPERATOR_HOME"), Node: env("MESH_NODE")} return p, p.State != "" && p.Facts != "" && p.Settings != "" && p.Home != "" && p.Node != "" } func (p Paths) credentials() string { return filepath.Join(p.Home, ".claude", ".credentials.json") } func (p Paths) account() string { return filepath.Join(p.Home, ".claude.json") } func (p Paths) binding() string { return filepath.Join(p.State, "licence.json") } func (p Paths) apiKey() string { return filepath.Join(p.State, "api-key") } func (p Paths) helper() string { return filepath.Join(p.State, "api-key-helper") } func (p Paths) registry() string { return filepath.Join(p.State, "mcp-servers.json") } func (p Paths) config() string { return filepath.Join(p.State, "config.json") } func (p Paths) placed() string { return filepath.Join(p.State, "home-placed.json") } // Ask is a tool on the bus: its address and arguments in, its JSON answer out. type Ask func(address string, args any) (json.RawMessage, error) // WriteManaged writes one managed file and answers what happened. type WriteManaged func(name, content string) (string, error) func readJSON(path string, into any) bool { raw, err := os.ReadFile(path) return err == nil && json.Unmarshal(raw, into) == nil } // Keypair is this module's own, made once in its state; the TypeScript module's files are kept, so a node // moving to this binary keeps the key it had. func Keypair(p Paths) (KeyPair, error) { priv, pub := filepath.Join(p.State, "key.pem"), filepath.Join(p.State, "key.pub.pem") if _, err := os.Stat(priv); errors.Is(err, os.ErrNotExist) { k, err := GenerateKeyPair() if err != nil { return KeyPair{}, err } if err := os.WriteFile(priv, []byte(k.PrivateKey), 0o600); err != nil { return KeyPair{}, err } if err := os.WriteFile(pub, []byte(k.PublicKey), 0o644); err != nil { return KeyPair{}, err } } a, err1 := os.ReadFile(priv) b, err2 := os.ReadFile(pub) return KeyPair{PrivateKey: string(a), PublicKey: string(b)}, errors.Join(err1, err2) } // Registered is what applies here of the servers registered through this module. func Registered(p Paths) Servers { s := Servers{} readJSON(p.registry(), &s) return s } var renderMu sync.Mutex // RenderNow writes the managed directory from the facts, the settings, the licence held and the servers // registered here. func RenderNow(p Paths, write WriteManaged) ([]string, error) { // One at a time: the watches and the tools all render, and the home's record of what was placed is // read and written whole. renderMu.Lock() defer renderMu.Unlock() var facts Facts if !readJSON(p.Facts, &facts) || facts.Console == "" { return nil, fmt.Errorf("the mesh has not rendered %s yet; nothing to write", p.Facts) } var settings Settings readJSON(p.Settings, &settings) var binding *Binding var b Binding if readJSON(p.binding(), &b) { binding = &b } var items map[string]Item _ = readJSON(p.config(), &items) config := ConfigOf(items) files := Render(facts, settings, binding, p.helper(), Registered(p), config) tree, _ := json.Marshal(Marketplace(config)) files[MarketplaceDir+"/"] = string(tree) names := make([]string, 0, len(files)) for n := range files { names = append(names, n) } // The marketplace first: the settings that enable its plugin must never name one that is not there yet. sort.Slice(names, func(i, j int) bool { if (names[i] == MarketplaceDir+"/") != (names[j] == MarketplaceDir+"/") { return names[i] == MarketplaceDir+"/" } return names[i] < names[j] }) // Every file is attempted: one that cannot be written — a registration the vendor's layout refuses, a // failed escalation — must not keep the licence, the tool servers or the instructions from landing. var out []string var failed []error for _, n := range names { line, err := write(n, files[n]) if err != nil { failed = append(failed, err) continue } out = append(out, line) } // The home scope: what this module places in the account's own agent directory (ADR 0182). done, left := PlaceHome(p, HomeFiles(config)) for _, line := range done { out = append(out, "home "+line) } for _, line := range left { out = append(out, "home "+line) } return out, errors.Join(failed...) } // ---- the licence ---------------------------------------------------------------------------------- // BindingState is what the manager's `bindings` state says one consumer should hold (ADR 0206). type BindingState struct { Licence string `json:"licence"` Kind string `json:"kind"` Generation int64 `json:"generation"` } // Current is what the seat answers to `current`: the licence this node is bound to and its token, sealed. type Current struct { Licence string `json:"licence"` Kind string `json:"kind"` Generation int64 `json:"generation"` Sealed *SealedBox `json:"sealed"` Identity *Identity `json:"identity"` } // Holdings is what this node holds, as the `holdings` state carries it (ADR 0206): enough for the manager // to tell a login it has not adopted from one it has, and never a token — fingerprints and expiries only. type Holdings struct { Node string `json:"node"` Identity *Identity `json:"identity"` Kind *string `json:"kind"` Refresh struct { Present bool `json:"present"` Fingerprint *string `json:"fingerprint"` ExpiresAt *int64 `json:"expiresAt"` } `json:"refresh"` Access *struct { Fingerprint string `json:"fingerprint"` ExpiresAt int64 `json:"expiresAt"` } `json:"access"` Licence *string `json:"licence"` Generation int64 `json:"generation"` ChangedAt *string `json:"changedAt"` } // HoldingsOf is what this node holds now. func HoldingsOf(p Paths) Holdings { h := Holdings{Node: p.Node, Identity: ReadIdentity(p.account())} creds := ReadCredentials(p.credentials()) if info, err := os.Stat(p.credentials()); err == nil { at := info.ModTime().UTC().Format("2006-01-02T15:04:05.000Z") h.ChangedAt = &at } if rt := RefreshTokenOf(creds); rt != "" { fp := Fingerprint(rt) h.Refresh.Present, h.Refresh.Fingerprint = true, &fp } if v, ok := number(creds.oauth()["refreshTokenExpiresAt"]); ok { h.Refresh.ExpiresAt = &v } if g := GrantOf(creds); g != nil { h.Access = &struct { Fingerprint string `json:"fingerprint"` ExpiresAt int64 `json:"expiresAt"` }{Fingerprint(g.AccessToken), g.ExpiresAt} } kind := "" if _, err := os.Stat(p.apiKey()); err == nil { kind = "api-key" } else if h.Access != nil { kind = "subscription" } if kind != "" { h.Kind = &kind } var applied Binding if readJSON(p.binding(), &applied) && applied.Licence != "" { h.Licence, h.Generation = &applied.Licence, applied.Generation } return h } // GrantAnswer is what `claude_code_grant` answers: a login sealed to the key given, or nothing waiting. type GrantAnswer struct { Sealed *SealedBox `json:"sealed,omitempty"` Identity *Identity `json:"identity,omitempty"` Fingerprint string `json:"fingerprint,omitempty"` Waiting *bool `json:"waiting,omitempty"` } // GrantFor is the full grant in the credentials file sealed to the manager's key — the one time a refresh // token leaves this node, for the manager to adopt by refreshing it (ADR 0206). Nothing waiting when the // file holds no refresh token. func GrantFor(p Paths, managerPublicKey string) (GrantAnswer, error) { creds := ReadCredentials(p.credentials()) rt := RefreshTokenOf(creds) if rt == "" { no := false return GrantAnswer{Waiting: &no}, nil } raw, err := json.Marshal(creds.oauth()) if err != nil { return GrantAnswer{}, err } box, err := Seal(string(raw), managerPublicKey) if err != nil { return GrantAnswer{}, err } return GrantAnswer{Sealed: &box, Identity: ReadIdentity(p.account()), Fingerprint: Fingerprint(rt)}, nil } // Pull asks the seat for this node's current token and applies it. func Pull(p Paths, ask Ask, write WriteManaged) (map[string]any, error) { keys, err := Keypair(p) if err != nil { return nil, err } raw, err := ask(SeatVerb("current"), map[string]any{"consumer": p.Node, "public_key": keys.PublicKey}) if err != nil { return nil, err } var c Current if err := json.Unmarshal(raw, &c); err != nil || c.Sealed == nil { return map[string]any{"applied": false, "reason": "the seat holds no licence for this node"}, nil } return Apply(p, c, write) } // OnBinding takes a change to this node's key in the manager's `bindings` state (ADR 0206): the token is // fetched when the binding differs from the one applied. A released binding keeps the last token, which // lives hours, and says so. // // **Differs, not "is newer"** (novox/hq issue 243). The state keeps only the latest value per node, so // nothing older can arrive. A manager whose store was rebuilt counts generations from one again, and // a node that waited for a number above its own ignored every binding it was sent, its login and the // licence's rotations included, until the count caught up. Only the binding already applied is skipped. func OnBinding(p Paths, b *BindingState, ask Ask, write WriteManaged) (string, error) { if b == nil { return "this node's binding was released; it keeps its last token until it expires", nil } var applied Binding if readJSON(p.binding(), &applied) && applied.Generation == b.Generation && applied.Licence == b.Licence { return "", nil } out, err := Pull(p, ask, write) if err != nil { return "", err } raw, _ := json.Marshal(out) return string(raw), nil } // Apply applies what the seat handed over. A switch replaces the grant whole and cleans up after the old // licence; whatever it is, the file is written without a refresh token, so the agent here never refreshes. func Apply(p Paths, c Current, write WriteManaged) (map[string]any, error) { keys, err := Keypair(p) if err != nil { return nil, err } plain, err := Open(*c.Sealed, keys.PrivateKey) if err != nil { return nil, err } var previous Binding had := readJSON(p.binding(), &previous) switched := !had || previous.Licence != c.Licence out := map[string]any{"applied": true, "licence": c.Licence, "kind": c.Kind, "switched": switched} if c.Kind == "api-key" { if err := os.WriteFile(p.apiKey(), []byte(strings.TrimSpace(plain)+"\n"), 0o600); err != nil { return nil, err } if err := os.WriteFile(p.helper(), []byte("#!/bin/sh\nexec cat '"+p.apiKey()+"'\n"), 0o700); err != nil { return nil, err } _ = os.Chmod(p.helper(), 0o700) } else { var g Grant if err := json.Unmarshal([]byte(plain), &g); err != nil { return nil, err } local := ReadCredentials(p.credentials()) // A login waiting here was handed to the manager first (ADR 0206): what comes back is its successor, // and the refresh token in the file is the one the manager just spent. d := DecideApply(GrantOf(local), g, switched || HoldsLogin(local)) if d.Apply { next := WithGrant(local, g) if switched { next = ReplacedBy(local, g) } if err := WriteCredentials(p.credentials(), next); err != nil { return nil, err } } else { out = map[string]any{"applied": false, "licence": c.Licence, "reason": d.Reason} } // Away from the API key: it goes, with its helper. _ = os.Remove(p.apiKey()) _ = os.Remove(p.helper()) } if switched && c.Identity != nil && c.Identity.AccountUUID != "" { changed, err := WriteIdentity(p.account(), *c.Identity) if err == nil { out["account"] = map[bool]string{true: "updated", false: "unchanged"}[changed] } } gen := c.Generation if gen == 0 { gen = previous.Generation } raw, _ := json.Marshal(Binding{Licence: c.Licence, Kind: c.Kind, Generation: gen}) if err := os.WriteFile(p.binding(), append(raw, '\n'), 0o600); err != nil { return nil, err } // The key-helper comes or goes with the licence's kind. if rendered, err := RenderNow(p, write); err != nil { out["rendered"] = map[string]any{"failed": err.Error()} } else { out["rendered"] = rendered } return out, nil } // AddAPIKey adds an API key from a file on this node to the licence manager (ADR 0209): sealed to the // manager's public key, handed to the seat's `adopt` on request/reply, and the file removed once taken. With // useHere, this node is switched to the new licence. The key never crosses the bus in the clear and is // never an argument. func AddAPIKey(p Paths, name, file string, useHere bool, ask Ask) (map[string]any, error) { raw, err := os.ReadFile(file) if err != nil { return nil, fmt.Errorf("the key is read from a file on this node: %w", err) } key := strings.TrimSpace(string(raw)) if key == "" { return nil, fmt.Errorf("%s is empty", file) } answer, err := ask(SeatVerb("public-key"), map[string]any{}) if err != nil { return nil, err } var pk struct { PublicKey string `json:"public_key"` } if err := json.Unmarshal(answer, &pk); err != nil || !strings.Contains(pk.PublicKey, "PUBLIC KEY") { return nil, errors.New("the licence manager did not say what key to seal to") } box, err := Seal(key, pk.PublicKey) if err != nil { return nil, err } adopted, err := ask(SeatVerb("adopt"), map[string]any{"name": name, "sealed": box, "from": p.Node}) if err != nil { return nil, err } out := map[string]any{"adopted": json.RawMessage(adopted)} // Taken: the key now lives encrypted in the manager's store alone. if err := os.Remove(file); err != nil { out["file"] = "could not be removed: " + err.Error() } else { out["file"] = "removed" } if useHere { switched, err := ask(SeatVerb("switch"), map[string]any{"consumer": p.Node, "licence": name}) if err != nil { return out, fmt.Errorf("adopted, and switching this node to it failed: %w", err) } out["switched"] = json.RawMessage(switched) } return out, nil } // ---- MCP servers ---------------------------------------------------------------------------------- // Registration is a server registered (or, with no entry, unregistered) through this module. type Registration struct { Name string Entry map[string]any // Nodes: nil for this node, ["all"] for every node running the module, or a list. Nodes []string } // ServerState is the `servers` state as this module reaches it through the runtime. type ServerState interface { Put(key string, value any) error Delete(key string) error Keys() ([]string, error) } // ServerChange is one change to the `servers` state, as a watch hands it over. type ServerChange struct { Key string Op string // put | delete Value map[string]any } // KeyOf is the key a registration lives at: `all.` for every node, `.` for one. func KeyOf(scope, name string) string { return scope + "." + name } // ServerView is what this node takes from the `servers` state: the entries for every node and for this // one, kept in memory from the watch and written through to the module's own file whenever what applies // here changes, so the managed directory renders without the bus. type ServerView struct { p Paths mu sync.Mutex entries map[string]map[string]any } // NewServerView is an empty view for this node. func NewServerView(p Paths) *ServerView { return &ServerView{p: p, entries: map[string]map[string]any{}} } // Take takes one change, and answers whether what applies to this node changed. func (v *ServerView) Take(c ServerChange) bool { scope, name, ok := strings.Cut(c.Key, ".") if !ok || scope == "" || (scope != "all" && scope != v.p.Node) { return false } v.mu.Lock() if c.Op == "put" && c.Value != nil && EntryProblem(name, c.Value) == "" { v.entries[c.Key] = c.Value } else { delete(v.entries, c.Key) } v.mu.Unlock() return v.writeThrough() } // Effective is what applies here: every node's entries, with this node's own laid over them by name. func (v *ServerView) Effective() Servers { v.mu.Lock() defer v.mu.Unlock() out := Servers{} for _, scope := range []string{"all", v.p.Node} { for key, entry := range v.entries { if name, ok := strings.CutPrefix(key, scope+"."); ok { out[name] = entry } } } return out } func (v *ServerView) writeThrough() bool { now, _ := indented(v.Effective()) before, _ := os.ReadFile(v.p.registry()) if string(before) == string(now) { return false } _ = os.WriteFile(v.p.registry(), now, 0o600) return true } // OnServerChange takes a change from the watch, and renders when what applies here changed. func OnServerChange(v *ServerView, c ServerChange, p Paths, write WriteManaged) (string, error) { if !v.Take(c) { return "", nil } if _, err := RenderNow(p, write); err != nil { return "", err } what := "registered" if c.Op != "put" { what = "unregistered" } return what + " " + c.Key, nil } // RegisterServer registers (or, with no entry, unregisters) a server: a put (or delete) per scope in the // `servers` state, taken into this node's view at once so the answer says what it did here; every other // node takes it from its watch, and a node that joins later from the current state. func RegisterServer(p Paths, r Registration, servers ServerState, v *ServerView, write WriteManaged, others func() ([]string, error)) (map[string]any, error) { if r.Entry != nil { if problem := EntryProblem(r.Name, r.Entry); problem != "" { return map[string]any{"registered": false, "reason": problem}, nil } } scopes := r.Nodes if len(scopes) == 0 { scopes = []string{p.Node} } // Compared before and after rather than read from Take: this node's own watch may hand the view the // same change first, and then Take here finds nothing new although this call made it. before, _ := json.Marshal(v.Effective()) for _, scope := range scopes { key := KeyOf(scope, r.Name) var err error if r.Entry != nil { err = servers.Put(key, r.Entry) } else { err = servers.Delete(key) } if err != nil { return nil, err } op := "put" if r.Entry == nil { op = "delete" } v.Take(ServerChange{Key: key, Op: op, Value: r.Entry}) } after, _ := json.Marshal(v.Effective()) changed := string(before) != string(after) here := false for _, s := range scopes { here = here || s == "all" || s == p.Node } verb := "registered" if r.Entry == nil { verb = "unregistered" } answer := map[string]any{verb: r.Name, "on": scopes} switch { case !here: answer["here"] = "not this node" case changed: answer["here"] = "changed" default: answer["here"] = "already so" } if changed { rendered, err := RenderNow(p, write) if err != nil { return nil, err } answer["rendered"] = rendered } if r.Entry == nil { if _, still := v.Effective()[r.Name]; still { answer["still"] = r.Name + " still applies here from another registration (for every node, or for this one); unregister that too" } } if len(r.Nodes) == 0 { // The question the operator wanted asked: here only, or more? var elsewhere []string if nodes, err := others(); err == nil { for _, n := range nodes { if n != p.Node { elsewhere = append(elsewhere, n) } } } if len(elsewhere) > 0 { answer["also"] = fmt.Sprintf("claude-code also runs on %s. To %s it there too, call again with nodes: \"all\" or a list of those nodes.", strings.Join(elsewhere, ", "), map[bool]string{true: "register", false: "unregister"}[r.Entry != nil]) } else { answer["also"] = "To do the same on every node running claude-code, call again with nodes: \"all\"." } } return answer, nil } // stamp is a time as the status answers it. func stamp(ms int64) string { return time.UnixMilli(ms).UTC().Format(time.RFC3339) }