fix(deferred): close backend correctness/efficiency tails from the hygiene sweep
Verified each deferred per-subsystem item against current source, then fixed the
real ones (tradeoffs left as-is, see siftlode-ops/CODE-HYGIENE.md closeout):
- search BUG-3: don't finalise shorts_probed on un-enriched stubs (enrichment
failure/omitted rows) — restores the scheduler's enriched_at guard so a real
Short can't leak into the feed and never get reclassified.
- downloads GC: 4th pass reaps orphaned errored, fileless, unreferenced assets
(they carry no TTL, so the expiry passes never cleared them).
- downloads B6: quota/edit errors now return a structured {code,reason,limit}
the trilingual client localises, instead of hardcoded English + dot-decimal GB.
- channels BB1: reset-backfill re-arms deep sync on every subscriber (bulk update)
instead of 404ing when the admin isn't personally subscribed.
- channels BB2: enrich the stub on BOTH the normal and "already exists" desync
path (nest the insert try inside the client `with`).
- channels CB3: drop the redundant second _discovery_rows read (identity-mapped
rows are already enriched; re-sort in Python for the title tie-break).
- playlists PC1: read the live playlist once in push() and share it with plan_push
+ push_playlist (halves read-quota, closes the second TOCTOU window).
- playlists PC2/PC5: batch the cover thumbnails in one window query (was N+1);
rename combines count+duration into one aggregate + a single cover lookup.
- messages MB2: get_thread only resolves a messageable partner OR one we already
share a thread with (closes the user-enumeration oracle).
- messages MB3: push a live unread-count to the user's other tabs after mark-read.
- messages MC4: list_conversations uses DISTINCT ON + grouped COUNT instead of
loading the whole message history into memory.
- config AB3: per-spec allow_empty so smtp_user/youtube_api_proxy can be blanked
to disable them rather than snapping back to the env default.
This commit is contained in:
parent
182dddf5ed
commit
4e80e2b39b
8 changed files with 205 additions and 102 deletions
|
|
@ -25,6 +25,7 @@ class ConfigSpec:
|
|||
secret: bool = False
|
||||
min: int | None = None
|
||||
max: int | None = None
|
||||
allow_empty: bool = False # str keys: a stored "" is an explicit empty value, not "unset"
|
||||
|
||||
|
||||
# Registry of DB-overridable keys. Add a key here + wire its read through get_*() to move it
|
||||
|
|
@ -33,7 +34,7 @@ SPECS: tuple[ConfigSpec, ...] = (
|
|||
# --- Email / SMTP (one logical group; the password is the only secret) ---
|
||||
ConfigSpec("smtp_host", "str", "email", "smtp_host"),
|
||||
ConfigSpec("smtp_port", "int", "email", "smtp_port", min=1, max=65535),
|
||||
ConfigSpec("smtp_user", "str", "email", "smtp_user"),
|
||||
ConfigSpec("smtp_user", "str", "email", "smtp_user", allow_empty=True),
|
||||
ConfigSpec("smtp_from", "str", "email", "smtp_from"),
|
||||
ConfigSpec("smtp_password", "str", "email", "smtp_password", secret=True),
|
||||
# --- Quota (shared YouTube Data API daily budget) ---
|
||||
|
|
@ -59,7 +60,7 @@ SPECS: tuple[ConfigSpec, ...] = (
|
|||
# --- YouTube Data API key (secret; optional — public reads prefer it over OAuth) ---
|
||||
ConfigSpec("youtube_api_key", "str", "youtube", "youtube_api_key", secret=True),
|
||||
# Optional egress proxy for YouTube API calls (fixed-IP host for an IP-restricted key).
|
||||
ConfigSpec("youtube_api_proxy", "str", "youtube", "youtube_api_proxy"),
|
||||
ConfigSpec("youtube_api_proxy", "str", "youtube", "youtube_api_proxy", allow_empty=True),
|
||||
# --- Google OAuth client (Sign in with Google; both encrypted, env fallback). Set from the
|
||||
# install wizard / Configuration page so no restart is needed when the creds change. ---
|
||||
ConfigSpec("google_client_id", "str", "google", "google_client_id", secret=True),
|
||||
|
|
@ -124,7 +125,12 @@ def get(db: Session, key: str):
|
|||
"""Effective value: the DB override (typed) if set, else the env/config default."""
|
||||
s = _BY_KEY[key]
|
||||
raw = _raw_override(db, key)
|
||||
if raw is None or raw == "":
|
||||
if raw is None:
|
||||
return _default(s)
|
||||
if raw == "" and not s.allow_empty:
|
||||
# For most keys an empty override means "fall back to the env default". Keys that opt
|
||||
# into allow_empty (e.g. smtp_user, youtube_api_proxy) treat "" as a real value — so an
|
||||
# admin can blank one to DISABLE it rather than being stuck with the env default.
|
||||
return _default(s)
|
||||
try:
|
||||
return _coerce(s, raw)
|
||||
|
|
@ -197,6 +203,7 @@ def describe(db: Session) -> dict:
|
|||
"min": s.min,
|
||||
"max": s.max,
|
||||
"is_set": is_set, # an override row exists
|
||||
"allow_empty": s.allow_empty, # if true, the UI stores "" rather than deleting the row
|
||||
}
|
||||
if s.secret:
|
||||
item["default_is_set"] = bool(_default(s))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue