docs(16): create API migration phase plans (5 plans in 2 waves)

This commit is contained in:
Lucas Berger
2026-02-09 09:19:10 -05:00
parent 5880dc4573
commit 4fc791dd43
6 changed files with 943 additions and 3 deletions
@@ -0,0 +1,139 @@
---
phase: 16-api-migration
plan: 01
type: execute
wave: 1
depends_on: []
files_modified: [n8n-status.json]
autonomous: true
must_haves:
truths:
- "Container list displays same containers with same names and states as before"
- "Container submenu shows correct status for selected container"
- "Pagination works identically (same page size, same navigation)"
artifacts:
- path: "n8n-status.json"
provides: "Container status queries via Unraid GraphQL API"
contains: "graphql"
key_links:
- from: "n8n-status.json HTTP Request nodes"
to: "Unraid GraphQL API"
via: "POST to $env.UNRAID_HOST/graphql"
pattern: "UNRAID_HOST.*graphql"
- from: "n8n-status.json HTTP Request nodes"
to: "Existing Code nodes (Build Container List, Build Container Submenu, Build Paginated List)"
via: "GraphQL Response Normalizer transforms Unraid response to Docker API contract"
pattern: "Names.*State.*Id"
---
<objective>
Migrate n8n-status.json from Docker socket proxy to Unraid GraphQL API for all container listing and status queries.
Purpose: Container status is the most-used feature and simplest migration target (3 read-only GET queries become 3 GraphQL POST queries). Establishes the query migration pattern for all subsequent plans.
Output: n8n-status.json with all Docker API HTTP Request nodes replaced by Unraid GraphQL queries, wired through GraphQL Response Normalizer so downstream Code nodes see identical data shape.
</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/ROADMAP.md
@.planning/STATE.md
@.planning/phases/16-api-migration/16-RESEARCH.md
@.planning/phases/15-infrastructure-foundation/15-01-SUMMARY.md
@.planning/phases/15-infrastructure-foundation/15-02-SUMMARY.md
@n8n-status.json
@n8n-workflow.json (for Phase 15 utility node code — Container ID Registry, GraphQL Response Normalizer)
@ARCHITECTURE.md
</context>
<tasks>
<task type="auto">
<name>Task 1: Replace Docker API queries with Unraid GraphQL queries in n8n-status.json</name>
<files>n8n-status.json</files>
<action>
Replace all 3 Docker API HTTP Request nodes with Unraid GraphQL query equivalents. For each node:
1. **Docker List Containers** (used for list view):
- Change from: GET `http://docker-socket-proxy:2375/containers/json?all=true`
- Change to: POST `={{ $env.UNRAID_HOST }}/graphql` with body `{"query": "query { docker { containers { id names state image status } } }"}`
- Set method to POST, add headers: `Content-Type: application/json`, `x-api-key: ={{ $env.UNRAID_API_KEY }}`
- Set timeout to 15000ms (15s for myunraid.net relay)
- Set `options.response.response.fullResponse` to false (we want body only, matching current Docker API behavior)
- Set error handling to `continueRegularOutput` to match existing pattern
2. **Docker Get Container** (used for submenu/status view):
- Same transformation as above (same query — downstream Code node filters by name)
3. **Docker List For Paginate** (used for pagination):
- Same transformation as above
After converting each HTTP Request node, add a **GraphQL Response Normalizer** Code node between each HTTP Request and its downstream Code node consumer. The normalizer code must be copied from the standalone "GraphQL Response Normalizer" utility node in n8n-workflow.json (at position [200, 2600]). The normalizer transforms Unraid response shape `{data: {docker: {containers: [...]}}}` to flat array `[{Id, Names, State, Image, Status}]` matching Docker API contract.
**Wiring pattern for each of the 3 queries:**
```
HTTP Request (GraphQL) → GraphQL Response Normalizer (Code) → existing Code node (unchanged)
```
The normalizer handles:
- Extract `data.docker.containers` from GraphQL response
- Map `id``Id` (preserve full Unraid PrefixedID)
- Map `names``Names` (array, keep leading slash convention)
- Map `state``State` (UPPERCASE → lowercase: RUNNING→running, STOPPED→exited, PAUSED→paused)
- Map `image``Image`
- Map `status``Status`
**Also update Container ID Registry cache** after normalizer: Add a Code node after each normalizer that updates the Container ID Registry static data. Copy the registry update logic from the "Container ID Registry" utility node (position [200, 2400] in n8n-workflow.json). This ensures name-to-PrefixedID mapping stays fresh for downstream mutation operations.
Rename the HTTP Request nodes from Docker-centric names:
- "Docker List Containers" → "Query Containers"
- "Docker Get Container" → "Query Container Status"
- "Docker List For Paginate" → "Query Containers For Paginate"
Keep all downstream Code nodes (Build Container List, Build Container Submenu, Build Paginated List, Prepare * Request) completely unchanged — the normalizer ensures they receive Docker API format.
**Implementation note:** The normalizer should be implemented as inline Code nodes in this sub-workflow (not references to the main workflow utility node, since sub-workflows cannot cross-reference parent workflow nodes). Copy the normalizer logic from n8n-workflow.json's "GraphQL Response Normalizer" node and embed it in each position needed. Similarly for registry cache updates.
To keep the workflow lean, use a single shared normalizer node where possible. If all 3 HTTP Request queries produce the same shape and feed into separate downstream paths, consider whether a single normalizer can serve multiple paths via the existing Route Action switch node routing, or if 3 separate normalizers are needed due to n8n's connection model.
</action>
<verify>
Load n8n-status.json with python3 and verify:
1. Zero HTTP Request nodes contain "docker-socket-proxy" in URL
2. All HTTP Request nodes use POST method to `$env.UNRAID_HOST/graphql`
3. GraphQL Response Normalizer Code nodes exist between HTTP requests and downstream Code nodes
4. Downstream Code nodes (Build Container List, Build Container Submenu, Build Paginated List) are UNCHANGED
5. All connections are valid (no dangling references)
6. Push to n8n via API and verify HTTP 200
</verify>
<done>
All 3 container queries in n8n-status.json use Unraid GraphQL API instead of Docker socket proxy. Normalizer transforms responses to Docker API contract. Downstream Code nodes unchanged. Workflow pushed to n8n successfully.
</done>
</task>
</tasks>
<verification>
1. Load n8n-status.json and confirm zero "docker-socket-proxy" references
2. Confirm all HTTP Request nodes point to `$env.UNRAID_HOST/graphql`
3. Confirm normalizer Code nodes exist with correct state mapping (RUNNING→running, STOPPED→exited)
4. Confirm downstream Code nodes are byte-for-byte identical to pre-migration versions
5. Push to n8n and verify HTTP 200 response
</verification>
<success_criteria>
- n8n-status.json has zero Docker socket proxy references
- All container data flows through GraphQL Response Normalizer
- Container ID Registry cache updated on every query
- Downstream Code nodes unchanged (zero-change migration for consumers)
- Workflow valid and pushed to n8n
</success_criteria>
<output>
After completion, create `.planning/phases/16-api-migration/16-01-SUMMARY.md`
</output>