# 大埔地圖導覽 更新日誌 (Changelog)

此檔案為本專案的「更新日誌鐵律」所要求的自動更新檔案。
只要修改了程式碼、修正了 Bug 或調整了樣式，就必須立刻在最上方新增紀錄。

---

### v.1.4.1 - 2026-08-22 - ✨ [Feature] 限定內容後台編輯器
- 新增 `/admin/content`：新增／編輯／刪除限定內容，可綁定路線站點。
- 內文編輯器有**即時預覽**，用的是與前台**完全相同**的 `renderMarkdown`——
  避免出現「後台看起來對、前台又不一樣」。Markdown 寫錯（例如清單少了空格）
  只看原文很難察覺，所以預覽不是裝飾。
- 綁定站點時會驗證該站點真的存在於該路線，不會靜靜建立一篇永遠不會出現的內容。
- 清單會標示**孤兒內容**（綁定的站點已改 id 或路線已刪），並說明它不會在地圖出現。
- 新增 API `/api/admin/content` 與 `/api/admin/content/[slug]`（需 editor；刪除需 admin）。

**開帳號腳本加防呆**
- `scripts/create-user.mjs` 與新增的 `scripts/set-password.mjs` 會拒絕指示中的佔位文字。
- 佔位符一律用**純 ASCII**：在 Windows cmd.exe，中文經 pipe 會由 CP950 位元組被當成
  UTF-8 解讀而變亂碼，字串比對就對不上，防呆會靜靜失效——而使用者仍以為自己設了好密碼。
- `set-password.mjs` 除了換密碼，也會刪除該帳號所有現存 session：
  換密碼多半是因為舊密碼不可信，那就不該留著已登入的 session。

### v.1.4.0 - 2026-08-22 - 🔒 [Security] 路線搬入 D1，移除 Firebase
**修復：任何人都可以改寫地圖路線**
- 實測證實 Firestore `guided_routes` 的安全規則容許**匿名寫入**：以 repo 內公開的
  Firebase config，在完全未認證的情況下成功寫入文件再刪除。任何人都可以改寫、
  刪除導覽路線，或加入假路線並設 `published: true` 使其出現在公開地圖。
- 後台登入閘擋不住這個攻擊——路線編輯器是在**瀏覽器**直接以 Firebase client SDK
  寫入，不經 Worker，而 Firebase config 依設計必然公開。真正的防線一直是
  Firestore Security Rules，寫在另一個系統裡，容易與程式碼脫節。
- 修法：把路線搬入 D1（新增 `routes` 與 `stations` 兩張表），Firebase 整個移除。
  讀取走 `GET /api/routes`（公開，只送已發布），寫入走 `POST /api/admin/routes`
  （需要 editor 或以上的職員 session），與團碼、限定內容共用同一套認證。
- 完整記錄與驗證證據：`docs/security-firestore.md`。

**連帶改動**
- 新增 `src/lib/routes.js` 作為路線讀寫的單一入口，含 payload 驗證：
  站點 id 不可重複、座標必須是數字且落在香港範圍內（擋得住經緯度調轉或錯配到深圳）。
- 站點正規化成獨立的 `stations` 表，讓限定內容能以 `(route_id, station_id)` 綁定。
- 公開的 `/api/routes` **不會**送出 `editorDraft`（編輯器復原狀態，前台用不著）。
- 移除 `firebase` 依賴與 `src/lib/firebase.js`；`.env.local` 不再需要。
- 一併移除三個無用依賴（`proj4` 完全沒被引用；`puppeteer`、`dotenv` 只有根目錄
  的 Firebase／除錯 script 用到）與那 14 個已失效的 script。

### v.1.3.0 - 2026-08-22 - ✨ [Feature] 網站重構：首頁、團碼限定區、視覺改版
**網站結構**
- 新增首頁 `/`，說明這個網站是什麼、為兩種人而設（導賞團參加者、自行來大埔遊玩的朋友）。原本佔用 `/` 的地圖應用移至 `/map`。
- 新增 `/enter`（輸入團碼）、`/exclusive`（限定內容庫）、`/exclusive/[slug]`（單篇限定內容）。

**視覺主題「由河到海」**
- 新增 `src/app/theme.css` 作為設計 token 的**單一來源**：舊測繪圖紙底色、林村河綠、吐露港藍、木棉紅印記、等高線紋理。
  所有前景／背景組合以 WCAG 公式實算過，23 組全部 ≥4.5:1；四個角色色互相 ΔE >15。
  ⚠️ 改色、圓角、字級一律改這個檔，不要在個別元件寫死色值。
- 新增版面元件 `SiteHeader`／`SiteFooter`／`AccessBadge`／`RiverMark`（純 SVG 的河流圖記）。

**認證與限定內容**
- 新增 Cloudflare D1 `taipo-map-db` 與 R2 `taipo-map-assets`，schema 見 `db/schema.sql`。
  地圖路線仍留在 Firestore——兩邊刻意分開，任一邊故障另一邊照常運作。
- 新增 `src/lib/auth.js` 作為認證唯一入口：團碼 session（12 小時）、職員 session（30 天）、
  PBKDF2-SHA256 密碼、加鹽雜湊的限流、CSRF Origin 檢查、稽核記錄。
  session token 與團碼都只存 SHA-256 雜湊，資料庫外洩不等於立即可用。
