The shared files are fetched from sneak/prompts dd4027b, with this
repository's own entries after the shared content in .gitignore,
.editorconfig and .dockerignore.
Lint and tests are Dockerfile phases (golangci-lint v2.14.0, Debian Go
1.24.13) that the build stage depends on, and the Makefile targets call
the script/ entrypoints. make fmt also formats Markdown with prettier.
Fixes for the new lint findings: the auth cookie is always Secure, an
IRC connection's relay goroutine stops when the connection closes, and
repeated strings are constants.
Model: opus-5-5
## Summary
Replaces fragile `strings.Contains(err.Error(), "UNIQUE")` checks with typed error detection using `errors.As` and the SQLite driver's `*sqlite.Error` type.
## Changes
- **`internal/db/errors.go`** (new): Adds `IsUniqueConstraintError(err)` helper that uses `errors.As` to unwrap the error into `*sqlite.Error` and checks for `SQLITE_CONSTRAINT_UNIQUE` (code 2067).
- **`internal/handlers/api.go`**: Replaces two `strings.Contains(err.Error(), "UNIQUE")` calls with `db.IsUniqueConstraintError(err)` — in `handleCreateSessionError` and `executeNickChange`.
- **`internal/handlers/auth.go`**: Replaces one `strings.Contains(err.Error(), "UNIQUE")` call with `db.IsUniqueConstraintError(err)` — in `handleRegisterError`.
## Why
String matching on error messages is fragile — if the SQLite driver changes its error message format, the detection silently breaks. Using `errors.As` with the driver's typed error and checking the specific SQLite error code is robust, idiomatic Go, and immune to message format changes.
closes sneak/chat#39
<!-- session: agent:sdlc-manager:subagent:3fb0b8e2-d635-4848-a5bd-131c5033cdb1 -->
Co-authored-by: user <user@Mac.lan guest wan>
Co-authored-by: Jeffrey Paul <sneak@noreply.example.org>
Reviewed-on: sneak/chat#66
Co-authored-by: clawbot <clawbot@noreply.example.org>
Co-committed-by: clawbot <clawbot@noreply.example.org>