carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package console
2
3import (
4 "go/ast"
5 "go/parser"
6 "go/token"
7 "os"
8 "path/filepath"
9 "sort"
10 "strings"
11 "testing"
12)
13
14// TestClaimSQLSeamCallers keeps the gate's trusted seams where they are:
15//
16// - the claim restore and materialization files never touch a Store's db,
17// pool or boot field, and never call bootDB: every write goes through
18// WithAppMutation and its canonical grants;
19// - the raw handles (Store.rawPool, Store.rawBoot) are named only in
20// store.go and store_gate.go: every other file reaches SQL through s.db,
21// which inside WithAppMutation is the bound view;
22// - withClaimSQL (the permit engine) is called only by WithAppMutation;
23// - bootDB is called only by the boot seam;
24// - sqlGrant values are built only in claim_sql_grants.go;
25// - ControlWriter.AbandonRestore and RecoverRestore are called only by the
26// restore issuer and its sweep (claim_restore.go).
27//
28// A new caller fails here before it can ship.
29func TestClaimSQLSeamCallers(t *testing.T) {
30 noRawSQL := map[string]bool{"claim_restore.go": true, "claim_materialize.go": true, "claim_sql_grants.go": true}
31 allowed := map[string]map[string]bool{
32 "rawPool": {"store.go": true, "store_gate.go": true},
33 "rawBoot": {"store.go": true, "store_gate.go": true, "claim_sql_receipts.go": true},
34 "withClaimSQL": {"claim_sql_grants.go": true},
35 "withPreparedClaimSQL": {"claim_sql_grants.go": true, "store_gate.go": true},
36 "bootDB": {"store_gate.go": true, "claim_app_identity.go": true},
37 "AbandonRestore": {"claim_restore.go": true},
38 "RecoverRestore": {"claim_restore.go": true},
39 "sqlGrant-composite": {"claim_sql_grants.go": true},
40 }
41 files, err := filepath.Glob("*.go")
42 if err != nil {
43 t.Fatal(err)
44 }
45 fset := token.NewFileSet()
46 var bad []string
47 for _, name := range files {
48 if strings.HasSuffix(name, "_test.go") {
49 continue
50 }
51 src, err := os.ReadFile(name)
52 if err != nil {
53 t.Fatal(err)
54 }
55 f, err := parser.ParseFile(fset, name, src, 0)
56 if err != nil {
57 t.Fatal(err)
58 }
59 ast.Inspect(f, func(n ast.Node) bool {
60 switch x := n.(type) {
61 case *ast.SelectorExpr:
62 sel := x.Sel.Name
63 if noRawSQL[name] && (sel == "db" || sel == "rawPool" || sel == "rawBoot" || sel == "bootDB") {
64 bad = append(bad, fset.Position(x.Pos()).String()+": raw SQL handle ."+sel)
65 }
66 if ok, listed := allowed[sel]; listed && !ok[name] {
67 bad = append(bad, fset.Position(x.Pos()).String()+": "+sel+" outside its seam")
68 }
69 case *ast.CompositeLit:
70 if id, ok := x.Type.(*ast.Ident); ok && id.Name == "sqlGrant" && !allowed["sqlGrant-composite"][name] {
71 bad = append(bad, fset.Position(x.Pos()).String()+": sqlGrant built outside claim_sql_grants.go")
72 }
73 }
74 return true
75 })
76 }
77 sort.Strings(bad)
78 for _, b := range bad {
79 t.Error(b)
80 }
81}
82