feat: implement custom fields, gantt view, calendar view, and file encryption
- Custom Fields (FEAT-001): - CustomField and TaskCustomValue models with formula support - CRUD API for custom field management - Formula engine for calculated fields - Frontend: CustomFieldEditor, CustomFieldInput, ProjectSettings page - Task list API now includes custom_values - KanbanBoard displays custom field values - Gantt View (FEAT-003): - TaskDependency model with FS/SS/FF/SF dependency types - Dependency CRUD API with cycle detection - start_date field added to tasks - GanttChart component with Frappe Gantt integration - Dependency type selector in UI - Calendar View (FEAT-004): - CalendarView component with FullCalendar integration - Date range filtering API for tasks - Drag-and-drop date updates - View mode switching in Tasks page - File Encryption (FEAT-010): - AES-256-GCM encryption service - EncryptionKey model with key rotation support - Admin API for key management - Encrypted upload/download for confidential projects - Migrations: 011 (custom fields), 012 (encryption keys), 013 (task dependencies) - Updated issues.md with completion status 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
# Proposal: Add File Encryption
|
||||
|
||||
**Change ID:** `add-file-encryption`
|
||||
**Issue Reference:** `FEAT-010` (issues.md)
|
||||
**Status:** Draft
|
||||
**Author:** Claude
|
||||
**Date:** 2026-01-05
|
||||
|
||||
## Summary
|
||||
|
||||
實作 AES-256 加密存儲功能,對機密等級專案的附件進行加密保護,並提供金鑰管理與輪換機制。
|
||||
|
||||
## Motivation
|
||||
|
||||
半導體產業的設計文件、製程參數和良率報告屬於高度機密資料。目前系統的附件以明文形式儲存於 NAS,若發生以下情況可能導致資料外洩:
|
||||
- NAS 遭未授權存取
|
||||
- 備份媒體遺失
|
||||
- 儲存設備報廢未妥善處理
|
||||
|
||||
透過 AES-256 加密,即使檔案被取得也無法解讀內容,提供額外的安全層。
|
||||
|
||||
## Scope
|
||||
|
||||
### In Scope
|
||||
- Backend: EncryptionKey model 和 key 管理 API
|
||||
- Backend: 加密服務(encrypt/decrypt)
|
||||
- Backend: 附件上傳時自動加密(依專案機密等級)
|
||||
- Backend: 附件下載時自動解密
|
||||
- Backend: 金鑰輪換功能
|
||||
- 稽核日誌:加密相關操作記錄
|
||||
|
||||
### Out of Scope
|
||||
- 客戶端加密(End-to-End Encryption)
|
||||
- Hardware Security Module (HSM) 整合
|
||||
- 現有檔案的批次加密遷移(需另案處理)
|
||||
|
||||
## Design Decisions
|
||||
|
||||
### 加密策略
|
||||
| 專案機密等級 | 加密行為 |
|
||||
|-------------|---------|
|
||||
| public | 不加密 |
|
||||
| department | 不加密 |
|
||||
| confidential | 強制加密 |
|
||||
|
||||
### 金鑰管理
|
||||
- 採用對稱金鑰加密(AES-256-GCM)
|
||||
- 每個金鑰有唯一 ID,儲存於資料庫
|
||||
- 金鑰本身使用 Master Key 加密後存儲
|
||||
- Master Key 從環境變數讀取,不存於資料庫
|
||||
|
||||
### 加密流程
|
||||
```
|
||||
1. 上傳檔案
|
||||
2. 檢查專案機密等級
|
||||
3. 若為 confidential:
|
||||
a. 取得當前有效金鑰
|
||||
b. 使用 AES-256-GCM 加密檔案
|
||||
c. 儲存加密後的檔案
|
||||
d. 記錄 encryption_key_id
|
||||
4. 儲存 Attachment 記錄
|
||||
```
|
||||
|
||||
### 解密流程
|
||||
```
|
||||
1. 請求下載檔案
|
||||
2. 驗證存取權限
|
||||
3. 若 is_encrypted = true:
|
||||
a. 取得 encryption_key_id 對應的金鑰
|
||||
b. 解密檔案
|
||||
c. 返回解密後的內容
|
||||
4. 若 is_encrypted = false:
|
||||
a. 直接返回檔案
|
||||
```
|
||||
|
||||
### 金鑰輪換
|
||||
- 建立新金鑰並標記為 active
|
||||
- 舊金鑰標記為 inactive(但保留用於解密舊檔案)
|
||||
- 新上傳檔案使用新金鑰
|
||||
- 可選:批次重新加密舊檔案(背景任務)
|
||||
|
||||
### API 設計
|
||||
```
|
||||
# 金鑰管理 (Admin only)
|
||||
GET /api/admin/encryption-keys # 列出所有金鑰
|
||||
POST /api/admin/encryption-keys # 建立新金鑰
|
||||
POST /api/admin/encryption-keys/rotate # 金鑰輪換
|
||||
DELETE /api/admin/encryption-keys/{id} # 停用金鑰(不刪除)
|
||||
|
||||
# 附件加密狀態由系統自動處理,無需額外 API
|
||||
```
|
||||
|
||||
## Affected Specs
|
||||
|
||||
| Spec | Change Type |
|
||||
|------|-------------|
|
||||
| document-management | MODIFIED (File Encryption requirement 實作細節) |
|
||||
|
||||
## Risks & Mitigations
|
||||
|
||||
| Risk | Mitigation |
|
||||
|------|------------|
|
||||
| Master Key 遺失導致資料無法解密 | 提供 Master Key 備份指引,建議異地保存 |
|
||||
| 加密效能影響 | 使用串流加密避免大檔案記憶體問題 |
|
||||
| 金鑰輪換中斷 | 使用資料庫交易確保原子性 |
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Python cryptography 套件
|
||||
- Master Key 環境變數配置
|
||||
@@ -0,0 +1,52 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: File Encryption
|
||||
系統 SHALL 對半導體敏感圖檔進行 AES-256 加密存儲。
|
||||
|
||||
#### Scenario: 自動加密判斷
|
||||
- **GIVEN** 使用者上傳檔案至任務
|
||||
- **WHEN** 該任務所屬專案的 security_level 為 "confidential"
|
||||
- **THEN** 系統自動使用 AES-256-GCM 加密檔案
|
||||
- **AND** 設定 is_encrypted = true 及 encryption_key_id
|
||||
|
||||
#### Scenario: 加密存儲
|
||||
- **GIVEN** 專案設定為機密等級
|
||||
- **WHEN** 使用者上傳檔案
|
||||
- **THEN** 系統使用 AES-256 加密後存儲
|
||||
- **AND** 加密金鑰安全管理
|
||||
|
||||
#### Scenario: 解密讀取
|
||||
- **GIVEN** 使用者請求下載加密檔案
|
||||
- **WHEN** 系統驗證權限通過
|
||||
- **THEN** 系統解密檔案後提供下載
|
||||
- **AND** 解密過程透明,使用者無感
|
||||
|
||||
#### Scenario: 串流處理大檔案
|
||||
- **GIVEN** 使用者上傳或下載大型加密檔案
|
||||
- **WHEN** 系統處理加密或解密
|
||||
- **THEN** 使用串流方式處理避免記憶體溢出
|
||||
- **AND** 效能損耗在可接受範圍內
|
||||
|
||||
#### Scenario: 金鑰輪換
|
||||
- **GIVEN** 安全政策要求金鑰輪換
|
||||
- **WHEN** 管理員執行金鑰輪換
|
||||
- **THEN** 系統建立新金鑰並標記為 active
|
||||
- **AND** 舊金鑰保留用於解密既有檔案
|
||||
- **AND** 新上傳檔案使用新金鑰加密
|
||||
|
||||
#### Scenario: Master Key 管理
|
||||
- **GIVEN** 系統需要加解密檔案
|
||||
- **WHEN** 系統取得加密金鑰
|
||||
- **THEN** 使用 Master Key 解密金鑰後使用
|
||||
- **AND** Master Key 從環境變數讀取,不存於資料庫
|
||||
|
||||
#### Scenario: 加密操作稽核
|
||||
- **GIVEN** 發生加密相關操作
|
||||
- **WHEN** 操作完成
|
||||
- **THEN** 系統記錄操作類型、金鑰 ID、檔案 ID、操作者、時間
|
||||
- **AND** 日誌不可竄改
|
||||
|
||||
#### Scenario: 金鑰管理權限
|
||||
- **GIVEN** 使用者嘗試管理加密金鑰
|
||||
- **WHEN** 使用者不是系統管理員
|
||||
- **THEN** 系統拒絕操作並返回 403 錯誤
|
||||
@@ -0,0 +1,89 @@
|
||||
# Tasks: Add File Encryption
|
||||
|
||||
## Backend Tasks
|
||||
|
||||
### 1. Create EncryptionKey model
|
||||
- [x] Create `backend/app/models/encryption_key.py`
|
||||
- [x] Update `backend/app/models/__init__.py`
|
||||
- [x] Add `encryption_key_id` FK to Attachment model
|
||||
- [x] Create Alembic migration
|
||||
- **驗證**: Migration 成功執行
|
||||
|
||||
### 2. Implement encryption service
|
||||
- [x] Create `backend/app/services/encryption_service.py`
|
||||
- [x] Add `MASTER_KEY` to config.py (from env var)
|
||||
- [x] Implement `generate_key()` - 產生新的 AES-256 金鑰
|
||||
- [x] Implement `encrypt_key()` - 使用 Master Key 加密金鑰
|
||||
- [x] Implement `decrypt_key()` - 使用 Master Key 解密金鑰
|
||||
- [x] Implement `encrypt_file()` - 串流式檔案加密 (AES-256-GCM)
|
||||
- [x] Implement `decrypt_file()` - 串流式檔案解密
|
||||
- [x] Add unit tests for encryption service
|
||||
- **驗證**: 加密解密測試通過
|
||||
|
||||
### 3. Create encryption key management API
|
||||
- [x] Create `backend/app/api/admin/encryption_keys.py`
|
||||
- [x] Implement `GET /api/admin/encryption-keys` - 列出金鑰(不含實際金鑰值)
|
||||
- [x] Implement `POST /api/admin/encryption-keys` - 建立新金鑰
|
||||
- [x] Implement `POST /api/admin/encryption-keys/rotate` - 金鑰輪換
|
||||
- [x] Add system admin only permission check
|
||||
- [x] Register router in main.py
|
||||
- **驗證**: API 可正常呼叫
|
||||
|
||||
### 4. Integrate encryption with attachment upload
|
||||
- [x] Modify `backend/app/api/attachments/router.py` upload endpoint
|
||||
- [x] Check project security_level before upload
|
||||
- [x] If confidential: encrypt file using encryption service
|
||||
- [x] Set is_encrypted = True and encryption_key_id
|
||||
- [x] Store encrypted file to NAS
|
||||
- **驗證**: 機密專案上傳的檔案為加密狀態
|
||||
|
||||
### 5. Integrate decryption with attachment download
|
||||
- [x] Modify `backend/app/api/attachments/router.py` download endpoint
|
||||
- [x] Check is_encrypted flag
|
||||
- [x] If encrypted: decrypt using encryption service before returning
|
||||
- [x] Maintain streaming for large files
|
||||
- **驗證**: 下載加密檔案可正確解密
|
||||
|
||||
### 6. Add encryption audit logging
|
||||
- [x] Log encryption operations (encrypt, decrypt, key_create, key_rotate)
|
||||
- [x] Include key_id, file_id, user_id, timestamp
|
||||
- **驗證**: 稽核日誌正確記錄加密操作
|
||||
|
||||
### 7. Add backend tests
|
||||
- [x] Test encryption service (encrypt/decrypt)
|
||||
- [x] Test key management API
|
||||
- [x] Test attachment upload with encryption
|
||||
- [x] Test attachment download with decryption
|
||||
- [x] Test key rotation
|
||||
- **驗證**: 所有測試通過
|
||||
|
||||
## Configuration Tasks
|
||||
|
||||
### 8. Environment configuration
|
||||
- [x] Add `MASTER_KEY` to .env.example
|
||||
- [x] Document key generation procedure
|
||||
- [x] Document key backup recommendations
|
||||
- **驗證**: 文件完整
|
||||
|
||||
## Task Dependencies
|
||||
|
||||
```
|
||||
[1] EncryptionKey Model
|
||||
↓
|
||||
[2] Encryption Service
|
||||
↓
|
||||
[3] Key Management API ─────┐
|
||||
↓ │
|
||||
[4] Upload Integration │
|
||||
↓ │
|
||||
[5] Download Integration │
|
||||
↓ │
|
||||
[6] Audit Logging │
|
||||
↓ │
|
||||
[7] Tests ←─────────────────┘
|
||||
↓
|
||||
[8] Configuration
|
||||
```
|
||||
|
||||
- Tasks 1-7 為循序依賴
|
||||
- Task 8 可平行進行
|
||||
Reference in New Issue
Block a user