0bb52f9ec6
Create structured plan files with 12 phases covering the full implementation: scaffold, store, crypto, Docker/NPM clients, registry poller, webhook, deployer, API layer, SvelteKit frontend, embedding, and hardening.
2.2 KiB
2.2 KiB
Phase 4: NPM Client
Status: ⬜ Not Started Parent plan: PLAN.md Domain: backend
Objective
Implement the Nginx Proxy Manager API client — JWT authentication, CRUD for proxy hosts, and host lookup.
Tasks
- Task 1: Create NPM client struct with base URL, cached JWT token, and auto-refresh
- Task 2: Implement
Authenticate(ctx, email, password)— POST /api/tokens, store JWT - Task 3: Implement
CreateProxyHost(ctx, config)— POST /api/nginx/proxy-hosts - Task 4: Implement
UpdateProxyHost(ctx, id, config)— PUT /api/nginx/proxy-hosts/{id} - Task 5: Implement
DeleteProxyHost(ctx, id)— DELETE /api/nginx/proxy-hosts/{id} - Task 6: Implement
ListProxyHosts(ctx)— GET /api/nginx/proxy-hosts - Task 7: Implement
FindProxyHostByDomain(ctx, domain)— search existing hosts by domain name - Task 8: Define proxy host config struct (domain, forward host/port, SSL settings, etc.)
- Task 9: Handle JWT token expiry — re-authenticate automatically on 401
Files to Modify/Create
internal/npm/client.go— NPM API client, auth, HTTP helpersinternal/npm/types.go— request/response types for proxy hosts
Acceptance Criteria
- Client authenticates and caches JWT
- CRUD operations work for proxy hosts
- Token refresh happens transparently on expiry
- Proxy host config supports: domain, forward host, forward port, SSL (Let's Encrypt optional)
- FindByDomain enables checking if a proxy already exists before creating
Notes
- NPM API base: typically
http://npm:81/api - Forward host for containers: use container name on the shared Docker network
- Forward port: the container's internal port (from EXPOSE)
- SSL: for staging, can be disabled; production may want Let's Encrypt
- NPM credentials come from settings (encrypted in SQLite, decrypted at runtime)
Review Checklist
- All tasks completed
- JWT caching and refresh work correctly
- HTTP errors are properly handled (not just status code, but response body)
- No credentials logged or leaked in errors
- Struct types match NPM API contract