package caps import ( "bytes" "go/parser" "go/token" "os" "path/filepath" "strings" "testing" ) // liveChannels mirrors internal/release/laddercheck_test.go's list — the // channels production is running on RIGHT NOW. Copied rather than imported: // internal/caps must not import internal/release (and importing this test // package from there would prove the wrong direction), so four literal // strings are cheaper than restructuring either package to share them. If // laddercheck_test.go's list ever changes, this one should be re-copied by // hand — a shared constant would be one more thing this package would need // to import from outside itself. var liveChannels = []string{"canary/platform-adoption", "canary/keymail", "canary/console", "canary/rehearsal"} // TestCapabilitiesNeverConsultAChannelName is this package's half of the // design's channel-neutrality claim (spec: "Nothing in this change may // consult, constrain, or be constrained by a channel name" — the same // promise internal/release/laddercheck_test.go pins for the ladder itself). // canary/* in, canary/* out — the fleet runs on those channels and a // capability change that refused, favoured, or even NOTICED one would stop // deploys production depends on. // // Two halves, because neither alone is the whole claim: // // - structural: no identifier or literal in this package's own PRODUCTION // source (not its tests) says "channel" or "canary" outside a comment. // Parsed with go/parser rather than grepped so that a doc comment // EXPLAINING channel-neutrality (as this very comment does) can never // trip the test that states it. // - behavioural: this package's inputs — Plan, Set, Grants, Ops — carry no // channel field to begin with, and RenderService/RenderSocket take // (app, *Set, Grants) only, never a Host and never a channel. So a route // "on" any of production's four live channels converges byte-identical // unit text for the same declared and granted capabilities. Converging // the same Plan under a Host named for each channel and diffing the // rendered bytes (never the path, which DOES vary by host) is what makes // that a test rather than an assertion about code nobody re-reads. func TestCapabilitiesNeverConsultAChannelName(t *testing.T) { t.Run("structural", func(t *testing.T) { assertNoChannelWord(t, ".") }) t.Run("behavioural", func(t *testing.T) { s := &Set{ V: Version, Command: "relay", Daemon: true, Children: true, RuntimeDir: "keymail", Ports: []Port{{Port: 25, Name: "mx"}}, Data: &Data{Replicate: DataReplicateApp}, HostRole: true, } g := Grants{Ports: map[int]bool{25: true}, HostRole: true} var first []byte var firstChannel string for _, ch := range liveChannels { // The channel name is sanitized into a legal hostname ONLY so this // loop has something host-shaped to converge under. Host is not a // render input — RenderService and RenderSocket never take one — // so this is not smuggling the channel in through the back door; // it is the strongest form of "cannot reach it" available: even a // value DERIVED from the channel name, sitting in the one plan // field a channel might plausibly have leaked into, changes // nothing about what gets written. host := "relay-" + strings.NewReplacer("canary/", "", "/", "-").Replace(ch) + ".example.com" etc := t.TempDir() o := Ops{ EtcDir: etc, StateRoot: t.TempDir(), Systemctl: func(...string) error { return nil }, Query: func(...string) bool { return false }, EnsureUser: func(string) error { return nil }, } p := Plan{Host: host, App: "keymail", Set: s, Grants: g} if _, err := Converge(o, p); err != nil { t.Fatalf("converge for channel %q: %v", ch, err) } svcPath, _ := DropInPaths(etc, host) body, err := os.ReadFile(svcPath) if err != nil { t.Fatalf("read rendered drop-in for channel %q: %v", ch, err) } if first == nil { first, firstChannel = body, ch continue } if !bytes.Equal(first, body) { t.Errorf("materialized capabilities differ between channel %q and %q for an identical declared+granted set:\n%s\n---\n%s", firstChannel, ch, first, body) } } }) } // assertNoChannelWord fails if any non-test .go file directly in dir mentions // "channel" or "canary" outside a comment. Comments are found with // go/parser's ParseComments and blanked out of the source before the search, // so a doc comment stating the neutrality rule (this file's own included) // can never be mistaken for a violation of it. func assertNoChannelWord(t *testing.T, dir string) { t.Helper() entries, err := os.ReadDir(dir) if err != nil { t.Fatal(err) } fset := token.NewFileSet() for _, e := range entries { name := e.Name() if e.IsDir() || !strings.HasSuffix(name, ".go") || strings.HasSuffix(name, "_test.go") { continue } path := filepath.Join(dir, name) src, err := os.ReadFile(path) if err != nil { t.Fatal(err) } file, err := parser.ParseFile(fset, path, src, parser.ParseComments) if err != nil { t.Fatalf("parse %s: %v", path, err) } sanitized := append([]byte(nil), src...) for _, cg := range file.Comments { start := fset.Position(cg.Pos()).Offset end := fset.Position(cg.End()).Offset for i := start; i < end && i < len(sanitized); i++ { sanitized[i] = ' ' } } lower := strings.ToLower(string(sanitized)) for _, word := range []string{"channel", "canary"} { if strings.Contains(lower, word) { t.Errorf("%s mentions %q outside a comment — internal/caps must never consult or constrain a channel name", name, word) } } } }