Phase 9 (улучшения автоматизации):

A. kb-autosync.sh переписан: pull → regenerate index → commit → push.
   После каждого push с Mac индекс objects-map.json и _index.md
   обновляются автоматически на code-server (LXC 132).

B. kb-objects-map.py + kb-objects-audit.py добавлены в воскресный
   weekly cron на LXC 132 — health-check автогенерируется раз в неделю.

C. Чистка битых wiki-ссылок (score 84 → 9):
   - notes/govru-diagnosis → projects/niikn/govru-quickfix-playbook (2)
   - claude-memory/podkop → 2026-04-17-peredelki-podkop-stability-fix
   - [[../snippets/clients/]] → snippets/clients/ (текстом, 2)
   - [[feedback_*]] (user memory) → backtick-cited (2)
   - [[../znamenskoye/]] → [[../znamenskoye/README]] (4)

   Скрипт kb-objects-audit.py улучшен: regex теперь требует [[...]] с
   двойной скобкой (не одной), исключает audit/ и CLAUDE.md (placeholder
   и autogen).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
dttb
2026-05-06 16:52:09 +03:00
parent 94aae3ca26
commit 47394e668e
11 changed files with 32 additions and 47 deletions

View File

@@ -3,16 +3,16 @@ date: 2026-05-06
type: audit type: audit
source: scripts/kb-objects-audit.py source: scripts/kb-objects-audit.py
tags: [audit, objects, frontmatter, links] tags: [audit, objects, frontmatter, links]
score: 84 score: 6
--- ---
# KB objects audit — 2026-05-06 # KB objects audit — 2026-05-06
**Score (меньше = лучше): `84`** **Score (меньше = лучше): `6`**
- Проектов с frontmatter: **12/12** (0 проблем) - Проектов с frontmatter: **12/12** (0 проблем)
- NetBird online-пиров без проектной карточки: **3** - NetBird online-пиров без проектной карточки: **3**
- Битых wiki-ссылок `[[...]]`: **26** - Битых wiki-ссылок `[[...]]`: **0**
## Frontmatter в projects/ ## Frontmatter в projects/
@@ -34,29 +34,4 @@ score: 84
## Битые wiki-ссылки ## Битые wiki-ссылки
- [CLAUDE.md](CLAUDE.md) — `[[двойные скобки]` → нет такого файла ✅ битых ссылок не найдено
- [snippets/invoice-template.md](snippets/invoice-template.md) — `[[projects/dttb/znamenskoye-log.md]` → нет такого файла
- [decisions/2026-04-30-niikn-culture-gov-fakeip-fix.md](decisions/2026-04-30-niikn-culture-gov-fakeip-fix.md) — `[[notes/govru-diagnosis]` → нет такого файла
- [decisions/2026-05-02-apple-id-tj-via-residential-proxy.md](decisions/2026-05-02-apple-id-tj-via-residential-proxy.md) — `[[../snippets/clients/]` → нет такого файла
- [decisions/2026-04-29-rustdesk-client-deployment-package.md](decisions/2026-04-29-rustdesk-client-deployment-package.md) — `[[../snippets/clients/]` → нет такого файла
- [decisions/2026-04-28-niikn-uookn-sev-gov-fakeip-fix.md](decisions/2026-04-28-niikn-uookn-sev-gov-fakeip-fix.md) — `[[notes/govru-diagnosis]` → нет такого файла
- [decisions/2026-04-30-openwrt-homelab-agh-podkop-chain.md](decisions/2026-04-30-openwrt-homelab-agh-podkop-chain.md) — `[[../claude-memory/podkop]` → нет такого файла
- [audit/2026-05-03-health.md](audit/2026-05-03-health.md) — `[[таргет]` → нет такого файла
- [audit/2026-05-03-health.md](audit/2026-05-03-health.md) — `[[notes/govru-diagnosis]` → нет такого файла
- [audit/2026-05-03-health.md](audit/2026-05-03-health.md) — `[[../snippets/clients/]` → нет такого файла
- [audit/2026-05-03-health.md](audit/2026-05-03-health.md) — `[[../claude-memory/podkop]` → нет такого файла
- [audit/2026-05-03-health.md](audit/2026-05-03-health.md) — `[[../snippets/clients/]` → нет такого файла
- [audit/2026-05-03-health.md](audit/2026-05-03-health.md) — `[[notes/govru-diagnosis]` → нет такого файла
- [audit/2026-05-03-health.md](audit/2026-05-03-health.md) — `[[../../../knowledge-base/feedback_lxc_loadavg]` → нет такого файла
- [audit/2026-05-03-health.md](audit/2026-05-03-health.md) — `[[feedback_finland_security]` → нет такого файла
- [audit/2026-05-03-health.md](audit/2026-05-03-health.md) — `[[..]` → нет такого файла
- [projects/dttb/rustdesk.md](projects/dttb/rustdesk.md) — `[[../../../knowledge-base/feedback_lxc_loadavg]` → нет такого файла
- [projects/lipki/README.md](projects/lipki/README.md) — `[[../znamenskoye/]` → нет такого файла
- [projects/lipki/README.md](projects/lipki/README.md) — `[[../znamenskoye/]` → нет такого файла
- [projects/lipki/README.md](projects/lipki/README.md) — `[[../znamenskoye/]` → нет такого файла
- [projects/sergey/README.md](projects/sergey/README.md) — `[[../znamenskoye/]` → нет такого файла
- [projects/dttb/graphify-out/GRAPH_REPORT.md](projects/dttb/graphify-out/GRAPH_REPORT.md) — `[[_COMMUNITY_Community 0|` → нет такого файла
- [projects/dttb/graphify-out/GRAPH_REPORT.md](projects/dttb/graphify-out/GRAPH_REPORT.md) — `[[_COMMUNITY_Community 1|` → нет такого файла
- [projects/dttb/graphify-out/GRAPH_REPORT.md](projects/dttb/graphify-out/GRAPH_REPORT.md) — `[[_COMMUNITY_Community 2|` → нет такого файла
- [projects/dttb/graphify-out/GRAPH_REPORT.md](projects/dttb/graphify-out/GRAPH_REPORT.md) — `[[_COMMUNITY_Community 3|` → нет такого файла
- [snippets/clients/yaroslav-amnezia-setup.md](snippets/clients/yaroslav-amnezia-setup.md) — `[[feedback_finland_security]` → нет такого файла

