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
# tubev — Deploy Flow
Як зміна потрапляє з робочого місця → у prod.
## Two-tier model
```
Edit /home/nosfortube/frontend_<port>/ ← work / source-of-truth
│
├──→ t1.<domain> ← test (instant, IP-allowlist)
│
└──→ admin panel "site/control" ← prod деплой per-site (юзер натискає)
а б о через Адміна ← для var.lua / нових файлів
│
└──→ <domain> ← live, з CDN
```
## Test environment — `t1.<domain>`
- **Доступ:** IP-allowlist (ймовірно nginx-level, не точно). Юзер заходить через VPN щоб мати стабільний IP.
- **Apply:** instant — змінив файл у `frontend_<port>/` → видно на t1.<domain> одразу.
- **Обмеження** (per-site різні): CDN off, compression off, повільніше, comments/ads можуть бути обмежені а б о тестові.
- **AI-side:** ✅ Claude з сервера **МАЄ доступ ** до t1.<domain> (server IP `185.73.222.75` у allowlist). Перевірено 2026-05-01: `curl -I https://t1.atube.sex` → 200 OK, `curl -I https://t1.hdsexvideo.xxx` → 200 OK. Можна робити HTTP probes для health-check, regression smoke, response inspection.
## Prod deploy — три шляхи
### A) Через admin panel "site control" (юзер сам, instant per-site)
`https://rss.g--o.info/admin/site/control` — список у с і х сайтів, кнопка викатати оновлення з тесту → прод.
**Покриває:** templates `.etlua` , CSS, JS (звичайні per-site файли).
**Н е покриває (потрібен Адмін):**
- `lib/<port>/var.lua` — нові/змінені змінні
- Нові файли (yet not in admin's git)
- Shared `views/static/js/lib/` , `lib2/` (cross-site impact)
### B) Через admin panels (settings / translations / sitemap)
Контент-шар, не код. Самостійно, без Адміна:
- Per-site settings: `https://<domain>/admin/index` , `/admin/settings`
- Languages set: `https://<domain>/moderation/languages/langs`
- Translations (UI strings): `https://<domain>/moderation/languages/translation/`
- Sitemap: `https://rss.g--o.info/admin/site`
Деталі: [ADMINS.md ](ADMINS.md ).
### C) Через Адміна (Орест / основний програміст)
- Нові файли потрапляють у Адмінів git → kor pull/reload
- `var.lua` зміни → kor reboot
- Mass operations (mirror swaps, multi-site fixes)
Trigger: попросити (чат / задача).
## kor reload
- `lib/<port>/var.lua` зміни → потрібен **kor reboot ** щоб env змінні підвантажилися
- Templates `.etlua` — підхоплюються hot (без reboot)
- Static assets — hot, але **CDN cache ** може тримати стару версію → потрібен **cache-bust ** (через `?v=<md5>` у layout — реалізовано у `~/git-save-all.sh` )
## CDN
- **Custom CDN** для більшості сайтів (наявний; провайдер невідомий поки)
- **Cloudflare** на двох сайтах (наприклад **8081 ** ) — додаткове edge кешування
- **При оновленні prod** для Cloudflare-сайтів: треба **purge cache ** + враховувати у логіці що зміни не миттєві (cache TTL до purge)
- Cache-bust через `?v=<md5>` у `layout.etlua` працює для о б о х (custom + CF)
2026-05-02 21:51:32 +00:00
### ⚠️ Stale-cache gotcha (custom CDN, 8148 confirmed 2026-05-02)
Custom CDN serve-ить різні `cache-control` залежно від виду query string:
| Pattern URL | s-maxage | Поведінка |
|-------------|----------|-----------|
| `?v=<hex-like-7-chars>` (md5 prefix) | **31536000 (1 рік) ** | "Content-addressed asset" — immutable, edge cache aggressive |
| `?v=<short>` (число, ZZZZ etc.) | 10 sec | Швидко refresh-иться |
| (no query) | ~ | Звичайний cache |
**Race condition при deploy:**
1. Template (layout.etlua) deploy-иться з новим `?v=<new_md5>` reference
2. До того як static (`ad-bundle.min.js` ) сам file deploy-иться — браузер/crawler hit-ить `<host>/ad-bundle.min.js?v=<new_md5>`
3. CDN cache-miss → origin ще має OLD bundle → CDN кешує OLD під новим `?v=` ключем
4. Static deploy-иться з NEW bundle, але **CDN cache stuck на 1 рік ** з OLD content
**Симптом:** `curl <host>/ad-bundle.min.js` → NEW. `curl <host>/ad-bundle.min.js?v=<deployed_md5>` → OLD. Live site поломаний.
**Рішення:**
- Bump bundle md5 (тривіальна зміна у source — додаткова line, build stamp): `git-save-all.sh` rebuilds → новий md5 → новий ?v= → нова cache entry → fresh
- А б о **purge CDN cache ** (через адмін / hostiserver)
- Краще довгостроково: змінити cache-bust scheme у `git-save-all.sh` щоб включав timestamp (`?v=<md5>-<unix>` ) → завжди унікально
Перевірка чи це сталося: `curl -sI <host>/<file>?v=<md5> | grep s-maxage` — якщо `31536000` , кеш заблокувався на рік.
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
## git-save-all.sh — git-snapshot для backup_<port>/
`~/git-save-all.sh "msg"` ітерує `/home/w4/backup_*/` :
1. * * `sync.sh` per backup** — копіює з prod (`/home/nosfortube/frontend_<port>/` ) у backup. **Tracked subset ** (whitelist у sync.sh): templates (`layout.etlua` , `id_index.etlua` , `video.etlua` , banner modules), ad orchestration JS (`ad-config.js` , `ad-core.js` , `vast-preroll.js` , `ad-bundle.min.js` ), player files, тести, robots.txt. Решта prod-коду — поза git.
2. **Auto-rebuild ad-bundle: ** якщо будь-який з 5 source JS (`ad-config.js` , `ad-core.js` , `ad-mute.js` , `vast-preroll.js` , `ad-bootstrap.js` ) новіший за `ad-bundle.min.js` → запуск `bash build-ad-bundle.sh` (terser concat+minify).
3. **Cache-bust: ** md5sum bundle → перші 7 hex → `sed -i ?v=...` у `views/layout.etlua` . Idempotent (однаковий контент = однаковий хеш).
4. **Commit per backup: ** message формат `YYYY-MM-DD_HH:MM - <msg> [backup_<port>]` . Кожен backup repo окремо — N changed sites = N commits у різних repos.
**Призначення:** git-tracking для recovery / audit / blame. **Н е deploy mechanism. **
## Open questions
- [ ] CDN — який провайдер (Cloudflare / BunnyCDN / Fastly)? Per-site чи unified?
- [ ] Backup_<port>/ покриття — чому 14 із 94 сайтів? Поширити чи це історичний субсет? (open-разом з юзером)
- [ ] Headless browser (Puppeteer / Playwright) на сервері для visual regression / ad-render check — варто setup-нути на потребу?