diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..61aceb9 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,80 @@ +# Repository Rules + +Last Updated 2026-01-10 + +These rules MUST be followed at all times, it is very important. + +* Do NOT stop working while there are still incomplete TODOs in the todo list + or in TODO.md. Continue implementing until all tasks are complete or you are + explicitly told to stop. + +* Never use `git add -A` - add specific changes to a deliberate commit. A + commit should contain one change. After each change, make a commit with a + good one-line summary. + +* NEVER modify the linter config without asking first. + +* NEVER modify tests to exclude special cases or otherwise get them to pass + without asking first. In almost all cases, the code should be changed, + NOT the tests. If you think the test needs to be changed, make your case + for that and ask for permission to proceed, then stop. You need explicit + user approval to modify existing tests. (You do not need user approval + for writing NEW tests.) + +* When linting, assume the linter config is CORRECT, and that each item + output by the linter is something that legitimately needs fixing in the + code. + +* When running tests, use `make test`. + +* Before commits, run `make check`. This runs `make lint` and `make test` + and `make check-fmt`. Any issues discovered MUST be resolved before + committing unless explicitly told otherwise. + +* When fixing a bug, write a failing test for the bug FIRST. Add + appropriate logging to the test to ensure it is written correctly. Commit + that. Then go about fixing the bug until the test passes (without + modifying the test further). Then commit that. + +* When adding a new feature, do the same - implement a test first (TDD). It + doesn't have to be super complex. Commit the test, then commit the + feature. + +* When adding a new feature, use a feature branch. When the feature is + completely finished and the code is up to standards (passes `make check`) + then and only then can the feature branch be merged into `main` and the + branch deleted. + +* Write godoc documentation comments for all exported types and functions as + you go along. + +* ALWAYS be consistent in naming. If you name something one thing in one + place, name it the EXACT SAME THING in another place. + +* Be descriptive and specific in naming. `wl` is bad; + `SourceHostWhitelist` is good. `ConnsPerHost` is bad; + `MaxConnectionsPerHost` is good. + +* This is not prototype or teaching code - this is designed for production. + Any security issues (such as denial of service) or other web + vulnerabilities are P1 bugs and must be added to TODO.md at the top. + +* As this is production code, no stubbing of implementations unless + specifically instructed. We need working implementations. + +* NEVER silently fall back to a different setting when a user's parameter + explicitly specifies a value. If a user requests format=webp and WebP + encoding is not supported, return an error - do NOT silently output PNG + instead. If a user specifies fit=invalid and that fit mode doesn't exist, + return an error - do NOT silently default to "cover". Silent fallbacks + violate the principle of least surprise and mask bugs. The only acceptable + defaults are for OMITTED parameters, never for INVALID explicit values. + +* Avoid vendoring deps unless specifically instructed to. NEVER commit + the vendor directory, NEVER commit compiled binaries. If these + directories or files exist, add them to .gitignore (and commit the + .gitignore) if they are not already in there. Keep the entire git + repository (with history) small - under 20MiB, unless you specifically + must commit larger files (e.g. test fixture example media files). Only + OUR source code and immediately supporting files (such as test examples) + goes into the repo/history. diff --git a/CONVENTIONS.md b/CONVENTIONS.md index 855c680..8885442 100644 --- a/CONVENTIONS.md +++ b/CONVENTIONS.md @@ -114,13 +114,11 @@ import ( var ( Appname string = "CHANGEME" Version string - Buildarch string ) func main() { globals.Appname = Appname globals.Version = Version - globals.Buildarch = Buildarch fx.New( fx.Provide( @@ -453,6 +451,11 @@ func New(lc fx.Lifecycle, params HandlersParams) (*Handlers, error) { ### Closure-Based Handler Pattern +For JSON route handlers, both the request and the response structures are +defined in the scope of the method that returns the HandlerFunc. They can +be called simply `Request` and `Response` or slightly more descriptive +names. + All handlers return `http.HandlerFunc` using the closure pattern. This allows initialization logic to run once when the handler is created: ```go @@ -477,6 +480,11 @@ func (s *Handlers) HandleIndex() http.HandlerFunc { ```go // internal/handlers/now.go func (s *Handlers) HandleNow() http.HandlerFunc { + + type request struct { + // request format + } + // Response struct defined in closure scope type response struct { Now time.Time `json:"now"` @@ -816,7 +824,6 @@ func (l *Logger) Identify() { l.log.Info("starting", "appname", l.params.Globals.Appname, "version", l.params.Globals.Version, - "buildarch", l.params.Globals.Buildarch, ) } ``` @@ -938,20 +945,17 @@ import "go.uber.org/fx" var ( Appname string Version string - Buildarch string ) // Struct for DI type Globals struct { Appname string Version string - Buildarch string } func New(lc fx.Lifecycle) (*Globals, error) { n := &Globals{ Appname: Appname, - Buildarch: Buildarch, Version: Version, } return n, nil @@ -965,13 +969,11 @@ func New(lc fx.Lifecycle) (*Globals, error) { var ( Appname string = "CHANGEME" // Default, overridden by build Version string // Set at build time - Buildarch string // Set at build time ) func main() { globals.Appname = Appname globals.Version = Version - globals.Buildarch = Buildarch // ... } ``` @@ -982,10 +984,9 @@ Use ldflags to inject version information at build time: ```makefile VERSION := $(shell git describe --tags --always) -BUILDARCH := $(shell go env GOARCH) build: - go build -ldflags "-X main.Version=$(VERSION) -X main.Buildarch=$(BUILDARCH)" ./cmd/httpd + go build -ldflags "-X main.Version=$(VERSION)" ./cmd/httpd ``` ---