Four root causes blocked the CI test gate; all fixed minimally:
1. test_release_provider._allow_private_urls used setenv +
importlib.reload(ssrf_mod). The reload permanently rebound
_ALLOW_PRIVATE=True in the module; monkeypatch.setenv undid the
env var on teardown but the module attribute stayed True for the
rest of the session, masking every test_ssrf*/test_ssrf_hardening
case (16 failures). Switched to monkeypatch.setattr on the module
attribute directly — restored cleanly on teardown.
2. _FakeResponse in test_release_provider lacked the content_length
attribute and a top-level read() method that the new size-cap
guards in gitea.py consult before parsing (5 failures).
3. test_gate_quiet_hours_wins_over_event_type_flag was asserting the
pre-refactor gate order. evaluate_event_gate now intentionally
reports EVENT_TYPE_DISABLED before QUIET_HOURS so deferrable
events with the event-type flag off get dropped immediately
instead of being deferred and then silently discarded at drain
time. Renamed the test and inverted the expectation.
4. resolve_version() returned 0.0.0+unknown in CI because
pip-wheel-built hatchling distributions ended up with METADATA
missing the Version field — importlib.metadata returned None.
Added __version__ = "0.8.1" to notify_bridge_server/__init__.py
as a third (always-available) candidate; resolve_version() now
picks the max of (installed, package, source).
- Defer quiet-hours dispatches into new deferred_dispatch table; drain
job + periodic catch-up scan re-fire at window end with coalescing on
(link, event_type, collection_id).
- Add ON DELETE SET NULL migration on event_log_id and partial unique
index on (link_id, collection_id, event_type) WHERE status='pending'.
- Add release-check provider abstraction (Gitea/GitHub) with SSRF-safe
URL validation, settings UI cassette, and scheduled polling.
- Replace importlib-only version lookup with version.py helper that
prefers the higher of installed metadata vs source pyproject so stale
editable dev installs stop misreporting.
- Aurora frontend polish: MetaStrip component, ReleaseCassette,
EventDetailModal expansion, and i18n additions.