整合規劃 · 第五版 · 2026-08-17 更新 · 執行路線圖 → · 網域規劃 →

五個目的地,三條戰線

第四版之後前提變了三件事:教育事業已整包搬離、ERP 全面接手可以重構了、 目的確認為「AI 好維運+安全隔離+降維護負擔」。這一版據此重排—— 整合的真正邊界不是站台數量,是資料寫入權: 站台收斂到五個目的地,但衡量成功的指標是「訂單與帳務資料只剩一個寫入者」。

範圍內站台19 6
執行戰線3 條
goalu 直連帶寫入14 站 1
同時進行的重建項目≤ 1
html 底下的寄生網域5 個 0

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 的量能,爛尾的成因永遠是同時開太多工地。

意象圖:左側雜亂交錯的眾多小建築,收斂為右側五棟環繞中央樞紐的整齊建築群
插圖 · 這次要做的事左邊是現況——19 個站台用糾纏的路徑互相依賴;右邊是終態——五個目的地環繞一個核心(ERP),路徑清楚、各走各的門。

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
對外 5 站 www · forms · shop · line · delivery salary 系傳統 PHP html/salary · call · cf · sales · pbx ERP(舊) 大量寫入 inventory · crm 等 4 站 report · flux 唯讀 kn.kng.tw(跨庫直讀) david 帳號 11 站共用 tom 帳號 4 站 goalu 共用資料庫 讀+寫 讀+寫 唯讀 跨庫直讀
圖 1 · 現況實查 2026-08-16:16 站直連 goalu,其中 14 站帶寫入;11 站(含 ERP 與整個 salary 系)擠在同一組 david 憑證後面——任何一站被攻破,等於整庫的讀寫權外洩。invoice 與 shop 另有獨立庫未畫入。

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 LINE 站 webhook 獨立 對內管理站 電訪 · 報表 BI · 庫存 · 行政 · 人資 模組硬邊界(人資 8/17 裁示併入) 行動入口 m.kng.tw 業務員+配送員 · PWA 命令 API(Sanctum) ERP erp.kng.tw 訂單 · 配送 · 帳務主引擎 idempotency · 狀態機 · 審計 goalu 寫入一律走命令 唯一寫入 BI/報表/人資模組 唯讀(專屬帳號) kn · delivery(退役中) 功能移入行動入口後下架 sys.kng.tw(凍結維持) 自有 sys 庫 · 不在收斂範圍 共用層:kng/notify(寄信 · 簡訊 · LINE push)+ design token ←各站以套件引用
圖 2 · 目標架構寫入只剩一條路:對外站、LINE 站、對內站的業務寫入全部走 ERP 命令 API,goalu 的寫入者從 14 個變 1 個;報表 BI 與人資模組走唯讀專屬帳號;行動入口與各站同樣走命令 API。PBX 維持獨立 API 服務(未畫入);kn 與 delivery 過渡期照跑、功能移入行動入口後退役;sys 凍結維持。

對外站

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 例行對齊不重構
PBXLaravel 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三條戰線

取代第四版的七個線性階段。三條戰線各有退出條件,每一步都能獨立收工; 重建型項目全域同時最多一個,其餘只做維護級小步。

A0 muxue 下線收尾 A1 研究目錄移出 web root A2 寄生網域拆出 A3 寫入權矩陣+帳號收窄 B1 ERP 穩定化(測試+契約) B2 對外站 strangler+雙寫 B3 兩個月結觀察 B4 刪碼(五關判準) C1 對內站模組遷入 C2 人資模組(薪資合一) C3 行動入口(取代 kn) C4 LINE 收尾(條件觸發) 拆出後才可併 藍框=重建型項目(B2 · C1 · C2 · C3)——全域同時只能亮一顆;虛線框=條件觸發。 主線由上而下:A 全部是零風險搬移;B1 之後才有資格動收單路徑;B4 刪碼永遠是最後一步。
圖 3 · 三條戰線依賴順序:A2 拆出寄生網域是 C1 對內站整併的前提;A3 的寫入權矩陣直接餵給 B1 穩定化;B 線嚴格線性——沒跑過兩個月結(B3)不准刪碼(B4)。
戰線 A 暴露面收斂 安全隔離 · 立即開工 · 全程不碰業務邏輯

