# Coba 後端 — 階段 1(基礎建設)

> Coba(庫柏)是 5-15 人微型團隊的 AI 原生協作系統。本資料夾是後端 API。

## 這個版本能做什麼

階段 1 是**地基**,只提供帳號相關功能,讓後面的任務、對話、會議等模組有東西可以掛:

- 註冊帳號(第一個註冊的人自動成為 owner)
- 登入(取得 access + refresh token)
- refresh token 換新 token
- 取得 / 更新自己的個人資料
- 五個服務都跑起來:PostgreSQL、Redis、Qdrant、FastAPI、Adminer

---

## 第一次啟動(三步驟)

### 1. 確認你裝了 Docker Desktop

Windows 版 Docker Desktop 啟動後,確認小鯨魚圖示是綠色。

### 2. 複製環境變數檔

打開 PowerShell 或 Git Bash,進到本資料夾後:

```bash
cp .env.example .env
```

(Windows PowerShell 用 `Copy-Item .env.example .env`)

`.env` 裡面預設值已經能跑起本機開發環境,**你不用改任何東西**。
唯一一個跟你有關的是:第一個 owner 帳號會用 `.env` 裡面的:

- email:`ssbb30529@gmail.com`
- 密碼:`a183b729`

啟動後可以直接用這組登入。

### 3. 啟動全部服務

```bash
docker compose up -d --build
```

第一次會花 3-5 分鐘下載 image + build。之後啟動只要 10 秒。

---

## 確認啟動成功

打開瀏覽器,以下三個 URL 都要能開:

| URL | 應該看到 |
|---|---|
| <http://localhost:8000/docs> | Swagger API 文件,有 `auth` 和 `users` 兩組 endpoint |
| <http://localhost:8000/health> | `{"status":"ok",...}` JSON |
| <http://localhost:8080> | Adminer 登入頁(資料庫管理介面) |

### Adminer 登入資訊

- 系統:`PostgreSQL`
- 伺服器:`postgres`
- 使用者:`coba`
- 密碼:`.env` 裡的 `POSTGRES_PASSWORD`(預設 `coba_dev_password_change_me`)
- 資料庫:`coba`

---

## 階段 1 驗收清單

請依序在瀏覽器操作驗證:

### A. 第一個 owner 已自動建立

1. 開 <http://localhost:8080> 登入 Adminer
2. 點左側 `users` 表 → 應該已經有一筆 `ssbb30529@gmail.com`,`role=owner`

### B. 用 Swagger 驗證 API

1. 開 <http://localhost:8000/docs>
2. 找 `POST /api/auth/login` → 點 "Try it out" → 輸入:
   ```json
   {"email": "ssbb30529@gmail.com", "password": "a183b729"}
   ```
3. 點 "Execute" → 應該收到 200 + 一組 `access_token`、`refresh_token`
4. 複製 `access_token` 的值
5. 點頁面右上角 "Authorize" 按鈕 → 貼上 token → "Authorize"
6. 找 `GET /api/users/me` → "Try it out" → "Execute"
7. 應該回傳你的帳號資料,`role` 是 `"owner"`

### C. 註冊一個 member 帳號

1. 同樣在 Swagger
2. `POST /api/auth/register` → 輸入:
   ```json
   {"email": "test@x.com", "password": "test12345", "display_name": "測試員"}
   ```
3. 應該收到 201 + 回傳 `role: "member"`(因為已經有 owner 了)
4. 回 Adminer 重新整理 `users` 表 → 多了一筆

### D. 跑單元測試

```bash
docker compose exec api pytest -v
```

應該全綠(15+ 個測試 PASS)。

---

## 常用指令

```bash
# 看 API 服務的 log
docker compose logs -f api

# 看資料庫 log
docker compose logs -f postgres

# 進入 API 容器(debug 用)
docker compose exec api bash

# 跑測試
docker compose exec api pytest -v

# 完全重來(刪除所有資料,重新 seed owner)
docker compose down -v
docker compose up -d --build

# 停掉所有服務(資料保留)
docker compose down

# 改了 Model 之後產生新的 migration
docker compose exec api alembic revision --autogenerate -m "描述變更"

# 把 migration 套用到資料庫
docker compose exec api alembic upgrade head
```

---

## 專案結構

```
coba-backend/
├── docker-compose.yml      ← 五個服務的編排
├── Dockerfile              ← API 服務的 image 定義
├── .env.example            ← 環境變數範本
├── requirements.txt        ← Python 依賴
├── pytest.ini              ← 測試設定
├── alembic.ini             ← Migration 工具設定
├── alembic/                ← 資料庫 schema 變更歷史
│   ├── env.py
│   └── versions/
│       └── 0001_initial_users.py
├── app/
│   ├── main.py             ← FastAPI 入口
│   ├── config.py           ← 環境變數讀取
│   ├── database.py         ← PostgreSQL 連線管理
│   ├── models/             ← 資料表定義
│   │   └── user.py
│   ├── schemas/            ← API 請求/回應格式
│   │   ├── auth.py
│   │   └── user.py
│   ├── api/                ← 路由
│   │   ├── auth.py
│   │   └── users.py
│   └── core/               ← 共用工具
│       ├── security.py     ← JWT + 密碼雜湊
│       ├── deps.py         ← FastAPI 依賴注入
│       └── seed.py         ← 第一個 owner 自動建立
└── tests/
    ├── conftest.py
    └── test_auth.py
```

---

## 下一階段預告

**階段 2(任務中心)** 會新增:

- `projects`、`tasks`、`subtasks`、`task_assignments`、`task_comments`、`task_activities`、`task_attachments` 七張表
- 任務 CRUD API
- Web 前端登入頁 + AppShell + 看板/列表視圖

詳細設計見 `../docs/db-schema.md`(完整 24 張表的階段規劃)。

---

## 常見問題排查

**Q. `docker compose up` 卡在 postgres 健康檢查不過**
A. 通常是 5432 port 被本機原本的 PostgreSQL 占用。
改 `docker-compose.yml` 把 `"5432:5432"` 改成 `"15432:5432"`,再重來。

**Q. 改了 code 但 API 沒更新**
A. `docker-compose.yml` 已經把 `./app` 掛進容器,uvicorn `--reload` 應該會自動偵測。
如果沒有,執行 `docker compose restart api`。

**Q. 想完全重來,把資料庫清空**
A. `docker compose down -v`(注意 `-v` 會刪除 volume = 所有資料)
