tasks: close secrets-manager-adopt 🟢 (etap-2 secret-management complete)

Pass-based encrypted-at-rest secret store live:
- gpg key RSA 4096 (fpr 0CB0B019...4FE3F59E), no expiration
- pass v1.7.4 at ~/.local/bin/pass (manual clone)
- 5 entries: interns/ollama-cloud-api-key, gitea/admin-token,
  vds-kzntsv/full-env, kreknin/full-env, snolla-smtp/full-env
- gpg-agent: pinentry-w32 + 30-day cache TTL
- Wrapper ~/.local/bin/interns-mcp-launcher.sh — pass show → env →
  exec python -m interns_mcp.server
- ~/.claude.json mcpServers.interns swapped to wrapper bash invocation
- Cross-machine: OpeItcLoc03/password-store-private (private), 7 commits
- Plaintext ~/.config/projects-secrets/ cleaned (5 secret files removed;
  README rewritten as pass-pattern marker)

Acceptance: all 4 spec criteria met.

Open follow-ups:
- meeting-room dirty WIP (etap-1 edit unstaged) — user decision needed
- setup-interns SKILL v0.5.0 — migrate phase 5/6 to pass+wrapper
- New endpoints — pattern documented in projects-secrets/README.md

Closes secrets-manager-adopt (admin agenda E.3); secrets-out-of-common
+ secrets-manager-adopt chain (E.1 → E.3) fully shipped this session.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-21 14:55:32 +03:00
parent 7493e07b34
commit d20a9d41e4

View File

