package api import ( "context" "crypto/ed25519" "encoding/base64" "net/http/httptest" "net/url" "testing" "github.com/rcourtman/pulse-go-rewrite/internal/config" "github.com/rcourtman/pulse-go-rewrite/internal/relay" pkglicensing "github.com/rcourtman/pulse-go-rewrite/pkg/licensing" ) func TestLoadRelayConfigForRuntime_HostedEntitlementAutoBootstrapsRelay(t *testing.T) { router, entitlementJWT, instanceHost := newHostedRelayRuntimeTestRouter(t) cfg, err := router.loadRelayConfigForRuntime(context.Background()) if err != nil { t.Fatalf("loadRelayConfigForRuntime() error = %v", err) } if cfg == nil { t.Fatal("loadRelayConfigForRuntime() returned nil config") } if !cfg.Enabled { t.Fatal("expected hosted relay bootstrap to enable relay") } if cfg.ServerURL != relay.DefaultServerURL { t.Fatalf("server_url = %q, want %q", cfg.ServerURL, relay.DefaultServerURL) } if cfg.InstanceSecret != instanceHost { t.Fatalf("instance_secret = %q, want %q", cfg.InstanceSecret, instanceHost) } if cfg.IdentityPrivateKey == "" || cfg.IdentityPublicKey == "" || cfg.IdentityFingerprint == "" { t.Fatalf("expected hosted relay bootstrap to generate full identity, got %+v", cfg) } persisted, err := router.persistence.LoadRelayConfig() if err != nil { t.Fatalf("LoadRelayConfig() error = %v", err) } if persisted == nil || !persisted.Enabled { t.Fatal("expected persisted hosted relay config to be enabled") } if persisted.InstanceSecret != instanceHost { t.Fatalf("persisted instance_secret = %q, want %q", persisted.InstanceSecret, instanceHost) } gotToken := router.relayRegistrationToken(context.Background()) if gotToken != entitlementJWT { t.Fatalf("relayRegistrationToken() = %q, want hosted entitlement JWT", gotToken) } } func TestLoadRelayConfigForRuntime_EnvEnabledRelayGeneratesPersistedIdentity(t *testing.T) { t.Setenv(relay.EnvRelayEnabled, "true") t.Setenv(relay.EnvRelayServerURL, "wss://relay.internal.example/ws/instance") persistence := config.NewConfigPersistence(t.TempDir()) router := &Router{persistence: persistence} cfg, err := router.loadRelayConfigForRuntime(context.Background()) if err != nil { t.Fatalf("loadRelayConfigForRuntime() error = %v", err) } if cfg == nil { t.Fatal("loadRelayConfigForRuntime() returned nil config") } if !cfg.Enabled { t.Fatal("expected env-enabled relay config to remain enabled") } if cfg.ServerURL != "wss://relay.internal.example/ws/instance" { t.Fatalf("server_url = %q, want env override", cfg.ServerURL) } if cfg.IdentityPrivateKey == "" || cfg.IdentityPublicKey == "" || cfg.IdentityFingerprint == "" { t.Fatal("expected env-enabled relay config to generate full identity") } t.Setenv(relay.EnvRelayEnabled, "") t.Setenv(relay.EnvRelayServerURL, "") persisted, err := persistence.LoadRelayConfig() if err != nil { t.Fatalf("LoadRelayConfig() error = %v", err) } if persisted == nil || !persisted.Enabled { t.Fatal("expected generated relay identity config to be persisted enabled") } if persisted.ServerURL != cfg.ServerURL { t.Fatalf("persisted server_url = %q, want %q", persisted.ServerURL, cfg.ServerURL) } if persisted.IdentityPrivateKey == "" || persisted.IdentityPublicKey == "" || persisted.IdentityFingerprint == "" { t.Fatal("expected persisted relay config to include full identity") } } func TestLoadRelayConfigForRuntime_EnabledPartialIdentityRegeneratesFullIdentity(t *testing.T) { persistence := config.NewConfigPersistence(t.TempDir()) partial := relay.Config{ Enabled: true, ServerURL: "wss://relay.example.test/ws/instance", InstanceSecret: "relay-instance-secret", IdentityPrivateKey: "private-key-without-public-material", } if err := persistence.SaveRelayConfig(partial); err != nil { t.Fatalf("SaveRelayConfig() error = %v", err) } router := &Router{persistence: persistence} cfg, err := router.loadRelayConfigForRuntime(context.Background()) if err != nil { t.Fatalf("loadRelayConfigForRuntime() error = %v", err) } if cfg == nil { t.Fatal("loadRelayConfigForRuntime() returned nil config") } if !cfg.Enabled { t.Fatal("expected enabled relay config to remain enabled") } if cfg.IdentityPrivateKey == partial.IdentityPrivateKey { t.Fatal("expected partial relay identity to be replaced with a complete keypair") } if cfg.IdentityPrivateKey == "" || cfg.IdentityPublicKey == "" || cfg.IdentityFingerprint == "" { t.Fatal("expected enabled relay config to include full identity") } persisted, err := persistence.LoadRelayConfig() if err != nil { t.Fatalf("LoadRelayConfig() error = %v", err) } if persisted == nil || persisted.IdentityPrivateKey != cfg.IdentityPrivateKey { t.Fatal("expected repaired relay identity to be persisted") } if persisted.IdentityPublicKey == "" || persisted.IdentityFingerprint == "" { t.Fatal("expected persisted relay identity to be complete") } } func TestLoadRelayConfigForRuntime_DoesNotOverrideExplicitDisabledRelayConfig(t *testing.T) { router, _, instanceHost := newHostedRelayRuntimeTestRouter(t) explicit := relay.Config{ Enabled: false, ServerURL: "wss://relay.example.test/ws/instance", InstanceSecret: "user-managed-secret", IdentityPrivateKey: "user-private", IdentityPublicKey: "user-public", IdentityFingerprint: "USER:FP", } if err := router.persistence.SaveRelayConfig(explicit); err != nil { t.Fatalf("SaveRelayConfig() error = %v", err) } cfg, err := router.loadRelayConfigForRuntime(context.Background()) if err != nil { t.Fatalf("loadRelayConfigForRuntime() error = %v", err) } if cfg.Enabled { t.Fatal("expected explicit disabled relay config to remain disabled") } if cfg.InstanceSecret != explicit.InstanceSecret { t.Fatalf("instance_secret = %q, want %q", cfg.InstanceSecret, explicit.InstanceSecret) } if cfg.InstanceSecret == instanceHost { t.Fatalf("expected explicit config to avoid hosted auto-bootstrap secret %q", instanceHost) } } func TestHostedRelayRuntimeBuildsMobileOnboardingAppRelayURL(t *testing.T) { router, _, instanceHost := newHostedRelayRuntimeTestRouter(t) relayCfg, err := router.loadRelayConfigForRuntime(context.Background()) if err != nil { t.Fatalf("loadRelayConfigForRuntime() error = %v", err) } router.relayClient = fakeRelayRuntimeClient{ status: relay.ClientStatus{ Connected: true, InstanceID: instanceHost, }, } req := httptest.NewRequest("GET", "https://t-hostedrelay01.cloud.pulserelay.pro/api/onboarding/qr", nil) payload, diagnostics := router.buildOnboardingPayload(req, relayCfg, "test-mobile-proof-token") if hasOnboardingError(diagnostics) { t.Fatalf("onboarding diagnostics contain errors: %#v", diagnostics) } if payload.Relay.URL != "wss://relay.pulserelay.pro/ws/app" { t.Fatalf("mobile onboarding relay URL = %q", payload.Relay.URL) } deepLink, err := url.Parse(payload.DeepLink) if err != nil { t.Fatalf("parse deep link: %v", err) } query := deepLink.Query() if query.Get("relay_url") != payload.Relay.URL { t.Fatalf("deep-link relay_url = %q, want %q", query.Get("relay_url"), payload.Relay.URL) } if query.Get("auth_token") != "test-mobile-proof-token" { t.Fatalf("deep-link auth_token did not preserve the proof token") } } func newHostedRelayRuntimeTestRouter(t *testing.T) (*Router, string, string) { t.Helper() pub, priv, err := ed25519.GenerateKey(nil) if err != nil { t.Fatalf("generate entitlement keypair: %v", err) } t.Setenv(pkglicensing.TrialActivationPublicKeyEnvVar, base64.StdEncoding.EncodeToString(pub)) baseDir := t.TempDir() cfg := &config.Config{ DataPath: baseDir, FrontendPort: 7655, PublicURL: "https://t-HOSTEDRELAY01.cloud.pulserelay.pro", } mtp := config.NewMultiTenantPersistence(baseDir) persistence, err := mtp.GetPersistence(hostedRelayBootstrapOrgID) if err != nil { t.Fatalf("GetPersistence(default) error = %v", err) } instanceHost := "t-hostedrelay01.cloud.pulserelay.pro" entitlementJWT, err := pkglicensing.SignEntitlementLeaseToken(priv, pkglicensing.EntitlementLeaseClaims{ OrgID: hostedRelayBootstrapOrgID, InstanceHost: instanceHost, PlanVersion: "cloud", SubscriptionState: pkglicensing.SubStateActive, Capabilities: []string{pkglicensing.FeatureRelay}, }) if err != nil { t.Fatalf("SignEntitlementLeaseToken() error = %v", err) } billingStore := config.NewFileBillingStore(mtp.BaseDataDir()) if err := billingStore.SaveBillingState(hostedRelayBootstrapOrgID, &billingState{ PlanVersion: "cloud", SubscriptionState: subscriptionStateActiveValue, Capabilities: []string{pkglicensing.FeatureRelay}, EntitlementJWT: entitlementJWT, }); err != nil { t.Fatalf("SaveBillingState() error = %v", err) } router := &Router{ config: cfg, persistence: persistence, licenseHandlers: NewLicenseHandlers(mtp, true, cfg), } return router, entitlementJWT, instanceHost }