# 安裝流程（Installer + 管理者帳號）

此文件定義「首次安裝」與「既有環境管理」兩種情境，並以 EF Core Code First 為主。

## 目標
- 透過 EF Core migrations 建立/更新 DB schema
- 建立或更新 superuser 帳號
- 已設定 DB 連線時，可重複執行（不重建 schema）

## 安裝模式

### A. 首次安裝（Init）
1) 輸入 DB 連線資訊
2) 連線檢查與版本檢查
3) 建立/更新 schema（EF Core migrations）
4) 建立 superuser（預設帳號 admin，可自訂）
5) 建立必要 seed（roles 等）

### B. 既有環境（管理）
- 建立額外 superuser
- 強制重設 superuser 密碼
- 只執行 migration（差異安裝），不重建 schema

## CLI 指令規格（實作）

### 通用參數
- `--connection-string <string>`: DB 連線字串
- `--appsettings <path>`: 設定檔路徑（讀/寫 `ConnectionStrings:Default`）
- `--no-prompt`: 不使用互動輸入（CI/CD）
- `--verbose`: 詳細輸出

### 環境變數（建議用於部署）
- `ConnectionStrings__Default`: 主要連線字串（優先）
- `MEMBERCENTER_CONNECTION`: 備用連線字串

若在開發環境（`ASPNETCORE_ENVIRONMENT=Development` 或 `DOTNET_ENVIRONMENT=Development`），
可以建立 `.env` 檔案，installer 與 API 會在啟動時讀取（僅限開發環境）。
建議在 `.env` 內加入：

```
ASPNETCORE_ENVIRONMENT=Development
ConnectionStrings__Default=Host=localhost;Database=member_center;Username=postgres;Password=postgres
Auth__Issuer=http://localhost:7850/
Auth__Resources__MemberCenter__Audience=member_center_api
Auth__Resources__SendEngine__Audience=send_engine_api
Auth__Resources__FileAccess__Audience=file_access_api
SendEngine__BaseUrl=http://localhost:6060
SendEngine__WebhookSecret=change-me
```

相容性說明：
- 現行程式已優先使用 resource registry 與目標型態：
  - `Auth__Resources__MemberCenter__Audience`
  - `Auth__Resources__SendEngine__Audience`
  - `Auth__Resources__FileAccess__Audience`
- 舊 key 仍保留相容讀取：
  - `Auth__MemberCenterAudience`
  - `Auth__SendEngineAudience`
- 規劃上將收斂為 DB resource registry；`.env` 僅作為初始 seed / 部署覆寫來源，不應再為每個新服務新增平行 hardcoded key。
- `File Access` 已直接採用 resource registry 形式，不新增第三組硬編碼 audience 判斷。

`SendEngine` 設定說明：
- `SendEngine__BaseUrl`: Send Engine API base URL
- `SendEngine__WebhookSecret`: 與 Send Engine `Webhook:Secrets:member_center` 一致
- tenant 對應 `X-Client-Id` 改由 DB 管理（Tenant 設定）
- 可透過管理 UI 設定，或由 Send Engine 呼叫 `POST /integrations/send-engine/webhook-clients/upsert` 自動回填

測試旗標（TEST-ONLY）：
- `Testing__DisableSubscriptionDryRunNoDb=true`
  - 作用：`POST /subscriptions/disable` 完全不做 DB read/write，只寫 log（含預計執行的 DB 動作）
  - 用途：SES/Send Engine 串接初次測試，避免測試資料污染
  - 測試結束請改回 `false`

### 1) `installer init`
用途：首次安裝（含 migrations + seed + superuser）

參數：
- `--admin-email <email>`: 預設 `admin@example.com`
- `--admin-password <string>`: 預設需互動輸入
- `--admin-display-name <string>`: 可選
- `--force`: 若偵測已初始化，仍強制執行

流程：
1) 解析連線字串（參數或 appsettings）
   - 若提供 `--connection-string`，會寫入 appsettings
   - 若 appsettings 中缺少連線字串，會互動式詢問並寫入
   - 若設定環境變數，會優先使用環境變數（不寫入 appsettings）
2) 執行 migrations（不 Drop）
3) 建立 roles（superuser, admin, support）
4) 建立使用者（不存在才建立）並加入 `superuser` 角色
5) 寫入安裝鎖定（DB flag: `system_flags` / `installed=true`）

### 2) `installer add-superuser`
用途：新增或提升 superuser

參數：
- `--admin-email <email>`
- `--admin-password <string>`
- `--admin-display-name <string>`

流程：
1) 解析連線字串
2) 建立使用者並指派 `superuser` 角色

相容性：
- 舊指令 `installer add-admin` 仍保留為 alias，目前語意等同 `installer add-superuser`

### 3) `installer reset-superuser-password`
用途：重設指定 superuser 密碼

參數：
- `--admin-email <email>`
- `--admin-password <string>`

流程：
1) 解析連線字串
2) 更新密碼（強制）

相容性：
- 舊指令 `installer reset-admin-password` 仍保留為 alias，目前語意等同 `installer reset-superuser-password`

### 4) `installer migrate`
用途：只執行 migrations

參數：
- `--target <migration>`: 指定遷移（可選）

流程：
1) 解析連線字串
2) 執行 migrations（可指定 target）

## 安全注意
- 密碼必須符合強度規則
- 初次安裝完成後，禁用安裝入口或限內網
- 安裝過程需紀錄 audit log

## Docker / 部署建議
- 建議用環境變數提供連線字串（避免重建 container 後設定遺失）
- 範例：

```yaml
environment:
  ConnectionStrings__Default: "Host=postgres;Database=member_center;Username=postgres;Password=postgres"
```

- 若仍要用 `appsettings.json`，請用 volume 維持設定檔
