Skip to content

Roadmap

keanu77 edited this page Jul 3, 2026 · 1 revision

Roadmap — 產品與工程路線圖

本頁是滾動更新的方向性文件,描述 antidopingplatform(package name sports-doping-platform)的近/中/長期演進方向。所有 rationale 皆以實讀 repo 為依據(file:line 見 Tech-Debt)。這裡談「方向與取捨」,不談逐步驗收條件——可執行的收斂計畫請看 Plan,技術債細節看 Tech-Debt,本機開發/建置指令一律以 Maintenance 頁為準。

標註規則:near 主題若直接對應某條技術債的償還,會在標題後標 → 對應 Tech-Debt


Near(近期:工程健全化,先止血再談功能)

現況一句話:功能面已可用(案例庫、統計圖表、教育/測驗/TUE、SEO 預渲染皆到位),但工程安全網幾乎為零——沒有任何自動化測試、沒有 CI、資料治理靠手動腳本。near 期全部聚焦在「讓後續任何改動都不再裸奔」。

N1. 從零建立測試與 CI 安全網 → 對應 Tech-Debt(zero-tests-no-ci)

Rationale:實讀確認 root / backend / frontend 三個 package.json 皆無 jest/vitest/mocha/playwright/cypress/supertest,也無任何 test script,且無 .github/(CI 缺)、無 .husky/(pre-commit 缺)。唯一 tooling 是 frontend/eslint.config.jsbackend/test_db.jsbackend/test_route.js 是無斷言的手動連線腳本,不是測試套件。偏偏請求路徑上有高風險邏輯——casesFixed.js:56-96punishmentType regex switchstatsFixed.js:135-177$addFields/$switch/$regexMatch 禁賽時長分類——一改就可能靜默壞掉卻無人察覺。

  • 導入 Vitest + Supertest(搭配 mongodb-memory-server),先為四條掛載路由(casesFixed / statsFixed / education / tue)寫 API 整合測試,優先鎖定 punishmentType 分類與 statsFixed 禁賽時長 $switch pipeline 的邊界值
  • escapeRegexcasesFixed.js:5)與搜尋長度上限(casesFixed.js:42)寫單元測試,把已做的 ReDoS 防護釘成回歸測試,避免日後被改掉
  • 加 contract 測試比對 frontend/src/services/api.js 每個方法是否對得上真實後端路由,讓 casesAPI.create/update/deleteeducationAPI.getArticles 這類死 stub 在 CI 就現形
  • 前端用 Vitest + React Testing Library 為 CaseList 多條件篩選與 Quiz 計分寫 smoke test
  • 建立 GitHub Actions:lint → build → test 三段,PR 綠燈才可 merge,補上目前完全缺席的 CI 閘門
  • 加最小 pre-commit(lint-staged 跑 eslint)

N2. 收斂資料存取層與連線生命週期 → 對應 Tech-Debt(per-route-mongo-connections、caseid-validation-500、no-error-monitoring 部分)

Rationale:casesFixed.js:12statsFixed.js:13 各自在 module load 時 MongoClient.connect() 並 hardcode db 名 'sports-doping-db'casesFixed.js:14statsFixed.js:15),加上 server.js:160 的 Mongoose 連線,等於同一個 DB 開了三組獨立連線池;connect 前的請求一律 if(!db) return 500casesFixed.js:22statsFixed.js:29)。兩支 route 還各自複製 escapeRegexerrorResponse/connect 樣板。此外 casesFixed.js:205 直接 new ObjectId(req.params.id) 未先 isValid(全 repo 無 ObjectId.isValid),非法 id 會丟例外落到 500 而非 400/404。

  • 抽出單一共享 db 模組(一個 MongoClient pool,或直接重用 server.js 的 Mongoose 連線),讓 route 匯入而非各開各的
  • escapeRegexerrorResponse、db 名等重複片段抽成共用 util/config,消除 casesFixedstatsFixed 的樣板重複
  • /cases/:idObjectId.isValid() 前置檢查,非法 id 回 400、查無回 404,不落到 500
  • /api/healthserver.js:68)反映實際 DB 連線狀態(目前恆回 {status:"OK"},DB 掛了也看不出來)
  • 把 hardcode 的 'sports-doping-db' 收進環境變數/設定,與 MONGODB_URI 對齊
  • server.js 補 SIGTERM/SIGINT graceful shutdown(目前 serving 連線從不關閉;client.close 只出現在一次性 seed 腳本)

N3. 清理腳本沼澤、死碼與文件漂移 → 對應 Tech-Debt(seed-scripts-sprawl、orphaned-api-methods、docs-drift-dead-refs、oversized-files)

