feat: follow upstream twtxt post rules: reject control characters, allow U+2028, make the length cap configurable

This commit is contained in:
randogoth 2026-10-15 13:59:39 +03:00
parent dd6865782a
commit 801c66d3b0
12 changed files with 63 additions and 58 deletions

View file

@ -42,6 +42,7 @@ poll_secs = 60 # fetch interval
timeout = 30 # smolmail network timeout, seconds
posts_per_day = 50 # per-feed daily quota
reposts_per_day = 50
max_post_chars = 288 # longest post, in characters (code points)
cap_bytes = 1048576 # per-feed size cap, default 1 MiB
registration = silent # open | closed | silent — see Admission
registrations_per_hour = 10 # global cap on attempts that reach the network
@ -162,7 +163,7 @@ One command per mail. Two of them together, or one mixed with another, is refuse
fumi send twtxt@smol.place --header Twt-Delete:2026-10-01T12:47:00Z --body ""
```
The rules the daemon enforces: text is at most 160 Unicode code points and 640 bytes and may not contain TAB, LF, CR or U+2028; the timestamp is the mail's own time, pinned by the signature, so a same-second resend is rejected with a reply — wait a second and resend; at 90% of the size cap the daemon mails a warning naming the cap and both prune modes. Error replies are subject to the address's rules: at most ten per sender per hour, never twice for the same rejected payload.
The rules the daemon enforces: text is at most `max_post_chars` characters (288 by default; twtxt itself sets no hard limit) and may not contain control characters such as TAB, LF or CR, as twtxt requires, while U+2028 is allowed as the Multiline extension's line break; the timestamp is the mail's own time, pinned by the signature, so a same-second resend is rejected with a reply — wait a second and resend; at 90% of the size cap the daemon mails a warning naming the cap and both prune modes. Error replies are subject to the address's rules: at most ten per sender per hour, never twice for the same rejected payload.
## What a feed looks like