Files
takeone-youtube-clone/docs/audit-remediation-plan.md
T
ghassanandClaude Opus 4.7 56b6a83b34 docs: audit remediation plan (7 phases)
Checklist across security, performance/DOM, feeds/search/trending,
watch page, Shorts, channel/studio/live, and admin/a11y. Branch per
phase; backup tag backup/pre-audit-2026-10-21 at 5058eaf.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-10-21 00:33:10 +03:00

89 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# YouTube-parity audit remediation plan
Branch per phase. Feature tests per fix. STOP for approval between phases.
**Safety tag:** `backup/pre-audit-2026-10-21` at commit `5058eaf` on `full-screen-data`.
**Stashed WIP:** `stash@{0}` — pre-audit WIP on `full-screen-data` (recover with `git stash pop` on that branch).
---
## Phase 1 — Security & data integrity
Branch: `fix/phase-1-security`
- [ ] Wrap `sendEmailVerificationNotification` + `NewCommentNotification` mail in try/catch; move to a queued notification channel; log failures. Document `.env` for Gmail app password + Mailgun/Postmark fallback.
- [ ] `php artisan app:resend-verification {--user=}` command.
- [ ] Reserved-name blocklist (`admin`, `superadmin`, `takeone`, `support`, `root`, …) via `App\Rules\ReservedIdentifier` wired into `RegisteredUserController`.
- [ ] Harden login throttling to `5,1` with lockout message; log repeated failures and alert super admins.
- [ ] Confirm `email_verified_at` is not mass-assignable; only the signed-URL verification route flips it.
- [ ] Comment dedupe: raise 5s → 60s window, add client idempotency key header, server reject on duplicate. Disable submit button on first click.
- [ ] `php artisan comments:dedupe --dry-run` cleanup command.
- [ ] Owner-view exclusion in `VideoController@trackProgress`; dedupe by `device_hash` within 30 min.
- [ ] Feature tests for each item.
## Phase 2 — Performance & DOM
Branch: `fix/phase-2-perf`
- [ ] One shared `#globalEditModal` + `#globalCardMenu` per page; populated via `GET /videos/{id}/edit-payload`. Owner-only items gated server-side.
- [ ] Lazy-render reply/edit boxes (template clone on open).
- [ ] Match highlights panel rendered once.
- [ ] `href="javascript:void(0)"` → real `<button>` elements. Hide "Not interested" / "Don't recommend" / "Report" on own videos.
- [ ] Cursor pagination (`?cursor=`) across Home, `/videos` filters, channel Videos, search, history, liked, comments.
- [ ] IntersectionObserver infinite scroll + "Load more" fallback.
- [ ] `loading="lazy"`, explicit `width`/`height`, skeleton placeholders on thumbnails.
## Phase 3 — Feeds, search, trending
Branch: `fix/phase-3-feeds`
- [ ] Music + filter feeds switch to `latest()`.
- [ ] Trending windows: 24 / 168 / 720 h; rank by in-window views.
- [ ] Channel Popular: order by views, tiebreak by likes.
- [ ] Duration badge on card thumbnail. Scoreboard thumb → `<img>` or `aria-hidden`. Strip `CLUBLOGO` / `FLAG` placeholders.
- [ ] Filter tabs: fetch + `pushState`, sticky, `aria-current`.
- [ ] Normalize naming (DB stays `match`, display label "Sports" everywhere).
- [ ] "New to You" → "Recent" (or make personalized).
- [ ] New `SearchController` with `/search?q=` matching title/description/tags/language/channel; include channels + playlists. `/videos/search` becomes 302 redirect. Keep query in input. Merge the two duplicate search forms.
- [ ] `/feed/subscriptions` route backed by `subscriptions` table.
## Phase 4 — Watch page
Branch: `fix/phase-4-watch`
- [ ] Up Next: real `<a href>` cards. Recommender by type/tags/language, cross-channel. Tabs All / From this channel / Same type. Show more.
- [ ] Unified player wrapper for match/music/generic: theater (t), mini (i), PiP, volume slider, captions=lyrics (c), 2x speed, end screen, autoplay countdown. Autoplay-ON forces Loop-OFF.
- [ ] Like count visible, dislike button, Subscribe for guests, viewer `⋯` → Report. Channel row on match videos.
- [ ] `/videos/{id}/download/{format}` signed route; enforce per-video Downloads setting (Off/Everyone/Members/Subscribers) server-side for MP4 **and** MP3.
- [ ] Comments: `?lc=` permalink with scroll + highlight. Heart + pin (creator). "Read more" clamp. @handle prefill on nested reply. Singular/plural counts. Top-level vs reply counts separate.
- [ ] Markdown rendered (or stripped) in descriptions.
- [ ] Dedupe audio Language menu.
- [ ] Hide "Generating lyrics…" overlay unless job active.
- [ ] Edit form prefilled with real values (fix "Generic" / "Loading…" defaults).
- [ ] Streaming: HLS exists (`GenerateHlsJob`, `/videos/{video}/hls/{file}`). Switch player to hls.js when `hls_path` set. Verify `-movflags +faststart` on mp4 encode in `CompressVideoJob`. Add `Cache-Control` + Range on stream route.
## Phase 5 — Shorts
Branch: `fix/phase-5-shorts`
- [ ] Upload flag + auto-detect (vertical, ≤60s).
- [ ] `/shorts/{id}` route + branded 404 at `resources/views/errors/404.blade.php`.
- [ ] `/shorts` feed: 100dvh snap container, single reused `<video>` moved between slots, next 1–2 preloaded, URL via `history.replaceState`, wheel + arrows + swipe + ▲▼. Loop. Muted autoplay + "Tap to unmute"; unmuted state in `localStorage`.
- [ ] Right action column (like/dislike/comments/share). Bottom overlay (avatar/@handle/Subscribe/title). Comments side panel desktop / bottom sheet mobile.
- [ ] Home Shorts shelf. Channel Shorts tab (fix "My Shorts").
## Phase 6 — Channel / Studio / Live
Branch: `fix/phase-6-channel-studio-live`
- [ ] `users.handle` migration (unique, nullable → backfill → required). `/@handle` routes. Tabs `/@handle/{videos,shorts,playlists,posts,about}`. "Preview as visitor" toggle. Header shows description + links. Age/gender/horoscope private by default. Pluralize "1 video"; drop stray "· 0.0" on playlist cards.
- [ ] `/studio/*`: content table + bulk edit, per-video analytics, two-step upload (Details → Visibility: tags + playlist + schedule), file-size + duration + processing-status surfaced.
- [ ] Live: ended state → "Stream ended" + duration + recording (never "Waiting"). Live chat. Like / share / subscribe on viewer page. Channel name link. Private option on `/live/new` matching upload wording.
## Phase 7 — Admin, a11y, consistency
Branch: `fix/phase-7-admin-a11y`
- [ ] Rename "Live Videos" → "Ready". Storage counts NAS (via `NasSyncService`). Fix KPI WoW %. Strip HTML in description excerpts. Full titles with tooltip. Next/Last pagination on Audit Logs, Users, Videos. Error log viewer groups by stack trace in natural order.
- [ ] A11y: `aria-label` on every icon button (menu, search, voice, avatar, ⋯, Like-active, comment menus, seek slider with value text). Skip-to-content link. One `<h1>` per page. `label[for]` on all inputs. Remove duplicate "Prefer not to say". Birth year 13+ cap.
- [ ] Title helper `{page} | Play`. Brand: **Play** displayed; `TAKEONE` stays as `config('app.name')` per CLAUDE.md.
- [ ] Cleanup commands (all `--dry-run` first): `comments:dedupe`, `live:cleanup-test`, `tracks:dedupe`.
## Final deliverables
- Checklist: done / partial / skipped (with reason).
- `.env` keys the user must set.
- Deploy steps: migrations, queue restart, cache clear, asset build.