package main import ( "encoding/json" "os" "path/filepath" "reflect" "strings" "testing" "time" ) var now = time.Now().UnixMilli() func node(t *testing.T, name string) (Paths, map[string]string) { t.Helper() root := t.TempDir() p := Paths{State: filepath.Join(root, "state"), Facts: filepath.Join(root, "state", "facts.json"), Settings: filepath.Join(root, "state", "settings.json"), Home: filepath.Join(root, "home"), Node: name} _ = os.MkdirAll(p.State, 0o700) _ = os.MkdirAll(filepath.Join(p.Home, ".claude"), 0o700) _ = os.WriteFile(p.Facts, []byte(`{"node":"`+name+`","console":"http://127.0.0.1:4270/mcp"}`), 0o600) _ = os.WriteFile(p.Settings, []byte(`{"role":"","mcp_servers":{}}`), 0o600) return p, map[string]string{} } func writer(w map[string]string) WriteManaged { return func(name, content string) (string, error) { w[name] = content; return name + ": written", nil } } func writeFile(t *testing.T, path, content string) { t.Helper() if err := os.WriteFile(path, []byte(content), 0o600); err != nil { t.Fatal(err) } } func creds(t *testing.T, p Paths) map[string]any { t.Helper() var c map[string]any raw, _ := os.ReadFile(p.credentials()) if err := json.Unmarshal(raw, &c); err != nil { t.Fatal(err) } return c["claudeAiOauth"].(map[string]any) } // ---- the renderer, held to the TypeScript it replaced ------------------------------------------------- func TestTheRendererWritesWhatTheTypeScriptOneWrote(t *testing.T) { raw, err := os.ReadFile("testdata/rendered-by-typescript.json") if err != nil { t.Fatal(err) } var f struct { Facts Facts `json:"facts"` Settings Settings `json:"settings"` Registered Servers `json:"registered"` WithKey map[string]string `json:"withKey"` Plain map[string]string `json:"plain"` } if err := json.Unmarshal(raw, &f); err != nil { t.Fatal(err) } same := func(label string, got, want map[string]string) { if got["CLAUDE.md"] != want["CLAUDE.md"] { t.Errorf("%s: CLAUDE.md differs from the TypeScript's:\n--- go\n%s\n--- typescript\n%s", label, got["CLAUDE.md"], want["CLAUDE.md"]) } for _, file := range []string{"managed-mcp.json", "managed-settings.json"} { var a, b any _ = json.Unmarshal([]byte(got[file]), &a) _ = json.Unmarshal([]byte(want[file]), &b) if !reflect.DeepEqual(a, b) { t.Errorf("%s: %s means something else:\n--- go\n%s\n--- typescript\n%s", label, file, got[file], want[file]) } } } same("with an API key", Render(f.Facts, f.Settings, &Binding{Licence: "api", Kind: "api-key"}, "/state/api-key-helper", f.Registered), f.WithKey) same("plain", Render(f.Facts, Settings{}, nil, "/h", Servers{}), f.Plain) } func TestASettingCannotReplaceTheMeshsOwnEntryAndABadNameIsLeftOut(t *testing.T) { out := Render(Facts{Node: "w", Console: "http://127.0.0.1:4270/mcp"}, Settings{MCPServers: map[string]map[string]any{"mesh": {"type": "http", "url": "http://evil"}, "bad name": {}}}, nil, "/h", nil) var mcp struct { MCPServers map[string]map[string]any `json:"mcpServers"` } _ = json.Unmarshal([]byte(out["managed-mcp.json"]), &mcp) if mcp.MCPServers["mesh"]["url"] != "http://127.0.0.1:4270/mcp" || mcp.MCPServers["bad name"] != nil { t.Fatalf("%v", mcp.MCPServers) } if !reflect.DeepEqual(Render(Facts{Console: "x"}, Settings{}, nil, "/h", nil), Render(Facts{Console: "x"}, Settings{}, nil, "/h", nil)) { t.Fatal("rendering is not deterministic") } } // ---- the credentials file ----------------------------------------------------------------------------- func i64(v int64) *int64 { return &v } func TestTheLineageRules(t *testing.T) { const hour = 3_600_000 g := func(at string, exp int64, rtExp int64) Grant { return Grant{AccessToken: at, ExpiresAt: exp, RefreshTokenExpiresAt: i64(rtExp)} } month := now + 30*24*hour if d := DecideApply(&Grant{AccessToken: "A", ExpiresAt: now + hour, RefreshTokenExpiresAt: i64(month)}, g("B", now+2*hour, month), false); !d.Apply { t.Fatal("a newer rotation was refused") } if d := DecideApply(&Grant{AccessToken: "new", ExpiresAt: now + 2*hour, RefreshTokenExpiresAt: i64(month)}, g("old", now+hour, month), false); d.Apply || d.Reason != "not-newer" { t.Fatalf("a late older rotation: %+v", d) } if d := DecideApply(&Grant{AccessToken: "A", ExpiresAt: now + 8*hour, RefreshTokenExpiresAt: i64(month)}, g("re", now+hour, now+5*24*hour), false); !d.Apply || !d.Reissued { t.Fatalf("a re-issued grant: %+v", d) } if d := DecideApply(&Grant{AccessToken: "A", ExpiresAt: now + 8*hour}, g("other", now+hour, month), true); !d.Apply { t.Fatal("a switch was refused") } if d := DecideApply(&Grant{AccessToken: "A"}, Grant{AccessToken: "A"}, true); d.Apply || d.Reason != "already-current" { t.Fatalf("the same token: %+v", d) } } func TestALoginIsSeenAndStrippedWhenTheNodesOwnGrantIsWritten(t *testing.T) { p, _ := node(t, "laptop") writeFile(t, p.credentials(), `{"claudeAiOauth":{"accessToken":"at-login","refreshToken":"rt-login","expiresAt":1700000000000},"other":1}`) login := ReadCredentials(p.credentials()) if !HoldsLogin(login) { t.Fatal("a login was not seen") } if err := WriteCredentials(p.credentials(), WithGrant(login, Grant{AccessToken: "at-mesh", ExpiresAt: 1, Scopes: []string{"user:inference"}})); err != nil { t.Fatal(err) } back := ReadCredentials(p.credentials()) raw, _ := os.ReadFile(p.credentials()) info, _ := os.Stat(p.credentials()) if HoldsLogin(back) || GrantOf(back).AccessToken != "at-mesh" || back["other"] == nil || strings.Contains(string(raw), "rt-login") || info.Mode().Perm() != 0o600 { t.Fatalf("written %s (mode %v)", raw, info.Mode()) } } func TestTheAccountIsReadFromTheAgentsStateFileAndNeverGuessed(t *testing.T) { p, _ := node(t, "laptop") writeFile(t, p.account(), `{"oauthAccount":{"accountUuid":"u-1","emailAddress":"a@example.org"},"other":2}`) if id := ReadIdentity(p.account()); id == nil || id.AccountUUID != "u-1" || id.EmailAddress != "a@example.org" { t.Fatalf("%+v", id) } if ReadIdentity("/nonexistent/.claude.json") != nil { t.Fatal("an identity from nothing") } writeFile(t, p.account(), `{}`) if ReadIdentity(p.account()) != nil { t.Fatal("an identity from an empty file") } } // ---- the licence, ADR 0206 ---------------------------------------------------------------------------- func TestWhatANodeHoldsIsReportedWithFingerprintsAndItsAccountNeverAToken(t *testing.T) { p, _ := node(t, "laptop") writeFile(t, p.credentials(), `{"claudeAiOauth":{"accessToken":"at-secret","refreshToken":"rt-secret","expiresAt":2000,"refreshTokenExpiresAt":9000}}`) writeFile(t, p.account(), `{"oauthAccount":{"accountUuid":"u-1","emailAddress":"a@example.org"}}`) h := HoldingsOf(p) if h.Node != "laptop" || h.Identity.AccountUUID != "u-1" || *h.Kind != "subscription" || !h.Refresh.Present || !strings.HasPrefix(*h.Refresh.Fingerprint, "sha256:") || h.Access.ExpiresAt != 2000 || h.ChangedAt == nil { t.Fatalf("%+v", h) } raw, _ := json.Marshal(h) if strings.Contains(string(raw), "at-secret") || strings.Contains(string(raw), "rt-secret") { t.Fatalf("a token is in the report: %s", raw) } var keys map[string]any _ = json.Unmarshal(raw, &keys) for k := range keys { if strings.Contains(strings.ToLower(k), "token") || strings.Contains(strings.ToLower(k), "secret") { t.Fatalf("a field the runtime would refuse: %s", k) } } // The manager reads exactly this shape. if _, err := time.Parse(time.RFC3339Nano, *h.ChangedAt); err != nil { t.Fatalf("the manager cannot read the report's time: %v", err) } } func TestTheGrantAnswersOnlyAWaitingLoginSealedToTheManagersKey(t *testing.T) { p, _ := node(t, "laptop") manager, _ := GenerateKeyPair() if a, _ := GrantFor(p, manager.PublicKey); a.Sealed != nil || a.Waiting == nil || *a.Waiting { t.Fatalf("%+v", a) } writeFile(t, p.credentials(), `{"claudeAiOauth":{"accessToken":"at","refreshToken":"rt-login","expiresAt":1}}`) writeFile(t, p.account(), `{"oauthAccount":{"accountUuid":"u-9"}}`) a, err := GrantFor(p, manager.PublicKey) if err != nil || a.Identity.AccountUUID != "u-9" { t.Fatalf("%+v %v", a, err) } plain, _ := Open(*a.Sealed, manager.PrivateKey) if !strings.Contains(plain, `"refreshToken":"rt-login"`) { t.Fatalf("opened %s", plain) } raw, _ := json.Marshal(a) if strings.Contains(string(raw), "rt-login") { t.Fatal("the refresh token crossed in the clear") } } // seat answers `current` as the manager does: the grant sealed to the key the node sent. func seat(t *testing.T, licence, token string, gen int64, asked *[]string) Ask { return func(address string, args any) (json.RawMessage, error) { *asked = append(*asked, address) key := args.(map[string]any)["public_key"].(string) g, _ := json.Marshal(Grant{AccessToken: token, ExpiresAt: now + 3_600_000}) box, err := Seal(string(g), key) if err != nil { t.Fatal(err) } return json.Marshal(Current{Licence: licence, Kind: "subscription", Generation: gen, Sealed: &box}) } } func TestANewerGenerationFetchesTheTokenOnceByTheSeatsVerb(t *testing.T) { p, w := node(t, "laptop") var asked []string ask := seat(t, "personal", "at-1", 3, &asked) if _, err := OnBinding(p, &BindingState{Licence: "personal", Kind: "subscription", Generation: 3}, ask, writer(w)); err != nil { t.Fatal(err) } if len(asked) != 1 || asked[0] != "seat:anthropic-licence-manager.current" || creds(t, p)["accessToken"] != "at-1" { t.Fatalf("asked %v, credentials %v", asked, creds(t, p)) } if done, _ := OnBinding(p, &BindingState{Licence: "personal", Kind: "subscription", Generation: 3}, ask, writer(w)); done != "" || len(asked) != 1 { t.Fatal("an equal generation asked again") } if HoldingsOf(p).Generation != 3 || w["managed-mcp.json"] == "" { t.Fatal("the generation or the managed files were not written") } } func TestTheTokenANodeIsHandedReplacesALoginsGrantAndLeavesNoRefreshToken(t *testing.T) { p, w := node(t, "laptop") writeFile(t, p.credentials(), `{"claudeAiOauth":{"accessToken":"at-old","refreshToken":"rt-spent","expiresAt":`+ strings.TrimSpace(string(mustJSON(now+7_200_000)))+`}}`) var asked []string out, err := Pull(p, seat(t, "personal", "at-new", 1, &asked), writer(w)) if err != nil || out["applied"] != true { t.Fatalf("%v %v", out, err) } c := creds(t, p) if c["accessToken"] != "at-new" || c["refreshToken"] != nil || HoldingsOf(p).Refresh.Present { t.Fatalf("%v", c) } } func mustJSON(v any) []byte { b, _ := json.Marshal(v); return b } // ---- MCP servers in state, ADR 0201 ------------------------------------------------------------------- // bus is the `servers` state as every node in a test shares it, with each node's watch. type bus struct { kept map[string]map[string]any watchers []func(ServerChange) } func (b *bus) Put(key string, value any) error { v := value.(map[string]any) b.kept[key] = v for _, w := range b.watchers { w(ServerChange{Key: key, Op: "put", Value: v}) } return nil } func (b *bus) Delete(key string) error { delete(b.kept, key) for _, w := range b.watchers { w(ServerChange{Key: key, Op: "delete"}) } return nil } func (b *bus) Keys() ([]string, error) { var out []string for k := range b.kept { out = append(out, k) } return out, nil } // join is a node joining: its view takes the current state, then every change. func (b *bus) join(p Paths, w map[string]string) *ServerView { v := NewServerView(p) for k, val := range b.kept { _, _ = OnServerChange(v, ServerChange{Key: k, Op: "put", Value: val}, p, writer(w)) } b.watchers = append(b.watchers, func(c ServerChange) { _, _ = OnServerChange(v, c, p, writer(w)) }) return v } func noOthers() ([]string, error) { return nil, nil } func TestRegisteringHerePutsItUnderThisNodesKeyAndAsksAboutTheOthers(t *testing.T) { p, w := node(t, "laptop") b := &bus{kept: map[string]map[string]any{}} v := b.join(p, w) r, err := RegisterServer(p, Registration{Name: "search", Entry: map[string]any{"type": "http", "url": "https://s.example/mcp"}}, b, v, writer(w), func() ([]string, error) { return []string{"laptop", "server", "desktop"}, nil }) if err != nil || r["here"] != "changed" || !strings.Contains(r["also"].(string), "server, desktop") || b.kept["laptop.search"] == nil { t.Fatalf("%v %v %v", r, err, b.kept) } if !strings.Contains(w["managed-mcp.json"], `"search"`) { t.Fatal("not rendered") } } func TestEveryNodeRegistrationReachesTheOthersAndALateNodeReadsIt(t *testing.T) { a, wa := node(t, "laptop") s, ws := node(t, "server") b := &bus{kept: map[string]map[string]any{}} va := b.join(a, wa) b.join(s, ws) _, _ = RegisterServer(a, Registration{Name: "docs", Entry: map[string]any{"type": "stdio", "command": "docs-mcp"}, Nodes: []string{"all"}}, b, va, writer(wa), noOthers) if Registered(s)["docs"] == nil || !strings.Contains(ws["managed-mcp.json"], "docs-mcp") { t.Fatalf("the other node did not take it: %v", Registered(s)) } late, wl := node(t, "desktop") b.join(late, wl) if Registered(late)["docs"] == nil { t.Fatal("a node joining later did not read the current set") } _, _ = RegisterServer(a, Registration{Name: "docs", Nodes: []string{"all"}}, b, va, writer(wa), noOthers) if Registered(s)["docs"] != nil || Registered(late)["docs"] != nil { t.Fatal("an unregistration did not reach every node") } } func TestANodesOwnRegistrationOverridesTheOneForEveryNode(t *testing.T) { a, wa := node(t, "laptop") s, ws := node(t, "server") b := &bus{kept: map[string]map[string]any{}} va := b.join(a, wa) b.join(s, ws) _, _ = RegisterServer(a, Registration{Name: "x", Entry: map[string]any{"type": "http", "url": "https://all"}, Nodes: []string{"all"}}, b, va, writer(wa), noOthers) _, _ = RegisterServer(a, Registration{Name: "x", Entry: map[string]any{"type": "http", "url": "https://laptop"}}, b, va, writer(wa), noOthers) if Registered(a)["x"]["url"] != "https://laptop" || Registered(s)["x"]["url"] != "https://all" { t.Fatalf("%v %v", Registered(a), Registered(s)) } r, _ := RegisterServer(a, Registration{Name: "x"}, b, va, writer(wa), noOthers) if !strings.Contains(r["still"].(string), "still applies here") || Registered(a)["x"]["url"] != "https://all" { t.Fatalf("%v", r) } } func TestABadEntryIsRefusedBeforeAnythingIsPut(t *testing.T) { p, w := node(t, "laptop") b := &bus{kept: map[string]map[string]any{}} v := b.join(p, w) r, _ := RegisterServer(p, Registration{Name: "mesh", Entry: map[string]any{"type": "http", "url": "https://x"}}, b, v, writer(w), noOthers) if r["registered"] != false || len(b.kept) != 0 { t.Fatalf("%v %v", r, b.kept) } if done, _ := OnServerChange(v, ServerChange{Key: "server.b", Op: "put", Value: map[string]any{"type": "http", "url": "https://b"}}, p, writer(w)); done != "" { t.Fatal("another node's key changed this one") } }