docs(16-api-migration): create gap closure plan 16-06
This commit is contained in:
@@ -83,7 +83,7 @@ Plans:
|
|||||||
4. User can batch update multiple containers via Unraid API
|
4. User can batch update multiple containers via Unraid API
|
||||||
5. User can "update all :latest" via Unraid API
|
5. User can "update all :latest" via Unraid API
|
||||||
6. Unraid update badges clear automatically after bot-initiated updates (no manual sync)
|
6. Unraid update badges clear automatically after bot-initiated updates (no manual sync)
|
||||||
**Plans**: 5 plans
|
**Plans**: 6 plans
|
||||||
|
|
||||||
Plans:
|
Plans:
|
||||||
- [ ] 16-01-PLAN.md -- Container Status workflow migration (n8n-status.json)
|
- [ ] 16-01-PLAN.md -- Container Status workflow migration (n8n-status.json)
|
||||||
@@ -91,6 +91,7 @@ Plans:
|
|||||||
- [ ] 16-03-PLAN.md -- Container Update workflow migration (n8n-update.json)
|
- [ ] 16-03-PLAN.md -- Container Update workflow migration (n8n-update.json)
|
||||||
- [ ] 16-04-PLAN.md -- Batch UI workflow migration (n8n-batch-ui.json)
|
- [ ] 16-04-PLAN.md -- Batch UI workflow migration (n8n-batch-ui.json)
|
||||||
- [ ] 16-05-PLAN.md -- Main workflow routing migration (n8n-workflow.json)
|
- [ ] 16-05-PLAN.md -- Main workflow routing migration (n8n-workflow.json)
|
||||||
|
- [ ] 16-06-PLAN.md -- Gap closure: text command entry points migration + dead code removal
|
||||||
|
|
||||||
#### Phase 17: Cleanup
|
#### Phase 17: Cleanup
|
||||||
**Goal**: All Docker socket proxy artifacts removed from codebase
|
**Goal**: All Docker socket proxy artifacts removed from codebase
|
||||||
@@ -138,11 +139,11 @@ Phases execute in numeric order: 1-14 (complete) → 15 → 16 → 17 → 18
|
|||||||
| 13 | Documentation Overhaul | v1.2 | 1/1 | Complete | 2026-02-08 |
|
| 13 | Documentation Overhaul | v1.2 | 1/1 | Complete | 2026-02-08 |
|
||||||
| 14 | Unraid API Access | v1.3 | 2/2 | Complete | 2026-02-08 |
|
| 14 | Unraid API Access | v1.3 | 2/2 | Complete | 2026-02-08 |
|
||||||
| 15 | Infrastructure Foundation | v1.4 | 2/2 | Complete | 2026-02-09 |
|
| 15 | Infrastructure Foundation | v1.4 | 2/2 | Complete | 2026-02-09 |
|
||||||
| 16 | API Migration | v1.4 | 0/5 | Not started | - |
|
| 16 | API Migration | v1.4 | 5/6 | In progress | - |
|
||||||
| 17 | Cleanup | v1.4 | 0/? | Not started | - |
|
| 17 | Cleanup | v1.4 | 0/? | Not started | - |
|
||||||
| 18 | Documentation | v1.4 | 0/? | Not started | - |
|
| 18 | Documentation | v1.4 | 0/? | Not started | - |
|
||||||
|
|
||||||
**Total: 4 milestones shipped (14 phases, 50 plans), v1.4 in progress (Phase 15 complete, 3 phases remaining)**
|
**Total: 4 milestones shipped (14 phases, 50 plans), v1.4 in progress (Phase 15 complete, Phase 16: 5/6 plans)**
|
||||||
|
|
||||||
---
|
---
|
||||||
*Updated: 2026-02-09 — Phase 15 complete (2/2 plans)*
|
*Updated: 2026-02-09 — Phase 16 gap closure plan added (16-06)*
|
||||||
|
|||||||
@@ -0,0 +1,257 @@
|
|||||||
|
---
|
||||||
|
phase: 16-api-migration
|
||||||
|
plan: 06
|
||||||
|
type: execute
|
||||||
|
wave: 1
|
||||||
|
depends_on: []
|
||||||
|
files_modified: [n8n-workflow.json]
|
||||||
|
autonomous: true
|
||||||
|
gap_closure: true
|
||||||
|
|
||||||
|
must_haves:
|
||||||
|
truths:
|
||||||
|
- "Text command 'start/stop/restart <container>' queries containers via GraphQL, not Docker socket proxy"
|
||||||
|
- "Text command 'update <container>' queries containers via GraphQL, not Docker socket proxy"
|
||||||
|
- "Text command 'batch' queries containers via GraphQL, not Docker socket proxy"
|
||||||
|
- "Zero active Execute Command nodes with docker-socket-proxy references remain in n8n-workflow.json"
|
||||||
|
artifacts:
|
||||||
|
- path: "n8n-workflow.json"
|
||||||
|
provides: "Main workflow with all text command paths using GraphQL"
|
||||||
|
contains: "UNRAID_HOST"
|
||||||
|
key_links:
|
||||||
|
- from: "n8n-workflow.json (Query Containers for Action)"
|
||||||
|
to: "Unraid GraphQL API"
|
||||||
|
via: "POST to $env.UNRAID_HOST/graphql"
|
||||||
|
pattern: "UNRAID_HOST.*graphql"
|
||||||
|
- from: "n8n-workflow.json (Query Containers for Update)"
|
||||||
|
to: "Unraid GraphQL API"
|
||||||
|
via: "POST to $env.UNRAID_HOST/graphql"
|
||||||
|
pattern: "UNRAID_HOST.*graphql"
|
||||||
|
- from: "n8n-workflow.json (Query Containers for Batch)"
|
||||||
|
to: "Unraid GraphQL API"
|
||||||
|
via: "POST to $env.UNRAID_HOST/graphql"
|
||||||
|
pattern: "UNRAID_HOST.*graphql"
|
||||||
|
---
|
||||||
|
|
||||||
|
<objective>
|
||||||
|
Migrate the 3 remaining text command entry points in the main workflow from Docker socket proxy Execute Command nodes to Unraid GraphQL API queries, and remove dead code nodes.
|
||||||
|
|
||||||
|
Purpose: Close the verification gaps that block Phase 17 (docker-socket-proxy removal). The 3 text command paths (start/stop/restart, update, batch) still use Execute Command nodes with `curl` to the docker-socket-proxy. After this plan, ALL container operations in the main workflow use GraphQL -- zero Docker socket proxy dependencies remain.
|
||||||
|
|
||||||
|
Output: Updated n8n-workflow.json with 3 GraphQL query chains replacing 3 Execute Command nodes, 6 dead code nodes removed.
|
||||||
|
</objective>
|
||||||
|
|
||||||
|
<execution_context>
|
||||||
|
@/home/luc/.claude/get-shit-done/workflows/execute-plan.md
|
||||||
|
@/home/luc/.claude/get-shit-done/templates/summary.md
|
||||||
|
</execution_context>
|
||||||
|
|
||||||
|
<context>
|
||||||
|
@.planning/PROJECT.md
|
||||||
|
@.planning/STATE.md
|
||||||
|
@.planning/phases/16-api-migration/16-01-SUMMARY.md
|
||||||
|
@.planning/phases/16-api-migration/16-05-SUMMARY.md
|
||||||
|
@.planning/phases/16-api-migration/16-VERIFICATION.md
|
||||||
|
@n8n-workflow.json
|
||||||
|
@CLAUDE.md
|
||||||
|
</context>
|
||||||
|
|
||||||
|
<tasks>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 1: Replace 3 Execute Command nodes with GraphQL query chains</name>
|
||||||
|
<files>n8n-workflow.json</files>
|
||||||
|
<action>
|
||||||
|
Replace 3 Execute Command nodes that use `curl` to docker-socket-proxy with GraphQL HTTP Request + Normalizer + Registry Update chains. Follow the exact same pattern established in Plan 16-05 (Task 1) for the 6 inline keyboard query paths.
|
||||||
|
|
||||||
|
**Node 1: "Docker List for Action" (id: exec-docker-list-action)**
|
||||||
|
|
||||||
|
Current: Execute Command node running `curl -s --max-time 5 'http://docker-socket-proxy:2375/v1.47/containers/json?all=true'`
|
||||||
|
Position: [1120, 400]
|
||||||
|
Connected FROM: "Parse Action Command"
|
||||||
|
Connected TO: "Prepare Action Match Input"
|
||||||
|
|
||||||
|
Replace with 3 nodes:
|
||||||
|
|
||||||
|
1a. **"Query Containers for Action"** — HTTP Request node (replaces Execute Command)
|
||||||
|
- type: n8n-nodes-base.httpRequest, typeVersion: 4.2
|
||||||
|
- method: POST
|
||||||
|
- url: `={{ $env.UNRAID_HOST }}/graphql`
|
||||||
|
- authentication: predefinedCredentialType, httpHeaderAuth, credential "Unraid API Key"
|
||||||
|
- sendBody: true, specifyBody: json
|
||||||
|
- jsonBody: `{"query": "query { docker { containers { id names state image status } } }"}`
|
||||||
|
- options: timeout: 15000
|
||||||
|
- position: [1120, 400]
|
||||||
|
|
||||||
|
1b. **"Normalize Action Containers"** — Code node (GraphQL response normalizer)
|
||||||
|
- Inline normalizer code (same as Plan 16-01/16-05 pattern):
|
||||||
|
- Extract `data.docker.containers` from GraphQL response
|
||||||
|
- Map fields: id->Id, names->Names (add '/' prefix), state->State (RUNNING->running, STOPPED->exited, PAUSED->paused), image->Image, status->Status
|
||||||
|
- Handle GraphQL errors (check response.errors array)
|
||||||
|
- position: [1230, 400] (shift right to make room)
|
||||||
|
|
||||||
|
1c. **"Update Registry (Action)"** — Code node (Container ID Registry update)
|
||||||
|
- Inline registry update code (same as Plan 16-01/16-05 pattern):
|
||||||
|
- Read static data `_containerIdRegistry`, parse JSON
|
||||||
|
- Map each normalized container: name (strip '/') -> { name, unraidId: container.Id }
|
||||||
|
- Write back to static data with JSON.stringify (top-level assignment for persistence)
|
||||||
|
- Pass through all container items unchanged
|
||||||
|
- position: [1340, 400] (note: this is where "Prepare Action Match Input" currently sits)
|
||||||
|
|
||||||
|
**CRITICAL wiring change for "Prepare Action Match Input":**
|
||||||
|
- Move "Prepare Action Match Input" position to [1450, 400] (shift right to accommodate new nodes)
|
||||||
|
- Update its Code to read normalized containers instead of `stdout`:
|
||||||
|
- OLD: `const dockerOutput = $input.item.json.stdout;`
|
||||||
|
- NEW: `const containers = $input.all().map(item => item.json);` then `const dockerOutput = JSON.stringify(containers);`
|
||||||
|
- The matching sub-workflow (n8n-matching.json) expects `containerList` as a JSON string of the container array, so JSON.stringify the normalized array.
|
||||||
|
- Connection chain: Query Containers for Action -> Normalize Action Containers -> Update Registry (Action) -> Prepare Action Match Input -> Execute Action Match (unchanged)
|
||||||
|
|
||||||
|
**Node 2: "Docker List for Update" (id: exec-docker-list-update)**
|
||||||
|
|
||||||
|
Current: Execute Command node running same curl command
|
||||||
|
Position: [1120, 1000]
|
||||||
|
Connected FROM: "Parse Update Command"
|
||||||
|
Connected TO: "Prepare Update Match Input"
|
||||||
|
|
||||||
|
Replace with 3 nodes (same pattern):
|
||||||
|
|
||||||
|
2a. **"Query Containers for Update"** — HTTP Request node
|
||||||
|
- Same config as 1a, position: [1120, 1000]
|
||||||
|
|
||||||
|
2b. **"Normalize Update Containers"** — Code node
|
||||||
|
- Same normalizer code, position: [1230, 1000]
|
||||||
|
|
||||||
|
2c. **"Update Registry (Update)"** — Code node
|
||||||
|
- Same registry code, position: [1340, 1000]
|
||||||
|
|
||||||
|
**Update "Prepare Update Match Input":**
|
||||||
|
- Move position to [1450, 1000]
|
||||||
|
- Change Code from `$input.item.json.stdout` to `JSON.stringify($input.all().map(item => item.json))`
|
||||||
|
- Connection chain: Query Containers for Update -> Normalize Update Containers -> Update Registry (Update) -> Prepare Update Match Input -> Execute Update Match (unchanged)
|
||||||
|
|
||||||
|
**Node 3: "Get Containers for Batch" (id: exec-docker-list-batch)**
|
||||||
|
|
||||||
|
Current: Execute Command node running same curl command
|
||||||
|
Position: [1340, -300]
|
||||||
|
Connected FROM: "Is Batch Command"
|
||||||
|
Connected TO: "Prepare Batch Match Input"
|
||||||
|
|
||||||
|
Replace with 3 nodes (same pattern):
|
||||||
|
|
||||||
|
3a. **"Query Containers for Batch"** — HTTP Request node
|
||||||
|
- Same config as 1a, position: [1340, -300]
|
||||||
|
|
||||||
|
3b. **"Normalize Batch Containers"** — Code node
|
||||||
|
- Same normalizer code, position: [1450, -300]
|
||||||
|
|
||||||
|
3c. **"Update Registry (Batch)"** — Code node
|
||||||
|
- Same registry code, position: [1560, -300]
|
||||||
|
|
||||||
|
**Update "Prepare Batch Match Input":**
|
||||||
|
- Move position to [1670, -300]
|
||||||
|
- Change Code from `$input.item.json.stdout` to `JSON.stringify($input.all().map(item => item.json))`
|
||||||
|
- Connection chain: Is Batch Command [output 0] -> Query Containers for Batch -> Normalize Batch Containers -> Update Registry (Batch) -> Prepare Batch Match Input -> Execute Batch Match (unchanged)
|
||||||
|
|
||||||
|
**Connection updates in the connections object:**
|
||||||
|
- "Parse Action Command" target changes from "Docker List for Action" to "Query Containers for Action"
|
||||||
|
- "Parse Update Command" target changes from "Docker List for Update" to "Query Containers for Update"
|
||||||
|
- "Is Batch Command" output 0 target changes from "Get Containers for Batch" to "Query Containers for Batch"
|
||||||
|
- Add new connection entries for each 3-node chain (Query -> Normalize -> Registry -> Prepare)
|
||||||
|
- Remove old connection entries for deleted nodes
|
||||||
|
|
||||||
|
**Important:** Use the same inline normalizer and registry update Code exactly as implemented in Plan 16-05 Task 1. Copy the jsCode from any of the 6 existing normalizer/registry nodes already in n8n-workflow.json (e.g., find "Normalize GraphQL Response" or "Update Container Registry" nodes). Do NOT reference utility node templates from the main workflow -- sub-workflow pattern requires inline code (per Phase 16-01 decision).
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
1. Search n8n-workflow.json for "docker-socket-proxy" -- should find ONLY the 2 infra-exclusion filter references in "Check Available Updates" (line ~2776) and "Prepare Update All Batch" (line ~3093) Code nodes which use `socket-proxy` as a container name pattern, NOT as an API endpoint
|
||||||
|
2. Search for "executeCommand" node type -- should find ZERO instances (all 3 Execute Command nodes removed)
|
||||||
|
3. Search for "Query Containers for Action", "Query Containers for Update", "Query Containers for Batch" -- all 3 must exist
|
||||||
|
4. Search for "Normalize Action Containers", "Normalize Update Containers", "Normalize Batch Containers" -- all 3 must exist
|
||||||
|
5. Search for "Update Registry (Action)", "Update Registry (Update)", "Update Registry (Batch)" -- all 3 must exist
|
||||||
|
6. Verify connections: "Parse Action Command" -> "Query Containers for Action", "Parse Update Command" -> "Query Containers for Update", "Is Batch Command" [0] -> "Query Containers for Batch"
|
||||||
|
7. Push workflow to n8n and verify HTTP 200 response
|
||||||
|
</verify>
|
||||||
|
<done>
|
||||||
|
All 3 text command entry points (action, update, batch) query containers via Unraid GraphQL API using the HTTP Request -> Normalizer -> Registry Update -> Prepare Match Input chain. Zero Execute Command nodes remain. Workflow pushes successfully to n8n.
|
||||||
|
</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 2: Remove dead code nodes and clean stale references</name>
|
||||||
|
<files>n8n-workflow.json</files>
|
||||||
|
<action>
|
||||||
|
Remove 6 dead code nodes that are no longer connected to any live path. These are remnants of the old Docker API direct-execution pattern that was replaced by sub-workflow calls during modularization.
|
||||||
|
|
||||||
|
**Dead code nodes to remove from the nodes array:**
|
||||||
|
|
||||||
|
1. **"Build Action Command"** (id: code-build-action-cmd) — Code node that built docker curl commands for text command actions. No incoming connections from any live path.
|
||||||
|
|
||||||
|
2. **"Execute Action"** (id: exec-action) — Execute Command node that ran the curl command built by "Build Action Command". Only fed by dead node above.
|
||||||
|
|
||||||
|
3. **"Parse Action Result"** (id: code-parse-action-result) — Code node that parsed curl HTTP status codes. Only fed by dead node above. NOTE: Its output went to "Send Action Result" which IS still live (also receives from "Handle Text Action Result"), so only remove this node, not "Send Action Result".
|
||||||
|
|
||||||
|
4. **"Build Immediate Action Command"** (id: code-build-immediate-action-cmd) — Code node that built docker curl commands for inline keyboard immediate actions. No incoming connections from any live path.
|
||||||
|
|
||||||
|
5. **"Execute Immediate Action"** (id: exec-immediate-action) — Execute Command node that ran the curl command built by "Build Immediate Action Command". Only fed by dead node above.
|
||||||
|
|
||||||
|
6. **"Format Immediate Result"** (id: code-format-immediate-result) — Code node that formatted immediate action results. Only fed by dead node above. NOTE: Its output went to "Send Immediate Result" which IS still live (also receives from "Handle Inline Action Result"), so only remove this node, not "Send Immediate Result".
|
||||||
|
|
||||||
|
**Connection entries to remove:**
|
||||||
|
|
||||||
|
Remove the following entries from the connections object:
|
||||||
|
- "Build Action Command" (connects to "Execute Action")
|
||||||
|
- "Execute Action" (connects to "Parse Action Result")
|
||||||
|
- "Parse Action Result" (connects to "Send Action Result")
|
||||||
|
- "Build Immediate Action Command" (connects to "Execute Immediate Action")
|
||||||
|
- "Execute Immediate Action" (connects to "Format Immediate Result")
|
||||||
|
- "Format Immediate Result" (connects to "Send Immediate Result")
|
||||||
|
|
||||||
|
**DO NOT remove:**
|
||||||
|
- "Send Action Result" — still receives from "Handle Text Action Result" (live path)
|
||||||
|
- "Send Immediate Result" — still receives from "Handle Inline Action Result" (live path)
|
||||||
|
|
||||||
|
**After removal:**
|
||||||
|
- Verify node count decreased by 6 (from 193, accounting for 9 new nodes added in Task 1, net change should be 193 + 9 - 6 = 196 nodes, but the 3 Execute Command nodes from Task 1 were also removed, so: 193 - 3 removed + 9 added - 6 dead = 193 nodes)
|
||||||
|
- Push updated workflow to n8n
|
||||||
|
|
||||||
|
**Stale docker-socket-proxy references:**
|
||||||
|
The 2 remaining `socket-proxy` references in "Check Available Updates" and "Prepare Update All Batch" Code nodes are functional infrastructure exclusion filters (they exclude `socket-proxy` named containers from update-all operations). These are NOT stale -- they serve a valid purpose as long as the docker-socket-proxy container exists on the Unraid server. They will be addressed in Phase 17 (Cleanup) when the docker-socket-proxy container is actually removed.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
1. Count nodes in n8n-workflow.json -- should be 193 (193 original - 3 Execute Commands replaced + 9 new GraphQL nodes - 6 dead code removed = 193)
|
||||||
|
2. Search for "Build Action Command" -- should NOT exist
|
||||||
|
3. Search for "Build Immediate Action Command" -- should NOT exist
|
||||||
|
4. Search for "exec-action" -- should NOT exist
|
||||||
|
5. Search for "exec-immediate-action" -- should NOT exist
|
||||||
|
6. Verify "Send Action Result" still exists and is connected from "Handle Text Action Result"
|
||||||
|
7. Verify "Send Immediate Result" still exists and is connected from "Handle Inline Action Result"
|
||||||
|
8. Push workflow to n8n and verify HTTP 200 response
|
||||||
|
</verify>
|
||||||
|
<done>
|
||||||
|
6 dead code nodes removed. "Send Action Result" and "Send Immediate Result" preserved with their live connections. Workflow node count is 193. Zero dead Execute Command or docker curl code nodes remain.
|
||||||
|
</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
</tasks>
|
||||||
|
|
||||||
|
<verification>
|
||||||
|
1. `grep -c "docker-socket-proxy" n8n-workflow.json` returns 2 (only infra-exclusion filter patterns, not API endpoints)
|
||||||
|
2. `grep -c "executeCommand" n8n-workflow.json` returns 0 (zero Execute Command nodes)
|
||||||
|
3. `grep -c "UNRAID_HOST" n8n-workflow.json` returns 12+ (9 existing GraphQL nodes + 3 new ones)
|
||||||
|
4. `grep "Query Containers for Action\|Query Containers for Update\|Query Containers for Batch" n8n-workflow.json` finds all 3 new query nodes
|
||||||
|
5. Workflow pushes to n8n successfully (HTTP 200)
|
||||||
|
6. All connection chains intact: Parse Command -> Query -> Normalize -> Registry -> Prepare Match -> Execute Match -> Route Result
|
||||||
|
</verification>
|
||||||
|
|
||||||
|
<success_criteria>
|
||||||
|
- Zero Execute Command nodes with docker-socket-proxy curl commands
|
||||||
|
- 3 new GraphQL HTTP Request + Normalizer + Registry Update chains for text command paths
|
||||||
|
- 6 dead code nodes removed
|
||||||
|
- Total node count: 193
|
||||||
|
- Workflow pushes to n8n successfully
|
||||||
|
- All text command paths route through GraphQL before reaching matching sub-workflow
|
||||||
|
- Phase 16 verification gaps closed: all 3 partial truths become fully verified
|
||||||
|
</success_criteria>
|
||||||
|
|
||||||
|
<output>
|
||||||
|
After completion, create `.planning/phases/16-api-migration/16-06-SUMMARY.md`
|
||||||
|
</output>
|
||||||
Reference in New Issue
Block a user