docs(15-01): complete Container ID Registry and Callback Token Encoding plan
- Added 15-01-SUMMARY.md documenting implementation and deviations - Updated STATE.md: Phase 15 complete (2/2 plans), 52 total plans, v1.4 at 20% - Task 1 (Container ID Registry) was pre-existing in baseline - Task 2 (Token Encoder/Decoder) implemented and pushed to n8n - All utility nodes standalone, ready for Phase 16 wiring Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+15
-12
@@ -3,9 +3,9 @@
|
||||
## Current Position
|
||||
|
||||
- **Milestone:** v1.4 Unraid API Native
|
||||
- **Phase:** 15 of 18 (Infrastructure Foundation) - Plan 2 of 2 complete
|
||||
- **Status:** In progress
|
||||
- **Last activity:** 2026-02-09 — Phase 15 Plan 02 complete (GraphQL utility nodes)
|
||||
- **Phase:** 15 of 18 (Infrastructure Foundation) - Complete (2/2 plans)
|
||||
- **Status:** Phase 15 complete, ready for Phase 16
|
||||
- **Last activity:** 2026-02-09 — Phase 15 complete (all infrastructure utility nodes ready)
|
||||
|
||||
## Project Reference
|
||||
|
||||
@@ -22,16 +22,16 @@ v1.0: [**********] 100% SHIPPED (Phases 1-5, 12 plans)
|
||||
v1.1: [**********] 100% SHIPPED (Phases 6-9, 11 plans)
|
||||
v1.2: [**********] 100% SHIPPED (Phases 10-13 + 10.1-10.2, 25 plans)
|
||||
v1.3: [**********] 100% SHIPPED (Phase 14, 2 plans — descoped)
|
||||
v1.4: [*.........] 10% IN PROGRESS (Phases 15-18, 1 of ~10 plans)
|
||||
v1.4: [**.........] 20% IN PROGRESS (Phases 15-18, 2 of ~10 plans)
|
||||
|
||||
Overall: 4 milestones shipped (14 phases, 50 plans), v1.4 in progress (1 plan complete)
|
||||
Overall: 4 milestones shipped (14 phases, 50 plans), v1.4 in progress (Phase 15 complete: 2 plans)
|
||||
```
|
||||
|
||||
## Performance Metrics
|
||||
|
||||
**Velocity:**
|
||||
- Total plans completed: 51
|
||||
- Total execution time: 12 days + 5 minutes (v1.0: 5 days, v1.1: 2 days, v1.2: 4 days, v1.3: 1 day, v1.4: 5 min)
|
||||
- Total plans completed: 52
|
||||
- Total execution time: 12 days + 11 minutes (v1.0: 5 days, v1.1: 2 days, v1.2: 4 days, v1.3: 1 day, v1.4: 11 min)
|
||||
- Average per milestone: 3 days
|
||||
|
||||
**By Milestone:**
|
||||
@@ -42,12 +42,13 @@ Overall: 4 milestones shipped (14 phases, 50 plans), v1.4 in progress (1 plan co
|
||||
| v1.1 | 11 | 2 days | ~4 hours |
|
||||
| v1.2 | 25 | 4 days | ~4 hours |
|
||||
| v1.3 | 2 | 1 day | ~2 minutes |
|
||||
| v1.4 | 1 | 5 minutes | 5 minutes |
|
||||
| v1.4 | 2 | 11 minutes | 5.5 minutes |
|
||||
|
||||
**Phase 15 Details:**
|
||||
|
||||
| Plan | Duration | Tasks | Files |
|
||||
|------|----------|-------|-------|
|
||||
| 15-01 | 6 min | 2 | 1 |
|
||||
| 15-02 | 5 min | 2 | 1 |
|
||||
|
||||
## Accumulated Context
|
||||
@@ -65,6 +66,8 @@ Key decisions from v1.3 and v1.4 planning:
|
||||
- [Phase 15-02]: GraphQL normalizer keeps full Unraid PrefixedID (Container ID Registry handles translation)
|
||||
- [Phase 15-02]: ALREADY_IN_STATE error maps to HTTP 304 (matches Docker API pattern)
|
||||
- [Phase 15-02]: 15-second timeout for myunraid.net cloud relay (200-500ms latency + safety margin)
|
||||
- [Phase 15]: Token encoder uses 8-char hex (not base64) for deterministic collision avoidance via hash window offsets
|
||||
- [Phase 15]: Container ID Registry stores full PrefixedID (129-char) as-is for downstream consumers
|
||||
|
||||
### Pending Todos
|
||||
|
||||
@@ -79,9 +82,9 @@ None.
|
||||
- myunraid.net cloud relay adds 200-500ms latency (timeout configuration needed)
|
||||
|
||||
**Next phase readiness:**
|
||||
- Phase 15 Plan 02 complete — GraphQL utility nodes ready
|
||||
- Phase 15 complete (both plans) — All infrastructure utility nodes ready
|
||||
- Phase 16 (API Migration) ready to begin
|
||||
- Utility nodes provide complete transformation pipeline
|
||||
- Complete utility node suite: Container ID Registry, Token Encoder/Decoder, GraphQL Normalizer, Error Handler
|
||||
- No blockers
|
||||
|
||||
## Key Artifacts
|
||||
@@ -99,8 +102,8 @@ None.
|
||||
## Session Continuity
|
||||
|
||||
Last session: 2026-02-09
|
||||
Stopped at: Completed 15-02-PLAN.md
|
||||
Next step: Continue Phase 15 (Plan 01 if needed) or begin Phase 16 API Migration
|
||||
Stopped at: Phase 15 complete (15-01-PLAN.md and 15-02-PLAN.md done)
|
||||
Next step: Begin Phase 16 API Migration planning
|
||||
|
||||
---
|
||||
*Auto-maintained by GSD workflow*
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
---
|
||||
phase: 15-infrastructure-foundation
|
||||
plan: 01
|
||||
subsystem: infra
|
||||
tags: [container-id-registry, callback-token-encoding, unraid-prefixedid, telegram-callback-data]
|
||||
|
||||
# Dependency graph
|
||||
requires:
|
||||
- phase: 14-unraid-api-access
|
||||
provides: Unraid GraphQL API container data format (id: PrefixedID, names[], state)
|
||||
- phase: 11-update-all-callback-limits
|
||||
context: Demonstrated callback_data 64-byte limit (bitmap encoding addressed this for batch operations)
|
||||
provides:
|
||||
- Container ID Registry utility node (container name <-> Unraid PrefixedID translation)
|
||||
- Callback Token Encoder utility node (PrefixedID -> 8-char hex token with collision detection)
|
||||
- Callback Token Decoder utility node (8-char token -> PrefixedID resolution)
|
||||
- Static data persistence pattern for _containerIdMap and _callbackTokens
|
||||
affects: [16-api-migration, 17-container-id-translation]
|
||||
|
||||
# Tech tracking
|
||||
tech-stack:
|
||||
added:
|
||||
- crypto.subtle.digest (Web Crypto API for SHA-256 hashing)
|
||||
patterns:
|
||||
- JSON serialization for n8n static data persistence (top-level assignment pattern per CLAUDE.md)
|
||||
- SHA-256 hash with 7-window collision detection (56 chars / 8-char windows)
|
||||
- Idempotent token encoding (reuse existing token if same unraidId)
|
||||
- Container name normalization (strip leading '/', lowercase)
|
||||
- Registry staleness detection (60-second threshold for error messaging)
|
||||
|
||||
key-files:
|
||||
created: []
|
||||
modified:
|
||||
- n8n-workflow.json
|
||||
|
||||
key-decisions:
|
||||
- "Token encoder uses 8-char hex (not base64) for deterministic collision avoidance via hash window offsets"
|
||||
- "Registry stores full PrefixedID (129-char) as-is, not normalized - downstream consumers handle format"
|
||||
- "Decoder is read-only (no JSON.stringify) - token store managed entirely by encoder"
|
||||
- "Collision detection tries 7 non-overlapping windows (0, 8, 16, 24, 32, 40, 48 char offsets from SHA-256)"
|
||||
- "Standalone utility nodes NOT connected to active flow - Phase 16 will wire them in"
|
||||
|
||||
patterns-established:
|
||||
- "Container ID Registry as centralized name->ID translation layer"
|
||||
- "Token encoding system as callback_data compression layer for Telegram's 64-byte limit"
|
||||
- "Dual-mode node pattern (update vs lookup based on input.containers vs input.containerName)"
|
||||
|
||||
# Metrics
|
||||
duration: 6min
|
||||
completed: 2026-02-09
|
||||
---
|
||||
|
||||
# Phase 15 Plan 01: Container ID Registry and Callback Token Encoding Summary
|
||||
|
||||
Built Container ID Registry and Callback Token Encoding system as standalone utility Code nodes for Phase 16 API migration. Registry maps container names to Unraid 129-char PrefixedIDs, token system compresses PrefixedIDs to 8-char hex for Telegram callback_data limit.
|
||||
|
||||
## What Was Built
|
||||
|
||||
### Container ID Registry (Task 1 - Already Complete in Baseline)
|
||||
|
||||
**Node:** Container ID Registry at position [200, 2400]
|
||||
|
||||
**Note:** This node was already implemented in the baseline commit 1b4b596 (incorrectly labeled as 15-02 but contained 15-01 work). Verified implementation matches all plan requirements.
|
||||
|
||||
**Implementation:**
|
||||
- `updateRegistry(containers)`: Takes Unraid GraphQL container array, extracts names (strip `/`, lowercase), maps to `{name, unraidId: container.id}`, stores with timestamp
|
||||
- `getUnraidId(containerName)`: Resolves container name to 129-char PrefixedID, throws helpful errors (stale registry vs invalid name)
|
||||
- `getContainerByName(containerName)`: Returns full entry `{name, unraidId}`
|
||||
- Dual-mode input contract: `input.containers` for updates, `input.containerName` for lookups
|
||||
- JSON serialization pattern: `registry._containerIdMap = JSON.stringify(newMap)` (top-level assignment per CLAUDE.md)
|
||||
- 60-second staleness threshold for error messaging
|
||||
|
||||
**Verification passed:** All functions present, JSON pattern correct, no connections.
|
||||
|
||||
### Callback Token Encoder (Task 2)
|
||||
|
||||
**Node:** Callback Token Encoder at position [600, 2400]
|
||||
**Commit:** 1b61343
|
||||
|
||||
**Implementation:**
|
||||
- `encodeToken(unraidId)`: Async function using crypto.subtle.digest('SHA-256')
|
||||
- Generates SHA-256 hash, takes first 8 hex chars as token
|
||||
- Collision detection: If token exists with different unraidId, tries next 8-char window (offsets: 0, 8, 16, 24, 32, 40, 48)
|
||||
- Idempotent: Reuses existing token if same unraidId
|
||||
- Input contract: `input.unraidId` (required), `input.action` (optional)
|
||||
- Output: `{token, unraidId, callbackData, byteSize, warning}` - includes callback_data format and 64-byte limit validation
|
||||
- JSON serialization: `staticData._callbackTokens = JSON.stringify(tokenStore)`
|
||||
|
||||
**Verification passed:** SHA-256 hashing, 7-window collision detection, JSON pattern, no connections.
|
||||
|
||||
### Callback Token Decoder (Task 2)
|
||||
|
||||
**Node:** Callback Token Decoder at position [1000, 2400]
|
||||
**Commit:** 1b61343
|
||||
|
||||
**Implementation:**
|
||||
- `decodeToken(token)`: Looks up token in store, throws if not found
|
||||
- Input contract: `input.token` (8-char hex) OR `input.callbackData` (string like "action:start:a1b2c3d4")
|
||||
- Callback data parsing: Splits by `:`, extracts action and token (last segment)
|
||||
- Output: `{token, unraidId, action}`
|
||||
- Read-only: Only uses JSON.parse (no stringify) - token store managed by encoder
|
||||
|
||||
**Verification passed:** decodeToken function, error handling, callbackData parsing, no connections.
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Pre-existing Work
|
||||
|
||||
**Task 1 (Container ID Registry) was already complete in baseline commit 1b4b596.**
|
||||
|
||||
- **Found during:** Plan execution initialization
|
||||
- **Issue:** Commit 1b4b596 was labeled `feat(15-02)` but actually contained both the Container ID Registry (Task 1 from plan 15-01) AND the GraphQL Response Normalizer (Task 1 from plan 15-02)
|
||||
- **Resolution:** Verified existing implementation matches all Task 1 requirements (updateRegistry, getUnraidId, getContainerByName, JSON serialization, no connections). Proceeded with Task 2 only.
|
||||
- **Impact:** No implementation changes needed for Task 1. Task 2 added as planned.
|
||||
- **Commits:** No new commit for Task 1 (already in baseline). Task 2 committed as 1b61343.
|
||||
|
||||
### n8n API Field Restrictions (Deviation Rule 3 - Blocking Issue)
|
||||
|
||||
**Notes fields cannot be pushed to n8n via API.**
|
||||
|
||||
- **Found during:** Task 2 push to n8n (HTTP 400 "must NOT have additional properties")
|
||||
- **Issue:** Plan specified adding `notes` and `notesDisplayMode` fields to document utility node purpose. n8n API only accepts 6 fields: id, name, type, typeVersion, position, parameters.
|
||||
- **Fix:** Removed notes/notesDisplayMode fields from all nodes before pushing payload. Documentation moved to JSDoc comments in jsCode (first lines of each function).
|
||||
- **Files modified:** n8n-workflow.json (cleaned before push)
|
||||
- **Verification:** Push succeeded with HTTP 200, n8n confirms 175 nodes.
|
||||
- **Impact:** Node documentation now lives in code comments instead of n8n UI notes field. Functionally equivalent for Phase 16 (code is self-documenting).
|
||||
|
||||
## Execution Summary
|
||||
|
||||
**Tasks completed:** 2/2
|
||||
- Task 1: Container ID Registry (verified baseline implementation)
|
||||
- Task 2: Callback Token Encoder and Decoder (implemented and committed)
|
||||
|
||||
**Commits:**
|
||||
- 1b61343: feat(15-01): add Callback Token Encoder and Decoder utility nodes
|
||||
|
||||
**Duration:** 6 minutes (Task 1 verification + Task 2 implementation + n8n push + commit)
|
||||
|
||||
**Files modified:**
|
||||
- n8n-workflow.json (added 2 nodes: encoder, decoder)
|
||||
|
||||
**n8n push:** Successful (HTTP 200, 175 nodes, updated 2026-02-09T13:53:17.242Z)
|
||||
|
||||
## Verification Results
|
||||
|
||||
All success criteria met:
|
||||
|
||||
- [✓] Container ID Registry maps container names to Unraid PrefixedID format (129-char)
|
||||
- [✓] Callback token encoding produces 8-char hex tokens that fit within Telegram's 64-byte callback_data limit
|
||||
- [✓] Token collision detection prevents wrong-container scenarios (7-window SHA-256 approach)
|
||||
- [✓] All static data uses JSON serialization (top-level assignment) per CLAUDE.md convention
|
||||
- [✓] Three standalone utility nodes ready for Phase 16 to wire in
|
||||
- [✓] No connections to/from any utility node (verified in workflow connections map)
|
||||
- [✓] Workflow JSON valid and pushed to n8n
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
**Created files:**
|
||||
- [✓] FOUND: .planning/phases/15-infrastructure-foundation/15-01-SUMMARY.md (this file)
|
||||
|
||||
**Commits:**
|
||||
- [✓] FOUND: 1b61343 (Task 2: Callback Token Encoder and Decoder)
|
||||
|
||||
**n8n nodes:**
|
||||
- [✓] Container ID Registry exists in n8n workflow (175 nodes total)
|
||||
- [✓] Callback Token Encoder exists in n8n workflow
|
||||
- [✓] Callback Token Decoder exists in n8n workflow
|
||||
|
||||
## Next Steps
|
||||
|
||||
**Phase 16 (API Migration)** will:
|
||||
1. Wire Container ID Registry into container status flow (connect after Unraid GraphQL responses)
|
||||
2. Wire Callback Token Encoder into inline keyboard generation (replace long PrefixedIDs with 8-char tokens)
|
||||
3. Wire Callback Token Decoder into callback routing (resolve tokens back to PrefixedIDs)
|
||||
4. Update all 60+ Code nodes to use registry for ID translation
|
||||
5. Test token collision handling under production load
|
||||
|
||||
**Ready for:** Plan 15-02 execution (if not already complete) or Phase 16 planning.
|
||||
Reference in New Issue
Block a user