docs: complete v1.3 project research (STACK, FEATURES, ARCHITECTURE, PITFALLS, SUMMARY)

This commit is contained in:
Lucas Berger
2026-02-08 19:52:57 -05:00
parent c071b890ef
commit 07cde0490a
5 changed files with 1554 additions and 1288 deletions
+178 -196
View File
@@ -1,268 +1,250 @@
# Research Summary: v1.1 n8n Integration & Polish
# Project Research Summary
**Project:** Unraid Docker Manager
**Domain:** Telegram Bot Enhancement / Security Hardening
**Researched:** 2026-02-02
**Confidence:** MEDIUM-HIGH
**Project:** Unraid Docker Manager v1.3 — Update Status Sync
**Domain:** Docker container management integration with Unraid server
**Researched:** 2026-02-08
**Confidence:** HIGH
## Executive Summary
The v1.1 milestone focuses on four areas: Docker socket security (critical), Telegram UX improvements (inline keyboards), n8n API access (development workflow), and Unraid update sync (nice-to-have). Research confirms all features are achievable with existing n8n capabilities and no new application dependencies beyond a Docker socket proxy container.
Unraid tracks container update status through an internal state file (`/var/lib/docker/unraid-update-status.json`) that is only updated when updates are initiated through Unraid's WebGUI or GraphQL API. When containers are updated externally via Docker API (as the bot currently does), Unraid's state becomes stale, showing false "update available" badges and sending duplicate notifications. This is the core pain point for v1.3.
The recommended approach is security-first: deploy the Docker socket proxy before any workflow changes, then migrate existing curl commands to use TCP instead of Unix socket. This order minimizes risk and provides a clean foundation. Telegram inline keyboards require HTTP Request nodes due to n8n native node limitations with dynamic keyboards. The n8n API is enabled by default on self-hosted instances and requires only an API key for Claude Code access.
The recommended approach is to use Unraid's official GraphQL API with the `updateContainer` mutation. This leverages the same mechanism Unraid's WebGUI uses and automatically handles status file synchronization, image digest comparison, and UI refresh. The GraphQL API is available natively in Unraid 7.2+ or via the Connect plugin for earlier versions. This approach is significantly more robust than direct file manipulation, is version-safe, and has proper error handling.
Key risk is breaking existing functionality during socket proxy migration. All 15+ Execute Command nodes using `--unix-socket` must be updated simultaneously. The mitigation is incremental migration with comprehensive testing before removing direct socket access. Unraid update sync has the lowest confidence - it works via file deletion but requires additional volume mounts.
Key risks include race conditions between bot updates and Unraid's periodic update checker, version compatibility across Unraid 6.x-7.x, and ensuring n8n container has proper network access to the Unraid host's GraphQL endpoint. These are mitigated through atomic operations via the GraphQL API, version detection, and using `host.docker.internal` networking with proper container configuration.
---
## Key Findings
## Stack Additions
### Recommended Stack
| Component | Purpose | Why This Choice |
|-----------|---------|-----------------|
| **LinuxServer socket-proxy** | Docker socket security | HAProxy-based filtering, active maintenance, Unraid community familiarity |
| **n8n REST API** | Programmatic workflow management | Already enabled by default, no new dependencies |
| **HTTP Request nodes** | Dynamic Telegram keyboards | Workaround for n8n native node limitations with inline keyboards |
**Use Unraid's GraphQL API via n8n's built-in HTTP Request node** — no new dependencies required. The GraphQL API is the official Unraid interface and handles all status synchronization internally through the DockerService and Dynamix Docker Manager integration.
**No new application dependencies** - all solutions use existing n8n capabilities:
- HTTP Request node for Telegram API and Docker via proxy
- Execute Command node for Unraid file operations
- n8n public API for Claude Code workflow management
**Core technologies:**
- **Unraid GraphQL API (7.2+ or Connect plugin)**: Container update status sync — Official API, same mechanism as WebGUI, handles all internal state updates automatically
- **HTTP Request (n8n built-in)**: GraphQL client — Already available, no new dependencies, simple POST request pattern
- **Unraid API Key**: Authentication — Same credential pattern as existing n8n API keys, stored in `.env.unraid-api`
**Socket proxy environment variables (minimum required):**
```bash
CONTAINERS=1 # List/inspect containers
IMAGES=1 # Pull images for updates
POST=1 # Enable write operations
ALLOW_START=1 # Container start
ALLOW_STOP=1 # Container stop
ALLOW_RESTARTS=1 # Container restart/kill
**Network requirements:**
- n8n container → Unraid host via `http://host.docker.internal/graphql`
- Requires `--add-host=host.docker.internal:host-gateway` in n8n container config
- Alternative: Use Unraid IP directly (`http://tower.local/graphql` or `http://192.168.x.x/graphql`)
**Critical finding from stack research:** Direct file manipulation of `/var/lib/docker/unraid-update-status.json` was investigated but rejected. The file format is undocumented, doesn't trigger UI refresh, and is prone to race conditions. The GraphQL API is the proper abstraction layer.
### Expected Features
Based on feature research, the v1.3 scope is tightly focused on solving the core pain point.
**Must have (table stakes):**
- Clear "update available" badge after bot updates container — Users expect Unraid UI to reflect reality after external updates
- Prevent duplicate update notifications — After bot updates, Unraid shouldn't send false-positive Telegram notifications
- Automatic sync after every update — Zero user intervention, bot handles sync transparently
**Should have (v1.4+):**
- Manual sync command (`/sync`) — Trigger when user updates via other tools (Portainer, CLI, Watchtower)
- Read Unraid update status for better detection — Parse Unraid's view to enhance bot's container selection UI
- Batch status sync — Optimize multi-container update operations
**Defer (v2+):**
- Bidirectional status awareness — Use Unraid's update detection as source of truth instead of Docker digest comparison
- Persistent monitoring daemon — Real-time sync via Docker events (conflicts with n8n's workflow execution model)
- Full Unraid API integration — Authentication, template parsing, web session management (overly complex for cosmetic badge)
**Anti-features identified:**
- Automatic template XML regeneration (breaks container configuration)
- Sync status for ALL containers on every operation (performance impact, unnecessary)
- Full Unraid API integration via authentication/sessions (complexity overkill for status sync)
### Architecture Approach
**Extend n8n-update.json sub-workflow with a single HTTP Request node** that calls Unraid's GraphQL `updateContainer` mutation after successful Docker API update. This keeps sync tightly coupled to update operations, requires minimal architectural changes, and maintains single responsibility (update sub-workflow owns all update-related actions).
**Major components:**
1. **Clear Unraid Status (NEW node)** — HTTP Request to GraphQL API after "Remove Old Image (Success)", calls `mutation { docker { updateContainer(id: "docker:containerName") } }`
2. **n8n container configuration (modified)** — Add `--add-host=host.docker.internal:host-gateway` for network access to Unraid host
3. **Unraid API credential (NEW)** — API key stored in `.env.unraid-api`, loaded via n8n credential system, requires `DOCKER:UPDATE_ANY` permission
**Data flow:**
```
Update sub-workflow success → Extract container name → HTTP Request to GraphQL
→ Unraid's DockerService executes syncVersions() → Update status file written
→ Return to sub-workflow → Success response to user
```
---
**Rejected alternatives:**
- **Direct file write** — Brittle, undocumented format, no UI refresh, race conditions
- **New sub-workflow (n8n-unraid-sync.json)** — Overkill for single operation
- **Main workflow integration** — Adds latency, harder to test
- **Helper script on host** — Unnecessary complexity when GraphQL API exists
## Feature Table Stakes
### Critical Pitfalls
### Must Have
Research identified 7 critical pitfalls with phase-specific prevention strategies:
| Feature | Rationale |
|---------|-----------|
| **Docker socket proxy** | Security requirement - remove root-equivalent access from internet-exposed n8n |
| **Inline keyboard callback handling** | Already partially implemented; must complete for button responses |
| **answerCallbackQuery responses** | Telegram requirement - loading spinner persists up to 1 minute without it |
| **n8n API key setup** | Enables programmatic workflow management for Claude Code |
| **Batch update with progress** | Core batch use case - `update plex sonarr radarr` with per-container feedback |
1. **State Desync Between Docker API and Unraid's Internal Tracking** — GraphQL API solves this by using Unraid's official update mechanism instead of direct file manipulation. Validation: Update via bot, verify Unraid shows "up-to-date" after manual "Check for Updates"
### Should Have
2. **Race Condition Between Unraid's Periodic Update Check and Bot Sync** — GraphQL `updateContainer` mutation is idempotent and atomic. Even if Unraid's update checker runs concurrently, no file corruption or lost updates occur. The API handles synchronization internally.
| Feature | Rationale |
|---------|-----------|
| **Container action buttons** | Tap-to-action UX improvement over typing commands |
| **Confirmation dialogs** | "Are you sure?" before stop/restart/update prevents accidents |
| **"Update all" command** | Convenience feature with mandatory confirmation |
| **Unraid status file sync** | Clear "update available" badge after bot updates (file deletion method) |
3. **Unraid Version Compatibility** — GraphQL API is stable across Unraid 6.9+ (via Connect plugin) and 7.2+ (native). Version detection should check `/etc/unraid-version` and verify API availability before sync. If GraphQL unavailable, log error and skip sync (preserve bot functionality).
### Defer to v2+
4. **Docker Socket Proxy Blocks Filesystem Access** — Resolved by using GraphQL API instead of direct file access. n8n only needs HTTP access to Unraid host, not filesystem mounts. This preserves security boundaries.
| Feature | Rationale |
|---------|-----------|
| **Unraid GraphQL API integration** | Requires Unraid 7.2+, adds complexity |
| **MCP integration for n8n** | Unofficial server exists but adds significant complexity |
| **Cancel mid-batch** | Requires state management complexity |
| **Pagination for containers** | Only needed if >10 containers common |
5. **Notification Spam During Batch Updates** — Batch updates should collect all container names and call `updateContainers` (plural) mutation once after batch completes, not per-container. This triggers single status recalculation instead of N notifications.
---
6. **n8n Workflow State Doesn't Persist** — Sync happens within same execution (no cross-execution state needed). Batch updates already collect results in single execution, sync after loop completes. No reliance on static data.
## Architecture Changes
7. **Unraid's br0 Network Recreate** — Not directly related to status sync, but update flow must preserve network config. Current n8n-update.json uses Docker API recreate — verify network settings are copied from old container inspect to new create body.
### Target Architecture
## Implications for Roadmap
```
User -> Telegram -> n8n webhook -> curl -> socket-proxy:2375 -> docker.sock -> Docker Engine
^
|
Claude Code -> n8n API --+
```
Based on combined research, v1.3 should be structured as 3 focused phases:
### Key Integration Points
### Phase 1: API Setup & Network Access
**Rationale:** Validate the GraphQL approach before n8n integration. Infrastructure changes first, workflow changes second.
| Component | Change | Impact |
|-----------|--------|--------|
| **socket-proxy container** | NEW - sidecar on internal network | Infrastructure |
| **n8n container** | MODIFY - `DOCKER_HOST=tcp://socket-proxy:2375`, remove socket mount | Medium |
| **Execute Command nodes** | MODIFY - change curl from `--unix-socket` to TCP | ~15 nodes |
| **Route Callback switch** | MODIFY - add new callback types for keyboards | Low |
| **HTTP Request nodes** | NEW - for dynamic inline keyboard generation | Medium |
**Delivers:**
- Unraid API key created with `DOCKER:UPDATE_ANY` permission
- Network access verified from n8n container to Unraid host
- Container ID format documented (via GraphQL query test)
### Curl Migration Pattern
**Tasks:**
- Create API key via `unraid-api apikey --create` CLI command
- Store in `.env.unraid-api` (gitignored)
- Add `--add-host=host.docker.internal:host-gateway` to n8n container config
- Test GraphQL query from command line: `curl -X POST http://host.docker.internal/graphql -H "x-api-key: ..." -d '{"query": "{ docker { containers { id name } } }"}'`
- Verify container ID format returned (likely `docker:<name>`)
```
FROM: curl -s --unix-socket /var/run/docker.sock 'http://localhost/v1.47/...'
TO: curl -s 'http://socket-proxy:2375/v1.47/...'
```
**Avoids:**
- Pitfall 4 (filesystem access issues) — uses API not file mounts
- Pitfall 3 (version compatibility) — validates API availability before implementation
---
**Research flag:** NEEDS DEEPER RESEARCH — Network access testing, container ID format verification, API permission validation
## Top Risks
### Phase 2: n8n Workflow Integration
**Rationale:** Once API access is proven, integrate into update sub-workflow. Single node addition is minimal risk.
### 1. Socket Proxy Breaks Existing Commands (CRITICAL)
**Delivers:**
- n8n-update.json calls GraphQL `updateContainer` after successful Docker API update
- Error handling for API failures (continue on error, log for debugging)
- Single-container updates sync automatically
**Risk:** All Docker commands fail after migration
**Prevention:**
1. Deploy socket-proxy first without removing direct socket
2. Update curl commands one-by-one to use proxy
3. Test each command via proxy before removing direct socket
4. Maintain rollback capability throughout
**Tasks:**
- Add HTTP Request node to n8n-update.json after "Remove Old Image (Success)"
- Configure GraphQL mutation: `mutation { docker { updateContainer(id: "docker:{{$json.containerName}}") { id name state } } }`
- Set authentication: Header Auth with `x-api-key: {{$env.UNRAID_API_KEY}}`
- Error handling: `continueRegularOutput` (don't fail update if sync fails)
- Connect to "Return Success" node
- Test with single container update
### 2. n8n Native Telegram Node Rejects Dynamic Keyboards (HIGH)
**Uses:**
- Unraid GraphQL API from Phase 1
- n8n HTTP Request node (built-in)
**Risk:** Error "The value is not supported!" when using expressions in keyboard fields
**Prevention:** Use HTTP Request node to call Telegram Bot API directly for any dynamic keyboard. Keep native node for simple text responses only.
**Implements:**
- Clear Unraid Status component from architecture research
- Post-Action Sync pattern (sync after primary operation completes)
### 3. callback_data Exceeds 64 Bytes (MEDIUM)
**Avoids:**
- Pitfall 1 (state desync) — uses official sync mechanism
- Pitfall 2 (race conditions) — GraphQL API handles atomicity
**Risk:** Buttons silently fail when callback_data is too long
**Prevention:** Use short codes: `s:abc12345` (action:container_id_prefix) instead of full names. Map back via container ID lookup.
**Research flag:** STANDARD PATTERNS — HTTP Request node usage well-documented, unlikely to need additional research
### 4. n8n 2.0 Breaking Changes (MEDIUM)
### Phase 3: Batch Optimization & UAT
**Rationale:** After core functionality works, optimize for batch operations and validate across scenarios.
**Risk:** Execute Command disabled by default, env vars blocked, Save/Publish separation
**Prevention:** Check n8n version before starting. If 2.0+, verify Execute Command is enabled in settings. Don't upgrade n8n during this milestone.
**Delivers:**
- Batch updates use `updateContainers` (plural) mutation for efficiency
- Validation across Unraid versions (6.12, 7.0, 7.2)
- Confirmation that network config preservation works
### 5. Unraid Update Badge Never Clears (LOW impact but HIGH likelihood)
**Tasks:**
- Modify batch update flow to collect all updated container IDs
- Call `updateContainers(ids: ["docker:container1", "docker:container2"])` once after batch loop completes
- Test on Unraid 6.12 (with Connect plugin) and 7.2 (native API)
- Verify no notification spam during batch updates (5+ containers)
- Test container on custom network (`br0`) — verify DNS resolution after update
- Document manual sync option in README (if GraphQL sync fails, user clicks "Check for Updates")
**Risk:** Unraid UI shows "update available" even after bot updates container
**Prevention:** Delete `/var/lib/docker/unraid-update-status.json` after successful bot update. Document that user may need to click "Check for Updates" in Unraid UI.
**Avoids:**
- Pitfall 5 (notification spam) — batch mutation prevents per-container notifications
- Pitfall 3 (version compatibility) — multi-version UAT catches breaking changes
- Pitfall 7 (network issues) — UAT includes network-dependent scenarios
---
**Research flag:** STANDARD PATTERNS — Batch optimization is iteration of Phase 2 pattern
## Recommended Build Order
### Phase Ordering Rationale
Based on dependencies and risk mitigation:
- **Infrastructure before integration** — Phase 1 validates GraphQL API access before modifying workflows. If network access fails, can pivot to alternative (e.g., helper script) without workflow rework.
### Phase 1: Socket Security Foundation
**Delivers:** Secure Docker socket access via proxy
**What:**
1. Deploy socket-proxy container on internal network
2. Configure minimum required permissions
3. Migrate all curl commands to use TCP endpoint
4. Test all existing functionality
5. Remove direct socket mount from n8n
- **Single-container before batch** — Phase 2 proves core sync mechanism with simplest case. Batch optimization (Phase 3) is safe iteration once foundation works.
**Rationale:** Security is the primary v1.1 goal. Must complete before adding any new features to avoid compounding risk.
- **Validation last** — Phase 3 UAT happens after implementation complete. Testing earlier wastes time if implementation changes.
**Pitfalls to avoid:**
- Proxy port exposed publicly (keep internal only)
- Insufficient permissions (test each operation)
- Breaking existing curl commands (migrate incrementally)
**Dependencies discovered:**
- Phase 2 depends on Phase 1 (API access must work)
- Phase 3 depends on Phase 2 (batch builds on single-container pattern)
- No parallelization opportunities (sequential phases)
### Phase 2: n8n API Access
**Delivers:** Claude Code can read/update/test workflows programmatically
**What:**
1. Create API key in n8n Settings
2. Document API endpoints for workflow management
3. Test basic operations (list, get, update workflow)
### Research Flags
**Rationale:** Low risk, high value. Enables faster iteration for subsequent phases.
Phases likely needing deeper research during planning:
**Pitfalls to avoid:**
- API key committed to repository (use environment/secrets)
- Workflow ID hardcoded (query API to discover)
- **Phase 1:** Network access testing, API permission verification — Some unknowns around container ID format and `host.docker.internal` behavior in Unraid's Docker implementation. Low risk (fallback to IP-based access), but needs validation.
### Phase 3: Inline Keyboard Infrastructure
**Delivers:** Foundation for button-based UX
**What:**
1. HTTP Request node pattern for dynamic keyboards
2. Callback routing for new action types
3. answerCallbackQuery integration
4. Short callback_data encoding scheme
Phases with standard patterns (skip research-phase):
**Rationale:** Foundation needed before adding specific button features.
**Pitfalls to avoid:**
- Using native Telegram node for keyboards (use HTTP Request)
- callback_data exceeding 64 bytes (use short codes)
### Phase 4: UX Improvements
**Delivers:** Button-based container management
**What:**
1. Container selection keyboards from commands
2. Confirmation dialogs for dangerous actions
3. Message editing for progress/results
4. Batch update with progress feedback
**Rationale:** User-facing improvements built on Phase 3 foundation.
### Phase 5: Unraid Sync (Optional)
**Delivers:** Clear update badges after bot updates
**What:**
1. Add volume mount for status file access
2. Delete status file after successful updates
3. Document user step to refresh Unraid UI
**Rationale:** Lowest confidence, most uncertain. May require additional host access. Defer if other phases take longer than expected.
---
## Open Questions
1. **Socket proxy network:** Should socket-proxy be on a dedicated internal network or share n8n's network? (Recommendation: dedicated internal network)
2. **n8n API exposure:** Should n8n API be accessible only via Tailscale/VPN or also on LAN? (Recommendation: Tailscale only for security)
3. **Unraid status file access:** Does n8n already have `/var/lib/docker` mounted, or is a new volume mount needed? (Needs verification)
4. **Batch size limits:** Should "update all" have a maximum container limit or always require confirmation? (Recommendation: always confirm, no limit)
---
## Ready for Requirements
Research is complete. All four research files provide sufficient detail for roadmap creation:
- **STACK.md:** Socket proxy configuration, n8n API setup, Telegram keyboard patterns
- **FEATURES.md:** Table stakes vs differentiators, complexity estimates, MVP recommendations
- **ARCHITECTURE.md:** Integration points, data flow changes, component modifications
- **PITFALLS.md:** Top 5 risks ranked, prevention strategies, phase-specific warnings
**Recommended phase count:** 4-5 phases
**Estimated complexity:** Medium (infrastructure change + UX improvements)
**Confidence for planning:** HIGH for Phases 1-4, MEDIUM for Phase 5 (Unraid sync)
---
- **Phase 2:** HTTP Request node integration — Well-documented n8n pattern, GraphQL mutation structure is simple
- **Phase 3:** Batch optimization and UAT — Iteration of Phase 2, no new concepts
## Confidence Assessment
| Area | Confidence | Notes |
|------|------------|-------|
| Stack | HIGH | Official docs for socket-proxy and n8n API verified |
| Features | MEDIUM-HIGH | Telegram API well-documented; n8n limitations confirmed via GitHub issues |
| Architecture | HIGH | Clear integration points, existing workflow well understood |
| Pitfalls | MEDIUM-HIGH | Based on official docs + community experience; Unraid behavior forum-confirmed |
| Stack | HIGH | GraphQL API is official Unraid interface, documented in schema and DeepWiki. HTTP Request node is n8n built-in. |
| Features | MEDIUM | Core pain point well-understood from community forums. Feature prioritization based on user impact analysis, but batch optimization impact is estimated. |
| Architecture | HIGH | Extension of existing sub-workflow pattern. GraphQL integration is standard HTTP Request usage. Rejected alternatives are well-reasoned. |
| Pitfalls | MEDIUM | Critical pitfalls identified from community reports and source code analysis. Race condition and version compatibility need UAT validation. |
**Overall confidence:** MEDIUM-HIGH
**Overall confidence:** HIGH
The GraphQL API approach is well-documented and official. Core functionality (sync after single-container update) is low-risk. Batch optimization and multi-version support add complexity but are defer-able if needed.
### Gaps to Address
1. **n8n version check** - Verify current n8n version before starting (2.0 has breaking changes)
2. **Unraid volume mounts** - Verify existing mounts or plan for new ones
3. **Telegram keyboard testing** - HTTP Request pattern needs validation with actual workflow
Areas where research was inconclusive or needs validation during implementation:
---
- **Container ID format** — GraphQL schema shows `id: ID!` but exact format (`docker:<name>` vs just `<name>`) needs testing. Resolution: Phase 1 queries containers to get actual ID format.
- **API rate limiting** — Not documented. Impact: LOW (bot updates are infrequent, <10/min even in batch). Resolution: Monitor during UAT, no preemptive handling.
- **GraphQL subscription for real-time status** — Schema includes subscriptions but unclear if Docker status changes are subscribable. Impact: None for v1.3 (defer to future enhancement). Resolution: Document as v2+ exploration.
- **Unraid 6.9-7.1 Connect plugin availability** — Research confirms Connect plugin exists but installation process not validated. Impact: MEDIUM (users on pre-7.2 need this). Resolution: Phase 1 should document plugin installation steps and test.
- **Exact permission name for API key** — Research shows `DOCKER:UPDATE_ANY` but this wasn't explicitly stated in official docs (inferred from schema). Impact: LOW (easily testable). Resolution: Phase 1 tests API key creation and documents exact permission syntax.
## Sources
### Primary (HIGH confidence)
- [n8n API Documentation](https://docs.n8n.io/api/) - Authentication, endpoints
- [LinuxServer socket-proxy](https://docs.linuxserver.io/images/docker-socket-proxy/) - Configuration options
- [Telegram Bot API](https://core.telegram.org/bots/api) - Inline keyboards, callback queries
- [Unraid API Schema](https://raw.githubusercontent.com/unraid/api/main/api/generated-schema.graphql) — GraphQL mutations, container ID types, query structure
- [DeepWiki — Docker Integration](https://deepwiki.com/unraid/api/2.4-docker-integration) — DockerService architecture, updateContainer mutation behavior
- [limetech/dynamix source](https://github.com/limetech/dynamix/blob/master/plugins/dynamix.docker.manager/include/DockerClient.php) — syncVersions() function, update status file handling
- [Unraid API Documentation](https://docs.unraid.net/API/) — API key management, version availability
- [Unraid API Key Management](https://docs.unraid.net/API/programmatic-api-key-management/) — API key creation, permission scopes
### Secondary (MEDIUM confidence)
- [n8n GitHub Issue #19955](https://github.com/n8n-io/n8n/issues/19955) - Native node keyboard limitations
- [Tecnativa docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy) - Alternative proxy option
- [Unraid Forum: Incorrect Update Notification](https://forums.unraid.net/bug-reports/stable-releases/regression-incorrect-docker-update-notification-r2807/) — Community-identified pain point, file deletion workaround
- [Watchtower + Unraid Discussion](https://github.com/containrrr/watchtower/discussions/1389) — External update detection issues, Unraid doesn't auto-sync
- [Unraid Forum: Watchtower Status Not Reflected](https://forums.unraid.net/topic/149953-docker-update-via-watchtower-status-not-reflected-in-unraid/) — Confirmation of stale status after external updates
- [Unraid MCP Server](https://github.com/jmagar/unraid-mcp) — Reference GraphQL client implementation
- [Home Assistant Unraid Integration](https://github.com/domalab/unraid-api-client) — Additional GraphQL usage examples
- [Docker host.docker.internal guide](https://eastondev.com/blog/en/posts/dev/20251217-docker-host-access/) — Network access pattern
### Tertiary (LOW confidence)
- [Unraid Forums](https://forums.unraid.net/bug-reports/stable-releases/regression-incorrect-docker-update-notification-r2807/) - Update badge behavior workarounds
- [Unraid Forums — Docker Update Status](https://forums.unraid.net/topic/114415-plugin-docker-compose-manager/page/9/) — Status file structure (observed, not documented)
- Community reports of notification spam — Anecdotal, but consistent pattern across forums
---
*Research completed: 2026-02-02*
*Research completed: 2026-02-08*
*Ready for roadmap: yes*