Re-vendor the canonical files from sneak/prompts at dd4027b (closes #112)
check / check (push) Failing after 4s

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
-1
View File
@@ -1,4 +1,3 @@
// Package db provides database access and migration management.
package db
import (
+22 -12
View File
@@ -1150,7 +1150,8 @@ func scanMessages(
code, _ := strconv.Atoi(msg.Command)
msg.Code = code
if mt, err := irc.FromInt(code); err == nil {
mt, lookupErr := irc.FromInt(code)
if lookupErr == nil {
msg.Command = mt.Name()
}
}
@@ -1373,7 +1374,9 @@ func (database *Database) GetStaleOrphanSessions(
for rows.Next() {
var stale StaleSession
if err := rows.Scan(&stale.ID, &stale.Nick); err != nil {
err = rows.Scan(&stale.ID, &stale.Nick)
if err != nil {
return nil, fmt.Errorf(
"scan stale session: %w", err,
)
@@ -1382,7 +1385,8 @@ func (database *Database) GetStaleOrphanSessions(
result = append(result, stale)
}
if err := rows.Err(); err != nil {
err = rows.Err()
if err != nil {
return nil, fmt.Errorf(
"iterate stale sessions: %w", err,
)
@@ -1905,9 +1909,10 @@ func (database *Database) ListChannelBans(
for rows.Next() {
var ban BanInfo
if scanErr := rows.Scan(
scanErr := rows.Scan(
&ban.Mask, &ban.SetBy, &ban.CreatedAt,
); scanErr != nil {
)
if scanErr != nil {
return nil, fmt.Errorf(
"scan channel ban: %w", scanErr,
)
@@ -1916,7 +1921,8 @@ func (database *Database) ListChannelBans(
bans = append(bans, ban)
}
if rowErr := rows.Err(); rowErr != nil {
rowErr := rows.Err()
if rowErr != nil {
return nil, fmt.Errorf(
"iterate channel bans: %w", rowErr,
)
@@ -2247,11 +2253,12 @@ func (database *Database) ListAllChannelsWithCountsFiltered(
for rows.Next() {
var chanInfo ChannelInfoFull
if scanErr := rows.Scan(
scanErr := rows.Scan(
&chanInfo.Name,
&chanInfo.MemberCount,
&chanInfo.Topic,
); scanErr != nil {
)
if scanErr != nil {
return nil, fmt.Errorf(
"scan channel: %w", scanErr,
)
@@ -2260,7 +2267,8 @@ func (database *Database) ListAllChannelsWithCountsFiltered(
channels = append(channels, chanInfo)
}
if rowErr := rows.Err(); rowErr != nil {
rowErr := rows.Err()
if rowErr != nil {
return nil, fmt.Errorf(
"iterate channels: %w", rowErr,
)
@@ -2308,11 +2316,12 @@ func (database *Database) GetSessionChannelsFiltered(
for rows.Next() {
var chanInfo ChannelInfo
if scanErr := rows.Scan(
scanErr := rows.Scan(
&chanInfo.ID,
&chanInfo.Name,
&chanInfo.Topic,
); scanErr != nil {
)
if scanErr != nil {
return nil, fmt.Errorf(
"scan channel: %w", scanErr,
)
@@ -2321,7 +2330,8 @@ func (database *Database) GetSessionChannelsFiltered(
channels = append(channels, chanInfo)
}
if rowErr := rows.Err(); rowErr != nil {
rowErr := rows.Err()
if rowErr != nil {
return nil, fmt.Errorf(
"iterate channels: %w", rowErr,
)
+9 -6
View File
@@ -987,11 +987,12 @@ func TestGetOperCount(t *testing.T) {
sid2, _, _, err := database.CreateSession(
ctx, "user2", "", "", "",
)
_ = sid2
if err != nil {
t.Fatal(err)
}
_ = sid2
// Initially zero opers.
count, err := database.GetOperCount(ctx)
if err != nil {
@@ -1023,23 +1024,25 @@ func TestGetOperCount(t *testing.T) {
func TestWildcardMatch(t *testing.T) {
t.Parallel()
const hostmask = "nick!user@host"
tests := []struct {
pattern string
input string
match bool
}{
{"*!*@*", "nick!user@host", true},
{"*!*@*", hostmask, true},
{"*!*@*.example.com", "nick!user@foo.example.com", true},
{"*!*@*.example.com", "nick!user@other.net", false},
{"badnick!*@*", "badnick!user@host", true},
{"badnick!*@*", "goodnick!user@host", false},
{"nick!user@host", "nick!user@host", true},
{"nick!user@host", "nick!user@other", false},
{hostmask, hostmask, true},
{hostmask, "nick!user@other", false},
{"*", "anything", true},
{"?ick!*@*", "nick!user@host", true},
{"?ick!*@*", hostmask, true},
{"?ick!*@*", "nn!user@host", false},
// Case-insensitive.
{"Nick!*@*", "nick!user@host", true},
{"Nick!*@*", hostmask, true},
}
for _, tc := range tests {