把不該在線上的東西拿下來、把每個站能碰的東西收窄。全是搬移與設定,不改程式行為。

  1. A0muxue 搬遷收尾:125 驗收通過後,94 下線 lk / callhub / mu.kng.tw / analysis 的 vhost 與 systemd 服務,憑證停止續約
  2. 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 引用,屬孤立目錄,搬移零風險
  3. A2四個寄生網域拆出獨立目錄:cf.kng.tw(簡訊管理)、call.kng.tw(電訪名單)、ny26.kng.tw、sales.kng.tw;cpt.kng.tw 的 proxy 一併理清。拆出=先搬目錄改 vhost,不改碼
  4. A3建「網域 → 目錄 → runtime user → DB 帳號」對照表,然後做寫入權矩陣:每張核心表(訂單、會員、帳務、薪資)標出誰在寫。據此把各站的 DB 帳號換成專屬最小權限帳號——實查 11 站共用 david、4 站用 tom,只有 report 與 flux 是唯讀;短期動不了程式的站至少先換受限帳號
  5. A4快贏清單:flux.kng.tw 舊殼目錄移除、/var/www/salary 收整(實查 :6048 只在 ports.conf 留埠、無 vhost 綁定——清埠設定,站本體留作 C2 人資基底)、報表站兩套登入(unified-auth / session-auth)收成一套
  6. 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 帳號且權限與寫入權矩陣一致;矩陣成文並進版控

意象圖:工作人員把雜物與纜線搬出機房,門口立著一面帶鑰匙孔的盾牌
插圖 · 戰線 A把不屬於機房的東西搬出去、拔掉不該插著的線、門口只留一把鎖——全是搬移與設定,不動任何業務邏輯。
戰線 B 寫入權集中 ERP 核心 · 價值最高 · 也最危險

讓「會寫業務資料的程式」只剩 ERP 一份。改的是收單路徑,每一步都要能回頭。

  1. B1ERP 穩定化:對訂單建立、付款確認、配送異動、結帳過帳補 characterization tests(鎖住現狀行為,不判斷對錯);盤點所有寫入點與交易邊界;命令契約建在新殼(8/17 起,見 06 新殼規格)——以舊 ERP Api 現有的 11+4 支 controller(Sanctum+system.operator、V2 薄代理、README 六領域文檔)為藍本,每個命令有 idempotency key、狀態機、審計與 schema,版本針對契約。測試面起點差(10 個測試檔對 79 支 controller):characterization 跟著搬遷走、搬哪塊補哪塊,另建營運金絲雀組(見 06)
  2. B2對外站 strangler:新建對外站骨架後逐一搬——forms(同為 Laravel,最容易)→ ny26 活動頁 → shop → 最後才碰 www——它的 api/ 實測 58,321 行、90 條路由,比第四版以為的一萬行大 5.8 倍。每搬一塊,該塊的寫入改呼叫 ERP 命令;舊路徑照常寫入,新舊並行,每日自動比對筆數與金額、差異即告警——不靠人工對帳
  3. B3觀察兩個完整月結週期:月結、補帳、活動檔期都跑過,對帳告警連續綠燈,才進下一步
  4. B4才刪:外圍站的舊訂單/會員邏輯下線;ERP 死碼依 06 的判準分批刪,每批獨立 commit 可回滾

退出條件訂單、會員、帳務資料的唯一寫入者=ERP;新舊對帳告警連續兩個月結週期綠燈

