- Defer polling_service.start() and FilterEngine init to a one-shot
before_request hook so importing app.py no longer spawns a scheduler
thread (also fixes migrate_*.py import side effects).
- Fix migrate_bookmarks.py: init_db returns None, so use the shared
`db` instead of assigning its None return.
- Enforce MIN_PASSWORD_LENGTH (8) in the password-reset route for
consistency with signup (was hardcoded 6).
- post_detail.html: replace undefined moment(...).fromNow() (always
"Recently") with a new timeago Jinja filter + data-timestamp attrs
that also drive the existing JS updater; make nl2br escape-then-Markup
and drop | safe from comment/post content to close the XSS hole.
- filter_pipeline: when AI is disabled but a filterset requires it,
pass posts through with status=FAILED + explicit error instead of
silently degrading to no_filter.
No source-file mojibake found; content-encoding ingest is a Phase 3 concern.
Co-Authored-By: Claude <noreply@anthropic.com>