# ZITADEL（dev / k6）

本機跑 k6 測試用的 ZITADEL stack（docker-compose `profile: k6`）。

## 啟動

```bash
make k6-up
```

會啟動 mongo / redis / mailhog / postgres / **openldap** / zitadel。

ZITADEL 首次啟動會 init Postgres schema 並執行 [steps.yaml](steps.yaml) 預載：
- Instance 名稱：`ZITADEL`
- Org：`GatewayDev`
- Admin 使用者：`zitadel-admin@zitadel.localhost` / `Password1!`
- Service Account：`zitadel-admin-sa`（產生 PAT 寫到 `machinekey/zitadel-admin-sa.token`）

完成需 30~90 秒，可用 `make k6-wait` 等到 `/debug/healthz` 200。

## PAT 取用

```bash
cat deploy/zitadel/machinekey/zitadel-admin-sa.token
```

把這個值塞進 `etc/gateway.k6.yaml` 的 `Zitadel.ServiceUserToken`，或用環境變數：

```bash
export ZITADEL_SERVICE_TOKEN=$(cat deploy/zitadel/machinekey/zitadel-admin-sa.token)
```

`make k6-gateway` 會自動做這件事。

## 密碼登入（`/auth/login`）

ZITADEL v2 **預設停用** OAuth Resource Owner Password Grant（`unsupported_grant_type`）。
本 repo 的 Gateway 在**未設定** `OAuthClientID` / `OAuthClientSecret` 時，會改用 **v2 Sessions API**（PAT）驗證密碼，無需額外建立 OIDC App。

若要在正式環境使用 ROPG，請自行建立 OIDC Application 並設定：

```bash
export ZITADEL_OAUTH_CLIENT_ID=...
export ZITADEL_OAUTH_CLIENT_SECRET=...
```

## 重設

```bash
make k6-down                                    # 停容器（保留 volume）
docker volume rm template-monorepo_postgres_data   # 清 ZITADEL 資料
rm deploy/zitadel/machinekey/zitadel-admin-sa.*    # 清 PAT
```

## Google / LDAP 聯邦登入（Social + LDAP IdP）

Gateway **不直接** bind LDAP；登入／註冊走 ZITADEL OIDC，並以 `idp_id` 指定外部 IdP。

### 1. 建立 OIDC Application（User Agent）

在 ZITADEL Console → Project → Applications → **User Agent**：

- Redirect URIs（本機前端，經 Vite proxy 打 API）：
  - `http://localhost:5173/auth/callback/login`
  - `http://localhost:5173/auth/callback/register`
- Grant types：`Authorization Code`
- Response type：`code`
- Scopes：`openid` `profile` `email`

記下 **Client ID** / **Client Secret**，寫入 Gateway：

```bash
export ZITADEL_OAUTH_CLIENT_ID=...
export ZITADEL_OAUTH_CLIENT_SECRET=...
```

或 `etc/gateway.k6.yaml` 的 `Zitadel.OAuthClientID` / `OAuthClientSecret`。

### 2. 設定 Google IdP

Console → Settings → Identity Providers → **Google** → 建立後複製 **IdP ID**：

```yaml
Zitadel:
  GoogleIdPID: "<zitadel-google-idp-id>"
  # Google OAuth client 也可放在 Zitadel IdP 設定內
```

### 3. 設定 LDAP IdP（本機 OpenLDAP）

`make k6-wait` 會**自動**建立 LDAP IdP 與 OIDC App（[`bootstrap_dev.py`](bootstrap_dev.py)），並把 IdP ID 寫入 `machinekey/k6.env` 的 `ZITADEL_LDAP_IDP_ID`。

手動設定（選用）見 **[deploy/openldap/README.md](../openldap/README.md)**。

驗證目錄：`make ldap-test`

### 4. 行為摘要

| 流程 | Google | LDAP |
|------|--------|------|
| 登入 | 需已有會員；否則 404「請先註冊」 | 首登可 `EnsureFromLDAP` 自動建立會員 |
| 註冊 | `EnsureFromOIDC` + 邀請碼 | 支援但通常改走 LDAP 登入 |
| TOTP 已啟用 | callback 回 `mfa_required`，前端導回登入頁輸入 TOTP | 同左 |

重啟 Gateway：`make dev-restart-gateway`（或 `make k6-gateway`）。

## 端點

- Console UI：http://localhost:8080/ui/console
- OIDC issuer：http://localhost:8080
- Management API：http://localhost:8080/management/v1
- Health：http://localhost:8080/debug/healthz

## 不可帶上 prod

`MasterkeyNeedsToHave32Characters` 與 [steps.yaml](steps.yaml) 內的密碼都是固定 dev 值，**只能**本機用。
