fix: production-readiness hardening from full-codebase review

Apply six isolated, low-risk fixes surfaced by the parallel
production-readiness review (backend, frontend, security, perf,
UI/UX, bugs+features).

Backend
- Mask access_token in provider GET responses and drop it on edit
  when carrying the *** placeholder — fixes plaintext leak of HA
  long-lived tokens (security H-1). Centralized via
  PROVIDER_SECRET_FIELDS so all call sites stay in sync (C-5).
- Hold HA status-change tasks in a module-level set with a
  done_callback — asyncio.create_task only keeps weak refs and
  the task could be GC'd before its row was written (C-1).
- Roll back the request session in the Telegram-webhook catch-all
  so a handler exception cannot leak uncommitted writes into the
  next request (C-2).
- Bail before reading the 1 MiB webhook body when the Gitea
  provider has no secret configured or the request has no
  signature header. For the generic webhook with bearer_token
  auth, verify the Authorization header before the body read.
  Closes the pre-auth resource-exhaustion amplifier (C-3).

Frontend
- Add supportsAutoOrganize capability to ProviderDescriptor and
  consume it from RuleEditor instead of `provider.type !== 'immich'`,
  bringing the last action-rule editor under CLAUDE.md rule 8
  (no provider-type hardcoding in components).
- Snackbar: add role="region" + per-toast role/aria-live/aria-atomic
  so screen readers announce success/error toasts.
- Sidebar nav: add aria-current="page" on the active link so the
  active state has an accessible name.
- New snackbar.region key in en + ru (locale parity preserved).

Out of scope for this commit (tracked in .claude/reviews/README.md
ship-blocker list): secret encryption at rest, JWT cookie move,
Alembic adoption, webhook idempotency, deferred-dispatch crash
window, persisted Telegram update watermark, bridge_self counter
lock — each needs more than a mechanical edit.
This commit is contained in:
2026-05-22 22:47:20 +03:00
parent a20635a657
commit 2d59a5b994
12 changed files with 77 additions and 21 deletions
+4 -1
View File
@@ -32,12 +32,15 @@
</script>
{#if snacks.length > 0}
<div use:portal class="snackbar-container">
<div use:portal class="snackbar-container" role="region" aria-label={t('snackbar.region')}>
{#each snacks as snack (snack.id)}
<div
in:fly={{ y: 40, duration: 300 }}
out:fade={{ duration: 200 }}
class="snack-item"
role={snack.type === 'error' ? 'alert' : 'status'}
aria-live={snack.type === 'error' ? 'assertive' : 'polite'}
aria-atomic="true"
style="--snack-accent: {accentMap[snack.type]};"
>
<span class="snack-icon" style="color: {accentMap[snack.type]};">