chore: directory migration - gateway→server, web→client/electron

This commit is contained in:
2026-09-08 19:16:35 +08:00
parent fd9f99a3f9
commit f9d757b5e5
243 changed files with 5095 additions and 228 deletions

View File

@ -0,0 +1,160 @@
package models
// 权限档位的判据测试。
//
// 为什么值得单独一组测试:`ModeAtMost` 被两处调用(子会话继承 / 平台向更严取整),
// 两处若各写一遍必有一处写成「取更宽松」。而 `NormalizePermissionMode` 的保守
// 取向(非法值 → workspace 而非 full是安全属性拼错一个档位名不该换来更大权限。
import "testing"
func TestValidPermissionMode(t *testing.T) {
for _, m := range []string{ModePlan, ModeWorkspace, ModeFull} {
if !ValidPermissionMode(m) {
t.Fatalf("%q 应当合法", m)
}
}
for _, m := range []string{"", "PLAN", "readonly", "danger-full-access", "workspace-write"} {
if ValidPermissionMode(m) {
t.Fatalf("%q 不该合法", m)
}
}
}
// 非法值必须落到 workspace不能落到 full。
// 拼错一个档位名换来全权是最不该有的失败方向。
func TestNormalizePermissionMode_FailsClosed(t *testing.T) {
for _, in := range []string{"", "full-access", "plan ", "FULL", "无", "workspace-write"} {
got := NormalizePermissionMode(in)
if got != DefaultPermissionMode {
t.Fatalf("NormalizePermissionMode(%q) = %q应当是默认档 %q", in, got, DefaultPermissionMode)
}
}
if DefaultPermissionMode == ModeFull {
t.Fatal("默认档不能是 full —— 「我忘了收紧」与「我确实需要全权」会无法区分")
}
}
func TestNormalizePermissionMode_KeepsValid(t *testing.T) {
for _, m := range []string{ModePlan, ModeWorkspace, ModeFull} {
if got := NormalizePermissionMode(m); got != m {
t.Fatalf("合法档位应原样返回:%q → %q", m, got)
}
}
}
// ModeAtMost 取更严的一档 —— 子会话继承与平台取整共用这一个判据。
func TestModeAtMost(t *testing.T) {
cases := []struct{ a, b, want string }{
{ModePlan, ModeFull, ModePlan},
{ModeFull, ModePlan, ModePlan},
{ModeWorkspace, ModeFull, ModeWorkspace},
{ModeFull, ModeWorkspace, ModeWorkspace},
{ModePlan, ModeWorkspace, ModePlan},
{ModeWorkspace, ModePlan, ModePlan},
{ModeFull, ModeFull, ModeFull},
{ModePlan, ModePlan, ModePlan},
{ModeWorkspace, ModeWorkspace, ModeWorkspace},
}
for _, c := range cases {
if got := ModeAtMost(c.a, c.b); got != c.want {
t.Fatalf("ModeAtMost(%q,%q) = %qwant %q", c.a, c.b, got, c.want)
}
}
}
// 未知值归到默认档workspace而不是最严的 plan。
//
// 为什么不是 plan脏数据的含义应该在整个包里只有一个 ——
// NormalizePermissionMode / ModeNeedsHuman 都把它当默认档ModeAtMost
// 若单独把它当 plan同一个脏值就有两种语义且 ModeAtMost 不可交换
// (单元测试当场抓到过)。一致比“局部更严”重要:默认档本身已经是安全的。
func TestModeAtMost_UnknownFallsToDefault(t *testing.T) {
if got := ModeAtMost("garbage", ModeFull); got != DefaultPermissionMode {
t.Fatalf("未知档位应归默认档,得到 %q", got)
}
if got := ModeAtMost(ModeFull, "garbage"); got != DefaultPermissionMode {
t.Fatalf("未知档位应归默认档,得到 %q", got)
}
// 脏值不得抬升权限:与 plan 相遇时仍然是 plan 胜出。
if got := ModeAtMost("garbage", ModePlan); got != ModePlan {
t.Fatalf("脏值不该把 plan 抬成更宽松的档,得到 %q", got)
}
}
// ModeAtMost 必须可交换:两处调用点传参顺序不同,结果不能不同。
func TestModeAtMost_Commutative(t *testing.T) {
all := append([]string{"garbage", ""}, PermissionModes...)
for _, a := range all {
for _, b := range all {
if ModeAtMost(a, b) != ModeAtMost(b, a) {
t.Fatalf("ModeAtMost 不可交换:(%q,%q)=%q 但 (%q,%q)=%q",
a, b, ModeAtMost(a, b), b, a, ModeAtMost(b, a))
}
}
}
}
// 只有 workspace 档需要人 —— 这一条直接决定「找不到人类时怎么办」。
//
// plan 档当场拒绝、full 档自动放行,两者都不问人,所以只有 workspace 档会
// 走到「这条链上有没有人类」这个问题,找不到就是 409。permission.go 里那段
// 「退回第一个管理员」的兜底正因此必须删掉:它让 409 分支永远不可达。
func TestModeNeedsHuman(t *testing.T) {
if ModeNeedsHuman(ModePlan) {
t.Fatal("plan 档不该问人:语义就是这轮不动手,直接拒绝即可")
}
if !ModeNeedsHuman(ModeWorkspace) {
t.Fatal("workspace 档必须问人:越界时需要人点头")
}
if ModeNeedsHuman(ModeFull) {
t.Fatal("full 档不该问人:已声明全权,再问一遍只是噪音")
}
}
func TestModeNeedsHuman_NormalizesInput(t *testing.T) {
// 脏数据走默认档workspace→ 需要人。宁可多问一次,不可静默放行。
if !ModeNeedsHuman("garbage") {
t.Fatal("认不出的档位应当按默认档处理,即需要人")
}
if !ModeNeedsHuman("") {
t.Fatal("空档位应当按默认档处理,即需要人")
}
}
// ─── 强制力 ───
func TestValidEnforcement(t *testing.T) {
if !ValidEnforcement(EnforcementNative) || !ValidEnforcement(EnforcementAdvisory) {
t.Fatal("native / advisory 都应合法")
}
for _, e := range []string{"", "NATIVE", "none", "enforced"} {
if ValidEnforcement(e) {
t.Fatalf("%q 不该合法", e)
}
}
}
// 保守方向是 advisory没自报过的插件不能替它宣称档位在那里是被强制的。
func TestNormalizeEnforcement_FailsClosed(t *testing.T) {
for _, in := range []string{"", "garbage", "NATIVE", "native "} {
if got := NormalizeEnforcement(in); got != EnforcementAdvisory {
t.Fatalf("NormalizeEnforcement(%q) = %q应当是 advisory", in, got)
}
}
if got := NormalizeEnforcement(EnforcementNative); got != EnforcementNative {
t.Fatalf("显式 native 应原样保留,得到 %q", got)
}
}
// PermissionModes 的顺序是 ModeAtMost 的依据,不能被随手改动。
func TestPermissionModesOrder(t *testing.T) {
if len(PermissionModes) != 3 {
t.Fatalf("档位应当是三个,得到 %d 个", len(PermissionModes))
}
if PermissionModes[0] != ModePlan ||
PermissionModes[1] != ModeWorkspace ||
PermissionModes[2] != ModeFull {
t.Fatalf("PermissionModes 必须按宽松程度递增排列plan < workspace < full得到 %v", PermissionModes)
}
}