package cluster import ( "context" "encoding/json" "errors" "strings" "testing" "time" "github.com/example/remote-access-platform/backend/internal/platform/clusterauth" "github.com/example/remote-access-platform/backend/internal/platform/secrets" "github.com/jackc/pgx/v5" ) func TestHashJoinTokenDoesNotStoreRawToken(t *testing.T) { raw := "rap_join_example" hashed, err := hashJoinToken(raw) if err != nil { t.Fatalf("hash join token: %v", err) } if hashed == raw { t.Fatal("hash must not equal raw token") } if got, wantPrefix := hashed[:len(joinTokenHashPrefix)], joinTokenHashPrefix; got != wantPrefix { t.Fatalf("hash prefix = %q, want %q", got, wantPrefix) } hashedAgain, err := hashJoinToken(raw) if err != nil { t.Fatalf("hash join token again: %v", err) } if hashed != hashedAgain { t.Fatal("hash must be deterministic") } } func TestClusterAuthorityPrivateKeyEncodingUsesSecretEncryptor(t *testing.T) { encryptor, err := secrets.NewEncryptor("MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY=", "test-key") if err != nil { t.Fatalf("NewEncryptor: %v", err) } store := (&PostgresStore{}).WithClusterKeyEncryptor(encryptor) encoded, err := store.encodeClusterAuthorityPrivateKey("cluster-1", "private-key") if err != nil { t.Fatalf("encodeClusterAuthorityPrivateKey: %v", err) } if encoded == "private-key" || !strings.HasPrefix(encoded, encryptedClusterAuthorityKeyPrefix) { t.Fatalf("private key was not encrypted: %q", encoded) } decoded, err := store.decodeClusterAuthorityPrivateKey("cluster-1", encoded) if err != nil { t.Fatalf("decodeClusterAuthorityPrivateKey: %v", err) } if decoded != "private-key" { t.Fatalf("decoded private key = %q", decoded) } if _, err := store.decodeClusterAuthorityPrivateKey("cluster-2", encoded); err == nil { t.Fatal("expected wrong cluster AAD to fail") } } func TestCreateJoinTokenRequiresPlatformAdmin(t *testing.T) { store := &fakeRepository{platformRole: "user"} service := NewService(store) _, err := service.CreateJoinToken(context.Background(), CreateJoinTokenInput{ ActorUserID: "user-1", ClusterID: "cluster-1", }) if !errors.Is(err, ErrAccessDenied) { t.Fatalf("err = %v, want ErrAccessDenied", err) } } func TestCreateJoinTokenStoresHashOnlyAndReturnsRawOnce(t *testing.T) { store := &fakeRepository{platformRole: PlatformRoleAdmin} service := NewService(store) service.now = func() time.Time { return time.Date(2026, 4, 26, 12, 0, 0, 0, time.UTC) } created, err := service.CreateJoinToken(context.Background(), CreateJoinTokenInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", Scope: json.RawMessage(`{"roles":["rdp-worker"]}`), MaxUses: 1, }) if err != nil { t.Fatalf("create join token: %v", err) } if created.Token == "" { t.Fatal("raw token must be returned to caller once") } if store.lastTokenHash == "" || store.lastTokenHash == created.Token { t.Fatalf("stored token hash = %q, raw token = %q", store.lastTokenHash, created.Token) } if created.AuthoritySignature == nil || len(created.AuthorityPayload) == 0 { t.Fatalf("created token missing authority signature: %+v", created.NodeJoinToken) } if err := clusterauth.VerifyRaw(store.clusterAuthority.PublicKey, created.AuthorityPayload, *created.AuthoritySignature); err != nil { t.Fatalf("verify token authority signature: %v", err) } } func TestUpdateClusterRequiresMutableAuthority(t *testing.T) { store := &fakeRepository{ platformRole: PlatformRoleAdmin, authorityState: ClusterAuthorityState{ ClusterID: "cluster-1", AuthorityState: "minority", MutationMode: "read_only", }, } service := NewService(store) _, err := service.UpdateCluster(context.Background(), UpdateClusterInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", Name: "Cluster One", Status: ClusterStatusActive, Metadata: json.RawMessage(`{}`), }) if !errors.Is(err, ErrClusterReadOnly) { t.Fatalf("err = %v, want ErrClusterReadOnly", err) } } func TestUpdateClusterValidatesStatusAndMetadata(t *testing.T) { store := &fakeRepository{platformRole: PlatformRoleAdmin} service := NewService(store) _, err := service.UpdateCluster(context.Background(), UpdateClusterInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", Name: "Cluster One", Status: "unknown", Metadata: json.RawMessage(`{}`), }) if !errors.Is(err, ErrInvalidPayload) { t.Fatalf("err = %v, want ErrInvalidPayload", err) } _, err = service.UpdateCluster(context.Background(), UpdateClusterInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", Name: "Cluster One", Status: ClusterStatusActive, Metadata: json.RawMessage(`{`), }) if err == nil || !strings.Contains(err.Error(), "metadata") { t.Fatalf("err = %v, want metadata validation error", err) } } func TestCreateNodeGroupValidatesNameAndMetadata(t *testing.T) { store := &fakeRepository{platformRole: PlatformRoleAdmin} service := NewService(store) _, err := service.CreateNodeGroup(context.Background(), CreateNodeGroupInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", Name: " ", }) if !errors.Is(err, ErrInvalidPayload) { t.Fatalf("err = %v, want ErrInvalidPayload", err) } _, err = service.CreateNodeGroup(context.Background(), CreateNodeGroupInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", Name: "DC-1", Metadata: json.RawMessage(`{`), }) if err == nil || !strings.Contains(err.Error(), "metadata") { t.Fatalf("err = %v, want metadata validation error", err) } } func TestAssignNodeToGroupPreservesConcreteMembership(t *testing.T) { groupID := "group-1" store := &fakeRepository{platformRole: PlatformRoleAdmin} service := NewService(store) node, err := service.AssignNodeToGroup(context.Background(), AssignNodeGroupInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", NodeID: "node-1", GroupID: &groupID, }) if err != nil { t.Fatalf("assign node group: %v", err) } if node.ID != "node-1" || node.NodeGroupID == nil || *node.NodeGroupID != groupID { t.Fatalf("unexpected node group assignment: %+v", node) } if store.lastAssignGroupInput.NodeID != "node-1" || store.lastAssignGroupInput.GroupID == nil { t.Fatalf("assignment input not preserved: %+v", store.lastAssignGroupInput) } } func TestCreateFabricEntryPointValidatesControlPlanePayload(t *testing.T) { store := &fakeRepository{platformRole: PlatformRoleAdmin} service := NewService(store) _, err := service.CreateFabricEntryPoint(context.Background(), CreateFabricEntryPointInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", Name: " ", EndpointType: "client_access", }) if !errors.Is(err, ErrInvalidPayload) { t.Fatalf("err = %v, want ErrInvalidPayload", err) } _, err = service.CreateFabricEntryPoint(context.Background(), CreateFabricEntryPointInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", Name: "Main Entry", EndpointType: "client_access", Policy: json.RawMessage(`{`), }) if err == nil || !strings.Contains(err.Error(), "valid json") { t.Fatalf("err = %v, want json validation error", err) } } func TestCreateFabricEgressPoolDefaultsAndAudits(t *testing.T) { store := &fakeRepository{platformRole: PlatformRoleAdmin} service := NewService(store) item, err := service.CreateFabricEgressPool(context.Background(), CreateFabricEgressPoolInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", Name: "Office Moscow", }) if err != nil { t.Fatalf("create egress pool: %v", err) } if item.Status != "active" || string(item.RouteScope) != "{}" { t.Fatalf("unexpected egress pool defaults: %+v", item) } if len(store.auditEvents) == 0 || store.auditEvents[len(store.auditEvents)-1].EventType != "fabric.egress_pool.created" { t.Fatalf("missing egress pool audit event: %+v", store.auditEvents) } } func TestAssignNodeRoleRejectsUnknownRole(t *testing.T) { store := &fakeRepository{platformRole: PlatformRoleAdmin} service := NewService(store) _, err := service.AssignNodeRole(context.Background(), AssignNodeRoleInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", NodeID: "node-1", Role: "can_run_rdp_worker", }) if !errors.Is(err, ErrInvalidNodeRole) { t.Fatalf("err = %v, want ErrInvalidNodeRole", err) } } func TestAttachExistingNodeRequiresPlatformAdmin(t *testing.T) { store := &fakeRepository{platformRole: "user"} service := NewService(store) _, err := service.AttachExistingNodeToCluster(context.Background(), AttachExistingNodeInput{ ActorUserID: "user-1", ClusterID: "cluster-1", NodeID: "node-1", }) if !errors.Is(err, ErrAccessDenied) { t.Fatalf("err = %v, want ErrAccessDenied", err) } } func TestAttachExistingNodeRejectsUnknownRole(t *testing.T) { store := &fakeRepository{platformRole: PlatformRoleAdmin} service := NewService(store) _, err := service.AttachExistingNodeToCluster(context.Background(), AttachExistingNodeInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", NodeID: "node-1", Roles: []string{"can_run_rdp_worker"}, }) if !errors.Is(err, ErrInvalidNodeRole) { t.Fatalf("err = %v, want ErrInvalidNodeRole", err) } } func TestAttachExistingNodeUsesConcreteNodeAndRoles(t *testing.T) { store := &fakeRepository{platformRole: PlatformRoleAdmin} service := NewService(store) node, err := service.AttachExistingNodeToCluster(context.Background(), AttachExistingNodeInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", NodeID: "node-1", Roles: []string{"entry-node", "rdp-worker"}, }) if err != nil { t.Fatalf("attach existing node: %v", err) } if node.ID != "node-1" || node.MembershipStatus != "active" { t.Fatalf("unexpected node: %+v", node) } if store.lastAttachInput.NodeID != "node-1" || len(store.lastAttachInput.Roles) != 2 { t.Fatalf("attach input not preserved: %+v", store.lastAttachInput) } } func TestCreateJoinRequestRejectsExpiredOrRevokedToken(t *testing.T) { store := &fakeRepository{validTokenErr: ErrInvalidJoinToken} service := NewService(store) _, err := service.CreateJoinRequest(context.Background(), CreateJoinRequestInput{ ClusterID: "cluster-1", JoinToken: "rap_join_invalid", NodeName: "node-a", NodeFingerprint: "fingerprint-a", PublicKey: "public-key", }) if !errors.Is(err, ErrInvalidJoinToken) { t.Fatalf("err = %v, want ErrInvalidJoinToken", err) } } func TestRevokeJoinTokenRequiresPlatformAdmin(t *testing.T) { store := &fakeRepository{platformRole: "user"} service := NewService(store) _, err := service.RevokeJoinToken(context.Background(), RevokeJoinTokenInput{ ActorUserID: "user-1", ClusterID: "cluster-1", TokenID: "token-1", }) if !errors.Is(err, ErrAccessDenied) { t.Fatalf("err = %v, want ErrAccessDenied", err) } } func TestApproveJoinRequestReturnsBootstrapContract(t *testing.T) { store := &fakeRepository{platformRole: PlatformRoleAdmin} service := NewService(store) approved, err := service.ApproveJoinRequest(context.Background(), ApproveJoinRequestInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", JoinRequestID: "join-request-1", NodeKey: "node-key-1", }) if err != nil { t.Fatalf("approve join request: %v", err) } if approved.Bootstrap.ClusterID != "cluster-1" || approved.Bootstrap.IdentityStatus == "" { t.Fatalf("unexpected bootstrap contract: %+v", approved.Bootstrap) } if approved.Bootstrap.ClusterAuthority == nil || approved.Bootstrap.AuthoritySignature == nil || len(approved.Bootstrap.AuthorityPayload) == 0 { t.Fatalf("bootstrap missing authority contract: %+v", approved.Bootstrap) } if err := clusterauth.VerifyRaw(store.clusterAuthority.PublicKey, approved.Bootstrap.AuthorityPayload, *approved.Bootstrap.AuthoritySignature); err != nil { t.Fatalf("verify approval authority signature: %v", err) } } func TestGetJoinRequestBootstrapReturnsSignedApproval(t *testing.T) { nodeID := "node-1" store := &fakeRepository{ platformRole: PlatformRoleAdmin, bootstrapJoinRequest: NodeJoinRequest{ ID: "join-request-1", ClusterID: "cluster-1", NodeFingerprint: "node-fp", PublicKey: "node-public-key", Status: JoinRequestStatusApproved, ApprovedNodeID: &nodeID, }, } service := NewService(store) result, err := service.GetJoinRequestBootstrap(context.Background(), GetJoinRequestBootstrapInput{ ClusterID: "cluster-1", JoinRequestID: "join-request-1", NodeFingerprint: "node-fp", PublicKey: "node-public-key", }) if err != nil { t.Fatalf("get join request bootstrap: %v", err) } if result.Bootstrap == nil || result.Bootstrap.NodeID != nodeID || result.Bootstrap.ClusterAuthority == nil { t.Fatalf("unexpected bootstrap result: %+v", result) } if result.Bootstrap.AuthoritySignature == nil || len(result.Bootstrap.AuthorityPayload) == 0 { t.Fatalf("bootstrap missing authority signature: %+v", result.Bootstrap) } if err := clusterauth.VerifyRaw(store.clusterAuthority.PublicKey, result.Bootstrap.AuthorityPayload, *result.Bootstrap.AuthoritySignature); err != nil { t.Fatalf("verify bootstrap authority signature: %v", err) } } func TestSetDesiredWorkloadRequiresPlatformAdmin(t *testing.T) { store := &fakeRepository{platformRole: "user"} service := NewService(store) _, err := service.SetDesiredWorkload(context.Background(), SetDesiredWorkloadInput{ ActorUserID: "user-1", ClusterID: "cluster-1", NodeID: "node-1", ServiceType: "rdp-worker", }) if !errors.Is(err, ErrAccessDenied) { t.Fatalf("err = %v, want ErrAccessDenied", err) } } func TestReportWorkloadStatusDefaultsToSafeStubState(t *testing.T) { store := &fakeRepository{} service := NewService(store) status, err := service.ReportWorkloadStatus(context.Background(), ReportWorkloadStatusInput{ ClusterID: "cluster-1", NodeID: "node-1", ServiceType: "rdp-worker", }) if err != nil { t.Fatalf("report workload status: %v", err) } if status.ReportedState != "unknown" || status.RuntimeMode != "container" { t.Fatalf("unexpected status defaults: %+v", status) } } func TestReportMeshLinkDoesNotRequirePlatformAdmin(t *testing.T) { store := &fakeRepository{} service := NewService(store) link, err := service.ReportMeshLink(context.Background(), ReportMeshLinkInput{ ClusterID: "cluster-1", SourceNodeID: "node-a", TargetNodeID: "node-b", LinkStatus: "reachable", }) if err != nil { t.Fatalf("report mesh link: %v", err) } if link.LinkStatus != "reachable" { t.Fatalf("LinkStatus = %q", link.LinkStatus) } } func TestCreateRouteIntentRequiresPlatformAdmin(t *testing.T) { store := &fakeRepository{platformRole: "user"} service := NewService(store) _, err := service.CreateRouteIntent(context.Background(), CreateRouteIntentInput{ ActorUserID: "user-1", ClusterID: "cluster-1", ServiceClass: "input", }) if !errors.Is(err, ErrAccessDenied) { t.Fatalf("err = %v, want ErrAccessDenied", err) } } func TestGetNodeSyntheticMeshConfigRequiresTestingFlag(t *testing.T) { service := NewService(&fakeRepository{}) cfg, err := service.GetNodeSyntheticMeshConfig(context.Background(), GetNodeSyntheticMeshConfigInput{ ClusterID: "cluster-1", NodeID: "node-a", }) if err != nil { t.Fatalf("get synthetic config: %v", err) } if cfg.Enabled { t.Fatal("config must be disabled when synthetic testing flag is off") } if len(cfg.Routes) != 0 || len(cfg.PeerEndpoints) != 0 { t.Fatalf("disabled config must not leak topology: %+v", cfg) } } func TestGetNodeSyntheticMeshConfigIsNodeScoped(t *testing.T) { now := time.Date(2026, 4, 27, 12, 0, 0, 0, time.UTC) service := NewService(&fakeRepository{ testingFlags: EffectiveNodeTestingFlags{ Enabled: true, SyntheticLinksEnabled: true, }, routeIntents: []MeshRouteIntent{ { ID: "route-a-b", ClusterID: "cluster-1", SourceSelector: json.RawMessage(`{"node_id":"node-a"}`), DestinationSelector: json.RawMessage(`{"node_id":"node-b"}`), ServiceClass: "synthetic", Status: "active", Policy: json.RawMessage(`{ "synthetic_enabled": true, "hops": ["node-a", "node-r", "node-b"], "allowed_channels": ["fabric_control", "route_control"], "peer_endpoints": { "node-r": "http://node-r:19000", "node-b": "http://node-b:19000", "node-y": "http://node-y:19000" }, "peer_endpoint_candidates": { "node-r": [ { "endpoint_id": "node-r-public", "node_id": "node-r", "transport": "direct_tcp_tls", "address": "203.0.113.10:443", "address_family": "ipv4", "reachability": "public", "nat_type": "none", "connectivity_mode": "direct", "region": "eu", "priority": 10, "policy_tags": ["fast-path"], "metadata": {"source":"test"} } ], "node-b": [ { "endpoint_id": "node-b-outbound", "node_id": "node-b", "transport": "outbound_reverse", "address": "node-b.reverse.local", "reachability": "outbound_only", "nat_type": "symmetric", "connectivity_mode": "outbound_only", "priority": 20 } ] }, "recovery_seeds": [ { "node_id": "node-r", "endpoint": "https://node-r.example.test:443", "transport": "direct_tcp_tls", "connectivity_mode": "direct", "region": "eu", "priority": 10, "metadata": {"role":"stable-recovery"} }, { "node_id": "node-seed", "endpoint": "wss://seed.example.test/mesh", "transport": "wss", "connectivity_mode": "direct", "priority": 20 } ], "route_version": "route-v1", "policy_version": "policy-v1", "peer_directory_version": "peers-v1" }`), UpdatedAt: now, }, { ID: "route-x-y", ClusterID: "cluster-1", SourceSelector: json.RawMessage(`{"node_id":"node-x"}`), DestinationSelector: json.RawMessage(`{"node_id":"node-y"}`), ServiceClass: "synthetic", Status: "active", Policy: json.RawMessage(`{ "synthetic_enabled": true, "hops": ["node-x", "node-y"], "peer_endpoints": {"node-y": "http://node-y:19000"} }`), UpdatedAt: now, }, }, }) service.now = func() time.Time { return now } cfg, err := service.GetNodeSyntheticMeshConfig(context.Background(), GetNodeSyntheticMeshConfigInput{ ClusterID: "cluster-1", NodeID: "node-a", }) if err != nil { t.Fatalf("get synthetic config: %v", err) } if !cfg.Enabled { t.Fatal("config should be enabled") } if len(cfg.Routes) != 1 || cfg.Routes[0].RouteID != "route-a-b" { t.Fatalf("routes = %+v", cfg.Routes) } if cfg.PeerEndpoints["node-r"] == "" || cfg.PeerEndpoints["node-b"] == "" { t.Fatalf("peer endpoints missing: %+v", cfg.PeerEndpoints) } if _, leaked := cfg.PeerEndpoints["node-y"]; leaked { t.Fatalf("unrelated topology leaked: %+v", cfg.PeerEndpoints) } nodeRCandidates := cfg.PeerEndpointCandidates["node-r"] if len(nodeRCandidates) != 1 { t.Fatalf("node-r candidates = %+v", cfg.PeerEndpointCandidates) } if got := nodeRCandidates[0]; got.EndpointID != "node-r-public" || got.Transport != "direct_tcp_tls" || got.Reachability != "public" || got.NATType != "none" || got.ConnectivityMode != "direct" || got.Priority != 10 { t.Fatalf("unexpected node-r candidate: %+v", got) } if _, leaked := cfg.PeerEndpointCandidates["node-y"]; leaked { t.Fatalf("unrelated candidate topology leaked: %+v", cfg.PeerEndpointCandidates) } if len(cfg.RecoverySeeds) != 2 || cfg.RecoverySeeds[0].NodeID != "node-r" || cfg.RecoverySeeds[1].NodeID != "node-seed" { t.Fatalf("unexpected recovery seeds: %+v", cfg.RecoverySeeds) } nodeRDirectory, ok := findPeerDirectoryEntry(cfg.PeerDirectory, "node-r") if !ok || nodeRDirectory.CandidateCount != 1 || !nodeRDirectory.RecoverySeed { t.Fatalf("node-r peer directory missing recovery/candidate metadata: %+v", cfg.PeerDirectory) } if _, ok := findPeerDirectoryEntry(cfg.PeerDirectory, "node-a"); ok { t.Fatalf("local node leaked into peer directory: %+v", cfg.PeerDirectory) } if _, ok := findPeerDirectoryEntry(cfg.PeerDirectory, "node-y"); ok { t.Fatalf("unrelated node leaked into peer directory: %+v", cfg.PeerDirectory) } if cfg.ProductionForwarding { t.Fatal("production forwarding must remain false") } } func TestGetNodeSyntheticMeshConfigUsesReportedMeshEndpoint(t *testing.T) { now := time.Date(2026, 4, 28, 12, 0, 0, 0, time.UTC) service := NewService(&fakeRepository{ testingFlags: EffectiveNodeTestingFlags{ Enabled: true, SyntheticLinksEnabled: true, }, routeIntents: []MeshRouteIntent{ { ID: "route-a-b", ClusterID: "cluster-1", SourceSelector: json.RawMessage(`{"node_id":"node-a"}`), DestinationSelector: json.RawMessage(`{"node_id":"node-b"}`), ServiceClass: "synthetic", Status: "active", Policy: json.RawMessage(`{ "synthetic_enabled": true, "hops": ["node-a", "node-b"] }`), UpdatedAt: now, }, }, heartbeats: map[string][]NodeHeartbeat{ "node-b": { { ClusterID: "cluster-1", NodeID: "node-b", Metadata: json.RawMessage(`{ "mesh_endpoint_report": { "schema_version": "c17z6.mesh_endpoint_report.v1", "cluster_id": "cluster-1", "node_id": "node-b", "peer_endpoint": "https://node-b.dynamic.example.test:443", "transport": "direct_tcp_tls", "connectivity_mode": "direct", "nat_type": "none", "endpoint_candidates": [ { "endpoint_id": "node-b-dynamic", "node_id": "node-b", "transport": "direct_tcp_tls", "address": "https://node-b.dynamic.example.test:443", "reachability": "public", "connectivity_mode": "direct", "nat_type": "none", "priority": 1, "metadata": {"source":"heartbeat"} } ] } }`), ObservedAt: now, }, }, }, }) service.now = func() time.Time { return now } cfg, err := service.GetNodeSyntheticMeshConfig(context.Background(), GetNodeSyntheticMeshConfigInput{ ClusterID: "cluster-1", NodeID: "node-a", }) if err != nil { t.Fatalf("get synthetic config: %v", err) } if cfg.PeerEndpoints["node-b"] != "https://node-b.dynamic.example.test:443" { t.Fatalf("reported endpoint not projected: %+v", cfg.PeerEndpoints) } if got := cfg.PeerEndpointCandidates["node-b"]; len(got) != 1 || got[0].EndpointID != "node-b-dynamic" { t.Fatalf("reported candidates not projected: %+v", cfg.PeerEndpointCandidates) } entry, ok := findPeerDirectoryEntry(cfg.PeerDirectory, "node-b") if !ok || entry.EndpointCount != 1 || entry.CandidateCount != 1 { t.Fatalf("peer directory did not include reported endpoint/candidate: %+v", cfg.PeerDirectory) } } func TestGetNodeSyntheticMeshConfigIssuesRendezvousRelayLeases(t *testing.T) { now := time.Date(2026, 4, 28, 12, 0, 0, 0, time.UTC) service := NewService(&fakeRepository{ testingFlags: EffectiveNodeTestingFlags{ Enabled: true, SyntheticLinksEnabled: true, }, routeIntents: []MeshRouteIntent{ { ID: "route-a-b", ClusterID: "cluster-1", SourceSelector: json.RawMessage(`{"node_id":"node-a"}`), DestinationSelector: json.RawMessage(`{"node_id":"node-b"}`), ServiceClass: "synthetic", Status: "active", Policy: json.RawMessage(`{ "synthetic_enabled": true, "hops": ["node-a", "node-r", "node-b"], "allowed_channels": ["fabric_control", "route_control", "service_payload"], "peer_endpoints": { "node-r": "http://node-r:19000" }, "peer_endpoint_candidates": { "node-b": [ { "endpoint_id": "node-b-outbound", "node_id": "node-b", "transport": "outbound_reverse", "address": "node-b.reverse.local", "reachability": "outbound_only", "nat_type": "symmetric", "connectivity_mode": "outbound_only", "priority": 20 } ] }, "rendezvous_leases": [ { "peer_node_id": "node-b", "relay_node_id": "node-r", "relay_endpoint": "http://node-r:19000", "priority": 5 } ] }`), UpdatedAt: now, }, { ID: "route-x-y", ClusterID: "cluster-1", SourceSelector: json.RawMessage(`{"node_id":"node-x"}`), DestinationSelector: json.RawMessage(`{"node_id":"node-y"}`), ServiceClass: "synthetic", Status: "active", Policy: json.RawMessage(`{ "synthetic_enabled": true, "hops": ["node-x", "node-y"], "peer_endpoints": {"node-x": "http://node-x:19000"}, "rendezvous_leases": [ { "peer_node_id": "node-y", "relay_node_id": "node-x", "relay_endpoint": "http://node-x:19000" } ] }`), UpdatedAt: now, }, }, }) service.now = func() time.Time { return now } cfg, err := service.GetNodeSyntheticMeshConfig(context.Background(), GetNodeSyntheticMeshConfigInput{ ClusterID: "cluster-1", NodeID: "node-a", }) if err != nil { t.Fatalf("get synthetic config: %v", err) } if cfg.SchemaVersion != "c17z18.synthetic.v1" { t.Fatalf("schema version = %s, want c17z18.synthetic.v1", cfg.SchemaVersion) } if len(cfg.RendezvousLeases) != 1 { t.Fatalf("unexpected rendezvous leases: %+v", cfg.RendezvousLeases) } lease := cfg.RendezvousLeases[0] if lease.LeaseID != "route-a-b-rv-node-b-via-node-r" || lease.PeerNodeID != "node-b" || lease.RelayNodeID != "node-r" || lease.RelayEndpoint != "http://node-r:19000" || lease.Transport != "relay_control" || lease.Priority != 5 || !lease.ControlPlaneOnly || !containsString(lease.AllowedChannels, "fabric_control") || containsString(lease.AllowedChannels, "service_payload") { t.Fatalf("unexpected rendezvous lease contract: %+v", lease) } if _, ok := findPeerDirectoryEntry(cfg.PeerDirectory, "node-y"); ok { t.Fatalf("unrelated rendezvous lease leaked into peer directory: %+v", cfg.PeerDirectory) } nodeB, ok := findPeerDirectoryEntry(cfg.PeerDirectory, "node-b") if !ok || !containsString(nodeB.ConnectivityModes, "relay_required") { t.Fatalf("peer directory missing rendezvous peer mode: %+v", cfg.PeerDirectory) } nodeR, ok := findPeerDirectoryEntry(cfg.PeerDirectory, "node-r") if !ok || !containsString(nodeR.ConnectivityModes, "relay_control") { t.Fatalf("peer directory missing relay control mode: %+v", cfg.PeerDirectory) } } func TestGetNodeSyntheticMeshConfigReplacesStaleRendezvousRelay(t *testing.T) { now := time.Date(2026, 4, 28, 12, 30, 0, 0, time.UTC) staleHeartbeatMetadata, err := json.Marshal(map[string]any{ "mesh_rendezvous_lease_report": map[string]any{ "schema_version": "c17z18.mesh_rendezvous_lease_report.v1", "cluster_id": "cluster-1", "node_id": "node-a", "observed_at": now.Format(time.RFC3339Nano), "leases": []map[string]any{ { "lease_id": "route-a-b-rv-node-b-via-node-r-old", "peer_node_id": "node-b", "relay_node_id": "node-r-old", "route_ids": []string{"route-a-b"}, "stale_relay": true, "reselection_needed": true, "connection_state": "degraded", "reason": "auto_outbound_only", }, }, }, }) if err != nil { t.Fatalf("marshal heartbeat metadata: %v", err) } service := NewService(&fakeRepository{ testingFlags: EffectiveNodeTestingFlags{ Enabled: true, SyntheticLinksEnabled: true, }, heartbeats: map[string][]NodeHeartbeat{ "node-a": { { ClusterID: "cluster-1", NodeID: "node-a", Metadata: staleHeartbeatMetadata, ObservedAt: now.Add(-10 * time.Second), }, }, }, routeIntents: []MeshRouteIntent{ { ID: "route-a-b", ClusterID: "cluster-1", SourceSelector: json.RawMessage(`{"node_id":"node-a"}`), DestinationSelector: json.RawMessage(`{"node_id":"node-b"}`), ServiceClass: "synthetic", Status: "active", Policy: json.RawMessage(`{ "synthetic_enabled": true, "hops": ["node-a", "node-r-old", "node-r-new", "node-b"], "allowed_channels": ["fabric_control", "route_control"], "peer_endpoints": { "node-r-old": "http://node-r-old:19000", "node-r-new": "http://node-r-new:19000" }, "peer_endpoint_candidates": { "node-b": [ { "endpoint_id": "node-b-outbound", "node_id": "node-b", "transport": "outbound_reverse", "address": "node-b.reverse.local", "reachability": "outbound_only", "nat_type": "symmetric", "connectivity_mode": "outbound_only", "priority": 5 } ] }, "rendezvous_leases": [ { "lease_id": "route-a-b-rv-node-b-via-node-r-old", "peer_node_id": "node-b", "relay_node_id": "node-r-old", "relay_endpoint": "http://node-r-old:19000", "priority": 4 } ] }`), UpdatedAt: now, }, }, }) service.now = func() time.Time { return now } cfg, err := service.GetNodeSyntheticMeshConfig(context.Background(), GetNodeSyntheticMeshConfigInput{ ClusterID: "cluster-1", NodeID: "node-a", }) if err != nil { t.Fatalf("get synthetic config: %v", err) } if len(cfg.RendezvousLeases) != 1 { t.Fatalf("unexpected rendezvous leases: %+v", cfg.RendezvousLeases) } lease := cfg.RendezvousLeases[0] if lease.RelayNodeID != "node-r-new" || lease.LeaseID != "route-a-b-rv-node-b-via-node-r-new" || lease.Reason != "stale_relay_replacement" { t.Fatalf("stale relay was not replaced: %+v", lease) } var metadata map[string]any if err := json.Unmarshal(lease.Metadata, &metadata); err != nil { t.Fatalf("unmarshal lease metadata: %v", err) } if metadata["replacement_for_stale_relay"] != true || metadata["relay_replacement_contract"] != "stale_relay_feedback_policy" { t.Fatalf("replacement metadata missing: %+v", metadata) } if cfg.RendezvousRelayPolicy == nil || cfg.RendezvousRelayPolicy.StaleRelayCount != 1 || cfg.RendezvousRelayPolicy.WithdrawnLeaseCount != 1 || cfg.RendezvousRelayPolicy.ReplacementLeaseCount != 1 { t.Fatalf("unexpected relay policy report: %+v", cfg.RendezvousRelayPolicy) } var decision RendezvousRelayPolicyDecision for _, item := range cfg.RendezvousRelayPolicy.Decisions { if item.Reason == "stale_relay_replacement" { decision = item break } } if decision.SelectedRelayID != "node-r-new" || decision.StaleRelayNodeID != "node-r-old" { t.Fatalf("unexpected relay replacement decision: %+v", cfg.RendezvousRelayPolicy.Decisions) } if cfg.RoutePathDecisions == nil || cfg.RoutePathDecisions.SchemaVersion != "c17z18.route_path_decisions.v1" || cfg.RoutePathDecisions.DecisionCount != 1 || cfg.RoutePathDecisions.ReplacementDecisionCount != 1 { t.Fatalf("unexpected route path decisions: %+v", cfg.RoutePathDecisions) } pathDecision := cfg.RoutePathDecisions.Decisions[0] if pathDecision.DecisionSource != "stale_relay_replacement" || pathDecision.SelectedRelayID != "node-r-new" || pathDecision.StaleRelayNodeID != "node-r-old" || pathDecision.RendezvousPeerNodeID != "node-b" || pathDecision.RendezvousLeaseID != "route-a-b-rv-node-b-via-node-r-new" || pathDecision.NextHopID != "node-r-new" || pathDecision.ProductionForwarding || !pathDecision.ControlPlaneOnly || strings.Join(pathDecision.EffectiveHops, ",") != "node-a,node-r-new,node-b" { t.Fatalf("unexpected route path decision: %+v", pathDecision) } } func TestGetNodeSyntheticMeshConfigAppliesReplacementPathHintForExit(t *testing.T) { now := time.Date(2026, 4, 28, 12, 30, 0, 0, time.UTC) hintMetadata, err := json.Marshal(map[string]any{ "mesh_route_path_decision_report": map[string]any{ "cluster_id": "cluster-1", "node_id": "node-a", "decisions": []map[string]any{ { "decision_id": "route-a-b-path-node-a-via-node-r-new", "route_id": "route-a-b", "cluster_id": "cluster-1", "local_node_id": "node-a", "source_node_id": "node-a", "destination_node_id": "node-b", "original_hops": []string{"node-a", "node-r-old", "node-r-new", "node-b"}, "effective_hops": []string{"node-a", "node-r-new", "node-b"}, "next_hop_id": "node-r-new", "local_role": "entry", "selected_relay_id": "node-r-new", "selected_relay_endpoint": "http://node-r-new:19000", "stale_relay_node_id": "node-r-old", "rendezvous_peer_node_id": "node-b", "rendezvous_lease_id": "route-a-b-rv-node-b-via-node-r-new", "rendezvous_lease_reason": "stale_relay_replacement", "decision_source": "stale_relay_replacement", "generation": "hint-generation", "path_score": 900, "score_reasons": []string{"route_path_decision_hint"}, "control_plane_only": true, "production_forwarding": false, "expires_at": now.Add(time.Hour).UTC().Format(time.RFC3339Nano), }, }, }, }) if err != nil { t.Fatalf("marshal hint metadata: %v", err) } service := NewService(&fakeRepository{ testingFlags: EffectiveNodeTestingFlags{ Enabled: true, SyntheticLinksEnabled: true, }, heartbeats: map[string][]NodeHeartbeat{ "node-a": { { ClusterID: "cluster-1", NodeID: "node-a", Metadata: hintMetadata, ObservedAt: now.Add(-10 * time.Second), }, }, }, routeIntents: []MeshRouteIntent{ { ID: "route-a-b", ClusterID: "cluster-1", SourceSelector: json.RawMessage(`{"node_id":"node-a"}`), DestinationSelector: json.RawMessage(`{"node_id":"node-b"}`), ServiceClass: "synthetic", Status: "active", Policy: json.RawMessage(`{ "synthetic_enabled": true, "hops": ["node-a", "node-r-old", "node-r-new", "node-b"], "allowed_channels": ["fabric_control", "route_control"], "peer_endpoints": { "node-r-old": "http://node-r-old:19000", "node-r-new": "http://node-r-new:19000" }, "peer_endpoint_candidates": { "node-b": [ { "endpoint_id": "node-b-outbound", "node_id": "node-b", "transport": "outbound_reverse", "address": "node-b.reverse.local", "reachability": "outbound_only", "nat_type": "symmetric", "connectivity_mode": "outbound_only", "priority": 5 } ] }, "rendezvous_leases": [ { "lease_id": "route-a-b-rv-node-b-via-node-r-old", "peer_node_id": "node-b", "relay_node_id": "node-r-old", "relay_endpoint": "http://node-r-old:19000", "priority": 4 } ] }`), UpdatedAt: now, }, }, }) service.now = func() time.Time { return now } cfg, err := service.GetNodeSyntheticMeshConfig(context.Background(), GetNodeSyntheticMeshConfigInput{ ClusterID: "cluster-1", NodeID: "node-b", }) if err != nil { t.Fatalf("get synthetic config: %v", err) } if len(cfg.RendezvousLeases) != 1 || cfg.RendezvousLeases[0].RelayNodeID != "node-r-new" || cfg.RendezvousLeases[0].Reason != "stale_relay_replacement" { t.Fatalf("replacement hint did not withdraw stale relay lease: %+v", cfg.RendezvousLeases) } if cfg.RoutePathDecisions == nil || cfg.RoutePathDecisions.ReplacementDecisionCount != 1 || len(cfg.RoutePathDecisions.Decisions) != 1 { t.Fatalf("unexpected route path decisions: %+v", cfg.RoutePathDecisions) } decision := cfg.RoutePathDecisions.Decisions[0] if decision.DecisionSource != "stale_relay_replacement" || decision.LocalRole != "exit" || decision.PreviousHopID != "node-r-new" || decision.SelectedRelayID != "node-r-new" || decision.StaleRelayNodeID != "node-r-old" || decision.RendezvousPeerNodeID != "node-b" || strings.Join(decision.EffectiveHops, ",") != "node-a,node-r-new,node-b" { t.Fatalf("unexpected hinted route path decision: %+v", decision) } } func TestGetNodeSyntheticMeshConfigUsesRouteHealthDriftToReselectRelay(t *testing.T) { now := time.Date(2026, 4, 28, 12, 30, 0, 0, time.UTC) routeHealthMetadata, err := json.Marshal(map[string]any{ "observation_type": "synthetic_route_health", "route_id": "route-a-b", "route_path_decision_applied": true, "route_path_decision_selected_relay_id": "node-s", "route_path_decision_rendezvous_peer_node_id": "node-b", "route_path_decision_rendezvous_lease_id": "route-a-b-rv-node-b-via-node-s", "route_path_decision_rendezvous_lease_reason": "auto_rendezvous_required", "expected_effective_hops": []string{"node-a", "node-s", "node-b"}, "observed_ack_path": []string{"node-a", "node-t", "node-b"}, "route_path_drift_detected": true, "control_plane_only": true, "production_forwarding": false, "production_payload_forwarding": false, "route_health_production_payload_forwarding": false, "route_health_service_payload_forwarding": false, "synthetic_route_health_route_path_runtime": true, "production_route_path_forwarding_runtime": false, "route_health_route_config_contract": "control_plane_route_path_decisions_to_synthetic_route_health", }) if err != nil { t.Fatalf("marshal route health metadata: %v", err) } service := NewService(&fakeRepository{ testingFlags: EffectiveNodeTestingFlags{ Enabled: true, SyntheticLinksEnabled: true, }, meshLinks: []MeshLinkObservation{ { ClusterID: "cluster-1", SourceNodeID: "node-a", TargetNodeID: "node-b", LinkStatus: "reachable", Metadata: routeHealthMetadata, ObservedAt: now.Add(-10 * time.Second), }, }, routeIntents: []MeshRouteIntent{ { ID: "route-a-b", ClusterID: "cluster-1", SourceSelector: json.RawMessage(`{"node_id":"node-a"}`), DestinationSelector: json.RawMessage(`{"node_id":"node-b"}`), ServiceClass: "synthetic", Status: "active", Policy: json.RawMessage(`{ "synthetic_enabled": true, "hops": ["node-a", "node-s", "node-t", "node-b"], "allowed_channels": ["fabric_control", "route_control"], "peer_endpoint_candidates": { "node-b": [ { "endpoint_id": "node-b-outbound", "node_id": "node-b", "transport": "outbound_reverse", "address": "node-b.reverse.local", "reachability": "outbound_only", "nat_type": "symmetric", "connectivity_mode": "outbound_only", "priority": 5 } ], "node-s": [ { "endpoint_id": "node-s-public", "node_id": "node-s", "transport": "direct_tcp_tls", "address": "http://node-s:19000", "reachability": "public", "nat_type": "none", "connectivity_mode": "direct", "priority": 1, "policy_tags": ["fast-path"] } ], "node-t": [ { "endpoint_id": "node-t-public", "node_id": "node-t", "transport": "direct_tcp_tls", "address": "http://node-t:19000", "reachability": "public", "nat_type": "none", "connectivity_mode": "direct", "priority": 50 } ] } }`), UpdatedAt: now, }, }, }) service.now = func() time.Time { return now } cfg, err := service.GetNodeSyntheticMeshConfig(context.Background(), GetNodeSyntheticMeshConfigInput{ ClusterID: "cluster-1", NodeID: "node-a", }) if err != nil { t.Fatalf("get synthetic config: %v", err) } if len(cfg.RendezvousLeases) != 1 { t.Fatalf("unexpected rendezvous leases: %+v", cfg.RendezvousLeases) } lease := cfg.RendezvousLeases[0] if lease.RelayNodeID != "node-t" || lease.Reason != "stale_relay_replacement" { t.Fatalf("route health drift did not reselect relay: %+v", lease) } if cfg.RendezvousRelayPolicy == nil || cfg.RendezvousRelayPolicy.StaleRelayCount != 1 || cfg.RendezvousRelayPolicy.ReplacementLeaseCount != 1 || cfg.RendezvousRelayPolicy.ScoringMode != "route_adjacency_endpoint_priority_mesh_link_health_synthetic_route_health_feedback" { t.Fatalf("unexpected relay policy report: %+v", cfg.RendezvousRelayPolicy) } var policyDecision RendezvousRelayPolicyDecision for _, item := range cfg.RendezvousRelayPolicy.Decisions { if item.Reason == "stale_relay_replacement" { policyDecision = item break } } if policyDecision.StaleRelayNodeID != "node-s" || policyDecision.SelectedRelayID != "node-t" || policyDecision.PeerNodeID != "node-b" { t.Fatalf("unexpected route health replacement decision: %+v", cfg.RendezvousRelayPolicy.Decisions) } if cfg.RoutePathDecisions == nil || cfg.RoutePathDecisions.ReplacementDecisionCount != 1 { t.Fatalf("expected replacement route path decision: %+v", cfg.RoutePathDecisions) } decision := cfg.RoutePathDecisions.Decisions[0] if decision.SelectedRelayID != "node-t" || decision.StaleRelayNodeID != "node-s" || decision.RendezvousPeerNodeID != "node-b" || strings.Join(decision.EffectiveHops, ",") != "node-a,node-t,node-b" || decision.ProductionForwarding || !decision.ControlPlaneOnly { t.Fatalf("unexpected route path decision from route health feedback: %+v", decision) } } func TestGetNodeSyntheticMeshConfigUsesRouteHealthLatencyForRelayScore(t *testing.T) { now := time.Date(2026, 4, 28, 12, 30, 0, 0, time.UTC) routeHealthMetadata, err := json.Marshal(map[string]any{ "observation_type": "synthetic_route_health", "route_id": "route-a-b", "route_path_decision_applied": true, "route_path_decision_selected_relay_id": "node-t", "route_path_decision_rendezvous_peer_node_id": "node-b", "expected_effective_hops": []string{"node-a", "node-t", "node-b"}, "observed_ack_path": []string{"node-a", "node-t", "node-b"}, "route_path_drift_detected": false, "control_plane_only": true, "production_forwarding": false, "production_payload_forwarding": false, "route_health_production_payload_forwarding": false, "route_health_service_payload_forwarding": false, }) if err != nil { t.Fatalf("marshal route health metadata: %v", err) } latency := 5 quality := 99 service := NewService(&fakeRepository{ testingFlags: EffectiveNodeTestingFlags{ Enabled: true, SyntheticLinksEnabled: true, }, meshLinks: []MeshLinkObservation{ { ClusterID: "cluster-1", SourceNodeID: "node-a", TargetNodeID: "node-b", LinkStatus: "reachable", LatencyMs: &latency, QualityScore: &quality, Metadata: routeHealthMetadata, ObservedAt: now.Add(-10 * time.Second), }, }, routeIntents: []MeshRouteIntent{ { ID: "route-a-b", ClusterID: "cluster-1", SourceSelector: json.RawMessage(`{"node_id":"node-a"}`), DestinationSelector: json.RawMessage(`{"node_id":"node-b"}`), ServiceClass: "synthetic", Status: "active", Policy: json.RawMessage(`{ "synthetic_enabled": true, "hops": ["node-a", "node-s", "node-t", "node-b"], "allowed_channels": ["fabric_control", "route_control"], "peer_endpoint_candidates": { "node-b": [ { "endpoint_id": "node-b-outbound", "node_id": "node-b", "transport": "outbound_reverse", "address": "node-b.reverse.local", "reachability": "outbound_only", "nat_type": "symmetric", "connectivity_mode": "outbound_only", "priority": 5 } ], "node-s": [ { "endpoint_id": "node-s-public", "node_id": "node-s", "transport": "direct_tcp_tls", "address": "http://node-s:19000", "reachability": "public", "nat_type": "none", "connectivity_mode": "direct", "priority": 1, "policy_tags": ["fast-path"] } ], "node-t": [ { "endpoint_id": "node-t-public", "node_id": "node-t", "transport": "direct_tcp_tls", "address": "http://node-t:19000", "reachability": "public", "nat_type": "none", "connectivity_mode": "direct", "priority": 50 } ] } }`), UpdatedAt: now, }, }, }) service.now = func() time.Time { return now } cfg, err := service.GetNodeSyntheticMeshConfig(context.Background(), GetNodeSyntheticMeshConfigInput{ ClusterID: "cluster-1", NodeID: "node-a", }) if err != nil { t.Fatalf("get synthetic config: %v", err) } if len(cfg.RendezvousLeases) != 1 { t.Fatalf("unexpected rendezvous leases: %+v", cfg.RendezvousLeases) } lease := cfg.RendezvousLeases[0] if lease.RelayNodeID != "node-t" || lease.Reason == "stale_relay_replacement" { t.Fatalf("route health latency did not influence relay score: %+v", lease) } var metadata map[string]any if err := json.Unmarshal(lease.Metadata, &metadata); err != nil { t.Fatalf("unmarshal lease metadata: %v", err) } reasons, _ := metadata["relay_selection_score_reasons"].([]any) if !anyString(reasons, "route_health_reachable") || !anyString(reasons, "route_health_no_drift") || !anyString(reasons, "route_health_latency") { t.Fatalf("route health score reasons missing: %+v", metadata) } } func anyString(values []any, want string) bool { for _, value := range values { if text, ok := value.(string); ok && text == want { return true } } return false } func findPeerDirectoryEntry(entries []PeerDirectoryEntry, nodeID string) (PeerDirectoryEntry, bool) { for _, entry := range entries { if entry.NodeID == nodeID { return entry, true } } return PeerDirectoryEntry{}, false } func TestValidatePeerEndpointCandidates(t *testing.T) { valid := map[string][]PeerEndpointCandidate{ "node-b": { { EndpointID: "node-b-public", NodeID: "node-b", Transport: "direct_tcp_tls", Address: "203.0.113.20:443", AddressFamily: "ipv4", Reachability: "public", NATType: "restricted", ConnectivityMode: "direct", Priority: 10, Metadata: json.RawMessage(`{"source":"test"}`), }, }, } if err := validatePeerEndpointCandidates(valid, []string{"node-a", "node-b"}); err != nil { t.Fatalf("validate valid candidates: %v", err) } tests := []struct { name string candidates map[string][]PeerEndpointCandidate }{ { name: "unknown transport", candidates: map[string][]PeerEndpointCandidate{"node-b": {{ EndpointID: "node-b-public", NodeID: "node-b", Transport: "udp-hole-punch", Address: "203.0.113.20:443", Reachability: "public", ConnectivityMode: "direct", }}}, }, { name: "unknown nat", candidates: map[string][]PeerEndpointCandidate{"node-b": {{ EndpointID: "node-b-public", NodeID: "node-b", Transport: "direct_tcp_tls", Address: "203.0.113.20:443", Reachability: "public", NATType: "mystery_nat", ConnectivityMode: "direct", }}}, }, { name: "node outside route path", candidates: map[string][]PeerEndpointCandidate{"node-y": {{ EndpointID: "node-y-public", NodeID: "node-y", Transport: "direct_tcp_tls", Address: "203.0.113.30:443", Reachability: "public", ConnectivityMode: "direct", }}}, }, { name: "node mismatch", candidates: map[string][]PeerEndpointCandidate{"node-b": {{ EndpointID: "node-b-public", NodeID: "node-c", Transport: "direct_tcp_tls", Address: "203.0.113.20:443", Reachability: "public", ConnectivityMode: "direct", }}}, }, { name: "invalid metadata", candidates: map[string][]PeerEndpointCandidate{"node-b": {{ EndpointID: "node-b-public", NodeID: "node-b", Transport: "direct_tcp_tls", Address: "203.0.113.20:443", Reachability: "public", ConnectivityMode: "direct", Metadata: json.RawMessage(`{`), }}}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := validatePeerEndpointCandidates(tt.candidates, []string{"node-a", "node-b"}) if !errors.Is(err, ErrInvalidPayload) { t.Fatalf("err = %v, want ErrInvalidPayload", err) } }) } } func TestMinorityClusterBlocksPolicyMutation(t *testing.T) { store := &fakeRepository{ platformRole: PlatformRoleAdmin, authorityState: ClusterAuthorityState{ ClusterID: "cluster-1", AuthorityState: "minority", MutationMode: "read_only", }, } service := NewService(store) _, err := service.AssignNodeRole(context.Background(), AssignNodeRoleInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", NodeID: "node-1", Role: "rdp-worker", }) if !errors.Is(err, ErrClusterReadOnly) { t.Fatalf("err = %v, want ErrClusterReadOnly", err) } } func TestRecoveryAdminCanMutateReadOnlyCluster(t *testing.T) { store := &fakeRepository{ platformRole: PlatformRoleRecoveryAdmin, authorityState: ClusterAuthorityState{ ClusterID: "cluster-1", AuthorityState: "isolated", MutationMode: "read_only", }, } service := NewService(store) _, err := service.AssignNodeRole(context.Background(), AssignNodeRoleInput{ ActorUserID: "recovery-1", ClusterID: "cluster-1", NodeID: "node-1", Role: "rdp-worker", }) if err != nil { t.Fatalf("recovery admin mutate: %v", err) } } func TestCreateVPNConnectionRequiresPlatformAdmin(t *testing.T) { store := &fakeRepository{platformRole: "user"} service := NewService(store) _, err := service.CreateVPNConnection(context.Background(), CreateVPNConnectionInput{ ActorUserID: "user-1", ClusterID: "cluster-1", OrganizationID: "org-1", Name: "office-a", }) if !errors.Is(err, ErrAccessDenied) { t.Fatalf("err = %v, want ErrAccessDenied", err) } } func TestCreateVPNConnectionDefaultsToDisabledSingleActive(t *testing.T) { store := &fakeRepository{platformRole: PlatformRoleAdmin} service := NewService(store) item, err := service.CreateVPNConnection(context.Background(), CreateVPNConnectionInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", OrganizationID: "org-1", Name: "office-a", }) if err != nil { t.Fatalf("create vpn connection: %v", err) } if item.Mode != VPNConnectionModeSingleActive || item.DesiredState != VPNConnectionDesiredDisabled { t.Fatalf("unexpected defaults: %+v", item) } if string(store.lastVPNConnectionInput.AllowedNodePolicy) == "" || string(store.lastVPNConnectionInput.RoutingUsage) == "" { t.Fatalf("expected default json policies, got %+v", store.lastVPNConnectionInput) } } func TestCreateVPNConnectionRequiresClusterAndOrganizationScope(t *testing.T) { store := &fakeRepository{platformRole: PlatformRoleAdmin} service := NewService(store) _, err := service.CreateVPNConnection(context.Background(), CreateVPNConnectionInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", Name: "office-a", }) if !errors.Is(err, ErrInvalidPayload) { t.Fatalf("err = %v, want ErrInvalidPayload", err) } } func TestCreateVPNConnectionBlockedInReadOnlyCluster(t *testing.T) { store := &fakeRepository{ platformRole: PlatformRoleAdmin, authorityState: ClusterAuthorityState{ ClusterID: "cluster-1", AuthorityState: "minority", MutationMode: "read_only", }, } service := NewService(store) _, err := service.CreateVPNConnection(context.Background(), CreateVPNConnectionInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", OrganizationID: "org-1", Name: "office-a", }) if !errors.Is(err, ErrClusterReadOnly) { t.Fatalf("err = %v, want ErrClusterReadOnly", err) } } func TestAcquireVPNLeaseRequiresEnabledConnection(t *testing.T) { store := &fakeRepository{ platformRole: PlatformRoleAdmin, vpnConnection: VPNConnection{ ID: "vpn-1", ClusterID: "cluster-1", Mode: VPNConnectionModeSingleActive, DesiredState: VPNConnectionDesiredDisabled, }, } service := NewService(store) _, err := service.AcquireVPNConnectionLease(context.Background(), AcquireVPNConnectionLeaseInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", VPNConnectionID: "vpn-1", OwnerNodeID: "node-1", }) if err == nil || !strings.Contains(err.Error(), "enabled single_active") { t.Fatalf("err = %v, want enabled single_active validation", err) } } func TestAcquireVPNLeaseRejectsSecondActiveOwner(t *testing.T) { store := &fakeRepository{ platformRole: PlatformRoleAdmin, vpnConnection: VPNConnection{ ID: "vpn-1", ClusterID: "cluster-1", Mode: VPNConnectionModeSingleActive, DesiredState: VPNConnectionDesiredEnabled, }, acquireVPNLeaseErr: ErrVPNLeaseAlreadyActive, } service := NewService(store) _, err := service.AcquireVPNConnectionLease(context.Background(), AcquireVPNConnectionLeaseInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", VPNConnectionID: "vpn-1", OwnerNodeID: "node-2", }) if !errors.Is(err, ErrVPNLeaseAlreadyActive) { t.Fatalf("err = %v, want ErrVPNLeaseAlreadyActive", err) } } func TestAcquireVPNLeaseRejectsOwnerOutsideAllowedPolicy(t *testing.T) { store := &fakeRepository{ platformRole: PlatformRoleAdmin, vpnConnection: VPNConnection{ ID: "vpn-1", ClusterID: "cluster-1", Mode: VPNConnectionModeSingleActive, DesiredState: VPNConnectionDesiredEnabled, }, ownerEligibility: VPNLeaseOwnerEligibility{ VPNConnectionID: "vpn-1", ClusterID: "cluster-1", OwnerNodeID: "node-1", MembershipStatus: "active", NodeRegistrationStatus: NodeRegistrationActive, AllowedByPolicy: false, HasAuthorizedRole: true, }, } service := NewService(store) _, err := service.AcquireVPNConnectionLease(context.Background(), AcquireVPNConnectionLeaseInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", VPNConnectionID: "vpn-1", OwnerNodeID: "node-1", }) if !errors.Is(err, ErrVPNLeaseOwnerNotAllowed) { t.Fatalf("err = %v, want ErrVPNLeaseOwnerNotAllowed", err) } } func TestAcquireVPNLeaseRejectsOwnerWithoutVPNRole(t *testing.T) { store := &fakeRepository{ platformRole: PlatformRoleAdmin, vpnConnection: VPNConnection{ ID: "vpn-1", ClusterID: "cluster-1", Mode: VPNConnectionModeSingleActive, DesiredState: VPNConnectionDesiredEnabled, }, ownerEligibility: VPNLeaseOwnerEligibility{ VPNConnectionID: "vpn-1", ClusterID: "cluster-1", OwnerNodeID: "node-1", MembershipStatus: "active", NodeRegistrationStatus: NodeRegistrationActive, AllowedByPolicy: true, HasAuthorizedRole: false, }, } service := NewService(store) _, err := service.AcquireVPNConnectionLease(context.Background(), AcquireVPNConnectionLeaseInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", VPNConnectionID: "vpn-1", OwnerNodeID: "node-1", }) if !errors.Is(err, ErrVPNLeaseOwnerRoleRequired) { t.Fatalf("err = %v, want ErrVPNLeaseOwnerRoleRequired", err) } } func TestAcquireVPNLeaseRejectsWrongCluster(t *testing.T) { store := &fakeRepository{ platformRole: PlatformRoleAdmin, vpnConnection: VPNConnection{ ID: "vpn-1", ClusterID: "cluster-1", Mode: VPNConnectionModeSingleActive, DesiredState: VPNConnectionDesiredEnabled, }, ownerEligibilityErr: pgx.ErrNoRows, } service := NewService(store) _, err := service.AcquireVPNConnectionLease(context.Background(), AcquireVPNConnectionLeaseInput{ ActorUserID: "admin-1", ClusterID: "cluster-other", VPNConnectionID: "vpn-1", OwnerNodeID: "node-1", }) if !errors.Is(err, ErrInvalidVPNConnection) { t.Fatalf("err = %v, want ErrInvalidVPNConnection", err) } } func TestRenewVPNLeaseRejectsExpiredLease(t *testing.T) { store := &fakeRepository{ platformRole: PlatformRoleAdmin, ownerEligibility: VPNLeaseOwnerEligibility{ VPNConnectionID: "vpn-1", ClusterID: "cluster-1", OwnerNodeID: "node-1", MembershipStatus: "active", NodeRegistrationStatus: NodeRegistrationActive, AllowedByPolicy: true, HasAuthorizedRole: true, }, renewVPNLeaseErr: pgx.ErrNoRows, } service := NewService(store) _, err := service.RenewVPNConnectionLease(context.Background(), RenewVPNConnectionLeaseInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", VPNConnectionID: "vpn-1", LeaseID: "lease-1", OwnerNodeID: "node-1", FencingToken: "token-1", }) if !errors.Is(err, ErrInvalidVPNLease) { t.Fatalf("err = %v, want ErrInvalidVPNLease", err) } } func TestFenceVPNLeaseRequiresRecoveryAdmin(t *testing.T) { store := &fakeRepository{platformRole: PlatformRoleAdmin} service := NewService(store) _, err := service.FenceVPNConnectionLease(context.Background(), FenceVPNConnectionLeaseInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", VPNConnectionID: "vpn-1", LeaseID: "lease-1", }) if !errors.Is(err, ErrAccessDenied) { t.Fatalf("err = %v, want ErrAccessDenied", err) } } func TestExpireStaleVPNConnectionLeasesAuditsEachExpiredLease(t *testing.T) { store := &fakeRepository{ platformRole: PlatformRoleAdmin, expiredVPNLeases: []VPNConnectionLease{ {ID: "lease-1", ClusterID: "cluster-1", VPNConnectionID: "vpn-1", Status: VPNLeaseStatusExpired}, {ID: "lease-2", ClusterID: "cluster-1", VPNConnectionID: "vpn-2", Status: VPNLeaseStatusExpired}, }, } service := NewService(store) items, err := service.ExpireStaleVPNConnectionLeases(context.Background(), ExpireStaleVPNConnectionLeasesInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", }) if err != nil { t.Fatalf("expire stale vpn leases: %v", err) } if got, want := len(items), 2; got != want { t.Fatalf("expired leases = %d, want %d", got, want) } var auditCount int for _, event := range store.auditEvents { if event.EventType == "vpn_connection.lease_expired" { auditCount++ } } if got, want := auditCount, 2; got != want { t.Fatalf("lease_expired audit count = %d, want %d", got, want) } } func TestSetVPNConnectionAllowedNodesDeduplicatesScope(t *testing.T) { store := &fakeRepository{platformRole: PlatformRoleAdmin} service := NewService(store) items, err := service.SetVPNConnectionAllowedNodes(context.Background(), SetVPNConnectionAllowedNodesInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", VPNConnectionID: "vpn-1", NodeIDs: []string{"node-1", "node-1", " ", "node-2"}, }) if err != nil { t.Fatalf("set allowed nodes: %v", err) } if got, want := len(store.lastAllowedNodesInput.NodeIDs), 2; got != want { t.Fatalf("deduped nodes = %d, want %d", got, want) } if got, want := len(items), 2; got != want { t.Fatalf("allowed nodes returned = %d, want %d", got, want) } } func TestUpsertVPNRoutePolicyRejectsInvalidType(t *testing.T) { store := &fakeRepository{platformRole: PlatformRoleAdmin} service := NewService(store) _, err := service.UpsertVPNConnectionRoutePolicy(context.Background(), UpsertVPNConnectionRoutePolicyInput{ ActorUserID: "admin-1", ClusterID: "cluster-1", VPNConnectionID: "vpn-1", RouteType: "submarine", Destination: "10.0.0.0/24", }) if !errors.Is(err, ErrInvalidPayload) { t.Fatalf("err = %v, want ErrInvalidPayload", err) } } func TestListNodeVPNAssignmentsDoesNotRequirePlatformAdmin(t *testing.T) { store := &fakeRepository{ platformRole: "user", nodeVPNAssignments: []NodeVPNAssignment{ {VPNConnectionID: "vpn-1", ClusterID: "cluster-1", OrganizationID: "org-1", AssignmentReason: "eligible_candidate"}, }, } service := NewService(store) items, err := service.ListNodeVPNAssignments(context.Background(), "cluster-1", "node-1") if err != nil { t.Fatalf("list node vpn assignments: %v", err) } if got, want := len(items), 1; got != want { t.Fatalf("assignments = %d, want %d", got, want) } } func TestReportNodeVPNAssignmentStatusRejectsInvisibleAssignment(t *testing.T) { store := &fakeRepository{} service := NewService(store) _, err := service.ReportNodeVPNAssignmentStatus(context.Background(), ReportNodeVPNAssignmentStatusInput{ ClusterID: "cluster-1", NodeID: "node-1", VPNConnectionID: "vpn-foreign", ObservedStatus: VPNAssignmentStatusAssigned, }) if !errors.Is(err, ErrVPNLeaseOwnerNotAllowed) { t.Fatalf("err = %v, want ErrVPNLeaseOwnerNotAllowed", err) } } func TestReportNodeVPNAssignmentStatusAcceptsExplicitStates(t *testing.T) { store := &fakeRepository{ nodeVPNAssignments: []NodeVPNAssignment{ {VPNConnectionID: "vpn-1", ClusterID: "cluster-1", OrganizationID: "org-1"}, }, } service := NewService(store) status, err := service.ReportNodeVPNAssignmentStatus(context.Background(), ReportNodeVPNAssignmentStatusInput{ ClusterID: "cluster-1", NodeID: "node-1", VPNConnectionID: "vpn-1", ObservedStatus: VPNAssignmentStatusLeaseRequired, StatusPayload: json.RawMessage(`{"reason":"no_lease"}`), }) if err != nil { t.Fatalf("report node vpn assignment status: %v", err) } if status.ObservedStatus != VPNAssignmentStatusLeaseRequired { t.Fatalf("ObservedStatus = %q, want %q", status.ObservedStatus, VPNAssignmentStatusLeaseRequired) } } func TestReportNodeVPNAssignmentStatusRejectsInvalidStatus(t *testing.T) { store := &fakeRepository{ nodeVPNAssignments: []NodeVPNAssignment{ {VPNConnectionID: "vpn-1", ClusterID: "cluster-1", OrganizationID: "org-1"}, }, } service := NewService(store) _, err := service.ReportNodeVPNAssignmentStatus(context.Background(), ReportNodeVPNAssignmentStatusInput{ ClusterID: "cluster-1", NodeID: "node-1", VPNConnectionID: "vpn-1", ObservedStatus: "running_tunnel", }) if !errors.Is(err, ErrInvalidPayload) { t.Fatalf("err = %v, want ErrInvalidPayload", err) } } type fakeRepository struct { platformRole string lastTokenHash string validTokenErr error createJoinRequestID string bootstrapJoinRequest NodeJoinRequest clusterAuthority ClusterAuthorityKey lastTokenAuthority json.RawMessage lastApprovalAuthority json.RawMessage authorityState ClusterAuthorityState vpnConnection VPNConnection lastVPNConnectionInput CreateVPNConnectionInput lastAllowedNodesInput SetVPNConnectionAllowedNodesInput lastAttachInput AttachExistingNodeInput lastNodeGroupInput CreateNodeGroupInput lastAssignGroupInput AssignNodeGroupInput lastEntryPointInput CreateFabricEntryPointInput lastEgressPoolInput CreateFabricEgressPoolInput acquireVPNLeaseErr error ownerEligibility VPNLeaseOwnerEligibility ownerEligibilityErr error renewVPNLeaseErr error expiredVPNLeases []VPNConnectionLease nodeVPNAssignments []NodeVPNAssignment testingFlags EffectiveNodeTestingFlags routeIntents []MeshRouteIntent meshLinks []MeshLinkObservation heartbeats map[string][]NodeHeartbeat auditEvents []ClusterAuditEvent } func (f *fakeRepository) GetPlatformRole(context.Context, string) (string, error) { return f.platformRole, nil } func (f *fakeRepository) ListClusters(context.Context) ([]Cluster, error) { return nil, nil } func (f *fakeRepository) GetCluster(context.Context, string) (Cluster, error) { return Cluster{}, nil } func (f *fakeRepository) CreateCluster(context.Context, CreateClusterInput) (Cluster, error) { return Cluster{}, nil } func (f *fakeRepository) UpdateCluster(_ context.Context, input UpdateClusterInput) (Cluster, error) { return Cluster{ ID: input.ClusterID, Slug: "cluster-1", Name: input.Name, Status: input.Status, Region: input.Region, Metadata: input.Metadata, }, nil } func (f *fakeRepository) GetClusterAuthority(_ context.Context, clusterID string) (ClusterAuthorityKey, error) { if f.clusterAuthority.PrivateKey == "" { keys, err := clusterauth.GenerateKeyPair() if err != nil { return ClusterAuthorityKey{}, err } f.clusterAuthority = ClusterAuthorityKey{ ClusterAuthorityDescriptor: ClusterAuthorityDescriptor{ SchemaVersion: clusterauth.AuthoritySchemaVersion, ClusterID: clusterID, AuthorityState: "active", KeyAlgorithm: clusterauth.AlgorithmEd25519, PublicKey: keys.PublicKeyB64, PublicKeyFingerprint: keys.Fingerprint, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC(), }, PrivateKey: keys.PrivateKeyB64, } } if f.clusterAuthority.ClusterID == "" { f.clusterAuthority.ClusterID = clusterID } return f.clusterAuthority, nil } func (f *fakeRepository) EnsureClusterAuthority(ctx context.Context, clusterID string, _ *string) (ClusterAuthorityKey, error) { return f.GetClusterAuthority(ctx, clusterID) } func (f *fakeRepository) ListClusterNodes(context.Context, string) ([]ClusterNode, error) { return nil, nil } func (f *fakeRepository) ListNodeGroups(context.Context, string) ([]ClusterNodeGroup, error) { return nil, nil } func (f *fakeRepository) CreateNodeGroup(_ context.Context, input CreateNodeGroupInput) (ClusterNodeGroup, error) { f.lastNodeGroupInput = input return ClusterNodeGroup{ ID: "group-1", ClusterID: input.ClusterID, ParentGroupID: input.ParentGroupID, Name: input.Name, Description: input.Description, SortOrder: input.SortOrder, Metadata: input.Metadata, }, nil } func (f *fakeRepository) AssignNodeToGroup(_ context.Context, input AssignNodeGroupInput) (ClusterNode, error) { f.lastAssignGroupInput = input return ClusterNode{ ID: input.NodeID, NodeKey: "node-key-1", Name: "Node One", RegistrationStatus: NodeRegistrationActive, MembershipStatus: "active", NodeGroupID: input.GroupID, }, nil } func (f *fakeRepository) CreateJoinToken(_ context.Context, input CreateJoinTokenInput, tokenHash string) (NodeJoinToken, error) { f.lastTokenHash = tokenHash return NodeJoinToken{ ID: "token-1", ClusterID: input.ClusterID, Scope: input.Scope, ExpiresAt: input.ExpiresAt, MaxUses: input.MaxUses, Status: "active", CreatedByUserID: &input.ActorUserID, CreatedAt: time.Now().UTC(), }, nil } func (f *fakeRepository) SetJoinTokenAuthority(_ context.Context, clusterID, tokenID string, payload json.RawMessage, signature ClusterSignature) (NodeJoinToken, error) { f.lastTokenAuthority = payload return NodeJoinToken{ ID: tokenID, ClusterID: clusterID, Scope: json.RawMessage(`{"roles":["rdp-worker"]}`), ExpiresAt: time.Now().UTC().Add(time.Hour), MaxUses: 1, Status: "active", AuthorityPayload: payload, AuthoritySignature: &signature, }, nil } func (f *fakeRepository) GetValidJoinTokenByHash(context.Context, string, string) (NodeJoinToken, error) { if f.validTokenErr != nil { return NodeJoinToken{}, f.validTokenErr } return NodeJoinToken{ID: "token-1", Status: "active", ExpiresAt: time.Now().Add(time.Hour), MaxUses: 1}, nil } func (f *fakeRepository) RevokeJoinToken(context.Context, RevokeJoinTokenInput) (NodeJoinToken, error) { return NodeJoinToken{ID: "token-1", Status: "revoked"}, nil } func (f *fakeRepository) ExpireJoinTokens(context.Context, string) error { return nil } func (f *fakeRepository) CreateJoinRequest(_ context.Context, input CreateJoinRequestInput, joinTokenID string) (NodeJoinRequest, error) { id := f.createJoinRequestID if id == "" { id = "join-request-1" } return NodeJoinRequest{ ID: id, ClusterID: input.ClusterID, JoinTokenID: &joinTokenID, NodeName: input.NodeName, NodeFingerprint: input.NodeFingerprint, PublicKey: input.PublicKey, ReportedCapabilities: input.ReportedCapabilities, ReportedFacts: input.ReportedFacts, RequestedRoles: input.RequestedRoles, Status: JoinRequestStatusPending, }, nil } func (f *fakeRepository) GetJoinRequestForBootstrap(context.Context, GetJoinRequestBootstrapInput) (NodeJoinRequest, error) { if f.bootstrapJoinRequest.ID != "" { return f.bootstrapJoinRequest, nil } return NodeJoinRequest{ID: "join-request-1", ClusterID: "cluster-1", Status: JoinRequestStatusPending}, nil } func (f *fakeRepository) ListJoinRequests(context.Context, string) ([]NodeJoinRequest, error) { return nil, nil } func (f *fakeRepository) ApproveJoinRequest(_ context.Context, input ApproveJoinRequestInput) (ApprovedJoinRequest, error) { return ApprovedJoinRequest{ JoinRequest: NodeJoinRequest{ID: input.JoinRequestID, ClusterID: input.ClusterID, Status: JoinRequestStatusApproved, ApprovedNodeID: &input.NodeKey}, Bootstrap: NodeBootstrap{NodeID: input.NodeKey, ClusterID: input.ClusterID, IdentityStatus: "active"}, }, nil } func (f *fakeRepository) SetJoinRequestApprovalAuthority(_ context.Context, clusterID, joinRequestID string, payload json.RawMessage, signature ClusterSignature) (NodeJoinRequest, error) { f.lastApprovalAuthority = payload signatureRaw, _ := json.Marshal(signature) nodeID := "node-1" return NodeJoinRequest{ ID: joinRequestID, ClusterID: clusterID, Status: JoinRequestStatusApproved, ApprovedNodeID: &nodeID, ApprovalPayload: payload, ApprovalSignature: signatureRaw, }, nil } func (f *fakeRepository) RejectJoinRequest(context.Context, RejectJoinRequestInput) (NodeJoinRequest, error) { return NodeJoinRequest{}, nil } func (f *fakeRepository) AssignNodeRole(_ context.Context, input AssignNodeRoleInput) (NodeRoleAssignment, error) { return NodeRoleAssignment{ClusterID: input.ClusterID, NodeID: input.NodeID, Role: input.Role}, nil } func (f *fakeRepository) ListNodeRoleAssignments(context.Context, string, string) ([]NodeRoleAssignment, error) { return nil, nil } func (f *fakeRepository) AttachExistingNodeToCluster(_ context.Context, input AttachExistingNodeInput) (ClusterNode, error) { f.lastAttachInput = input return ClusterNode{ ID: input.NodeID, NodeKey: "node-key-1", Name: "Node One", RegistrationStatus: NodeRegistrationActive, MembershipStatus: "active", }, nil } func (f *fakeRepository) RecordHeartbeat(context.Context, RecordHeartbeatInput) (NodeHeartbeat, error) { return NodeHeartbeat{}, nil } func (f *fakeRepository) ListNodeHeartbeats(_ context.Context, _ string, nodeID string, _ int) ([]NodeHeartbeat, error) { return f.heartbeats[nodeID], nil } func (f *fakeRepository) RevokeNodeIdentity(context.Context, RevokeNodeIdentityInput) error { return nil } func (f *fakeRepository) DisableClusterMembership(context.Context, DisableMembershipInput) error { return nil } func (f *fakeRepository) UpsertFabricTestingFlag(_ context.Context, input UpsertFabricTestingFlagInput) (FabricTestingFlag, error) { return FabricTestingFlag{ ScopeType: input.ScopeType, ScopeID: input.ScopeID, ClusterID: input.ClusterID, Enabled: input.Enabled, TelemetryEnabled: input.TelemetryEnabled, SyntheticLinksEnabled: input.SyntheticLinksEnabled, HistoryRetentionHours: input.HistoryRetentionHours, Metadata: input.Metadata, }, nil } func (f *fakeRepository) ListFabricTestingFlags(context.Context) ([]FabricTestingFlag, error) { return nil, nil } func (f *fakeRepository) GetEffectiveNodeTestingFlags(context.Context, string, string) (EffectiveNodeTestingFlags, error) { return f.testingFlags, nil } func (f *fakeRepository) RecordNodeTelemetry(_ context.Context, input RecordNodeTelemetryInput) (NodeTelemetryObservation, error) { return NodeTelemetryObservation{ ClusterID: input.ClusterID, NodeID: input.NodeID, Payload: input.Payload, }, nil } func (f *fakeRepository) ListNodeTelemetry(context.Context, string, string, int) ([]NodeTelemetryObservation, error) { return nil, nil } func (f *fakeRepository) SetDesiredWorkload(_ context.Context, input SetDesiredWorkloadInput) (NodeWorkloadDesiredState, error) { return NodeWorkloadDesiredState{ ClusterID: input.ClusterID, NodeID: input.NodeID, ServiceType: input.ServiceType, DesiredState: input.DesiredState, RuntimeMode: input.RuntimeMode, Config: input.Config, Environment: input.Environment, }, nil } func (f *fakeRepository) ListDesiredWorkloads(context.Context, string, string) ([]NodeWorkloadDesiredState, error) { return nil, nil } func (f *fakeRepository) ReportWorkloadStatus(_ context.Context, input ReportWorkloadStatusInput) (NodeWorkloadStatus, error) { return NodeWorkloadStatus{ ClusterID: input.ClusterID, NodeID: input.NodeID, ServiceType: input.ServiceType, ReportedState: input.ReportedState, RuntimeMode: input.RuntimeMode, StatusPayload: input.StatusPayload, }, nil } func (f *fakeRepository) ListLatestWorkloadStatuses(context.Context, string, string) ([]NodeWorkloadStatus, error) { return nil, nil } func (f *fakeRepository) ReportMeshLink(_ context.Context, input ReportMeshLinkInput) (MeshLinkObservation, error) { return MeshLinkObservation{ ClusterID: input.ClusterID, SourceNodeID: input.SourceNodeID, TargetNodeID: input.TargetNodeID, LinkStatus: input.LinkStatus, Metadata: input.Metadata, }, nil } func (f *fakeRepository) ListMeshLinks(context.Context, string) ([]MeshLinkObservation, error) { return f.meshLinks, nil } func (f *fakeRepository) CreateRouteIntent(_ context.Context, input CreateRouteIntentInput) (MeshRouteIntent, error) { return MeshRouteIntent{ ClusterID: input.ClusterID, SourceSelector: input.SourceSelector, DestinationSelector: input.DestinationSelector, ServiceClass: input.ServiceClass, Priority: input.Priority, Policy: input.Policy, }, nil } func (f *fakeRepository) ListRouteIntents(context.Context, string) ([]MeshRouteIntent, error) { return f.routeIntents, nil } func (f *fakeRepository) ListQoSPolicies(context.Context, string) ([]MeshQoSPolicy, error) { return nil, nil } func (f *fakeRepository) ListFabricEntryPoints(context.Context, string) ([]FabricEntryPoint, error) { return nil, nil } func (f *fakeRepository) CreateFabricEntryPoint(_ context.Context, input CreateFabricEntryPointInput) (FabricEntryPoint, error) { f.lastEntryPointInput = input return FabricEntryPoint{ ID: "entry-1", ClusterID: input.ClusterID, Name: input.Name, Status: input.Status, EndpointType: input.EndpointType, PublicEndpoint: input.PublicEndpoint, Policy: input.Policy, Metadata: input.Metadata, }, nil } func (f *fakeRepository) SetFabricEntryPointNode(_ context.Context, input SetFabricEntryPointNodeInput) (FabricEntryPointNode, error) { return FabricEntryPointNode{ EntryPointID: input.EntryPointID, ClusterID: input.ClusterID, NodeID: input.NodeID, Status: input.Status, Priority: input.Priority, Metadata: input.Metadata, }, nil } func (f *fakeRepository) ListFabricEntryPointNodes(context.Context, string, string) ([]FabricEntryPointNode, error) { return []FabricEntryPointNode{}, nil } func (f *fakeRepository) ListFabricEgressPools(context.Context, string) ([]FabricEgressPool, error) { return nil, nil } func (f *fakeRepository) CreateFabricEgressPool(_ context.Context, input CreateFabricEgressPoolInput) (FabricEgressPool, error) { f.lastEgressPoolInput = input return FabricEgressPool{ ID: "egress-1", ClusterID: input.ClusterID, Name: input.Name, Status: input.Status, Description: input.Description, RouteScope: input.RouteScope, Policy: input.Policy, Metadata: input.Metadata, }, nil } func (f *fakeRepository) SetFabricEgressPoolNode(_ context.Context, input SetFabricEgressPoolNodeInput) (FabricEgressPoolNode, error) { return FabricEgressPoolNode{ EgressPoolID: input.EgressPoolID, ClusterID: input.ClusterID, NodeID: input.NodeID, Status: input.Status, Priority: input.Priority, Metadata: input.Metadata, }, nil } func (f *fakeRepository) ListFabricEgressPoolNodes(context.Context, string, string) ([]FabricEgressPoolNode, error) { return []FabricEgressPoolNode{}, nil } func (f *fakeRepository) GetClusterAuthorityState(context.Context, string) (ClusterAuthorityState, error) { if f.authorityState.ClusterID == "" { return ClusterAuthorityState{ClusterID: "cluster-1", AuthorityState: "authoritative", MutationMode: "normal"}, nil } return f.authorityState, nil } func (f *fakeRepository) UpdateClusterAuthorityState(_ context.Context, input UpdateClusterAuthorityInput) (ClusterAuthorityState, error) { return ClusterAuthorityState{ ClusterID: input.ClusterID, AuthorityState: input.AuthorityState, MutationMode: input.MutationMode, Notes: input.Notes, }, nil } func (f *fakeRepository) ListClusterAdminSummaries(context.Context) ([]ClusterAdminSummary, error) { return nil, nil } func (f *fakeRepository) CreateVPNConnection(_ context.Context, input CreateVPNConnectionInput) (VPNConnection, error) { f.lastVPNConnectionInput = input return VPNConnection{ ID: "vpn-1", ClusterID: input.ClusterID, OrganizationID: input.OrganizationID, Name: input.Name, TargetEndpoint: input.TargetEndpoint, ProtocolFamily: input.ProtocolFamily, CredentialRef: input.CredentialRef, Mode: input.Mode, DesiredState: input.DesiredState, AllowedNodePolicy: input.AllowedNodePolicy, RoutingUsage: input.RoutingUsage, RoutePolicy: input.RoutePolicy, QoSPolicy: input.QoSPolicy, PlacementPolicy: input.PlacementPolicy, Status: VPNConnectionStatusDisabled, Metadata: input.Metadata, }, nil } func (f *fakeRepository) ListVPNConnections(context.Context, string) ([]VPNConnection, error) { return nil, nil } func (f *fakeRepository) GetVPNConnection(context.Context, string, string) (VPNConnection, error) { if f.vpnConnection.ID != "" { return f.vpnConnection, nil } return VPNConnection{ ID: "vpn-1", ClusterID: "cluster-1", Mode: VPNConnectionModeSingleActive, DesiredState: VPNConnectionDesiredEnabled, }, nil } func (f *fakeRepository) UpdateVPNConnectionDesiredState(_ context.Context, input UpdateVPNConnectionDesiredStateInput) (VPNConnection, error) { return VPNConnection{ID: input.VPNConnectionID, ClusterID: input.ClusterID, DesiredState: input.DesiredState}, nil } func (f *fakeRepository) UpsertVPNConnectionRoutePolicy(_ context.Context, input UpsertVPNConnectionRoutePolicyInput) (VPNConnectionRoutePolicy, error) { return VPNConnectionRoutePolicy{ ID: "route-policy-1", VPNConnectionID: input.VPNConnectionID, ClusterID: input.ClusterID, RouteType: input.RouteType, Destination: input.Destination, Action: input.Action, ServiceType: input.ServiceType, Priority: input.Priority, Policy: input.Policy, Status: input.Status, }, nil } func (f *fakeRepository) ListVPNConnectionRoutePolicies(context.Context, string, string) ([]VPNConnectionRoutePolicy, error) { return nil, nil } func (f *fakeRepository) SetVPNConnectionAllowedNodes(_ context.Context, input SetVPNConnectionAllowedNodesInput) ([]VPNConnectionAllowedNode, error) { f.lastAllowedNodesInput = input items := make([]VPNConnectionAllowedNode, 0, len(input.NodeIDs)) for _, nodeID := range input.NodeIDs { items = append(items, VPNConnectionAllowedNode{ VPNConnectionID: input.VPNConnectionID, ClusterID: input.ClusterID, NodeID: nodeID, RolePreference: input.RolePreference, Status: "active", Metadata: input.Metadata, }) } return items, nil } func (f *fakeRepository) ListVPNConnectionAllowedNodes(context.Context, string, string) ([]VPNConnectionAllowedNode, error) { return nil, nil } func (f *fakeRepository) AcquireVPNConnectionLease(_ context.Context, input AcquireVPNConnectionLeaseInput, expiresAt time.Time, fencingToken string) (VPNConnectionLease, error) { if f.acquireVPNLeaseErr != nil { return VPNConnectionLease{}, f.acquireVPNLeaseErr } return VPNConnectionLease{ ID: "lease-1", VPNConnectionID: input.VPNConnectionID, ClusterID: input.ClusterID, OwnerNodeID: input.OwnerNodeID, LeaseGeneration: 1, FencingToken: fencingToken, Status: VPNLeaseStatusActive, ExpiresAt: expiresAt, Metadata: input.Metadata, }, nil } func (f *fakeRepository) RenewVPNConnectionLease(_ context.Context, input RenewVPNConnectionLeaseInput, expiresAt time.Time) (VPNConnectionLease, error) { if f.renewVPNLeaseErr != nil { return VPNConnectionLease{}, f.renewVPNLeaseErr } return VPNConnectionLease{ID: input.LeaseID, VPNConnectionID: input.VPNConnectionID, ClusterID: input.ClusterID, OwnerNodeID: input.OwnerNodeID, FencingToken: input.FencingToken, Status: VPNLeaseStatusActive, ExpiresAt: expiresAt}, nil } func (f *fakeRepository) ReleaseVPNConnectionLease(_ context.Context, input ReleaseVPNConnectionLeaseInput) (VPNConnectionLease, error) { return VPNConnectionLease{ID: input.LeaseID, VPNConnectionID: input.VPNConnectionID, ClusterID: input.ClusterID, OwnerNodeID: input.OwnerNodeID, FencingToken: input.FencingToken, Status: VPNLeaseStatusReleased}, nil } func (f *fakeRepository) FenceVPNConnectionLease(_ context.Context, input FenceVPNConnectionLeaseInput) (VPNConnectionLease, error) { return VPNConnectionLease{ID: input.LeaseID, VPNConnectionID: input.VPNConnectionID, ClusterID: input.ClusterID, Status: VPNLeaseStatusFenced}, nil } func (f *fakeRepository) GetActiveVPNConnectionLease(context.Context, string, string) (VPNConnectionLease, error) { return VPNConnectionLease{ID: "lease-1", Status: VPNLeaseStatusActive}, nil } func (f *fakeRepository) CheckVPNLeaseOwnerEligibility(context.Context, string, string, string) (VPNLeaseOwnerEligibility, error) { if f.ownerEligibilityErr != nil { return VPNLeaseOwnerEligibility{}, f.ownerEligibilityErr } if f.ownerEligibility.VPNConnectionID != "" { return f.ownerEligibility, nil } return VPNLeaseOwnerEligibility{ VPNConnectionID: "vpn-1", ClusterID: "cluster-1", OrganizationID: "org-1", OwnerNodeID: "node-1", MembershipStatus: "active", NodeRegistrationStatus: NodeRegistrationActive, AllowedByPolicy: true, HasAuthorizedRole: true, }, nil } func (f *fakeRepository) ExpireStaleVPNConnectionLeases(context.Context, string, time.Time) ([]VPNConnectionLease, error) { return f.expiredVPNLeases, nil } func (f *fakeRepository) ListNodeVPNAssignments(context.Context, string, string) ([]NodeVPNAssignment, error) { return f.nodeVPNAssignments, nil } func (f *fakeRepository) ReportNodeVPNAssignmentStatus(_ context.Context, input ReportNodeVPNAssignmentStatusInput) (NodeVPNAssignmentStatus, error) { return NodeVPNAssignmentStatus{ ID: "status-1", VPNConnectionID: input.VPNConnectionID, ClusterID: input.ClusterID, NodeID: input.NodeID, ObservedStatus: input.ObservedStatus, StatusPayload: input.StatusPayload, ObservedAt: input.ObservedAt, }, nil } func (f *fakeRepository) RecordAudit(_ context.Context, event ClusterAuditEvent) error { f.auditEvents = append(f.auditEvents, event) return nil } func (f *fakeRepository) ListAuditEvents(context.Context, string, int) ([]ClusterAuditEvent, error) { return nil, nil }