Add isolated Calendar activation observer
Co-Authored-By: Codex <noreply@openai.com>
5 files changed,
+273
−0
Makefile+9 −0cmd/calendar-fixture-preflight/dependencies_test.go+49 −0cmd/calendar-fixture-preflight/main.go+24 −0cmd/calendar-fixture-preflight/main_test.go+105 −0cmd/calendar-fixture-preflight/validate.go+86 −0
CI passed — run details
diff --git a/Makefile b/Makefile| index 86ae38b..6f9dd53 100644 |
| --- a/Makefile |
| +++ b/Makefile |
| @@ -118,3 +118,12 @@ ci: vet fmt-check test migration-check |
| browser: |
| npm install --no-save playwright |
| go test -tags browser -run InARealBrowser ./internal/calendartest/ |
| + |
| +FIXTURE_RUN_ID ?= |
| +.PHONY: fixture-preflight |
| +fixture-preflight: version-check |
| + @test -n "$(FIXTURE_RUN_ID)" |
| + @mkdir -p releases |
| + CGO_ENABLED=0 GOOS=$(RELEASE_GOOS) GOARCH=$(RELEASE_GOARCH) \ |
| + go build -ldflags="-s -w -X main.buildVersion=$(VERSION)-fixture-preflight-$(FIXTURE_RUN_ID) -X main.buildRunID=$(FIXTURE_RUN_ID)" \ |
| + -o releases/calendar-fixture-preflight-$(RELEASE_GOOS)-$(RELEASE_GOARCH) ./cmd/calendar-fixture-preflight |
diff --git a/cmd/calendar-fixture-preflight/dependencies_test.go b/cmd/calendar-fixture-preflight/dependencies_test.go| new file mode 100644 |
| index 0000000..762bf34 |
| --- /dev/null |
| +++ b/cmd/calendar-fixture-preflight/dependencies_test.go |
| @@ -0,0 +1,49 @@ |
| +package main |
| + |
| +import ( |
| + "go/ast" |
| + "go/parser" |
| + "go/token" |
| + "strconv" |
| + "strings" |
| + "testing" |
| +) |
| + |
| +func TestObserverSourceHasNoIOInitialization(t *testing.T) { |
| + files, err := parser.ParseDir(token.NewFileSet(), ".", nil, 0) |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + allowed := map[string]bool{"fmt": true, "io": true, "os": true, "bytes": true, "encoding/base64": true, "path/filepath": true, "strings": true} |
| + osCalls := map[string]bool{"Exit": true, "LookupEnv": true} |
| + pathCalls := map[string]bool{"IsAbs": true, "Clean": true, "Base": true, "Dir": true} |
| + for name, file := range files["main"].Files { |
| + if strings.HasSuffix(name, "_test.go") { |
| + continue |
| + } |
| + for _, imp := range file.Imports { |
| + path, _ := strconv.Unquote(imp.Path.Value) |
| + if !allowed[path] || imp.Name != nil { |
| + t.Errorf("observer dependency outside fixed pure/output boundary: %s", path) |
| + } |
| + } |
| + ast.Inspect(file, func(n ast.Node) bool { |
| + if f, ok := n.(*ast.FuncDecl); ok && f.Name.Name == "init" { |
| + t.Error("observer has init function") |
| + } |
| + if call, ok := n.(*ast.CallExpr); ok { |
| + if sel, ok := call.Fun.(*ast.SelectorExpr); ok { |
| + if id, ok := sel.X.(*ast.Ident); ok { |
| + if id.Name == "os" && !osCalls[sel.Sel.Name] { |
| + t.Errorf("observer OS call %s", sel.Sel.Name) |
| + } |
| + if id.Name == "filepath" && !pathCalls[sel.Sel.Name] { |
| + t.Errorf("observer filesystem call %s", sel.Sel.Name) |
| + } |
| + } |
| + } |
| + } |
| + return true |
| + }) |
| + } |
| +} |
diff --git a/cmd/calendar-fixture-preflight/main.go b/cmd/calendar-fixture-preflight/main.go| new file mode 100644 |
| index 0000000..3f81898 |
| --- /dev/null |
| +++ b/cmd/calendar-fixture-preflight/main.go |
| @@ -0,0 +1,24 @@ |
| +package main |
| + |
| +import ( |
| + "fmt" |
| + "io" |
| + "os" |
| +) |
| + |
| +var buildVersion string |
| +var buildRunID string |
| + |
| +func main() { os.Exit(run(os.Args[1:], os.LookupEnv, os.Stdout)) } |
| + |
| +func run(args []string, env func(string) (string, bool), out io.Writer) int { |
| + db, code := validate(args, env, buildVersion, buildRunID) |
| + if code != "" { |
| + fmt.Fprintln(out, "calendar-fixture-preflight:"+code) |
| + return 1 |
| + } |
| + if _, err := fmt.Fprintf(out, "calendar-fixture-preflight:ok version=%s run=%s socket=%s db=%s\n", buildVersion, buildRunID, socketPath, db); err != nil { |
| + return 1 |
| + } |
| + return 0 |
| +} |
diff --git a/cmd/calendar-fixture-preflight/main_test.go b/cmd/calendar-fixture-preflight/main_test.go| new file mode 100644 |
| index 0000000..b2b1b22 |
| --- /dev/null |
| +++ b/cmd/calendar-fixture-preflight/main_test.go |
| @@ -0,0 +1,105 @@ |
| +package main |
| + |
| +import ( |
| + "bytes" |
| + "encoding/base64" |
| + "strings" |
| + "testing" |
| +) |
| + |
| +const testRun = "synthetic-observer" |
| + |
| +var testVersion = strings.Repeat("a", 40) + "-fixture-preflight-" + testRun |
| + |
| +func fixtureEnv() map[string]string { |
| + e := map[string]string{"CALENDAR_ORIGIN": "https://" + host, "CALENDAR_ALLOWED_ADDRESSES": subject, "CALENDAR_ENV": "production", "CALENDAR_FIXTURE_RUN_ID": testRun, "CALENDAR_INSTANCE_KEY": base64.StdEncoding.EncodeToString(bytes.Repeat([]byte{1}, 32)), "CALENDAR_DEK": base64.StdEncoding.EncodeToString(bytes.Repeat([]byte{2}, 32))} |
| + for _, prefix := range []string{"CALENDAR_SMTP_", "CARLOS_SMTP_"} { |
| + for k, v := range map[string]string{"HOST": "smtp-fixture.invalid", "FROM": subject, "PORT": "587", "USER": "", "PASS": ""} { |
| + e[prefix+k] = v |
| + } |
| + } |
| + return e |
| +} |
| +func lookup(e map[string]string) func(string) (string, bool) { |
| + return func(k string) (string, bool) { v, ok := e[k]; return v, ok } |
| +} |
| +func validArgs() []string { |
| + return []string{"--socket", socketPath, "--db", "/unobserved-parent/" + host + ".db"} |
| +} |
| + |
| +func TestUnsupportedArgvNeverInspectsEnvironment(t *testing.T) { |
| + cases := [][]string{nil, {"seed"}, {"--db", "/data/" + host + ".db"}, {"--socket", socketPath, "--db", validArgs()[3], "--seed"}, {"--socket", socketPath, "--socket", socketPath}, {"--db", validArgs()[3], "--socket", socketPath}, {"-socket", socketPath, "-db", validArgs()[3]}, {"--socket=" + socketPath, "--db=" + validArgs()[3]}, {"--addr", "127.0.0.1:80", "--db", validArgs()[3]}, {"--socket", socketPath, "--db", "relative.db"}, {"--socket", socketPath, "--db", "/data/../data/" + host + ".db"}, {"--socket", socketPath, "--db", "/data/other.db"}, {"--socket", "/run/other.sock", "--db", validArgs()[3]}, {"--socket", socketPath, "--db", "/path\nsecret/" + host + ".db"}} |
| + for _, args := range cases { |
| + _, code := validate(args, func(string) (string, bool) { |
| + t.Fatalf("environment inspected for unsupported argv shape") |
| + return "", false |
| + }, testVersion, testRun) |
| + if code == "" { |
| + t.Fatal("unsupported argv accepted") |
| + } |
| + } |
| +} |
| + |
| +func TestConfigurationFailsClosed(t *testing.T) { |
| + for name := range fixtureEnv() { |
| + t.Run(name, func(t *testing.T) { |
| + e := fixtureEnv() |
| + delete(e, name) |
| + if _, code := validate(validArgs(), lookup(e), testVersion, testRun); code == "" { |
| + t.Fatal("missing required setting accepted") |
| + } |
| + e = fixtureEnv() |
| + e[name] = "synthetic-secret-sentinel" |
| + if _, code := validate(validArgs(), lookup(e), testVersion, testRun); code == "" { |
| + t.Fatal("wrong required setting accepted") |
| + } |
| + }) |
| + } |
| + for _, name := range []string{"LISTEN_FDS", "LISTEN_PID", "LISTEN_FDNAMES", "STATE_DIRECTORY"} { |
| + e := fixtureEnv() |
| + e[name] = "" |
| + if _, code := validate(validArgs(), lookup(e), testVersion, testRun); code == "" { |
| + t.Fatal("contradictory activation accepted") |
| + } |
| + } |
| + for _, value := range []string{fixtureEnv()["CALENDAR_INSTANCE_KEY"], base64.StdEncoding.EncodeToString(make([]byte, 32)), fixtureEnv()["CALENDAR_DEK"] + "\n"} { |
| + e := fixtureEnv() |
| + e["CALENDAR_DEK"] = value |
| + if _, code := validate(validArgs(), lookup(e), testVersion, testRun); code == "" { |
| + t.Fatal("unsafe key accepted") |
| + } |
| + } |
| + for _, v := range []struct{ version, run string }{{"", testRun}, {testVersion, ""}, {testVersion, "wrong-run"}, {"dev-fixture-preflight-" + testRun, testRun}} { |
| + if _, code := validate(validArgs(), lookup(fixtureEnv()), v.version, v.run); code == "" { |
| + t.Fatal("unstamped build accepted") |
| + } |
| + } |
| +} |
| + |
| +func TestPlatformShapeReportsOnlyValidatedPathsAndStamp(t *testing.T) { |
| + buildVersion, buildRunID = testVersion, testRun |
| + t.Cleanup(func() { buildVersion, buildRunID = "", "" }) |
| + for _, state := range []bool{false, true} { |
| + e := fixtureEnv() |
| + if state { |
| + e["STATE_DIRECTORY"] = "/unobserved-parent" |
| + } |
| + var out bytes.Buffer |
| + if code := run(validArgs(), lookup(e), &out); code != 0 { |
| + t.Fatalf("valid activation refused: %d", code) |
| + } |
| + want := "calendar-fixture-preflight:ok version=" + testVersion + " run=" + testRun + " socket=" + socketPath + " db=" + validArgs()[3] + "\n" |
| + if out.String() != want { |
| + t.Fatal("unexpected observer output") |
| + } |
| + } |
| + e := fixtureEnv() |
| + e["CALENDAR_DEK"] = "synthetic-secret-sentinel" |
| + var out bytes.Buffer |
| + if code := run(validArgs(), lookup(e), &out); code == 0 { |
| + t.Fatal("bad configuration succeeded") |
| + } |
| + if out.String() != "calendar-fixture-preflight:key\n" { |
| + t.Fatal("refusal was not fixed code") |
| + } |
| +} |
diff --git a/cmd/calendar-fixture-preflight/validate.go b/cmd/calendar-fixture-preflight/validate.go| new file mode 100644 |
| index 0000000..a3052f2 |
| --- /dev/null |
| +++ b/cmd/calendar-fixture-preflight/validate.go |
| @@ -0,0 +1,86 @@ |
| +package main |
| + |
| +import ( |
| + "bytes" |
| + "encoding/base64" |
| + "path/filepath" |
| + "strings" |
| +) |
| + |
| +const host = "overnight-calendar.bds.oncarlos.com" |
| +const socketPath = "/run/carlos/" + host + ".sock" |
| +const subject = "oficina-fixture@example.test" |
| + |
| +func validate(args []string, env func(string) (string, bool), version, runID string) (string, string) { |
| + // Argument validation precedes even environment inspection: seed invocations |
| + // cannot reach a configuration-dependent path. |
| + if len(args) != 4 || args[0] != "--socket" || args[2] != "--db" { |
| + return "", "argv" |
| + } |
| + if args[1] != socketPath { |
| + return "", "socket" |
| + } |
| + db := args[3] |
| + if !filepath.IsAbs(db) || filepath.Clean(db) != db || filepath.Base(db) != host+".db" || strings.IndexFunc(db, invalidPathRune) >= 0 { |
| + return "", "db" |
| + } |
| + if len(runID) < 8 || len(runID) > 64 || strings.IndexFunc(runID, invalidRunRune) >= 0 { |
| + return "", "build-run" |
| + } |
| + sha, ok := strings.CutSuffix(version, "-fixture-preflight-"+runID) |
| + if !ok || len(sha) != 40 || strings.IndexFunc(sha, invalidHexRune) >= 0 { |
| + return "", "build-version" |
| + } |
| + for _, name := range []string{"LISTEN_FDS", "LISTEN_PID", "LISTEN_FDNAMES"} { |
| + if _, present := env(name); present { |
| + return "", "activation" |
| + } |
| + } |
| + if state, present := env("STATE_DIRECTORY"); present && state != filepath.Dir(db) { |
| + return "", "state-directory" |
| + } |
| + for _, c := range []struct{ key, want string }{ |
| + {"CALENDAR_ORIGIN", "https://" + host}, |
| + {"CALENDAR_ALLOWED_ADDRESSES", subject}, |
| + {"CALENDAR_ENV", "production"}, |
| + {"CALENDAR_FIXTURE_RUN_ID", runID}, |
| + } { |
| + if got, present := env(c.key); !present || got != c.want { |
| + return "", "scope" |
| + } |
| + } |
| + for _, prefix := range []string{"CALENDAR_SMTP_", "CARLOS_SMTP_"} { |
| + for _, c := range []struct{ key, want string }{{"HOST", "smtp-fixture.invalid"}, {"FROM", subject}, {"PORT", "587"}, {"USER", ""}, {"PASS", ""}} { |
| + if got, present := env(prefix + c.key); !present || got != c.want { |
| + return "", "smtp" |
| + } |
| + } |
| + } |
| + instance, ok := key(env, "CALENDAR_INSTANCE_KEY") |
| + if !ok { |
| + return "", "key" |
| + } |
| + dek, ok := key(env, "CALENDAR_DEK") |
| + if !ok || bytes.Equal(instance, dek) { |
| + return "", "key" |
| + } |
| + return db, "" |
| +} |
| + |
| +func key(env func(string) (string, bool), name string) ([]byte, bool) { |
| + value, present := env(name) |
| + if !present { |
| + return nil, false |
| + } |
| + decoded, err := base64.StdEncoding.DecodeString(value) |
| + if err != nil || len(decoded) != 32 || base64.StdEncoding.EncodeToString(decoded) != value || bytes.Equal(decoded, make([]byte, 32)) { |
| + return nil, false |
| + } |
| + return decoded, true |
| +} |
| + |
| +func invalidHexRune(r rune) bool { return !(r >= '0' && r <= '9' || r >= 'a' && r <= 'f') } |
| +func invalidRunRune(r rune) bool { return !(r >= 'a' && r <= 'z' || r >= '0' && r <= '9' || r == '-') } |
| +func invalidPathRune(r rune) bool { |
| + return !(r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z' || r >= '0' && r <= '9' || strings.ContainsRune("/._-", r)) |
| +} |