diff options
Diffstat (limited to 'AGENTS.md')
| -rw-r--r-- | AGENTS.md | 8 |
1 files changed, 6 insertions, 2 deletions
@@ -143,7 +143,7 @@ internal/web/ server.go (host router, middleware, render helpers) - **Hardening** (`web/ratelimit.go`): a per-key token bucket throttles the anonymous endpoints worth abusing — `loginLimit` on `POST /webadmin`, keyed by client address *and* by lowercased username (10 at once, then 10 a - minute each), answered with 429 by `s.throttle` and a log line; failed + minute each), `searchLimit` on `GET /search` per address — answered with 429 by `s.throttle` and a log line; failed logins are logged with the username and address, and the login body is capped at `maxLoginBody` (64 KB) since it is the one POST outside `guardPOST`. `s.clientIP` is the peer address, or the last @@ -481,7 +481,11 @@ internal/web/ server.go (host router, middleware, render helpers) are literal, case does not matter (`~*` / `(?is)`) and spaces mean "anything in between", in order. `SearchPublishedPosts` matches it against `title || '\n' || body_md` of published posts from every page, 20 per page - (`searchPerPage`); queries are cut at 100 runes. Results are title, date + (`searchPerPage`); queries are cut at 100 runes and 8 words + (`maxSearchWords`). The scan is unindexed, so the handler is throttled + per client address (`searchLimit`, 30 then 30 a minute) and the query + runs under `searchDeadline` (5 s): a timeout is logged and shown as no + results, not a 500. Results are title, date and `searchSnippet` (the Markdown around the first match, escaped, the match in `<mark>`; the body's start when only the title matched). A blank or unmatched query is a normal 200, not a 404; the pager is the page's |