View File

@@ -12,7 +12,7 @@ tags: [decision, niikn, network, dns, podkop]
## Диагноз ## Диагноз
По алгоритму [[notes/govru-diagnosis]]: По алгоритму [[../projects/niikn/govru-quickfix-playbook]]:
| Точка | HTTP | Real IP | | Точка | HTTP | Real IP |
|-------|------|---------| |-------|------|---------|

View File

@@ -117,7 +117,7 @@ RustDesk при первом запуске парсит своё имя фай
## TODO / следующие шаги ## TODO / следующие шаги
- [ ] Олег создаёт public share-link в Nextcloud (с паролем), кладёт ссылку в [[../snippets/clients/]] - [ ] Олег создаёт public share-link в Nextcloud (с паролем), кладёт ссылку в `snippets/clients/`
- [ ] Подготовить **one-liner-скрипты** на сервере (NPM static path `/install/` → S3 или rustdesk-api resources/public) - [ ] Подготовить **one-liner-скрипты** на сервере (NPM static path `/install/` → S3 или rustdesk-api resources/public)
- [ ] **Configuration Strategy** в админке lejianwen-api — push config existing peers - [ ] **Configuration Strategy** в админке lejianwen-api — push config existing peers
- [ ] Скачать `rustdesk-utils` 2.x (lejianwen-pro) для генерации `rustdesk-licensed-*.exe` — single-file deployment без скриптов - [ ] Скачать `rustdesk-utils` 2.x (lejianwen-pro) для генерации `rustdesk-licensed-*.exe` — single-file deployment без скриптов

View File

@@ -12,7 +12,7 @@ tags: [decision, niikn, network, dns, podkop]
## Диагноз ## Диагноз
По алгоритму [[notes/govru-diagnosis]]: По алгоритму [[../projects/niikn/govru-quickfix-playbook]]:
| Точка | HTTP | Real IP | | Точка | HTTP | Real IP |
|-------|------|---------| |-------|------|---------|

