memory.md 5.8 KB

Construction Timelapse — Session Memory

Tổng quan dự án

Hệ thống timelapse construction monitoring.

  • Repo Gogs: https://git.k9tech.space/kingkong/timelapse-2
  • Token: a6224640fb6f576f6cba46f0e1646500c87226b6 (Personal Access Token)
  • Stack: Next.js 14 + NestJS + PostgreSQL (Drizzle) + Redis + Python (device-agent)
  • Package manager: Bun (KHÔNG dùng npm vì workspace protocol không hoạt động với nexus registry)
  • Registry: Luôn thêm --registry https://registry.npmjs.org/ khi cài package

Kiến trúc hiện tại

MacOS (code) → Gogs push → webhook → Pi 4 (deploy)
                                           ↓
                              ┌─ postgres (docker)
                              ├─ redis (docker)
                              ├─ api-server (NestJS)
                              ├─ web-dashboard (Next.js)
                              └─ worker (Node)

Workspace config

  • KHÔNG dùng apps/* trong workspacesdevice-agent là Python
  • Workspace config đúng:

    "workspaces": ["apps/api-server", "apps/web-dashboard", "apps/worker", "packages/*"]
    
  • @shared-types KHÔNG hợp lệ — dùng @shared/types

  • Luôn cd vào workspace trước khi bun add


Gogs API

# List repos
curl -H "Authorization: token <TOKEN>" https://git.k9tech.space/api/v1/user/repos

# Create repo
curl -X POST -H "Authorization: token <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"name":"repo-name","private":false}' \
  https://git.k9tech.space/api/v1/user/repos

# Create webhook
curl -X POST -H "Authorization: token <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"type":"gogs","active":true,"config":{"url":"http://<pi>:9000/webhook","content_type":"json"},"events":["push"]}' \
  https://git.k9tech.space/api/v1/repos/<user>/<repo>/hooks

# Push với token
git remote set-url origin "https://<TOKEN>@git.k9tech.space/kingkong/timelapse-2.git"
git push -u origin main

Pi 4 Deploy Setup (TODO)

Trên Pi 4 cần:

  1. Clone repo: git clone https://git.k9tech.space/kingkong/timelapse-2.git /opt/timelapse
  2. Tạo /opt/timelapse/.env với:

    GOGS_TOKEN=<deploy_token>
    GOGS_REPO_URL=https://git.k9tech.space/kingkong/timelapse-2.git
    DATABASE_URL=postgres://user:pass@postgres:5432/timelapse
    REDIS_URL=redis://redis:6379
    JWT_SECRET=...
    
  3. Chạy webhook server: node scripts/webhook-server.js

  4. Update Gogs webhook URL với IP thật của Pi 4

  5. Deploy script: bash scripts/deploy.sh


Docker Compose (in repo)

docker compose up -d postgres redis
docker compose up -d --build api-server web-dashboard worker

Phase 1 — Trạng thái: ✅ HOÀN THÀNH

Backend (apps/api-server)

  • src/modules/auth/ — AuthController/Service/Strategies stubs
  • src/modules/devices/ — heartbeat endpoint + API key guard + repo/service/controller
  • src/common/ — guards, decorators
  • src/modules/orgs|projects|captures|videos|alerts/ — stubs
  • src/realtime/ — stub

Dashboard (apps/web-dashboard)

  • Dashboard home, device list, device detail pages
  • Tailwind CSS v3 + React Query

Database (Drizzle Schema)

  • File: apps/api-server/src/db/schema.ts
  • Enum: org_status, project_status, device_status, capture_status, video_status, alert_severity, alert_type, user_role, command_result_status
  • Tables: organizations, projects, users, memberships, sessions, magic_links, devices, device_heartbeats, captures, videos, video_jobs, commands, alert_rules, alerts, audit_logs, activity_logs

Các lỗi đã gặp và cách fix

  1. @shared-types@shared/types
  2. device-agent (Python) trong npm workspaces → loại khỏi workspaces
  3. npm install không hoạt động → bun install --registry https://registry.npmjs.org/
  4. bun add với nexus registry → luôn --registry https://registry.npmjs.org/
  5. db không export được → import từ database.module.ts riêng
  6. experimentalDecorators thiếu → thêm vào packages/config/tsconfig.node.json
  7. TSC output vào src/ → cleanup .js/.d.ts/*.js.map + fix outDir

TODO — Phase tiếp theo

  1. DB migration: drizzle-kit push + seed data (trên Pi)
  2. Role-based access control nâng cao (org_admin/project_manager/viewer)
  3. Device-agent (Python) heartbeat sender
  4. Realtime WebSocket cho status update
  5. Google OAuth thật (redirect + callback)
  6. Worker thực tế (hiện vẫn restart vì stub)

Đã hoàn thành gần đây

  • Auth thực sự: register/login/refresh/logout + JWT guard + /auth/me
  • Dashboard auth flow: /login, ProtectedRoute, logout, auto attach Bearer token
  • Orgs CRUD API (/v1/orgs) có JWT guard
  • RBAC theo role:
    • org_admin: full org/project/member management
    • project_manager: create/update project
    • viewer: read-only
  • Membership management endpoints:
    • GET /v1/orgs/:id/members
    • POST /v1/orgs/:id/members (org_admin)
    • PATCH /v1/orgs/:id/members/:userId (org_admin)
    • DELETE /v1/orgs/:id/members/:userId (org_admin)
  • Projects CRUD API:
    • POST /v1/projects
    • GET /v1/projects?orgId=
    • GET /v1/projects/:id
    • PATCH /v1/projects/:id
    • DELETE /v1/projects/:id (đều có JwtAuthGuard)

Lệnh nhanh (MacOS dev)

# Cài deps
bun install --registry https://registry.npmjs.org/

# Dev
cd apps/api-server && bun run dev
cd apps/web-dashboard && bun run dev

# Build (verify)
cd apps/api-server && bun run build
cd apps/web-dashboard && bun run build

# Test heartbeat
curl -X POST http://localhost:3001/v1/devices/test-device/heartbeat \
  -H "Content-Type: application/json" \
  -H "X-API-Key: dev-key-123" \
  -d '{"deviceId":"test-device","apiKey":"dev-key-123","status":"online","storageFreeGb":50,"capturesToday":12,"firmwareVersion":"1.0.0"}'