feat: implement user authentication module
- Backend (FastAPI): - External API authentication (pj-auth-api.vercel.app) - JWT token validation with Redis session storage - RBAC with department isolation - User, Role, Department models with pjctrl_ prefix - Alembic migrations with project-specific version table - Complete test coverage (13 tests) - Frontend (React + Vite): - AuthContext for state management - Login page with error handling - Protected route component - Dashboard with user info display - OpenSpec: - 7 capability specs defined - add-user-auth change archived 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
159
openspec/specs/audit-trail/spec.md
Normal file
159
openspec/specs/audit-trail/spec.md
Normal file
@@ -0,0 +1,159 @@
|
||||
# Audit Trail
|
||||
|
||||
系統級稽核追蹤,記錄所有關鍵變更操作供合規與追溯需求。
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Change Logging
|
||||
系統 SHALL 記錄所有關鍵變更操作,包含誰在何時改了什麼。
|
||||
|
||||
#### Scenario: 任務欄位變更記錄
|
||||
- **GIVEN** 使用者修改任務的任何欄位(如截止日期、狀態、指派者)
|
||||
- **WHEN** 變更儲存成功
|
||||
- **THEN** 系統記錄變更前後的值
|
||||
- **AND** 記錄操作者、時間、IP 位址
|
||||
|
||||
#### Scenario: 專案設定變更記錄
|
||||
- **GIVEN** 管理者修改專案設定
|
||||
- **WHEN** 設定變更儲存
|
||||
- **THEN** 系統記錄所有變更的設定項目
|
||||
- **AND** 記錄操作者與時間
|
||||
|
||||
#### Scenario: 權限變更記錄
|
||||
- **GIVEN** 管理者修改使用者權限或角色
|
||||
- **WHEN** 權限變更生效
|
||||
- **THEN** 系統記錄權限變更詳情
|
||||
- **AND** 標記為高敏感度操作
|
||||
|
||||
### Requirement: Delete Operations Tracking
|
||||
系統 SHALL 追蹤所有刪除操作,支援軟刪除與追溯。
|
||||
|
||||
#### Scenario: 任務刪除記錄
|
||||
- **GIVEN** 使用者刪除任務
|
||||
- **WHEN** 刪除操作執行
|
||||
- **THEN** 系統執行軟刪除(標記 is_deleted = true)
|
||||
- **AND** 記錄刪除操作與原因
|
||||
|
||||
#### Scenario: 附件刪除記錄
|
||||
- **GIVEN** 使用者刪除附件
|
||||
- **WHEN** 刪除操作執行
|
||||
- **THEN** 系統保留檔案於存檔區
|
||||
- **AND** 記錄刪除操作詳情
|
||||
|
||||
### Requirement: Audit Log Immutability
|
||||
系統 SHALL 確保稽核日誌不可竄改。
|
||||
|
||||
#### Scenario: 日誌寫入
|
||||
- **GIVEN** 需要記錄稽核事件
|
||||
- **WHEN** 日誌寫入
|
||||
- **THEN** 日誌記錄不可被修改或刪除
|
||||
- **AND** 包含校驗碼確保完整性
|
||||
|
||||
#### Scenario: 日誌完整性驗證
|
||||
- **GIVEN** 稽核人員需要驗證日誌完整性
|
||||
- **WHEN** 執行完整性檢查
|
||||
- **THEN** 系統驗證所有日誌記錄的校驗碼
|
||||
- **AND** 報告任何異常
|
||||
|
||||
### Requirement: Audit Query Interface
|
||||
系統 SHALL 提供稽核查詢介面供授權人員使用。
|
||||
|
||||
#### Scenario: 依時間範圍查詢
|
||||
- **GIVEN** 稽核人員需要查詢特定時間範圍的操作
|
||||
- **WHEN** 設定時間範圍並執行查詢
|
||||
- **THEN** 顯示該時間範圍內的所有稽核記錄
|
||||
|
||||
#### Scenario: 依操作者查詢
|
||||
- **GIVEN** 稽核人員需要查詢特定使用者的操作歷史
|
||||
- **WHEN** 選擇使用者並執行查詢
|
||||
- **THEN** 顯示該使用者的所有操作記錄
|
||||
|
||||
#### Scenario: 依資源查詢
|
||||
- **GIVEN** 稽核人員需要查詢特定任務或專案的變更歷史
|
||||
- **WHEN** 選擇資源並執行查詢
|
||||
- **THEN** 顯示該資源的完整變更歷程
|
||||
|
||||
#### Scenario: 稽核報告匯出
|
||||
- **GIVEN** 稽核人員需要匯出稽核報告
|
||||
- **WHEN** 選擇匯出格式(CSV/PDF)
|
||||
- **THEN** 系統生成報告檔案供下載
|
||||
|
||||
### Requirement: Sensitive Operation Alerts
|
||||
系統 SHALL 對高敏感度操作發送即時警示。
|
||||
|
||||
#### Scenario: 權限提升警示
|
||||
- **GIVEN** 使用者被授予管理員權限
|
||||
- **WHEN** 權限變更生效
|
||||
- **THEN** 系統發送警示給安全管理員
|
||||
|
||||
#### Scenario: 大量刪除警示
|
||||
- **GIVEN** 使用者在短時間內刪除大量資料
|
||||
- **WHEN** 偵測到異常刪除模式
|
||||
- **THEN** 系統發送警示並暫停操作
|
||||
|
||||
#### Scenario: 異常登入警示
|
||||
- **GIVEN** 偵測到異常登入行為(如異地登入、非工作時間登入)
|
||||
- **WHEN** 異常行為發生
|
||||
- **THEN** 系統記錄並發送警示
|
||||
|
||||
## Data Model
|
||||
|
||||
```
|
||||
pjctrl_audit_logs
|
||||
├── id: UUID (PK)
|
||||
├── event_type: VARCHAR(50)
|
||||
│ └── 'task.update', 'task.delete', 'project.update', 'user.permission_change', etc.
|
||||
├── resource_type: VARCHAR(50)
|
||||
│ └── 'task', 'project', 'user', 'attachment', 'trigger', etc.
|
||||
├── resource_id: UUID
|
||||
├── user_id: UUID (FK -> users)
|
||||
├── action: ENUM('create', 'update', 'delete', 'restore', 'login', 'logout')
|
||||
├── changes: JSON
|
||||
│ └── { "field": "due_date", "old_value": "2024-01-15", "new_value": "2024-01-20" }
|
||||
├── metadata: JSON
|
||||
│ └── { "ip_address": "192.168.1.100", "user_agent": "...", "session_id": "..." }
|
||||
├── sensitivity_level: ENUM('low', 'medium', 'high', 'critical')
|
||||
├── checksum: VARCHAR(64) (SHA-256 of record content)
|
||||
├── created_at: TIMESTAMP (immutable)
|
||||
└── INDEX idx_audit_user (user_id, created_at)
|
||||
└── INDEX idx_audit_resource (resource_type, resource_id, created_at)
|
||||
└── INDEX idx_audit_time (created_at)
|
||||
|
||||
pjctrl_audit_alerts
|
||||
├── id: UUID (PK)
|
||||
├── audit_log_id: UUID (FK -> audit_logs)
|
||||
├── alert_type: VARCHAR(50)
|
||||
├── recipients: JSON (array of user IDs)
|
||||
├── message: TEXT
|
||||
├── is_acknowledged: BOOLEAN DEFAULT false
|
||||
├── acknowledged_by: UUID (FK -> users)
|
||||
├── acknowledged_at: TIMESTAMP
|
||||
└── created_at: TIMESTAMP
|
||||
```
|
||||
|
||||
## Event Types Reference
|
||||
|
||||
| 事件類型 | 說明 | 敏感度 |
|
||||
|---------|------|--------|
|
||||
| task.create | 建立任務 | low |
|
||||
| task.update | 更新任務 | low |
|
||||
| task.delete | 刪除任務 | medium |
|
||||
| task.assign | 指派任務 | low |
|
||||
| task.blocker | 標記阻礙 | medium |
|
||||
| project.create | 建立專案 | medium |
|
||||
| project.update | 更新專案 | medium |
|
||||
| project.delete | 刪除專案 | high |
|
||||
| user.login | 使用者登入 | low |
|
||||
| user.logout | 使用者登出 | low |
|
||||
| user.permission_change | 權限變更 | critical |
|
||||
| attachment.upload | 上傳附件 | low |
|
||||
| attachment.download | 下載附件 | low |
|
||||
| attachment.delete | 刪除附件 | medium |
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- 稽核日誌表設計為 append-only,不允許 UPDATE 或 DELETE
|
||||
- 使用資料庫觸發器或應用層中間件自動記錄變更
|
||||
- 日誌保留期限依法規要求設定(建議至少 7 年)
|
||||
- 考慮使用時間序列資料庫(如 TimescaleDB)處理大量日誌
|
||||
- Checksum 計算包含:event_type + resource_id + user_id + changes + created_at
|
||||
152
openspec/specs/automation/spec.md
Normal file
152
openspec/specs/automation/spec.md
Normal file
@@ -0,0 +1,152 @@
|
||||
# Automation
|
||||
|
||||
自動化系統,提供觸發器與自動報告生成功能。
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Trigger-Based Automation
|
||||
系統 SHALL 支援觸發器 (Triggers),當特定條件滿足時自動執行動作。
|
||||
|
||||
#### Scenario: 狀態變更觸發通知
|
||||
- **GIVEN** 專案設定了「當任務狀態變更為待測試時,通知設備工程師」的觸發器
|
||||
- **WHEN** 任務狀態變更為「待測試」
|
||||
- **THEN** 系統自動發送通知給指定的設備工程師群組
|
||||
|
||||
#### Scenario: 截止日期觸發提醒
|
||||
- **GIVEN** 專案設定了「截止日前 3 天自動提醒」的觸發器
|
||||
- **WHEN** 任務距離截止日還有 3 天
|
||||
- **THEN** 系統自動發送提醒給任務指派者
|
||||
|
||||
#### Scenario: 建立觸發器
|
||||
- **GIVEN** 專案管理者需要建立自動化規則
|
||||
- **WHEN** 管理者設定觸發條件與動作
|
||||
- **THEN** 系統儲存觸發器規則
|
||||
- **AND** 規則立即生效
|
||||
|
||||
### Requirement: Trigger Conditions
|
||||
系統 SHALL 支援多種觸發條件類型。
|
||||
|
||||
#### Scenario: 欄位變更條件
|
||||
- **GIVEN** 觸發器設定為「當 Status 欄位變更為特定值」
|
||||
- **WHEN** 任務的 Status 欄位變更為該值
|
||||
- **THEN** 觸發器被觸發
|
||||
|
||||
#### Scenario: 時間條件
|
||||
- **GIVEN** 觸發器設定為「每週五下午 4:00」
|
||||
- **WHEN** 系統時間達到設定時間
|
||||
- **THEN** 觸發器被觸發
|
||||
|
||||
#### Scenario: 複合條件
|
||||
- **GIVEN** 觸發器設定為「當 Status = 完成 且 Priority = 高」
|
||||
- **WHEN** 任務同時滿足兩個條件
|
||||
- **THEN** 觸發器被觸發
|
||||
|
||||
### Requirement: Trigger Actions
|
||||
系統 SHALL 支援多種觸發動作類型。
|
||||
|
||||
#### Scenario: 發送通知動作
|
||||
- **GIVEN** 觸發器動作設定為發送通知
|
||||
- **WHEN** 觸發器被觸發
|
||||
- **THEN** 系統發送通知給指定對象
|
||||
- **AND** 通知內容可使用變數(如任務名稱、指派者)
|
||||
|
||||
#### Scenario: 更新欄位動作
|
||||
- **GIVEN** 觸發器動作設定為更新欄位
|
||||
- **WHEN** 觸發器被觸發
|
||||
- **THEN** 系統自動更新指定欄位的值
|
||||
|
||||
#### Scenario: 指派任務動作
|
||||
- **GIVEN** 觸發器動作設定為自動指派
|
||||
- **WHEN** 觸發器被觸發
|
||||
- **THEN** 系統自動將任務指派給指定人員
|
||||
|
||||
### Requirement: Automated Weekly Report
|
||||
系統 SHALL 每週五下午 4:00 自動彙整本週「已完成」與「進行中」的任務發送給主管。
|
||||
|
||||
#### Scenario: 週報自動生成
|
||||
- **GIVEN** 系統排程設定為每週五 16:00
|
||||
- **WHEN** 到達排程時間
|
||||
- **THEN** 系統彙整每位主管所屬專案的任務狀態
|
||||
- **AND** 生成週報並發送給該主管
|
||||
|
||||
#### Scenario: 週報內容
|
||||
- **GIVEN** 週報生成中
|
||||
- **WHEN** 系統彙整資料
|
||||
- **THEN** 週報包含:
|
||||
- 本週已完成任務清單
|
||||
- 進行中任務清單
|
||||
- 逾期任務警示
|
||||
- 阻礙中任務清單
|
||||
- 下週預計完成任務
|
||||
|
||||
#### Scenario: 週報發送方式
|
||||
- **GIVEN** 週報已生成
|
||||
- **WHEN** 系統發送週報
|
||||
- **THEN** 透過系統內通知發送給收件者
|
||||
- **AND** 週報可在系統內查閱歷史紀錄
|
||||
|
||||
#### Scenario: Email 發送(可選)
|
||||
- **GIVEN** 週報已生成且系統已啟用 Email 功能
|
||||
- **WHEN** 系統發送週報
|
||||
- **THEN** 同時透過 Email 發送給收件者
|
||||
- **AND** 記錄 Email 發送狀態
|
||||
|
||||
#### Scenario: Email 未啟用
|
||||
- **GIVEN** 週報已生成但系統未啟用 Email 功能
|
||||
- **WHEN** 系統發送週報
|
||||
- **THEN** 僅透過系統內通知發送
|
||||
- **AND** 記錄「Email 未啟用,僅發送系統通知」
|
||||
|
||||
## Data Model
|
||||
|
||||
```
|
||||
pjctrl_triggers
|
||||
├── id: UUID (PK)
|
||||
├── project_id: UUID (FK -> projects)
|
||||
├── name: VARCHAR(200)
|
||||
├── description: TEXT
|
||||
├── trigger_type: ENUM('field_change', 'schedule', 'creation')
|
||||
├── conditions: JSON
|
||||
│ └── { "field": "status", "operator": "equals", "value": "testing" }
|
||||
├── actions: JSON
|
||||
│ └── [{ "type": "notify", "target": "group:equipment_engineers" }]
|
||||
├── is_active: BOOLEAN DEFAULT true
|
||||
├── created_by: UUID (FK -> users)
|
||||
├── created_at: TIMESTAMP
|
||||
└── updated_at: TIMESTAMP
|
||||
|
||||
pjctrl_trigger_logs
|
||||
├── id: UUID (PK)
|
||||
├── trigger_id: UUID (FK -> triggers)
|
||||
├── task_id: UUID (FK -> tasks, nullable)
|
||||
├── executed_at: TIMESTAMP
|
||||
├── status: ENUM('success', 'failed')
|
||||
└── error_message: TEXT
|
||||
|
||||
pjctrl_scheduled_reports
|
||||
├── id: UUID (PK)
|
||||
├── report_type: ENUM('weekly', 'monthly', 'custom')
|
||||
├── recipient_id: UUID (FK -> users)
|
||||
├── schedule_cron: VARCHAR(50)
|
||||
├── last_sent_at: TIMESTAMP
|
||||
├── next_run_at: TIMESTAMP
|
||||
├── is_active: BOOLEAN DEFAULT true
|
||||
├── email_enabled: BOOLEAN DEFAULT false (Email 發送開關)
|
||||
└── created_at: TIMESTAMP
|
||||
|
||||
pjctrl_report_history
|
||||
├── id: UUID (PK)
|
||||
├── scheduled_report_id: UUID (FK -> scheduled_reports)
|
||||
├── generated_at: TIMESTAMP
|
||||
├── content: JSON
|
||||
├── sent_to: JSON (array of user IDs)
|
||||
├── channels_used: JSON (e.g., ["in_app"] or ["in_app", "email"])
|
||||
├── email_status: ENUM('sent', 'skipped', 'failed', null)
|
||||
└── status: ENUM('sent', 'failed')
|
||||
```
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- 使用 Celery + Redis 處理排程任務
|
||||
- 觸發器執行採用非同步處理,避免阻塞主流程
|
||||
- 所有觸發器執行都記錄日誌供追蹤
|
||||
126
openspec/specs/collaboration/spec.md
Normal file
126
openspec/specs/collaboration/spec.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# Collaboration
|
||||
|
||||
協作功能系統,提供任務內討論、@提及通知與阻礙處理機制。
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Task Comments
|
||||
系統 SHALL 支援任務內部的討論線索,減少 Email 往返。
|
||||
|
||||
#### Scenario: 新增留言
|
||||
- **GIVEN** 使用者擁有任務的存取權限
|
||||
- **WHEN** 使用者在任務中新增留言
|
||||
- **THEN** 系統儲存留言並顯示在討論區
|
||||
- **AND** 記錄留言者與時間戳記
|
||||
|
||||
#### Scenario: 回覆留言
|
||||
- **GIVEN** 任務已有留言
|
||||
- **WHEN** 使用者回覆特定留言
|
||||
- **THEN** 系統建立巢狀回覆結構
|
||||
- **AND** 通知原留言者
|
||||
|
||||
#### Scenario: 編輯留言
|
||||
- **GIVEN** 使用者是留言的作者
|
||||
- **WHEN** 使用者編輯自己的留言
|
||||
- **THEN** 系統更新留言內容
|
||||
- **AND** 標示「已編輯」及編輯時間
|
||||
|
||||
### Requirement: User Mentions
|
||||
系統 SHALL 支援 @相關人員 功能,提及時發送即時通知。
|
||||
|
||||
#### Scenario: @提及通知
|
||||
- **GIVEN** 使用者在留言中使用 @username 提及某人
|
||||
- **WHEN** 留言送出
|
||||
- **THEN** 被提及者收到即時通知
|
||||
- **AND** 通知包含任務連結與留言摘要
|
||||
|
||||
#### Scenario: @提及自動完成
|
||||
- **GIVEN** 使用者輸入 @ 符號
|
||||
- **WHEN** 使用者繼續輸入
|
||||
- **THEN** 系統顯示符合的使用者名單供選擇
|
||||
- **AND** 可用鍵盤或滑鼠選擇
|
||||
|
||||
### Requirement: Blocker Management
|
||||
系統 SHALL 提供阻礙 (Blocker) 機制,強制要求主管介入排解。
|
||||
|
||||
#### Scenario: 標記阻礙
|
||||
- **GIVEN** 工程師的任務遇到阻礙無法進行
|
||||
- **WHEN** 工程師將任務標記為 "Blocked"
|
||||
- **THEN** 系統設定 Blocker_Flag = true
|
||||
- **AND** 強制發送即時通知給該任務所屬專案的主管
|
||||
|
||||
#### Scenario: 阻礙原因說明
|
||||
- **GIVEN** 任務被標記為 Blocked
|
||||
- **WHEN** 使用者標記阻礙
|
||||
- **THEN** 系統要求填寫阻礙原因
|
||||
- **AND** 原因顯示在任務詳情與通知中
|
||||
|
||||
#### Scenario: 解除阻礙
|
||||
- **GIVEN** 主管或被指派者處理完阻礙
|
||||
- **WHEN** 使用者解除 Blocked 狀態
|
||||
- **THEN** 系統清除 Blocker_Flag
|
||||
- **AND** 記錄解除時間與處理說明
|
||||
|
||||
### Requirement: Real-time Notifications
|
||||
系統 SHALL 透過 Redis 推播即時通知。
|
||||
|
||||
#### Scenario: 即時通知推播
|
||||
- **GIVEN** 發生需要通知的事件(如:被指派任務、被 @提及、阻礙標記)
|
||||
- **WHEN** 事件發生
|
||||
- **THEN** 系統透過 WebSocket 即時推播通知給相關使用者
|
||||
- **AND** 未讀通知顯示數量標示
|
||||
|
||||
#### Scenario: 通知已讀標記
|
||||
- **GIVEN** 使用者有未讀通知
|
||||
- **WHEN** 使用者查看通知
|
||||
- **THEN** 系統標記為已讀
|
||||
- **AND** 更新未讀數量
|
||||
|
||||
## Data Model
|
||||
|
||||
```
|
||||
pjctrl_comments
|
||||
├── id: UUID (PK)
|
||||
├── task_id: UUID (FK -> tasks)
|
||||
├── parent_comment_id: UUID (FK -> comments, nullable)
|
||||
├── author_id: UUID (FK -> users)
|
||||
├── content: TEXT
|
||||
├── is_edited: BOOLEAN DEFAULT false
|
||||
├── created_at: TIMESTAMP
|
||||
└── updated_at: TIMESTAMP
|
||||
|
||||
pjctrl_mentions
|
||||
├── id: UUID (PK)
|
||||
├── comment_id: UUID (FK -> comments)
|
||||
├── mentioned_user_id: UUID (FK -> users)
|
||||
├── created_at: TIMESTAMP
|
||||
└── is_notified: BOOLEAN DEFAULT false
|
||||
|
||||
pjctrl_notifications
|
||||
├── id: UUID (PK)
|
||||
├── user_id: UUID (FK -> users)
|
||||
├── type: ENUM('mention', 'assignment', 'blocker', 'status_change', 'comment')
|
||||
├── reference_type: VARCHAR(50) (e.g., 'task', 'comment')
|
||||
├── reference_id: UUID
|
||||
├── title: VARCHAR(200)
|
||||
├── message: TEXT
|
||||
├── is_read: BOOLEAN DEFAULT false
|
||||
├── created_at: TIMESTAMP
|
||||
└── read_at: TIMESTAMP
|
||||
|
||||
pjctrl_blockers
|
||||
├── id: UUID (PK)
|
||||
├── task_id: UUID (FK -> tasks)
|
||||
├── reported_by: UUID (FK -> users)
|
||||
├── reason: TEXT
|
||||
├── resolved_by: UUID (FK -> users, nullable)
|
||||
├── resolution_note: TEXT
|
||||
├── created_at: TIMESTAMP
|
||||
└── resolved_at: TIMESTAMP
|
||||
```
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- 使用 Redis Pub/Sub 處理即時通知推播
|
||||
- WebSocket 連線管理確保訊息送達
|
||||
- 離線使用者登入後補送未讀通知
|
||||
164
openspec/specs/document-management/spec.md
Normal file
164
openspec/specs/document-management/spec.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# Document Management
|
||||
|
||||
文件管理系統,提供檔案附件、版本控制、加密存儲與浮水印功能。
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: File Attachments
|
||||
系統 SHALL 支援任務層級的檔案附件,儲存於地端 NAS。
|
||||
|
||||
#### Scenario: 上傳附件
|
||||
- **GIVEN** 使用者擁有任務的編輯權限
|
||||
- **WHEN** 使用者上傳檔案至任務
|
||||
- **THEN** 系統將檔案儲存至 NAS
|
||||
- **AND** 建立附件記錄關聯至該任務
|
||||
|
||||
#### Scenario: 下載附件
|
||||
- **GIVEN** 使用者擁有任務的存取權限
|
||||
- **WHEN** 使用者下載附件
|
||||
- **THEN** 系統驗證權限後提供檔案下載
|
||||
- **AND** 記錄下載操作日誌
|
||||
|
||||
#### Scenario: 刪除附件
|
||||
- **GIVEN** 使用者擁有任務的編輯權限
|
||||
- **WHEN** 使用者刪除附件
|
||||
- **THEN** 系統標記附件為已刪除(軟刪除)
|
||||
- **AND** 保留檔案供稽核追溯
|
||||
|
||||
### Requirement: Version Control
|
||||
系統 SHALL 支援檔案版本控制,追蹤所有版本變更。
|
||||
|
||||
#### Scenario: 上傳新版本
|
||||
- **GIVEN** 任務已有同名附件
|
||||
- **WHEN** 使用者上傳同名檔案
|
||||
- **THEN** 系統建立新版本而非覆蓋
|
||||
- **AND** 版本號自動遞增
|
||||
|
||||
#### Scenario: 查看版本歷史
|
||||
- **GIVEN** 附件有多個版本
|
||||
- **WHEN** 使用者查看版本歷史
|
||||
- **THEN** 顯示所有版本清單
|
||||
- **AND** 包含上傳者、上傳時間、檔案大小
|
||||
|
||||
#### Scenario: 回復舊版本
|
||||
- **GIVEN** 使用者需要使用舊版本
|
||||
- **WHEN** 使用者選擇回復特定版本
|
||||
- **THEN** 系統將該版本設為當前版本
|
||||
- **AND** 記錄回復操作
|
||||
|
||||
### Requirement: File Encryption
|
||||
系統 SHALL 對半導體敏感圖檔進行 AES-256 加密存儲。
|
||||
|
||||
#### Scenario: 加密存儲
|
||||
- **GIVEN** 專案設定為機密等級
|
||||
- **WHEN** 使用者上傳檔案
|
||||
- **THEN** 系統使用 AES-256 加密後存儲
|
||||
- **AND** 加密金鑰安全管理
|
||||
|
||||
#### Scenario: 解密讀取
|
||||
- **GIVEN** 使用者請求下載加密檔案
|
||||
- **WHEN** 系統驗證權限通過
|
||||
- **THEN** 系統解密檔案後提供下載
|
||||
- **AND** 解密過程透明,使用者無感
|
||||
|
||||
#### Scenario: 加密金鑰輪換
|
||||
- **GIVEN** 安全政策要求金鑰輪換
|
||||
- **WHEN** 管理員執行金鑰輪換
|
||||
- **THEN** 系統使用新金鑰重新加密所有檔案
|
||||
- **AND** 舊金鑰安全銷毀
|
||||
|
||||
### Requirement: Dynamic Watermarking
|
||||
系統 SHALL 在下載時自動為檔案加上使用者浮水印。
|
||||
|
||||
#### Scenario: 圖片浮水印
|
||||
- **GIVEN** 使用者下載圖片類型附件
|
||||
- **WHEN** 系統處理下載請求
|
||||
- **THEN** 自動加上包含使用者姓名、工號、下載時間的浮水印
|
||||
- **AND** 浮水印位置不影響主要內容
|
||||
|
||||
#### Scenario: PDF 浮水印
|
||||
- **GIVEN** 使用者下載 PDF 類型附件
|
||||
- **WHEN** 系統處理下載請求
|
||||
- **THEN** 每頁加上浮水印
|
||||
- **AND** 浮水印透明度適中
|
||||
|
||||
#### Scenario: 浮水印內容
|
||||
- **GIVEN** 需要加上浮水印
|
||||
- **WHEN** 系統生成浮水印
|
||||
- **THEN** 浮水印包含:
|
||||
- 使用者姓名
|
||||
- 使用者工號
|
||||
- 下載日期時間
|
||||
- 機密等級標示(如適用)
|
||||
|
||||
### Requirement: Audit Trail
|
||||
系統 SHALL 記錄所有文件操作供稽核追溯。
|
||||
|
||||
#### Scenario: 操作日誌記錄
|
||||
- **GIVEN** 使用者對附件執行任何操作
|
||||
- **WHEN** 操作完成
|
||||
- **THEN** 系統記錄操作類型、操作者、時間、IP 位址
|
||||
- **AND** 日誌不可竄改
|
||||
|
||||
#### Scenario: 稽核查詢
|
||||
- **GIVEN** 稽核人員需要查詢文件操作歷史
|
||||
- **WHEN** 稽核人員執行查詢
|
||||
- **THEN** 顯示完整操作歷史
|
||||
- **AND** 支援依時間、操作者、檔案篩選
|
||||
|
||||
## Data Model
|
||||
|
||||
```
|
||||
pjctrl_attachments
|
||||
├── id: UUID (PK)
|
||||
├── task_id: UUID (FK -> tasks)
|
||||
├── filename: VARCHAR(500)
|
||||
├── original_filename: VARCHAR(500)
|
||||
├── file_path: VARCHAR(1000) (NAS path)
|
||||
├── file_size: BIGINT
|
||||
├── mime_type: VARCHAR(100)
|
||||
├── version: INT DEFAULT 1
|
||||
├── is_encrypted: BOOLEAN DEFAULT false
|
||||
├── encryption_key_id: UUID (FK -> encryption_keys)
|
||||
├── checksum: VARCHAR(64) (SHA-256)
|
||||
├── uploaded_by: UUID (FK -> users)
|
||||
├── is_deleted: BOOLEAN DEFAULT false
|
||||
├── created_at: TIMESTAMP
|
||||
└── updated_at: TIMESTAMP
|
||||
|
||||
pjctrl_attachment_versions
|
||||
├── id: UUID (PK)
|
||||
├── attachment_id: UUID (FK -> attachments)
|
||||
├── version: INT
|
||||
├── file_path: VARCHAR(1000)
|
||||
├── file_size: BIGINT
|
||||
├── checksum: VARCHAR(64)
|
||||
├── uploaded_by: UUID (FK -> users)
|
||||
├── is_current: BOOLEAN DEFAULT false
|
||||
└── created_at: TIMESTAMP
|
||||
|
||||
pjctrl_encryption_keys
|
||||
├── id: UUID (PK)
|
||||
├── key_hash: VARCHAR(64) (for verification)
|
||||
├── algorithm: VARCHAR(20) DEFAULT 'AES-256'
|
||||
├── is_active: BOOLEAN DEFAULT true
|
||||
├── created_at: TIMESTAMP
|
||||
└── rotated_at: TIMESTAMP
|
||||
|
||||
pjctrl_document_audit_logs
|
||||
├── id: UUID (PK)
|
||||
├── attachment_id: UUID (FK -> attachments)
|
||||
├── user_id: UUID (FK -> users)
|
||||
├── action: ENUM('upload', 'download', 'delete', 'restore', 'version_create', 'version_restore')
|
||||
├── ip_address: VARCHAR(45)
|
||||
├── user_agent: VARCHAR(500)
|
||||
├── details: JSON
|
||||
└── created_at: TIMESTAMP
|
||||
```
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- 加密金鑰存儲於獨立的 Key Management Service (KMS)
|
||||
- 浮水印使用 Pillow (圖片) 和 PyPDF2 (PDF) 處理
|
||||
- 大檔案使用串流處理避免記憶體溢出
|
||||
- NAS 存儲路徑結構:`/{project_id}/{task_id}/{attachment_id}/{version}/`
|
||||
100
openspec/specs/resource-management/spec.md
Normal file
100
openspec/specs/resource-management/spec.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Resource Management
|
||||
|
||||
資源管理系統,提供負載熱圖與人員容量追蹤,協助主管進行資源分配決策。
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Workload Heatmap
|
||||
系統 SHALL 提供負載熱圖,自動統計每人每週分配的任務總時數。
|
||||
|
||||
#### Scenario: 負載正常顯示
|
||||
- **GIVEN** 某人員本週被指派的任務總時數低於其容量的 80%
|
||||
- **WHEN** 主管查看負載熱圖
|
||||
- **THEN** 該人員顯示為綠色(正常)
|
||||
|
||||
#### Scenario: 負載警告顯示
|
||||
- **GIVEN** 某人員本週被指派的任務總時數達到其容量的 80%-100%
|
||||
- **WHEN** 主管查看負載熱圖
|
||||
- **THEN** 該人員顯示為黃色(警告)
|
||||
|
||||
#### Scenario: 負載超載顯示
|
||||
- **GIVEN** 某人員本週被指派的任務總時數超過其容量的 100%
|
||||
- **WHEN** 主管查看負載熱圖
|
||||
- **THEN** 該人員顯示為紅色(超載)
|
||||
- **AND** 可點擊查看詳細任務分配
|
||||
|
||||
### Requirement: Capacity Planning
|
||||
系統 SHALL 支援人員容量規劃與追蹤。
|
||||
|
||||
#### Scenario: 設定人員容量
|
||||
- **GIVEN** 管理者需要設定人員的週工時上限
|
||||
- **WHEN** 管理者更新使用者的 Capacity 值
|
||||
- **THEN** 系統儲存新的容量設定
|
||||
- **AND** 重新計算該人員的負載百分比
|
||||
|
||||
#### Scenario: 容量調整(如請假)
|
||||
- **GIVEN** 人員某週有請假安排
|
||||
- **WHEN** 系統計算該週負載
|
||||
- **THEN** 考慮實際可用工時進行計算
|
||||
|
||||
### Requirement: Multi-Project Health Dashboard
|
||||
系統 SHALL 提供多專案健康看板,讓主管一覽所有專案狀態。
|
||||
|
||||
#### Scenario: 專案健康總覽
|
||||
- **GIVEN** 主管負責多個專案
|
||||
- **WHEN** 主管開啟健康看板
|
||||
- **THEN** 顯示所有專案的進度、風險指標、延遲任務數
|
||||
- **AND** 可依風險程度排序
|
||||
|
||||
#### Scenario: 專案延遲警示
|
||||
- **GIVEN** 專案有任務超過截止日期
|
||||
- **WHEN** 主管查看健康看板
|
||||
- **THEN** 該專案標示為延遲狀態
|
||||
- **AND** 顯示延遲任務數量與影響
|
||||
|
||||
### Requirement: Team Workload Distribution
|
||||
系統 SHALL 視覺化呈現團隊工作分配狀況。
|
||||
|
||||
#### Scenario: 部門負載總覽
|
||||
- **GIVEN** 主管需要了解部門整體負載
|
||||
- **WHEN** 主管查看團隊負載視圖
|
||||
- **THEN** 顯示部門內每位成員的負載狀況
|
||||
- **AND** 可按專案或任務類型篩選
|
||||
|
||||
#### Scenario: 資源分配不均警示
|
||||
- **GIVEN** 團隊中存在負載差異過大的情況
|
||||
- **WHEN** 系統偵測到分配不均
|
||||
- **THEN** 在看板上標示警示
|
||||
- **AND** 建議可重新分配的任務
|
||||
|
||||
## Data Model
|
||||
|
||||
```
|
||||
pjctrl_workload_snapshots
|
||||
├── id: UUID (PK)
|
||||
├── user_id: UUID (FK -> users)
|
||||
├── week_start: DATE
|
||||
├── allocated_hours: DECIMAL
|
||||
├── capacity_hours: DECIMAL
|
||||
├── load_percentage: DECIMAL
|
||||
├── created_at: TIMESTAMP
|
||||
└── updated_at: TIMESTAMP
|
||||
|
||||
pjctrl_project_health
|
||||
├── id: UUID (PK)
|
||||
├── project_id: UUID (FK -> projects)
|
||||
├── snapshot_date: DATE
|
||||
├── total_tasks: INT
|
||||
├── completed_tasks: INT
|
||||
├── overdue_tasks: INT
|
||||
├── blocked_tasks: INT
|
||||
├── risk_score: DECIMAL
|
||||
├── created_at: TIMESTAMP
|
||||
└── updated_at: TIMESTAMP
|
||||
```
|
||||
|
||||
## Calculation Rules
|
||||
|
||||
- **負載百分比** = (allocated_hours / capacity_hours) × 100
|
||||
- **風險評分** = f(overdue_tasks, blocked_tasks, timeline_remaining)
|
||||
- 快取計算結果於 Redis,每小時更新或任務變更時即時更新
|
||||
164
openspec/specs/task-management/spec.md
Normal file
164
openspec/specs/task-management/spec.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# Task Management
|
||||
|
||||
任務管理核心系統,支援多層級架構、自定義欄位與多維視角。
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Hierarchical Task Structure
|
||||
系統 SHALL 支援多層級任務架構:空間 (Space) > 專案 (Project) > 任務 (Task) > 子任務 (Sub-task)。
|
||||
|
||||
#### Scenario: 建立空間
|
||||
- **GIVEN** 使用者擁有建立空間的權限
|
||||
- **WHEN** 使用者建立新空間
|
||||
- **THEN** 系統建立空間並設定擁有者
|
||||
- **AND** 空間可包含多個專案
|
||||
|
||||
#### Scenario: 建立專案
|
||||
- **GIVEN** 使用者在某空間內擁有建立專案的權限
|
||||
- **WHEN** 使用者建立新專案
|
||||
- **THEN** 系統建立專案並關聯至該空間
|
||||
- **AND** 設定專案的 Owner、Budget、Timeline、Security_Level
|
||||
|
||||
#### Scenario: 建立任務與子任務
|
||||
- **GIVEN** 使用者在專案內擁有建立任務的權限
|
||||
- **WHEN** 使用者建立任務或子任務
|
||||
- **THEN** 系統建立任務並維護父子關係
|
||||
- **AND** 子任務繼承父任務的部分屬性
|
||||
|
||||
### Requirement: Custom Fields
|
||||
系統 SHALL 支援自定義欄位,包含下拉選單、公式、人員標籤等類型。
|
||||
|
||||
#### Scenario: 新增自定義欄位
|
||||
- **GIVEN** 專案管理者需要追蹤特定資料(如:封裝類型、機台編號、預計良率)
|
||||
- **WHEN** 管理者在專案中新增自定義欄位
|
||||
- **THEN** 系統建立欄位定義並套用至該專案所有任務
|
||||
|
||||
#### Scenario: 公式欄位計算
|
||||
- **GIVEN** 任務包含公式類型的自定義欄位
|
||||
- **WHEN** 相依欄位的值發生變更
|
||||
- **THEN** 系統自動重新計算公式欄位的值
|
||||
|
||||
#### Scenario: 人員標籤欄位
|
||||
- **GIVEN** 任務包含人員標籤類型的自定義欄位
|
||||
- **WHEN** 使用者選擇人員
|
||||
- **THEN** 系統驗證人員存在並建立關聯
|
||||
- **AND** 被標籤的人員可收到相關通知
|
||||
|
||||
### Requirement: Multiple Views
|
||||
系統 SHALL 支援多維視角:看板 (Kanban)、甘特圖 (Gantt)、列表 (List)、行事曆 (Calendar)。
|
||||
|
||||
#### Scenario: 看板視角
|
||||
- **GIVEN** 使用者選擇看板視角
|
||||
- **WHEN** 系統載入專案任務
|
||||
- **THEN** 任務依狀態分組顯示為卡片
|
||||
- **AND** 支援拖拉變更狀態
|
||||
|
||||
#### Scenario: 甘特圖視角
|
||||
- **GIVEN** 使用者選擇甘特圖視角
|
||||
- **WHEN** 系統載入專案任務
|
||||
- **THEN** 任務依時間軸顯示
|
||||
- **AND** 顯示任務相依關係與里程碑
|
||||
|
||||
#### Scenario: 列表視角
|
||||
- **GIVEN** 使用者選擇列表視角
|
||||
- **WHEN** 系統載入專案任務
|
||||
- **THEN** 任務以表格形式顯示
|
||||
- **AND** 支援欄位排序與篩選
|
||||
|
||||
#### Scenario: 行事曆視角
|
||||
- **GIVEN** 使用者選擇行事曆視角
|
||||
- **WHEN** 系統載入專案任務
|
||||
- **THEN** 任務依截止日期顯示在行事曆上
|
||||
|
||||
### Requirement: Task Status Management
|
||||
系統 SHALL 管理任務狀態,包含標準狀態與自定義狀態。
|
||||
|
||||
#### Scenario: 狀態變更
|
||||
- **GIVEN** 使用者擁有更新任務的權限
|
||||
- **WHEN** 使用者變更任務狀態
|
||||
- **THEN** 系統更新狀態並記錄變更時間
|
||||
- **AND** 觸發相關自動化規則(如有設定)
|
||||
|
||||
#### Scenario: 阻礙標記
|
||||
- **GIVEN** 任務遇到阻礙無法進行
|
||||
- **WHEN** 工程師將任務標記為 "Blocked"
|
||||
- **THEN** 系統設定 Blocker_Flag = true
|
||||
- **AND** 強制發送通知給主管要求介入排解
|
||||
|
||||
### Requirement: Task Assignment
|
||||
系統 SHALL 支援任務指派與時間估算。
|
||||
|
||||
#### Scenario: 指派任務
|
||||
- **GIVEN** 使用者擁有指派任務的權限
|
||||
- **WHEN** 使用者將任務指派給某人
|
||||
- **THEN** 系統更新 Assignee 並發送通知
|
||||
- **AND** 任務計入被指派者的工作負載
|
||||
|
||||
#### Scenario: 時間估算與追蹤
|
||||
- **GIVEN** 任務已被指派
|
||||
- **WHEN** 使用者設定 Original_Estimate 與回報 Time_Spent
|
||||
- **THEN** 系統記錄並計算剩餘時間
|
||||
- **AND** 更新資源負載統計
|
||||
|
||||
## Data Model
|
||||
|
||||
```
|
||||
pjctrl_spaces
|
||||
├── id: UUID (PK)
|
||||
├── name: VARCHAR(200)
|
||||
├── description: TEXT
|
||||
├── owner_id: UUID (FK -> users)
|
||||
├── created_at: TIMESTAMP
|
||||
└── updated_at: TIMESTAMP
|
||||
|
||||
pjctrl_projects
|
||||
├── id: UUID (PK)
|
||||
├── space_id: UUID (FK -> spaces)
|
||||
├── title: VARCHAR(200)
|
||||
├── description: TEXT
|
||||
├── owner_id: UUID (FK -> users)
|
||||
├── budget: DECIMAL
|
||||
├── start_date: DATE
|
||||
├── end_date: DATE
|
||||
├── security_level: ENUM('public', 'department', 'confidential')
|
||||
├── status: VARCHAR(50)
|
||||
├── created_at: TIMESTAMP
|
||||
└── updated_at: TIMESTAMP
|
||||
|
||||
pjctrl_tasks
|
||||
├── id: UUID (PK)
|
||||
├── project_id: UUID (FK -> projects)
|
||||
├── parent_task_id: UUID (FK -> tasks, nullable)
|
||||
├── title: VARCHAR(500)
|
||||
├── description: TEXT
|
||||
├── assignee_id: UUID (FK -> users)
|
||||
├── priority: ENUM('low', 'medium', 'high', 'urgent')
|
||||
├── status: VARCHAR(50)
|
||||
├── original_estimate: DECIMAL (hours)
|
||||
├── time_spent: DECIMAL (hours)
|
||||
├── blocker_flag: BOOLEAN DEFAULT false
|
||||
├── due_date: DATETIME
|
||||
├── created_at: TIMESTAMP
|
||||
└── updated_at: TIMESTAMP
|
||||
|
||||
pjctrl_custom_fields
|
||||
├── id: UUID (PK)
|
||||
├── project_id: UUID (FK -> projects)
|
||||
├── name: VARCHAR(100)
|
||||
├── field_type: ENUM('text', 'number', 'dropdown', 'date', 'person', 'formula')
|
||||
├── options: JSON (for dropdown)
|
||||
├── formula: TEXT (for formula type)
|
||||
├── is_required: BOOLEAN
|
||||
└── created_at: TIMESTAMP
|
||||
|
||||
pjctrl_task_custom_values
|
||||
├── id: UUID (PK)
|
||||
├── task_id: UUID (FK -> tasks)
|
||||
├── field_id: UUID (FK -> custom_fields)
|
||||
├── value: TEXT
|
||||
└── updated_at: TIMESTAMP
|
||||
```
|
||||
|
||||
## Real-time Sync
|
||||
|
||||
系統使用 WebSocket 實現即時同步,當多人同時編輯同一個專案看板時,狀態能即時更新而不需刷新頁面。
|
||||
154
openspec/specs/user-auth/spec.md
Normal file
154
openspec/specs/user-auth/spec.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# User Authentication & Authorization
|
||||
|
||||
## Purpose
|
||||
|
||||
使用者認證與授權系統,透過外部認證 API 進行身份驗證,提供細部權限控制。
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: API-Based Authentication
|
||||
系統 SHALL 限定使用外部認證 API (https://pj-auth-api.vercel.app) 進行登入認證,不支援其他認證方式。
|
||||
|
||||
#### Scenario: API 登入成功
|
||||
- **GIVEN** 使用者擁有有效的企業帳號
|
||||
- **WHEN** 使用者透過前端提交憑證
|
||||
- **THEN** 系統呼叫 https://pj-auth-api.vercel.app 驗證憑證
|
||||
- **AND** 驗證成功後建立 session 並回傳 JWT token
|
||||
|
||||
#### Scenario: API 登入失敗
|
||||
- **GIVEN** 使用者提供無效的憑證
|
||||
- **WHEN** 使用者嘗試登入
|
||||
- **THEN** 認證 API 回傳錯誤
|
||||
- **AND** 系統拒絕登入並顯示錯誤訊息
|
||||
- **AND** 記錄失敗的登入嘗試
|
||||
|
||||
#### Scenario: 認證 API 無法連線
|
||||
- **GIVEN** 認證 API 服務無法連線
|
||||
- **WHEN** 使用者嘗試登入
|
||||
- **THEN** 系統顯示服務暫時無法使用的訊息
|
||||
- **AND** 記錄連線失敗事件
|
||||
|
||||
### Requirement: System Administrator
|
||||
系統 SHALL 預設一個系統管理員帳號,擁有所有權限。系統管理員帳號必須存在於外部認證系統,且登入流程仍需透過外部認證 API;不允許本地繞過認證。
|
||||
|
||||
#### Scenario: 預設管理員帳號
|
||||
- **GIVEN** 系統初始化完成
|
||||
- **WHEN** 系統啟動
|
||||
- **THEN** 存在預設管理員帳號 `ymirliu@panjit.com.tw`
|
||||
- **AND** 該帳號擁有 `super_admin` 角色
|
||||
- **AND** 該帳號不可被刪除或降級
|
||||
|
||||
#### Scenario: 管理員登入流程
|
||||
- **GIVEN** 管理員帳號 `ymirliu@panjit.com.tw` 需要登入
|
||||
- **WHEN** 管理員提交憑證
|
||||
- **THEN** 系統仍需呼叫 https://pj-auth-api.vercel.app 驗證
|
||||
- **AND** 不存在任何本地繞過認證的機制
|
||||
- **AND** 驗證成功後才授予 `super_admin` 權限
|
||||
|
||||
#### Scenario: 管理員全域權限
|
||||
- **GIVEN** 管理員帳號 `ymirliu@panjit.com.tw` 已通過 API 認證並登入
|
||||
- **WHEN** 管理員存取任何資源
|
||||
- **THEN** 系統允許存取,無視部門隔離限制
|
||||
|
||||
### Requirement: Role-Based Access Control
|
||||
系統 SHALL 支援基於角色的存取控制 (RBAC)。
|
||||
|
||||
#### Scenario: 角色權限檢查
|
||||
- **GIVEN** 使用者被指派特定角色 (如:工程師、主管、PMO)
|
||||
- **WHEN** 使用者嘗試存取受保護的資源
|
||||
- **THEN** 系統根據角色權限決定是否允許存取
|
||||
|
||||
#### Scenario: 角色指派
|
||||
- **GIVEN** 管理員擁有使用者管理權限
|
||||
- **WHEN** 管理員為使用者指派角色
|
||||
- **THEN** 系統更新使用者的角色設定
|
||||
- **AND** 新權限立即生效
|
||||
|
||||
### Requirement: Department Isolation
|
||||
系統 SHALL 實施部門級別的資料隔離,確保跨部門資料安全。
|
||||
|
||||
#### Scenario: 部門資料隔離
|
||||
- **GIVEN** 使用者屬於研發部門
|
||||
- **WHEN** 使用者嘗試存取廠務部門的專案
|
||||
- **THEN** 系統拒絕存取並顯示無權限訊息
|
||||
|
||||
#### Scenario: 跨部門專案存取
|
||||
- **GIVEN** 專案被設定為跨部門可見
|
||||
- **WHEN** 不同部門的使用者嘗試存取該專案
|
||||
- **THEN** 系統根據專案的 Security_Level 設定決定是否允許存取
|
||||
|
||||
### Requirement: Session Management
|
||||
系統 SHALL 管理使用者 session,包含過期與登出機制。
|
||||
|
||||
#### Scenario: Session 過期
|
||||
- **GIVEN** 使用者已登入系統
|
||||
- **WHEN** Session 超過設定的有效期限
|
||||
- **THEN** 系統自動使 session 失效
|
||||
- **AND** 使用者需重新登入
|
||||
|
||||
#### Scenario: 主動登出
|
||||
- **GIVEN** 使用者已登入系統
|
||||
- **WHEN** 使用者執行登出操作
|
||||
- **THEN** 系統銷毀 session 並清除 token
|
||||
|
||||
## Data Model
|
||||
|
||||
```
|
||||
pjctrl_users
|
||||
├── id: UUID (PK)
|
||||
├── email: VARCHAR(200) UNIQUE
|
||||
├── name: VARCHAR(200)
|
||||
├── department_id: UUID (FK)
|
||||
├── role_id: UUID (FK)
|
||||
├── skills: JSON
|
||||
├── capacity: DECIMAL (週工時上限)
|
||||
├── is_active: BOOLEAN
|
||||
├── is_system_admin: BOOLEAN DEFAULT false (不可修改的系統管理員標記)
|
||||
├── created_at: TIMESTAMP
|
||||
└── updated_at: TIMESTAMP
|
||||
|
||||
pjctrl_departments
|
||||
├── id: UUID (PK)
|
||||
├── name: VARCHAR(100)
|
||||
├── parent_id: UUID (FK, self-reference)
|
||||
└── created_at: TIMESTAMP
|
||||
|
||||
pjctrl_roles
|
||||
├── id: UUID (PK)
|
||||
├── name: VARCHAR(50)
|
||||
├── permissions: JSON
|
||||
├── is_system_role: BOOLEAN DEFAULT false
|
||||
└── created_at: TIMESTAMP
|
||||
```
|
||||
|
||||
## Default Data (Seed)
|
||||
|
||||
```sql
|
||||
-- 預設系統管理員角色
|
||||
INSERT INTO pjctrl_roles (id, name, permissions, is_system_role) VALUES
|
||||
('00000000-0000-0000-0000-000000000001', 'super_admin', '{"all": true}', true);
|
||||
|
||||
-- 預設系統管理員帳號
|
||||
INSERT INTO pjctrl_users (id, email, name, role_id, is_active, is_system_admin) VALUES
|
||||
('00000000-0000-0000-0000-000000000001', 'ymirliu@panjit.com.tw', 'System Administrator',
|
||||
'00000000-0000-0000-0000-000000000001', true, true);
|
||||
```
|
||||
|
||||
## External Dependencies
|
||||
|
||||
- **Authentication API**: https://pj-auth-api.vercel.app (唯一認證方式)
|
||||
|
||||
## Authentication Flow
|
||||
|
||||
```
|
||||
┌─────────┐ ┌─────────────┐ ┌──────────────────────────┐
|
||||
│ User │────▶│ Frontend │────▶│ pj-auth-api.vercel.app │
|
||||
└─────────┘ └─────────────┘ └──────────────────────────┘
|
||||
│ │
|
||||
│◀────── JWT Token ───────│
|
||||
│
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ Backend │ (驗證 JWT, 建立 Session)
|
||||
└─────────────┘
|
||||
```
|
||||
Reference in New Issue
Block a user