docs(vault-sync): acl fix closed 236/236 INHERIT+WRITE, watchdog cron, root cause hermes-taiga

This commit is contained in:
Alexey Martemyanov committed 2026-09-22 20:09:38 +06:00
1 parent 8b831a85a1
commit afbf895e2e
2 files changed
+154 -8

No files matched your search

@@ -133,10 +133,66 @@ touch /mnt/RED_2TB/storage/git/obsidian-vault.git/objects/80/.wrtest && echo WRI
```
`WRITE OK` → push will succeed. Confirmed: `f9a5c2b..21505ec main -> main`, then a clean `git pull` on Kraken.
### Durable fix with INHERITANCE (2026-09-21, applied — 291 dirs)
### Durable fix with INHERITANCE (2026-09-21 — 291 dirs, 2026-09-22 — 236 dirs)
The minimal recipe above (add perms to existing `group@` ACE) restores write for *current* dirs, **but the bug returns**: the next push by the root-owned `mcpvault` creates a NEW `objects/XX/` dir whose ACL is inherited from the *parent*, and if the parent's `everyone@`/`group@` lacks `WRITE_DATA` + inherit flags, the new dir is root-owned and read-only again → push fails again.
🔴 **RE-CUR 2026-09-22.** Дефект вернулся (35 root-каталогов). Итог фикса: **236/236 каталогов
с `INHERIT` + `WRITE`**, push прошёл end-to-end. Порядок работ и уроки — в
`family/documents/vault-sync/2026-09-21-bare-repo-push-permission-denied.md` §«✅ ФИНАЛЬНЫЙ ФИКС».
**Working fix = read-modify-write, НЕ сборка dacl с нуля:**
```python
# perms granted to owner@ AND group@ AND everyone@:
# READ_DATA WRITE_DATA APPEND_DATA EXECUTE DELETE_CHILD
# READ_ATTRIBUTES WRITE_ATTRIBUTES READ_NAMED_ATTRS WRITE_NAMED_ATTRS
# READ_ACL (and WRITE_ACL WRITE_OWNER DELETE for owner@)
# flags задаются КАК СТРОКА, не булев dict:
# ace["flags"] = {"BASIC": "INHERIT"} ← FILE_INHERIT + DIRECTORY_INHERIT
# call: midclt call filesystem.setacl '<one json with path + dacl + options>'
# options = {"recursive": False, "traverse": True, "stripacl": False}
```
🔴 **Четыре питфолла, стоившие времени:**
1. **Собирать `dacl` «с нуля» НЕЛЬЗЯ.** TrueNAS требует поле `id` в каждой ACE:
`[EINVAL] filesystem_acl.dacl.0: ACL entry is missing required keys(s): {'id'}`.
Работает только **read-modify-write**: `getacl` → править `perms`/`flags` → `setacl`.
2. **Флаги — `{"BASIC":"INHERIT"}`, НЕ `{"FILE_INHERIT":True,"DIRECTORY_INHERIT":True}`.**
Булев dict отклоняется той же ошибкой про `id` (при неверном формате TrueNAS
пересобирает ACE и теряет поле).
3. **`setacl` АСИНХРОННЫЙ — надо ЖДАТЬ job до `SUCCESS`.** Проверка `getacl` сразу после
вызова видит СТАРЫЕ флаги → ложный `fail`. Признак гонки: `fixed=0, already=N, fail=M`.
```python
jid = int(midclt("filesystem.setacl", arg))
while deadline:
j = json.loads(midclt("core.get_jobs", f'[["id","=",{jid}]]'))
if j[0]["state"] in ("SUCCESS","FAILED","ABORTED"): break
time.sleep(1)
```
4. **Владелец `root` сам по себе НЕ блокирует запись.** `getacl` даёт `uid:0, gid:950`,
запись от uid 950 идёт через `group@` (gid 950). `write-тест` в 35 root-каталогов:
OK=35 FAIL=0.
**Верификация (обязательна, делай до retry push):**
```bash
touch <repo>/objects/XX/.wrtest && echo WRITE_OK # у КАЖДОГО каталога
# + тест наследования: mkdir objects/zzz → getacl → должен быть INHERITED:True → touch внутрь
# + end-to-end: git clone <repo> && cd && echo x > f && git add f && git commit && git push
```
**Сторож (поставлен 2026-09-22):**
```
~/scripts/vault-acl-watchdog.py (TrueNAS, от truenas_admin)
cron: 0 */2 * * * python3 ~/scripts/vault-acl-watchdog.py >> ~/scripts/vault-acl-watchdog.log 2>&1
```
SILENT если всё ок; чинит + докладывает если сломано.
⚠️ **Корень НЕ устранён:** `mcpvault` контейнера `hermes-taiga`
(`/mnt/RED_2TB/docker/hermes/docker-compose.yml`, `HERMES_ALLOW_ROOT_GATEWAY=1`, `User:` пусто)
работает от root. Перманентный фикс — добавить `user: "950:950"` в `taiga` service.
Working fix = **full dacl replacement** (not per-ACE edit) with **inheritance flags ON**, applied to every dir:
```python