01結論
第四版最重要的發現不變:要消滅的是重複,不是網域—— 實查(8/16)比第四版宣稱的還嚴重:寄信六份、金流八處以上、地址轉配送區五份, 簡訊三份、LINE push 兩份、薪資兩套、報表三份。但這一版把衡量標準再推進一層: 重複之所以危險,是因為寫入權失控——實查(2026-08-16)16 個站直連 goalu、 其中 14 個帶寫入、11 個共用同一個 david 帳號,比第四版以為的「10 站直連」更嚴重。 只要大家都能改訂單、會員、帳務資料,站台合併得再漂亮,事故面沒有變小。
所以第五版的主軸是三條戰線:A 暴露面收斂(把不該在線上的東西拿下來、把權限收窄)、 B 寫入權集中(ERP 先穩定化,外圍站逐一改走它的命令 API,最後才刪碼)、 C 站台歸併(按使用者與變更節奏收斂成五個目的地)。 三條各有退出條件,可以在任何一步停下來,且停在哪裡都比現在好。
ERP 的路線 8/17 定案:不在舊專案裡越修越複雜,開新殼 strangler—— 同一個 goalu、核心表不改,新功能與逐頁搬遷都進新專案,舊 ERP 凍結只修 bug。 「舊邏輯沒在用」實測是雙寫並行(SyncOld 還在餵舊表), 所以刪碼永遠是最後一步:先搬讀者、再停同步、跑過月結才刪—— 先刪會砍掉月結還依賴的隱性規則,那種錯誤要到月底才爆炸。
執行紀律只有一條:同一時間只允許一個「重建型」項目在進行, 其他戰線只做維護級小步。一人+AI 的量能,爛尾的成因永遠是同時開太多工地。
02前提變化(8/05 → 8/16)
第四版的盤點資料(各站功能、重複清單、路徑陷阱)仍然有效,掛在本頁的版本歷史裡。 這裡只列改變了規劃前提的事。
| 變化 | 狀態 | 對規劃的影響 |
|---|---|---|
| 教育側整包搬離 | lk+callhub 已合併為 muxue 遷往 125 主機(8/16 執行中) |
第四版「電訪與報表 → callhub.kng.tw」的目的地不存在了; 跨 callhub 庫的難題一併消失。94 上的 lk / callhub / mu / analysis 待驗收後下線 |
| ERP 全面接手 | 79 controller · 354 model · 56 Job+37 Command · 417+63 條路由;排程由 DB 動態載入(TaskRepository) | 從「不能動的核心」變成「要穩定化+瘦身的核心」。 使用者明說:裡面保有很多已經沒在用的舊程式邏輯 |
| 電訪與報表歸屬拍板 | call.kng.tw 名單系統+report 93 支+FLUX BI → 併進對內管理站 | 對內站成為第三大目的地,內部必須模組化(見 04) |
| 清理已完成的 | projview / starmath / skilltree 已刪(憑證同步清)、linjia 停用、 13 個停用站 8/05 下線、全機 PHP 統一 8.5 | 第四版階段 0 的大半已經做完 |
| crm.kng.tw 沒有想像中閒置 | 程式半年沒動(2026-02),但 line_chat 貼圖資產掛在它身上,每日數十次真實請求 | 不能直接下架——改走 A5 三步:貼圖搬家 → 301 轉址 → 觀察期滿才清 |
| sys 放棄、kn 改為被取代目標 | sys.kng.tw 綠地重建於 8/17 放棄(不改資料表架構),站台凍結維持;kn.kng.tw 原裁示排除,8/17 再裁示:新行動入口目標取代 kn,過渡期照跑不動 | 舊 ERP 確定為長期本體;delivery 與 kn 的功能終將併入行動入口 m.kng.tw |
| 換表實況:雙寫並行 | hcust_dorder 與 weekly_orders 同秒寫入(SyncOld job 維持);真凍結的只有 dorder/dorderd/hcust_trdh(2025-03-14) | ERP 主軸從「刪死碼」改為「收斂雙寫」+新專案 strangler,詳見 06 |
03三個目的,各自的架構含義
AI 好維運 —— 護欄要機器可驗證,不是寫成文件
AI 擅長遵守可檢查的規則,不擅長從散落文件猜隱性規矩。 所以「好維運」的具體形態不是更多 CLAUDE.md,而是: 全站 machine-readable 目錄(每站的網域、repo、runtime、DB 帳號、排程、健康檢查、部署方式), 加上 CI 強制的架構護欄(禁止跨域直接寫表、API schema 相容性、寫入端點守門回歸)。 細節在第 07 節——大半是把 salary 已驗證的模式推廣出去,不是從零發明。
安全隔離 —— 暴露面是現在進行式,不是重構議題
html/salary 至今仍有 234 個頂層 PHP 檔、77 個子目錄、9.2 GB,
個人研究工具(finlab、爬蟲、遊戲原型、GPU 實驗)與正式業務共用同一個 web root,
底下還寄生五個對外網域(call/cf/ny26/sales/sony,8/13 清理後的實查數)。
這不是「日後整併時順便清」的東西——
任何一個檔案被誤設成可存取就是洞。它排在所有工作的最前面。
降維護負擔 —— 收斂寫入權比收斂網址有效
網址收斂省的是憑證與 vhost 的量; 寫入者從 14 個變 1 個,省的才是「同一條業務規則要改四個地方」的本體。 兩件都做,但優先序是後者。
04目標架構
五個目的地+一個獨立服務。切分軸與第四版相同——使用者是誰、變更節奏多快、資料多敏感—— 本版新增:內外勤分流——客服內勤用對內站(桌面),業務員與配送員用行動入口 m.kng.tw(手機 PWA,8/17 裁示);人資為對內站硬隔離模組。
對外站
kngoatmilk.com 新建 Laravel- www 前台+隱藏的 5.8 萬行 API
- forms 表單與活動 landing
- shop 購物車
- ny26 年菜活動、kng.tw 短網址
- 金流留在站上,寫入走 ERP 命令
strangler 逐一搬:forms → 活動頁 → shop → 最後才 www
ERP(舊本體+新殼)
erp.kng.tw 核心 · 唯一寫入者 · 路徑分流- 舊 ERP 凍結維護:訂單、配送、帳務主引擎照跑,只修 bug
- 新專案 strangler 殼:同網域、同 goalu、只碰新世代表(CI 攔檢)
- 三大階段搬遷:基礎資料 → 估奶管線 → 配送執行;業務異動核最後動
- 按領域定義命令契約,不做 God API
sys 路線已放棄(8/17);搬哪塊、搬前補那塊的 characterization tests,詳見 06
對內管理站
salary.kng.tw 收斂 · 模組化- 現有 salary 業務模組
- 電訪名單(call.kng.tw 併入)
- 報表 93 支+FLUX BI(唯讀接入)
- 庫存 inventory、行政表單
共用入口與 SSO,模組間禁止互讀 model——不然只是把總務室換個門牌
人資模組(對內站內)
salary.kng.tw/hr 8/17 裁示- 薪資兩套合一(Livewire 版為基底)
- 請假與年度結算、證件管理
- 硬隔離配套:薪資表專屬 DB 帳號只掛人資 connection、獨立 route+middleware、附件移出 web root、匯出走審計 log
裁示不獨立部署(推翻 codex 建議)。上列配套是底線;若日後出過一次跨模組事故,直接升級成獨立站
行動入口(外勤)
m.kng.tw 業務員+配送員 · 手機 PWA- 實體=erp-next 的行動區(同一個部署,mobile-first Blade+PWA 可安裝)
- 業務員:sales.kng.tw 功能逐頁搬入(階段 5)
- 配送員:先吸 delivery 日誌,再逐步搬 kn 的功能(軌跡/積分/獎金)
- 終態:kn 與 delivery 退役
內外勤分流:客服在對內站(桌面),外勤在這裡(手機)。打卡 PWA 是成功先例
LINE 站
line.kngoatmilk.com 維持獨立- 現有功能保留
- 吸掉 www/api/linebot 殘留
- webhook 有回應時限,不與大站共命運
收尾不排期——條件到了(能力已被 shared 取代)就關舊路徑
PBX(獨立服務)
pbx-laravel12 API only- Asterisk 撥號中介,保持長連線
- 對外只留 API
- monitor 頁併進對內站電訪模組
對內站與 ERP 的分界(8/17 定則)
一條判準:ERP 管交易,對內站管支援——會寫客戶/訂單/帳務資料的邏輯屬 ERP (畫面放哪都行,寫入必過命令 API);只讀業務資料、寫自己領域表的,屬對內站。
| 功能 | 歸屬 | 模式 |
|---|---|---|
| 客戶 · 訂單 · 估奶 · 配送 · 結帳 · 應收 | ERP | 交易核心,資料權威 |
| 發票開立(XML/字軌/Turnkey) | ERP 帳務域 | 與結帳金流強耦合;invoice 站只留行政雜項給對內站 |
| 撿奶 pick · 路條 | ERP 配送域 | 配送交易鏈的一環;配送員介面在行動入口 |
| 電訪名單 call_list | 對內站 | 寫自己的 call_* 域表、讀客戶唯讀;回寫客戶異動走命令 API |
| 報表 93 支+FLUX BI | 對內站 | 純唯讀(專屬唯讀帳號) |
| 庫存 · 行政表單 · 人資 | 對內站 | 自己的域表(inventory_*/iexpense/hum 薪資) |
| 訊息發送(sms_management/催繳) | 對內站 | 發送走 kng/notify;補登 trades 走命令 API——「介面在對內站、寫入過 ERP」的典型 |
灰色地帶一律套通則:介面歸使用場景(對內站/行動入口),寫入歸領域(ERP 命令)。 由此對內站的 DB 帳號可以鎖成「業務表唯讀+自己域表讀寫」——與 A3 寫入權矩陣完全對齊, salary 現有幾十個業務模組逐一套這條就能分完。
整合後各站技術棧(8/17 定調)
一句話:Blade 陣營全面統一,React 隨 kn 退役自然淘汰。
| 站 | 技術棧 | 說明 |
|---|---|---|
| 對外站(新建) | Laravel 13 · PHP 8.5 · Blade+Alpine · Tailwind 4 token · Vite · Pest | 金流留在站上,寫入走命令 API |
| ERP 舊本體 | Laravel 13(現況凍結) | 只修 bug;不升級、不重構、不投測試 |
| ERP 新殼+行動入口 | Laravel 13 · Blade+Alpine · Tailwind 4 token · Vite · Pest · PWA(行動區) | 一個 repo 養桌面+手機兩種介面(見新殼規格) |
| 對內站 | Laravel 13 新專案+傳統 PHP 存量共存(同網域路徑分流)· Blade+Alpine · token | 新模組用 Laravel;93 支舊報表存量保留在 legacy 區,不硬搬 |
| LINE 站 | Laravel 12 → 13 例行對齊 | 不重構 |
| PBX | Laravel 12 API-only 維持 | 不動 |
| kn · delivery(退役中) | 維持現況(React/Laravel 8.83) | 零投資;kn 的 125 個 React 元件不搬,隨站淘汰 |
統一原則:①全站 PHP 8.5+Laravel 13(凍結中的舊 ERP 除外)
②前端一律 Blade+Alpine+Tailwind 4 @theme token,不再投資 React/Inertia
③建置統一 Vite(laravel-mix 淘汰)④測試一律 Pest(傳統 PHP 存量沿用 salary 的 FakePdo 模式)
⑤部署統一 git+systemd worker,不用 Docker。
共用層:縮小版的 kng/shared
第四版把 Mail、SMS、金流、Geo、領域 Models、發票全部放進一個 composer 套件。 這一版刻意縮小:生命週期不同的東西塞同一個套件,任何小改動都逼全站升版, 共享 Models 更會把資料庫耦合永久化。
| 層 | 內容 | 去向 |
|---|---|---|
| kng/notify | Mail、SMS(every8d)、LINE push——低狀態、無業務邏輯的 adapter | 抽成套件 取代六份 PHPMailer、三份 every8d、兩份 push(實查 8/16) |
| design token | Tailwind 4 @theme CSS 一檔 |
獨立前端套件 與後端套件分開發版 |
| Payment、Invoice | 金流註冊/扣款/驗簽、發票 XML | 不抽 留在明確擁有者(對外站、人資站),有狀態有交易邊界 |
| 領域 Models | Hcust / DailyOrder / CustomerPrice 等在七個專案各有一份定義 | 不共享 用 ERP 命令 API 消滅重複,不是把耦合包進套件 |
05三條戰線
取代第四版的七個線性階段。三條戰線各有退出條件,每一步都能獨立收工; 重建型項目全域同時最多一個,其餘只做維護級小步。
把不該在線上的東西拿下來、把每個站能碰的東西收窄。全是搬移與設定,不改程式行為。
- A0muxue 搬遷收尾:125 驗收通過後,94 下線 lk / callhub / mu.kng.tw / analysis 的 vhost 與 systemd 服務,憑證停止續約
- A1html/salary 的 15 個個人/研究目錄(finlab、dedao、steam_research、games、tetris、maze、ski、laser-cut、gfpgan、musetalk、dictation_client、ai-images、sparklab、comfy_cuda_patch、gpu-fleet-snapshots;合計約 2.1 GB)整批移出 web root,搬到
/home/ying/lab/,各留 README 指路。已逐一驗證:無任何 vhost 或 /etc/cron.d 引用,屬孤立目錄,搬移零風險 - A2四個寄生網域拆出獨立目錄:cf.kng.tw(簡訊管理)、call.kng.tw(電訪名單)、ny26.kng.tw、sales.kng.tw;cpt.kng.tw 的 proxy 一併理清。拆出=先搬目錄改 vhost,不改碼
- A3建「網域 → 目錄 → runtime user → DB 帳號」對照表,然後做寫入權矩陣:每張核心表(訂單、會員、帳務、薪資)標出誰在寫。據此把各站的 DB 帳號換成專屬最小權限帳號——實查 11 站共用
david、4 站用tom,只有 report 與 flux 是唯讀;短期動不了程式的站至少先換受限帳號 - A4快贏清單:flux.kng.tw 舊殼目錄移除、/var/www/salary 收整(實查 :6048 只在 ports.conf 留埠、無 vhost 綁定——清埠設定,站本體留作 C2 人資基底)、報表站兩套登入(unified-auth / session-auth)收成一套
- A5crm.kng.tw 三步下架(8/17 實查推翻「閒置」判定:line_chat 的
sticker_crm指向它、LINE 歷史訊息烙死其網址、每日數十次真實貼圖請求):①貼圖資產複製到 salary.kng.tw 同路徑、line_chat config 改指 ②crm.kng.tw 縮成純 301 轉址 vhost,Laravel app 退役打包 ③觀察一個月無 404 再清目錄與憑證。教訓:git 半年沒動 ≠ 沒人用,靜態資產不寫進 commit
退出條件web root 只剩正式業務;每站專屬 DB 帳號且權限與寫入權矩陣一致;矩陣成文並進版控
讓「會寫業務資料的程式」只剩 ERP 一份。改的是收單路徑,每一步都要能回頭。
- B1ERP 穩定化:對訂單建立、付款確認、配送異動、結帳過帳補 characterization tests(鎖住現狀行為,不判斷對錯);盤點所有寫入點與交易邊界;命令契約建在新殼(8/17 起,見 06 新殼規格)——以舊 ERP Api 現有的 11+4 支 controller(Sanctum+system.operator、V2 薄代理、README 六領域文檔)為藍本,每個命令有 idempotency key、狀態機、審計與 schema,版本針對契約。測試面起點差(10 個測試檔對 79 支 controller):characterization 跟著搬遷走、搬哪塊補哪塊,另建營運金絲雀組(見 06)
- B2對外站 strangler:新建對外站骨架後逐一搬——forms(同為 Laravel,最容易)→ ny26 活動頁 → shop → 最後才碰 www——它的 api/ 實測 58,321 行、90 條路由,比第四版以為的一萬行大 5.8 倍。每搬一塊,該塊的寫入改呼叫 ERP 命令;舊路徑照常寫入,新舊並行,每日自動比對筆數與金額、差異即告警——不靠人工對帳
- B3觀察兩個完整月結週期:月結、補帳、活動檔期都跑過,對帳告警連續綠燈,才進下一步
- B4才刪:外圍站的舊訂單/會員邏輯下線;ERP 死碼依 06 的判準分批刪,每批獨立 commit 可回滾
退出條件訂單、會員、帳務資料的唯一寫入者=ERP;新舊對帳告警連續兩個月結週期綠燈
網址與部署的收斂。每一項都等它依賴的 A/B 步驟完成才動,不搶跑。
- C1對內站:共用入口+SSO 先立起來,然後電訪名單(call_list)、report 93 支、FLUX 十頁 Volt BI、inventory、invoice 行政表單逐模組遷入。模組間硬邊界:各自的 route group、各自的 service 層,禁止跨模組直接讀對方 model;BI 一律走唯讀 DB 帳號(見 08 決策三)
- C2人資模組:以 /var/www/salary 的 Livewire 版為基底併入對內站(8/17 裁示:不獨立部署),合併 html/salary 的舊版薪資(實查為兩套)、吸收 invoice 的 /leave 請假。硬隔離配套一項不可少:薪資表專屬 DB 帳號、獨立 route+middleware、附件移出 web root、匯出審計。合併前用同一批員工同一個月份把兩套各跑一次比對——差異要先解釋
- C3行動入口 m.kng.tw(8/17 裁示):erp-next 行動區+PWA,業務員與配送員的手機主入口。先吸收 delivery 日誌與 sales 業務功能,再逐步搬 kn 的軌跡/積分/獎金——目標取代 kn(推翻 8/16 排除令),過渡期 kn 照跑;kn 與 delivery 分別在功能清空後退役
- C4LINE 收尾:不排期。當 www/api/linebot 殘留確認被 line 專案涵蓋、通知能力已走 kng/notify,就關舊路徑
退出條件對外可見網址收斂到目標清單;每個存活站帶齊第 07 節的維運地基標配
第四版階段 0(凍結盤點)大半已完成;階段 1(抽套件)縮小為 kng/notify+token,併入戰線 A 之後隨時可做; 階段 2(對外站合併)=戰線 B2,改為 strangler;階段 3(拆寄生網域)提前為戰線 A2; 階段 4(電訪報表)與 5(人資)=戰線 C1/C2;階段 6(LINE)改為條件觸發的 C4。
06ERP 怎麼動:新殼 strangler,三大階段
本節 2026-08-17 全面改版:sys 綠地路線放棄、不改資料表架構、 新開一個獨立專案當「同 schema 的 strangler 殼」——依據是 CBM 實測與 DB 寫入時間的證據,不是感覺。
換表的真相:不是換完,是雙寫並行中
「訂單已從 hcust_dorder 換到 weekly_orders、舊邏輯沒在用」——DB 實測只對了一半:
| 表家族 | 最後實際寫入 | 判定 |
|---|---|---|
| weekly_orders · daily_orders · dv_orders · trades · customers | 每日 | 新世代主線 |
| hcust_dorder · gcust_dorder · hcust_trd · hcust_dv… | 與新表同秒(8/16 23:38:47) | 雙寫中 SyncOld 家族 job 在維持,引用它們的程式不是死碼 |
| dorder · dorderd · hcust_trdh · *h 歷史表 | 2025-03-14 同日凍結 | 真死區 約 10–15 檔引用碼,隔離第一批 |
所以 ERP 的重心不是「刪很多死碼」,是收斂雙寫:把舊表的「讀者」逐個搬到新表, 讀者清空就停對應的 SyncOld,那批碼才自然死。2025-03-14 那次成功停掉 dorder 家族,就是這條路的先例。
新專案:同 schema 的 strangler 殼(8/17 裁示)
在同一個專案裡越做越複雜、越受限——但 sys(換 schema 重建)與 muxue-platform(全新重寫)兩個大爆炸案都廢了, 成功的全是漸進案。所以新專案的存活條件寫死在四條鐵律:
| # | 鐵律 | 機制 |
|---|---|---|
| 1 | 同 goalu、核心表不改 | 只讀寫新世代表(customers/weekly_orders/trades…);真正的邊界在 DB 帳號——新 app 專屬 MySQL 帳號只授權新世代表,CI 靜態掃描當第一層提醒。核心表結構不動,但新 app 可建自己的輔助表(outbox/批次狀態/稽核)——同 schema 是過渡護欄,不是永久戒律 |
| 2 | 同網域路徑分流 | 留在 erp.kng.tw,Apache 以不重疊前綴導流(如 /next/*);兩 app 分開 FPM pool/log/cache prefix/queue 名/storage;不共用 APP_KEY——登入態由舊 app 簽短效一次性票據給新 app,CSRF 各自簽驗、logout 兩邊都做 |
| 3 | 舊 ERP 凍結 | 只修 bug 不加功能;新功能一律進新專案。每搬一頁舊 ERP 就縮一點,沒有「搬完才上線」的里程碑 |
| 4 | AI 地基 day-one 標配 | 第 07 節的服務目錄、CI 護欄、測試安全網從第一個 commit 就掛,不是事後補 |
新殼規格:技術棧 · 網域 · 帳號 · API
| 面向 | 規格 | 理由 |
|---|---|---|
| 技術棧 | Laravel 13+PHP 8.5(與主機一致)· Blade+Tailwind 4 @theme(吃共用 design token)+Vite · Pest(金絲雀+characterization)· Redis queue(prefix next:)· repo /var/www/erp-next 獨立 git |
與 ERP/kn 同世代,AI 與人都零切換成本;不引入 Inertia/React——內部站是 Blade 陣營 |
| 網域 | erp.kng.tw/next/*(對外 443 與內網 8888 同規則);行動入口另配 m.kng.tw → 同一個 erp-next 的行動區(PWA manifest scope /m/);靜態資源 /next/build/*;健康檢查 /next/healthz;Apache 前綴不重疊、分 FPM pool |
使用者無感、SSO 最簡、逐頁可回退(8/17 已裁決) |
| 帳號 | DB erpnext_app:DML 只授權新世代表 allowlist(customers · weekly_orders(+items) · daily_orders · dv_orders · daily_dvs · dv_dvms · dv_covers · dv_unit_price · delivery_list · trades · change_resources · marea 系 · hum · customer_pre_jobs · daily_gprods · estimate_runs · address_book 系);
erpnext_migrate:僅部署時執行,只建 next_ 前綴輔助表(outbox/審計/批次狀態);
APP_KEY 獨立;登入=舊 ERP 簽發一次性票據,新殼驗票後建自己的 session;SyncOld 橋維持舊 ERP 帳號 |
權限邊界鎖在 DB 層;輔助表用前綴隔離,核心表 schema 不動 |
| API | 命令式 /next/api/v1/<領域>/<命令>,六領域承接現有 Api README(客戶、訂單、異動、估奶過帳、地址簿、預收);每命令必帶 Idempotency-Key、寫審計表 next_audit;認證沿用 Sanctum+system.operator;版本針對單一契約不整站升版 |
消費者接入順序:對外站(階段 3)→ LINE → 對內站 → kn(未來自願切換) |
三大階段(CBM 實測後的節奏判定)
現役配送系統實測:18 張核心表、11 個 Service、5 個 Job、呼叫鏈 4–5 層, 天然分四層且依賴單向——複雜度中等,可以大階段搬,不必碎步:
| 階段 | 搬什麼 | 邊界 | 風險 |
|---|---|---|---|
| 一 · 基礎資料 | customers、weekly_orders CRUD、地址簿、奶區 marea、員工 hum、定價 | 零依賴,純 CRUD | 低 |
| 二 · 估奶管線 | DailyPre+DailyPostingService(weekly_orders → daily_orders+dv_orders) | 單向流,最肥但最乾淨。切換走「雙算單寫」:舊程式維持正式寫入、新程式算進 staging 逐筆比對,達標後停舊排程、記 cutover epoch、新程式才成為唯一 writer——絕不允許兩套 writer 同時寫同一批。搬遷前先分類 daily_orders 哪些欄位是估奶產物、哪些人工擁有(extra_qty 等),DELETE+INSERT 不可盲目整列重建 | 中 |
| 三 · 配送執行 | DvDvm 日計、DvReport 路條列印 | 多為唯讀消費端 | 低 |
| 尾 · 業務異動核 | TradeService+DailyRenew | trades 三方寫入(估奶初估+業務異動+當日刷新)+ daily_orders「人工調整 vs 重估覆蓋」——帳務一致性心臟 | 最高 留在舊 ERP 最久,前三階段跑穩後單獨動 |
測試策略兩層:搬哪塊、搬前先給那塊補 characterization tests(鎖現狀行為), 不對凍結程式全面補測;但另設一組不可省略的營運金絲雀——下單、估奶、路條、異動、 帳務彙總、既有讀者相容——用固定去識別資料集比對新舊輸出,金額/瓶數/配送戶數是硬門檻。 只測待搬頁面會漏掉跨系統契約,金絲雀補這個洞。
每個搬遷切片的完成定義(防止新殼變成第二套 ERP 的唯一機制): 舊入口關閉、舊 writer 停止、對應同步縮減、舊程式與排程可刪除——四項全達成才算搬完。 優先搬「完整的垂直業務能力」而不是只搬 CRUD 頁面; 雙寫收斂則按 A3 的 ownership matrix 執行(每張表唯一 writer、同步方向、每日 reconciliation)。
daily_orders_shadow/dv_orders_shadow 是每日 07:00 的 SQL vs PHP 估奶比對機制
(DailyPreSql 寫影子 → DailyPre 寫正式 → EstimateCompare 對比告警),原始目的隨 sys 廢案消失。
✓ 已於 8/17 執行:goalu.tasks 的 45(daily:pre-sql)與 46(estimate:compare)停用。影子表凍結觀察一個月結後清除,省下每日一次全量估奶計算。
死碼判準:HTTP log 只是第一層
月結、年結、補帳、季節性活動(年菜、中元)、排程 job、queue、artisan 指令、 外部 webhook、人工救援入口,都可能 90 天沒有一筆 HTTP 紀錄;call graph 也看不到動態呼叫。
判死要同時過五關,全過才進隔離區:
| # | 檢查 | 方法 |
|---|---|---|
| 1 | HTTP 流量 | access log 對照 417+63 條路由(實查 log 只留 14 天——先拉到 90 天以上再判) |
| 2 | 排程與 queue | 56 Job+37 Command、事件監聽逐一反查;⚠️ ERP 排程由 DB 動態載入(TaskRepository),要查任務表,看 Kernel 看不到 |
| 3 | 程式引用 | CBM call graph+全文檢索(含 view、config、動態字串) |
| 4 | 資料證據 | 相關資料表的最後寫入時間(DB 稽核/updated_at) |
| 5 | 業務確認 | 問使用者:這功能還有人用嗎?季節性的標記觀察窗 |
初步訊號(實查 8/16):30 餘支 controller 自 2021–2022 就沒再變動—— 這是候選清單的起點,不是結論;每一支仍要過五關。
刪除紀律:候選先移進 app/Deprecated/ 隔離區(路由回 410、log 觸擊)跨過至少一個月結,
沒觸擊才真刪;每批獨立 commit,訊息載明五關證據,隨時可 revert。
07AI 維運地基
大半不是新發明——salary 專案這一年已經驗證了一套(Pest 安全網、寫入端點守門測試、 CronTracker、tbls schema 文件、CBM 索引),這一節是把它變成每站標配並補上缺的兩塊。
| 地基 | 內容 | 現況 |
|---|---|---|
| 服務目錄 | machine-readable 的 services.json:每站的網域、repo、runtime、
DB 帳號與權限、排程、queue、webhook、健康檢查、部署方式。
戰線 A3 的對照表就是它的第一版 |
新建 lan_hosts 有設備層,缺服務層 |
| CI 護欄 | 機器強制的架構規則:禁止跨域直接寫表(掃 SQL/model 引用)、
寫入端點守門回歸(salary 的 test:security 模式推廣)、
API 契約相容性檢查、migration lint |
部分 salary 已有守門測試,其他站沒有 |
| 測試安全網 | 每站最少一套煙霧測試+高風險模組 characterization tests; 金流與簡訊已有 delivery audit(message_logs、payment_callback_failures) | 有基礎 推廣即可 |
| 可重現性 | request correlation ID 貫穿站間呼叫;核心流程備一組去識別化 fixture, 讓 AI 能在不碰正式 DB、不讀個資的情況下重現問題 | 缺 目前除錯常需要讀正式資料 |
| 知識可發現 | CBM 全專案索引、tbls schema 文件(每日重生)、每站 CLAUDE.md 慣例 | 已運作 維持 |
優先序:服務目錄與 CI 護欄跟著戰線 A 一起做(A3 的產出直接餵它), fixture 跟著戰線 B1 的 characterization tests 一起長出來,不另立專案。
08決策點
shop 的獨立資料庫要不要併進 goalu?
要併,時點在戰線 B2 搬完 shop 之後,不當前置條件。(照建議)
理由不變:「網購買過什麼」連到「他是不是訂戶」是這次整合少數的新價值; shop 只有 7 張 model,是最小遷移面。先程式後資料,兩段分開做。
薪資做對內站的權限模組,還是獨立站?
做對內站的權限模組,不獨立部署。原建議(獨立站)被裁示推翻。
代價是薪資與其他內部功能同 process、同部署——所以硬隔離配套是底線而非加分項: 薪資表專屬 DB 帳號(只掛人資模組的 connection)、獨立 route+middleware、附件移出 web root、 匯出一律過審計 log。並保留升級路徑:若發生一次跨模組事故,直接改獨立站。
報表與 BI(93 支+FLUX)怎麼接資料,才不會拖垮交易庫?
先不決定——C1 實際要搬報表時再議。屆時的預設方向仍是:專屬唯讀帳號+慢查詢監控,有數據再考慮 replica。
94 是單機,先做 replica 是過度工程。唯讀帳號本身就是戰線 A3 的一部分, 零額外成本;慢查詢監控已在運作,有數據再決定要不要 replica。
delivery(配送員日誌,Laravel 8.83,3 controller / 9 route)的去向?
8/16:kn 不整合 delivery、暫列存量。8/17 更新:delivery 併入行動入口 m.kng.tw 的配送員區,功能清空後退役。
「kn 不動」的前提也於 8/17 改變——新行動入口目標取代 kn(見決策六),delivery 自然歸入同一條收斂路徑。
ERP 越做越複雜、受限——要不要獨立開新專案?
要。同 schema 的 strangler 殼:新功能全進新專案、舊 ERP 凍結只修 bug、逐頁搬遷隨時可停。
配套三裁示:①資料紀律進 CI 靜態攔檢(新專案掃到舊表名就紅) ②入口用 erp.kng.tw 路徑分流(使用者無感、逐頁可回退) ③shadow 估奶驗證收回(DailyPreSql/EstimateCompare 停用,影子表觀察一個月結後清)。 節奏依 CBM 實測定為三大階段(見 06)——複雜度中等,不必碎步。
業務員與配送員以手機為主,入口怎麼跟客服內勤分開?
行動入口 m.kng.tw=erp-next 的行動區(PWA),目標取代 kn;sales 搬遷納入階段 5。
內外勤分流:客服用對內站(桌面)、外勤用行動入口(手機)。 同一個 erp-next 部署養兩種介面,不多養系統;kn 的功能(軌跡/積分/獎金)逐步搬入後退役—— 推翻 8/16 的「kn 排除」,過渡期 kn 照跑不動。delivery 日誌一併吸收。
09爛尾防線
第四版排了七個線性階段。誠實檢討:以一人+AI 的量能,七階段會爛尾在中段—— 同時開三個工地,然後全部停在 70%。這版的防線:
| 防線 | 具體規則 |
|---|---|
| 單一重建原則 | 全域同時最多一個重建型項目(新建站、搬遷、換寫入路徑)。其他戰線只做維護級小步(設定、搬目錄、補測試)。開新工地前,先問「上一個收工了嗎」 |
| 收單路徑零信任 | 戰線 B2 是全計畫最危險的一段:改的是錢的入口。新舊並行+每日自動對帳告警是硬前提,沒建好告警不准切流量。切換出錯的代價是漏單,不是 bug |
| 月結是驗收單位 | 任何動到 ERP 或訂單路徑的變更,以「跑過完整月結」為驗收,不以「測試綠了」為驗收。隱性規則都藏在月底 |
| 每步可停 | 三條戰線的每個步驟都設計成獨立收工:停在 A3 也比現在安全,停在 B2 的 forms 也比現在少一份重複。不存在「做一半比不做糟」的步驟——唯一例外是 B2 的單次切流量,所以它要小 |
| 測試環境 | 93 測試機已有 ERP 測試環境(7777);戰線 B 的契約與切換先在 93 演練。備份鏈(每日 DB+異地)不因整合改動 |
建議的第一步
戰線 A 的 A0+A1:muxue 搬遷驗收後把 94 的教育側服務下線, 同一週把 html/salary 的 13 個研究目錄搬出 web root。 兩件都是純搬移、零業務風險、當天可回滾,而且完成後整個機器的暴露面立刻小一圈—— 這是整份規劃裡 CP 值最高的四十八小時。