# check-safety Static safety checker for the BlockNinja codebase. Walks a target tree, runs ~25 invariant checks across Go and frontend sources, and exits non-zero on violations. Lives at `~/src/blockninja/check-safety/` as a standalone Go module, alongside `cms/`, `orchestrator/`, `core/`, etc. ## Run ```bash # Scan CMS (default target) make run # Scan something else make run TARGET=../orchestrator # Direct go run . ../sites/bidbuddy ``` ## Install globally ```bash make install # → $GOPATH/bin/check-safety check-safety ~/src/blockninja/cms ``` ## Test ```bash make test # all tests (some shell out to npm/tsc/golangci-lint and may skip if absent) make test-short # skip the long ones make test-update # regenerate golden snapshots after intentional output changes ``` ## What it checks See the comment block at the top of `main.go` for the canonical list. Highlights: - Secret env-var reads happen only inside `config.Load()` - All RPC methods are registered in the RBAC interceptor - Frontend uses generated ConnectRPC hooks, no hand-crafted clients - No hardcoded colors, no `useState` for tab state, no npm/yarn lockfiles - No raw SQL outside sqlc/Bob, no `err.Error()` leaked to HTTP clients - Plugin presets validate against `theme.Theme` - Standalone plugins stay on the published SDK boundary ## How it stays in sync with CMS `internal/helpers/deferlog.go` and `internal/theme/*.go` are vendored copies from CMS (`cms/backend/internal/{helpers,theme}/`). Go's `internal/` rule blocks direct imports across modules, so they live here. When CMS changes the theme schema or `LogDeferredError`, re-copy them — that drift is the point of the preset-validation check. ## Adding a new check 1. Add a `check_.go` file with a `runCheck` func 2. Wire it into `main.go`'s check sequence 3. Add a goldens case in `golden_test.go` if the output is deterministic 4. Run `make test-update` to regenerate goldens