fix(e8): deep-review hardening + cut 0.73.0

Fixes from several multi-agent deep-review passes over the E8 feed-filtering &
channel-manager epic (S1-S4):
- feed_years buckets by UTC year to match the UTC-pinned year-filter bounds
- tag suggestions: examples ∩ subscribed (drop tagged-then-unsubscribed channels
  from the profile denominator); exclude hidden channels as suggestion targets
- channel manager: restore ghost chips + surface an error toast on a failed tag accept
- year filter: debounce the search term so the per-year facet doesn't refetch per keystroke
- channel tags: aria-label the "+N" overflow pills
- extract useTagSuggestions hook; add backend + hook tests (profile boundaries, cap,
  language exclusion, unsubscribed/hidden handling, UTC bucketing, bulk-accept)

Bump VERSION to 0.73.0 + release notes.
This commit is contained in:
2026-08-26 05:25:47 +02:00
parent 17f8885fb1
commit 7104767ff9
13 changed files with 519 additions and 70 deletions
+5 -1
View File
@@ -450,7 +450,11 @@ def feed_years(db: Session, user: User, **params) -> list[dict]:
**{**params, "published_after": None, "published_before": None, "max_age_days": None},
)
pub = base.with_only_columns(Video.published_at.label("pub")).subquery()
year = func.extract("year", pub.c.pub)
# Bucket by UTC year to stay in lockstep with the year filter's boundaries (published_after/before
# are pinned to UTC in filtered_query). published_at is timestamptz, so a bare extract('year', …)
# would use the DB session timezone and, on a non-UTC session, bucket a video near a year boundary
# into a different year than the filter includes — the count and the drill-down feed would disagree.
year = func.extract("year", func.timezone("UTC", pub.c.pub))
rows = db.execute(
select(year.label("y"), func.count()).group_by(year).order_by(year.desc())
).all()