## Corrected Implementation Plan Based on the new findings, the DevTunnel feature is **already largely implemented** (18+ files for SSH server, nginx integration, session management, subdomain registry, auth, metrics, CLI, Docker Compose). What remains is completing the missing pieces and hardening the implementation. Do **not** create files that already exist. Instead: ### Changes to Make #### 1. Enforce Rate Limiting in `devplacepy/services/tunnel/server.py` - The config constant `TUNNEL_RATE_LIMIT_PER_USER=5` is imported but never checked. - In the SSH server session handler, before accepting a new reverse tunnel connection, count active sessions for the same username (using `TunnelManager`). If `>= TUNNEL_RATE_LIMIT_PER_USER`, reject the connection with a clear message (e.g., "Rate limit exceeded: maximum 5 concurrent tunnels per user"). #### 2. Add DevII Action Tools for Tunnel Management - Create a new file `devplacepy/services/devii/actions/catalog/tunnel.py` (or modify existing catalog if appropriate) that registers three tools: - `tunnel_list` – calls `TunnelManager.list_by_user()` or `list_all()` for admin. - `tunnel_kill` – calls `TunnelManager.kill_session()`. - `tunnel_metrics` – returns metrics from `get_metrics()`. - Register these tools in the DevII action catalog (likely via a `CATALOG` dict or similar pattern used by other actions). Check existing actions for the registration convention (e.g., `devplacepy/services/devii/actions/catalog/deepsearch.py`). #### 3. Write Unit Tests for Tunnel Components - Create a test file `tests/unit/services/tunnel/test_server.py` covering: - Password auth mock (valid/invalid/3-second delay). - Interactive session prompts (local port, subdomain choice). - Subdomain uniqueness enforcement. - Session creation, listing, killing. - Rate limit check. - Create `tests/unit/services/tunnel/test_subdomain_registry.py` covering claim/release/idempotency. - Create `tests/unit/services/tunnel/test_ssh_auth.py` covering auth caching, TTL, invalidation. - Use `unittest.mock` or `pytest-asyncio` with async mocks. #### 4. Update Documentation - Add a section to `CLAUDE.md` (root) under "Services" describing the tunnel service, its config keys, and usage. - Add a section to `devplacepy/services/CLAUDE.md` under "Tunnel" describing the architecture and module layout. - Update `README.md` with a DevTunnel badge/description referencing the ssh command. - Ensure `CHANGELOG.md` (or a note in the release) mentions the tunnel feature. #### 5. Verify All Configuration Keys Are Used - Check `devplacepy/config.py` ensures every `TUNNEL_*` constant is actually referenced in the service code (e.g., `TUNNEL_MAX_BANDWIDTH_PER_CLIENT` is defined but may not be enforced in `server.py` – add bandwidth throttling if missing). - Ensure `.env.example` has all tunnel defaults. ### Files to Create / Modify | File | Action | Reason | |------|--------|--------| | `devplacepy/services/tunnel/server.py` | **Modify** | Add rate limit enforcement before accepting reverse tunnel. Optionally add bandwidth throttle. | | `devplacepy/services/devii/actions/catalog/tunnel.py` | **Create** | Register DevII action tools. | | `tests/unit/services/tunnel/test_server.py` | **Create** | Unit tests for SSH server. | | `tests/unit/services/tunnel/test_ssh_auth.py` | **Create** | Unit tests for auth cache. | | `tests/unit/services/tunnel/test_subdomain_registry.py` | **Create** | Unit tests for subdomain registry. | | `CLAUDE.md` | **Modify** | Add tunnel section. | | `devplacepy/services/CLAUDE.md` | **Modify** | Add tunnel architecture details. | | `README.md` | **Modify** | Add tunnel badge/summary. | | `.env.example` | **Verify** | Ensure tunnel defaults present (if not, add). | | `devplacepy/config.py` | **Verify** | Ensure all config keys are consumed somewhere (e.g., bandwidth limit). | ### No Changes To - `nginx/nginx.conf.template` – already has wildcard server block. - `docker-compose.yml` – already has `ssh-server` service. - `devplacepy/routers/tunnel.py` – already implements API endpoints. - `devplacepy/cli/tunnel.py` – already exists. - `devplacepy/services/tunnel/session_manager.py`, `subdomain_registry.py`, `ssh_auth.py`, `nginx_updater.py`, `metrics.py` – all exist and are correct. ### Verification Steps 1. **Run tests**: `pip install -e '.[dev]' -q && make test-unit` – all existing tests plus new tunnel tests must pass. 2. **Lint**: `pip install -q ruff && ruff check .` – zero errors. 3. **Check rate limit enforcement**: Manually attempt 6 concurrent SSH connections from the same user – the 6th should be rejected with a clear message. 4. **Check DevII tools**: Run a DevII command that invokes `tunnel_list` – it should return active tunnels. 5. **Documentation grep**: `grep -ri 'tunnel' CLAUDE.md devplacepy/services/CLAUDE.md README.md` – must show relevant content. 6. **No em-dashes** in any changed file (use `grep — '—'` – should be zero). 7. **AST parse check**: All Python files parse cleanly (can be verified with `python -c "compile(open(f).read(), f, 'exec')"` for each new/modified file). ### Definition of Done - [ ] Rate limit enforcement added in `server.py` – 6th concurrent session from same user rejected. - [ ] DevII action tools `tunnel_list`, `tunnel_kill`, `tunnel_metrics` registered and functional. - [ ] Unit tests for tunnel auth, session management, subdomain registry, and rate limiting exist and pass. - [ ] `CLAUDE.md`, `devplacepy/services/CLAUDE.md`, `README.md` updated with tunnel documentation. - [ ] `.env.example` contains all tunnel config keys. - [ ] All `TUNNEL_*` config keys are consumed in runtime code (bandwidth limit enforced if defined). - [ ] `pip install -e '.[dev]' -q && make test-unit` passes. - [ ] `pip install -q ruff && ruff check .` passes. - [ ] No em-dashes in any changed file. - [ ] All new/modified Python files parse correctly.