154 lines
6.5 KiB
Plaintext
154 lines
6.5 KiB
Plaintext
# MES Dashboard(README.mdj)
|
||
|
||
本文件為 `README.md` 的精簡技術同步版,聚焦目前可運行架構與運維契約。
|
||
|
||
## 1. 架構摘要(2026-02-08)
|
||
|
||
- 後端:Flask + Gunicorn(單一 port)
|
||
- 前端:Vite build 輸出到 `src/mes_dashboard/static/dist`
|
||
- 快取:Redis + process-level cache + indexed selection telemetry
|
||
- 資料:Oracle(QueuePool)
|
||
- 運維:watchdog + admin worker restart API + guarded-mode policy
|
||
- 環境設定:開發與正式環境統一使用專案根目錄同一份 `.env`
|
||
- 啟動腳本:`./scripts/start_server.sh start` 會同時啟動 Gunicorn 與 `worker_watchdog.py`
|
||
|
||
## 2. 既有設計原則(保留)
|
||
|
||
- `resource`(設備基礎資料)與 `wip`(線上即時狀況)維持全表快取策略。
|
||
- 前端頁面邏輯與 drill-down 操作語意維持不變。
|
||
- 系統維持單一 port 服務模式(前後端同源)。
|
||
|
||
## 3. P0 Runtime Hardening(已完成)
|
||
|
||
- Production 強制 `SECRET_KEY`:未設定或使用不安全預設值時,啟動直接失敗。
|
||
- CSRF 防護:
|
||
- `/admin/login` 表單需 token
|
||
- `/admin/api/*` 的 `POST/PUT/PATCH/DELETE` 需 `X-CSRF-Token`
|
||
- Session hardening:登入成功後 `session.clear()` + CSRF token rotation。
|
||
- Health probe isolation:`/health` DB 連通檢查使用獨立 health pool。
|
||
- Shutdown cleanup:統一停止 cache updater、equipment sync worker,並關閉 Redis 與 DB engine。
|
||
- XSS hardening:`hold_detail` fallback script 的 `reason` 改用 `tojson`。
|
||
|
||
## 4. P1 Cache/Query Efficiency(已完成)
|
||
|
||
- `resource` / `wip` 仍維持全表快取策略(業務約束不變)。
|
||
- WIP 查詢改走 indexed selection,並加入增量同步(watermark/version)與 drift fallback。
|
||
- `/health`、`/health/deep`、`/admin/api/system-status` 提供 cache memory amplification/index telemetry。
|
||
- 新增 benchmark harness:`scripts/run_cache_benchmarks.py --enforce`。
|
||
|
||
## 5. P2 Ops Self-Healing(已完成)
|
||
|
||
- runtime contract 共用化:app/start_server/watchdog/systemd 使用同一組 watchdog/conda 路徑契約。
|
||
- 啟動 fail-fast:conda/runtime path drift 時拒絕啟動並輸出可操作診斷。
|
||
- worker restart policy:cooldown + retry budget + churn guarded mode。
|
||
- manual override:需 admin 身分 + `manual_override` + `override_acknowledged` + `override_reason`,且寫入 audit log。
|
||
- health/admin payload 提供 policy state:`allowed` / `cooldown` / `blocked`。
|
||
|
||
## 6. Round-3 Residual Hardening(已完成)
|
||
|
||
- WIP cache publish 改為 staged publish,更新失敗不覆寫舊快照。
|
||
- WIP process cache slow-path parse 移到鎖外,降低 lock contention。
|
||
- realtime equipment process cache 補齊 bounded LRU(含 `EQUIPMENT_PROCESS_CACHE_MAX_SIZE`)。
|
||
- `_clean_nan_values` 改為 depth-safe 迭代式清理(避免深層遞迴風險)。
|
||
- WIP/Hold/Resource bool query parser 共用化(`core/utils.py`)。
|
||
- filter cache source view 可由 env 覆寫(便於環境切換與測試)。
|
||
- `/health`、`/health/deep` 增加 5 秒 memo(testing 模式自動關閉)。
|
||
- 高成本 API 增加輕量 in-process rate limit,超限回傳一致 429 結構。
|
||
- DB 連線字串記錄加上敏感欄位遮罩(密碼 redaction)。
|
||
|
||
## 7. Round-4 Residual Consolidation(已完成)
|
||
|
||
- Resource derived index 改為 row-position representation,不再在 process 內保存 full records 複本。
|
||
- Resource / Realtime Equipment 共用 Oracle SQL fragments,避免查詢定義重複漂移。
|
||
- `resource_cache` / `realtime_equipment_cache` 型別註記風格與高頻常數命名收斂。
|
||
- `page_registry` 寫檔改為 atomic replace,降低設定檔半寫入風險。
|
||
- 新增測試覆蓋 shared SQL fragment 與 bool parser 不重複定義治理。
|
||
|
||
## 8. 重要環境變數
|
||
|
||
```bash
|
||
FLASK_ENV=production
|
||
SECRET_KEY=<required-in-production>
|
||
CSRF_ENABLED=true
|
||
|
||
LDAP_API_URL=https://ldap-api.example.com
|
||
LDAP_ALLOWED_HOSTS=ldap-api.example.com,ldap-api-dr.example.com
|
||
|
||
DB_POOL_SIZE=10
|
||
DB_MAX_OVERFLOW=20
|
||
DB_POOL_TIMEOUT=30
|
||
DB_POOL_RECYCLE=1800
|
||
DB_CALL_TIMEOUT_MS=55000
|
||
DB_POOL_EXHAUSTED_RETRY_AFTER_SECONDS=5
|
||
|
||
DB_HEALTH_POOL_SIZE=1
|
||
DB_HEALTH_MAX_OVERFLOW=0
|
||
DB_HEALTH_POOL_TIMEOUT=2
|
||
|
||
CONDA_BIN=/opt/miniconda3/bin/conda
|
||
CONDA_ENV_NAME=mes-dashboard
|
||
RUNTIME_CONTRACT_VERSION=2026.02-p2
|
||
RUNTIME_CONTRACT_ENFORCE=true
|
||
|
||
WATCHDOG_RUNTIME_DIR=./tmp
|
||
WATCHDOG_RESTART_FLAG=./tmp/mes_dashboard_restart.flag
|
||
WATCHDOG_PID_FILE=./tmp/gunicorn.pid
|
||
WATCHDOG_STATE_FILE=./tmp/mes_dashboard_restart_state.json
|
||
WATCHDOG_RESTART_HISTORY_MAX=50
|
||
|
||
WORKER_RESTART_COOLDOWN=60
|
||
WORKER_RESTART_RETRY_BUDGET=3
|
||
WORKER_RESTART_WINDOW_SECONDS=600
|
||
WORKER_RESTART_CHURN_THRESHOLD=3
|
||
WORKER_GUARDED_MODE_ENABLED=true
|
||
|
||
PROCESS_CACHE_MAX_SIZE=32
|
||
WIP_PROCESS_CACHE_MAX_SIZE=32
|
||
RESOURCE_PROCESS_CACHE_MAX_SIZE=32
|
||
EQUIPMENT_PROCESS_CACHE_MAX_SIZE=32
|
||
|
||
FILTER_CACHE_WIP_VIEW=DWH.DW_MES_LOT_V
|
||
FILTER_CACHE_SPEC_WORKCENTER_VIEW=DWH.DW_MES_SPEC_WORKCENTER_V
|
||
|
||
HEALTH_MEMO_TTL_SECONDS=5
|
||
|
||
WIP_MATRIX_RATE_LIMIT_MAX_REQUESTS=120
|
||
WIP_MATRIX_RATE_LIMIT_WINDOW_SECONDS=60
|
||
WIP_DETAIL_RATE_LIMIT_MAX_REQUESTS=90
|
||
WIP_DETAIL_RATE_LIMIT_WINDOW_SECONDS=60
|
||
HOLD_LOTS_RATE_LIMIT_MAX_REQUESTS=90
|
||
HOLD_LOTS_RATE_LIMIT_WINDOW_SECONDS=60
|
||
RESOURCE_DETAIL_RATE_LIMIT_MAX_REQUESTS=60
|
||
RESOURCE_DETAIL_RATE_LIMIT_WINDOW_SECONDS=60
|
||
RESOURCE_STATUS_RATE_LIMIT_MAX_REQUESTS=90
|
||
RESOURCE_STATUS_RATE_LIMIT_WINDOW_SECONDS=60
|
||
```
|
||
|
||
## 9. 驗證命令(建議)
|
||
|
||
```bash
|
||
# 後端(conda)
|
||
conda run -n mes-dashboard python -m pytest -q tests/test_runtime_hardening.py
|
||
|
||
# 前端
|
||
npm --prefix frontend test
|
||
npm --prefix frontend run build
|
||
|
||
# P1 benchmark gate
|
||
conda run -n mes-dashboard python scripts/run_cache_benchmarks.py --enforce
|
||
|
||
# P2 runtime contract check
|
||
RUNTIME_CONTRACT_ENFORCE=true ./scripts/start_server.sh check
|
||
```
|
||
|
||
## 10. 開發歷史(Vite 專案)
|
||
|
||
- 2026-02-07:完成 Vite 根目錄重構與舊版切除。
|
||
- 2026-02-08:完成 resilience 診斷治理與前端共用模組化。
|
||
- 2026-02-08:完成 P0 安全/穩定性硬化(本次更新)。
|
||
- 2026-02-08:完成 P1 快取查詢效率重構(index + benchmark gate)。
|
||
- 2026-02-08:完成 P2 運維自癒治理(guarded mode + manual override + runtime contract)。
|
||
- 2026-02-08:完成 round-2 hardening(LDAP URL 驗證、bounded LRU cache、circuit breaker 鎖外日誌、安全標頭、分頁邊界)。
|
||
- 2026-02-08:完成 round-3 residual hardening(staged publish、health memo、API rate limit、DB redaction、filter view env 化)。
|
||
- 2026-02-08:完成 round-4 residual consolidation(resource index 表示正規化、shared SQL fragments、型別與常數治理、atomic page status 寫入)。
|