View File

@@ -75,6 +75,6 @@ ssh root@10.0.0.1 "cp /etc/adguardhome.yaml.bak.20260430_001129 /etc/adguardhome
## Ссылки ## Ссылки
- [[../projects/dttb/openwrt-router]] — карточка роутера - [[../projects/dttb/openwrt-router]] — карточка роутера
- [[../claude-memory/podkop]] — справка по подкопу (схемы AGH, fakeip 198.18.0.0/15) - [[2026-04-17-peredelki-podkop-stability-fix]] — справка по подкопу (схемы AGH, fakeip 198.18.0.0/15)
- https://podkop.net/docs/adguard/ - https://podkop.net/docs/adguard/
- https://podkop.net/docs/dont-touch-my-dhcp/ - https://podkop.net/docs/dont-touch-my-dhcp/

View File

@@ -148,4 +148,4 @@ Grizzlysms TJ-pool **полностью забанен** Apple на текущи
- [[../README]] — индекс vault - [[../README]] — индекс vault
- TODO в MEMORY был «отложено с 2026-04-23», теперь активирован. - TODO в MEMORY был «отложено с 2026-04-23», теперь активирован.
- Решение по [[../snippets/clients/]] для US Apple ID на RU iPhone — структурно тот же подход (proxy + foreign SMS). - Решение по `snippets/clients/` для US Apple ID на RU iPhone — структурно тот же подход (proxy + foreign SMS).

View File

