diff --git a/.planning/phases/14-unraid-api-access/14-RESEARCH.md b/.planning/phases/14-unraid-api-access/14-RESEARCH.md new file mode 100644 index 0000000..1d4d4ee --- /dev/null +++ b/.planning/phases/14-unraid-api-access/14-RESEARCH.md @@ -0,0 +1,593 @@ +# Phase 14: Unraid API Access - Research + +**Researched:** 2026-02-08 +**Domain:** Unraid GraphQL API integration from n8n container +**Confidence:** HIGH + +## Summary + +Phase 14 establishes connectivity from the n8n container to Unraid's GraphQL API endpoint and validates authentication, enabling subsequent phases to sync container update status. This phase is pure infrastructure setup — no workflow modifications, no mutations called, no status synchronization implemented yet. + +The Unraid GraphQL API is the official interface for Docker container management, available natively in Unraid 7.2+ or via the Connect plugin for 6.9-7.1. Authentication uses API keys with granular permission scoping. The API endpoint is `http:///graphql` and uses standard GraphQL over HTTP with x-api-key header authentication. + +Network access from the n8n container to the Unraid host requires either `host.docker.internal` (with `--add-host=host.docker.internal:host-gateway` in container config) or direct IP/hostname access. Container ID format uses Unraid's `PrefixedID` scalar type (e.g., `docker:containername` or server-prefixed format like `123:containername`). + +**Primary recommendation:** Use `host.docker.internal` for network access (standard Docker pattern), store credentials in `.env.unraid-api` file (mirrors existing n8n API pattern), and validate with a simple container list query before planning mutation calls in Phase 15. + +--- + + +## User Constraints (from CONTEXT.md) + +### Locked Decisions + +**Credential management** +- Dual storage: `.env.unraid-api` file (for CLI/deploy scripts) + n8n credential (for workflow nodes) +- `.env.unraid-api` contains both `UNRAID_API_KEY` and `UNRAID_HOST` (mirrors `.env.n8n-api` pattern) +- Phase includes documentation for creating the Unraid API key in WebGUI with correct permissions +- File is gitignored + +**Network connectivity** +- User runs Unraid on default WebGUI ports — GraphQL API assumed on same port +- HTTP vs HTTPS and self-signed cert handling needs to be figured out during research/testing +- Connectivity verification done purely through n8n workflow nodes — no separate test script +- Host URL stored in `UNRAID_HOST` env var — user configures during setup + +**GraphQL query design** +- Document only the queries/mutations relevant to update sync — not the full Docker schema +- Container ID format mapping needs research — we don't know how Unraid identifies containers in GraphQL yet +- GraphQL API contract documented in ARCHITECTURE.md alongside existing Docker API contract + +**Error handling & feedback** +- Clear, descriptive error messages on failure (what failed, why, what to check) +- Use existing error logging system — same pattern as Docker API errors, not a separate log category +- Phase 14 tests connectivity only — permission validation happens naturally in Phase 15 when mutations are attempted +- No user-facing Telegram health check command for Unraid API — errors surface naturally during sync failures + +### Claude's Discretion + +- n8n credential type selection (based on Unraid GraphQL API's actual auth mechanism) +- Network approach for n8n container reaching Unraid host (host IP, Docker networking, etc.) +- What fields to include in the test query (based on what downstream phases need) + +### Deferred Ideas (OUT OF SCOPE) + +None — discussion stayed within phase scope + + +--- + +## Standard Stack + +### Core + +| Library | Version | Purpose | Why Standard | +|---------|---------|---------|--------------| +| Unraid GraphQL API | 7.2+ native, 6.9-7.1 via Connect plugin | Container management and status sync | Official Unraid interface, same mechanism as WebGUI | +| n8n HTTP Request node | Built-in (n8n 1.x) | GraphQL client | Standard GraphQL-over-HTTP pattern, no additional dependencies | +| Unraid API Key | N/A (credential) | Authentication | Official authentication method, granular permission scoping | + +### Supporting + +| Library | Version | Purpose | When to Use | +|---------|---------|---------|-------------| +| n8n Credential system | Built-in | Secure credential storage | Store `UNRAID_HOST` and `UNRAID_API_KEY` for workflow access | +| `.env.unraid-api` file | N/A (file) | External credential storage | CLI testing, deployment scripts, credential documentation | + +### Alternatives Considered + +| Instead of | Could Use | Tradeoff | +|------------|-----------|----------| +| GraphQL API | Direct file write to `/var/lib/docker/unraid-update-status.json` | File format undocumented, brittle, no UI refresh trigger | +| API key auth | Session cookies | Requires WebGUI login flow, session expiry handling, fragile | +| `host.docker.internal` | Hardcoded Unraid IP | Works but not portable, requires manual config changes | + +**Installation:** + +No n8n dependencies required (HTTP Request node is built-in). Requires Unraid API key creation on host: + +```bash +# SSH to Unraid: +unraid-api apikey --create \ + --name "Docker Manager Bot" \ + --permissions "DOCKER:UPDATE_ANY" \ + --description "Telegram bot container update sync" \ + --json +``` + +**Network configuration:** + +If using `host.docker.internal` (recommended), add to n8n container config via Unraid Docker template editor: + +``` +Extra Parameters: --add-host=host.docker.internal:host-gateway +``` + +--- + +## Architecture Patterns + +### Recommended Credential Storage Pattern + +**Dual storage approach** (mirrors existing `.env.n8n-api` pattern): + +```bash +# .env.unraid-api (gitignored) +UNRAID_HOST=http://host.docker.internal +UNRAID_API_KEY=your-api-key-here +``` + +**n8n credential configuration:** + +1. Credentials → Add Credential → Header Auth +2. Name: `Unraid API Key` +3. Header Name: `x-api-key` +4. Header Value: Reference environment variable or paste key directly + +**Why dual storage:** CLI scripts (testing, deployment verification) use `.env` file, n8n workflows use n8n credential system. Keeps patterns consistent with existing n8n API access. + +### Network Access Pattern + +**Option 1: host.docker.internal (RECOMMENDED)** + +```javascript +// n8n HTTP Request node configuration +{ + url: 'http://host.docker.internal/graphql', + method: 'POST', + authentication: 'headerAuth', + credentialName: 'Unraid API Key', + body: { + query: 'query { docker { containers { id names state } } }' + } +} +``` + +**Requires:** `--add-host=host.docker.internal:host-gateway` in n8n container config + +**Pros:** Portable (works across different Unraid IPs), standard Docker pattern +**Cons:** Requires container reconfiguration (one-time setup) + +**Option 2: Direct IP/Hostname** + +```javascript +// Alternative for environments where host.docker.internal doesn't work +{ + url: 'http://192.168.1.100/graphql', // or http://tower.local/graphql + // ... rest same as Option 1 +} +``` + +**Pros:** No container reconfiguration needed +**Cons:** Hardcoded, not portable if Unraid IP changes + +**Recommendation:** Use `host.docker.internal` for primary implementation, document direct IP as fallback. + +### GraphQL Query Pattern for Testing + +**Test connectivity query:** + +```graphql +query TestConnectivity { + docker { + containers { + id + names + state + isUpdateAvailable + } + } +} +``` + +**What this validates:** +- Network connectivity (can reach `/graphql` endpoint) +- Authentication (API key accepted) +- Permissions (can read Docker data) +- Container ID format (see actual ID structure in response) + +**n8n HTTP Request node body:** + +```json +{ + "query": "query { docker { containers { id names state isUpdateAvailable } } }" +} +``` + +### Container ID Format Documentation Pattern + +**Research finding:** Unraid uses `PrefixedID` scalar type. Format is `:` where server_id is stripped on input, added on output. + +**Example observed formats:** +- `docker:plex` (name-based, common pattern) +- `123:456` (numeric server + resource ID) + +**Critical:** Actual format must be validated during Phase 14 testing. The GraphQL schema defines `PrefixedID` as abstract — implementation details discovered by running test query. + +**Documentation location:** `ARCHITECTURE.md` section "GraphQL API Contract" (to be added in Phase 14). + +### Anti-Patterns to Avoid + +- **Hardcoding credentials in workflow nodes:** Always use n8n credential system or environment variables +- **Testing GraphQL mutations in Phase 14:** Only queries, mutations are Phase 15+ +- **Skipping network connectivity verification:** Must validate HTTP access before assuming GraphQL works +- **Using Docker socket proxy for Unraid API calls:** Different security boundary — Unraid API is host-level, not Docker daemon + +--- + +## Don't Hand-Roll + +| Problem | Don't Build | Use Instead | Why | +|---------|-------------|-------------|-----| +| GraphQL client library | Custom HTTP client with schema parsing, error handling, type validation | n8n HTTP Request node with POST method | GraphQL-over-HTTP is standard, no client library needed | +| API key rotation system | Automated key lifecycle management, expiry tracking | Manual rotation via `unraid-api apikey --delete` + recreate | Keys don't expire, rotation is infrequent | +| Network discovery | Auto-detect Unraid host IP, scan network for GraphQL endpoints | User-configured `UNRAID_HOST` variable | Single-host environment, user knows Unraid IP | +| Credential encryption at rest | Custom encryption wrapper for `.env.unraid-api` | n8n's built-in credential encryption (via `N8N_ENCRYPTION_KEY`) | n8n already handles credential security, file is for CLI/testing only | + +**Key insight:** Unraid GraphQL API is designed as a simple HTTP interface. Over-engineering the client side (schema validation, code generation, connection pooling) adds complexity without benefit for this use case. + +--- + +## Common Pitfalls + +### Pitfall 1: host.docker.internal Not Working on Linux Docker + +**What goes wrong:** `host.docker.internal` is a Docker Desktop feature. On native Linux Docker, it may not resolve, causing "connection refused" or "no such host" errors. + +**Why it happens:** Docker Engine on Linux doesn't automatically create the `host.docker.internal` DNS entry like Docker Desktop does on macOS/Windows. + +**How to avoid:** Add `--add-host=host.docker.internal:host-gateway` to container extra parameters. The `host-gateway` special value resolves to the host's bridge IP (typically `172.17.0.1`). + +**Warning signs:** +- n8n HTTP Request node returns `getaddrinfo ENOTFOUND host.docker.internal` +- `docker exec -it n8n curl http://host.docker.internal` fails with DNS error + +**Verification:** +```bash +# From inside n8n container: +docker exec -it n8n curl -I http://host.docker.internal/graphql +# Should return HTTP 400 (GraphQL needs POST) or 200, NOT connection refused +``` + +**Source:** [Docker Bridge Network Guide](https://docs.docker.com/engine/network/drivers/bridge/), [Connecting to Host from Container](https://dev.to/iamrj846/connecting-to-the-host-machines-localhost-from-a-docker-container-a-practical-guide-nc4) + +### Pitfall 2: HTTP vs HTTPS Confusion with Self-Signed Certs + +**What goes wrong:** User runs Unraid WebGUI on HTTPS with self-signed cert. HTTP Request node either fails with SSL verification error or connects to HTTP (port 80) when Unraid only listens on HTTPS (port 443). + +**Why it happens:** Unraid defaults to HTTP but many users enable HTTPS via Settings → Management Access → Use SSL/TLS. Self-signed certs fail Node.js default SSL validation. + +**How to avoid:** +1. Check Unraid WebGUI URL — if `https://tower.local`, use `https://` in `UNRAID_HOST` +2. In n8n HTTP Request node, set "Ignore SSL Issues" to `true` for self-signed certs +3. Document both HTTP and HTTPS configs in setup instructions + +**Warning signs:** +- `UNABLE_TO_VERIFY_LEAF_SIGNATURE` error +- `CERT_HAS_EXPIRED` error +- Connection works on port 80 but not 443 (or vice versa) + +**Verification:** +```bash +# Test which port Unraid listens on: +curl -I http://tower.local/graphql # Port 80 +curl -I https://tower.local/graphql # Port 443 +``` + +**Recommendation:** Default to HTTP in examples (simpler), document HTTPS config as optional enhancement. + +**Source:** Observed behavior in Unraid community forums, standard Node.js HTTPS client behavior + +### Pitfall 3: Container ID Format Mismatch + +**What goes wrong:** Phase 15+ calls `updateContainer(id: "plex")` but Unraid expects `"docker:plex"` or numeric ID. Mutation returns "container not found" error despite container existing. + +**Why it happens:** GraphQL schema defines `PrefixedID` scalar but doesn't document exact format. Implementation may vary by Unraid version or container source (template vs. custom). + +**How to avoid:** +1. **Phase 14 MUST document actual ID format** observed in test query response +2. Store both `id` (GraphQL format) and `names` (Docker format) during testing +3. Phase 15 uses documented format from Phase 14, not assumptions + +**Warning signs:** +- Test query returns IDs like `"123:456"` or `"docker:containername"` +- Mutation fails with "invalid ID format" or "container not found" + +**Verification pattern:** +```graphql +# Phase 14 test query: +query { docker { containers { id names } } } + +# Response reveals format: +{ + "data": { + "docker": { + "containers": [ + { "id": "docker:plex", "names": ["plex"] } # Format discovered + ] + } + } +} +``` + +**Critical:** Do NOT assume format. Let test query reveal truth. + +**Source:** [Unraid API Schema](https://raw.githubusercontent.com/unraid/api/main/api/generated-schema.graphql) (defines PrefixedID as abstract), community client implementations show variation + +### Pitfall 4: API Key Permissions Too Broad or Too Narrow + +**What goes wrong:** +- **Too narrow:** API key created without `DOCKER:UPDATE_ANY`, Phase 15 mutations fail with "permission denied" +- **Too broad:** API key has `ADMIN` role, excessive permissions violate least privilege + +**Why it happens:** Unraid API key creation supports both role-based (`--roles ADMIN`) and permission-based (`--permissions DOCKER:UPDATE_ANY`) access. Docs show both examples, easy to pick wrong one. + +**How to avoid:** +1. Use **permission-based scoping:** `--permissions "DOCKER:UPDATE_ANY"` +2. **Do NOT use `--roles ADMIN`** (grants full system access) +3. Phase 14 tests read-only query (permissions validation happens in Phase 15) + +**Warning signs:** +- API key works for queries but fails for mutations +- Unraid logs show "insufficient permissions" for Docker operations + +**Correct command:** +```bash +unraid-api apikey --create \ + --name "Docker Manager Bot" \ + --permissions "DOCKER:UPDATE_ANY" \ + --description "Container update status sync" +``` + +**Wrong command (don't use):** +```bash +unraid-api apikey --create --roles ADMIN # Too broad! +``` + +**Source:** [Unraid API Key Management](https://docs.unraid.net/API/programmatic-api-key-management/), [Using Unraid API](https://docs.unraid.net/API/how-to-use-the-api/) + +### Pitfall 5: Rate Limiting Surprises + +**What goes wrong:** Phase 16 batch sync calls `updateContainers` for 20+ containers, API returns 429 Too Many Requests or rate limit error. + +**Why it happens:** Unraid API documentation states "The API implements rate limiting to prevent abuse" but doesn't specify thresholds. Actual limits are unknown. + +**How to avoid:** +1. Phase 14/15 use single-container queries/mutations (well within any reasonable limit) +2. Phase 16 batch operations should use `updateContainers` (plural) mutation for efficiency, not N individual calls +3. If rate limiting occurs, implement exponential backoff (standard HTTP pattern) + +**Warning signs:** +- HTTP 429 response +- GraphQL error: `"message": "rate limit exceeded"` + +**Impact assessment:** LOW for this project (bot updates are infrequent, <10/min even in aggressive batch mode). Rate limiting unlikely to be hit in normal usage. + +**Mitigation:** Document in ARCHITECTURE.md, handle 429 gracefully (retry with backoff), consider it edge case not primary concern. + +**Source:** [Using Unraid API](https://docs.unraid.net/API/how-to-use-the-api/) (confirms rate limiting exists), specific thresholds not documented + +### Pitfall 6: Unraid Version Compatibility (Connect Plugin Missing) + +**What goes wrong:** User runs Unraid 6.11 (pre-7.2), assumes GraphQL API is built-in, gets "404 Not Found" on `/graphql` endpoint. + +**Why it happens:** Native GraphQL API was added in Unraid 7.2. Earlier versions (6.9-7.1) require the Connect plugin to be installed. + +**How to avoid:** +1. Phase 14 setup documentation MUST include version check +2. If Unraid <7.2, document Connect plugin installation steps +3. Test query naturally fails if API unavailable, clear error message guides user to install plugin + +**Warning signs:** +- HTTP 404 on `/graphql` endpoint +- `curl http://tower.local/graphql` returns "Not Found" + +**Setup instructions pattern:** +```bash +# Check Unraid version: +cat /etc/unraid-version # SSH to Unraid + +# If <7.2: Install Connect plugin +# Apps → Search "Unraid Connect" → Install +# Settings → Management Access → API → Enable +``` + +**Verification:** +```bash +# After setup, this should return HTTP 400 (GraphQL requires POST body): +curl -I http://tower.local/graphql +``` + +**Source:** [Unraid API Documentation](https://docs.unraid.net/API/) (version availability), community forum discussions about Connect plugin + +--- + +## Code Examples + +Verified patterns from official sources: + +### Test Connectivity Query (Phase 14) + +```javascript +// n8n HTTP Request node configuration +// Node name: "Test Unraid API" +// Method: POST +// URL: http://host.docker.internal/graphql +// Authentication: Header Auth (credential: "Unraid API Key") +// Body Content Type: JSON + +{ + "query": "query TestConnectivity { docker { containers { id names state isUpdateAvailable } } }" +} + +// Expected response structure: +{ + "data": { + "docker": { + "containers": [ + { + "id": "docker:plex", // Format may vary — document actual format + "names": ["plex"], + "state": "running", + "isUpdateAvailable": false + } + // ... more containers + ] + } + } +} + +// Error handling pattern (n8n Code node after HTTP Request): +const response = $input.item.json; + +if (response.errors) { + // GraphQL returned errors + const errorMsg = response.errors.map(e => e.message).join(', '); + throw new Error(`Unraid API error: ${errorMsg}`); +} + +if (!response.data || !response.data.docker) { + // Unexpected response structure + throw new Error('Invalid GraphQL response from Unraid API'); +} + +// Success — pass container data to next node +return { + json: { + success: true, + containers: response.data.docker.containers, + containerIdFormat: response.data.docker.containers[0]?.id // Document format + } +}; +``` + +**Source:** [n8n GraphQL Documentation](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.graphql/), Unraid API schema + +### CLI Testing Pattern (Outside n8n) + +```bash +# Source credentials +. .env.unraid-api + +# Test query via curl +curl -X POST "${UNRAID_HOST}/graphql" \ + -H "Content-Type: application/json" \ + -H "x-api-key: ${UNRAID_API_KEY}" \ + -d '{ + "query": "query { docker { containers { id names state isUpdateAvailable } } }" + }' \ + | python3 -c " +import sys, json +data = json.load(sys.stdin) +if 'errors' in data: + print('ERROR:', data['errors']) + sys.exit(1) +containers = data['data']['docker']['containers'] +print(f'Found {len(containers)} containers') +for c in containers[:3]: # Show first 3 + print(f\" {c['id']} - {c['names'][0]} ({c['state']})\") +" +``` + +**Why CLI testing:** Validates API access outside n8n environment, useful for debugging network issues. + +### Credential Storage Pattern + +```bash +# .env.unraid-api (gitignored) +UNRAID_HOST=http://host.docker.internal +UNRAID_API_KEY=1234567890abcdef + +# Load in bash scripts: +. .env.unraid-api +curl -H "x-api-key: ${UNRAID_API_KEY}" "${UNRAID_HOST}/graphql" ... + +# Reference in n8n: +# Option 1: n8n credential system (recommended for workflows) +# Option 2: Environment variables if n8n container has env file mounted +``` + +**Security note:** Never commit `.env.unraid-api` to git. Already in `.gitignore` (mirrors `.env.n8n-api` pattern). + +**Source:** [n8n Credentials Environment Variables](https://docs.n8n.io/hosting/configuration/environment-variables/credentials/), existing project `.env.n8n-api` pattern + +--- + +## State of the Art + +| Old Approach | Current Approach | When Changed | Impact | +|--------------|------------------|--------------|--------| +| Direct file manipulation (`/var/lib/docker/unraid-update-status.json`) | GraphQL API `updateContainer` mutation | Unraid 6.9 (2020, Connect plugin) | Official interface, version-safe, handles internal state sync | +| Session cookie auth | API key with x-api-key header | Unraid 6.9 API introduction | Stateless, no expiry handling, programmatic access | +| Unraid CLI scripts (`/usr/local/emhttp/plugins/dynamix.docker.manager/`) | GraphQL API exposure of DockerService | Unraid 7.2 (2023, native API) | No PHP runtime needed, standard HTTP interface | + +**Deprecated/outdated:** +- **Direct `/var/lib/docker/unraid-update-status.json` writes:** File format undocumented, no UI refresh trigger, brittle +- **Unraid API-RE (community plugin):** Replaced by official Unraid API/Connect plugin, no longer maintained +- **WebGUI session scraping:** Fragile, breaks on Unraid updates, security risk + +**Current best practice (2026):** Use official GraphQL API via HTTP Request with API key authentication. Mirrors how Unraid's own WebGUI communicates with backend. + +--- + +## Open Questions + +1. **Exact container ID format in GraphQL responses** + - What we know: Schema defines `PrefixedID` scalar, format is `:` + - What's unclear: Whether it's `"docker:containername"`, numeric like `"123:456"`, or varies by source + - Recommendation: Phase 14 test query MUST document actual format observed, used by Phase 15+ + +2. **HTTP vs HTTPS default on user's Unraid** + - What we know: Unraid defaults to HTTP but many users enable HTTPS + - What's unclear: How many users have self-signed certs vs. valid certs vs. HTTP-only + - Recommendation: Default to HTTP in examples, document HTTPS + "Ignore SSL" as configuration option + +3. **Rate limiting thresholds** + - What we know: API implements rate limiting (confirmed in docs) + - What's unclear: Actual request/minute limits, burst allowances + - Recommendation: Assume reasonable limits (100+/min), handle 429 gracefully, unlikely to hit in practice + +4. **Unraid version distribution (6.x vs 7.x)** + - What we know: 7.2+ has native API, 6.9-7.1 needs Connect plugin, <6.9 unsupported + - What's unclear: User's actual Unraid version + - Recommendation: Phase 14 setup instructions check version, guide plugin install if needed + +--- + +## Sources + +### Primary (HIGH confidence) +- [Unraid GraphQL Schema](https://raw.githubusercontent.com/unraid/api/main/api/generated-schema.graphql) — Container queries, mutation signatures, PrefixedID definition +- [Using the Unraid API](https://docs.unraid.net/API/how-to-use-the-api/) — Endpoint URL, authentication header format, rate limiting acknowledgment +- [Unraid API Key Management](https://docs.unraid.net/API/programmatic-api-key-management/) — API key creation, permission scoping +- [n8n GraphQL Node Documentation](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.graphql/) — HTTP Request node GraphQL patterns +- [Docker Bridge Network](https://docs.docker.com/engine/network/drivers/bridge/) — host.docker.internal behavior, bridge IP access + +### Secondary (MEDIUM confidence) +- [n8n Security Best Practices](https://docs.n8n.io/hosting/configuration/environment-variables/credentials/) — Credential storage, encryption +- [Connecting to Host from Docker Container](https://dev.to/iamrj846/connecting-to-the-host-machines-localhost-from-a-docker-container-a-practical-guide-nc4) — host.docker.internal Linux workarounds +- Project `.planning/research/STACK.md` — Prior v1.3 research on Unraid API (same domain, validates findings) +- Project `.planning/research/SUMMARY.md` — Architecture patterns for this project + +### Tertiary (LOW confidence) +- Community forum posts on Unraid API authentication — Anecdotal troubleshooting examples +- GitHub client implementations ([unraid-mcp](https://github.com/jmagar/unraid-mcp), [ha-unraid](https://github.com/domalab/unraid-api-client)) — Reference patterns, not official docs + +--- + +## Metadata + +**Confidence breakdown:** +- Standard stack: HIGH — GraphQL API is official, HTTP Request node is n8n built-in, well-documented +- Architecture: HIGH — Network patterns are standard Docker, credential storage mirrors existing project pattern +- Pitfalls: MEDIUM-HIGH — Most are standard HTTP/Docker issues, container ID format needs empirical validation + +**Research date:** 2026-02-08 +**Valid until:** 60 days (Unraid API is stable, GraphQL schema changes infrequent) + +**Critical dependencies for planning:** +- Phase 14 MUST validate container ID format via test query (open question #1) +- Phase 14 MUST document HTTP vs HTTPS configuration for user's environment (open question #2) +- Setup instructions MUST include Unraid version check and Connect plugin guidance (open question #4) + +**Ready for planning:** YES — Sufficient information to create tasks for API key creation, network configuration, test query implementation, and container ID format documentation.