From 9b0e5fd8a53dd3ef0700782f07469ac3c2d530d5 Mon Sep 17 00:00:00 2001 From: Lucas Berger Date: Mon, 2 Feb 2026 21:50:39 -0500 Subject: [PATCH] chore: archive v1.0 milestone MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Archived: - milestones/v1.0-ROADMAP.md (full phase details) Updated: - MILESTONES.md (new entry for v1.0) - PROJECT.md (requirements → Validated, Current State added) - ROADMAP.md (collapsed to one-line with archive link) - STATE.md (reset for next milestone) v1.0 Docker Control via Telegram shipped: - 5 phases, 12 plans, 5 days - Telegram bot with keyword commands - Docker socket integration via n8n Co-Authored-By: Claude Opus 4.5 --- .planning/MILESTONES.md | 27 ++++++ .planning/PROJECT.md | 72 ++++++++-------- .planning/ROADMAP.md | 122 ++------------------------ .planning/STATE.md | 81 ++++------------- .planning/milestones/v1.0-ROADMAP.md | 124 +++++++++++++++++++++++++++ 5 files changed, 209 insertions(+), 217 deletions(-) create mode 100644 .planning/MILESTONES.md create mode 100644 .planning/milestones/v1.0-ROADMAP.md diff --git a/.planning/MILESTONES.md b/.planning/MILESTONES.md new file mode 100644 index 0000000..e653fe4 --- /dev/null +++ b/.planning/MILESTONES.md @@ -0,0 +1,27 @@ +# Project Milestones: Unraid Docker Manager + +## v1.0 Docker Control via Telegram (Shipped: 2026-02-02) + +**Delivered:** Telegram bot for managing Docker containers on Unraid — status, start, stop, restart, update, logs via keyword commands. + +**Phases completed:** 1-5 (12 plans total) + +**Key accomplishments:** +- Telegram bot with keyword routing (no Claude API dependency) +- Docker socket integration via n8n with curl +- Container matching with exact-match priority +- Update command with image pull, recreate, old image cleanup +- Log viewing with configurable line counts +- Single-user auth via Telegram user ID + +**Stats:** +- 2 files (n8n-workflow.json, README.md) +- ~3,400 lines of JSON workflow + markdown +- 5 phases, 12 plans +- 5 days from start to ship (2026-01-28 → 2026-02-02) + +**Git range:** Initial commit → `e5c02f9` + +**What's next:** Consider v1.1 with n8n API integration for faster development iteration, or additional features like resource monitoring. + +--- diff --git a/.planning/PROJECT.md b/.planning/PROJECT.md index f301b5a..92346da 100644 --- a/.planning/PROJECT.md +++ b/.planning/PROJECT.md @@ -6,66 +6,66 @@ A Telegram bot that lets you manage Docker containers on your Unraid server. Con ## Core Value -When you get a container update notification or notice a service is down, you can immediately investigate and act from your phone through a natural conversation. +When you get a container update notification or notice a service is down, you can immediately investigate and act from your phone. ## Requirements ### Validated -(None yet — ship to validate) +- [x] Send a message to the bot and receive a response — v1.0 +- [x] Check container status ("status") — v1.0 +- [x] Start a container by name — v1.0 +- [x] Stop a container by name — v1.0 +- [x] Restart a container by name — v1.0 +- [x] Update a container (pull new image, recreate) — v1.0 +- [x] View container logs with configurable line count — v1.0 +- [x] Bot only responds to your Telegram user ID — v1.0 ### Active -- [ ] Send a message to the bot and receive a response -- [ ] Ask about container status ("how's Plex doing?") -- [ ] Start a container by name -- [ ] Stop a container by name -- [ ] Restart a container by name -- [ ] Update a container (pull new image, recreate) -- [ ] View container logs with configurable line count (default 50) -- [ ] Bot only responds to your Telegram user ID +(None — v1.0 complete, define new requirements for v1.1) ### Out of Scope - Taking over Unraid notifications — keep existing notification system, this bot is for control - Deploying new containers — manage existing only, not create new ones -- Natural language understanding — simple keyword matching sufficient for v1, Claude API adds complexity -- Proactive monitoring/notifications — bot is reactive (you ask, it answers) for v1 +- Natural language understanding — simple keyword matching sufficient, Claude API adds complexity +- Proactive monitoring/notifications — bot is reactive (you ask, it answers) - Resource queries — "what's using the most memory?" deferred to future version +## Current State + +**Shipped:** v1.0 (2026-02-02) +**Tech stack:** n8n workflow + Telegram Bot API + Docker socket +**Files:** n8n-workflow.json (~3,200 lines), README.md + ## Context **Environment:** - Unraid server with Intel N100 CPU, 32GB RAM -- n8n already running and mostly unused — will use as orchestration layer -- Multiple Docker containers running various services (Plex, Sonarr, etc.) +- n8n container with Docker socket access +- Multiple Docker containers (Plex, Sonarr, lldap, etc.) -**Current workflow:** -- Unraid sends notifications when container updates are available -- Currently need laptop/desktop to act on updates or troubleshoot -- Want to be able to respond immediately from phone - -**User scenarios:** -1. Get update notification → open Telegram → "update plex" → done -2. Notice service not responding → "check sonarr logs" → see errors → "restart sonarr" -3. Curious about system → "what containers are running?" or "what's using the most resources?" - -## Constraints - -- **Platform**: Must run on Unraid (Docker-based deployment) -- **Orchestration**: Use n8n for workflow orchestration (already running) -- **Matching**: Keyword/substring matching for container names -- **Auth**: Single user only — verify Telegram user ID -- **Logs**: Support configurable line count, default to 50 lines +**Constraints:** +- Platform: Unraid (Docker-based) +- Orchestration: n8n (already running) +- Matching: Keyword/substring with exact-match priority +- Auth: Single user via Telegram ID +- Logs: Configurable line count, default 50, max 1000 ## Key Decisions | Decision | Rationale | Outcome | |----------|-----------|---------| -| Use keyword matching over NLU | Simple substring matching works well, Claude API adds complexity for v1 | ✓ Good | -| Use n8n for orchestration | Already running, handles Telegram webhooks, reduces new infrastructure | — Pending | -| Manage existing containers only | Keeps scope focused, deployment is complex and rarely needed from mobile | — Pending | -| Single user auth via Telegram ID | Simple security model, only one person needs access | — Pending | +| Use keyword matching over NLU | Simple substring matching works well, Claude API adds complexity | ✓ Good | +| Use n8n for orchestration | Already running, handles Telegram webhooks | ✓ Good | +| Manage existing containers only | Keeps scope focused, deployment rarely needed from mobile | ✓ Good | +| Single user auth via Telegram ID | Simple security, only one person needs access | ✓ Good | +| Static curl binary mount | Hardened n8n image lacks package manager | ✓ Good | +| Exact match priority | Prevents substring collisions (plex vs jellyplex) | ✓ Good | +| Default to :latest tag | Prevents Docker API from pulling all tags | ✓ Good | +| HTML escape logs | Log content may contain text | ✓ Good | +| Text menu over keyboard | Native Telegram node replyKeyboard had issues | ✓ Good | --- -*Last updated: 2026-01-31 after removing NLU from v1.0 scope* +*Last updated: 2026-02-02 after v1.0 milestone* diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index a749633..4903b46 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -1,122 +1,12 @@ -# Roadmap — Unraid Docker Manager v1.0 +# Roadmap — Unraid Docker Manager -## Milestone: v1.0 — Docker Control via Telegram +## Milestones -### Phase 1: Foundation -**Goal:** Basic Telegram ↔ n8n communication working +- **v1.0 Docker Control via Telegram** — Phases 1-5 (shipped 2026-02-02) → [Archive](milestones/v1.0-ROADMAP.md) -- Set up n8n workflow with Telegram trigger -- Configure Telegram bot via BotFather -- Echo messages back to verify round-trip -- Implement user ID verification (single-user auth) +## Next Milestone -**Delivers:** REQ-01 (send/receive messages), REQ-09 (user ID auth) - -**Plans:** 2 plans - -Plans: -- [x] 01-01-PLAN.md — Create Telegram bot and n8n workflow -- [x] 01-02-PLAN.md — Verify echo and authentication - -**Status:** ✅ Complete (2026-01-28) +(Not yet planned — run `/gsd:new-milestone` to define v1.1) --- - -### Phase 2: Docker Integration -**Goal:** n8n can query Docker and return container info - -- Connect n8n to Unraid Docker socket -- Implement container listing endpoint -- Parse container status (running, stopped, health) -- Format status responses for Telegram - -**Delivers:** REQ-02 (container status queries) - -**Plans:** 2 plans - -Plans: -- [x] 02-01-PLAN.md — Configure n8n container for Docker socket access -- [x] 02-02-PLAN.md — Add Docker query workflow with container matching - -**Status:** ✅ Complete (2026-01-29) - ---- - -### Phase 3: Container Actions -**Goal:** Control containers through conversation - -- Implement start container by name -- Implement stop container by name -- Implement restart container by name -- Implement update container (pull + recreate) -- Handle fuzzy name matching ("plex" → "plex-server") - -**Delivers:** REQ-03, REQ-04, REQ-05, REQ-06 - -**Plans:** 4 plans - -Plans: -- [x] 03-01-PLAN.md — Single-match container actions (start/stop/restart) -- [x] 03-02-PLAN.md — Callback infrastructure and no-match suggestions -- [x] 03-03-PLAN.md — Batch confirmation for multiple matches -- [x] 03-04-PLAN.md — Container update action (pull + recreate) - -**Status:** ✅ Complete (2026-01-30) - ---- - -### Phase 4: Logs -**Goal:** View container logs via Telegram - -- Implement log retrieval with configurable line count -- Handle long log output (truncation for Telegram limits) - -**Delivers:** REQ-07 (logs) - -**Plans:** 1 plan - -Plans: -- [x] 04-01-PLAN.md — Container log retrieval with configurable lines - -**Status:** ✅ Complete (2026-01-31) - ---- - -### Phase 5: Polish & Deploy -**Goal:** Production-ready deployment on Unraid - -- Remove NLU/Claude nodes from workflow (replace with keyword routing) -- Error handling and user-friendly error messages -- Create Docker container for any custom components -- Write deployment instructions for Unraid -- End-to-end testing of all scenarios - -**Delivers:** Production readiness - -**Plans:** 3 plans - -Plans: -- [x] 05-01-PLAN.md — Remove NLU nodes and add keyword routing with persistent menu -- [x] 05-02-PLAN.md — Standardize error messages and migrate credentials -- [x] 05-03-PLAN.md — Write deployment README and end-to-end testing - -**Status:** ✅ Complete (2026-02-02) - ---- - -## Requirements Mapping - -| REQ | Description | Phase | -|-----|-------------|-------| -| REQ-01 | Send/receive messages | 1 | -| REQ-02 | Container status queries | 2 | -| REQ-03 | Start container | 3 | -| REQ-04 | Stop container | 3 | -| REQ-05 | Restart container | 3 | -| REQ-06 | Update container | 3 | -| REQ-07 | View logs (configurable lines) | 4 | -| REQ-08 | ~~Conversational queries~~ | Out of scope | -| REQ-09 | User ID authentication | 1 | - ---- -*Created: 2026-01-28* +*Updated: 2026-02-02* diff --git a/.planning/STATE.md b/.planning/STATE.md index c472863..0cae3b1 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -2,84 +2,35 @@ ## Project Reference -**Building:** Telegram bot for Docker container management on Unraid -**Core Value:** Control containers from your phone via simple keyword commands +See: .planning/PROJECT.md (updated 2026-02-02) + +**Core value:** Immediate container control from your phone +**Current focus:** v1.0 shipped — planning next milestone ## Current Position -- **Milestone:** v1.0 — Docker Control via Telegram -- **Phase:** 5 of 5 — Polish & Deploy (COMPLETE) -- **Plan:** 3 of 3 executed -- **Status:** v1.0 COMPLETE -- **Last activity:** 2026-02-02 - Completed end-to-end testing +- **Milestone:** v1.0 — Docker Control via Telegram (SHIPPED) +- **Phase:** All complete (5/5) +- **Status:** Ready for next milestone +- **Last activity:** 2026-02-02 — v1.0 milestone archived ## Progress ``` -Phase 1: Foundation [##########] Complete (2/2 plans) -Phase 2: Docker Integration [##########] Complete (2/2 plans) -Phase 3: Container Actions [##########] Complete (4/4 plans) -Phase 4: Logs [##########] Complete (1/1 plans) -Phase 5: Polish & Deploy [##########] Complete (3/3 plans) +v1.0: [##########] 100% SHIPPED -Overall: [##########] 100% +Phase 1: Foundation [##########] Complete +Phase 2: Docker Integration [##########] Complete +Phase 3: Container Actions [##########] Complete +Phase 4: Logs [##########] Complete +Phase 5: Polish & Deploy [##########] Complete ``` -## Recent Decisions - -| Decision | Rationale | Date | -|----------|-----------|------| -| Use n8n for orchestration | Already running on Unraid, handles Telegram webhooks | 2026-01-28 | -| Claude API for NLU | N100 can't run local LLMs fast enough | 2026-01-28 | -| Single-user auth | Simple security, only owner needs access | 2026-01-28 | -| Hardcoded user ID in workflow | n8n CE blocks env var access in expressions | 2026-01-28 | -| Silent ignore unauthorized | No false branch nodes, prevents information leak | 2026-01-28 | -| HTML parse mode | Future formatting flexibility for responses | 2026-01-28 | -| Static curl binary mount | Hardened n8n image lacks package manager | 2026-01-29 | -| --group-add 281 for socket | Node user needs docker group for socket access | 2026-01-29 | -| curl -s flag for silent mode | Prevents stderr progress output causing false errors | 2026-01-29 | -| Substring matching for containers | Simple approach works well, no external library needed | 2026-01-29 | -| HTTP 304 as success | Already-in-state is success from user perspective | 2026-01-30 | -| 10-second graceful timeout | Allows containers to shutdown cleanly before SIGKILL | 2026-01-30 | -| HTTP Request for inline keyboards | Native Telegram node has expression bug with dynamic keyboards | 2026-01-30 | -| Single-char action codes in callback | s/t/r/x encoding fits in 64-byte callback_data limit | 2026-01-30 | -| Stateless 2-min timeout | Timestamp in callback_data avoids server-side state | 2026-01-30 | -| Batch limit of 4 containers | callback_data array with 4 short IDs fits in 64 bytes | 2026-01-30 | -| Sequential batch execution | Single shell command with && chain, no n8n loops needed | 2026-01-30 | -| RESULT_N:statusCode markers | Parseable output format for aggregating batch results | 2026-01-30 | -| Silent when no update | Only notify on actual image change, not when already up-to-date | 2026-01-30 | -| Single match only for update | Update requires exact container name, no batch updates | 2026-01-30 | -| Version from OCI labels | Check org.opencontainers.image.version, then version, then ID | 2026-01-30 | -| Docker logs API with tail parameter | More efficient than fetching all logs and filtering in code | 2026-01-30 | -| Binary stream header via charCodeAt | Docker multiplexed stream uses byte 0 values 1/2, strip 8 bytes | 2026-01-30 | -| Default 50 lines, cap at 1000 | Balance between useful context and Telegram limits | 2026-01-30 | -| Truncate at 3800 chars | Telegram limit is 4096, leave room for header and formatting | 2026-01-30 | -| Remove NLU from v1.0 | Simple keyword matching sufficient, Claude API adds complexity | 2026-01-31 | -| NLU cleanup in Phase 5 | Workflow has Claude nodes to remove; defer cleanup to polish phase | 2026-01-31 | -| Keyword order matters | restart before start to avoid substring match issues | 2026-02-01 | -| No emojis on buttons | Clean button text for reliable keyword matching | 2026-02-01 | -| Terse error messages | "Failed to X Y" without HTTP codes or technical details | 2026-02-01 | -| User ID in n8n credentials | Allows workflow sharing without exposing sensitive data | 2026-02-01 | -| Text menu over keyboard | Native Telegram node replyKeyboard had issues | 2026-02-02 | -| Exact match priority | Prevents substring collisions (plex vs jellyplex) | 2026-02-02 | -| Default to :latest tag | Prevents Docker API from pulling all tags | 2026-02-02 | -| Tail pull output | Pipe through tail -c 10000 to prevent memory exhaustion | 2026-02-02 | -| HTML escape logs | Log content may contain text that breaks Telegram | 2026-02-02 | -| Notify when up-to-date | User feedback when update check finds no changes | 2026-02-02 | - -## Pending Todos - -(None) - -## Blockers & Concerns - -(None) - ## Session Continuity - **Last session:** 2026-02-02 -- **Stopped at:** v1.0 milestone complete -- **Next step:** Consider v1.1 features or n8n API integration for faster iteration +- **Stopped at:** v1.0 milestone archived +- **Next step:** `/gsd:new-milestone` to plan v1.1 --- *Auto-maintained by GSD workflow* diff --git a/.planning/milestones/v1.0-ROADMAP.md b/.planning/milestones/v1.0-ROADMAP.md new file mode 100644 index 0000000..c9600b8 --- /dev/null +++ b/.planning/milestones/v1.0-ROADMAP.md @@ -0,0 +1,124 @@ +# Milestone v1.0: Docker Control via Telegram + +**Status:** SHIPPED 2026-02-02 +**Phases:** 1-5 +**Total Plans:** 12 + +## Overview + +Telegram bot for managing Docker containers on Unraid. Control containers from your phone via simple keyword commands — status, start, stop, restart, update, logs. + +## Phases + +### Phase 1: Foundation + +**Goal:** Basic Telegram ↔ n8n communication working +**Plans:** 2 plans + +Plans: +- [x] 01-01-PLAN.md — Create Telegram bot and n8n workflow +- [x] 01-02-PLAN.md — Verify echo and authentication + +**Delivers:** REQ-01 (send/receive messages), REQ-09 (user ID auth) +**Status:** Complete (2026-01-28) + +--- + +### Phase 2: Docker Integration + +**Goal:** n8n can query Docker and return container info +**Plans:** 2 plans + +Plans: +- [x] 02-01-PLAN.md — Configure n8n container for Docker socket access +- [x] 02-02-PLAN.md — Add Docker query workflow with container matching + +**Delivers:** REQ-02 (container status queries) +**Status:** Complete (2026-01-29) + +--- + +### Phase 3: Container Actions + +**Goal:** Control containers through conversation +**Plans:** 4 plans + +Plans: +- [x] 03-01-PLAN.md — Single-match container actions (start/stop/restart) +- [x] 03-02-PLAN.md — Callback infrastructure and no-match suggestions +- [x] 03-03-PLAN.md — Batch confirmation for multiple matches +- [x] 03-04-PLAN.md — Container update action (pull + recreate) + +**Delivers:** REQ-03, REQ-04, REQ-05, REQ-06 +**Status:** Complete (2026-01-30) + +--- + +### Phase 4: Logs + +**Goal:** View container logs via Telegram +**Plans:** 1 plan + +Plans: +- [x] 04-01-PLAN.md — Container log retrieval with configurable lines + +**Delivers:** REQ-07 (logs) +**Status:** Complete (2026-01-31) + +--- + +### Phase 5: Polish & Deploy + +**Goal:** Production-ready deployment on Unraid +**Plans:** 3 plans + +Plans: +- [x] 05-01-PLAN.md — Remove NLU nodes and add keyword routing with persistent menu +- [x] 05-02-PLAN.md — Standardize error messages and migrate credentials +- [x] 05-03-PLAN.md — Write deployment README and end-to-end testing + +**Delivers:** Production readiness +**Status:** Complete (2026-02-02) + +--- + +## Requirements Mapping + +| REQ | Description | Phase | Status | +|-----|-------------|-------|--------| +| REQ-01 | Send/receive messages | 1 | Complete | +| REQ-02 | Container status queries | 2 | Complete | +| REQ-03 | Start container | 3 | Complete | +| REQ-04 | Stop container | 3 | Complete | +| REQ-05 | Restart container | 3 | Complete | +| REQ-06 | Update container | 3 | Complete | +| REQ-07 | View logs (configurable lines) | 4 | Complete | +| REQ-08 | ~~Conversational queries~~ | - | Out of scope | +| REQ-09 | User ID authentication | 1 | Complete | + +--- + +## Milestone Summary + +**Key Decisions:** +- Use n8n for orchestration (already running on Unraid) +- Simple keyword matching over Claude NLU (reduces complexity) +- Single-user auth via Telegram user ID +- Hardcoded user ID in workflow (n8n CE limitation) +- Static curl binary mount (hardened n8n image) +- Exact match priority for container names +- Default to :latest tag when pulling images +- HTML escape log output for Telegram + +**Issues Resolved:** +- Docker socket access (--group-add 281) +- Memory exhaustion on large pulls (tail -c 10000) +- All tags pulled without explicit tag (append :latest) +- HTML parse errors in logs ( text) +- Container name collisions (exact match priority) + +**Technical Debt:** +- None significant for v1.0 + +--- +*Archived: 2026-02-02*