Files
admin/.tasks/STATUS.md
vitya c55cb11948 tasks: merge imported MoreThenCms task history with admin live agenda
- 7 admin per-task files moved from .tasks-imported/ to .tasks/ (renames)
- NEXT-SESSION-PROMPT.md (iis-migration session handoff) kept as sibling
- .tasks-imported/STATUS.md removed (content merged into admin STATUS.md)
- admin STATUS.md gains 'Imported from MoreThenCms' section with all 7 admin
  done tasks verbatim. 4 CMS-domain task blocks excluded (stay in MoreThenCms):
  cms-admin-assets-root-folders-seed, cms-port-leak-fix,
  traefik-maljarka-502-bug, cms-maljarka-https-mode-bug-fix
- morecms-subtree-split marked done (acceptance: 4 split branches exist with
  per-file history)
- admin-subtree-import-and-cleanup marked active (in-progress this session)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 13:51:48 +03:00

471 lines
41 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.
# Admin Task Board
_Updated: 2026-05-21_
<!--
Status legend:
🔴 Active — only one at a time
🟡 Paused — in progress, resumable
⚪ Ready — defined, not started
🟢 Done — kept until merged
🔵 Blocked — waiting on external input
-->
## 🟢 [admin-infra-project-pointers] — Bootstrap-pointers для design admin-infra-project. Pre-fills target's `.wiki/CLAUDE.md` Domain conventions ссылками на спецификацию. Дизайн не лежит в этом репо — только pointer-stub. Без этой таски следующий агент попадёт в дыру: where_stopped one-liner + пустой Domain conventions stub = угадывание порогов / pipeline-этапов вместо чтения готовых решений.
**Кто делает:** любой следующий агент в этом проекте. Это первая по приоритету таска промоушена — все остальные импл-таски ссылаются на pointers через .wiki/CLAUDE.md.
**Status:** done
**Closed:** 2026-05-21 — `.wiki/CLAUDE.md` Domain conventions заполнен design-context pointer-блоком (3 sources: `concepts/admin-infra-project.md`, archive `~/projects/.workshop/.archive/2026-05-21-admin-infra-project.md`, local `overview.md`). Unblocks migration chain.
**Where I stopped:** done
**Next action:** В `.wiki/CLAUDE.md` секции "Domain conventions" вставить блок (или заменить дефолтный setup-wiki stub):
### Mandatory: read design context before implementation
Before picking up any task in `.tasks/`, load the full design context. It does **not** live in this repo as a standalone source — only pointers do. Sources, in order:
1. **Local design (canonical):** `.wiki/concepts/admin-infra-project.md` — ingested via promote 2026-05-21. Identity, scope, content inventory, migration recipe (subtree-split + read-tree merge for populated prefixes), initial agenda.
2. **Brainstorm process trace (rationale):** `~/projects/.workshop/.archive/2026-05-21-admin-infra-project.md`. Why each decision was made (recommend vs menu trade-offs), what was rejected (filter-repo vs subtree-split, "admin-only" skills, splitting roadmap from ops), anti-patterns flagged during brainstorm.
3. **Local `overview.md`** — thin summary, quick orientation only — never the source of truth.
Do **not** invent migration recipes, file lists, taxonomies, or scope decisions from task `where_stopped` lines alone — those are pointers, not specifications. The concept doc and archive contain the rationale.
---
Закоммитить: `wiki(claude): add design-context pointers for admin-infra-project`.
**Branch:** n/a
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-05-21T10:21:59.082Z -->
---
## 🟢 [morecms-subtree-split] — Шаг 2 миграции: в `~/projects/MoreThenCms` создать 4 subtree-split ветки, каждая хранит per-file history своего dir'а. Эти ветки потом импортируются в admin (см. `admin-subtree-import-and-cleanup`).
См. `.wiki/concepts/admin-infra-project.md` §Migration mechanics шаг 2 для полного контекста.
**Status:** done
**Closed:** 2026-05-21 — 4 split branches созданы в `~/projects/MoreThenCms` (split-wiki-entities @24661c10, split-wiki-sources @a5e96432, split-wiki-concepts @c727aaa1, split-tasks @cbdc2b39). Acceptance: per-file history preserved (verified via subsequent subtree-add in admin). Не push'ились — служебные.
**Where I stopped:** (not started)
**Next action:** ```powershell
cd ~/projects/MoreThenCms
git subtree split --prefix=.wiki/entities -b split-wiki-entities
git subtree split --prefix=.wiki/sources -b split-wiki-sources
git subtree split --prefix=.wiki/concepts -b split-wiki-concepts
git subtree split --prefix=.tasks -b split-tasks
```
Acceptance: `git branch | grep split-` показывает 4 ветки. Каждая `git log split-<x>` содержит коммиты только относящиеся к соответствующему dir'у. **Не push'ить** эти ветки — они служебные, нужны только для local subtree-add в admin.
Done — пометить 🟢 + переходить к `admin-subtree-import-and-cleanup`.
**Branch:** n/a
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-05-21T10:22:50.307Z -->
---
## 🔴 [admin-subtree-import-and-cleanup] — Шаги 3-7 миграции: импорт 4 split-веток из MoreThenCms в admin (clean prefixes через `git subtree add`, populated prefixes — temp-prefix dance с `git subtree add` + `git mv` для history-preservation через merge-commit + rename; read-tree вариант spec'a отвергнут — не сохраняет parent-link к morecms history → `git log --follow` не доходит до morecms-era коммитов), cleanup CMS-следов из mixed splits, STATUS.md merge, index.md regen, push на Gitea.
Объединено в одну таску потому что: тот же agent, та же session, sequential steps без natural review-point между ними. См. `.wiki/concepts/admin-infra-project.md` §Migration mechanics шаги 3-7.
**Status:** active
**Where I stopped:** (not started)
**Next action:** **3a. Clean prefixes:**
```powershell
cd ~/projects/.admin
git remote add morecms ~/projects/MoreThenCms
git fetch morecms
git rm .wiki/entities/.gitkeep .wiki/sources/.gitkeep
git commit -m "prep: clear gitkeep before subtree import"
git subtree add --prefix=.wiki/entities morecms/split-wiki-entities
git subtree add --prefix=.wiki/sources morecms/split-wiki-sources
```
**3b. Mixed prefixes (`.wiki/concepts/` and `.tasks/` already have content):**
Preferred — `git read-tree` merge:
```powershell
git rm .wiki/concepts/.gitkeep
git commit -m "prep: clear concepts gitkeep before import"
git fetch morecms split-wiki-concepts
git read-tree --prefix=.wiki/concepts/ -u morecms/split-wiki-concepts
git commit -m "import: .wiki/concepts/ from MoreThenCms via subtree-split (history preserved via read-tree)"
git fetch morecms split-tasks
git read-tree --prefix=.tasks-imported/ -u morecms/split-tasks
git commit -m "import: .tasks/ from MoreThenCms via subtree-split (staged at .tasks-imported/)"
# Затем merge content with admin's existing STATUS.md (см. шаг 5).
```
Альтернатива при конфликтах — temp-prefix dance (`.tmp-concepts/`, `git mv`, `git rm -r .tmp-concepts`).
**4. Cleanup CMS-следов:**
```powershell
git rm .wiki/concepts/cms-admin-assets-root-folder-seed.md `
.wiki/concepts/cms-config-rewrite-pattern.md `
.wiki/concepts/cms-maljarka-https-mode-crash.md `
.wiki/concepts/cms-server-port-leak-fix.md `
.wiki/concepts/webconfig-password-xml-escape.md `
.tasks-imported/cms-admin-assets-root-folders-seed.md `
.tasks-imported/cms-admin-assets-root-folders-seed.inserted-rows.txt `
.tasks-imported/cms-maljarka-https-mode-bug-fix.md `
.tasks-imported/cms-port-leak-fix.md `
.tasks-imported/traefik-maljarka-502-bug.md
git commit -m "cleanup: drop CMS files imported via subtree (they stay in MoreThenCms)"
```
**5. STATUS.md merge:** скопировать non-CMS таски из `.tasks-imported/STATUS.md` в admin/.tasks/STATUS.md (сохраняя 🟢 done статусы); удалить `.tasks-imported/`; rename per-task files в `.tasks/`. Commit `tasks: merge imported MoreThenCms task history with admin live agenda`.
**6. index.md regen:** обновить `.wiki/index.md` чтобы catalog отражал импортированные entities/concepts/sources. Commit `wiki(index): refresh catalog after subtree import`.
**7. Push:** `git push origin master`.
Acceptance:
- `git log --follow .wiki/concepts/wd40efax-smr-cascade.md` показывает MoreThenCms-era коммиты (history preserved)
- `ls .wiki/entities/` содержит все 6 файлов
- `ls .wiki/concepts/` содержит 18 admin-domain + admin-infra-project (новый)
- `cat .tasks/STATUS.md` содержит и live agenda (pointers + impl + secrets + roadmap), и imported 🟢 done items
- Gitea web shows updated tree
Done — 🟢; unblock `morecms-cleanup-and-breadcrumb` + `resilience-roadmap-design`.
**Branch:** master
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-05-21T10:23:14.254Z -->
---
## 🔵 [morecms-cleanup-and-breadcrumb] — Шаги 8-10 миграции: в `~/projects/MoreThenCms` удалить мигрированные файлы (6 entities + 17 concepts + 3 sources + 7 tasks), обновить STATUS.md/index.md, добавить `.wiki/concepts/migrated-infra-to-admin.md` breadcrumb со списком «что куда уехало», push на Gitea.
См. `.wiki/concepts/admin-infra-project.md` §Migration mechanics шаги 8-10 + полный шаблон breadcrumb'а в §9.
**Очерёдность:** ТОЛЬКО после успешного push'а admin'а с импортированным контентом (`admin-subtree-import-and-cleanup` 🟢). Иначе риск удалить из MoreThenCms то что ещё не зафиксировано в admin.
**Status:** blocked
**Where I stopped:** (not started)
**Next action:** **8. Cleanup commit (drop migrated):**
```powershell
cd ~/projects/MoreThenCms
git rm .wiki/entities/* .wiki/sources/* `
.wiki/concepts/wd40efax-smr-cascade.md `
.wiki/concepts/hyper-backup-structure-and-recovery.md `
.wiki/concepts/vbox-windows-stability-tuning.md `
.wiki/concepts/mssql-container-data-restore.md `
.wiki/concepts/traefik-on-windows-docker-desktop.md `
.wiki/concepts/traefik-tcp-passthrough-vs-starttls.md `
.wiki/concepts/traefik-file-watch-wsl2-broken.md `
.wiki/concepts/docker-host-loopback-detect.md `
.wiki/concepts/compose-bcrypt-escape-trap.md `
.wiki/concepts/portainer-2.21-admin-password-regression.md `
.wiki/concepts/db-tls-self-signed-via-traefik-raw-tcp.md `
.wiki/concepts/rusonyx-vps-onboarding-quirks.md `
.wiki/concepts/registry-gc-mount-and-modify-flag.md `
.wiki/concepts/verdaccio-prune-semantics.md `
.wiki/concepts/recovery-architecture-snapshot.md `
.wiki/concepts/future-resilient-architecture-goals.md `
.wiki/concepts/iis-migration-2026-05-19-postmortem.md `
.tasks/vds-kzntsv-bootstrap.md .tasks/vds-gc-cron.md `
.tasks/vds-backup-rsync-kreknin.md .tasks/vds-ntfy-push.md `
.tasks/nas-recovery.md `
.tasks/iis-on-host-migration.md .tasks/iis-traefik-dead-routes-cleanup.md
```
Manually edit `.tasks/STATUS.md` — оставить только CMS-domain блоки (`cms-*`, `traefik-maljarka-502-bug`, `cms-maljarka-https-mode-bug-fix`). Manually edit `.wiki/index.md` — удалить мигрированные entries из catalog.
Commit: `migrate: drop infra content moved to OpeItcLoc03/admin (history preserved there via subtree split)`.
**9. Breadcrumb:** создать `.wiki/concepts/migrated-infra-to-admin.md` по шаблону в `.wiki/concepts/admin-infra-project.md` §9 (frontmatter + Migration table + "What stays here"). Также добавить запись в `.wiki/index.md` под Concepts.
Commit: `wiki(concepts): add migrated-infra-to-admin breadcrumb`.
**10. Push:** `git push origin master`.
Acceptance:
- `git log --oneline -3` в MoreThenCms показывает 2 cleanup-коммита поверх master
- `ls ~/projects/MoreThenCms/.wiki/entities/` пуст
- `ls ~/projects/MoreThenCms/.wiki/concepts/cms-*.md` показывает 4-5 CMS файлов (включая webconfig-password-xml-escape)
- Gitea web для MoreThenCms показывает обновлённую `.wiki/concepts/migrated-infra-to-admin.md`
Done — 🟢; unblock `verify-migration`.
**Blocker:** admin-subtree-import-and-cleanup
**Branch:** n/a
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-05-21T10:23:37.967Z -->
---
## 🔵 [verify-migration] — Шаг 11 миграции: end-to-end sanity check после migration push'ей. Подтвердить что projects-meta cache видит admin's tasks, knowledge_search находит migrated content, history preserved (`git log --follow`), и admin'ская архитектура целостная.
См. `.wiki/concepts/admin-infra-project.md` §Migration mechanics шаг 11.
**Status:** blocked
**Where I stopped:** (not started)
**Next action:** **Sync cache:**
```bash
node ~/projects/.common/lib/projects-meta-mcp/dist/sync.js
```
**Validation matrix:**
1. `mcp__projects-meta__tasks_aggregate project: "OpeItcLoc03/admin"` — должен вернуть все live admin tasks (`[admin-infra-project-pointers]`, impl-таски, `[resilience-roadmap-design]`, `[secrets-out-of-common]`, `[secrets-manager-adopt]`, review-umbrella).
2. `mcp__projects-meta__tasks_aggregate project: "OpeItcLoc03/MoreThenCms"`НЕ должна возвращать infra-таски (vds-*, nas-recovery, iis-*). Должна показывать только CMS-domain (`[cms-maljarka-https-mode-bug-fix]`).
3. `mcp__projects-meta__knowledge_search query: "WD40EFAX SMR cascade" domain: "all"` — должен находить `OpeItcLoc03/admin:.wiki/concepts/wd40efax-smr-cascade.md`.
4. `mcp__projects-meta__knowledge_search query: "migrated infra admin" domain: "all"` — должен находить MoreThenCms breadcrumb.
5. `cd ~/projects/.admin && git log --follow .wiki/concepts/wd40efax-smr-cascade.md` — показывает MoreThenCms-era коммиты (proof history preserved).
6. `cd ~/projects/MoreThenCms && git log -p .wiki/concepts/wd40efax-smr-cascade.md` — последний коммит = удаление (`migrate:` prefix).
7. Открыть `https://git.kzntsv.site/OpeItcLoc03/admin` в браузере — wiki/tasks visible.
**Findings**, если есть, — отдельные follow-up tasks через `mcp__projects-meta__tasks_create`.
Done — 🟢 с close-note типа `verified end-to-end: tasks+wiki visible in admin, MoreThenCms clean, history preserved`.
**Blocker:** morecms-cleanup-and-breadcrumb
**Branch:** n/a
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-05-21T10:23:54.407Z -->
---
## 🔵 [resilience-roadmap-design] — Развернуть placeholder `.wiki/concepts/future-resilient-architecture-goals.md` (мигрирует из MoreThenCms в `admin-subtree-import-and-cleanup`) в полноценный fault-tolerance roadmap. Естественная отправная точка для глобальной цели пользователя: «создать отказоустойчивое решение, чтобы такие проблемы как 2026-05-18 не повторялись».
Это **design task** (не impl): продукт — обновлённая `concepts/future-resilient-architecture-goals.md` + потенциально цепочка impl-тасок-children. См. `concepts/admin-infra-project.md` §Initial admin agenda E.1.
**Status:** blocked
**Where I stopped:** (not started)
**Next action:** Прочитать pointers (через `admin-infra-project-pointers`). Затем:
1. **Inputs read:** `concepts/recovery-architecture-snapshot.md` (текущее состояние request flow + SPOF list), `concepts/future-resilient-architecture-goals.md` (placeholder с rough goals), `entities/*` (что есть в стеке физически).
2. **Expand roadmap** — заполнить:
- **RTO/RPO targets** per service (client websites, gitea, verdaccio, registry, ntfy, traefik, DB park). Recovery Time Objective vs Recovery Point Objective отдельно по каждому. Сейчас effective RTO для NAS-loss был ~15 часов (15h до восстановления через recovery VM), RPO = 1 day (Hyper Backup daily). Какой target ставим?
- **3-2-1 backup strategy** — 3 копии, 2 разных media, 1 off-site. Сейчас: VDS-data → kreknin (1 off-site daily rsync ✅), но recovery-host data → ?, client sites content → ?, source code → gitea+kreknin-mirror?
- **Multi-host strategy** — клиентский прод сейчас на recovery-host (single point of failure). Опции: secondary IIS host (cold/warm standby), full migration на VDS (cms-on-VDS option), bare-metal колокация. Trade-offs стоимости / сложности / RTO.
- **Monitoring stack** — сейчас минимально: ntfy push при backup-completion, ручная проверка через ssh. Опции: Uptime Kuma / Prometheus+Grafana / Synology Active Insight / external (Pingdom/UptimeRobot). Цель — early-warning для cascading failures (типа SMR-deg которая привела к 2026-05-18).
- **Runbook coverage** — какие incident-сценарии должны иметь runbook'и (NAS-loss, VDS-loss, client-site-down, traefik-crash, cert-expiry, DB-corruption, ransomware-recovery). Какие уже есть фактически (post-mortem chronologies в `sources/`), какие missing.
3. **Output structure:**
- `concepts/future-resilient-architecture-goals.md` — обновленный (живой документ, не frozen).
- Если roadmap большой — child concepts (`concepts/resilience-rto-rpo-targets.md`, `concepts/resilience-monitoring-stack.md`, etc.) с link'ами из основного.
- Impl-tasks для каждого road-map item — отдельные таски через `tasks_create` (например `[setup-uptime-kuma]`, `[secondary-iis-host-cold-standby]`, etc.).
4. **Constraints:** roadmap **не** review автоматически — это living document. Acceptance: user (vitya) подтвердил план, есть concrete impl-tasks для top-3 priority items, документ committed.
Done — 🟢 с close-note: «roadmap expanded; N impl-tasks created for first wave».
**Blocker:** admin-subtree-import-and-cleanup
**Branch:** n/a
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-05-21T10:24:24.685Z -->
---
## ⚪ [secrets-out-of-common] — Этап 1 secret-management фикса: вынести `~/projects/.common/secrets/` в `~/.config/projects-secrets/` (вне git-tree). Не блокирует migration (независимый workstream).
**Why это дыра:**
1. `.common/` — git-tracked tree. Один неаккуратный `git add .` из wrong dir / отключение gitignore rule → leak в историю.
2. Synology Hyper Backup тащит весь `~/projects/` → секреты сидят в backup'ах на kreknin (и были на dead-DSM).
3. IDE indexing / LSP / Cursor / Copilot — `.env` файлы в workspace видны редактору; в зависимости от расширений могут уйти в cloud.
4. Любой `find ~/projects | xargs grep` — даёт plain-text secrets.
Этап 1 — быстрый фикс, low-risk, обратимый. Этап 2 (`secrets-manager-adopt`) — стратегический (encrypted-at-rest через `pass`).
См. `concepts/admin-infra-project.md` §Initial admin agenda E.2.
**Status:** ready
**Where I stopped:** (not started)
**Next action:** **1. Audit:** `ls ~/projects/.common/secrets/` — какие файлы там лежат сейчас? Список ожидаемых из памяти:
- `interns.env` — API keys для cheap LLM endpoints
- `gitea-token.txt` — admin-scoped Gitea token (admin-scope per memory)
- `vds-kzntsv.env` — VDS creds (ssh + DB + portainer + ntfy)
- возможно другие
**2. Audit потребителей:**
- `~/projects/.common/lib/interns-mcp/` — где читается `interns.env`? Grep по `interns.env` или `dotenv` calls.
- `~/projects/.common/lib/projects-meta-mcp/` — где читается token? Часто это `~/.config/projects-mcp/auth.toml` отдельно (см. setup-projects-meta skill); но возможны cross-refs.
- `~/.claude.json` `mcpServers.*` — где ENV/args ссылаются на `.common/secrets/*`?
- `~/projects/.common/secrets/vds-kzntsv.env` — кто его читает (scripts? local docs only?).
**3. Migration:**
```bash
mkdir -p ~/.config/projects-secrets
cp -r ~/projects/.common/secrets/* ~/.config/projects-secrets/
chmod 600 ~/.config/projects-secrets/* # paranoid; Windows ACL отдельно
```
**4. Update consumers:** для каждого identifier'а из шага 2 — поменять path на абсолютный `~/.config/projects-secrets/<file>` или принять env-override (рекомендуется env-override: легче тестировать на других машинах).
**5. Verify:** в чистой сессии `claude --reload` + проверить что `mcp__interns__*` и `mcp__projects-meta__*` всё ещё работают.
**6. Cleanup `.common/secrets/`:**
- Удалить (`rm -rf ~/projects/.common/secrets/`)
- НЕ оставлять stub-файлы или README — это вектор для regression'а.
- Git: `cd ~/projects/.common && git add -A && git commit -m "secrets: move out of common (now at ~/.config/projects-secrets/)"` если `.common` git-tracked.
**7. Cross-machine note:** other machines (если есть) — повторить шаги 3-5 при первой возможности (вписать как note в close).
Acceptance: `ls ~/projects/.common/secrets/` returns ENOENT, MCP servers still work, no `.env` references to `.common/secrets/` в коде/configs.
Done — 🟢; unblock `secrets-manager-adopt`.
**Branch:** n/a
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-05-21T10:24:48.748Z -->
---
## 🔵 [secrets-manager-adopt] — Этап 2 secret-management: внедрить `pass` (gpg-based password-store) — encrypted-at-rest secrets + cross-machine sync через private Gitea repo с encrypted blobs.
Альтернатива — Bitwarden CLI (cloud vault, audit log). Recommend `pass` для one-user setup — нет cloud-dependency, gpg native, encrypted git-syncable.
**Why этап 2 нужен:** после `secrets-out-of-common` (этап 1) секреты лежат plaintext в `~/.config/projects-secrets/`. Этап 1 убирает риски 1+3 (git leak + IDE indexing), но не риск 4 (любой filesystem read даёт plaintext) и не риск 2 (Hyper Backup на kreknin всё ещё тащит plaintext если `~/.config/` в scope, что зависит от backup config). `pass` закрывает оба — secrets зашифрованы на диске, расшифровка только в RAM при `pass show`.
См. `concepts/admin-infra-project.md` §Initial admin agenda E.3.
**Status:** blocked
**Where I stopped:** (not started)
**Next action:** **1. Pre-install — gpg setup (Windows):**
- Install Gpg4win (https://www.gpg4win.org/) или через Scoop: `scoop install gpg`.
- `gpg --full-generate-key` — выбрать RSA 4096, без expiration ИЛИ 2-year expiration с rotation reminder.
- `gpg --list-secret-keys` — захватить fingerprint.
**2. Install pass:**
- MSYS2: `pacman -S pass` (если есть MSYS2)
- Scoop: `scoop install pass`
- Manual: pass is bash script — clone https://git.zx2c4.com/password-store/ и положить на PATH.
**3. Initialize store:**
```bash
pass init <gpg-fingerprint>
# Creates ~/.password-store/.gpg-id
```
**4. Migrate secrets:**
- Для каждого file/var в `~/.config/projects-secrets/`:
- `pass insert <category>/<name>` → вводим plaintext, pass сохраняет как `~/.password-store/<category>/<name>.gpg`
- Примеры:
- `pass insert gitea/admin-token`
- `pass insert vds-kzntsv/ssh-password`
- `pass insert vds-kzntsv/portainer-password`
- `pass insert interns/openai-key`
- `pass insert interns/anthropic-key`
- Сохранить mapping (какой `.env` key какой `pass`-path) — `concepts/secrets-pass-mapping.md` ingest в admin wiki.
**5. Update consumers** — заменить direct file reads на shell-out calls:
- `interns-mcp` config: вместо `OPENAI_API_KEY=<plain>` в env-файле → `OPENAI_API_KEY=$(pass show interns/openai-key)` в wrapper-скрипте startup.
- `~/.claude.json` `mcpServers.*` env: если поддерживает command-eval — `pass show ...`; иначе wrapper-script.
- Альтернатива — `pass`-aware loader script `~/.config/projects-secrets/load.sh` который populate'ит env vars из pass при session start.
**6. Cross-machine sync:** initialize private Gitea repo `OpeItcLoc03/password-store-private` (visibility=private), push `~/.password-store/`. На каждой машине: clone + `gpg --import` master key + работает.
**7. Cleanup plaintext:** удалить `~/.config/projects-secrets/*` (содержимое мигрировано в pass). Оставить пустой dir + README указывающий на pass.
**8. Verify:** в чистой сессии все MCP / scripts работают через pass-resolved secrets.
Acceptance: `ls ~/.config/projects-secrets/` пуст или содержит только README, все consumers работают, `pass git status` clean, encrypted blobs в Gitea private repo.
Done — 🟢; secret-management dyra closed.
**Blocker:** secrets-out-of-common
**Branch:** n/a
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-05-21T10:25:14.759Z -->
---
## 🔵 [admin-infra-project-review] — Code-review checkpoint для брейнсторма admin-infra-project (промоушен 2026-05-21).
**Спецификация:** `.wiki/concepts/admin-infra-project.md` (ingested 2026-05-21).
**Pre-impl bootstrap:** `admin-infra-project-pointers` — заполнил `.wiki/CLAUDE.md` Domain conventions design-context pointer'ами. Без неё review бы читал stub.
**Импл-таски (review против их acceptance criteria):** `morecms-subtree-split`, `admin-subtree-import-and-cleanup`, `morecms-cleanup-and-breadcrumb`, `verify-migration`, `resilience-roadmap-design`, `secrets-out-of-common`, `secrets-manager-adopt`.
**Кто делает:** **не имплементер.** Следующая сессия в этом проекте (другая модель / другой день / другой агент) поднимает таску с чистым контекстом. «Я только что это написал» bias = главный риск.
**Чек-лист ревью:**
- Прочитать спецификацию `concepts/admin-infra-project.md` (acceptance criteria каждой импл-таски).
- `git log --oneline` shipped-коммитов в `~/projects/.admin/` и `~/projects/MoreThenCms/` (по migrate:/cleanup:/wiki:/tasks: префиксам в commit-message).
- Для migration-цепочки:
- `git log --follow` на парах файлов admin VS MoreThenCms — history preserved per-file?
- Нет ли CMS-файлов в admin (cleanup сработал)?
- Нет ли admin-файлов в MoreThenCms (cleanup сработал)?
- `cat MoreThenCms/.wiki/concepts/migrated-infra-to-admin.md` — breadcrumb корректный, все listings соответствуют реальности?
- Для `verify-migration` — повторно прогнать его validation matrix; нет ли регрессий после resilience/secrets работ?
- Для `resilience-roadmap-design` — roadmap расширен **по существу** (RTO/RPO с цифрами, не «TBD»; concrete impl-tasks для top-3) ИЛИ остался stub-`<TBD>`-placeholder fake-completion'ом?
- Для `secrets-out-of-common``ls ~/projects/.common/secrets/` точно пуст? Git history `.common/` не содержит leak'нутых secrets в недавних коммитах?
- Для `secrets-manager-adopt``pass show` actually works для всех migrated entries? `~/.config/projects-secrets/` пуст или README-only?
- Сверить дизайн-decisions из спецификации со shipped state. Любое отклонение от §Migration mechanics / §Initial admin agenda / §Identity — flag.
- Findings — отдельные follow-up tasks (`<topic>-<gap>-fix` или подобное) через `tasks_create`.
**Закрытие:** только когда все findings зафайлены ИЛИ ревьюер подтвердил «нет findings» в close-note.
**Status:** blocked
**Where I stopped:** (not started)
**Next action:** Дождаться 🟢 у всех blocker-тасок (включая `admin-infra-project-pointers` — без него pointers в `.wiki/CLAUDE.md` не залиты, и review будет читать stub). Прочитать спецификацию (см. путь в description). Для каждой импл-таски: `git show <commit>`, прогнать acceptance criteria из её next_action, сверить с design-decisions в спецификации. Findings → новые follow-up tasks через `mcp__projects-meta__tasks_create`.
**Blocker:** migration: admin-subtree-import-and-cleanup, morecms-cleanup-and-breadcrumb, verify-migration; agenda: resilience-roadmap-design, secrets-out-of-common, secrets-manager-adopt
**Branch:** n/a
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-05-21T10:25:43.430Z -->
---
# Imported from MoreThenCms — 2026-05-21 subtree-split migration
Полное содержимое `.tasks/STATUS.md` из MoreThenCms на момент 2026-05-21, **CMS-domain блоки исключены** (остались в MoreThenCms): `cms-admin-assets-root-folders-seed`, `cms-port-leak-fix`, `traefik-maljarka-502-bug`, `cms-maljarka-https-mode-bug-fix`. История per-file сохранена через subtree-split + temp-prefix merge.
## 🟢 [vds-kzntsv-bootstrap] — VDS поднят, gitea/verdaccio/registry мигрированы (3/3 phases done 2026-05-20)
**Status:** done (2026-05-20 вечер — все 3 заявленные фазы закрыты)
**Where I stopped:** Phase 1 + Phase 2 завершены ✅. VDS `89.253.255.94 / vds.kzntsv.site` Ubuntu 24.04 upgraded через VNC. sudo vitya (NOPASSWD) + ssh-key + hardened sshd (key-only) + ufw 22/80/443 + DB-порты + fail2ban + docker 29.5.1 + buildx + compose. Traefik v2.11 на `traefik.vds.kzntsv.site` (basicAuth vitya:Pryakhin9). Portainer CE 2.21.5 на `portainer.vds.kzntsv.site`**админ-пароль был принудительно изменён на `Pryakhin9-VDS-2026` (18 chars)** из-за hard min-12-char policy в Portainer 2.21+ (regression от 2.20). API key получен и сохранён в `vds-kzntsv.env`. 4 DB-стека (Postgres 16, MariaDB 11.4, Mongo 7, Redis 7) подняты с self-signed TLS, доступны снаружи через traefik raw-TCP passthrough на `<db>.vds.kzntsv.site:<port>` (HostSNI(*) — traefik tls.passthrough+SNI не работает с STARTTLS-протоколами PG/MariaDB; rawTCP forward, DBs терминируют TLS сами). Все DB passwords (PG/Maria/Mongo/Redis) — strong random hex16, сохранены в `vds-kzntsv.env`.
**Open questions:** LE certs для DBs (сейчас self-signed → клиент verify-skip; permanent fix позже через lego sidecar extract из traefik acme.json).
**Next action:** Phase 3 миграция с kreknin **ВСЯ DONE ✅**. 3.1 gitea (132 repos, 4 users, v1.25.5 на git.kzntsv.site). 3.2 verdaccio (8.6G storage, 2063 packages, secret 32 chars). 3.3 registry — **отказались от миграции** старых 35G images (user: «новых наделать могу»), fresh install на registry.kzntsv.site + Joxit UI на registry-ui.vds.kzntsv.site (DELETE_IMAGES=true для GUI cleanup, REGISTRY_STORAGE_DELETE_ENABLED для API delete). Auth vitya:Pryakhin9 (см. vds-kzntsv.env). Follow-up tasks: vds-gc-cron, vds-backup-rsync-kreknin, vds-ntfy-push.
**Branch:** master
---
## 🟢 [iis-on-host-migration] — attempt 2 close-out: 36h soak passed, 8/8 наших sites зеленые
**Status:** done (2026-05-21 close-out). Detail: Phase 11 в [iis-host-migration-2026-05-19](../.wiki/sources/iis-host-migration-2026-05-19.md).
**Close-out evidence:** traefik `Up 38h` (zero restarts), w3wp 8.8h (scheduled pool recycle ~29h default, не crash), 8/8 наших sites вернули `Microsoft-IIS/10.0` через full traefik HTTPS chain (`emspb/snolla/on.snolla/pilorama98/labtools.ru/labtools.pro/tandemmebel/kupimknigi`). Маljarka/sestech/ics-artmaterials оказались **off-infra** (DNS снят / parked / external nginx) — не наша инфра, не regression. Новая follow-up task ⚪ `iis-traefik-dead-routes-cleanup` (низкий приоритет — почистить yml для 3 dead доменов).
**VM savestate:** **done 2026-05-21 05:13 MSK** (45.6s, VMState=saved). Savestate file 1.73 GB (`C:\Users\vitya\VirtualBox VMs\snolla-recovery\Snapshots\2026-05-21T05-12-43-636491200Z.sav`). VBoxHeadless процессы освободили ~4 GB private memory. Resume: `VBoxManage startvm snolla-recovery --type headless` (~30 сек если понадобится). Disk delete (`unregistervm --delete`, ~95 GB) — позже через неделю uptime.
**Atomic revert (unchanged):** ```Get-ChildItem C:\Users\vitya\projects\docker\diskstation\traefik\data\custom\*.yml.bak-pre-attempt2-2026-05-19 | %{ Copy-Item $_.FullName -Destination ($_.FullName -replace '\.bak-pre-attempt2-2026-05-19$','') -Force }; Move-Item C:\Users\vitya\projects\docker\diskstation\traefik\data\custom\stostayer.yml.disabled C:\Users\vitya\projects\docker\diskstation\traefik\data\custom\stostayer.yml -Force -EA SilentlyContinue; Move-Item C:\Users\vitya\projects\docker\diskstation\traefik\data\custom\oldstostayer.yml.disabled C:\Users\vitya\projects\docker\diskstation\traefik\data\custom\oldstostayer.yml -Force -EA SilentlyContinue; docker restart traefik```
**Branch:** master
---
## 🟢 [iis-traefik-dead-routes-cleanup] — sestech + isc-artmaterials disabled, maljarka оказалась live
**Status:** done (2026-05-21 ~05:42 MSK; ~20 мин работы).
**Result:**
- `sestech.yml` → `.disabled` (backup `.bak-pre-dead-routes-cleanup-2026-05-21`). DNS `sestech.ru/www.sestech.ru → 31.31.205.163` = parking provider, наш traefik больше не отвечает (public requests идут на parking host через DNS).
- `isc-artmaterials.yml` → `.disabled` (backup created). DNS `ics-artmaterials.com/www → 87.236.16.28 = external nginx-reuseport WP-хостинг`, public traffic не через нас.
- **Maljarka — НЕ disabled** — оказалось yml route'ит `maljarka.tandemmebel.ru` (subdomain тандеммебели), не голый `maljarka.ru`. DNS → **94.19.247.14 = наш IP**, IIS backend отвечает 200 OK ("Малярка от Тандеммебель", 43KB). Live route, не dead. Изначальная task'а ошиблась с hostname.
**Smoke regression:** 4 live hosts (emspb/on.snolla/www.tandemmebel/kupimknigi) → Microsoft-IIS/10.0 без regression. File-provider auto-reload, traefik restart не понадобился.
**Side finding:** `maljarka.tandemmebel.ru` через traefik HTTPS → **502 Bad Gateway**, хотя backend (host.docker.internal:8089 + Host header) возвращает 200 OK. Конфиг yml identical к работающему `tandemmebel.yml`. Live bug. Новая follow-up ⚪ task `traefik-maljarka-502-bug` (CMS-domain — остаётся в MoreThenCms).
**Atomic revert:** ```Move-Item C:\Users\vitya\projects\docker\diskstation\traefik\data\custom\sestech.yml.disabled C:\Users\vitya\projects\docker\diskstation\traefik\data\custom\sestech.yml -Force; Move-Item C:\Users\vitya\projects\docker\diskstation\traefik\data\custom\isc-artmaterials.yml.disabled C:\Users\vitya\projects\docker\diskstation\traefik\data\custom\isc-artmaterials.yml -Force```
**Branch:** master
---
## 🟢 [vds-gc-cron] — weekly GC armed для verdaccio + registry на VDS
**Status:** done (2026-05-21 00:21 MSK; ~1ч работы). Детали в [vds-gc-cron.md](vds-gc-cron.md).
**Result:** `/etc/cron.d/vds-gc` armed — Sun 03:00 MSK registry-gc.sh, Sun 03:30 MSK verdaccio-prune.sh. Scripts в `/opt/stacks/gc/scripts/` (`notify.sh`, `registry-gc.sh`, `verdaccio-prune.sh`+`verdaccio-prune.js`). Logs в `/var/log/vds-gc/`. Notify через ntfy `vds-ops`.
**Verdaccio prune real run:** 8.5G → 6.8G (freed 1.7G), 7021 packages scanned, 1551 modified, 4524 tgz deleted, 0 errors, 73 locally-published versions защищены (@snollajs/* + similar — detected via `_distfiles[tgzName]` absent). Atomic JSON rewrite (`tmp + rename`) + `_rev` bump.
**Registry GC smoke:** alpine v1+v2 pushed → DELETE manifest → GC freed 61M (whole tree, since both tags pointed одну digest). Empty-storage guard added (first run на свежем registry — `/var/lib/registry/docker/registry/v2/repositories` отсутствует → skip+min-prio notify, не FAIL).
**Atomic revert:** `ssh vitya@89.253.255.94 'sudo rm /etc/cron.d/vds-gc; sudo systemctl restart cron; sudo rm -rf /opt/stacks/gc /var/log/vds-gc'`
**Branch:** master
---
## 🟢 [vds-backup-rsync-kreknin] — daily VDS→kreknin live, smoke green, cron armed
**Status:** done (2026-05-20 → 2026-05-21 00:00 first-run завершён успешно). Детали в [vds-backup-rsync-kreknin.md](vds-backup-rsync-kreknin.md).
**Result:** rsync `--link-dest` pipeline `/opt/stacks/backup/scripts/run.sh` под cron `0 5 * * *` (root) → kreknin `/volume1/NetBackup/vds-kzntsv/<DATE>/` + symlink `latest`. DB dumps (pg/maria/mongo/redis), system config (/etc/ssh, ufw, hosts, docker), ssh keys, /opt/stacks data. Notification dual-channel: email через msmtp+Yandex (`/etc/msmtprc`) + ntfy publish на `vds-backup` topic. Retention 7 daily snapshots. Smoke run done — 71,867 files / 11.74G в 21m27s, exit 0. Cron service installed (apt install cron — Ubuntu 24.04 не имел его) + enabled. Next run автоматически 2026-05-21 05:00 MSK.
**SPOF gap status:** closed for VDS — full restore from kreknin возможен (DB dumps + конфиги + ssh keys).
**Open:** phone-side smoke (user verifies ntfy push пришёл из реального backup run).
**Atomic revert:** `ssh vitya@89.253.255.94 'sudo systemctl stop cron; sudo rm /etc/cron.d/vds-backup; sudo apt-get remove -y cron msmtp msmtp-mta; sudo rm -rf /etc/msmtprc /opt/stacks/backup /var/log/vds-backup'`
**Branch:** master
---
## 🟢 [vds-ntfy-push] — self-hosted ntfy.vds.kzntsv.site live, phone-verified
**Status:** done (2026-05-20 вечер; ~30 min работы). Detail в [vds-ntfy-push.md](vds-ntfy-push.md).
**Result:** ntfy v2.11.0 на `ntfy.vds.kzntsv.site`, LE cert (R12, valid до 2026-08-18), admin user `vitya / Pryakhin9` (deny-all дефолт, admin role → rw to all), топики `vds-backup` + `vds-ops`. Phone-verified — оба push'а пришли в Android ntfy app (screenshot 22:54). Creds в `~/projects/.common/secrets/vds-kzntsv.env` + `/opt/stacks/ntfy/.env` (chmod 600).
**Integration ready for:** [[vds-backup-rsync-kreknin]] (publish status на `vds-backup`), monitoring scripts (на `vds-ops`).
**Atomic revert:** `ssh vitya@89.253.255.94 'cd /opt/stacks/ntfy && docker compose down -v && cd .. && rm -rf ntfy'` + remove ntfy entries из vds-kzntsv.env.
**Branch:** master
---
## 🟢 [nas-recovery] — клиентские сайты восстановлены, работают из публичного интернета
**Status:** done (2026-05-19 ~10:00 MSK — 15 часов работы)
**Final state:** OpenWRT NAT → traefik 2.6.6 (host:8000/4443) → VirtualBox VM snolla-recovery (IIS + CMS) + docker-стек на хосте (MSSQL/MinIO/ES/imgproxy/nginx). 13 client routes, 40 LE certs валидны. Проверено: пользовательский клиент из публичного интернета открывает snolla.com, pilorama98.ru, labtools.ru/pro, tandemmebel.ru, emspb.ru.
**Backup pull:** C:\nas-recovery\vm-sites\ (~11 GB inetpub/wwwroot + stayer/) — на случай если VM снова станет нестабильной.
**Open issues (минор):**
- X-Forwarded-Proto/Host: CMS делает redirect с портом 4443 в URL — нужно добавить middleware в traefik или включить trust в IIS.
- MinIO/Azure storage — пользователь упомянул "не так всё", ждём пояснение.
- docker-сокет проброс в traefik — daemon connection error (некритично, file-provider routing работает).
- VM в bridged-WiFi была нестабильной → переехали на NAT + port forwards.
- acme.json renewal через HTTP-01 фейлится для доменов с DNS не на нашем IP — нужно переключить на DNS-01 через REGRU (creds в env уже).
**Branch:** master
---