- 限定資源一律以 404 回應未授權者，不用 401／403——不讓未授權的人知道隱藏內容存在。
- 撤銷團碼會立即刪除該碼所有現存 session，不需等到期。
- 新增 `src/lib/markdown.js`：極簡 Markdown 渲染器，先 escape 全部輸入再產生固定的安全標籤，
  不放行原始 HTML。已針對 script 標籤、img onerror、`javascript:` 連結三種 XSS 情境測試。
- 新增 `/api/asset/[...key]`：限定內容的圖片同樣要通過閘，且只送資料庫有登記的 R2 key。

**開發環境**
- 新增 `docs/setup-mac.md`：在 MacBook 從零接手的完整清單。
- 新增 npm 指令 `db:migrate`／`db:migrate:prod`／`db:sql`／`db:sql:prod`，與 `scripts/create-user.mjs`。

### v.1.2.1 - 2026-08-22 - ♻️ [Refactor] 清理 Vercel 與台北時期的殘留物
- 移除誤 commit 進 repo 的 `.env.vercel.prod`（內容為 Vercel build metadata 與一組 2026-05 產生、早已過期的 12 小時 OIDC token），並在 `.gitignore` 加上 `.env.vercel.*` 與 `vercel.json`。
- 移除 `vercel.json`、`vercel.json.bak`、`public/vercel.svg` 等已無用途的 Vercel 設定與素材。
- 重寫 `README.md`：原內容整份抄自信義社大 xinyi-water-map 專案（台北水文路線），與本專案無關；現改為實際的大埔導覽地圖描述，部署段落由 Vercel CLI 改為 Cloudflare。
- 刪除台北時期的殘留資料與死程式碼（這些圖層已於 v1.1.0 從前台移除，元件自此未再被任何地方 import）：
  - `public/TaipeiTree_filtered.json`（3.2 MB）與其唯一使用者 `src/components/layers/ComfortLayer.js`、生成器 `processTrees.js`。
  - `public/data/xinyi_zoning.json`（2.5 MB）與其唯一使用者 `src/components/layers/ZoningLayer.js`、生成器 `src/scripts/process_zoning.mjs`。
  - `src/app/api/taipei-trees/route.js`，以及 `next.config.mjs` 內 `/api/taipei-trees`、`/api/taipei-sidewalks` 兩條指向 data.taipei 的 rewrites。
- 移除死路由 `src/app/api/temperature/route.ts` 與 `src/components/layers/TemperatureLayer.js`，並從 `package.json` 拿掉 `@google/earthengine` 依賴。
  原因：地表溫度圖層已於 v1.1.0 從前台移除，GEE 金鑰從未設定，線上一直回 500；但它把約 7.9 MB 的 `@google/earthengine` 拉進 server bundle。移除後 Worker bundle 大幅瘦身，冷啟動更快。

### v.1.2.0 - 2026-08-22 - ♻️ [Refactor] 由 Vercel 遷移至 Cloudflare Workers
- 改用 `@opennextjs/cloudflare` 轉接器部署至 Cloudflare Workers，新增 `wrangler.jsonc` 與 `open-next.config.ts`。
- Next.js 由 16.2.4 升級至 16.2.12（轉接器要求 >=16.2.11）。
- `/admin` 的跳轉由頁面層的 `redirect()` 改為 `next.config.mjs` 的 `redirects()` 設定，並移除 `src/app/admin/page.js`。
  原因：預先渲染的跳轉頁在 Workers 上會回傳 404 狀態碼，改在路由層處理才能得出正確的 307。
- 新增 npm 指令 `cf:build` / `cf:preview` / `cf:deploy`。

### v.1.1.1 - 2026-05-27 - 📜 [Docs] 鞏固更新日誌與防誤關機制
- 建立並嚴格規範 `public/CHANGELOG.md` 更新機制。
- 在 `CLAUDE.md` 中寫入 CRITICAL CHANGELOG RULE，確保所有未來的 AI 及開發者都會遵守。
- 寫入 React 19 與 Leaflet 彈窗結合時的 `setTimeout(..., 50)` 防誤關祕技，保障系統穩定。

### v.1.1.0 - 2026-05-23 - ✨ [Feature] 匯入GeoJSON與主視覺更新
- 新增後台編輯器「匯入 GeoJSON」功能。
- 更改前台主視覺色系：左欄改為深綠色 `#0e2a1d`，導覽路線改為綠色 `#2c704d`。
- 移除前台不適用於香港的開放資料圖層（行道樹遮蔭、人行道範圍、都市計畫分區、地表溫度）。
- 修復 Vercel 環境變數缺失導致 Firestore 儲存無限載入的問題。
- 移除前台地圖中寫死的預設「從河到海」路線，改為純動態載入。
- 精簡「資料來源」介面說明。

### v.1.0.1 - 2026-05-22 - 🐛 [Bugfix] 路由與水合修復
- 解決了 Vercel Next.js 路由 404 錯誤。
- 修復 `signInAnonymously` 造成前端水合作用（Hydration）崩潰的白畫面錯誤。

### v.1.0.0 - 2026-05-21 - 🎉 [Release] 初版上線
- 大埔地圖導覽初版上線。
- 實作 Leaflet 地圖、多圖層切換功能。
- 完成後台路線編輯器基礎架構。
