20 KiB
tubev — Recommendations Backlog
⚠️ Це РЕКОМЕНДАЦІЇ, не PLANS. Кожен пункт виявлено через audit (gocc1+2+3+4 на 2026-04-30) і чекає developer-go перед виконанням. goboss періодично нагадує про unprocessed items на session start.
Типи: REFACTOR (структурна зміна без зміни поведінки) / CLEANUP (видалення dead code) / BUG (неправильна поведінка) / FEATURE (нове). Деталі: REFACTOR_RULES.md.
🚨 HIGH severity — Security
S1. SRI / integrity для third-party JS (BUG/FEATURE)
Where: layout*.etlua усіх 14 сайтів
Files: ajax.googleapis.com/.../jquery.min.js, cdn.jsdelivr.net/...flatpickr/pikaday, verifycdn.agego.com/v1/verify.js, https://a5.g--o.info, https://t1.tubev.sex/static/js/{interdata.min,sync}.js
Why: Compromise CDN → arbitrary JS у браузері користувача. Особливо agego.com, g--o.info — third-party без вашого контролю.
What: pin-version + integrity="sha384-..." для кожного CDN script ABO self-host.
Effort: M (2-4h per site, batch'ами)
Status: OPEN. Чекає developer-go.
S2. Origin audit obfuscated JS (BUG)
Where: 10+ файлів random-name JS, не у sync.sh
Files: c24c4cd9.js, N7Ym4F.js, popa.js, f4T4s.js, gD0A3.js, qDap9.js, mo.js, aOKM9.js, 9qFdXQ7.js, gk5LT.js, PxqbeCb.js, k3KL5.js
Sites: 8084, 8085, 8102, 8107, 8112, 8126, 8131
Why: Підозріло на adblock-bypass payloads ABO malicious drop. Нема git track, нема sync.sh entry, обфусковані імена.
What: Audit походження. Якщо ваші → перейменувати + покласти у sync.sh + git track. Якщо невідомі → видалити після перевірки що active loading не залежить.
Effort: S (1-2h)
Status: OPEN. Питання до developer: ваші чи невідомі?
🟡 MEDIUM severity
M1. 8112 — два GA properties в одному gtag (BUG)
Where: backup_8112/views/modules/ga/ga.etlua
Why: gtag config містить одночасно G-CQN2KFSXSG і G-WW50B2EGSJ → дані пишуться на 2 property. Imовірний bug — не сумісно з legitimate analytics workflow.
What: Підтвердити з developer який ID правильний. Видалити інший.
Effort: XS (15 min)
Status: OPEN. Питання до developer.
M2. site_domain / GA ID / CDN host → config (REFACTOR)
Where: layout/header .etlua всіх 14 сайтів
Why: Site domain hardcoded у CSP form-action, preconnect, partner logo links. GA IDs hardcoded. CDN hosts hardcoded. Зараз — по N літералів у кожному layout. Drift-prone.
What: Створити views/config/site.lua (або еквівалент Lua module) з constants:
return {
domain = "hdsexvideo.xxx",
ga_id = "G-CQN2KFSXSG",
cdn_pic = "cdn-pic.hdsexvideo.xxx",
cdn_video = "...",
partners = { "fulltube.xxx", "nu-bay.com", ... },
}
Layout uses <%= site.domain %>, <%= site.ga_id %>.
Effort: M (4-6h)
Status: OPEN.
M3. CSP — meta → HTTP header (REFACTOR)
Where: layout*.etlua з <meta http-equiv="Content-Security-Policy" ...>
Why: meta-CSP не може встановити frame-ancestors / report-uri, повільніший за HTTP header. Зараз 8084 (та інші) використовують meta.
What: Перенести у nginx config. Може треба developer-side change бо nginx config не наш scope.
Effort: S frontend-side / depends backend
Status: OPEN. Залежить від developer.
M4. modules/video.etlua → shared partial (REFACTOR)
Where: views/modules/video.etlua × 14/14 сайтів
Why: 67-77% common lines, найвища similarity з усіх модулів. 14 окремих копій що data-loop ідентичний, але class names + tweaks per site.
What:
- Extract base partial з
<%= include 'modules/video_base' %> - Per-site theme = CSS overrides (не template fork)
- Shared params:
<%= video, css_class, lazy_load %>Effort: M (4-6h) Status: OPEN. Найбільший SSOT win з усіх refactor candidates.
M5. 8081 layout split (REFACTOR)
Where: backup_8081/views/layout.etlua (1223 рядки monolithом)
Why: Outlier. Median решти ~200 рядків. Усі profile_*.etlua унікальні тут — 8081 has different architecture (NL agego, premium fork).
What: Розбити на partials аналогічно іншим 13 сайтам (header.etlua + footer.etlua + bottom_block.etlua + main.etlua).
Effort: L (8-12h, ПІСЛЯ M4 — щоб 8081 теж пристосувався до shared video partial)
Status: OPEN. Залежність: M4.
M6. 8112 static/ duplicate tree (CLEANUP/REFACTOR)
Where: backup_8112/static/{js,css,img,jsplayer,player,trade-th,tmp} ↔ backup_8112/views/static/...
Why: Дві ідентичні копії (md5-confirmed). Один live, інший stale.
What: З'ясувати який referenced (читай OpenResty config якщо доступно, або питай developer). Видалити інший.
Effort: M (2-4h, потребує OpenResty config check)
Status: OPEN. Питання до developer.
M7. 8085 submodule drift (BUG)
Where: backup_8085/views/static/js/lib
Why: Modified submodule reference (m у git status). Submodule гілка drift'нула від трекованого коміту. Або локальний edit, або prod оновив submodule а tracking — ні.
What: З'ясувати з developer: rollback або commit поточний state.
Effort: XS (15 min)
Status: OPEN. Питання до developer.
M8. 8086 sync drift — 30+ legacy файлів (CLEANUP)
Where: backup_8086/views/
Why: Sync.sh селективно копіює ~25 файлів, але диск містить ~30+ legacy не у sync.sh: asdadsasd.html, layout_bak_25-05-18.etlua, id_index_copy_with_cjannels.etlua, del___search_top.etlua, header_with_country_if.etlua, layout_copy_withads.etlua, plus 24+ модулів.
What:
- Audit чи щось з цього reference'ed у живому layout/modules
- Unreferenced → видалити
- Sync 8086 на rsync-парадигму (Group A) —
--deleteзачистить решту Effort: S (1-2h) Status: OPEN.
M9. 8112 untracked drift (CLEANUP/BUG)
Where: backup_8112/{rotator/,lib/,nginx.conf,nginx.conf.compiled,redirect_*.nginx}
Why: Untracked у git, але присутні на disk. rotator/ має 40+ файлів 1_<lang>.txt (i18n) + cats.txt symlink → /home/nosfortube/frontend_8112/rotator/data/cats.txt. backup mirror'ить prod app structure частково.
What: Or:
- Додати у sync.sh + git track (якщо потрібно у backup)
- Виключити (
gitignore+ не sync) (якщо не потрібно) Effort: S (1h) Status: OPEN. Питання до developer.
🟢 LOW severity / cleanup
C1. Видалити DEL_* tombstones (CLEANUP)
Where: 24 файли × 6 сайтів
Files: DEL_channel_id.etlua, DEL_friend_list.etlua, DEL_lang.etlua, DEL_lang_mob.etlua
Sites: 8100, 8102, 8107, 8112, 8131, 8133
Why: Префікс DEL_ явно signals tombstone, але файли досі живуть. Шум grep-у, ризик випадкового деплою.
Effort: XS (15 min)
Status: OPEN.
C2. Видалити backup-via-rename артефакти (CLEANUP)
Where: ~30 файлів з пробілами / " copy" / "with ads" / "without ads" / "with titles" Files: Окремі категорії:
header copy bongo link 25_10_22.etlua× 5 сайтів (8084, 8085, 8112, 8126, 8131; з typobogolinkна 8112)id_index copy_ads_actual.etlua× 2 (8084, 8085)cat_list_thumb with ads.etlua× 10 (8112)* with titles.etlua× 5 (8100)untitled file× 2 (8126)my copy.js,machine copy.js, etc. × 8 Why: File names з пробілами ламають shell scripts. Версії повинні бути у git. Effort: S (1h) Status: OPEN.
C3. Видалити legacy *_old/ dirs (CLEANUP)
Where: backup_8085/views/static/{js_old/,img_old/} (6+25 файлів)
Why: "_old" — explicit legacy marker.
Verification: grep -rn "js_old\|img_old" backup_8085/ → 0 матчів = safe to delete.
Effort: XS (30 min)
Status: OPEN.
C4. Видалити legacy UA-* GA (CLEANUP)
Where: views/modules/ga/ga.etlua, static/js/ga.js, layout-orig.etlua
Sites: 8081, 8086, 8100, 8112, 8126
Why: Universal Analytics EOL 2023-07-01. UA-* IDs не shipping data, але збільшують attack surface (extra script tag) і гасять performance.
Files з UA-: UA-128492434-7, UA-109631925-*, UA-105546426-7 (7 унікальних)
Effort: XS (30 min)
Status: OPEN.
C5. Видалити paginator_old / video_test варіанти (CLEANUP)
Where: views/modules/
Sites: 8084 і 8085
Files: paginator_old.etlua, cat_list_thumb_test.etlua, cat_index_test.etlua, main_list_test.etlua, video_test.etlua, counters.min.test.js (8133)
Why: Tests / older versions у prod tree.
Effort: XS (15 min)
Status: OPEN.
C6. Уніфікувати sync.sh на rsync (REFACTOR)
Where: 7 selective sites: 8081, 8086, 8112, 8120, 8129, 8133, 8148
Why: 7 з 14 уже на ідентичному rsync template (74a6acb…). 7 інших роблять те саме через ad-hoc whitelists. Drift-magnet, важко synced модулі для нових сайтів.
What: Замінити selective cp allowlists на 12-line rsync template. Виняток — 8148 build-step (виносити окремо в build.sh).
Effort: S (1h)
Status: OPEN.
C7. 8148 — винести build з sync.sh (REFACTOR)
Where: backup_8148/sync.sh (виконує sed -i MUTATION на prod source)
Why: sync.sh не повинен мутувати джерело. Build step і sync — різні concerns.
What:
build.shробить ad-bundle build + md5 + sedsync.shробить тільки rsync mirror- Pipeline:
build.sh && sync.sh— explicit ordering Effort: S (1h) Status: OPEN.
C8. Naming convention enforcement (FEATURE/REFACTOR)
Where: Pre-commit hook (per-repo) ABO server-side guard Why: Запобігти повторного появи pробілів у file names, " copy", DEL_, _test, obfuscated random names. Інакше backlog буде відновлюватися. What:
- Pre-commit script blocks:
[ a-zA-Z0-9_./-]чорний список (тільки лат+цифри+_./-) - Block
^DEL_,*test*у production paths - Document у docs/NAMING.md (TODO P4) Effort: S (1h script + 1h documentation) Status: OPEN.
C9. Min/non-min JS policy (REFACTOR)
Where: c2.{js,min.js}, main.{js,min.js}, my.{js,min.js}, jquery-3.2.1.{js,min.js} etc.
Why: Production = тільки .min.js. Dev = source. Зараз обидва у репо — шумно.
What: Pre-commit minifier ABO build-step pipeline. Source у src/, minified у static/js/.
Effort: M (3-5h, build pipeline)
Status: OPEN. Потенційно потребує developer-side build infrastructure.
C10. CSS file naming standardization (REFACTOR)
Where: 8084 (no views/css/ folder), 8086 (styles.etlua instead of css_<page>.etlua), 8148 (no folder)
Why: 11/14 use css_<page>.etlua pattern → решта 3 не вписуються.
What: Привести 8084/8086/8148 до css_<page>.etlua convention. Якщо вони мають окрему причину (8148 — sprite-driven, не split per page) — задокументувати у SITES.md виняток.
Effort: S (1-2h)
Status: OPEN.
C11. Cross-site partner logos через config (REFACTOR)
Where: header*.etlua, layout footer-блоки 7 сайтів
Sites: 8084, 8085, 8086, 8100, 8102, 8126, 8131
Why: Hardlinks на партнерські сайти (fulltube.xxx, hdsexvideo.xxx, nu-bay.com, gaypornhd.xxx, xxxtube1.com, fullhdxxx.com, maturesexmovies.xxx) — кожен layout має свої literals.
What: Винести у views/config/partners.lua як array. Layout iterates.
Effort: S (1-2h, після M2 site.lua)
Status: OPEN. Залежність: M2.
🛠 INFRASTRUCTURE / Workflow
W1. Hook conflict — Claude editing у /home/nosfortube/ (BUG/FEATURE) ✅ DONE 2026-05-02
Resolution: Granular policy реалізована у guard-readonly.sh + guard-bash.sh. ALLOW frontend_<port>/ (digits-only) + orest/. DENY lang variants, frontend_core, .git, system paths. Backup попередніх hooks: .bak.2026-05-02. Test matrix: 19/19 readonly + 18/19 bash (1 pre-existing sed-i regex limitation).
W2. backup_/ scope — 14 із 94 сайтів (FEATURE)
Where: /home/w4/backup_*/
Problem: git-tracking покриває 14 сайтів, інші 80 без recovery. Можливі причини: історичний субсет / pilot / залишки старого етапу.
Options:
- Зберегти 14 (subset для критичних сайтів)
- Поширити на всі 94 (масовий setup
sync.sh+ initial commits) - Замінити на централізований моніторинг + adminskий git Effort: L якщо поширити (ініт repos + sync.sh per site + перші commits). Status: OPEN. Залежить від наскільки git-history важливий vs adminove ownership.
W3. PSI automonitoring (FEATURE)
Where: Future infra Problem: Поточний PSI check — manual через pagespeed.web.dev, не systematic. Регресії можуть бути непомічені до next ad-revenue падіння. What: PSI API + cron → daily snapshot + history db + alert при падінні. Або Lighthouse-CI на t1.* після deploy. Effort: M-L (setup ~6-12h) Status: DEFERRED (in-mind, не пріоритет — поки adspyglass dashboard як signal).
📚 DOC items
D1. ad-bundle source files location
Where: ADS.md § Source files
What: Знайти де живуть 5 source JS-файлів (ad-config.js, ad-core.js, ad-mute.js, vast-preroll.js, ad-bootstrap.js) — frontend_<port>/views/static/js/ чи shared. Записати у ADS.md.
Effort: XS (15 min, find /home/nosfortube/ -name 'ad-config.js')
Status: OPEN — потрібен hook resolution (W1) щоб дослідити.
D2. Mirror swap mechanism
Where: ADS.md § Open questions Q3 What: Зрозуміти як Адмін заміняє banned mirror — через ad-config.js mass replace, runtime config, чи інше. Записати у ADS.md. Effort: S (питання до developer + 1 example) Status: OPEN.
D3. CDN provider
Where: DEPLOY.md § Open questions What: Який CDN на prod (Cloudflare / BunnyCDN / Fastly / custom). Per-site або unified. Effort: XS (питання до developer) Status: OPEN.
D4. Template ad-zone pattern
Where: ADS.md § Template integration What: 1 sample template fragment з ad-zone для розуміння placement pattern. Effort: XS (показати 5-10 рядків з template) Status: OPEN.
Reminders cadence
goboss перевіряє цей файл на початку кожної session і нагадує developer-у:
- Скільки items OPEN (по severity)
- Що було додано з минулої session
- Найдешевші items (XS-S) — пропонувати спершу
- Найпріоритетніші (HIGH) — окремо помічати
Items з статусом DONE, WONTFIX, DEFERRED переходять у footer цього файлу (history), щоб не плутатися з активним backlog.
DONE / WONTFIX / DEFERRED
(порожньо — поки нічого не виконано)
Last update: 2026-05-01 (W1-W3 workflow + D1-D4 doc items added). Initial backlog: 2026-04-30 (gocc1+2+3+4 audits).
D-canonical-archive — Canonical points to /v/ instead of archive URL pattern (13 sites)
Зона: Backend (admin/dev) — потребує kor reboot.
Symptom: На archive routes (/v/arch/, /v-cache/, /v/stored/, etc. per CSV new-url-pattern) canonical link генерується як /v/<id>/... (standard) замість archive URL. Robots noindex,follow правильно set, але canonical не reflects archive.
Root cause: views/id_index.etlua line ~90 hardcodes /v/ у canonical generation. Frontend не має access до runtime URL (ngx.var.uri not accessible у etlua context, mysettings.cur_uri not set).
Reference (8161 has partial setup):
var.archive_video_dir = "/v-arch/"var.canonical_without_archive = 1— explicit strip → canonical = standard/v/(BY DESIGN для 8161)app.lualine 2408-2409 використовуєarchive_video_dirдля URL formation
Fix per site (13 sites — крім 8161 яке by design strip):
-- lib/<port>/var.lua
var.archive_video_dir = "<new-pattern-per-CSV>" -- e.g. "/v/arch/" для 8159
var.canonical_without_archive = 0 -- canonical KEEPS archive prefix
var.nofollow_on_archive = 1 -- if not already
Per CSV new-url-pattern column:
| Port | new-url-pattern |
|---|---|
| 8159 | /v/arch/ |
| 8163 | /v-cache/ |
| 8158 | /v/stored/ |
| 8151 | /v/old/ |
| 8160 | /v/storage/ |
| 8153 | /v/archive/ |
| 8154 | /v/unlisted/ |
| 8155 | /v/shelved/ |
| 8156 | /v/disabled/ |
| 8157 | /v/bin/ |
| 8162 | /v-storage/ |
| 8150 | /video/old/ |
| 8152 | /v/parked/ |
Plus subrouter.lua route registration якщо missing — verify each site handles archive route.
Verify post-deploy:
curl -sL "https://www.<domain>/<archive-pattern><id>/<slug>" | grep -oE 'rel="canonical" href="[^"]+"'
# Expected: href="https://www.<domain>/<archive-pattern><id>/<slug>" (canonical=archive URL)
Frontend template (id_index.etlua) можливо потребує adjustment коли backend exposes mysettings.cur_archive_path чи similar — depending on app.lua implementation.
Reported 2026-05-05 by user audit на 8159 → bug confirmed на ВСІХ 13 sites with archive routing setup.
D-canonical-archive-regression — REGRESSION у нових getLinks() (~20 sites)
Update 2026-05-05: Audit deeper показав що це regression, не intended config.
Reference (correct behavior — pre-batch sites):
- broxxx.com (8133), pornv.xxx (8120): same
var.canonical_without_archive=1, але archive route →getLinks()повертаєcur_canonical=""→ layout skip emit → no canonical on archive ✓ - Це matching intent variable name "canonical_without_archive" = "canonical видається без archive context, тобто на archive не emit-иться".
Bug (regression — newer sites):
- 8161, 8159, 8163, 8158, 8151, 8152, 8153, 8154, 8155, 8156, 8157, 8158, 8160, 8162, 8140, 8141, 8142, 8145, 8148, 8149: same config
=1, але archive route →cur_canonical=<standard URL stripped>→ canonical EMITS до /v/. - Це over-engineered — backend strips archive prefix замість returning empty.
Scope: ~20 sites with newer code version. Different getLinks() implementations у lib/<port>/content.lua.
Fix (backend dev task):
- Identify які content.lua versions мають regression.
- Patch
getLinks()to returncur_canonical=""whencanonical_without_archive=1AND archive route. - Match broxxx/pornv behavior (старий правильний reference).
- kor reboot per site.
Verify: після fix на archive URL — <link rel="canonical"> має бути absent (як у broxxx/pornv).
Reported 2026-05-05 by user audit. Frontend template OK — issue у getLinks() core return value.