refactor: replace HTTP error codes with IRC numeric replies (#56)
All checks were successful
check / check (push) Successful in 58s

## Summary

Refactors all IRC command handlers to respond with proper IRC numeric replies via the message queue instead of HTTP status codes.

HTTP error codes are now reserved exclusively for transport-level concerns:
- **401** — missing/invalid auth token
- **400** — malformed JSON, empty command
- **500** — server errors

## IRC Numerics Implemented

### Success replies (delivered via message queue on success):
- **001 RPL_WELCOME** — sent on session creation and login
- **331 RPL_NOTOPIC** — channel has no topic (on JOIN)
- **332 RPL_TOPIC** — channel topic (on JOIN, TOPIC set)
- **353 RPL_NAMREPLY** — channel member list (on JOIN)
- **366 RPL_ENDOFNAMES** — end of NAMES list (on JOIN)
- **375/372/376** — MOTD (already existed)

### Error replies (delivered via message queue instead of HTTP 4xx):
- **401 ERR_NOSUCHNICK** — DM target not found (was HTTP 404)
- **403 ERR_NOSUCHCHANNEL** — channel not found / invalid name (was HTTP 404)
- **421 ERR_UNKNOWNCOMMAND** — unrecognized command (was HTTP 400)
- **432 ERR_ERRONEUSNICKNAME** — invalid nick format (was HTTP 400)
- **433 ERR_NICKNAMEINUSE** — nick taken (was HTTP 409)
- **442 ERR_NOTONCHANNEL** — not a member of channel (was HTTP 403)
- **461 ERR_NEEDMOREPARAMS** — missing required fields (was HTTP 400)

## Database Changes
- Added `params` column to messages table for IRC-style parameters
- Added `Params` field to `IRCMessage` struct
- Updated `InsertMessage` to accept params

## Test Updates
- All existing tests updated to expect HTTP 200 + IRC numerics
- New tests: `TestWelcomeNumeric`, `TestJoinNumerics`

## Client Impact
- CLI and SPA already handle unknown numerics via default event handlers
- PRIVMSG/NOTICE success changed from HTTP 201 to HTTP 200

closes #54

Co-authored-by: clawbot <clawbot@noreply.git.eeqj.de>
Co-authored-by: Jeffrey Paul <sneak@noreply.example.org>
Reviewed-on: #56
Co-authored-by: clawbot <clawbot@noreply.example.org>
Co-committed-by: clawbot <clawbot@noreply.example.org>
This commit was merged in pull request #56.
This commit is contained in:
2026-03-09 22:21:30 +01:00
committed by Jeffrey Paul
parent 8e3166969e
commit f8f0b6afbb
7 changed files with 627 additions and 174 deletions

View File

@@ -845,10 +845,11 @@ the server to the client (never C2S) and use 3-digit string codes in the
| `442` | ERR_NOTONCHANNEL | Action on unjoined channel | `{"command":"442","to":"alice","params":["#general"],"body":["You're not on that channel"]}` |
| `482` | ERR_CHANOPRIVSNEEDED | Non-op tries op action | `{"command":"482","to":"alice","params":["#general"],"body":["You're not channel operator"]}` |
**Note:** Numeric replies are planned for full implementation. The current MVP
returns standard HTTP error responses (4xx/5xx with JSON error bodies) instead
of numeric replies for error conditions. Numeric replies in the message queue
will be added post-MVP.
**Note:** Numeric replies are now implemented. All IRC command responses
(success and error) are delivered as numeric replies through the message queue.
HTTP error codes are reserved for transport-level issues (auth failures,
malformed requests, server errors). The `params` field in the message envelope
carries IRC-style parameters (e.g., channel name, target nick).
### Channel Modes
@@ -1054,8 +1055,8 @@ reference with all required and optional fields.
| Command | Required Fields | Optional | Response Status |
|-----------|---------------------|---------------|-----------------|
| `PRIVMSG` | `to`, `body` | `meta` | 201 Created |
| `NOTICE` | `to`, `body` | `meta` | 201 Created |
| `PRIVMSG` | `to`, `body` | `meta` | 200 OK |
| `NOTICE` | `to`, `body` | `meta` | 200 OK |
| `JOIN` | `to` | | 200 OK |
| `PART` | `to` | `body` | 200 OK |
| `NICK` | `body` | | 200 OK |
@@ -1063,18 +1064,44 @@ reference with all required and optional fields.
| `QUIT` | | `body` | 200 OK |
| `PING` | | | 200 OK |
**Errors (all commands):**
All IRC commands return HTTP 200 OK. IRC-level success and error responses
are delivered as **numeric replies** through the message queue (see
[Numeric Replies](#numeric-replies) below). HTTP error codes (4xx/5xx) are
reserved for transport-level problems: malformed JSON (400), missing/invalid
auth tokens (401), and server errors (500).
**HTTP errors (transport-level only):**
| Status | Error | When |
|--------|-------|------|
| 400 | `invalid request` | Malformed JSON |
| 400 | `to field required` | Missing `to` for commands that need it |
| 400 | `body required` | Missing `body` for commands that need it |
| 400 | `unknown command: X` | Unrecognized command |
| 400 | `invalid request` | Malformed JSON or empty command |
| 401 | `unauthorized` | Missing or invalid auth token |
| 404 | `channel not found` | Target channel doesn't exist |
| 404 | `user not found` | DM target nick doesn't exist |
| 409 | `nick already in use` | NICK target is taken |
| 500 | `internal error` | Server-side failure |
**IRC numeric error replies (delivered via message queue):**
| Numeric | Name | When |
|---------|------|------|
| 401 | ERR_NOSUCHNICK | DM target nick doesn't exist |
| 403 | ERR_NOSUCHCHANNEL | Target channel doesn't exist or invalid name |
| 421 | ERR_UNKNOWNCOMMAND | Unrecognized command |
| 432 | ERR_ERRONEUSNICKNAME | Invalid nickname format |
| 433 | ERR_NICKNAMEINUSE | NICK target is taken |
| 442 | ERR_NOTONCHANNEL | Not a member of the target channel |
| 461 | ERR_NEEDMOREPARAMS | Missing required fields (to, body) |
**IRC numeric success replies (delivered via message queue):**
| Numeric | Name | When |
|---------|------|------|
| 001 | RPL_WELCOME | Sent on session creation/login |
| 331 | RPL_NOTOPIC | Channel has no topic (on JOIN) |
| 332 | RPL_TOPIC | Channel topic (on JOIN, TOPIC set) |
| 353 | RPL_NAMREPLY | Channel member list (on JOIN) |
| 366 | RPL_ENDOFNAMES | End of NAMES list (on JOIN) |
| 375 | RPL_MOTDSTART | Start of MOTD |
| 372 | RPL_MOTD | MOTD line |
| 376 | RPL_ENDOFMOTD | End of MOTD |
### GET /api/v1/history — Message History