diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index 9e16cda..0db024f 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -128,6 +128,7 @@ {"id":"ops-jrz1-qts","title":"RFC: Seamless dev access to ops-jrz1 repo","description":"Devs/agents on jrz1 should be able to access git.clarun.xyz (Forgejo on same server) seamlessly. Goal: minimal friction, leverage existing SSH access.\n\n## Orch Consensus (2026-01-08)\n\nRan serial consensus with flash-or, gemini, gpt, qwen. **Unanimous recommendation: Option B (SSH keys synced to Forgejo)**.\n\n### Why Option B Wins\n\n| Criterion | Advantage |\n|-----------|-----------|\n| Attribution | Each commit/push tied to specific user (critical for agents vs humans) |\n| Security | No PATs in plaintext, keys already used for VPS access |\n| Friction | SSH \"just works\" once key is in Forgejo |\n| Hooks/CI | Forgejo's server-side hooks, protections, webhooks all work |\n\n### Options Rejected\n\n- **D (shared account)**: Loses attribution, security nightmare as project grows\n- **E (filesystem access)**: Bypasses hooks, causes permission conflicts between `git` user and Unix users\n- **C (PAM/LDAP)**: Overkill for single VPS\n- **A (HTTP+PAT)**: Token lifecycle/rotation is extra work, agents leak tokens\n\n### Implementation Plan\n\nExtend `dev-add.sh` to:\n\n1. **Create Forgejo user** via admin API (using token from sops)\n2. **Upload SSH key** to Forgejo profile\n3. **Set git identity** (`user.name`, `user.email`)\n4. **Pre-seed known_hosts** (critical for agents - prevents interactive prompt hang)\n\n```bash\n# Key additions to dev-add.sh:\n\n# 1. Create Forgejo user\ncurl -X POST \"http://localhost:3000/api/v1/admin/users\" \\\n -H \"Authorization: token $FORGEJO_TOKEN\" \\\n -d '{\"username\": \"'$USER'\", \"email\": \"'$USER'@clarun.xyz\", \"password\": \"...\", \"must_change_password\": false}'\n\n# 2. Upload SSH key\ncurl -X POST \"http://localhost:3000/api/v1/admin/users/$USER/keys\" \\\n -H \"Authorization: token $FORGEJO_TOKEN\" \\\n -d '{\"title\": \"vps-local-key\", \"key\": \"'$PUB_KEY'\"}'\n\n# 3. Git identity\nsu - \"$USER\" -c \"git config --global user.name '$USER'\"\nsu - \"$USER\" -c \"git config --global user.email '$USER@clarun.xyz'\"\n\n# 4. Pre-seed known_hosts (prevents agent hang on first git operation)\nsu - \"$USER\" -c \"ssh-keyscan localhost \u003e\u003e ~/.ssh/known_hosts 2\u003e/dev/null\"\nsu - \"$USER\" -c \"ssh-keyscan git.clarun.xyz \u003e\u003e ~/.ssh/known_hosts 2\u003e/dev/null\"\n```\n\n### Optional Add-on\n\nOption F (anonymous reads) can supplement B for public repos - useful for \"clone without setup\" but doesn't solve writes.\n\n### Implementation Considerations\n\n- Make idempotent (don't fail if user/key already exists)\n- Handle `dev-remove.sh` cleanup (delete Forgejo user too)\n- Forgejo API token available in sops: `forgejo-api-token`\n- Consider retroactive sync script for existing users\n","notes":"PAM check: No external auth sources configured. Proceeding with API path.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T18:42:23.691289101-08:00","created_by":"dan","updated_at":"2026-01-08T18:00:57.755160223-08:00","closed_at":"2026-01-08T18:00:57.755160223-08:00","close_reason":"Implemented Forgejo integration for dev user provisioning. dev-add.sh now creates Forgejo accounts and uploads SSH keys automatically."} {"id":"ops-jrz1-qxr","title":"mautrix-slack message edit panic (upstream bug)","description":"Bridge upgraded to v25.11. Need to verify if edit panic is fixed by testing a Slack message edit. Watch logs: journalctl -u mautrix-slack -f | grep -E 'ERR|panic|edit'","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-05T18:22:38.18203834-08:00","updated_at":"2025-12-05T19:36:00.556011621-08:00","closed_at":"2025-12-05T19:36:00.556011621-08:00","dependencies":[{"issue_id":"ops-jrz1-qxr","depends_on_id":"ops-jrz1-03o","type":"blocks","created_at":"2025-12-05T18:24:23.259399275-08:00","created_by":"daemon","metadata":"{}"}]} {"id":"ops-jrz1-rkp","title":"Add egress abuse watchdog","description":"Monitor for users hitting egress rate limits, kill if sustained.\n\n## Script: /usr/local/bin/egress-watchdog\n```bash\n#\\!/usr/bin/env bash\n# Kill users who keep hitting egress limits\nTHRESHOLD=10 # EGRESS-LIMIT hits per minute\nCOUNTFILE=\"/var/lib/egress-watchdog\"\nmkdir -p \"$COUNTFILE\"\n\n# Count recent limit hits per UID\njournalctl -k --since \"1 minute ago\" 2\u003e/dev/null | grep \"EGRESS-LIMIT\" | \\\n grep -oP 'UID=\\K[0-9]+' | sort | uniq -c | while read count uid; do\n \n user=$(getent passwd \"$uid\" | cut -d: -f1)\n [ -z \"$user\" ] \u0026\u0026 continue\n \n if [ \"$count\" -gt \"$THRESHOLD\" ]; then\n strikes=$(cat \"$COUNTFILE/$user\" 2\u003e/dev/null || echo 0)\n strikes=$((strikes + 1))\n echo \"$strikes\" \u003e \"$COUNTFILE/$user\"\n logger -t egress-watchdog \"User $user hit egress limit $count times (strike $strikes/3)\"\n \n if [ \"$strikes\" -ge 3 ]; then\n /usr/local/bin/killswitch \"$user\" \"egress abuse ($count hits)\"\n rm -f \"$COUNTFILE/$user\"\n fi\n else\n rm -f \"$COUNTFILE/$user\"\n fi\ndone\n```\n\n## Behavior\n- Runs every minute (same timer as CPU watchdog, or separate)\n- 3 consecutive minutes of \u003e10 blocked connections = kill\n- Works with egress rate limiting (ops-jrz1-cmv)\n\n## Dependencies\n- Requires ops-jrz1-cmv (egress rate limiting)\n- Requires ops-jrz1-396 (killswitch script)","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-02T20:21:09.516724064-08:00","created_by":"dan","updated_at":"2026-01-03T06:02:02.132992356-08:00","closed_at":"2026-01-03T06:02:02.132992356-08:00","close_reason":"Egress watchdog deployed and tested. Script monitors EGRESS-LIMIT kernel log entries, tracks strikes per user, kills after 3 strikes.","dependencies":[{"issue_id":"ops-jrz1-rkp","depends_on_id":"ops-jrz1-396","type":"blocks","created_at":"2026-01-02T20:21:14.314011866-08:00","created_by":"dan"},{"issue_id":"ops-jrz1-rkp","depends_on_id":"ops-jrz1-cmv","type":"blocks","created_at":"2026-01-02T20:21:14.352411765-08:00","created_by":"dan"}]} +{"id":"ops-jrz1-s6p","title":"Research: Password delivery for auto-provisioned Forgejo users","description":"When dev-add.sh creates Forgejo accounts, users get random passwords with must_change_password=true but no way to learn the password.\n\n## Problem\n- SSH git access works (key uploaded)\n- Web UI access broken (can't log in to change password)\n\n## Options to Research\n- Print to terminal\n- Secure file in home directory\n- Email delivery\n- Matrix message\n- QR code\n- Skip password entirely (SSH-only)\n- OAuth/SSO integration\n\n## Context\n- Most users are agents (don't need web UI)\n- Human devs may want PR/issue access\n- Low frequency onboarding","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-08T18:06:56.473648691-08:00","created_by":"dan","updated_at":"2026-01-08T18:06:56.473648691-08:00"} {"id":"ops-jrz1-s8x","title":"Add health check endpoint for Matrix homeserver monitoring","description":"modules/dev-services.nix Matrix service has no health check for monitoring. Add nginx location for /_matrix/client/versions health probe.","status":"open","priority":4,"issue_type":"task","created_at":"2026-01-05T15:44:34.407481321-08:00","created_by":"dan","updated_at":"2026-01-05T15:44:34.407481321-08:00"} {"id":"ops-jrz1-sdz","title":"Remove /usr/local/bin scripts from server","description":"After declarative deployment works, clean up manually deployed scripts from /usr/local/bin on the server.","status":"closed","priority":3,"issue_type":"task","created_at":"2026-01-03T08:39:54.483032394-08:00","created_by":"dan","updated_at":"2026-01-03T09:20:34.591216526-08:00","closed_at":"2026-01-03T09:20:34.591216526-08:00","close_reason":"Removed all manual scripts from /usr/local/bin/","dependencies":[{"issue_id":"ops-jrz1-sdz","depends_on_id":"ops-jrz1-ujw","type":"blocks","created_at":"2026-01-03T08:40:02.851476398-08:00","created_by":"dan"},{"issue_id":"ops-jrz1-sdz","depends_on_id":"ops-jrz1-o9c","type":"blocks","created_at":"2026-01-03T08:45:48.023849189-08:00","created_by":"dan"}]} {"id":"ops-jrz1-svr","title":"Make dev-add.sh idempotent or add --update flag","description":"scripts/dev-add.sh:42-45 exits with error if user exists. Can't safely re-run to update SSH key or fix partial failures. Add --update flag or make idempotent by default.","status":"closed","priority":3,"issue_type":"task","created_at":"2026-01-05T15:44:33.963322361-08:00","created_by":"dan","updated_at":"2026-01-05T20:45:31.653910595-08:00","closed_at":"2026-01-05T20:45:31.653910595-08:00","close_reason":"Made idempotent - safe to re-run, updates existing users"}