Re-vendor the canonical files from sneak/prompts at dd4027b (closes #112)
check / check (push) Waiting to run

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. neoirc-cli treats a plain-HTTP server on
localhost or a loopback address as secure, so local use keeps its session.

Whether the 60-second test cap covers building the test phase is open
on sneak/prompts issue 113.

Model: opus-5-5
This commit was merged in pull request #115.
This commit is contained in:
2026-10-06 21:01:46 +02:00
parent 9a46421902
commit bb7bcb31ea
47 changed files with 2975 additions and 1427 deletions
+52 -60
View File
@@ -125,21 +125,18 @@ func (hdlr *Handlers) authSession(
}
// setAuthCookie sets the authentication cookie on the
// response.
// response. It is always Secure: the server runs behind a
// TLS-terminating reverse proxy.
func (hdlr *Handlers) setAuthCookie(
writer http.ResponseWriter,
request *http.Request,
token string,
) {
secure := request.TLS != nil ||
request.Header.Get("X-Forwarded-Proto") == "https"
http.SetCookie(writer, &http.Cookie{ //nolint:exhaustruct // optional fields
Name: authCookieName,
Value: token,
Path: "/",
HttpOnly: true,
Secure: secure,
Secure: true,
SameSite: http.SameSiteStrictMode,
})
}
@@ -148,17 +145,13 @@ func (hdlr *Handlers) setAuthCookie(
// the client.
func (hdlr *Handlers) clearAuthCookie(
writer http.ResponseWriter,
request *http.Request,
) {
secure := request.TLS != nil ||
request.Header.Get("X-Forwarded-Proto") == "https"
http.SetCookie(writer, &http.Cookie{ //nolint:exhaustruct // optional fields
Name: authCookieName,
Value: "",
Path: "/",
HttpOnly: true,
Secure: secure,
Secure: true,
SameSite: http.SameSiteStrictMode,
MaxAge: -1,
})
@@ -172,7 +165,7 @@ func (hdlr *Handlers) requireAuth(
hdlr.authSession(request)
if err != nil {
hdlr.respondJSON(writer, request, map[string]any{
"error": "not registered",
errorKey: "not registered",
"numeric": irc.ErrNotRegistered,
}, http.StatusUnauthorized)
@@ -285,11 +278,11 @@ func (hdlr *Handlers) executeCreateSession(
hdlr.deliverMOTD(request, clientID, sessionID, nick)
hdlr.setAuthCookie(writer, request, token)
hdlr.setAuthCookie(writer, token)
hdlr.respondJSON(writer, request, map[string]any{
"id": sessionID,
"nick": nick,
"id": sessionID,
nickKey: nick,
}, http.StatusCreated)
}
@@ -643,7 +636,7 @@ func (hdlr *Handlers) HandleState() http.HandlerFunc {
hdlr.respondJSON(writer, request, map[string]any{
"id": sessionID,
"nick": nick,
nickKey: nick,
"channels": channels,
}, http.StatusOK)
}
@@ -1090,7 +1083,7 @@ func (hdlr *Handlers) dispatchQueryCommand(
)
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "error"},
map[string]string{statusKey: statusError},
http.StatusOK)
}
}
@@ -1112,7 +1105,7 @@ func (hdlr *Handlers) handlePrivmsg(
)
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "error"},
map[string]string{statusKey: statusError},
http.StatusOK)
return
@@ -1127,7 +1120,7 @@ func (hdlr *Handlers) handlePrivmsg(
)
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "error"},
map[string]string{statusKey: statusError},
http.StatusOK)
return
@@ -1169,7 +1162,7 @@ func (hdlr *Handlers) respondIRCError(
)
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "error"},
map[string]string{statusKey: statusError},
http.StatusOK)
}
@@ -1257,7 +1250,7 @@ func (hdlr *Handlers) handleChannelMsg(
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"id": uuid, "status": "sent"},
map[string]string{"id": uuid, statusKey: "sent"},
http.StatusOK)
}
@@ -1447,7 +1440,7 @@ func (hdlr *Handlers) handleDirectMsg(
hdlr.respondJSON(writer, request,
map[string]string{
"id": result.UUID, "status": "sent",
"id": result.UUID, statusKey: "sent",
},
http.StatusOK)
}
@@ -1522,7 +1515,7 @@ func (hdlr *Handlers) executeJoin(
hdlr.respondJSON(writer, request,
map[string]string{
"status": "joined",
statusKey: "joined",
"channel": channel,
},
http.StatusOK)
@@ -1679,6 +1672,7 @@ func (hdlr *Handlers) handlePart(
// Extract reason from body for the service call.
reason := ""
if body != nil {
var lines []string
if json.Unmarshal(body, &lines) == nil &&
@@ -1700,7 +1694,7 @@ func (hdlr *Handlers) handlePart(
hdlr.respondJSON(writer, request,
map[string]string{
"status": "parted",
statusKey: "parted",
"channel": channel,
},
http.StatusOK)
@@ -1739,7 +1733,7 @@ func (hdlr *Handlers) handleNick(
if newNick == nick {
hdlr.respondJSON(writer, request,
map[string]string{
"status": "ok", "nick": newNick,
statusKey: "ok", nickKey: newNick,
},
http.StatusOK)
@@ -1770,7 +1764,7 @@ func (hdlr *Handlers) executeNickChange(
hdlr.respondJSON(writer, request,
map[string]string{
"status": "ok", "nick": newNick,
statusKey: "ok", nickKey: newNick,
},
http.StatusOK)
}
@@ -1831,7 +1825,7 @@ func (hdlr *Handlers) handleTopic(
hdlr.respondJSON(writer, request,
map[string]string{
"status": "ok", "topic": topic,
statusKey: "ok", "topic": topic,
},
http.StatusOK)
}
@@ -1885,7 +1879,7 @@ func (hdlr *Handlers) dispatchInfoCommand(
_ = target
_ = bodyLines
okResp := map[string]string{"status": "ok"}
okResp := map[string]string{statusKey: "ok"}
switch command {
case irc.CmdMotd:
@@ -1916,6 +1910,7 @@ func (hdlr *Handlers) handleQuit(
body json.RawMessage,
) {
reason := "Client quit"
if body != nil {
var lines []string
if json.Unmarshal(body, &lines) == nil &&
@@ -1928,10 +1923,10 @@ func (hdlr *Handlers) handleQuit(
request.Context(), sessionID, nick, reason,
)
hdlr.clearAuthCookie(writer, request)
hdlr.clearAuthCookie(writer)
hdlr.respondJSON(writer, request,
map[string]string{"status": "quit"},
map[string]string{statusKey: "quit"},
http.StatusOK)
}
@@ -1963,7 +1958,7 @@ func (hdlr *Handlers) handleMode(
)
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
return
@@ -2064,7 +2059,7 @@ func (hdlr *Handlers) queryChannelMode(
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -2241,7 +2236,7 @@ func (hdlr *Handlers) applyParameterizedMode(
)
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "error"},
map[string]string{statusKey: statusError},
http.StatusOK)
}
}
@@ -2307,7 +2302,7 @@ func (hdlr *Handlers) applyUserMode(
)
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -2353,7 +2348,7 @@ func (hdlr *Handlers) setChannelFlag(
)
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -2437,7 +2432,7 @@ func (hdlr *Handlers) setHashcashMode(
)
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -2486,7 +2481,7 @@ func (hdlr *Handlers) clearHashcashMode(
)
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -2591,7 +2586,7 @@ func (hdlr *Handlers) executeBanChange(
}
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -2645,7 +2640,7 @@ func (hdlr *Handlers) listBans(
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -2709,7 +2704,7 @@ func (hdlr *Handlers) setChannelKeyMode(
}
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -2758,7 +2753,7 @@ func (hdlr *Handlers) clearChannelKeyMode(
}
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -2833,7 +2828,7 @@ func (hdlr *Handlers) setChannelLimitMode(
}
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -2883,7 +2878,7 @@ func (hdlr *Handlers) clearChannelLimitMode(
}
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -3050,7 +3045,7 @@ func (hdlr *Handlers) executeInvite(
}
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -3119,7 +3114,7 @@ func (hdlr *Handlers) handleNames(
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -3172,7 +3167,7 @@ func (hdlr *Handlers) handleList(
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -3262,7 +3257,7 @@ func (hdlr *Handlers) executeWhois(
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -3287,7 +3282,7 @@ func (hdlr *Handlers) whoisNotFound(
)
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -3454,7 +3449,7 @@ func (hdlr *Handlers) handleWho(
)
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
return
@@ -3496,7 +3491,7 @@ func (hdlr *Handlers) handleWho(
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -3512,7 +3507,7 @@ func (hdlr *Handlers) handleLusers(
)
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -3703,10 +3698,10 @@ func (hdlr *Handlers) HandleLogout() http.HandlerFunc {
)
}
hdlr.clearAuthCookie(writer, request)
hdlr.clearAuthCookie(writer)
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
}
@@ -3809,7 +3804,7 @@ func (hdlr *Handlers) handleOper(
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -3857,7 +3852,7 @@ func (hdlr *Handlers) handleAway(
hdlr.broker.Notify(sessionID)
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -3919,7 +3914,7 @@ func (hdlr *Handlers) handleKick(
}
hdlr.respondJSON(writer, request,
map[string]string{"status": "ok"},
map[string]string{statusKey: "ok"},
http.StatusOK)
}
@@ -3943,10 +3938,7 @@ func (hdlr *Handlers) deliverWhoisIdle(
return
}
idleSeconds := int64(time.Since(lastSeen).Seconds())
if idleSeconds < 0 {
idleSeconds = 0
}
idleSeconds := max(int64(time.Since(lastSeen).Seconds()), 0)
signonUnix := strconv.FormatInt(
createdAt.Unix(), 10,