顧客下單/表單 收單入口不變 對外站 goalu ERP 命令 API idempotency key · 審計 舊路徑:直接寫(先保持運作) 新路徑 命令寫入 每日對帳 job 比對兩邊筆數 × 金額 差異即告警 切換規則:對帳連續兩個完整月結週期綠燈(B3) → 才關閉舊路徑、退役外站訂單邏輯(B4)。 沒建好告警之前,不准切任何流量。
圖 4 · B2 雙寫對帳整份規劃最危險的一步的保險絲:新舊路徑同時寫、機器每天對帳、差異立刻告警——切換的依據是連續綠燈的資料,不是「看起來沒問題」。
戰線 C 站台歸併 降維護負擔 · 按痛點排程 · 條件觸發

網址與部署的收斂。每一項都等它依賴的 A/B 步驟完成才動,不搶跑。

  1. C1對內站:共用入口+SSO 先立起來,然後電訪名單(call_list)、report 93 支、FLUX 十頁 Volt BI、inventory、invoice 行政表單逐模組遷入。模組間硬邊界:各自的 route group、各自的 service 層,禁止跨模組直接讀對方 model;BI 一律走唯讀 DB 帳號(見 08 決策三)
  2. C2人資模組:以 /var/www/salary 的 Livewire 版為基底併入對內站(8/17 裁示:不獨立部署),合併 html/salary 的舊版薪資(實查為兩套)、吸收 invoice 的 /leave 請假。硬隔離配套一項不可少:薪資表專屬 DB 帳號、獨立 route+middleware、附件移出 web root、匯出審計。合併前用同一批員工同一個月份把兩套各跑一次比對——差異要先解釋
  3. C3行動入口 m.kng.tw(8/17 裁示):erp-next 行動區+PWA,業務員與配送員的手機主入口。先吸收 delivery 日誌與 sales 業務功能,再逐步搬 kn 的軌跡/積分/獎金——目標取代 kn(推翻 8/16 排除令),過渡期 kn 照跑;kn 與 delivery 分別在功能清空後退役
  4. 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 寫入時間的證據,不是感覺。

意象圖:多條細管收斂進唯一的閥門,再由一條粗管進入儲存槽;一條舊管已封蓋
插圖 · 戰線 B 的終態十四條各自為政的寫入管線,收斂成唯一一個閥門(ERP 命令 API)進槽(goalu);左下那條封蓋的舊管,就是 B4 退役的外站直寫路徑。

換表的真相:不是換完,是雙寫並行中

「訂單已從 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 就縮一點,沒有「搬完才上線」的里程碑
4AI 地基 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+DailyRenewtrades 三方寫入(估奶初估+業務異動+當日刷新)+ daily_orders「人工調整 vs 重估覆蓋」——帳務一致性心臟最高 留在舊 ERP 最久,前三階段跑穩後單獨動

測試策略兩層:搬哪塊、搬前先給那塊補 characterization tests(鎖現狀行為), 不對凍結程式全面補測;但另設一組不可省略的營運金絲雀——下單、估奶、路條、異動、 帳務彙總、既有讀者相容——用固定去識別資料集比對新舊輸出,金額/瓶數/配送戶數是硬門檻。 只測待搬頁面會漏掉跨系統契約,金絲雀補這個洞。

每個搬遷切片的完成定義(防止新殼變成第二套 ERP 的唯一機制): 舊入口關閉、舊 writer 停止、對應同步縮減、舊程式與排程可刪除——四項全達成才算搬完。 優先搬「完整的垂直業務能力」而不是只搬 CRUD 頁面; 雙寫收斂則按 A3 的 ownership matrix 執行(每張表唯一 writer、同步方向、每日 reconciliation)。

Shadow 估奶驗證:收回(8/17 裁決)

daily_orders_shadowdv_orders_shadow 是每日 07:00 的 SQL vs PHP 估奶比對機制 (DailyPreSql 寫影子 → DailyPre 寫正式 → EstimateCompare 對比告警),原始目的隨 sys 廢案消失。 ✓ 已於 8/17 執行:goalu.tasks 的 45(daily:pre-sql)與 46(estimate:compare)停用。影子表凍結觀察一個月結後清除,省下每日一次全量估奶計算。