Rationale:backend/ 根目錄實測有 50 個 .js,其中約 47–48 支是一次性 add_/expansion_/phase*/fix_/update_/remove_/verify_ 腳本,與正式程式碼混放。api.js:19-21api.js:43-44 仍留 casesAPI.create/update/deleteeducationAPI.getArticles/getArticle 死 stub,但 casesFixed 只有 GET、education.js 也無 /articles。文件已漂移:README.md:88-93 記載 POST/PUT/DELETE /api/cases/api/cases/compare/api/education/articles 等不存在端點;CLAUDE.md:86 仍描述 mockData.jsroutes/cases.jsroutes/stats.jsbackend/server.js,但這四者已在 commit 7eab93e 全數刪除(實測 MISSING)。

  • 把約 47 支 seed/import/fix 腳本移進 backend/scripts/ 歸檔,或整併成單一具冪等性的 seed CLI,與正式路由程式碼分離
  • 刪除 api.js 中無對應後端的死 stub(cases 寫入、education articles),或明確標記為待實作
  • 重寫 README.md API 章節,只列真實存在端點;修正結構圖(把 server.js 畫進 backend/ 是錯的,真正入口是根 server.js
  • 更新 CLAUDE.md:86 把已刪除的 mockData.jscases.jsstats.jsbackend/server.js 敘述清掉,止住 drift
  • 統一 quiz 內容單一來源:frontend/src/data/quiz.js(Quiz 頁用)與 backend/data/quizzes.json(Education 頁走 API)目前是兩份會各自漂移的題庫,需擇一為 SoT
  • 刪除 backend/test_db.jsbackend/test_route.js 兩支臨時腳本(易被誤認為測試)
  • 修正或移除 backend/package.jsonmain/start/dev——皆指向已不存在的 backend/server.js

Mid(中期:平台信譽、內容維運與學習體驗)

M1. 案例資料治理與可追溯性(平台信譽核心) → 部分對應 Tech-Debt(fabricated-case-data)

Rationale:這是教育型禁藥平台的命脈,也是實讀後最嚴重的風險。backend/loadCompleteDatabase.js:124-166 用 14 處 Math.random() 從姓名/國家/物質池隨機拼出案例(athleteName: \${firstName} ${lastName}`eventBackground: `${year}年${event}期間藥檢呈陽性反應,違反了反禁藥規則。`),真實硬編案例僅 3 筆(famousCases:Ben Johnson、Lance Armstrong、Maria Sharapova),totalCases=166 → 約 163 筆為合成。案例真實性確認清單.md(233 行、標生成日 2025/8/23、185 案)本身就在列「虛構案例—需要移除的假案例」,含 57 個 ❓ 待驗證項。Case.js:70sourceLinks 是選填、schema 無「已查核」狀態欄位。運動禁藥案例資料庫_完整清單.md` 標總案例數 171,與清單的 185 對不上。(Pass 2 註記:live production DB 現況無法從 repo 確認,但生成器仍在、審計文件仍列待驗證項、且無自動守則。)

  • Case schema 升級:sourceLinks 改必填、每案至少一條可驗證來源,並新增 verificationStatus(已查核/待查核/存疑)與 lastVerifiedAt 欄位
  • 在 CaseDetail 前端顯示「資料來源/最後查核日/查核狀態」徽章,讓使用者自行判斷可信度
  • 寫一支可排程的來源連結健檢腳本(偵測 404/失效連結),取代目前一次性的 verify_/remove_ 腳本
  • 以真實性清單為依據批次下架或補證存疑案例,把清洗流程沉澱成可重跑 pipeline
  • 建立去重與案例數對帳機制,解決 171 vs 185 的計數落差,作為每次匯入後的驗收關卡
  • 移除/隔離 loadCompleteDatabase.js 亂數生成器(屬破壞性資料操作,需 migration + 雙重確認,見 Plan

M2. 身分驗證與內容管理後台

Rationale:實讀確認全站無任何 auth(backend/frontend 均無 jwt/bcrypt/passport/req.user;.env.example 雖列 JWT_SECRET 但程式從未使用)。casesFixed 只有 GET,內容只能靠直連 DB 的 seed 腳本更動——非工程人員(如醫療內容審稿者)完全無法維護。api.js:19-21 早已預留 create/update/delete,等於後台被規劃但沒做。tue.js 更把 tueContenttue.js:5-273)+wadaSubstancestue.js:274-444)共約 440 行硬寫在路由檔內(全檔 503 行),改一個字都要動程式碼、重部署。

  • 實作 JWT 登入與角色權限(env 已備 JWT_SECRET),先支援 editor / admin 兩種角色
  • 補齊 case 的驗證後 POST/PUT/DELETE 端點,讓 api.js 既有 stub 接上真實後端並加操作稽核日誌
  • tue.js 內嵌內容抽到 backend/data/tue-content.json,比照 education.js:6-8 的 JSON 資料模式,讓內容可被後台編輯
  • 為案例、題庫、TUE 內容提供輕量 CMS 介面(表單化 CRUD + 來源欄位驗證)
  • 所有寫入端點納入 schema 驗證與分級 rate limit(現有 /api 為 200 req/15min,server.js:52-59

M3. 學習體驗與國際化深化

Rationale:現有教育功能(Education、Quiz、TUE、ProhibitedList)皆為靜態內容、無使用者狀態:Quiz.jsx 讀本地 frontend/src/data/quiz.js、無成績或進度保存;README 宣傳的「案例比較」實際無 /api/cases/compare 後端支撐。全站 UI 皆繁中,但 WADA 禁用清單與案例本質是國際性主題,英文化能大幅擴大受眾與 SEO(frontend/scripts/prerender.js 已把 SEO 基礎建好,具備擴充條件)。

  • 為 Quiz/Education 加入使用者進度與成績保存(可先 localStorage、後接帳號),支援錯題複習
  • 實作 README 已宣傳但缺席的案例比較功能(前端 UI + 後端 compare 端點)
  • 案例時間軸與跨國別/項目的互動式視覺化,延伸現有 Statistics 的 Chart.js 基礎
  • 導入 i18n 與英文版內容,觸及國際運動員、教練與研究者
  • 無障礙(a11y)盤點:鍵盤導覽、對比度、ARIA

Long(長期:權威性、智慧化與營運成熟度)

L1. 權威資料同步與開放生態

Rationale:目前案例與禁用清單是人工策展的靜態快照(prohibitedList.js 以 inline 年份註記維護,如 :131 Tramadol 2024 新增、:174-175 CO M1.4 2026 新增),tue.js:23 引用 2023 ISTUE,而 WADA 禁用清單每年更新——長期靠手動 seed 腳本無法維持時效與權威性。server.js:28-35 刻意放行 *.blogspot.com/*.blogger.com iframe(by-design 嵌入意圖)顯示已有被外部網站嵌入的使用情境,具備做成可嵌入教育元件的生態基礎。

  • 建立自權威來源(WADA/USADA/各國 ADO)的半自動化資料匯入與年度禁用清單版本化機制
  • 對外開放唯讀公開 API 與可嵌入 widget,讓部落格/教育單位引用案例與 TUE 查詢
  • 重大新案例的訂閱/通知機制
  • 禁用清單與 TUE 標準的版本歷史,讓使用者可查特定年度規則
  • 與運動組織/學校建立內容合作與引用授權

L2. 智慧化檢索與臨床決策支援

Rationale:現行搜尋是 casesFixed.js:99-109 的 regex $or 多欄比對,屬關鍵字層級;教育與 TUE 內容豐富但彼此孤立。平台擁有結構化案例(Case.js 的 WADA S0–S9/M1–M3/P1 分類)與 TUE 藥物適用性檢查(tue.js POST /checktue.js:470),是做語意檢索與決策支援的良好基底,且能對接經營者(運動醫學醫師)的專業場景。

  • 對案例與 TUE 內容建立語意/向量檢索(RAG),支援自然語言問答式查詢
  • 個人化學習路徑:依使用者答題弱點推薦案例與教育單元
  • 面向隊醫/防護員的 TUE 決策支援工具,串接現有藥物適用性檢查邏輯
  • 面向單項運動組織的分析儀表板,延伸 statsFixed 的聚合能力
  • 多租戶化,讓不同運動組織擁有各自的案例集與教育內容

L3. 營運成熟度與可靠性 → 延伸 Tech-Debt(no-error-monitoring)

Rationale:實讀確認可觀測性僅止於 console.*server.js 12 處、statsFixed.js 11 處、casesFixed.js 5 處),無結構化日誌、無錯誤追蹤(Sentry 等)、無指標;DB 無備份/DR 敘述。工程基礎其實不差(compression、projection、statsFixedCache-Control 1hr、rate limit、非 root Docker、/api/version build 戳記皆已到位),但缺的是上線後的觀測與韌性,隨著加入 auth/寫入功能與使用者資料,這塊會成為瓶頸。

  • 導入結構化日誌(如 pino)與錯誤追蹤(Sentry),取代散落的 console.*
  • 建立 MongoDB 定期備份與還原演練,補上目前缺席的 DR
  • 加入基本指標與告警(uptime、API 延遲、5xx 率),對接 Zeabur 部署
  • 在導入使用者資料後補做正式安全審查與隱私/個資合規盤點
  • 建立效能預算與定期負載測試,驗證 regex 搜尋與 stats 聚合在資料成長後的表現

相關頁面:Introduction · Plan · Tech-Debt · Maintenance · Home

Clone this wiki locally