NAPAICP 技術架構
本頁說明平台的系統設計與技術架構,內容由概念性說明逐步延伸至技術細節。
系統概觀
NAPAICP 採前後端分離架構。前端僅負責畫面呈現與使用者互動,本身不具備任何授權判斷能力;所有身分驗證、權限檢查與業務邏輯皆集中於後端服務處理。無論請求來自網頁介面或直接呼叫 API,皆須通過相同的驗證與授權流程,不存在繞過檢查的路徑。
系統的正式資料(使用者、競賽、隊伍、作品紀錄、評分結果)儲存於獨立的資料庫;參賽作品檔案則存放於另一套物件儲存服務。兩者皆僅透過後端核發、效期以分鐘計的簽名網址存取,任何未經授權的直接存取請求都會被拒絕。
系統運作流程
一個典型的操作(例如登入、查看競賽、繳交作品)會依序經過以下各層:
瀏覽器
使用者操作的網頁畫面
前端
Cloudflare Pages
純靜態頁面,不進行任何權限判斷
後端服務
Cloudflare Workers
唯一執行身分驗證與權限判斷的節點
資料庫
D1
使用者、隊伍、作品、評分等結構化資料
檔案儲存
R2
參賽作品檔案,全程私有,僅透過短效簽名網址存取
瀏覽器上傳檔案時,資料直接傳送至檔案儲存服務,不經過後端主機——後端僅負責核發限時存取憑證。
技術選型
以下皆為正式上線使用的技術,非規劃階段之選項。
前端
使用者操作的網頁介面。
React 19 + Vite + Tailwind CSS,建置為靜態檔案,部署於 Cloudflare Pages。
後端
處理業務邏輯與權限判斷的服務層。
Hono(輕量 Web 框架)搭配 Zod(型別驗證),運行於 Cloudflare Workers,於全球邊緣節點就近回應請求。
資料庫
儲存使用者、競賽、作品、成績等正式紀錄。
Cloudflare D1(基於 SQLite)。所有 schema 變更皆透過版本控管的遷移腳本執行,系統啟動時不進行任何動態異動。
檔案儲存
儲存參賽者上傳的作品檔案。
Cloudflare R2。儲存桶維持全程私有,不開放公開存取,僅透過後端核發之短效簽名網址讀寫。
狀態協調
處理多方同時操作同一資源時的一致性問題。
Cloudflare Durable Objects,用於序列化作品提交鎖定、分段上傳生命週期、速率限制計數。
交易信件
寄送註冊驗證信、密碼重設信、入圍通知信等系統信件。
Cloudflare Email Service。寄送失敗僅記錄錯誤,不影響使用者原始操作的成功與否。
設計原則
本平台實際用於決賽評選,設計決策衝突時,依下列優先順序決定:
資料完整性 — 資料不得因任何原因遭到損毀或遺失
授權 — 僅限被授權者執行被授權之操作
競賽隔離 — 一場競賽的資料不得被另一場存取
可稽核性 — 任何異動皆可追溯至操作者、時間與原因
正確性 — 系統行為須符合預期,不容許計算錯誤
可用性 — 系統須能被正常操作
效能 — 回應速度應維持在合理範圍
視覺呈現 — 介面設計應具一致性與可用性
此優先序意味著:一個回應較慢、但計算正確且異動可查核的系統,優先於一個回應快速、但可能計算錯誤或事後無法查核的系統。
安全與資料保護
競賽資料隔離
各競賽之間的資料完全獨立,互不可見。
每一筆隸屬於特定競賽的資料(表單、隊伍、作品、成績)皆綁定該競賽 id,所有查詢皆須攜帶此 id,由後端統一驗證。
評審匿名機制
評審於評分過程中僅能看見匿名代碼,無法得知隊伍或學生身分。
此限制實作於 API 回應的資料結構層級,而非僅隱藏於畫面——即使直接呼叫後端 API,亦無法取得身分資訊。
檔案私密存取
作品檔案不透過公開網址提供存取。
所有檔案存取皆透過後端核發、效期以分鐘計的簽名網址進行;儲存桶本身不具備任何公開存取設定。
稽核紀錄
權限異動、狀態變更、成績調整等敏感操作皆留有紀錄。
稽核紀錄僅能新增,不可修改或刪除;密碼等敏感欄位於寫入前即會被過濾移除。