@@ -1,5 +1,5 @@
# Admin Task Board
_Updated: 2026-05-21 (etap-1 secrets-out-of-common closed)_
_Updated: 2026-05-21 (etap-1 + etap-2 secrets pipeline closed)_
<!--
Status legend:
@@ -331,7 +331,7 @@ Done — 🟢; unblock `secrets-manager-adopt`.
---
## 🔴 [secrets-manager-adopt] — Этап 2 secret-management: внедрить `pass` (gpg-based password-store) — encrypted-at-rest secrets + cross-machine sync через private Gitea repo с encrypted blobs.
## 🟢 [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.
@@ -339,8 +339,56 @@ Done — 🟢; unblock `secrets-manager-adopt`.
См. `concepts/admin-infra-project.md` §Initial admin agenda E.3.
**Status:** active
**Where I stopped:** Стартовал прямо за etap-1 (in same session) — gpg/pass install + key gen — next step.
**Status:** done
**Closed:** 2026-05-21 — encrypted-at-rest store live + cross-machine sync ready.
**Components installed:**
- **gpg key:** RSA 4096, no expiration, fingerprint `0CB0B0190149295E8012B438E969C2C24FE3F59E`, uid `Victor Kuznetsov <vitya.kuznetsov@gmail.com>`. User-managed passphrase.
- **pass v1.7.4:** manual clone `https://git.zx2c4.com/password-store``~/.local/src/password-store/`, symlinked at `~/.local/bin/pass` (PATH'е уже был `~/.local/bin`). Deps: gpg ✅, git ✅, getopt ✅. `tree` отсутствует (cosmetic; `pass ls` падает — non-critical).
- **gpg-agent config:** `~/.gnupg/gpg-agent.conf``pinentry-program C:/Program Files/Git/usr/bin/pinentry-w32.exe` + `default-cache-ttl 2592000` (30 days) + `max-cache-ttl 2592000`. Один passphrase prompt в 30 дней (или после reboot).
**Pass-store layout (5 entries):**
| Pass path | Source plaintext | Type |
|---|---|---|
| `interns/ollama-cloud-api-key` | `interns.env` `OLLAMA_CLOUD_API_KEY` | single value |
| `gitea/admin-token` | `gitea-token.txt` | single value |
| `vds-kzntsv/full-env` | `vds-kzntsv.env` (whole file) | multiline dotenv |
| `kreknin/full-env` | `kreknin.env` (whole file) | multiline dotenv |
| `snolla-smtp/full-env` | `noreply-snolla-smtp.env` (whole file) | multiline dotenv |
**Consumer integration:**
- `mcp__interns__*``~/.local/bin/interns-mcp-launcher.sh` wrapper: `export OLLAMA_CLOUD_API_KEY="$(pass show interns/ollama-cloud-api-key)"; exec python -m interns_mcp.server`. Wired в `~/.claude.json` `mcpServers.interns` (`command: bash.exe`, `args: [/c/.../launcher.sh]`, `env.INTERNS_PYTHON: /c/.../python.exe`). Backup `~/.claude.json.bak-pre-pass-20260521-144943`.
- `meeting-room` CLI — config.py читает env-override (если установлен) → fallback на `~/.config/projects-secrets/interns.env` (теперь нет). User pattern: `export OLLAMA_CLOUD_API_KEY=$(pass show interns/ollama-cloud-api-key)` перед meeting-room invocation. Documented в `~/.config/projects-secrets/README.md`.
**Cross-machine sync:**
- Private Gitea repo `OpeItcLoc03/password-store-private` (private=true) created via API. URL: `https://git.kzntsv.site/OpeItcLoc03/password-store-private.git`.
- `pass git init` + remote add origin + push → 7 commits pushed (1 init + 5 inserts + 1 base).
- Recovery на новой машине: install `pass`, `gpg --import privkey.asc`, `git clone <url> ~/.password-store`, `pass show <any>` для cache-warm. Documented в README.
**Cleanup plaintext:** `~/.config/projects-secrets/` — удалены 5 secret files (`interns.env`, `gitea-token.txt`, `vds-kzntsv.env`, `kreknin.env`, `noreply-snolla-smtp.env`). Остались marker README (rewritten под pass-pattern), `.gitignore`, 2 examples. Acceptance per spec ✅ — "пуст или содержит только README".
**Verification:**
-`pass show interns/ollama-cloud-api-key` → 57-char OLLAMA value (matches original interns.env)
- ✅ Wrapper smoke: `timeout 3 bash ~/.local/bin/interns-mcp-launcher.sh </dev/null` → EXIT=0, no startup error
- ✅ All 5 entries decrypt without re-prompt (gpg-agent cache warm)
-`pass git status` → clean, up to date with origin/master
- ⚠️ Full `mcp__interns__bulk_text_read` smoke требует Claude Code restart (текущая сессия bound к старому Python процессу — у него env уже cache'нут).
**Open follow-ups:**
1. **meeting-room WIP unblock:** etap-1 edit `meeting_room/config.py` сидит unstaged рядом с pre-existing dirty state (UU conflict в `.tasks/STATUS.md` + 13 staged files не моя работа). Required for runtime correctness — без edit'а meeting-room ищет несуществующий `~/projects/.common/secrets/interns.env`. Опционально: добавить subprocess-pass fallback в config.py (pass show с timeout) для transparent integration без manual export. Решение user'а.
2. **setup-interns SKILL update (next task candidate):** v0.4.0 описывает plaintext-`.env` write path как canonical. После etap-2 canonical — pass-based wrapper. Нужен SKILL bump 0.4.0 → 0.5.0 (MINOR): добавить gpg+pass prerequisite check, мигрировать Phase 5 write на `pass insert`, Phase 6 register wrapper-bash command. Большое обновление — отдельная task'а через `tasks_create`.
3. **New endpoints in `interns/config.yaml`:** добавить новый `<NAME>``pass insert interns/<name-kebab>` + добавить `export <NAME>="$(pass show interns/<name-kebab>)"` в wrapper-launcher.sh. Pattern documented в README.
4. **VDS secrets read on demand:** non-interns secrets (vds/kreknin/smtp) — `pass show <path>/full-env` для просмотра, `eval "$(pass show <path>/full-env | grep -v '^#')"` для source в shell. Pattern documented в README.
Acceptance per spec: ✅ all 4 criteria met (`~/.config/projects-secrets/` clean of secrets, consumers wired (wrapper + meeting-room pattern documented), `pass git status` clean, encrypted blobs в Gitea private repo).
**Commits:**
- `~/.password-store/` (OpeItcLoc03/password-store-private): 7 commits pushed
- `~/.claude.json`: edited locally (config, not git-tracked beyond bak file)
- New files: `~/.local/bin/interns-mcp-launcher.sh`, `~/.gnupg/gpg-agent.conf`, README rewritten at `~/.config/projects-secrets/`
- This STATUS.md update committed in OpeItcLoc03/admin
**Where I stopped:** (done)
**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.