Replace whole-repo grep with four production-only gates so Goose and tests stop looking like writer debt, and so new SQL, path, or event crossings fail immediately. Co-authored-by: Cursor <cursoragent@cursor.com>
167 lines
4.5 KiB
Go
167 lines
4.5 KiB
Go
package archtest
|
|
|
|
import (
|
|
"path/filepath"
|
|
"runtime"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func miniRoot(t *testing.T) string {
|
|
t.Helper()
|
|
_, file, _, ok := runtime.Caller(0)
|
|
if !ok {
|
|
t.Fatal("caller")
|
|
}
|
|
return filepath.Join(filepath.Dir(file), "testdata", "mini")
|
|
}
|
|
|
|
func fixtureBoundaries() *Boundaries {
|
|
return &Boundaries{
|
|
Imports: map[string][]string{
|
|
"server": {},
|
|
"docgov": {},
|
|
},
|
|
TableOwners: map[string][]string{
|
|
"document_records": {"docgov"},
|
|
},
|
|
PathOwners: map[string][]string{
|
|
"output.md": {"squad", "workspace"},
|
|
},
|
|
EventProducers: map[string][]string{
|
|
"outbox.notify": {"docrevision"},
|
|
"document.agent_version_committed": {"docrevision"},
|
|
},
|
|
EventConsumers: map[string][]string{
|
|
"outbox.notify": {"notification"},
|
|
},
|
|
BaselineCounts: map[string]int{},
|
|
}
|
|
}
|
|
|
|
func scanMini(t *testing.T) []Finding {
|
|
t.Helper()
|
|
findings, err := Scan(ScanOptions{Root: miniRoot(t)}, fixtureBoundaries())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return findings
|
|
}
|
|
|
|
func TestGooseAndTestsAreNotProductionWriters(t *testing.T) {
|
|
for _, f := range scanMini(t) {
|
|
if f.Kind == KindSQLWrite && f.Package == "docgov" && f.File == "internal/docgov/owner_write_test.go" {
|
|
t.Fatalf("test file must not be a production writer: %+v", f)
|
|
}
|
|
if f.Kind == KindSQLWrite && filepath.Ext(f.File) == ".sql" {
|
|
t.Fatalf("goose/sql must not be a production writer: %+v", f)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNonOwnerProductionWriteIsBlockedAndNamed(t *testing.T) {
|
|
var hit *Finding
|
|
findings := scanMini(t)
|
|
for i, f := range findings {
|
|
if f.Kind == KindSQLWrite && f.Symbol == "document_records" && f.Package == "server" {
|
|
hit = &findings[i]
|
|
if f.File != "internal/server/rogue_write.go" {
|
|
t.Fatalf("expected rogue_write.go, got %s", f.File)
|
|
}
|
|
}
|
|
}
|
|
if hit == nil {
|
|
t.Fatal("expected UPDATE document_records in internal/server/rogue_write.go to be blocked")
|
|
}
|
|
}
|
|
|
|
func TestOwnerProductionWriteIsAllowed(t *testing.T) {
|
|
for _, f := range scanMini(t) {
|
|
if f.Kind == KindSQLWrite && f.Package == "docgov" && f.File == "internal/docgov/owner_write.go" {
|
|
t.Fatalf("owner write should be allowed: %+v", f)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestPathJoinConcatAndConstAreDetected(t *testing.T) {
|
|
want := map[string]bool{
|
|
"internal/server/path_join.go": false,
|
|
"internal/server/path_concat.go": false,
|
|
"internal/server/path_const.go": false,
|
|
}
|
|
for _, f := range scanMini(t) {
|
|
if f.Kind != KindPath || f.Symbol != "output.md" {
|
|
continue
|
|
}
|
|
if _, ok := want[f.File]; ok {
|
|
want[f.File] = true
|
|
}
|
|
}
|
|
for file, seen := range want {
|
|
if !seen {
|
|
t.Errorf("path construction not detected in %s", file)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestUnauthorizedEventProducerIsBlocked(t *testing.T) {
|
|
found := false
|
|
for _, f := range scanMini(t) {
|
|
if f.Kind == KindEvent && f.Package == "server" {
|
|
found = true
|
|
}
|
|
}
|
|
if !found {
|
|
t.Fatal("expected unauthorized OnOutbox producer in server to be blocked")
|
|
}
|
|
}
|
|
|
|
func TestExceptionRequiresExpiryAndOwner(t *testing.T) {
|
|
b := fixtureBoundaries()
|
|
b.Exceptions = []Exception{{
|
|
Kind: KindSQLWrite, Package: "server", File: "internal/server/rogue_write.go",
|
|
Symbol: "document_records", Reason: "no owner or expiry",
|
|
}}
|
|
ev := Evaluate(scanMini(t), b, time.Date(2026, 9, 14, 12, 0, 0, 0, time.UTC))
|
|
if len(ev.BadExceptions) == 0 {
|
|
t.Fatal("expected missing owner/expires to block")
|
|
}
|
|
if len(ev.Unmatched) == 0 {
|
|
t.Fatal("invalid exception must not hide the finding")
|
|
}
|
|
}
|
|
|
|
func TestExpiredExceptionBlocksImmediately(t *testing.T) {
|
|
b := fixtureBoundaries()
|
|
b.Exceptions = []Exception{{
|
|
Kind: KindSQLWrite, Package: "server", File: "internal/server/rogue_write.go",
|
|
Symbol: "document_records", Owner: "server", Reason: "stale",
|
|
Milestone: "U3", Expires: "2026-09-01",
|
|
}}
|
|
ev := Evaluate(scanMini(t), b, time.Date(2026, 9, 14, 12, 0, 0, 0, time.UTC))
|
|
if len(ev.BadExceptions) == 0 {
|
|
t.Fatal("expected expired exception to block")
|
|
}
|
|
found := false
|
|
for _, f := range ev.Unmatched {
|
|
if f.File == "internal/server/rogue_write.go" {
|
|
found = true
|
|
}
|
|
}
|
|
if !found {
|
|
t.Fatal("expired exception must surface the original finding")
|
|
}
|
|
}
|
|
|
|
func TestClassifyGooseSQL(t *testing.T) {
|
|
root := miniRoot(t)
|
|
got := classifyFile(root, filepath.Join(root, "deploy", "postgres", "goose", "00001_fixture.sql"))
|
|
if got != classGoose {
|
|
t.Fatalf("classify goose: got %v want %v", got, classGoose)
|
|
}
|
|
got = classifyFile(root, filepath.Join(root, "internal", "docgov", "owner_write_test.go"))
|
|
if got != classTestOrFixture {
|
|
t.Fatalf("classify test: got %v want %v", got, classTestOrFixture)
|
|
}
|
|
}
|