Fixed
- Edit notifications no longer silently dropped on long messages — The 500-char truncation guard only protected
data["message"]["text"](new_message path), leavingdata["new_text"](edit path) unprotected. A 4096-char emoji edit could produce a 16KB payload exceeding PostgreSQL's 8KB NOTIFY limit, causing a silentpg_notifyerror. Both paths are now truncated via a shared_truncate_notify_data()helper. (#123 follow-up) - Use
pg_notify()with bound parameters for PostgreSQL NOTIFY — Replaces f-string SQL interpolation that was vulnerable to asyncpg$Nplaceholder parsing and fragile manual single-quote escaping. Contributed by @tondeaf in #123. - Push secret comparison is now timing-safe —
/internal/pushendpoint used!=for bearer token comparison; switched tosecrets.compare_digest()consistent with the rest of the auth layer. - Test assertions use stable
TextClause.textattribute — Replacedstr(stmt)withstmt.textfor SQLAlchemy SQL assertions, avoiding reliance on undocumented__str__behavior.
📋 Full changelog: docs/CHANGELOG.md