package mesh import ( "context" "crypto/ed25519" "testing" "time" ) func TestFabricRegistryGossipRecordRequiresTrustedSignature(t *testing.T) { now := time.Date(2026, 5, 18, 10, 0, 0, 0, time.UTC) publicKey, privateKey, err := ed25519.GenerateKey(nil) if err != nil { t.Fatal(err) } record := testFabricRegistryGossipRecord(now, 10) issuer := FabricRegistryTrustedIssuer{ IssuerID: "authority-1", Role: FabricRegistryAuthorityControl, PublicKey: publicKey, Scopes: []string{FabricRegistryScopeCluster}, Services: []string{FabricRegistryServiceControlAPI}, } signed, err := SignFabricRegistryGossipRecord(record, issuer, privateKey) if err != nil { t.Fatalf("sign record: %v", err) } if _, err := VerifyFabricRegistryGossipRecord(signed, FabricRegistryVerificationPolicy{ LocalClusterID: "cluster-1", TrustedIssuers: []FabricRegistryTrustedIssuer{issuer}, RequiredSignatures: 1, Now: now, }); err != nil { t.Fatalf("verify signed record: %v", err) } tampered := signed tampered.Endpoints[0].Address = "quic://10.10.10.10:19443" if _, err := VerifyFabricRegistryGossipRecord(tampered, FabricRegistryVerificationPolicy{ LocalClusterID: "cluster-1", TrustedIssuers: []FabricRegistryTrustedIssuer{issuer}, RequiredSignatures: 1, Now: now, }); err == nil { t.Fatal("tampered record verified") } } func TestFabricRegistryRejectsLegacyEndpointAndExpiredRecord(t *testing.T) { now := time.Date(2026, 5, 18, 10, 0, 0, 0, time.UTC) publicKey, privateKey, err := ed25519.GenerateKey(nil) if err != nil { t.Fatal(err) } issuer := FabricRegistryTrustedIssuer{IssuerID: "authority-1", Role: FabricRegistryAuthorityControl, PublicKey: publicKey} record := testFabricRegistryGossipRecord(now, 10) record.Endpoints[0].Address = "https://control.example.test/api/v1" signed, err := SignFabricRegistryGossipRecord(record, issuer, privateKey) if err != nil { t.Fatalf("sign record: %v", err) } if _, err := VerifyFabricRegistryGossipRecord(signed, FabricRegistryVerificationPolicy{ LocalClusterID: "cluster-1", TrustedIssuers: []FabricRegistryTrustedIssuer{ {IssuerID: "authority-1", Role: FabricRegistryAuthorityControl, PublicKey: publicKey}, }, Now: now, }); err == nil { t.Fatal("legacy HTTP endpoint was accepted") } expired := testFabricRegistryGossipRecord(now.Add(-2*time.Hour), 11) expired.ExpiresAt = now.Add(-time.Minute) expiredSigned, err := SignFabricRegistryGossipRecord(expired, issuer, privateKey) if err != nil { t.Fatalf("sign expired record: %v", err) } if _, err := VerifyFabricRegistryGossipRecord(expiredSigned, FabricRegistryVerificationPolicy{ LocalClusterID: "cluster-1", TrustedIssuers: []FabricRegistryTrustedIssuer{ {IssuerID: "authority-1", Role: FabricRegistryAuthorityControl, PublicKey: publicKey}, }, Now: now, }); err == nil { t.Fatal("expired record was accepted") } } func TestFabricRegistryKeepsActiveRecordUntilNewerVerified(t *testing.T) { now := time.Date(2026, 5, 18, 10, 0, 0, 0, time.UTC) publicKey, privateKey, err := ed25519.GenerateKey(nil) if err != nil { t.Fatal(err) } issuer := FabricRegistryTrustedIssuer{IssuerID: "authority-1", Role: FabricRegistryAuthorityControl, PublicKey: publicKey} policy := FabricRegistryVerificationPolicy{ LocalClusterID: "cluster-1", TrustedIssuers: []FabricRegistryTrustedIssuer{issuer}, RequiredSignatures: 1, Now: now, } registry := NewFabricRegistry() active, err := SignFabricRegistryGossipRecord(testFabricRegistryGossipRecord(now, 10), issuer, privateKey) if err != nil { t.Fatalf("sign active: %v", err) } entry, changed, err := registry.ApplyGossipRecord(active, policy, true) if err != nil || !changed || entry.State != FabricRegistryActive { t.Fatalf("apply active entry changed=%t entry=%+v err=%v", changed, entry, err) } old := testFabricRegistryGossipRecord(now.Add(time.Minute), 9) old.Endpoints[0].Address = "quic://192.0.2.9:19443" oldSigned, err := SignFabricRegistryGossipRecord(old, issuer, privateKey) if err != nil { t.Fatalf("sign old: %v", err) } entry, changed, err = registry.ApplyGossipRecord(oldSigned, policy, true) if err != nil { t.Fatalf("apply old: %v", err) } if changed || entry.Record.Epoch != 10 || entry.Record.Endpoints[0].Address != "quic://192.0.2.10:19443" { t.Fatalf("older record replaced active entry: changed=%t entry=%+v", changed, entry) } newer := testFabricRegistryGossipRecord(now.Add(2*time.Minute), 11) newer.Endpoints[0].Address = "quic://192.0.2.11:19443" newerSigned, err := SignFabricRegistryGossipRecord(newer, issuer, privateKey) if err != nil { t.Fatalf("sign newer: %v", err) } policy.Now = now.Add(2 * time.Minute) entry, changed, err = registry.ApplyGossipRecord(newerSigned, policy, false) if err != nil || !changed || entry.State != FabricRegistryCandidate { t.Fatalf("apply newer candidate changed=%t entry=%+v err=%v", changed, entry, err) } activeRecord, ok := registry.Active("cluster-1", FabricRegistryServiceControlAPI, FabricRegistryScopeCluster, "", policy.Now) if !ok || activeRecord.Endpoints[0].Address != "quic://192.0.2.10:19443" { t.Fatalf("unverified newer candidate displaced active fallback: ok=%t record=%+v", ok, activeRecord) } if !registry.MarkLiveVerified("cluster-1", FabricRegistryServiceControlAPI, FabricRegistryScopeCluster, "", policy.Now.Add(time.Second)) { t.Fatal("mark live verified failed") } activeRecord, ok = registry.Active("cluster-1", FabricRegistryServiceControlAPI, FabricRegistryScopeCluster, "", policy.Now.Add(time.Second)) if !ok || activeRecord.Endpoints[0].Address != "quic://192.0.2.11:19443" { t.Fatalf("newer verified record not active: ok=%t record=%+v", ok, activeRecord) } } func TestFabricRegistryResolveServicePrefersVerifiedScopedRegionalEndpoint(t *testing.T) { now := time.Date(2026, 5, 18, 10, 0, 0, 0, time.UTC) publicKey, privateKey, err := ed25519.GenerateKey(nil) if err != nil { t.Fatal(err) } issuer := FabricRegistryTrustedIssuer{IssuerID: "authority-1", Role: FabricRegistryAuthorityControl, PublicKey: publicKey} policy := FabricRegistryVerificationPolicy{ LocalClusterID: "cluster-1", TrustedIssuers: []FabricRegistryTrustedIssuer{issuer}, RequiredSignatures: 1, Now: now, } registry := NewFabricRegistry() clusterRecord := testFabricRegistryGossipRecord(now, 10) clusterRecord.Endpoints = []FabricRegistryEndpoint{ {EndpointID: "control-eu", Address: "quic://eu.example.test:19443", Transport: "direct_quic", Region: "eu", Priority: 10, Weight: 1}, {EndpointID: "control-us", Address: "quic://us.example.test:19443", Transport: "direct_quic", Region: "us", Priority: 10, Weight: 10}, } signedCluster, err := SignFabricRegistryGossipRecord(clusterRecord, issuer, privateKey) if err != nil { t.Fatalf("sign cluster record: %v", err) } if _, _, err := registry.ApplyGossipRecord(signedCluster, policy, true); err != nil { t.Fatalf("apply cluster record: %v", err) } orgRecord := testFabricRegistryGossipRecord(now.Add(time.Minute), 11) orgRecord.Scope = FabricRegistryScopeOrganization orgRecord.OrganizationID = "org-1" orgRecord.Endpoints = []FabricRegistryEndpoint{ {EndpointID: "control-org", Address: "quic://org.example.test:19443", Transport: "direct_quic", Region: "eu", Priority: 1, Weight: 1}, } signedOrg, err := SignFabricRegistryGossipRecord(orgRecord, issuer, privateKey) if err != nil { t.Fatalf("sign org record: %v", err) } policy.Now = now.Add(time.Minute) if _, _, err := registry.ApplyGossipRecord(signedOrg, policy, false); err != nil { t.Fatalf("apply org candidate: %v", err) } resolved := registry.ResolveService(FabricRegistryResolveRequest{ ClusterID: "cluster-1", Service: FabricRegistryServiceControlAPI, Scope: FabricRegistryScopeOrganization, OrganizationID: "org-1", PreferredRegion: "us", Now: now.Add(time.Minute), }) if !resolved.Found || resolved.Scope != FabricRegistryScopeCluster || resolved.Endpoints[0].EndpointID != "control-us" { t.Fatalf("expected cluster fallback with preferred region endpoint, got %+v", resolved) } if !registry.MarkLiveVerified("cluster-1", FabricRegistryServiceControlAPI, FabricRegistryScopeOrganization, "org-1", now.Add(2*time.Minute)) { t.Fatal("mark org live verified failed") } resolved = registry.ResolveService(FabricRegistryResolveRequest{ ClusterID: "cluster-1", Service: FabricRegistryServiceControlAPI, Scope: FabricRegistryScopeOrganization, OrganizationID: "org-1", Now: now.Add(2 * time.Minute), }) if !resolved.Found || resolved.Scope != FabricRegistryScopeOrganization || resolved.Endpoints[0].EndpointID != "control-org" { t.Fatalf("expected verified organization record, got %+v", resolved) } snapshot := registry.Snapshot(now.Add(2 * time.Minute)) if snapshot.Active != 2 || snapshot.Candidate != 0 { t.Fatalf("unexpected snapshot: %+v", snapshot) } } func TestFabricRegistryVerifyCandidatesPromotesAfterQUICPong(t *testing.T) { now := time.Date(2026, 5, 18, 10, 0, 0, 0, time.UTC) tlsConfig := testQUICTLSConfig(t) listener := startQUICFabricEchoServerWithTLS(t, tlsConfig) defer listener.Close() publicKey, privateKey, err := ed25519.GenerateKey(nil) if err != nil { t.Fatal(err) } issuer := FabricRegistryTrustedIssuer{IssuerID: "authority-1", Role: FabricRegistryAuthorityControl, PublicKey: publicKey} policy := FabricRegistryVerificationPolicy{ LocalClusterID: "cluster-1", TrustedIssuers: []FabricRegistryTrustedIssuer{issuer}, RequiredSignatures: 1, Now: now, } record := testFabricRegistryGossipRecord(now, 12) record.Endpoints[0].Address = "quic://" + listener.Addr().String() record.Endpoints[0].PeerCertSHA256 = testQUICCertSHA256(t, tlsConfig) signed, err := SignFabricRegistryGossipRecord(record, issuer, privateKey) if err != nil { t.Fatalf("sign record: %v", err) } registry := NewFabricRegistry() if entry, changed, err := registry.ApplyGossipRecord(signed, policy, false); err != nil || !changed || entry.State != FabricRegistryCandidate { t.Fatalf("apply candidate changed=%t entry=%+v err=%v", changed, entry, err) } results := registry.VerifyCandidates(context.Background(), NewQUICFabricTransport(nil), FabricRegistryLiveProbeRequest{ ClusterID: "cluster-1", Timeout: 3 * time.Second, Now: now.Add(time.Second), MaxCandidates: 1, }) if len(results) != 1 || results[0].Status != "reachable" || !results[0].Promoted { t.Fatalf("unexpected live probe results: %+v", results) } if _, ok := registry.Active("cluster-1", FabricRegistryServiceControlAPI, FabricRegistryScopeCluster, "", now.Add(time.Second)); !ok { t.Fatal("candidate was not promoted to active") } } func testFabricRegistryGossipRecord(now time.Time, epoch int64) FabricRegistryGossipRecord { return FabricRegistryGossipRecord{ SchemaVersion: FabricRegistryGossipRecordSchema, ClusterID: "cluster-1", Service: FabricRegistryServiceControlAPI, Scope: FabricRegistryScopeCluster, Epoch: epoch, Generation: "gen", IssuedAt: now, ExpiresAt: now.Add(10 * time.Minute), IssuerNodeID: "authority-1", IssuerRole: FabricRegistryAuthorityControl, Endpoints: []FabricRegistryEndpoint{ { EndpointID: "control-a", Address: "quic://192.0.2.10:19443", Transport: "direct_quic", Reachability: "public", ConnectivityMode: "direct", Priority: 1, }, }, } }