-
Notifications
You must be signed in to change notification settings - Fork 0
Roadmap
本頁是滾動更新的方向性文件,描述 antidopingplatform(package name
sports-doping-platform)的近/中/長期演進方向。所有 rationale 皆以實讀 repo 為依據(file:line 見 Tech-Debt)。這裡談「方向與取捨」,不談逐步驗收條件——可執行的收斂計畫請看 Plan,技術債細節看 Tech-Debt,本機開發/建置指令一律以 Maintenance 頁為準。標註規則:near 主題若直接對應某條技術債的償還,會在標題後標
→ 對應 Tech-Debt。
現況一句話:功能面已可用(案例庫、統計圖表、教育/測驗/TUE、SEO 預渲染皆到位),但工程安全網幾乎為零——沒有任何自動化測試、沒有 CI、資料治理靠手動腳本。near 期全部聚焦在「讓後續任何改動都不再裸奔」。
Rationale:實讀確認 root / backend / frontend 三個 package.json 皆無 jest/vitest/mocha/playwright/cypress/supertest,也無任何 test script,且無 .github/(CI 缺)、無 .husky/(pre-commit 缺)。唯一 tooling 是 frontend/eslint.config.js。backend/test_db.js、backend/test_route.js 是無斷言的手動連線腳本,不是測試套件。偏偏請求路徑上有高風險邏輯——casesFixed.js:56-96 的 punishmentType regex switch、statsFixed.js:135-177 的 $addFields/$switch/$regexMatch 禁賽時長分類——一改就可能靜默壞掉卻無人察覺。
- 導入 Vitest + Supertest(搭配 mongodb-memory-server),先為四條掛載路由(
casesFixed/statsFixed/education/tue)寫 API 整合測試,優先鎖定punishmentType分類與statsFixed禁賽時長$switchpipeline 的邊界值 - 為
escapeRegex(casesFixed.js:5)與搜尋長度上限(casesFixed.js:42)寫單元測試,把已做的 ReDoS 防護釘成回歸測試,避免日後被改掉 - 加 contract 測試比對
frontend/src/services/api.js每個方法是否對得上真實後端路由,讓casesAPI.create/update/delete、educationAPI.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:12 與 statsFixed.js:13 各自在 module load 時 MongoClient.connect() 並 hardcode db 名 'sports-doping-db'(casesFixed.js:14、statsFixed.js:15),加上 server.js:160 的 Mongoose 連線,等於同一個 DB 開了三組獨立連線池;connect 前的請求一律 if(!db) return 500(casesFixed.js:22、statsFixed.js:29)。兩支 route 還各自複製 escapeRegex/errorResponse/connect 樣板。此外 casesFixed.js:205 直接 new ObjectId(req.params.id) 未先 isValid(全 repo 無 ObjectId.isValid),非法 id 會丟例外落到 500 而非 400/404。
- 抽出單一共享 db 模組(一個 MongoClient pool,或直接重用
server.js的 Mongoose 連線),讓 route 匯入而非各開各的 - 把
escapeRegex、errorResponse、db 名等重複片段抽成共用 util/config,消除casesFixed與statsFixed的樣板重複 - 在
/cases/:id加ObjectId.isValid()前置檢查,非法 id 回 400、查無回 404,不落到 500 - 讓
/api/health(server.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-21、api.js:43-44 仍留 casesAPI.create/update/delete 與 educationAPI.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.js、routes/cases.js、routes/stats.js、backend/server.js,但這四者已在 commit 7eab93e 全數刪除(實測 MISSING)。
- 把約 47 支 seed/import/fix 腳本移進
backend/scripts/歸檔,或整併成單一具冪等性的 seed CLI,與正式路由程式碼分離 - 刪除
api.js中無對應後端的死 stub(cases 寫入、education articles),或明確標記為待實作 - 重寫
README.mdAPI 章節,只列真實存在端點;修正結構圖(把server.js畫進backend/是錯的,真正入口是根server.js) - 更新
CLAUDE.md:86把已刪除的mockData.js/cases.js/stats.js/backend/server.js敘述清掉,止住 drift - 統一 quiz 內容單一來源:
frontend/src/data/quiz.js(Quiz 頁用)與backend/data/quizzes.json(Education 頁走 API)目前是兩份會各自漂移的題庫,需擇一為 SoT - 刪除
backend/test_db.js、backend/test_route.js兩支臨時腳本(易被誤認為測試) - 修正或移除
backend/package.json的main/start/dev——皆指向已不存在的backend/server.js
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:70的sourceLinks 是選填、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)
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 更把 tueContent(tue.js:5-273)+wadaSubstances(tue.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)
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
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 標準的版本歷史,讓使用者可查特定年度規則
- 與運動組織/學校建立內容合作與引用授權
Rationale:現行搜尋是 casesFixed.js:99-109 的 regex $or 多欄比對,屬關鍵字層級;教育與 TUE 內容豐富但彼此孤立。平台擁有結構化案例(Case.js 的 WADA S0–S9/M1–M3/P1 分類)與 TUE 藥物適用性檢查(tue.js POST /check,tue.js:470),是做語意檢索與決策支援的良好基底,且能對接經營者(運動醫學醫師)的專業場景。
- 對案例與 TUE 內容建立語意/向量檢索(RAG),支援自然語言問答式查詢
- 個人化學習路徑:依使用者答題弱點推薦案例與教育單元
- 面向隊醫/防護員的 TUE 決策支援工具,串接現有藥物適用性檢查邏輯
- 面向單項運動組織的分析儀表板,延伸
statsFixed的聚合能力 - 多租戶化,讓不同運動組織擁有各自的案例集與教育內容
Rationale:實讀確認可觀測性僅止於 console.*(server.js 12 處、statsFixed.js 11 處、casesFixed.js 5 處),無結構化日誌、無錯誤追蹤(Sentry 等)、無指標;DB 無備份/DR 敘述。工程基礎其實不差(compression、projection、statsFixed 的 Cache-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
乾淨運動從你我開始 · 教育用途,案例資料經真實性查核 · 回首頁