feat(docker-watcher): phase 2 - crypto & config seed loader
AES-256-GCM encryption for credential storage, YAML seed config parser with validation, and transactional import into SQLite. Credentials (registry tokens, NPM password) encrypted before storage.
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
A self-hosted tool that automates Docker container deployment with Nginx Proxy Manager integration. Detects new images from Gitea/GitHub registries, deploys containers, and configures reverse proxy routing — all from a web dashboard. Supports multiple simultaneous versions of the same project.
|
||||
|
||||
## Build & Test Commands
|
||||
|
||||
- **Build (Go):** `go build ./cmd/server/`
|
||||
- **Test (Go):** `go test ./...`
|
||||
- **Lint (Go):** `golangci-lint run`
|
||||
@@ -34,16 +35,18 @@ A self-hosted tool that automates Docker container deployment with Nginx Proxy M
|
||||
- [ ] Phase 10: Quick Deploy & Settings Pages [domain: frontend] → [subplan](./phase-10-settings-deploy.md)
|
||||
- [ ] Phase 11: Frontend Embed & Real-Time Updates [domain: fullstack] → [subplan](./phase-11-embed-sse.md)
|
||||
- [ ] Phase 12: Hardening [domain: backend] → [subplan](./phase-12-hardening.md)
|
||||
- [ ] Phase 13: Frontend Polish & Modern UI [domain: frontend] → [subplan](./phase-13-ui-polish.md)
|
||||
|
||||
### Parallel Execution Notes
|
||||
|
||||
- Phases 3 and 4 are independent (Docker client vs NPM client) — can run in parallel
|
||||
- Phases 9 and 10 are independent (dashboard vs settings pages) — can run in parallel
|
||||
|
||||
## Phase Progress Log
|
||||
|
||||
| Phase | Domain | Status | Review | Build | Committed |
|
||||
|-------|--------|--------|--------|-------|-----------|
|
||||
| Phase 1: Scaffold & Store | backend | ✅ Complete | ⬜ | ⏭️ Skip (Big Bang) | ⬜ |
|
||||
| ----- | ------ | ------ | ------ | ----- | --------- |
|
||||
| Phase 1: Scaffold & Store | backend | ✅ Complete | ✅ Pass w/ fixes | ⏭️ Skip (Big Bang) | ✅ |
|
||||
| Phase 2: Crypto & Config | backend | ⬜ Not Started | ⬜ | ⏭️ Skip (Big Bang) | ⬜ |
|
||||
| Phase 3: Docker Client | backend | ⬜ Not Started | ⬜ | ⏭️ Skip (Big Bang) | ⬜ |
|
||||
| Phase 4: NPM Client | backend | ⬜ Not Started | ⬜ | ⏭️ Skip (Big Bang) | ⬜ |
|
||||
@@ -54,9 +57,27 @@ A self-hosted tool that automates Docker container deployment with Nginx Proxy M
|
||||
| Phase 9: Dashboard | frontend | ⬜ Not Started | ⬜ | ⏭️ Skip (Big Bang) | ⬜ |
|
||||
| Phase 10: Settings & Deploy | frontend | ⬜ Not Started | ⬜ | ⏭️ Skip (Big Bang) | ⬜ |
|
||||
| Phase 11: Embed & SSE | fullstack | ⬜ Not Started | ⬜ | ⏭️ Skip (Big Bang) | ⬜ |
|
||||
| Phase 12: Hardening | backend | ⬜ Not Started | ⬜ | ✅ Required (Final) | ⬜ |
|
||||
| Phase 12: Hardening | backend | ⬜ Not Started | ⬜ | ⏭️ Skip (Big Bang) | ⬜ |
|
||||
| Phase 13: UI Polish | frontend | ⬜ Not Started | ⬜ | ✅ Required (Final) | ⬜ |
|
||||
|
||||
## Amendment Log
|
||||
|
||||
### Amendment 1 — 2026-03-27
|
||||
|
||||
**Type:** Added phase
|
||||
**What changed:** Added Phase 13: Frontend Polish & Modern UI after Phase 12
|
||||
**Why:** User wants modern look & feel with SVG icons and polished frontend
|
||||
**Impact on existing phases:** None — Phase 13 runs after all functionality is complete. Build/tests now required on Phase 13 (final) instead of Phase 12.
|
||||
|
||||
### Amendment 2 — 2026-03-27
|
||||
|
||||
**Type:** Modified phase
|
||||
**What changed:** Added Task 13 (EN/RU localization) to Phase 13: Frontend Polish & Modern UI
|
||||
**Why:** User wants bilingual support (English and Russian) in the dashboard
|
||||
**Impact on existing phases:** None — contained within Phase 13
|
||||
|
||||
## Final Review
|
||||
|
||||
- [ ] Comprehensive code review
|
||||
- [ ] Full build passes
|
||||
- [ ] Full test suite passes
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
# Phase 13: Frontend Polish & Modern UI
|
||||
|
||||
**Status:** ⬜ Not Started
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** frontend
|
||||
|
||||
## Objective
|
||||
Enhance the web UI with a modern, polished look and feel — custom SVG icons, refined typography, consistent color palette, smooth transitions, and overall professional frontend quality.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Task 1: Design system foundations — define color palette (dark/light), spacing scale, typography scale, border radius tokens as CSS custom properties
|
||||
- [ ] Task 2: SVG icon set — create or integrate a consistent icon library (Lucide, Heroicons, or custom SVGs) for all UI actions (deploy, stop, start, restart, remove, settings, registry, etc.)
|
||||
- [ ] Task 3: Refine layout — polished sidebar/topnav with active state indicators, smooth transitions, responsive breakpoints
|
||||
- [ ] Task 4: Dashboard cards — redesign project cards with status indicators, instance count badges, sparkline activity, hover effects
|
||||
- [ ] Task 5: Project detail view — clean table/card layout for instances, inline status badges with pulse animation for "running", deploy history timeline
|
||||
- [ ] Task 6: Form styling — consistent input fields, select dropdowns, toggle switches (replace checkboxes), button hierarchy (primary/secondary/danger)
|
||||
- [ ] Task 7: Toast/notification system — slide-in toasts with icons, auto-dismiss, stacking
|
||||
- [ ] Task 8: Loading states — skeleton loaders for data fetching, spinner for actions, progress indicator for deploys
|
||||
- [ ] Task 9: Empty states — illustrated empty states with call-to-action for "no projects", "no instances", "no deploys"
|
||||
- [ ] Task 10: Responsive design — mobile-friendly layout, collapsible sidebar, touch-friendly controls
|
||||
- [ ] Task 11: Micro-interactions — button press feedback, status transition animations, deploy progress animation
|
||||
- [ ] Task 12: Dark mode support (optional) — toggle in settings, respect system preference
|
||||
- [ ] Task 13: Localization (EN/RU) — i18n setup with locale switcher, translate all UI strings to English and Russian, persist language preference
|
||||
|
||||
## Files to Modify/Create
|
||||
- `web/src/lib/styles/` — design tokens, global styles
|
||||
- `web/src/lib/components/icons/` — SVG icon components
|
||||
- `web/src/lib/components/` — enhanced existing components
|
||||
- `web/src/lib/i18n/` — locale files (en.json, ru.json), i18n helper, locale switcher component
|
||||
- All route files — refined layouts and styling, replace hardcoded strings with i18n keys
|
||||
|
||||
## Acceptance Criteria
|
||||
- UI looks modern and professional — not "default framework" appearance
|
||||
- Consistent icon language throughout the app
|
||||
- Smooth transitions and meaningful animations (not gratuitous)
|
||||
- Responsive down to mobile viewport
|
||||
- Loading and empty states provide good UX
|
||||
- Color palette works well in both light and dark contexts
|
||||
- All UI strings available in English and Russian, switchable via locale picker
|
||||
|
||||
## Notes
|
||||
- This phase runs AFTER all functionality is complete — pure visual/UX enhancement
|
||||
- Do not change any functionality or API contracts
|
||||
- Prefer CSS custom properties for theming over hardcoded values
|
||||
- Keep bundle size reasonable — inline SVGs preferred over icon font libraries
|
||||
- Animations should be tasteful and serve UX, not decoration
|
||||
- For i18n, use a lightweight approach (JSON locale files + Svelte store) — no heavy i18n framework needed
|
||||
- Default language: English. Russian as secondary. Locale persisted to localStorage
|
||||
|
||||
## Review Checklist
|
||||
- [ ] All tasks completed
|
||||
- [ ] Visual consistency across all pages
|
||||
- [ ] No functionality regressions
|
||||
- [ ] Responsive on mobile/tablet/desktop
|
||||
- [ ] Accessible (proper contrast ratios, focus states, aria labels on icons)
|
||||
|
||||
## Handoff to Next Phase
|
||||
<!-- This is the final UI phase — no handoff needed. -->
|
||||
@@ -1,6 +1,6 @@
|
||||
# Phase 2: Crypto & Config Seed Loader
|
||||
|
||||
**Status:** ⬜ Not Started
|
||||
**Status:** ✅ Complete
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** backend
|
||||
|
||||
@@ -9,14 +9,14 @@ Implement AES-256 encryption for credential storage and the YAML seed config par
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Task 1: Implement AES-256-GCM encrypt/decrypt functions using Go stdlib `crypto/aes` + `crypto/cipher`
|
||||
- [ ] Task 2: Key derivation from ENCRYPTION_KEY env var (SHA-256 hash to get 32 bytes)
|
||||
- [ ] Task 3: Define YAML config structs matching the seed format from PLAN.md
|
||||
- [ ] Task 4: Implement YAML parser — read and validate seed file
|
||||
- [ ] Task 5: Implement seed importer — checks if DB is empty, if so imports YAML into SQLite via store CRUD
|
||||
- [ ] Task 6: Encrypt credential fields (registry tokens, NPM password) during import
|
||||
- [ ] Task 7: Create `docker-watcher.example.yaml` with documented example config
|
||||
- [ ] Task 8: Wire seed import into `cmd/server/main.go` startup sequence
|
||||
- [x] Task 1: Implement AES-256-GCM encrypt/decrypt functions using Go stdlib `crypto/aes` + `crypto/cipher`
|
||||
- [x] Task 2: Key derivation from ENCRYPTION_KEY env var (SHA-256 hash to get 32 bytes)
|
||||
- [x] Task 3: Define YAML config structs matching the seed format from PLAN.md
|
||||
- [x] Task 4: Implement YAML parser — read and validate seed file
|
||||
- [x] Task 5: Implement seed importer — checks if DB is empty, if so imports YAML into SQLite via store CRUD
|
||||
- [x] Task 6: Encrypt credential fields (registry tokens, NPM password) during import
|
||||
- [x] Task 7: Create `docker-watcher.example.yaml` with documented example config
|
||||
- [x] Task 8: Wire seed import into `cmd/server/main.go` startup sequence
|
||||
|
||||
## Files to Modify/Create
|
||||
- `internal/crypto/crypto.go` — AES-256-GCM encrypt/decrypt
|
||||
@@ -40,11 +40,22 @@ Implement AES-256 encryption for credential storage and the YAML seed config par
|
||||
- The example YAML should have placeholder values, not real credentials
|
||||
|
||||
## Review Checklist
|
||||
- [ ] All tasks completed
|
||||
- [ ] Crypto uses secure practices (random nonce, GCM, no ECB)
|
||||
- [ ] No hardcoded keys or secrets
|
||||
- [ ] YAML parsing validates required fields
|
||||
- [ ] Import is transactional
|
||||
- [x] All tasks completed
|
||||
- [x] Crypto uses secure practices (random nonce, GCM, no ECB)
|
||||
- [x] No hardcoded keys or secrets
|
||||
- [x] YAML parsing validates required fields
|
||||
- [x] Import is transactional
|
||||
|
||||
## Handoff to Next Phase
|
||||
<!-- Filled in by the implementation agent after completing this phase. -->
|
||||
|
||||
- `crypto.Encrypt(key, plaintext)` and `crypto.Decrypt(key, ciphertextHex)` handle AES-256-GCM encryption; ciphertext is hex-encoded with prepended nonce
|
||||
- `crypto.KeyFromEnv()` derives a `[32]byte` key from the `ENCRYPTION_KEY` env var via SHA-256
|
||||
- `crypto.EncryptIfNotEmpty(key, value)` is a convenience wrapper that passes through empty strings unchanged
|
||||
- `config.ImportSeed(db, seedPath)` is the single entry point for seed import — called from `main.go` at startup
|
||||
- Import is idempotent: skipped if the DB already has projects or registries
|
||||
- Import is transactional: all inserts happen within a single SQLite transaction (rollback on any failure)
|
||||
- Registry `token` and settings `npm_password` are now stored encrypted in SQLite — later phases that read these fields must decrypt with `crypto.Decrypt(key, value)`
|
||||
- `store.DB()` method was added to expose the underlying `*sql.DB` for transaction use
|
||||
- Seed file path is configurable via `SEED_FILE` env var (default: `./docker-watcher.yaml`)
|
||||
- YAML validation ensures: `global.domain` is required, every project needs `image`, project registry references must exist, stages need `tag_pattern`
|
||||
- `go.sum` still does not exist — run `go mod tidy` when Go toolchain is available
|
||||
|
||||
Reference in New Issue
Block a user