📚職涯停看聽・知識庫← 總部儀表板
📅最後更新:2026/06/08
📑 目錄

SaaS 客戶擴張 SOP — 預約系統新客戶 Onboarding

最後更新:2026-06-08(v1.1 早期維護複查) 文件狀態:有效 負責部門:開發部(DEV)— SOP 主檔;法務部(LEG)— 服務協議與 DPA;策略部(STR)— 商業條款 適用範圍:預約系統 SaaS(shoppy09/my-booking-system)為新客戶在 Northflank 部署獨立實例的完整流程 參考實作:Tim 自用實例 www.careerssl.com/booking(C-Light 整合 2026-05-19;前身 booking.careerssl.com,Northflank 遷移 2026-04-20,見 dev/deploy-verify/SYS-04-2026-04-20.md


一、觸發條件

以下任一情境觸發本 SOP:

  1. 新付費客戶完成簽約(SaaS 服務協議 + DPA)
  2. 合作客戶申請使用(如姐姐-01 模式,免費或內部成本)
  3. 試用申請通過後(試用 14 天,到期需轉付費)

不觸發本 SOP 的情境

  • Tim 自用實例已部署完畢,無需重做
  • 客戶僅諮詢未簽約 → 走業務部外展流程
  • 程式碼異動部署 → 走既有 deploy SKILL(預約系統/.claude/skills/deploy/SKILL.md),客戶實例自動跟進

二、前置條件清單(8 項全達才啟動)

執行 SOP 前 Tim 必須確認:

  • ① 合約簽署:SaaS 服務協議已簽(模板:legal/saas-service-agreement-template.md,v1.0 2026-05-01 建立,14 章 + 2 附錄;⚠️ 正式簽約前建議律師審查)
  • ② DPA 簽署:資料處理協議已簽(若 MongoDB 採方案 A 同帳號,Tim = 資料處理者必簽 DPA;模板:legal/dpa-template.md,v1.0 2026-05-01 建立)
  • ③ 客戶資料齊備:第三章「客戶資訊收集表」7 欄全填
  • ④ 預算確認:客戶承擔費用 vs Tim 吸收費用已書面確認(包含 Northflank 月費 + MongoDB 升級可能 + Cloudinary 流量等)
  • ⑤ 技術可行性確認:Northflank Sandbox 額度 / MongoDB 容量 / Cloudinary 流量等預估在限制內,無立即超量
  • ⑥ 實例計費歸屬:Northflank service 費用走 Tim 帳號(含於服務費)vs 客戶自有 Northflank 帳號
  • ⑦ ⛔ 禁止業務類型確認:客戶業務性質不屬於:博弈 / 色情 / 詐騙 / 未授權醫療 / 政治宣傳 / 侵權商品 / 加密貨幣交易 / 任何違反台灣法律之業務
  • ⑧ ⛔ 客戶地理範圍:目前僅服務台灣境內客戶;境外客戶(GDPR 適用)需 LEG 額外審查 + GDPR Article 28 合約 + 跨境傳輸告知

WHY 8 項全達標準:任何一項缺失都可能導致法律糾紛、技術超量或商業誤解。前置條件比實作更重要。


三、客戶資訊收集表

執行此表後 Tim 應有完整的環境變數來源資料:

# 欄位 範例值 歸屬規則
1 客戶代號 client-shoppyA01 Tim 命名(建議 client- 前綴)
2 店名 SHOP_NAME 「美甲沙龍 OOO」 客戶提供
3 主題色 HEX THEME_PRIMARY_COLOR #C4622D 客戶提供(可附 brand guideline)
4 管理員帳密 ADMIN_USER / ADMIN_PASS Tim 生成隨機強密碼 Tim 生成 → 客戶首次登入後自改
5 MongoDB 隔離方式 A 同 Atlas / B 客戶自有 / C Tim Atlas 升級 詳見第四章決策樹
6 LINE OA 整合 LINE Channel Access Token 客戶必有(不可共用 Tim 帳號)
7 金流(ECPay 等) ECPay 商家帳號 + HashKey + HashIV 客戶必有(金流必須走客戶名義,不可掛 Tim 帳號)
8 SMTP 通知信 EMAIL_USER / EMAIL_PASS 可選:Tim 共用 Gmail / 客戶自有
9 Cloudinary 圖片上傳 Cloud name / API key / API secret 可選:Tim 共用(Tim 吸收流量成本)/ 客戶自有
10 域名選擇 A [name].careerssl.com / B 客戶自有 詳見第六章
11 是否接入 HQ 財務 是(合作關係,需 DPA)/ 否(純付費客戶資料隔離) 詳見第九章金流邊界

⛔ 必須客戶自有(不可妥協)

  • LINE Channel Access Token:一個 LINE OA 一個 token,technically 不可共用;commercially 訊息發送名義必須是客戶自身
  • ECPay / 任何金流商家帳號:金流走客戶名義,否則税務、糾紛、洗錢防制責任歸 Tim 不可

⚠️ 可選共用(記錄成本歸屬)

  • SMTP(共用 Tim Gmail):Tim 吸收流量;建議客戶量 ≥ 5 時轉付費 SMTP(如 SendGrid)
  • Cloudinary(共用 Tim 帳號):Tim 吸收 25GB/月免費額度;超量需升 $99/月

四、MongoDB 設定決策(A/B/C 三方案)

方案 適用情境 優點 缺點 法律意涵
A 同 Tim Atlas + 不同 db 合作關係(如姐姐)/ 試用客戶 成本 0 / 設定快(5 min) Tim 技術可看資料 / M0 共用 512MB(3 客戶後撞牆)/ 無自動備份 ⛔ Tim = 資料處理者,必簽 DPA
B 客戶自有 Atlas 付費客戶(隱私敏感業務) 資料完全隔離 / 客戶自負容量 / Tim 法律責任最低 客戶需自設 Atlas / 客戶須付 Atlas 費用 ✅ 客戶自為控制者 + 處理者,無 DPA 需求
C Tim Atlas M10+ 付費 Tim 客戶數 ≥ 3 含自動備份 / 大容量(10GB+)/ 集中管理 Tim 月費 $57+ 起跳 / 仍需 DPA ⛔ Tim = 資料處理者,必簽 DPA;建議費用攤入服務費

容量觸發點

  • 方案 A:客戶 ≥ 3 → 強烈建議轉 B 或 C(M0 512MB 不足)
  • 方案 C:每月監控 Atlas 用量,達 80% 規劃升級

五、Northflank 部署 10 步驟

⚠️ 接入前必查 Northflank 當下定價政策(Sandbox 免費額度可能變動,不寫死數字)

Step 5.1:登入 Northflank → 建立 Service

  1. 登入 https://app.northflank.com
  2. 選擇 Project(建議用 tzlth-saas 統一管理 / 或客戶自有 project)
  3. New Service → Combined service(同 Tim 自用實例設定)
  4. Source:GitHub shoppy09/my-booking-system
  5. Branch:main
  6. Build type:Buildpack 或 Dockerfile(依 repo 設定)
  7. Plan:nf-compute-10(Sandbox 免費,0.1 vCPU + 256MB)

Step 5.2:⛔ 啟用 GitHub auto-deploy on main 分支

  • Source 設定欄勾選「Auto-deploy on push to main」
  • WHY:未來 repo 異動時客戶實例自動跟進,避免「靜默漂移」

Step 5.3:環境變數設定(依 .env.example 20+ 變數,詳見附錄 A)

強制每實例獨立

  • JWT_SECRET:必獨立!生成指令:
    node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"
    
    WHY:跨實例共用 JWT_SECRET = token 互通 = 安全漏洞
  • ADMIN_USER / ADMIN_PASS:必獨立
  • MONGODB_URI:依方案 A/B/C 不同
  • BASE_URL / APP_URL:填 Northflank 給的暫時 URL(後續改 custom domain)
  • SHOP_NAME / THEME_*:依客戶資料

可共用(看歸屬決策):

  • SMTP / Cloudinary 變數

詳見附錄 A 環境變數對照表

Step 5.4:首次部署 → 等 build 完成(約 3-5 分鐘)

Step 5.5:驗證 ping endpoint

  • curl https://<northflank-url>/api/ping → 預期 {"status":"ok"}

Step 5.6:驗證 stats endpoint

  • curl https://<northflank-url>/api/stats → 預期 {total: 0, thisWeek: 0, thisMonth: 0}(新客戶為 0)

Step 5.7:自訂域名綁定(見第六章)

Step 5.8:SSL 自動申請(Let's Encrypt 自動,等 5-10 min)

Step 5.9:健康檢查設定

  • Northflank service → Health checks → /api/ping path → 30s interval

Step 5.10:UptimeRobot 監控加入

  • 加入 Tim 既有 UptimeRobot 帳號 → URL: https://<custom-domain>/api/ping
  • 告警:Tim 為主 + 客戶為副(Email + LINE)

Step 5.11:Google Calendar 整合(選填,推薦開啟)

⚠️ 若不設此兩個 env var,Calendar 同步功能靜默失敗(無錯誤訊息),客戶後台手動新增預約不會同步至 Google Calendar

  1. Google Cloud Console → 建立 Service Account → 下載 JSON 金鑰
  2. 把 JSON 轉為單行(所有換行符 → \n
  3. 客戶的 Google Calendar → 設定 → 與特定使用者共用 → 加入 Service Account email → 權限「編輯事件」
  4. Northflank env var 填入:
    • GOOGLE_CALENDAR_ID:行事曆 ID(格式:xxx@group.calendar.google.com 或 Gmail 地址)
    • GOOGLE_SERVICE_ACCOUNT_JSON:整個 JSON 字串(單行,含 \n
  5. Northflank service → Redeploy → 建立一筆測試預約 → 確認 Google Calendar 出現含 Google Meet 連結的事件

六、域名設定(A 子域名 / B 客戶自有)

方案 A:[name].careerssl.com 子域名

  1. 確認 careerssl.com DNS 託管方:⚠️ 首次執行此 SOP 的 Tim 必須在此填入並提交 PR 更新本 SOP(Cloudflare / Vercel DNS / 中華電信 / GoDaddy / 其他:____)
  2. DNS 託管後台 → 加 CNAME:
    Type: CNAME
    Name: [client-name]   (例:shoppyA01)
    Target: site--my-booking-system--xxx.code.run  (Northflank service URL)
    TTL: Auto / 3600
    
  3. Northflank → service → Domains → Add custom domain → shoppyA01.careerssl.com
  4. 等 DNS 傳播(5-30 min)+ SSL 自動申請

方案 B:客戶自有域名

  1. 客戶 DNS 後台 → 加 CNAME:
    Name: booking (or @ for root)
    Target: site--my-booking-system--xxx.code.run
    
  2. Northflank custom domain 加客戶域名
  3. SSL 自動申請

域名選擇權衡

維度 方案 A 子域名 方案 B 客戶自有
設定難度 低(Tim 全處理) 中(需客戶配合 DNS)
品牌 careerssl 主品牌污染風險 客戶獨立品牌
SEO careerssl 整體 SEO 受影響 客戶自有 SEO
成本 0 客戶自有域名年費
推薦 試用客戶 / 合作關係 付費客戶 / 重視品牌獨立

七、驗收清單(10 項全打勾才交付)

  • 主頁載入正常(前台 / 客戶域名 / SSL 綠鎖)
  • 後台登入正常(管理員帳密可登入)
  • 預約完整流程跑通(選方案 → 選時段 → 填資料 → 收 Email 確認)
  • SSL 有效(/api/ping HTTPS 200)
  • 主題色正確顯示(依 THEME_* env var)
  • SMTP 寄信成功(測試預約後收到通知信)
  • LINE OA 設定(如有):webhook URL 已更新為 https://<domain>/api/line-webhook
  • 評價邀請信流程(如有開啟)
  • 付款流程(ECPay / 銀行匯款,如有)
  • UptimeRobot 監控已加入並收到首次 OK 訊號
  • Google Calendar 整合(如有設定):建立測試預約 → 確認 Google Calendar 出現含 Google Meet 連結的事件

任一項失敗 → 不可交付,先排除問題(見第十章故障處理)


八、客戶交付包

交付給客戶的 5 項物件

  1. 前台 URLhttps://[domain]/(讓客戶分享給其顧客)
  2. 後台 URLhttps://[domain]/admin
  3. 管理員帳密:⛔ 透過安全管道交付(建議 1Password / Bitwarden 共享庫;不建議 LINE 訊息明文;客戶首次登入後強制自改密碼)
  4. 操作手冊連結:建議建立 knowledge/operations/booking-system-user-manual.md(待補 P3)
  5. 緊急聯絡方式:Tim LINE / Email / 預約系統管理員聯絡資訊

交付後 Tim 留檔

  • 客戶代號 / 域名 / Northflank service ID / MongoDB 方案 → 寫入 business/saas-clients-registry.md(待建)
  • onboard 日期 / 預估月費 / 服務費起算日 → 同上
  • 簽妥的 SaaS 協議 + DPA → legal/signed/[client-code]-YYYY-MM-DD.pdf

九、計費、權責、金流邊界

9.1 Northflank 費用

⚠️ 執行 SOP 前必查當下 Northflank 定價https://northflank.com/pricing)

當前已知(2026-04-30,可能變動):

  • Sandbox nf-compute-10:免費(限額度,達上限後新增 service 需付費或升級)
  • 生產級 plan:依 vCPU / RAM / 流量計費

9.2 Tim 服務費結構(建議)

模式 月費(建議) 涵蓋
試用 0 14 天試用,超過轉付費
基礎 NT$1,500-2,500 / 月 基本部署 + 維運 + 程式碼自動更新
進階 NT$3,000-5,000 / 月 基礎 + MongoDB 升級攤分 + 客製主題 + 優先支援
一次性建置費 NT$5,000-10,000 首次 onboard 工時費(含資料遷移、客製化)

數字為起跳建議,Tim 依客戶業務規模調整

9.3 ⛔ 金流邊界(FINANCE_SYNC_TOKENS 安全分流)

預約系統 server.js L286-298 已實作 multi-tenant token 機制(FINANCE_SYNC_TOKENS 環境變數):

客戶類型 FINANCE_SYNC_TOKENS 是否加 entry 理由
付費 SaaS 客戶 不加 Tim 不應看到客戶業務數據(違反 DPA);客戶收入歸客戶
合作關係客戶(如姐姐) ✅ 可加(需簽 DPA) 數據回流 HQ 財務系統,便於 Tim 看到家族整體
Tim 自用實例 ✅ 加(既有) 自家數據歸自家

9.4 客戶端金流(ECPay 等)權責

  • 客戶實例的金流走客戶 ECPay 商家帳號,款項直接入客戶銀行
  • Tim 的 SaaS 服務費另開發票收取,不從客戶業務金流抽成
  • 此分流避免:① 洗錢防制法責任 ② 統一發票稅務責任 ③ 客戶資金安全

十、回滾與故障處理

常見問題排查

# 故障 排查順序
1 部署失敗(Northflank build 紅燈) ① 看 build log → ② 確認 Node 版本(package.json engines)→ ③ 確認所有必填 env var 已設
2 DNS 不傳播(SSL 卡住) dig +short [domain] 確認 CNAME ② 等 30 min(部分 DNS 需更久)③ Northflank custom domain 重新 verify
3 SSL 申請失敗 ① 確認 DNS 已正確指向 ② Northflank Domains → 重新 issue certificate ③ 24h 後仍失敗 → 聯絡 Northflank support
4 MongoDB 連線錯(後台 stats 為空 / 預約失敗) ① 確認 MONGODB_URI 正確 ② Atlas Network Access → IP whitelist 加 0.0.0.0/0(或 Northflank egress IP)③ 確認 db user 權限

回滾流程

  • 部署失敗無法修 → Northflank rollback to last known good revision
  • 客戶域名綁錯 → 移除 custom domain → 重設定
  • 環境變數錯 → service settings → variables → 修正 → redeploy

十一、客戶解約與終止流程

觸發條件

  • 客戶到期不續費(試用未轉付費 / 付費不續)
  • 雙方協議終止
  • 客戶違反禁止業務條款(觸發強制終止)

Step 11.1:暫停期(30 天,資料保留)

  1. Northflank service → Pause(不刪除)
  2. DNS CNAME 不釋放(保留 30 天,給客戶反悔空間)
  3. 通知客戶:暫停日期 + 30 天後永久刪除 + 資料導出選項

Step 11.2:資料導出(客戶要求才執行)

  • 從 MongoDB 匯出該客戶 db → JSON / CSV
  • 加密傳輸給客戶(密碼另管道告知)
  • 30 天後 Tim 端自有副本刪除

Step 11.3:30 天後永久終止

  1. Northflank service → Delete
  2. DNS CNAME 移除
  3. MongoDB db drop(方案 A 同帳號)/ 通知客戶自行 Atlas 終止(方案 B/C)
  4. UptimeRobot 監控移除
  5. business/saas-clients-registry.md 標記 status: terminated + 終止日期

Step 11.4:終止確認文件

  • 雙方簽署終止確認書
  • 存檔 legal/signed/[client-code]-termination-YYYY-MM-DD.pdf

違反禁止業務條款的特殊終止

  • 立即暫停 service(不給 30 天緩衝)
  • 通知客戶 + 法務行動準備
  • 資料保留待法務指示

十二、SLA 草案 + 異動通知 SOP

SLA(best-effort,正式約定見 SaaS 服務協議)

項目 標準
系統可用性 99% / 月(best-effort,依 Northflank Sandbox 性能)
故障回應時效 工作日 4h / 假日 24h
故障修復時效 一般 24h / 重大 72h
計畫性停機 提前 7 天通知

異動通知 SOP(程式碼異動觸發)

異動性質 通知時效 通知管道
一般 patch(bug fix / 小功能) 不通知(滾動部署)
breaking change(API 變更 / 重大功能) 提前 7 天 LINE / Email
重大停機(DB 遷移 / 架構變更) 提前 14 天 LINE / Email + 確認回覆

客戶端的「滾動部署」期待管理

  • 一般客戶不需知曉每個 patch(採用 SaaS 即接受持續演進)
  • 但 breaking change 必須通知,避免客戶端整合斷裂

十三、SOP 維護週期

觸發複查

  • 每 6 個月(2026-10-30 觸發首次複查)
  • 每次新客戶 onboard 時 Claude 主動驗證 SOP 是否需更新(執行此 SOP 時順便複查)
  • Northflank / MongoDB Atlas / Cloudinary 政策有重大變動時

複查內容

  • Northflank 定價是否變動?
  • MongoDB Atlas M0 限制是否變動?
  • 預約系統 .env.example 是否新增變數?
  • 既有客戶是否反映哪一步驟難用 / 不清楚?
  • 法律環境是否變動(GDPR / 個資法修訂)?

維護紀錄

版本 日期 變更內容
v1.0 2026-04-30 首次建立(從 Tim 自用實例 2026-04-20 經驗 + 三輪查照盲點補正萃取)
v1.1 2026-06-08 早期維護複查(觸發:Calendar 整合 + C-Light URL 更新):§十三 五項複查清單全評估;Appendix A 新增 7 個 env var(GOOGLE_CALENDAR_ID / GOOGLE_SERVICE_ACCOUNT_JSON / LINE_FRIEND_URL / ADMIN_EMAIL / BANK_ACCOUNT_NAME / TELEGRAM_BOT_TOKEN / TELEGRAM_CHAT_ID);§五 新增 Step 5.11(Google Calendar 整合);§七 驗收清單補 Calendar 驗收項;§一 Tim 自用 URL 更新 booking.careerssl.com → www.careerssl.com/booking;相關文件 11+→20+;Northflank/MongoDB M0/個資法 2026 現況確認

附錄 A:環境變數對照表(每實例獨立 vs 共用)

變數 必填 獨立性 來源 備註
MONGODB_URI 每實例獨立(A: db name 不同;B/C: connection string 不同) 依方案 A/B/C 包含敏感帳密
JWT_SECRET ⛔ 強制獨立 crypto.randomBytes(64).toString('hex') 共用 = 安全漏洞
ADMIN_USER 強制獨立 Tim 設定(建議客戶代號) -
ADMIN_PASS 強制獨立 隨機強密碼 客戶首次登入後自改
EMAIL_USER / EMAIL_PASS 可共用 / 客戶自有 依客戶選擇 共用 Tim Gmail 需注意流量
SHOP_NAME 每實例獨立 客戶提供 -
BASE_URL / APP_URL 每實例獨立 客戶域名 -
BANK_NAME / BANK_CODE / BANK_ACCOUNT 每實例獨立 客戶銀行 -
THEME_PRIMARY_COLOR 每實例獨立 客戶 brand -
LINE_CHANNEL_ACCESS_TOKEN ⛔ 客戶必有 客戶 LINE OA 不可共用
LINE_ADMIN_USER_ID ⛔ 客戶必有 客戶端管理員 LINE ID -
ECPAY_* ⛔ 客戶必有 客戶 ECPay 商家 金流必須走客戶名義
CLOUDINARY_* 可共用 / 客戶自有 依客戶選擇 共用 Tim 帳號需 25GB/月留意
GOOGLE_CALENDAR_ID 每實例獨立 Google Calendar 行事曆 ID 格式:xxx@group.calendar.google.com不填 = Calendar 整合靜默失敗
GOOGLE_SERVICE_ACCOUNT_JSON 每實例獨立 GCP Service Account JSON(單行) 需先建立 Service Account + 共享日曆編輯權限;見 §五 Step 5.11
LINE_FRIEND_URL 每實例獨立 LINE 加好友連結(顯示在確認信中) 格式:https://lin.ee/xxx
ADMIN_EMAIL 每實例獨立 管理員信箱(接收系統錯誤通知) 與 ADMIN_USER 可不同
BANK_ACCOUNT_NAME 每實例獨立 銀行帳戶名稱(匯款資訊) 搭配 BANK_NAME / BANK_CODE / BANK_ACCOUNT 使用
TELEGRAM_BOT_TOKEN / TELEGRAM_CHAT_ID 每實例獨立 Telegram 通知(LINE 替代方案) 客戶無 LINE OA 時可用
FINANCE_SYNC_TOKENS ⛔ 不對付費客戶開放 僅 Tim 自用 + 合作客戶 詳見第 9.3
BOOKING_STATS_URL 不適用客戶實例 僅 HQ 儀表板用 客戶實例不需設此

附錄 B:監控告警分流設定

監控項目 主收人 副收人
UptimeRobot /api/ping Tim Email + LINE 客戶 Email
Northflank service 狀態 Tim(Northflank 介面) -
MongoDB Atlas 容量告警 Tim Email(方案 A/C)/ 客戶(方案 B) -
SSL 即將過期(30 天內) Tim Email -
月度檢視會議 每月與客戶 30 min review(電話 / LINE) -

相關文件

  • 預約系統 CLAUDE.md L66-90「多客戶架構」(C:\Users\USER\Desktop\CLAUDE寫工具\給別人\預約系統\CLAUDE.md)
  • 預約系統 .env.example(20+ 變數完整清單)
  • Tim 自用實例參考:dev/deploy-verify/SYS-04-2026-04-20.md
  • 法務模板(待建):legal/saas-service-agreement-template.md / legal/dpa-template.md
  • 客戶登錄表(待建):business/saas-clients-registry.md
  • 既有 deploy SKILL(程式碼異動,非 onboarding):預約系統/.claude/skills/deploy/SKILL.md
  • RCF-009 daily-revenue API SaaS 擴張前置設計:knowledge/decisions/RCF-009-finance-architecture.md
← 返回 操作 SOP