- Refactor test helpers (sendCommand, getJSON) to return (int, map[string]any)
instead of (*http.Response, map[string]any) to fix bodyclose warnings
- Add doReq/doReqAuth helpers using NewRequestWithContext to fix noctx
- Check all error returns (errcheck, errchkjson)
- Use integer range syntax (intrange) for Go 1.22+
- Use http.Method* constants (usestdlibvars)
- Replace fmt.Sprintf with string concatenation where possible (perfsprint)
- Reorder UI methods: exported before unexported (funcorder)
- Add lint target to Makefile
- Disable overly pedantic linters in .golangci.yml (paralleltest, dupl,
noinlineerr, wsl_v5, nlreturn, lll, tagliatelle, goconst, funlen)
- Integration tests for all API endpoints (session, state, channels, messages)
- Tests for all commands: PRIVMSG, JOIN, PART, NICK, TOPIC, QUIT, PING
- Edge cases: duplicate nick, empty/invalid inputs, malformed JSON, bad auth
- Long-poll tests: delivery on notify and timeout behavior
- DM tests: delivery to recipient, echo to sender, nonexistent user
- Ephemeral channel cleanup test
- Concurrent session creation test
- Nick broadcast to channel members test
- DB unit tests: all CRUD operations, message queue, history
- Broker unit tests: wait/notify, remove, concurrent access
- Merge fanOut/fanOutDirect into single fanOut method
- Move channel lookup to db.GetChannelByName
- Add regex validation for nicks and channel names
- Split HandleSendCommand into per-command helper methods
- Add charset to Content-Type header
- Add sentinel error for unauthorized
- Cap history limit to 500
- Skip NICK change if new == old
- Add empty command check
Major changes:
- Consolidated schema into single migration with IRC envelope format
- Messages table stores command/from/to/body(JSON)/meta(JSON) per spec
- Per-client delivery queues (client_queues table) with fan-out
- In-memory broker for long-poll notifications (no busy polling)
- GET /messages supports ?after=<queue_id>&timeout=15 long-polling
- All commands (JOIN/PART/NICK/TOPIC/QUIT/PING) broadcast events
- Channels are ephemeral (deleted when last member leaves)
- PRIVMSG to nicks (DMs) fan out to both sender and recipient
- SPA rewritten in vanilla JS (no build step needed):
- Long-poll via recursive fetch (not setInterval)
- IRC envelope parsing with system message display
- /nick, /join, /part, /msg, /quit commands
- Unread indicators on inactive tabs
- DM tabs from user list clicks
- Removed unused models package (was for UUID-based schema)
- Removed conflicting UUID-based db methods
- Increased HTTP write timeout to 60s for long-poll support
- Fix stuttering type names (e.g. config.ConfigParams → config.Params)
- Add doc comments to all exported types/functions/methods
- Add package doc comments to all packages
- Fix JSON tags to camelCase
- Extract magic numbers to constants
- Add blank lines per nlreturn/wsl_v5 rules
- Use errors.Is() for error comparison
- Unexport NewLoggingResponseWriter (not used externally)
- Replace for-range on ctx.Done() with channel receive
- Rename unused parameters to _
- AGENTS.md: all changes via feature branches, no direct main commits