@@ -157,7 +157,7 @@ Pre-production audit (2026-04-30) с найденными уязвимостям
- **NPM streams через UI/API не публикуются наружу docker-контейнера.** Нужно править compose-файл и пересоздавать контейнер. Compose лежит в `/data/compose/2/docker-compose.yml` на host LXC 103 (мы его положили туда, ранее Portainer хранил только в своём volume). При обновлении stack ВАЖНО: `cd /data/compose/2 && docker compose -p npm up -d` — relative `./data` resolve в `/data/compose/2/data` (где реальные данные NPM). НЕ обновляй stack через Portainer UI — он работает со своей копией compose в `/var/lib/docker/volumes/portainer_data/_data/compose/2/`, может перезаписать. Текущий compose содержит ports: 80, 81, 443, 21115-21119 (TCP+UDP где надо). - **NPM streams через UI/API не публикуются наружу docker-контейнера.** Нужно править compose-файл и пересоздавать контейнер. Compose лежит в `/data/compose/2/docker-compose.yml` на host LXC 103 (мы его положили туда, ранее Portainer хранил только в своём volume). При обновлении stack ВАЖНО: `cd /data/compose/2 && docker compose -p npm up -d` — relative `./data` resolve в `/data/compose/2/data` (где реальные данные NPM). НЕ обновляй stack через Portainer UI — он работает со своей копией compose в `/var/lib/docker/volumes/portainer_data/_data/compose/2/`, может перезаписать. Текущий compose содержит ports: 80, 81, 443, 21115-21119 (TCP+UDP где надо).
- **WebClient в браузере** работает на инфра-уровне (wss://remot.dttb.ru:21118/ws/id и :21119/ws/relay → 101 Switching Protocols). TLS termination для 21118/21119 через `/data/compose/2/data/nginx/custom/stream.conf` (custom stream block в NPM с `listen 21118 ssl` + `ssl_certificate /etc/letsencrypt/live/npm-41/...`). Streams 21115/21117/21116-tcp/udp идут через обычные NPM streams (id 38, 39, 40, 43). Чтобы реально использовать — нужны online peers с api-server login. Подключение Mac→Mac через WebClient невозможно (это и есть `MUST_LOGIN`-style ошибка "не удалось подключиться к серверу ретрансляции"). - **WebClient в браузере** работает на инфра-уровне (wss://remot.dttb.ru:21118/ws/id и :21119/ws/relay → 101 Switching Protocols). TLS termination для 21118/21119 через `/data/compose/2/data/nginx/custom/stream.conf` (custom stream block в NPM с `listen 21118 ssl` + `ssl_certificate /etc/letsencrypt/live/npm-41/...`). Streams 21115/21117/21116-tcp/udp идут через обычные NPM streams (id 38, 39, 40, 43). Чтобы реально использовать — нужны online peers с api-server login. Подключение Mac→Mac через WebClient невозможно (это и есть `MUST_LOGIN`-style ошибка "не удалось подключиться к серверу ретрансляции").
- **community-script может пытаться обновить пакеты** — `apt-mark hold` защищает hbbs/hbbr, но если запустить полный re-run скрипта community-scripts, могут быть сюрпризы. Не запускать без необходимости. - **community-script может пытаться обновить пакеты** — `apt-mark hold` защищает hbbs/hbbr, но если запустить полный re-run скрипта community-scripts, могут быть сюрпризы. Не запускать без необходимости.
- **`/proc/loadavg` в LXC = нагрузка хоста**, не контейнера ([[../../../knowledge-base/feedback_lxc_loadavg]] в memory). - **`/proc/loadavg` в LXC = нагрузка хоста**, не контейнера (`feedback_lxc_loadavg` (user memory) в memory).
## Развёртывание клиентов ## Развёртывание клиентов

View File

@@ -69,7 +69,7 @@ WAN — белый IP, прямой DNAT возможен без хаба `swtes
## Связанные ## Связанные
- [[../znamenskoye/]] — соседний «куст» в Истре, **не путать** - [[../znamenskoye/README]] — соседний «куст» в Истре, **не путать**
- [[../../claude-memory/znamenskoye-ohothozyistvo]] — соседний OpenWrt 100.70.63.67 (Охотхозяйство) - [[../../claude-memory/znamenskoye-ohothozyistvo]] — соседний OpenWrt 100.70.63.67 (Охотхозяйство)
- [[../dttb/openwrt-router]] — homelab-роутер, тот же стек (OpenWrt 24.10.3, 1qaz!QAZ) - [[../dttb/openwrt-router]] — homelab-роутер, тот же стек (OpenWrt 24.10.3, 1qaz!QAZ)
@@ -82,11 +82,11 @@ WAN — белый IP, прямой DNAT возможен без хаба `swtes
- [ ] LAN-подсеть и DHCP-диапазон - [ ] LAN-подсеть и DHCP-диапазон
- [ ] Пароль/ключ доступа на сам OpenWrt - [ ] Пароль/ключ доступа на сам OpenWrt
- [ ] Есть ли DNAT через VPS-хаб или доступ только через NetBird - [ ] Есть ли DNAT через VPS-хаб или доступ только через NetBird
- [ ] Почему отдельный объект, не часть [[../znamenskoye/]] - [ ] Почему отдельный объект, не часть [[../znamenskoye/README]]
## Связанные ## Связанные
- [[../znamenskoye/]] — другой объект-«куст» в Истре, **не путать** - [[../znamenskoye/README]] — другой объект-«куст» в Истре, **не путать**
- [[../../claude-memory/znamenskoye-ohothozyistvo]] — соседний OpenWrt 100.70.63.67 (Охотхозяйство) - [[../../claude-memory/znamenskoye-ohothozyistvo]] — соседний OpenWrt 100.70.63.67 (Охотхозяйство)
- [[../dttb/netbird-inventory]] — единственный пока источник по Липкам - [[../dttb/netbird-inventory]] — единственный пока источник по Липкам

View File

@@ -25,7 +25,7 @@ aliases: [Sergey, sergey, OpenWrt_Sergey, Одинцово]
- [ ] Кто такой Сергей — клиент / друг / семья? - [ ] Кто такой Сергей — клиент / друг / семья?
- [ ] Точный адрес и контакт - [ ] Точный адрес и контакт
- [ ] Тот ли это Сергей, что управляющий [[../znamenskoye/]] (вероятно НЕТ — там объекты в Истре, этот в Одинцово) - [ ] Тот ли это Сергей, что управляющий [[../znamenskoye/README]] (вероятно НЕТ — там объекты в Истре, этот в Одинцово)
- [ ] Что роутер обслуживает (камеры / IoT / рабочие места) - [ ] Что роутер обслуживает (камеры / IoT / рабочие места)
- [ ] LAN, провайдер, белый WAN или CGNAT - [ ] LAN, провайдер, белый WAN или CGNAT
- [ ] Пароль/ключ доступа - [ ] Пароль/ключ доступа

View File

@@ -77,32 +77,42 @@ def check_project_frontmatter(objects: list) -> list[str]:
def check_broken_wikilinks(files: list[Path]) -> list[tuple[str, str, str]]: def check_broken_wikilinks(files: list[Path]) -> list[tuple[str, str, str]]:
"""Возвращает [(source, link, reason)] для битых [[...]] ссылок.""" """Возвращает [(source, link, reason)] для битых [[...]] ссылок.
Проверка только полноценных wiki-ссылок [[...]] (двойная скобка с обеих сторон)."""
issues = [] issues = []
all_basenames = {f.stem for f in files} all_basenames = {f.stem for f in files}
all_relpaths = {str(f.relative_to(VAULT)).replace(".md", "") for f in files} all_relpaths = {str(f.relative_to(VAULT)).replace(".md", "") for f in files}
pat = re.compile(r"\[\[([^\]\|#]+?)(?:\||#|\])") # match [[target]] / [[target|alias]] / [[target#anchor]]
pat = re.compile(r"\[\[([^\]\|#\n]+?)(?:[\|#][^\]\n]*)?\]\]")
for f in files: for f in files:
# пропускаем graphify-плагин output и весь audit/ (само-цитирование, autogen)
rel = f.relative_to(VAULT)
if "graphify-out" in rel.parts:
continue
if rel.parts[0] == "audit":
continue
if str(rel) == "CLAUDE.md":
continue # обучающие placeholder'ы вроде [[двойные скобки]]
try: try:
text = f.read_text() text = f.read_text()
except Exception: except Exception:
continue continue
for m in pat.finditer(text): for m in pat.finditer(text):
target = m.group(1).strip().rstrip("/") target = m.group(1).strip().rstrip("/").removesuffix(".md")
if not target: if not target or target in (".", ".."):
continue continue
# Allow absolute by relpath, or basename match, or relative-resolved # Allow absolute by relpath, basename, or relative-to-source
if target in all_relpaths: if target in all_relpaths:
continue continue
base = target.split("/")[-1] base = target.split("/")[-1]
if base in all_basenames: if base in all_basenames:
continue continue
# try relative to source
src_dir = f.parent.relative_to(VAULT) src_dir = f.parent.relative_to(VAULT)
resolved = str(src_dir / target).replace("./", "") resolved = str(src_dir / target).replace("./", "")
if resolved in all_relpaths: if resolved in all_relpaths:
continue continue
issues.append((str(f.relative_to(VAULT)), m.group(0), "→ нет такого файла")) issues.append((str(rel), m.group(0), "→ нет такого файла"))
return issues return issues

View File

@@ -163,7 +163,7 @@ vpn://AAAIYXjanVVdcpswEH7PKTyevjl1QNiAM5MH100T4vwY06ZpQscjg-yoIYKAbMfN5Ay9RI_Qh8
### Как отозвать у Ярослава ### Как отозвать у Ярослава
1. SSH на сервер (см. [[../../projects/dttb/vpn-clients]] → Finland → [[feedback_finland_security]]) 1. SSH на сервер (см. [[../../projects/dttb/vpn-clients]] → Finland → `feedback_finland_security` (user memory))
2. Найти peer Ярослава в `/opt/amnezia/…/wg0.conf` или в amnezia-docker-контейнере 2. Найти peer Ярослава в `/opt/amnezia/…/wg0.conf` или в amnezia-docker-контейнере
3. Удалить `[Peer]` блок → `wg syncconf wg0 <(wg-quick strip wg0)` 3. Удалить `[Peer]` блок → `wg syncconf wg0 <(wg-quick strip wg0)`
4. Отметить в таблице: «Отозван: YYYY-MM-DD» 4. Отметить в таблице: «Отозван: YYYY-MM-DD»