add PDD workflow: CLAUDE.md, PDD.md, active.md symlink
This commit is contained in:
@@ -1,68 +1,64 @@
|
|||||||
# NAS Tools Project
|
# NAS Tools Project
|
||||||
|
|
||||||
## Architecture
|
## PDD Workflow
|
||||||
- Synology DS224+ (x86_64, 18GB RAM), Tailscale IP: `100.78.131.124`, LAN: `192.168.31.221`
|
|
||||||
- Docker: `/volume1/@appstore/ContainerManager/usr/bin/docker`, compose dirs: `/volume1/docker/*`
|
|
||||||
- VPS Caddy (`161.33.182.109`, Tailscale: `100.109.198.126`): reverse proxy for `*.jimmygan.com`
|
|
||||||
- Build VPS (server2, `158.101.140.85`, Tailscale: `100.70.115.1`): podman, fast network
|
|
||||||
- NAS Caddy: port 8443 fallback only (SNI broken)
|
|
||||||
|
|
||||||
## Dashboard
|
This project follows **PDD (Product Definition Document)** development.
|
||||||
|
|
||||||
|
**Always read these files before writing code:**
|
||||||
|
- `docs/PDD.md` — product vision, goals, targets (the north star)
|
||||||
|
- `docs/specs/active.md` — current sprint spec (what we're building now)
|
||||||
|
|
||||||
|
**Workflow:**
|
||||||
|
1. PDD → Sprint Spec → Implementation → Validate ACs
|
||||||
|
2. Scope changes update the sprint spec first, code second
|
||||||
|
3. Never ship without ACs passing
|
||||||
|
|
||||||
|
## Dev Commands
|
||||||
|
|
||||||
|
- **Build dashboard:** `cd dashboard/frontend && npm run build`
|
||||||
|
- **Dev dashboard:** `cd dashboard/backend && uvicorn main:app --reload` + `cd dashboard/frontend && npm run dev`
|
||||||
|
- **Test:** `cd dashboard && python -m pytest backend/tests/`
|
||||||
|
- **Deploy:** Push to main → Gitea CI builds + deploys to NAS
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
- **Synology DS224+** (x86_64, 18GB RAM), Tailscale IP: `100.78.131.124`, LAN: `192.168.31.221`
|
||||||
|
- **Docker:** `/volume1/@appstore/ContainerManager/usr/bin/docker`, compose dirs: `/volume1/docker/*`
|
||||||
|
- **VPS Caddy** (`161.33.182.109`, Tailscale: `100.109.198.126`): reverse proxy for `*.jimmygan.com`
|
||||||
|
- **Build VPS** (server2, `158.101.140.85`, Tailscale: `100.70.115.1`): podman builds
|
||||||
|
- **NAS Caddy:** port 8443 fallback only (SNI broken)
|
||||||
|
|
||||||
|
### Dashboard
|
||||||
- Backend: Python FastAPI (`dashboard/backend/`)
|
- Backend: Python FastAPI (`dashboard/backend/`)
|
||||||
- Frontend: Svelte 5 + Tailwind CSS (`dashboard/frontend/`)
|
- Frontend: Svelte 5 + Tailwind CSS (`dashboard/frontend/`)
|
||||||
- Svelte 5 runes: use `$state`, `$props`, `$bindable` (not legacy `export let`)
|
- Svelte 5 runes: `$state`, `$props`, `$bindable` (not `export let`)
|
||||||
- Sidebar categories: Main, Media, Tools (see `docs/architecture.md` for full layout)
|
|
||||||
- New pages: create route in `src/routes/`, import in `App.svelte`, update `Sidebar.svelte`
|
- New pages: create route in `src/routes/`, import in `App.svelte`, update `Sidebar.svelte`
|
||||||
|
|
||||||
## CI/CD
|
### CI/CD
|
||||||
Two workflows in `.gitea/workflows/`:
|
Two Gitea workflows in `.gitea/workflows/`:
|
||||||
- **deploy.yml** — main branch: tests → build → deploy to production
|
- **deploy.yml** — main branch: tests → build → deploy to production
|
||||||
- **deploy-dev.yml** — dev branch: tests → build → deploy to dev
|
- **deploy-dev.yml** — dev branch: tests → build → deploy to dev
|
||||||
|
|
||||||
Two runners:
|
Build flow: VPS builds → pushes to local registry (`100.78.131.124:5501/`) → streams to NAS → `docker compose up -d`
|
||||||
- **VPS runner** (`vps` label on server2) — build + test jobs (podman)
|
|
||||||
- **NAS runner** (`nas` label on DS224+) — deploy jobs (docker, host networking)
|
|
||||||
|
|
||||||
### Build flow
|
## Key Files
|
||||||
1. VPS builds Docker image + pushes to local registry `100.78.131.124:5501/`
|
|
||||||
2. Streams image to NAS: `podman save | gzip | ssh nasts "gunzip | docker load"`
|
|
||||||
3. NAS deploys: `docker compose up -d`
|
|
||||||
|
|
||||||
## Local Registry
|
- `docs/architecture.md` — full architecture reference
|
||||||
- Container: `registry-mirror` on NAS, port 5501
|
- `docs/TESTING.md` — test patterns and conventions
|
||||||
- Standalone mode (NOT Docker Hub proxy — blocked from China)
|
- `specs/` — sprint history
|
||||||
- VPS pushes with `podman push --tls-verify=false`
|
- `.gitea/workflows/deploy.yml` — main CI
|
||||||
|
- `.gitea/workflows/deploy-dev.yml` — dev CI
|
||||||
## Authentication
|
- `dashboard/backend/main.py` — FastAPI entry point
|
||||||
- **Gitea API Access:** Token stored in `~/.config/tea/config.yml` (user: `jimmy`)
|
- `dashboard/frontend/src/App.svelte` — Svelte entry point
|
||||||
- **Gitea Token:** `aa8c20329040c56c079d2676318c6e33f14b221d`
|
|
||||||
- **Project Secrets:** Gitea repo secrets: CI_TOKEN, CI_DB_PASSWORD, SECRET_KEY, ADMIN_PASSWORD_HASH, TRANSMISSION_USER, TRANSMISSION_PASS
|
|
||||||
|
|
||||||
## claude-dev CI Contract
|
|
||||||
- Source in `claude-dev/` (Dockerfile, required-tools.txt, scripts/)
|
|
||||||
- CI-first: update `claude-dev/*` in git, then push
|
|
||||||
- Workflow: `.gitea/workflows/deploy-claude-dev-dev.yml`
|
|
||||||
- Uses NAS runner with `DOCKER_BUILDKIT=0`
|
|
||||||
- Immutable tag format: `claude-dev:dev-<timestamp>-<sha>`
|
|
||||||
- Runtime compose: `claude-dev/docker-compose.yml`
|
|
||||||
- Rollback: run workflow with `rollback_image` using value from `/volume1/docker/claude-dev/previous-image.txt`
|
|
||||||
|
|
||||||
## Synology Quirks
|
## Synology Quirks
|
||||||
|
|
||||||
- No `crontab` — edit `/etc/crontab` with `sudo` + `printf`, restart crond
|
- No `crontab` — edit `/etc/crontab` with `sudo` + `printf`, restart crond
|
||||||
- No `scp` subsystem — use `cat file | ssh ... 'cat > dest'`
|
- No `scp` subsystem — use `cat file | ssh ... 'cat > dest'`
|
||||||
- ACLs override Unix perms — use `sudo chmod 777` + `synoacltool -enforce-inherit`
|
- ACLs override Unix perms — use `sudo chmod 777` + `synoacltool -enforce-inherit`
|
||||||
- Tailscale userspace mode — cannot bind Docker ports to Tailscale IPs
|
- Tailscale userspace mode — cannot bind Docker ports to Tailscale IPs
|
||||||
|
|
||||||
## DNS
|
## DNS
|
||||||
|
|
||||||
- dnsmasq on NAS resolves `*.jimmygan.com` → `161.33.182.109` (Caddy VPS)
|
- dnsmasq on NAS resolves `*.jimmygan.com` → `161.33.182.109` (Caddy VPS)
|
||||||
- Tailscale split DNS: `jimmygan.com` → NAS (queries hit dnsmasq)
|
- Tailscale split DNS: `jimmygan.com` → NAS (queries hit dnsmasq)
|
||||||
|
|
||||||
## Proxy API
|
|
||||||
- URL: `https://www.bytecatcode.org`
|
|
||||||
- Models: `claude-opus-4-6`, `claude-sonnet-4-6`, `claude-haiku-4-5-20251001`
|
|
||||||
|
|
||||||
## Key Files
|
|
||||||
- `docs/architecture.md` — full architecture reference
|
|
||||||
- `docs/TESTING.md` — test patterns and conventions
|
|
||||||
- `.gitea/workflows/deploy.yml` — main CI
|
|
||||||
- `.gitea/workflows/deploy-dev.yml` — dev CI
|
|
||||||
|
|||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
# Product Definition Document — NAS Tools
|
||||||
|
|
||||||
|
## Vision
|
||||||
|
|
||||||
|
A single dashboard to manage all self-hosted services on the NAS — Docker containers, media, tools, system health — accessible from anywhere via a clean web UI.
|
||||||
|
|
||||||
|
## Goals
|
||||||
|
|
||||||
|
1. **Unified management** — one dashboard for all NAS services (containers, media, tools, auth)
|
||||||
|
2. **GFW-proof deployment** — all traffic routes through VPS + Tailscale, works from China
|
||||||
|
3. **Self-healing** — auto-detect down containers, email alerts, health checks
|
||||||
|
4. **CI/CD from Gitea** — push to deploy with zero manual SSH
|
||||||
|
|
||||||
|
## Target Users
|
||||||
|
|
||||||
|
Self (Jimmy Gan). Secondary: family members who access media services on the NAS.
|
||||||
|
|
||||||
|
## Success Metrics
|
||||||
|
|
||||||
|
- Dashboard loads in < 3s from anywhere
|
||||||
|
- All CI workflows green
|
||||||
|
- Zero manual SSH deploys
|
||||||
|
- < 5min recovery from container crash
|
||||||
Symlink
+1
@@ -0,0 +1 @@
|
|||||||
|
../../specs/sprint-06-code-quality.md
|
||||||
Reference in New Issue
Block a user