When retain_recent_legal_suffix hits the else branch (tail has no user
messages), it takes a non-contiguous slice from the middle of the session.
enforce_file_cap incorrectly assumed dropped messages were always a prefix
(before[:dropped_count]), causing user messages to be both archived and
retained, and some messages to silently disappear.
Fix by having retain_recent_legal_suffix return the actual dropped message
list using identity-based diff, so enforce_file_cap no longer needs to
guess which messages were removed.
::ffff:127.0.0.1 and ::ffff:169.254.169.254 are IPv6Address objects
that match neither the IPv4 blocklists (127.0.0.0/8, 169.254.0.0/16)
nor the IPv6 ones (::1/128), allowing SSRF bypass via DNS responses
that return IPv6-mapped IPv4 addresses.
Add _normalize_addr() to convert ipv4_mapped IPv6 addresses to their
IPv4 form before blocklist/allowlist matching.
Remove the eager preloading of markdown/code-highlighting chunk at startup.
The markdown renderer will now only be loaded when actually needed to render content.
Skip inbound emails that come from the bot's own configured addresses so a mailbox wired to the same SMTP/IMAP account does not trigger infinite reply loops.
Rename the boolean flag in _sanitize_persisted_blocks and alias the imported helper so session persistence cannot crash with TypeError when truncation is enabled.