fix(license): shared invalid/grace banners + instance copy

Surface expired/over_instance/revoked red banners with CTAs via a
shared LicenseStatusBanners used by settings and ProGate. Hide seats
in product UI; keep HMAC dual-path and never silent-clear keys.
This commit is contained in:
opsx committed 2026-11-01 03:08:37 +08:00
1 parent af0298e994
commit 62d9b81a70
10 files changed
+265 -45

No files matched your search

+28
View File
@@ -0,0 +1,28 @@
package services
import "testing"
func TestClassifyRejectReason(t *testing.T) {
cases := []struct {
msg string
want string
}{
{"device limit exceeded", "over_instance"},
{"设备席位已满", "over_instance"},
{"已超过实例上限", "over_instance"},
{"license expired", "expired"},
{"许可码已过期", "expired"},
{"revoked by admin", "revoked"},
{"许可证无效", "revoked"},
}
for _, tc := range cases {
if got := classifyRejectReason(tc.msg); got != tc.want {
t.Fatalf("classifyRejectReason(%q)=%q want %q", tc.msg, got, tc.want)
}
}
}
func TestSanitizedHidesSeatsAndKeepsInvalidReason(t *testing.T) {
// 通过 models 包测 Sanitized:此处仅确保 classify 与 payload 路径可编译。
_ = classifyRejectReason("x")
}