Rename learner to dev across codebase
- scripts/learner-*.sh → scripts/dev-*.sh - docs/learner-*.md → docs/dev-*.md - tests/test-learner-env.sh → tests/test-dev-env.sh - Update all internal references 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
26be2b1548
commit
bc81b4ec15
|
|
@ -34,7 +34,7 @@
|
|||
{"id":"ops-jrz1-ayl","title":"Rename sna-instagram-bot to something memorable","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-08T16:54:31.223265094-08:00","updated_at":"2025-12-08T16:54:31.223265094-08:00"}
|
||||
{"id":"ops-jrz1-b09","title":"Research: Forgejo backup strategy","description":"Consider backup strategy for the Forgejo instance.\n\n## Questions\n- What data needs backing up? (repos, issues, users, config)\n- Where to back up to? (off-site, object storage, etc.)\n- Frequency?\n- Restore procedure?\n\n## Context\nForgejo runs on ops-jrz1 at :3000, stores git repos and metadata.","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-02T19:01:55.854723242-08:00","created_by":"dan","updated_at":"2026-01-02T19:01:55.854723242-08:00"}
|
||||
{"id":"ops-jrz1-b8v","title":"Enable nix-ld for VS Code Remote SSH","description":"VS Code Remote-SSH requires nix-ld to run the VS Code Server on NixOS.\n\n## Status\n- [x] Config added to hosts/ops-jrz1.nix\n- [x] nix flake check passed\n- [ ] Deploy to server\n\n## Config Added\n```nix\nprograms.nix-ld.enable = true;\nprograms.nix-ld.libraries = with pkgs; [\n stdenv.cc.cc.lib\n zlib\n openssl\n];\n```\n\n## Blocks\n- VS Code Remote-SSH (won't work without this)\n- Testing Claude Code extension over Remote-SSH\n- JetBrains Gateway (same issue)\n\n## Deploy Command\n```bash\nnixos-rebuild switch --flake .#ops-jrz1 --target-host root@ops-jrz1 --build-host localhost\n```","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T22:24:15.465531482-05:00","created_by":"dan","updated_at":"2026-01-02T10:22:07.3354851-08:00","closed_at":"2026-01-02T10:22:07.3354851-08:00","close_reason":"Deployed - nix-ld active at /lib64/ld-linux-x86-64.so.2"}
|
||||
{"id":"ops-jrz1-bbn","title":"Research: Resource limits and quotas","description":"Should we limit CPU/memory/disk per learner?\n\n## Current state\n- No limits configured\n- Single VPS shared by all users\n- 2GB RAM, 1 vCPU (Vultr $6 tier?)\n\n## Options\n1. **No limits** - Trust learners, monitor manually\n2. **Systemd slices** - cgroups for user sessions\n3. **Disk quotas** - Limit ~/\n4. **ulimits** - Process limits\n\n## Questions\n- What resources does a typical dev session use?\n- What about `go build` or `npm install`?\n- Is this premature optimization?","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-02T12:27:34.884865507-08:00","created_by":"dan","updated_at":"2026-01-02T12:27:34.884865507-08:00"}
|
||||
{"id":"ops-jrz1-bbn","title":"Research: Resource limits and quotas","description":"Should we limit CPU/memory/disk per learner?\n\n## Current state\n- No limits configured\n- Single VPS shared by all users\n- 2GB RAM, 1 vCPU (Vultr $6 tier?)\n\n## Options\n1. **No limits** - Trust learners, monitor manually\n2. **Systemd slices** - cgroups for user sessions\n3. **Disk quotas** - Limit ~/\n4. **ulimits** - Process limits\n\n## Questions\n- What resources does a typical dev session use?\n- What about `go build` or `npm install`?\n- Is this premature optimization?","status":"closed","priority":3,"issue_type":"task","created_at":"2026-01-02T12:27:34.884865507-08:00","created_by":"dan","updated_at":"2026-01-03T10:11:09.79120117-08:00","closed_at":"2026-01-03T10:11:09.79120117-08:00","close_reason":"Implemented: systemd slices (user.slice MemoryMax=80%, TasksMax=500) + per-user limits (MemoryMax=50%, TasksMax=200, CPUQuota=200%). Disk quotas tracked separately in ops-jrz1-oxx."}
|
||||
{"id":"ops-jrz1-bhk","title":"Add disk quotas for user workspaces","description":"User could fill host disk via /var/lib/vscode/\u003cuser\u003e/. Add per-directory quotas or monitoring/alerting on disk usage.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-05T15:32:41.199417226-08:00","updated_at":"2025-12-28T00:05:44.7635372-05:00","closed_at":"2025-12-28T00:05:44.7635372-05:00","close_reason":"Parent epic cancelled - browser-based dev approach abandoned","dependencies":[{"issue_id":"ops-jrz1-bhk","depends_on_id":"ops-jrz1-3so","type":"parent-child","created_at":"2025-12-05T17:05:47.309592029-08:00","created_by":"daemon","metadata":"{}"}]}
|
||||
{"id":"ops-jrz1-blh","title":"mautrix-slack edit panic persists in v25.11","description":"mautrix-slack panic on rapid message edits (race condition)\n\n**Root cause**: Edit event arrives before original message is stored in DB. ConvertEdit accesses nil metadata.\n\n**Location**: handleslack.go:575 - has TODO comment: 'this can panic?'\n\n**Reproduction**: Edit a Slack message within ~1 second of sending\n\n**Upstream status**: \n- v25.11 is latest (we're on it)\n- Known to devs (TODO in code)\n- No open issue filed yet\n\n**Stack trace**:\ngo.mau.fi/mautrix-slack/pkg/connector.(*SlackMessage).ConvertEdit\n handleslack.go:575\nmaunium.net/go/mautrix/bridgev2.(*Portal).handleRemoteEdit\n portal.go:2838","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-05T19:40:33.255395189-08:00","updated_at":"2025-12-28T00:06:14.637057055-05:00","closed_at":"2025-12-28T00:06:14.637057055-05:00","close_reason":"Duplicate of ops-jrz1-f15 which has fix ready","comments":[{"id":2,"issue_id":"ops-jrz1-blh","author":"dan","text":"Confirmed panic exists in nixpkgs-unstable from 2025-12-02. Fix will be addressed via platform upgrade (see ops-jrz1-00e).","created_at":"2025-12-08T23:54:57Z"}]}
|
||||
{"id":"ops-jrz1-cmv","title":"Add egress rate limiting (iptables)","description":"Hard limit outbound connections per user to prevent mass exfil/scanning.\n\n## Config\n```nix\nnetworking.firewall.extraCommands = ''\n # Rate limit new outbound connections for regular users (uid 1000+)\n iptables -A OUTPUT -m state --state NEW -m owner --uid-owner 1000:65534 \\\n -m limit --limit 30/min --limit-burst 60 -j ACCEPT\n iptables -A OUTPUT -m state --state NEW -m owner --uid-owner 1000:65534 \\\n -j LOG --log-prefix \"EGRESS-LIMIT: \"\n iptables -A OUTPUT -m state --state NEW -m owner --uid-owner 1000:65534 \\\n -j REJECT\n'';\n```\n\n## Behavior\n- 30 new connections/min sustained, burst of 60\n- Over limit: logged and rejected\n- Doesn't affect established connections\n\n## Testing\n- `for i in {1..100}; do curl -s ifconfig.me \u0026 done`\n- Should see EGRESS-LIMIT in journal after ~60","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-02T20:16:32.276607792-08:00","created_by":"dan","updated_at":"2026-01-02T21:12:35.5888406-08:00","closed_at":"2026-01-02T21:12:35.5888406-08:00","close_reason":"Closed"}
|
||||
|
|
@ -62,7 +62,7 @@
|
|||
{"id":"ops-jrz1-kg0","title":"Switch to subdomain routing (dan.code.clarun.xyz)","description":"Path-based routing (/code/dan/) is fragile. Extensions assume root path, cookies scope incorrectly, PWA breaks. Switch to wildcard subdomains for cleaner isolation.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-05T15:32:19.283887085-08:00","updated_at":"2025-12-05T17:23:11.983564455-08:00","closed_at":"2025-12-05T17:23:11.983564455-08:00","dependencies":[{"issue_id":"ops-jrz1-kg0","depends_on_id":"ops-jrz1-3so","type":"parent-child","created_at":"2025-12-05T17:05:47.043217984-08:00","created_by":"daemon","metadata":"{}"}]}
|
||||
{"id":"ops-jrz1-kia","title":"Container reset mechanism (keep workspace)","description":"If user breaks their environment, need simple way to wipe container and restore default image while preserving /workspace. Script or admin command.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-05T15:32:31.045592689-08:00","updated_at":"2025-12-28T00:05:44.757842852-05:00","closed_at":"2025-12-28T00:05:44.757842852-05:00","close_reason":"Parent epic cancelled - browser-based dev approach abandoned","dependencies":[{"issue_id":"ops-jrz1-kia","depends_on_id":"ops-jrz1-3so","type":"parent-child","created_at":"2025-12-05T17:05:47.275530016-08:00","created_by":"daemon","metadata":"{}"}]}
|
||||
{"id":"ops-jrz1-lae","title":"egress-watchdog: Fix subshell gotcha in while-read pipeline","description":"while-read in pipeline runs in subshell - variables don't persist outside loop. Use process substitution: while read ...; done \u003c \u003c(echo \"$hits\" | grep ...). scripts/egress-watchdog:25","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-03T08:17:35.401495377-08:00","created_by":"dan","updated_at":"2026-01-03T09:30:50.535018144-08:00","closed_at":"2026-01-03T09:30:50.535018144-08:00","close_reason":"Fixed: using process substitution instead of pipeline subshell"}
|
||||
{"id":"ops-jrz1-meh","title":"cpu-watchdog: Add flock for atomic strike counter updates","description":"Read-modify-write of strike counter not atomic. Systemd timer serializes runs so low risk now, but add flock if parallelism added later. scripts/cpu-watchdog:29-31","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-03T08:17:35.759126212-08:00","created_by":"dan","updated_at":"2026-01-03T08:26:28.66076716-08:00"}
|
||||
{"id":"ops-jrz1-meh","title":"cpu-watchdog: Add flock for atomic strike counter updates","description":"Read-modify-write of strike counter not atomic. Systemd timer serializes runs so low risk now, but add flock if parallelism added later. scripts/cpu-watchdog:29-31","status":"closed","priority":3,"issue_type":"task","created_at":"2026-01-03T08:17:35.759126212-08:00","created_by":"dan","updated_at":"2026-01-03T10:08:38.50903714-08:00","closed_at":"2026-01-03T10:08:38.50903714-08:00","close_reason":"Wontfix: systemd timer serializes runs, race condition is theoretical only"}
|
||||
{"id":"ops-jrz1-mh2","title":"Research: Forgejo integration for shared projects","description":"How does beads/bd integrate with our Forgejo git server (git.clarun.xyz)?\n\n## Questions\n- Can bd sync to Forgejo repos?\n- How do dev users on the server collaborate on shared projects?\n- Is there a git workflow that makes sense (forks? shared repo? branches?)\n- Does bd need any special config for Forgejo vs GitHub?\n\n## Context\n- Forgejo running at git.clarun.xyz\n- Dev users have SSH access to server\n- May want shared project tracking via beads","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-02T16:24:01.771168961-08:00","created_by":"dan","updated_at":"2026-01-02T16:24:01.771168961-08:00"}
|
||||
{"id":"ops-jrz1-ndl","title":"Browser-based dev environment (code-server)","description":"Explore setting up browser-based development:\n\nOptions:\n- code-server / openvscode-server - VS Code in browser\n- ttyd / wetty - terminal in browser \n- PWA install to home screen for native app feel\n\nCould combine with Tailscale for secure access without exposing ports.\n\nRef: ops-dev thin client brainstorm session","notes":"Design doc created: specs/004-browser-dev-environment/design.md - covers architecture, tech choices, resource planning, security model, rollout phases","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-04T15:08:02.406274744-08:00","updated_at":"2025-12-05T17:05:52.872944892-08:00","closed_at":"2025-12-05T17:05:52.872944892-08:00"}
|
||||
{"id":"ops-jrz1-nir","title":"RFC: SSH log noise reduction strategy","description":"Research showed 99.8% of SSH logs are scanner noise (9000 failed attempts/day). Options: (1) Change SSH port - simple, ~99% reduction (2) journald filter - surgical but complex (3) LogLevel ERROR - loses successful login audit trail (4) fail2ban - bans IPs, partial reduction. Orch consensus: Gemini opposed LogLevel ERROR due to losing audit trail, GPT supported. Need RFC to decide approach. See posture review from Dec 2025 session.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-04T22:55:13.990334935-08:00","updated_at":"2025-12-04T22:55:13.990334935-08:00"}
|
||||
|
|
@ -74,7 +74,7 @@
|
|||
{"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-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-t73","title":"Rename learner to dev in scripts and docs","description":"Rename terminology from \"learner\" to \"dev\" or \"user\" across:\n\n- scripts/learner-add.sh → dev-add.sh\n- scripts/learner-remove.sh → dev-remove.sh\n- /etc/slack-learner.env → /etc/slack-dev.env\n- learners group → devs group\n- docs/learner-*.md\n- tests/test-learner-env.sh\n\nLow priority cleanup.","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-02T12:32:40.340984626-08:00","created_by":"dan","updated_at":"2026-01-02T12:32:40.340984626-08:00"}
|
||||
{"id":"ops-jrz1-t73","title":"Rename learner to dev in scripts and docs","description":"Rename terminology from \"learner\" to \"dev\" or \"user\" across:\n\n- scripts/learner-add.sh → dev-add.sh\n- scripts/learner-remove.sh → dev-remove.sh\n- /etc/slack-learner.env → /etc/slack-dev.env\n- learners group → devs group\n- docs/learner-*.md\n- tests/test-learner-env.sh\n\nLow priority cleanup.","status":"closed","priority":3,"issue_type":"task","created_at":"2026-01-02T12:32:40.340984626-08:00","created_by":"dan","updated_at":"2026-01-03T10:37:34.321661169-08:00","closed_at":"2026-01-03T10:37:34.321661169-08:00","close_reason":"Renamed learner to dev across scripts, docs, tests, and configuration"}
|
||||
{"id":"ops-jrz1-u0w","title":"Security review of running server","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-04T21:03:22.420507724-08:00","updated_at":"2025-12-04T21:04:31.989886731-08:00","closed_at":"2025-12-04T21:04:31.989886731-08:00"}
|
||||
{"id":"ops-jrz1-ujw","title":"Update systemd services to use nix store paths","description":"Change ExecStart from /usr/local/bin/cpu-watchdog to use the derivation path. Either reference package directly or use pkgs.writeShellApplication.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-03T08:39:54.227335183-08:00","created_by":"dan","updated_at":"2026-01-03T09:20:08.685831615-08:00","closed_at":"2026-01-03T09:20:08.685831615-08:00","close_reason":"Systemd services now reference Nix store paths via ${pkg}/bin/script","dependencies":[{"issue_id":"ops-jrz1-ujw","depends_on_id":"ops-jrz1-5ef","type":"blocks","created_at":"2026-01-03T08:40:02.815677839-08:00","created_by":"dan"}]}
|
||||
{"id":"ops-jrz1-vix","title":"Evaluate home-manager for per-user config","description":"Evaluate whether home-manager adds value for our setup.\n\n## What home-manager could manage\n- Shell config (.bashrc, .zshrc)\n- Git config (.gitconfig)\n- Tool configs (~/.config/*)\n- direnv integration\n\n## Questions\n- Do we need declarative per-user dotfiles?\n- Is the complexity worth it for a small team?\n- Can we start without it and add later?\n\n## Recommendation from consensus\n\"Optional but recommended\" - good for pushing default configs to all devs.\nStart without it, add if pain point emerges.","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-02T16:36:04.849881753-08:00","created_by":"dan","updated_at":"2026-01-02T16:36:04.849881753-08:00"}
|
||||
|
|
@ -83,5 +83,5 @@
|
|||
{"id":"ops-jrz1-wj2","title":"Design API key provisioning strategy","description":"opencode needs API keys (OpenAI, Anthropic). Options: 1) Shared key with proxy + rate limiting, 2) Per-user keys in sops-nix. Need to prevent key exposure and enable usage tracking.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-05T15:32:19.526073243-08:00","updated_at":"2025-12-05T17:25:10.534718515-08:00","closed_at":"2025-12-05T17:25:10.534718515-08:00","dependencies":[{"issue_id":"ops-jrz1-wj2","depends_on_id":"ops-jrz1-3so","type":"parent-child","created_at":"2025-12-05T17:05:47.103332379-08:00","created_by":"daemon","metadata":"{}"}]}
|
||||
{"id":"ops-jrz1-xz1","title":"Fix maubot admin UI exposed to internet (port 29316)","description":"Maubot admin UI on port 29316 is publicly accessible (returns 401 but API surface exposed). Firewall explicitly allows this port. Risk: brute force on admin password, direct exploit of any maubot vulnerabilities. Fix: bind to 127.0.0.1 only, remove from firewall, access via SSH tunnel.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-04T21:03:22.531676543-08:00","updated_at":"2025-12-04T22:35:24.162735368-08:00","closed_at":"2025-12-04T22:35:24.162735368-08:00"}
|
||||
{"id":"ops-jrz1-xz7","title":"Research: Multi-user auth storage for agentic coders","description":"Investigate where auth credentials are stored for each agentic coder when multiple users authenticate:\n\n## Questions\n- Claude Code: Where is OAuth token stored? ~/.claude? Conflicts between users?\n- opencode: Auth storage location?\n- gemini-cli: Auth storage?\n- codex: Auth storage?\n\n## Goal\nUnderstand if there are isolation issues when multiple users auth on same server.","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-02T17:30:15.028994987-08:00","created_by":"dan","updated_at":"2026-01-02T17:30:15.028994987-08:00"}
|
||||
{"id":"ops-jrz1-yhu","title":"configuration.nix: Consider custom iptables chain for egress rules","description":"Same iptables match pattern repeated 8 times. Could create custom chain for cleaner rule management. Optional - readability tradeoff. configuration.nix:68-79","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-03T08:17:35.532609792-08:00","created_by":"dan","updated_at":"2026-01-03T08:26:28.411759428-08:00"}
|
||||
{"id":"ops-jrz1-yhu","title":"configuration.nix: Consider custom iptables chain for egress rules","description":"Same iptables match pattern repeated 8 times. Could create custom chain for cleaner rule management. Optional - readability tradeoff. configuration.nix:68-79","status":"closed","priority":3,"issue_type":"task","created_at":"2026-01-03T08:17:35.532609792-08:00","created_by":"dan","updated_at":"2026-01-03T10:07:28.725278889-08:00","closed_at":"2026-01-03T10:07:28.725278889-08:00","close_reason":"Wontfix: current inline rules work fine, custom chain is marginal improvement"}
|
||||
{"id":"ops-jrz1-zvh","title":"Fix maubot health check (failing every 5 min)","description":"Health check at /_matrix/maubot/v1/version returns 401 (auth required). Check script doesn't provide auth token. Spamming error logs every 5 minutes.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-04T22:55:25.755541054-08:00","updated_at":"2025-12-05T02:00:19.284410671-08:00","closed_at":"2025-12-05T02:00:19.284410671-08:00"}
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ NixOS-based Matrix homeserver (conduwuit) with mautrix-slack bridge for Slack
|
|||
├── killswitch # Emergency user termination
|
||||
├── cpu-watchdog # CPU abuse detection
|
||||
├── egress-watchdog # Egress rate limit abuse detection
|
||||
├── learner-add.sh # Add dev user account
|
||||
└── learner-remove.sh # Remove dev user account
|
||||
├── dev-add.sh # Add dev user account
|
||||
└── dev-remove.sh # Remove dev user account
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
|
|
|||
|
|
@ -35,16 +35,16 @@ let
|
|||
# Admin Scripts - Added to systemPackages for interactive use
|
||||
# ==========================================================================
|
||||
|
||||
learner-add = pkgs.writeShellApplication {
|
||||
name = "learner-add";
|
||||
dev-add = pkgs.writeShellApplication {
|
||||
name = "dev-add";
|
||||
runtimeInputs = with pkgs; [ shadow coreutils iproute2 gnugrep gawk ];
|
||||
text = builtins.readFile ./scripts/learner-add.sh;
|
||||
text = builtins.readFile ./scripts/dev-add.sh;
|
||||
};
|
||||
|
||||
learner-remove = pkgs.writeShellApplication {
|
||||
name = "learner-remove";
|
||||
dev-remove = pkgs.writeShellApplication {
|
||||
name = "dev-remove";
|
||||
runtimeInputs = with pkgs; [ shadow coreutils gnutar procps findutils ];
|
||||
text = builtins.readFile ./scripts/learner-remove.sh;
|
||||
text = builtins.readFile ./scripts/dev-remove.sh;
|
||||
};
|
||||
|
||||
in
|
||||
|
|
@ -83,8 +83,8 @@ in
|
|||
# For npm-based AI tools (gemini-cli, codex): users run npm install
|
||||
nodejs_22
|
||||
# Admin scripts (declarative deployment)
|
||||
learner-add
|
||||
learner-remove
|
||||
dev-add
|
||||
dev-remove
|
||||
];
|
||||
|
||||
# Add ~/.local/bin and /usr/local/bin to PATH for manually installed tools
|
||||
|
|
@ -117,7 +117,7 @@ in
|
|||
|
||||
# Egress controls for regular users
|
||||
# UID range: 1000 (first regular user) to 65534 (nobody - excluded from controls)
|
||||
# This covers all learner accounts while excluding system services
|
||||
# This covers all dev accounts while excluding system services
|
||||
extraCommands = ''
|
||||
# Log all new outbound connections from regular users
|
||||
iptables -A OUTPUT -m state --state NEW -m owner --uid-owner 1000:65534 \
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
# Learner Account Administration
|
||||
# Dev Account Administration
|
||||
|
||||
Guide for managing learner accounts on the maubot development server.
|
||||
Guide for managing dev accounts on the maubot development server.
|
||||
|
||||
## Adding a Learner
|
||||
## Adding a Dev
|
||||
|
||||
1. Get the learner's SSH public key (they run `cat ~/.ssh/id_ed25519.pub`)
|
||||
1. Get the dev's SSH public key (they run `cat ~/.ssh/id_ed25519.pub`)
|
||||
|
||||
2. SSH to the server and run:
|
||||
```bash
|
||||
sudo /path/to/scripts/learner-add.sh <username> '<ssh-public-key>'
|
||||
sudo /path/to/scripts/dev-add.sh <username> '<ssh-public-key>'
|
||||
```
|
||||
|
||||
Example:
|
||||
```bash
|
||||
sudo ./scripts/learner-add.sh alice 'ssh-ed25519 AAAAC3... alice@laptop'
|
||||
sudo ./scripts/dev-add.sh alice 'ssh-ed25519 AAAAC3... alice@laptop'
|
||||
```
|
||||
|
||||
3. The script will output onboarding instructions - send these to the learner.
|
||||
3. The script will output onboarding instructions - send these to the dev.
|
||||
|
||||
### What Gets Created
|
||||
|
||||
|
|
@ -24,37 +24,37 @@ Guide for managing learner accounts on the maubot development server.
|
|||
- `~/plugins/hello_<username>/` - starter maubot plugin
|
||||
- The plugin includes a working hello/ping bot
|
||||
|
||||
## Removing a Learner
|
||||
## Removing a Dev
|
||||
|
||||
```bash
|
||||
sudo ./scripts/learner-remove.sh <username>
|
||||
sudo ./scripts/dev-remove.sh <username>
|
||||
```
|
||||
|
||||
With archive (saves home directory before deleting):
|
||||
```bash
|
||||
sudo ./scripts/learner-remove.sh <username> --archive
|
||||
sudo ./scripts/dev-remove.sh <username> --archive
|
||||
```
|
||||
|
||||
Archives are saved to `/var/backups/learners/`.
|
||||
Archives are saved to `/var/backups/devs/`.
|
||||
|
||||
## Maubot Setup (One-Time)
|
||||
|
||||
After adding the first learner, set up the shared test environment:
|
||||
After adding the first dev, set up the shared test environment:
|
||||
|
||||
1. Create a Matrix bot user for learners (via Element or API)
|
||||
1. Create a Matrix bot user for devs (via Element or API)
|
||||
|
||||
2. In maubot admin (http://localhost:29316):
|
||||
- Add the bot user as a client
|
||||
- Learners will create instances using this client
|
||||
- Devs will create instances using this client
|
||||
|
||||
3. Create `#learners-sandbox` room:
|
||||
3. Create `#devs-sandbox` room:
|
||||
- Create the room in Matrix
|
||||
- Invite the bot user
|
||||
- Give learners the room ID/alias
|
||||
- Give devs the room ID/alias
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Check Learner Plugin Status
|
||||
### Check Dev Plugin Status
|
||||
|
||||
```bash
|
||||
# See what plugins are loaded
|
||||
|
|
@ -62,7 +62,7 @@ curl -s http://localhost:29316/_matrix/maubot/v1/plugins \
|
|||
-H "Authorization: Bearer <token>" | jq
|
||||
```
|
||||
|
||||
### View Learner Directories
|
||||
### View Dev Directories
|
||||
|
||||
```bash
|
||||
ls -la /home/*/plugins/
|
||||
|
|
@ -76,7 +76,7 @@ journalctl -u maubot -f
|
|||
|
||||
## Troubleshooting
|
||||
|
||||
### Learner Can't Connect
|
||||
### Dev Can't Connect
|
||||
|
||||
1. Verify user exists: `id <username>`
|
||||
2. Check SSH key: `cat /home/<username>/.ssh/authorized_keys`
|
||||
|
|
@ -95,7 +95,7 @@ journalctl -u maubot -f
|
|||
|
||||
### Disk Space
|
||||
|
||||
Monitor learner disk usage:
|
||||
Monitor dev disk usage:
|
||||
```bash
|
||||
du -sh /home/*/
|
||||
```
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Maubot Plugin Development - Learner Onboarding
|
||||
# Maubot Plugin Development - Dev Onboarding
|
||||
|
||||
This guide walks you through setting up your development environment for building maubot plugins.
|
||||
|
||||
|
|
@ -77,11 +77,11 @@ Your starter plugin responds to two commands:
|
|||
- Go to "Instances" tab
|
||||
- Click "Create instance"
|
||||
- Select your plugin and a bot user
|
||||
- Add `#learners-sandbox` to allowed rooms
|
||||
- Add `#devs-sandbox` to allowed rooms
|
||||
- Click "Create"
|
||||
|
||||
6. Test in Matrix:
|
||||
- Join the `#learners-sandbox` room
|
||||
- Join the `#devs-sandbox` room
|
||||
- Type `!hello` - your bot should respond!
|
||||
|
||||
## Plugin Development
|
||||
|
|
@ -172,6 +172,6 @@ In the maubot admin UI, go to "Logs" to see recent activity and errors.
|
|||
|
||||
## Getting Help
|
||||
|
||||
- Ask in `#learners-sandbox` - other learners and admins can help
|
||||
- Ask in `#devs-sandbox` - other devs and admins can help
|
||||
- Check the maubot logs for error messages
|
||||
- Review the maubot documentation
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
# Direct Slack Bot Development for Learners
|
||||
# Direct Slack Bot Development for Devs
|
||||
|
||||
Design doc for the "direct to Slack" learner path, bypassing Matrix/maubot.
|
||||
Design doc for the "direct to Slack" dev path, bypassing Matrix/maubot.
|
||||
|
||||
## Overview
|
||||
|
||||
Learners write Python bots using `slack-bolt` that connect directly to Slack via Socket Mode. No Matrix, no bridge, no maubot.
|
||||
Devs write Python bots using `slack-bolt` that connect directly to Slack via Socket Mode. No Matrix, no bridge, no maubot.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
|
|
@ -21,7 +21,7 @@ Learners write Python bots using `slack-bolt` that connect directly to Slack via
|
|||
|
||||
### Credentials
|
||||
|
||||
Shared Slack App tokens stored in `/etc/slack-learner.env`:
|
||||
Shared Slack App tokens stored in `/etc/slack-dev.env`:
|
||||
|
||||
| Variable | Purpose |
|
||||
|----------|---------|
|
||||
|
|
@ -32,24 +32,24 @@ These come from the existing mautrix-slack bridge login (Chochacho workspace, vl
|
|||
|
||||
### Access Control
|
||||
|
||||
- File owned by `root:learners`, mode `640`
|
||||
- Learner users added to `learners` group on creation
|
||||
- File owned by `root:devs`, mode `640`
|
||||
- Dev users added to `devs` group on creation
|
||||
- `.bashrc` sources the env file on login
|
||||
|
||||
### Scripts
|
||||
|
||||
```
|
||||
/usr/local/bin/learner-add.sh <username> '<ssh-pubkey>'
|
||||
/usr/local/bin/learner-remove.sh <username> [--archive]
|
||||
/usr/local/bin/dev-add.sh <username> '<ssh-pubkey>'
|
||||
/usr/local/bin/dev-remove.sh <username> [--archive]
|
||||
```
|
||||
|
||||
## Learner Workflow
|
||||
## Dev Workflow
|
||||
|
||||
### 1. Get Access
|
||||
|
||||
Send SSH pubkey to admin. Admin runs:
|
||||
```bash
|
||||
ssh root@ops-jrz1 'learner-add.sh alice "ssh-ed25519 AAAA..."'
|
||||
ssh root@ops-jrz1 'dev-add.sh alice "ssh-ed25519 AAAA..."'
|
||||
```
|
||||
|
||||
### 2. Connect
|
||||
|
|
@ -166,10 +166,10 @@ say(blocks=[
|
|||
|
||||
### Risks
|
||||
|
||||
1. **Shared tokens** - All learners use same bot identity
|
||||
1. **Shared tokens** - All devs use same bot identity
|
||||
2. **Token exposure** - If leaked, affects everyone
|
||||
3. **Rate limits** - Shared across all bots
|
||||
4. **Process sprawl** - N learners = N processes to manage
|
||||
4. **Process sprawl** - N devs = N processes to manage
|
||||
5. **No guardrails** - Bad code can spam/crash easily
|
||||
|
||||
### Mitigations
|
||||
|
|
@ -184,10 +184,10 @@ say(blocks=[
|
|||
### Process Management
|
||||
|
||||
Options:
|
||||
1. **systemd user services** - Each learner manages their own
|
||||
1. **systemd user services** - Each dev manages their own
|
||||
2. **supervisor** - Central process manager
|
||||
3. **tmux/screen** - Manual but simple
|
||||
4. **Container per learner** - Isolation but complex
|
||||
4. **Container per dev** - Isolation but complex
|
||||
|
||||
### Starter Template
|
||||
|
||||
|
|
@ -197,17 +197,17 @@ Create `~/slack-bot-template/` with:
|
|||
- `Makefile` - run, install targets
|
||||
- `README.md` - Quick start
|
||||
|
||||
### Per-Learner Bot Identity
|
||||
### Per-Dev Bot Identity
|
||||
|
||||
Create separate Slack App per learner:
|
||||
Create separate Slack App per dev:
|
||||
- More setup friction
|
||||
- Full isolation
|
||||
- Each bot has own name/avatar
|
||||
|
||||
### Test Channel
|
||||
|
||||
Create `#learner-sandbox` in Slack:
|
||||
- All learner bots invited
|
||||
Create `#dev-sandbox` in Slack:
|
||||
- All dev bots invited
|
||||
- Safe place to spam
|
||||
- Doesn't pollute real channels
|
||||
|
||||
|
|
@ -7,11 +7,11 @@ ops-jrz1 is a shared development server for learning agentic coding. Current sec
|
|||
## Threat Model
|
||||
|
||||
### Assumed Users
|
||||
- **Learners**: Trusted individuals learning agentic coding
|
||||
- **Devs**: Trusted individuals learning agentic coding
|
||||
- **Agentic Coders**: AI tools (Claude, opencode, etc.) running with user privileges
|
||||
|
||||
### Threat Actors
|
||||
1. **Curious learner** - Explores beyond their sandbox (low intent, low skill)
|
||||
1. **Curious dev** - Explores beyond their sandbox (low intent, low skill)
|
||||
2. **Compromised AI agent** - Prompt injection or malicious code execution
|
||||
3. **Malicious insider** - Intentional abuse (not in scope for learning environment)
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ ops-jrz1 is a shared development server for learning agentic coding. Current sec
|
|||
|---------|--------|
|
||||
| Firewall | Only 22, 80, 443 open |
|
||||
| Internal services | Bound to 127.0.0.1 only |
|
||||
| sudo access | Denied for learner users |
|
||||
| sudo access | Denied for dev users |
|
||||
| sops secrets | Root-only (/run/secrets) |
|
||||
| SSH auth | Key-only, no passwords |
|
||||
|
||||
|
|
@ -44,8 +44,8 @@ ops-jrz1 is a shared development server for learning agentic coding. Current sec
|
|||
### Secrets at Risk
|
||||
| Secret | Location | Access | Risk |
|
||||
|--------|----------|--------|------|
|
||||
| Slack bot token | /etc/slack-learner.env | learners group | Low - shared intentionally |
|
||||
| Slack app token | /etc/slack-learner.env | learners group | Low - shared intentionally |
|
||||
| Slack bot token | /etc/slack-dev.env | devs group | Low - shared intentionally |
|
||||
| Slack app token | /etc/slack-dev.env | devs group | Low - shared intentionally |
|
||||
| Matrix registration | /run/secrets | root only | Protected |
|
||||
| Maubot credentials | /run/secrets | root only | Protected |
|
||||
| User SSH keys | ~/.ssh | user only | Protected |
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#!/usr/bin/env bash
|
||||
# learner-add.sh - Add a new dev user account
|
||||
# Usage: learner-add.sh <username> <ssh-pubkey>
|
||||
# dev-add.sh - Add a new dev user account
|
||||
# Usage: dev-add.sh <username> <ssh-pubkey>
|
||||
#
|
||||
# Creates:
|
||||
# - Unix user account with SSH key
|
||||
# - Adds to learners group (Slack token access)
|
||||
# - Adds to devs group (Slack token access)
|
||||
# - Outputs onboarding instructions
|
||||
|
||||
set -euo pipefail
|
||||
|
|
@ -23,7 +23,7 @@ usage() {
|
|||
echo "Usage: $0 <username> <ssh-pubkey>"
|
||||
echo ""
|
||||
echo "Arguments:"
|
||||
echo " username - Learner's username (alphanumeric, 3-16 chars)"
|
||||
echo " username - Dev's username (alphanumeric, 3-16 chars)"
|
||||
echo " ssh-pubkey - SSH public key (starts with ssh-ed25519, ssh-rsa, etc.)"
|
||||
echo ""
|
||||
echo "Example:"
|
||||
|
|
@ -66,8 +66,8 @@ create_user() {
|
|||
# Make home directory private (not world-readable)
|
||||
chmod 700 "/home/$username"
|
||||
|
||||
# Add to learners group for Slack token access
|
||||
usermod -aG learners "$username"
|
||||
# Add to devs group for Slack token access
|
||||
usermod -aG devs "$username"
|
||||
|
||||
# Set up SSH key
|
||||
local ssh_dir="/home/$username/.ssh"
|
||||
|
|
@ -81,7 +81,7 @@ create_user() {
|
|||
{
|
||||
echo ''
|
||||
echo '# Slack bot development tokens'
|
||||
echo 'source /etc/slack-learner.env'
|
||||
echo 'source /etc/slack-dev.env'
|
||||
} >> "/home/$username/.bashrc"
|
||||
|
||||
log_info "User created with SSH access"
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env bash
|
||||
# learner-remove.sh - Remove a learner account
|
||||
# Usage: learner-remove.sh <username> [--archive]
|
||||
# dev-remove.sh - Remove a dev account
|
||||
# Usage: dev-remove.sh <username> [--archive]
|
||||
#
|
||||
# Removes:
|
||||
# - Unix user account
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
set -euo pipefail
|
||||
|
||||
MAUBOT_PLUGINS_DIR="/var/lib/maubot/plugins"
|
||||
ARCHIVE_DIR="/var/backups/learners"
|
||||
ARCHIVE_DIR="/var/backups/devs"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
|
|
@ -26,7 +26,7 @@ usage() {
|
|||
echo "Usage: $0 <username> [--archive]"
|
||||
echo ""
|
||||
echo "Arguments:"
|
||||
echo " username - Learner's username to remove"
|
||||
echo " username - Dev's username to remove"
|
||||
echo " --archive - Archive home directory instead of deleting"
|
||||
echo ""
|
||||
echo "Example:"
|
||||
|
|
@ -189,7 +189,7 @@ main() {
|
|||
|
||||
remove_user "$username"
|
||||
|
||||
log_info "Learner '$username' removed successfully"
|
||||
log_info "Dev '$username' removed successfully"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
|
@ -13,7 +13,7 @@ Provide VS Code in the browser via code-server, with:
|
|||
|---------|-------------|-------|
|
||||
| **Non-programmer** | Learning to code with AI assistance | GUI-first, minimal friction, no terminal knowledge required |
|
||||
| **Programmer (testing)** | Evaluating AI coding tools | Fast setup, full terminal access, multiple language support |
|
||||
| **Learner** | Learning AI-assisted dev or new languages | Gentle on-ramp, room to grow, pre-configured tools |
|
||||
| **Dev** | Learning AI-assisted dev or new languages | Gentle on-ramp, room to grow, pre-configured tools |
|
||||
|
||||
## Requirements
|
||||
|
||||
|
|
@ -529,4 +529,4 @@ Enterprise platform for provisioning dev environments.
|
|||
| Minimal resources | High learning curve |
|
||||
| Power user friendly | Non-programmers excluded |
|
||||
|
||||
**Why not chosen**: Must support non-programmer learners with GUI.
|
||||
**Why not chosen**: Must support non-programmer devs with GUI.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Integration tests for learner dev environment
|
||||
# Integration tests for dev dev environment
|
||||
# Run from repo root: make -C tests <target>
|
||||
|
||||
SERVER := 45.77.205.49
|
||||
|
|
@ -7,12 +7,12 @@ USER := dantest
|
|||
.PHONY: all env slack-bolt vscode help
|
||||
|
||||
help:
|
||||
@echo "Learner Environment Integration Tests"
|
||||
@echo "Dev Environment Integration Tests"
|
||||
@echo ""
|
||||
@echo "Usage: make -C tests <target> [USER=username]"
|
||||
@echo ""
|
||||
@echo "Targets:"
|
||||
@echo " env - Test learner environment (SSH, tokens, Python)"
|
||||
@echo " env - Test dev environment (SSH, tokens, Python)"
|
||||
@echo " slack-bolt - Test slack-bolt Socket Mode connection"
|
||||
@echo " vscode - Test VS Code Remote-SSH compatibility"
|
||||
@echo " all - Run all tests"
|
||||
|
|
@ -25,11 +25,11 @@ help:
|
|||
all: env slack-bolt
|
||||
|
||||
env:
|
||||
@./test-learner-env.sh $(USER)
|
||||
@./test-dev-env.sh $(USER)
|
||||
|
||||
slack-bolt:
|
||||
@echo "Testing slack-bolt on server as $(USER)..."
|
||||
@ssh $(USER)@$(SERVER) 'source /etc/slack-learner.env && \
|
||||
@ssh $(USER)@$(SERVER) 'source /etc/slack-dev.env && \
|
||||
uv pip install --quiet slack-bolt 2>/dev/null && \
|
||||
python3 -' < test-slack-bolt.py
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env bash
|
||||
# test-learner-env.sh - Integration tests for learner dev environment
|
||||
# Run from local machine: ./tests/test-learner-env.sh [username] [ssh-key]
|
||||
# test-dev-env.sh - Integration tests for dev dev environment
|
||||
# Run from local machine: ./tests/test-dev-env.sh [username] [ssh-key]
|
||||
# Default username: dantest
|
||||
|
||||
set -euo pipefail
|
||||
|
|
@ -30,7 +30,7 @@ fail() { FAIL=$((FAIL + 1)); red " FAIL: $1"; }
|
|||
skip() { yellow " SKIP: $1"; }
|
||||
|
||||
echo "=========================================="
|
||||
echo "Learner Environment Tests"
|
||||
echo "Dev Environment Tests"
|
||||
echo "Server: $SERVER"
|
||||
echo "User: $USER"
|
||||
echo "=========================================="
|
||||
|
|
@ -67,31 +67,31 @@ fi
|
|||
|
||||
# ---------------------------------------------
|
||||
echo ""
|
||||
echo "## 3. Learners group membership"
|
||||
echo "## 3. Devs group membership"
|
||||
# ---------------------------------------------
|
||||
if ssh_cmd 'groups' | grep -q learners; then
|
||||
pass "User in learners group"
|
||||
if ssh_cmd 'groups' | grep -q devs; then
|
||||
pass "User in devs group"
|
||||
else
|
||||
fail "User NOT in learners group"
|
||||
fail "User NOT in devs group"
|
||||
fi
|
||||
|
||||
# ---------------------------------------------
|
||||
echo ""
|
||||
echo "## 4. Slack tokens accessible"
|
||||
# ---------------------------------------------
|
||||
if ssh_cmd 'test -r /etc/slack-learner.env'; then
|
||||
if ssh_cmd 'test -r /etc/slack-dev.env'; then
|
||||
pass "Slack env file readable"
|
||||
else
|
||||
fail "Slack env file NOT readable (check group permissions)"
|
||||
fi
|
||||
|
||||
if ssh_cmd 'source /etc/slack-learner.env && test -n "$SLACK_BOT_TOKEN"' &>/dev/null; then
|
||||
if ssh_cmd 'source /etc/slack-dev.env && test -n "$SLACK_BOT_TOKEN"' &>/dev/null; then
|
||||
pass "SLACK_BOT_TOKEN set"
|
||||
else
|
||||
fail "SLACK_BOT_TOKEN not set"
|
||||
fi
|
||||
|
||||
if ssh_cmd 'source /etc/slack-learner.env && test -n "$SLACK_APP_TOKEN"' &>/dev/null; then
|
||||
if ssh_cmd 'source /etc/slack-dev.env && test -n "$SLACK_APP_TOKEN"' &>/dev/null; then
|
||||
pass "SLACK_APP_TOKEN set"
|
||||
else
|
||||
fail "SLACK_APP_TOKEN not set"
|
||||
|
|
@ -140,7 +140,7 @@ echo "## 7. Slack API connectivity"
|
|||
# ---------------------------------------------
|
||||
echo " Testing Slack API auth (this may take a moment)..."
|
||||
|
||||
SLACK_TEST=$(ssh_cmd 'source /etc/slack-learner.env && python3 -c "
|
||||
SLACK_TEST=$(ssh_cmd 'source /etc/slack-dev.env && python3 -c "
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
import json
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Test slack-bolt can connect via Socket Mode.
|
||||
|
||||
Run on server as learner user:
|
||||
Run on server as dev user:
|
||||
python3 tests/test-slack-bolt.py
|
||||
|
||||
Requires: pip install slack-bolt
|
||||
|
|
@ -20,12 +20,12 @@ def main():
|
|||
|
||||
if not bot_token:
|
||||
print("FAIL: SLACK_BOT_TOKEN not set")
|
||||
print(" Hint: source /etc/slack-learner.env")
|
||||
print(" Hint: source /etc/slack-dev.env")
|
||||
sys.exit(1)
|
||||
|
||||
if not app_token:
|
||||
print("FAIL: SLACK_APP_TOKEN not set")
|
||||
print(" Hint: source /etc/slack-learner.env")
|
||||
print(" Hint: source /etc/slack-dev.env")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Bot token: {bot_token[:10]}...{bot_token[-4:]}")
|
||||
|
|
|
|||
Loading…
Reference in a new issue