死碼判準:HTTP log 只是第一層

「90 天沒流量」不等於死碼

月結、年結、補帳、季節性活動(年菜、中元)、排程 job、queue、artisan 指令、 外部 webhook、人工救援入口,都可能 90 天沒有一筆 HTTP 紀錄;call graph 也看不到動態呼叫。

判死要同時過五關,全過才進隔離區:

#檢查方法
1HTTP 流量access log 對照 417+63 條路由(實查 log 只留 14 天——先拉到 90 天以上再判)
2排程與 queue56 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 索引),這一節是把它變成每站標配並補上缺的兩塊。

意象圖:機器人拿著放大鏡巡檢一排打勾的儀表板,道路兩側有護欄、盡頭是檢查站閘門
插圖 · AI 好維運AI 擅長的是沿著護欄開車、在檢查站受檢——服務目錄是地圖、CI 護欄是欄杆、測試安全網是檢查站;缺了這些,AI 只能在沒有標線的路上猜。
地基內容現況
服務目錄 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決策點

決策一 · 已裁決 2026-08-17

shop 的獨立資料庫要不要併進 goalu?

要併,時點在戰線 B2 搬完 shop 之後,不當前置條件。(照建議)

理由不變:「網購買過什麼」連到「他是不是訂戶」是這次整合少數的新價值; shop 只有 7 張 model,是最小遷移面。先程式後資料,兩段分開做。

決策二 · 已裁決 2026-08-17(推翻建議)

薪資做對內站的權限模組,還是獨立站?

做對內站的權限模組,不獨立部署。原建議(獨立站)被裁示推翻。

代價是薪資與其他內部功能同 process、同部署——所以硬隔離配套是底線而非加分項: 薪資表專屬 DB 帳號(只掛人資模組的 connection)、獨立 route+middleware、附件移出 web root、 匯出一律過審計 log。並保留升級路徑:若發生一次跨模組事故,直接改獨立站。

決策三 · 2026-08-17 裁示:暫緩

報表與 BI(93 支+FLUX)怎麼接資料,才不會拖垮交易庫?

先不決定——C1 實際要搬報表時再議。屆時的預設方向仍是:專屬唯讀帳號+慢查詢監控,有數據再考慮 replica。

94 是單機,先做 replica 是過度工程。唯讀帳號本身就是戰線 A3 的一部分, 零額外成本;慢查詢監控已在運作,有數據再決定要不要 replica。

決策四 · 已裁決 2026-08-16

delivery(配送員日誌,Laravel 8.83,3 controller / 9 route)的去向?

8/16:kn 不整合 delivery、暫列存量。8/17 更新:delivery 併入行動入口 m.kng.tw 的配送員區,功能清空後退役。

「kn 不動」的前提也於 8/17 改變——新行動入口目標取代 kn(見決策六),delivery 自然歸入同一條收斂路徑。

決策五 · 已裁決 2026-08-17

ERP 越做越複雜、受限——要不要獨立開新專案?

要。同 schema 的 strangler 殼:新功能全進新專案、舊 ERP 凍結只修 bug、逐頁搬遷隨時可停。

配套三裁示:①資料紀律進 CI 靜態攔檢(新專案掃到舊表名就紅) ②入口用 erp.kng.tw 路徑分流(使用者無感、逐頁可回退) ③shadow 估奶驗證收回(DailyPreSql/EstimateCompare 停用,影子表觀察一個月結後清)。 節奏依 CBM 實測定為三大階段(見 06)——複雜度中等,不必碎步。

決策六 · 已裁決 2026-08-17

業務員與配送員以手機為主,入口怎麼跟客服內勤分開?

行動入口 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 值最高的四十八小時。