TECHNICAL & PRODUCT DOCUMENT
架構與流程說明書
車安手帳 v1.2 的產品定位、系統架構、Cloudflare 雲端部署、資料模型、核心演算法、資安設計、風險評估、介面規範、更新上傳工作流程與路線圖。各章可收合,點上方章節可快速跳轉。
01產品概觀與 v1.2 更新
「車安手帳」給一般家庭與通勤族使用,用來記錄加油、保養與各項費用,自動提醒,並算出真正的養車成本。設計原則是「三秒內記完一筆」與「打開就知道車況」。
v1.2 改了什麼(2026-10-22)
- 正式上線:部署到 Cloudflare,網址
https://car.wen8604.com;舊檔名網址自動 301 轉到新網址。 - 可安裝、可離線:Web App Manifest+Service Worker,加入主畫面後像 App 一樣開啟,也解決 iPhone Safari 7 天清除資料的問題。
- 資安強化:伺服器端安全標頭(HSTS、防點擊劫持、Permissions-Policy),CSP 改用 SHA-256 雜湊白名單,移除 script 的 'unsafe-inline'。
- 網站更新時間:每次部署自動蓋上台北時間,頁尾、說明書、Service Worker 與 version.json 同步。
- 獨立訪客統計:匿名「不重複人數」(累計與今日),排除機器人,不收集 IP 與紀錄內容。
- 友善模式細部設定:新增「加寬行距字距」「加大按鈕 56px」「加粗焦點外框」「文字加粗」與一鍵恢復建議值。
- 內容補強:保養小百科(每個項目的原因與徵兆)、年度報表、列印保養履歷(賣車/過戶用)、合併匯入(家人資料合在一起)。
- 穩定性:多分頁同步後舊的「復原」自動失效,不會蓋掉別頁的新資料;編號改用加密亂數。
v1.1 改了什麼
- 資安:匯入資料白名單淨化、CSV 公式注入防護、內容安全政策(CSP)、移除 Unicode 偽裝字元。
- 資料安全:資料版本與自動遷移、刪除可「復原」、匯入/清除前自動快照、30 天備份提醒、多分頁同步。
- 介面:手機返回鍵關閉表單、未儲存內容確認、焦點管理、圖表附螢幕閱讀器資料表、加油紀錄搜尋。
- 功能:其他費用(停車、保險、稅金…)、每公里總成本、日期型提醒、匯出 .ics 行事曆、送出前合理性檢查。
02系統架構
v1.2 起分成兩層:前端仍是單一 HTML 檔(離線也能用),外面多一層 Cloudflare Worker 負責託管、安全標頭與匿名訪客統計,詳見第 15 章。
單一 HTML 檔、零外部相依。資料流為單向:使用者操作 → 驗證 → 更新 State → 存檔 → 重新渲染。所有外部資料(localStorage、匯入檔)一律先經過淨化層。
字串模板產生 HTML,只渲染目前頁面;所有使用者文字輸出前一律經過 esc() 跳脫。
Hash 路由、ACT 動作表(含錯誤攔截)、底部抽屜表單(History API、未儲存確認、焦點回復)、確認框、可復原 Toast。
無副作用純函式,可單獨測試。
normalize():欄位白名單、型別與範圍限制、id/日期格式驗證、重複 id 重編、孤兒紀錄剔除、舊版資料自動遷移。
localStorage(wen8604.vehiclelog.v1)+快照(wen8604.vehiclelog.v1.bak);storage 事件做多分頁同步;啟用 navigator.storage.persist() 降低被清除機率。
主題與友善模式轉成 <html data-*> 與 CSS 變數,首屏前套用,避免閃爍;友善模式 key wen8604-friendly-mode 與網站群共用。
03資料模型(schema 2)
| 欄位 | 型別/限制 | 說明 |
|---|---|---|
| Vehicle 車輛(上限 50 台) | ||
| id / type | 英數 4–32 字 / car|moto | 唯一碼、車種 |
| name / plate / brand | 16 / 10 / 30 字 | 暱稱、車牌(自動大寫)、廠牌車型 |
| odo0 / since | 0–3,000,000 / YYYY-MM-DD | 建檔里程與日期 |
| fuel / color | 92|95|98|柴油 / #RRGGBB | 常用油品、插圖顏色 |
| FuelRecord 加油 | ||
| date / odo | 日期 / 整數 | 加油日期、當下里程 |
| liters / price / total | 0–500 / 0–1000 / 整數 | 任兩項自動推算第三項 |
| full | boolean | 是否加滿(油耗關鍵) |
| ftype / station / note | 列舉 / 40 / 200 字 | 油品、加油站、備註 |
| MaintRecord 保養 | ||
| items / other | 代碼陣列 ≤20 / 60 字 | 保養項目、自訂項目 |
| cost / shop / note | 整數 / 40 / 200 字 | 費用、保養廠、備註 |
| Expense 其他費用(新) | ||
| cat / amount | 8 類列舉 / 整數 | 停車、過路、洗車、保險、稅金、罰單、配件、其他 |
| odo / note | 選填 / 200 字 | 當下里程、備註 |
| DateReminder 日期提醒(新) | ||
| name / date / repeat | 20 字 / 日期 / year|none | 每年重複者「已處理」後自動順延一年 |
| 其他 | ||
| rules[vid][key] | {km ≤300000, mo ≤240, on} | 保養週期;僅接受該車種的項目代碼 |
| meta | {lastBackup, created} | 備份提醒依據 |
| schema | 2 | v1.0 資料(無 schema)讀取時自動升級,新欄位補空陣列 |
04核心演算法與資料檢查
油耗:滿油法
每公里總成本(TCO)
保養到期:雙條件、先到先算
送出前合理性檢查
- 里程先後:較早日期的紀錄不應有較高里程(同時比對加油與保養)。
- 油箱容量:單次加油超過汽車 100 L/機車 20 L 提示確認。
- 油耗範圍:汽車 4–40、機車 12–90 km/L 以外提示「可能漏記一次加油」。
- 金額誤差:單價 × 公升 與金額相差超過 3% 提示。
- 檢查只提醒、不阻擋,使用者確認後仍可儲存(避免誤判造成無法記錄)。
05使用與資料流程
- 建立車輛選車種、填目前里程;自動套用保養週期。建議加入「強制險到期」日期提醒。
- 日常記錄加油(勾選加滿)、保養(勾選項目)、其他費用(停車、稅金…)。
- 系統檢查送出前做合理性檢查;儲存後自動重算油耗、成本與提醒。
- 處理提醒一鍵「登記已保養」或「已處理,排明年」;可匯出 .ics 放進手機行事曆。
- 備份每 30 天提醒匯出 JSON;誤刪 6 秒內可復原;匯入/清除前自動快照。
操作捷徑
- 手機:底部中央「+」→ 加油/保養/費用/車輛。
- 電腦:左側欄頂端快速按鈕。
- 任何頁面右上的車輛膠囊可切換車輛;手機返回鍵會先關閉開啟中的表單。
06資安設計
v1.2 伺服器端防護
- HTTP 安全標頭:HSTS 一年、X-Content-Type-Options、X-Frame-Options DENY+CSP frame-ancestors 'none'(meta 版 CSP 無法防點擊劫持,必須由伺服器送出)、Permissions-Policy 關閉相機/麥克風/定位/付款、COOP/CORP same-origin。
- CSP 雜湊白名單:部署時計算每段 inline script 的 SHA-256,伺服器只允許這幾段執行;就算有人注入 <script>,雜湊不符也不會執行。
- 連線白名單:connect-src 只允許同網域(只有訪客統計會用到),仍無法把資料送到別的網站。
- 統計 API 防濫用:只接受同源 POST、JSON、256 bytes 以內;機器人 UA 不計;同一來源每天最多新增 30 位訪客,防止灌票。
- 部署防呆:deploy.ps1 會檢查帳號、網域、Durable Object 設定,並先跑自動測試,任何一項不符就停止上傳。
- CSV 公式注入:以 = + − @ Tab 開頭的文字加上 ' 前綴,避免 Excel 執行公式或外連。
- 原型污染:rules 只讀取「自有屬性」且鍵名必須在保養項目白名單中;車輛 id 只允許英數,杜絕 __proto__。
- Unicode 偽裝:移除控制字元與雙向覆寫字元(U+202A–202E、U+2066–2069),避免畫面顯示與實際內容不一致。
- 匯入限制:檔案上限 5 MB、車輛 50 台、每類紀錄 20,000 筆,避免惡意大檔拖垮瀏覽器。
- Referrer:no-referrer(meta 與 HTTP 標頭雙重設定),連結不帶出任何頁面資訊。
- 隱私:車牌屬個人資料,僅存本機;匯出檔請妥善保管,不要公開分享。
07商業化風險評估與修復紀錄
以下為 v1.0 → v1.1 的完整稽核結果。等級依「發生機率 × 影響」評定。
| 類別 | 問題 | 等級 | 處置 | 狀態 |
|---|---|---|---|---|
| 資安 | 匯入的 JSON 未驗證,惡意 id/日期可注入 HTML(儲存型 XSS) | 高 | normalize() 白名單淨化,id/日期格式驗證,輸出跳脫 | 已修復 |
| 資安 | 匯出 CSV 可被 Excel 當公式執行(CSV Injection) | 中 | 危險開頭字元加 ' 前綴 | 已修復 |
| 資安 | 匯入物件含 __proto__ 等鍵可能造成原型污染 | 中 | 只讀自有屬性、鍵名白名單 | 已修復 |
| 資安 | 沒有 CSP,若被注入可外連竊取資料 | 中 | 加入嚴格 CSP,禁止一切對外連線 | 已修復 |
| 資安 | Unicode 雙向控制字元可偽裝顯示內容 | 低 | 輸入時移除控制與 Bidi 字元 | 已修復 |
| 資料 | 沒有資料版本,未來欄位變更會壞資料 | 高 | schema 版本+自動遷移 | 已修復 |
| 資料 | 誤刪無法復原 | 高 | 刪除後 6 秒可復原;破壞性操作前自動快照 | 已修復 |
| 資料 | Safari 對 7 天未互動的網站會清除本機儲存 | 高 | 30 天備份提醒、persist();v1.2 可加入主畫面(PWA 不受 7 天限制) | v1.2 已解決 |
| 資料 | 多分頁同時開啟互相覆蓋 | 中 | storage 事件即時同步畫面 | 已緩解 |
| 資料 | 儲存空間滿或無痕模式時靜默失敗 | 中 | 明確錯誤訊息與處理建議 | 已修復 |
| 資料 | 里程輸錯、漏記加油造成油耗異常 | 中 | 送出前四項合理性檢查 | 已修復 |
| 介面 | 手機返回鍵直接離開頁面而非關閉表單 | 中 | History API 整合 | 已修復 |
| 介面 | 點背景誤關表單,輸入內容遺失 | 中 | 未儲存內容確認 | 已修復 |
| 介面 | 關閉表單後鍵盤焦點遺失 | 低 | 焦點回到觸發元素或頁面標題 | 已修復 |
| 介面 | 圖表無法被螢幕閱讀器讀取 | 中 | 每張圖附隱藏資料表 | 已修復 |
| 介面 | 紀錄多時難以查找 | 低 | 加油搜尋:不重繪畫面,中文輸入法不中斷 | 已修復 |
| 介面 | 刪除確認框預設焦點在「刪除」,Enter 易誤觸 | 低 | 危險操作預設焦點改為「取消」 | 已修復 |
| 架構 | 單一畫面錯誤會造成整頁空白 | 中 | 錯誤邊界+備份入口 | 已修復 |
| 功能 | 只算油錢,看不到真實養車成本 | 中 | 其他費用+每公里總成本 | 已修復 |
| 功能 | 保險、驗車、稅金等日期義務沒有提醒 | 中 | 日期型提醒,每年自動順延 | 已修復 |
| 功能 | 提醒只有打開 App 才看得到 | 中 | 匯出 .ics(提前 7 天通知);推播需 PWA | 已緩解 |
| 法遵 | 保養週期非原廠數據可能產生爭議 | 中 | 免責聲明、週期可自訂 | 已處理 |
| 架構 | 單檔無 Service Worker,無法安裝與推播 | 中 | Cloudflare HTTPS 託管+manifest+Service Worker | v1.2 已完成 |
| 商業 | 無帳號、跨裝置同步與付費機制 | 高 | 後端+端對端加密同步+訂閱 | 待 v2.0 |
| 相容 | 依賴較新的 CSS 與 dialog | 低 | Chrome/Edge 111+、Safari 16.4+、Firefox 113+ | 已標示 |
08介面與響應式規劃
| 裝置 | 寬度 | 導覽 | 表單 | 版面 |
|---|---|---|---|---|
| 手機 | < 640px | 底部分頁列+中央+鍵 | 底部抽屜,返回鍵可關閉 | 單欄、KPI 2×2 |
| 平板 | 640–899px | 底部分頁列 | 置中對話框 | 內容 ≥720px 時卡片雙欄 |
| 電腦 | ≥ 900px | 左側固定側欄 | 置中對話框 | KPI 4 欄、主圖左右排列 |
- Container Query:卡片依自身容器寬度排版,平板直橫向都自然。
- 頁面不冗長:每頁以分段切換;長列表按月/年收合,預設只展開最近的。
- 切換絲滑:0.34 秒方向性滑入;收合使用原生 details 搭配高度動畫。
- 防呆:未儲存確認、送出中按鈕停用防重複送出、刪除可復原。
- 觸控目標至少 44px(友善模式 48px),所有圖示按鈕都附文字標籤。
09深色模式與友善模式
主題
跟隨系統/淺色/深色。深色採規範色:底 #0E1522、卡片 #17202F、文字 #EEF2F8、連結 #8FBCF2;插畫自動切換夜景。
友善模式細部設定
- 字級:115%/125%(預設)/140%,全站 rem 等比放大,行高 1.9。
- 高對比:底 #10212C、文字 #E8F1F5(對比 14.4),連結與主按鈕改金色。
- 減少動態:關閉轉場與插畫動畫,也遵守系統 prefers-reduced-motion。
- 連結底線:只套用內文連結,不影響導覽列。
- 加寬行距與字距(v1.2):行高 2.1、字距 .05em,適合長輩與閱讀障礙者。
- 加大按鈕(v1.2):觸控目標由 48px 加大到 56px。
- 加粗焦點外框(v1.2,預設開):4px 外框+光暈,鍵盤操作時看得清楚。
- 文字加粗(v1.2):字重 500,次要說明字改用主文字顏色,提高可讀性。
- 所有選項存在 App 設定中;開關鍵
wen8604-friendly-mode與網站群共用,說明書會讀同一份設定。
10效能策略
- 單檔零相依:一次請求完成載入,無框架、無外部字型。
- 按需渲染:只產生目前頁面的 DOM。
- 搜尋不重繪:以顯示/隱藏既有列完成,輸入不卡頓、注音輸入法不中斷。
- SVG Sprite:圖示定義一次、重複使用;插畫為向量。
- 事件委派:監聽器數量固定,不隨紀錄筆數增加。
- 圖表依實際寬度繪製,視窗變動節流重繪。
- content-visibility:收合區塊延遲排版。
- 容量估算:一筆約 200 bytes,5 MB 約可存 2 萬筆以上,一般家庭可用數十年。
11隱私、備份與資料保存
- 資料只存在瀏覽器 localStorage,不上傳、無追蹤碼;CSP 只允許連回自己的網域(僅訪客統計使用,內容只有一組匿名隨機編號)。
- 網址不同=資料不同:本機檔案、car.wen8604.com、其他網址各自獨立,搬家請用匯出/匯入。
- 可能遺失的情況:清除瀏覽資料、無痕模式、換裝置、Safari 7 天未開啟網站(加入主畫面的網頁 App 不受此限)。
- 防護:30 天未備份提醒、persist() 持久化請求、破壞性操作前快照、刪除可復原。
- CSV 匯出含 BOM,Excel 開啟中文不亂碼;.ics 可匯入 Google/Apple 行事曆。
- 「匯入並取代」會取代目前資料;「合併匯入」(v1.2)只新增沒有的紀錄,相同編號會略過。兩者都會先顯示筆數並自動保留快照。
12商業化路線圖
階段規劃
- v1.2 可安裝版(已完成 2026-10-22):Cloudflare HTTPS 託管、Web App Manifest、Service Worker 離線快取、匿名訪客統計、更新時間自動標示。
- v1.3 提醒升級:Web Push 推播(需伺服器)、收據拍照 OCR 自動填入。
- v2.0 雲端版:帳號、家人共用車輛、端對端加密同步(伺服器看不到明文)、衝突合併。
- v2.x 商業模式:免費版(單車、本機)+訂閱版(多車、同步、報表 PDF、提醒推播);可與保養廠合作預約。
上線前必備
- 隱私權政策與服務條款(個人資料保護法)、免責聲明。
- 錯誤回報機制(需使用者同意;CSP 已允許同網域連線,可直接加在 Worker)。
- 跨瀏覽器實機測試與無障礙檢測(WCAG 2.1 AA)。
文件與程式分離
本說明書獨立為 guide.html(原檔名 架構與流程說明書.html 會自動轉址),與 App 放在 cloudflare/public/;App 側欄與頂欄的「說明」直接開啟此檔。App 體積因此縮小、首屏更快,文件也可單獨列印或分享給開發與營運團隊。
開發約定
- 新增頁面:在
VIEWS註冊,並在導覽加上 data-nav。 - 新增動作:在
ACT加函式,按鈕標 data-act。 - 新增欄位:先改
normalize()並提升 SCHEMA,再改畫面。 - 計算邏輯一律寫成純函式放在 Engine 區。
- 改了任何 inline script 後,一定要經過
tools/build.mjs(上傳批次檔會自動執行),否則新雜湊不在 CSP 白名單,腳本會被瀏覽器擋下。
13測試與品質檢查清單
- 匯入含 <img onerror> 的惡意 JSON:畫面不執行、文字被淨化
- 匯出 CSV 後以 Excel 開啟:= 開頭的備註不會變成公式
- 刪除紀錄 → 按「復原」:資料完整回來
- 匯入/清除後到設定「還原快照」:回到操作前狀態
- 開兩個分頁,在 A 新增紀錄:B 自動同步
- 手機開啟表單後按返回鍵:只關閉表單,不離開頁面
- 表單輸入一半點背景:出現「放棄變更?」確認
- 輸入比上次低的里程、超大公升數:送出前出現提醒
- 注音輸入法在搜尋框連續輸入:不中斷、不跳字
- 友善模式+深色+手機寬度 360px:版面不破、無水平捲動
- 鍵盤 Tab 走完所有頁面:焦點外框清楚可見
- 螢幕閱讀器讀取圖表:可讀到每月金額與每段油耗
- (v1.2)離線(飛航模式)重新開啟網站:仍可開啟並新增紀錄
- (v1.2)同一裝置一天內重新整理多次:今日訪客只 +1
- (v1.2)其他網站嵌入 iframe:瀏覽器拒絕顯示
- (v1.2)A 分頁刪除後、B 分頁新增,再回 A 按「復原」:提示無法復原,不會蓋掉 B 的資料
- (v1.2)列印保養履歷:只印出履歷表,不含選單與按鈕
- (v1.2)合併匯入同一份備份兩次:第二次新增 0 筆
- (v1.2)自動測試 node --test:全部通過才允許上傳
14常見問題
為什麼油耗一直顯示「—」?
需要至少兩筆勾選「加滿」的紀錄,第一次加滿只是起點。
系統說我油耗異常?
通常是中間漏記一次加油,或里程輸入錯誤。確認無誤可直接選「仍要儲存」。
機油用全合成,週期可以拉長嗎?
可以,到「保養與費用 → 週期」依原廠或機油規格調整。
換手機怎麼搬資料?
舊手機「設定 → 匯出 JSON」,把檔案傳到新手機後「匯入 JSON」。
提醒可以推播嗎?
目前可匯出 .ics 加入手機行事曆,由行事曆提前 7 天通知;推播規劃於 v1.3。
怎麼安裝到手機?
iPhone 用 Safari 開啟 car.wen8604.com →「分享」→「加入主畫面」;Android 用 Chrome 會跳出「安裝」,或從選單選「安裝應用程式」。
以前用本機檔案記的資料,網站上看不到?
本機檔案與網站是不同的「網址」,資料彼此獨立。請在舊的檔案「設定 → 匯出 JSON」,再到網站「匯入並取代」。
訪客統計會知道我是誰嗎?
不會。只用一組隨機產生的匿名編號判斷「是不是同一個人」,伺服器只存它加鹽後的雜湊值,不存 IP、車牌或任何紀錄。
15Cloudflare 雲端架構
採用 Cloudflare Workers + 靜態資產(Assets)+ Durable Object,與 wen8604 管理站同一套做法,同一個 Cloudflare 帳號、同一套上傳批次檔流程。
index.html(App)、guide.html(本說明書);Service Worker 快取,離線可用;紀錄只存在 localStorage。
自訂網域 car.wen8604.com,關閉 workers.dev 與預覽網址。只接受正確網域;GET/HEAD 以外的請求一律 405;回應加上安全標頭與雜湊版 CSP;舊檔名 301 轉址。
單一實例、強一致的匿名訪客計數;自己產生隨機鹽,3 天前的去重資料自動清除。
HTML 不快取(no-cache,保證看到最新版);sw.js、manifest、version.json 不快取;其他檔案 1 小時。
檔案結構
汽機車保養/
├─ 更新上傳雲端版.cmd ← 雙擊:建置→測試→上傳
├─ 檢查建置.cmd ← 雙擊:建置→測試→乾跑(不上傳)
├─ 本機預覽.cmd ← 雙擊:在 http://localhost:8787 預覽
└─ cloudflare/
├─ wrangler.jsonc ← 帳號、網域、Durable Object 設定
├─ deploy.ps1 ← 上傳主程式(含防呆檢查)
├─ test.mjs ← 自動測試(node --test)
├─ 部署紀錄.md ← 每次上傳自動追加一行
├─ src/worker.mjs ← Worker+Visits 計數器
├─ src/build-info.json ← 版本、更新時間、CSP 雜湊(自動產生)
├─ tools/build.mjs ← 蓋更新時間、算雜湊
├─ tools/icons.mjs ← 產生主畫面圖示 PNG
└─ public/ ← 上線的網站檔案
├─ index.html guide.html sw.js manifest.webmanifest
└─ icon.svg icon-180.png icon-512.png robots.txt sitemap.xml version.json
API
| 方法與路徑 | 用途 | 回應 |
|---|---|---|
GET /api/visit | 讀取統計(不計數);管理站巡檢也用這支 | {total, today, since, days[], updated} |
POST /api/visit | 每台裝置每天最多呼叫一次,body {"v":"匿名編號"} | 同上,另含 counted |
GET /version.json | 目前上線版本與更新時間 | {app, version, updated} |
16更新上傳工作流程
- 修改只改
cloudflare/public/內的檔案(App 是 index.html,說明書是 guide.html)。改前可先複製一份到「_更新前備份_日期」資料夾。 - 本機預覽雙擊「本機預覽.cmd」,用瀏覽器開 http://localhost:8787 檢查;統計 API 在本機也能測。
- 檢查建置雙擊「檢查建置.cmd」:蓋更新時間、重算 CSP 雜湊、跑自動測試,最後做 wrangler 乾跑(不會上傳)。
- 上傳雙擊「更新上傳雲端版.cmd」:同樣先建置與測試,全部通過才上傳;結果寫進
cloudflare/部署紀錄.md。 - 上線確認開 https://car.wen8604.com:頁尾「最後更新」是剛剛的時間、訪客數有顯示;version.json 的時間一致。已安裝的手機下次開啟會跳「網站有新版本」。
deploy.ps1 防呆檢查(任何一項不符就停止)
- Worker 名稱
wen8604-car、帳號 ID、自訂網域只有car.wen8604.com、關閉 workers.dev 與預覽網址。 - Durable Object 綁定與 migration 只有
Visitsv1(避免誤刪統計資料)。 - Node.js 與 npx 存在;固定 wrangler 4.151.1(以 .cmd 呼叫,避開 PowerShell 5.1 參數問題)。
node tools/build.mjs與node --test test.mjs必須成功。
第一次上傳前
- 確認 wen8604.com 這個網域在同一個 Cloudflare 帳號(3d83…73d3)底下;自訂網域會自動建立 DNS 與憑證。
- 電腦需先登入 Cloudflare:在終端機執行
npx wrangler@4.151.1 login(只需一次)。
回復上一版
Cloudflare 後台 → Workers & Pages → wen8604-car → Deployments,選上一版按 Rollback;或把備份資料夾的檔案放回 public 後重新上傳。訪客統計資料存在 Durable Object,不會因回復而遺失。
17更新時間與訪客統計
網站更新時間
- 每次執行上傳批次檔,
tools/build.mjs會把台北時間(例如 2026-10-22 09:00)寫到:App 與說明書頁尾<time data-updated>、sw.js 版本、version.json、sitemap.xml。 - 只想重算雜湊、不改更新時間:
node tools/build.mjs --keep-time。 - 設定 →「關於」也會顯示同一個時間,不會有多處不一致。
獨立訪客統計(不重複人數)
- 第一次開啟時,瀏覽器產生 128 位元隨機編號存在本機;每天最多回報一次。
- 伺服器把編號加上 Durable Object 內部的隨機鹽做 SHA-256,只存雜湊;IP 只用來做「每天每來源最多 30 位新訪客」的防灌票,也只存加鹽雜湊,3 天後刪除。
- 不計入:自動化瀏覽器(navigator.webdriver)、爬蟲與監控 UA、本機檔案開啟、離線。
- 依設計規範:統計出錯時不顯示 0,直接隱藏;數字使用等寬字、600 字重、主色。
- 限制:清除瀏覽資料或換瀏覽器會被當成新訪客;同一人手機+電腦算 2 位。這是不追蹤個人的前提下最接近真實的算法。
18v1.2 深度稽核紀錄
以資深研發與資安角度,對 v1.1 做完整稽核後的發現與處置。
| 類別 | 問題 | 等級 | 處置 | 狀態 |
|---|---|---|---|---|
| 資安 | CSP 只用 meta 標籤,frame-ancestors 無效,網站可被嵌入做點擊劫持 | 高 | Worker 送出 CSP 標頭+X-Frame-Options DENY | 已修復 |
| 資安 | script 允許 'unsafe-inline',一旦有注入點即可執行 | 中 | 改用部署時計算的 SHA-256 雜湊白名單 | 已修復 |
| 資安 | 沒有 HSTS、nosniff、Permissions-Policy 等標頭 | 中 | Worker 統一加上安全標頭 | 已修復 |
| 資安 | 統計 API 可能被灌票或跨站呼叫 | 中 | 同源檢查、大小限制、機器人過濾、每來源每日上限 | v1.2 新增 |
| 隱私 | 訪客統計若存 IP 屬個人資料 | 中 | 只存加鹽雜湊,鹽值由 DO 自己產生、不在程式碼中;3 天後刪除 | v1.2 新增 |
| 資料 | 多分頁同步後按「復原」會用舊資料蓋掉別頁的新紀錄 | 中 | 同步時讓舊的復原失效並提示 | 已修復 |
| 資料 | 編號用 Math.random 產生,大量匯入時有碰撞可能 | 低 | 改用 crypto.getRandomValues | 已修復 |
| 資料 | 家人各自記錄無法合併,只能整份取代 | 中 | 新增「合併匯入」,相同編號略過 | v1.2 新增 |
| 架構 | 單檔只能本機開啟,無法安裝、Safari 7 天清除 | 高 | Cloudflare 託管+PWA | 已修復 |
| 架構 | 版本與更新日期寫死在 3 處,容易不一致 | 低 | 部署工具自動蓋時間,程式只從頁尾讀取 | 已修復 |
| 架構 | 沒有自動測試與部署防呆 | 中 | test.mjs+deploy.ps1 設定檢查,失敗即停止 | v1.2 新增 |
| 介面 | 保養週期只有數字,使用者不知道為什麼要換 | 低 | 保養小百科:每個項目附原因與徵兆 | v1.2 新增 |
| 介面 | 看不到每年花多少、跑多少 | 低 | 年度報表(里程、油耗、油資、保養、其他、每公里) | v1.2 新增 |
| 介面 | 賣車時無法提供保養紀錄給買家 | 低 | 列印保養履歷(可另存 PDF) | v1.2 新增 |
| 介面 | 友善模式只有字級、對比、動態、底線 | 低 | 新增行距字距、加大按鈕、焦點外框、文字加粗 | v1.2 新增 |
| 介面 | 未開 JavaScript 時整頁空白 | 低 | 加入 noscript 說明 | 已修復 |
| SEO | 缺 canonical、Open Graph、robots、sitemap | 低 | 補齊 | 已修復 |
| 待辦 | 提醒只能靠 .ics 行事曆,無推播 | 中 | Web Push 需後端排程,列入 v1.3 | 待 v1.3 |
| 待辦 | 里程表歸零/更換儀表無法處理 | 低 | 規劃「里程修正」紀錄類型 | 待 v1.3 |