package licensekit import ( "crypto/ed25519" "crypto/rand" "testing" "time" ) func testKeys(t *testing.T) (ed25519.PublicKey, ed25519.PrivateKey) { t.Helper() pub, priv, err := ed25519.GenerateKey(rand.Reader) if err != nil { t.Fatal(err) } return pub, priv } func TestLicenseRoundTripAndContext(t *testing.T) { pub, priv := testKeys(t) now := time.Now().UTC() claims := Claims{Version: 1, LicenseID: "lic_test", Issuer: "vendor", Customer: "customer", Product: "product-a", Edition: "pro", Features: []string{"b", "a"}, Domains: []string{"*.example.org"}, IssuedAt: now.Unix(), ExpiresAt: now.Add(time.Hour).Unix(), Verification: VerificationPolicy{Mode: ModeOffline}} token, err := SignLicense(priv, "issuer-1", claims) if err != nil { t.Fatal(err) } store := NewTrustStore() store.LicenseKeys["issuer-1"] = EncodeKey(pub) verified, err := VerifyLicense(store, token, now) if err != nil { t.Fatal(err) } if verified.Claims.Features[0] != "a" { t.Fatalf("features not sorted: %#v", verified.Claims.Features) } if err := ValidateLicenseContext(verified.Claims, "product-a", "https://app.example.org", ""); err != nil { t.Fatal(err) } if err := ValidateLicenseContext(verified.Claims, "product-b", "https://app.example.org", ""); err == nil { t.Fatal("expected product mismatch") } } func TestGlobalWildcardAllowsAllHosts(t *testing.T) { if err := ValidateDomain([]string{"*"}, "http://localhost:8080"); err != nil { t.Fatal(err) } if err := ValidateDomain([]string{"*"}, "https://anything.invalid"); err != nil { t.Fatal(err) } } func TestUnknownKeyIsRejected(t *testing.T) { _, priv := testKeys(t) now := time.Now().UTC() claims := Claims{Version: 1, LicenseID: "lic_test", Issuer: "vendor", Customer: "customer", Product: "product", Edition: "pro", IssuedAt: now.Unix(), ExpiresAt: now.Add(time.Hour).Unix(), Verification: VerificationPolicy{Mode: ModeOffline}} token, err := SignLicense(priv, "self-chosen", claims) if err != nil { t.Fatal(err) } if _, err := VerifyLicense(NewTrustStore(), token, now); err == nil { t.Fatal("untrusted user key must not be accepted") } } func TestLeaseRoundTrip(t *testing.T) { pub, priv := testKeys(t) now := time.Now().UTC() claims := LeaseClaims{Version: 1, LeaseID: "lease_1", LicenseID: "lic_1", Product: "product", Customer: "customer", Edition: "pro", Features: []string{"x"}, Host: "example.org", IssuedAt: now.Unix(), ExpiresAt: now.Add(time.Hour).Unix()} token, err := SignLease(priv, "lease-1", claims) if err != nil { t.Fatal(err) } store := NewTrustStore() store.LeaseKeys["lease-1"] = EncodeKey(pub) verified, err := VerifyLease(store, token, now, 0) if err != nil { t.Fatal(err) } license := Claims{LicenseID: "lic_1", Product: "product"} if err := ValidateLeaseContext(verified.Claims, license, "product", "https://example.org", ""); err != nil { t.Fatal(err) } }