2026-04-30 14:18:23 +00:00
# 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 ](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:
```lua
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:**
1. Audit чи щось з цього reference'ed у живому layout/modules
2. Unreferenced → видалити
3. 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; з typo `bogolink` на 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 + sed
- `sync.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 ](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 ](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.
---
Document granular hook policy + ad architecture + 94-site scale
Hook redesign (guard-readonly.sh + guard-bash.sh):
- ALLOW edits: /home/nosfortube/frontend_<port>/ (digits-only, all subdirs)
+ /home/nosfortube/orest/ (user working zone + screenshots)
- DENY: lang variants (frontend_<port>_<lang>/), frontend_core/, .git/,
system paths (/etc/, /usr/, /boot/, /var/* except /var/log/claude/)
- 19/19 readonly + 18/19 bash tests pass (1 pre-existing sed-i regex gap)
- Backup попередньої версії: .bak.2026-05-02
Doc updates:
- New: PROJECT.md, ARCHITECTURE.md, DEPLOY.md, ADS.md, PERFORMANCE.md,
INTERLINKING.md, ADMINS.md (topic-split docs/)
- CLAUDE.md: 94-site scale, granular edit zones, doc index
- INFRASTRUCTURE.md: hook table updated
- SITES.md: scope note (14 backup-tracked of 94 total)
- RECOMMENDATIONS.md: W1 (hook conflict) → DONE; W2-W3, D1-D4 added
Site architecture findings (audit 2026-05-02):
- 94 frontend_<port>/ sites, 71 in site-name-routing.csv, 14 backup-tracked
- 3 ad-architectures coexist: 8148 modern bundle (1), modern partials (~23),
legacy inline surstrom (31)
- 8148 unique: ad-bundle.min.js source files, build-ad-bundle.sh, terser
- Server IP 185.73.222.75 у t1.* allowlist (curl probes work)
- CDN: custom + Cloudflare на 8081 etc; purge-cache при prod deploy
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 13:26:25 +00:00
## 🛠 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_<port>/ 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 ](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 ](ADS.md#open-questions-for-developer ) 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 ](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 ](ADS.md#template-integration )
**What:** 1 sample template fragment з ad-zone для розуміння placement pattern.
**Effort:** XS (показати 5-10 рядків з template)
**Status:** OPEN.
---
2026-04-30 14:18:23 +00:00
## Reminders cadence
goboss перевіряє цей файл **на початку кожної session ** і нагадує developer-у :
- Скільки items OPEN (по severity)
- Що було додано з минулої session
- Найдешевші items (XS-S) — пропонувати спершу
- Найпріоритетніші (HIGH) — окремо помічати
Items з статусом `DONE` , `WONTFIX` , `DEFERRED` переходять у footer цього файлу (history), щоб не плутатися з активним backlog.
---
## DONE / WONTFIX / DEFERRED
*(порожньо — поки нічого не виконано)*
---
Document granular hook policy + ad architecture + 94-site scale
Hook redesign (guard-readonly.sh + guard-bash.sh):
- ALLOW edits: /home/nosfortube/frontend_<port>/ (digits-only, all subdirs)
+ /home/nosfortube/orest/ (user working zone + screenshots)
- DENY: lang variants (frontend_<port>_<lang>/), frontend_core/, .git/,
system paths (/etc/, /usr/, /boot/, /var/* except /var/log/claude/)
- 19/19 readonly + 18/19 bash tests pass (1 pre-existing sed-i regex gap)
- Backup попередньої версії: .bak.2026-05-02
Doc updates:
- New: PROJECT.md, ARCHITECTURE.md, DEPLOY.md, ADS.md, PERFORMANCE.md,
INTERLINKING.md, ADMINS.md (topic-split docs/)
- CLAUDE.md: 94-site scale, granular edit zones, doc index
- INFRASTRUCTURE.md: hook table updated
- SITES.md: scope note (14 backup-tracked of 94 total)
- RECOMMENDATIONS.md: W1 (hook conflict) → DONE; W2-W3, D1-D4 added
Site architecture findings (audit 2026-05-02):
- 94 frontend_<port>/ sites, 71 in site-name-routing.csv, 14 backup-tracked
- 3 ad-architectures coexist: 8148 modern bundle (1), modern partials (~23),
legacy inline surstrom (31)
- 8148 unique: ad-bundle.min.js source files, build-ad-bundle.sh, terser
- Server IP 185.73.222.75 у t1.* allowlist (curl probes work)
- CDN: custom + Cloudflare на 8081 etc; purge-cache при prod deploy
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 13:26:25 +00:00
*Last update: 2026-05-01 (W1-W3 workflow + D1-D4 doc items added).*
*Initial backlog: 2026-04-30 (gocc1+2+3+4 audits).*
2026-05-05 13:20:00 +00:00
## 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.lua` line 2408-2409 використовує `archive_video_dir` для URL formation
**Fix per site (13 sites — крім 8161 яке by design strip):**
```lua
-- 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:**
```bash
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.
2026-05-05 13:42:19 +00:00
## 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.
2026-05-05 13:55:54 +00:00
**Scope:** 20 sites confirmed: 8140, 8141, 8142, 8145, 8148, 8149, 8151, 8152, 8153, 8154, 8155, 8156, 8157, 8158, 8159, 8160, 8161, 8162, 8163, 8150 (weird). Different `getLinks()` implementations у `lib/<port>/content.lua` .
2026-05-05 13:42:19 +00:00
**Fix (backend dev task):**
- Identify які content.lua versions мають regression.
- Patch `getLinks()` to return `cur_canonical=""` when `canonical_without_archive=1` AND 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.