package service import ( "errors" "strings" "testing" ) // The read plane must never be talkable into serving proposal content. gitx // resolves ref names happily, so this guard is the only thing standing between // a crafted rev and unreviewed text entering an agent's context as approved. func TestValidateReadRevRefusesRefNames(t *testing.T) { sha := strings.Repeat("a1b2c3d4", 5) // 40 hex chars for _, tc := range []struct { name string rev string ok bool }{ {"approved head sentinel", ApprovedRev, true}, {"full object name", sha, true}, {"proposal branch", "proposals/42", false}, {"approved branch by name", "main", false}, {"HEAD", "HEAD", false}, {"tag", "refs/tags/v1", false}, {"abbreviated sha", sha[:12], false}, {"uppercase hex", strings.ToUpper(sha), false}, {"sha with trailing path", sha + "/x", false}, {"almost hex", strings.Repeat("g", 40), false}, } { t.Run(tc.name, func(t *testing.T) { err := ValidateReadRev(tc.rev) if tc.ok && err != nil { t.Fatalf("ValidateReadRev(%q) = %v, want nil", tc.rev, err) } if !tc.ok { if err == nil { t.Fatalf("ValidateReadRev(%q) = nil, want rejection", tc.rev) } if !errors.Is(err, ErrBadReadRev) { t.Fatalf("ValidateReadRev(%q) error = %v, want ErrBadReadRev", tc.rev, err) } } }) } }