限制與風控規則
文件狀態:草稿 / 以 search_add 建立第一版架構
最後驗證:2026-05-07
來源:pro360_api_82 search_add code、既有 PHPUnit、Common Process Documents
目的
這裡整理「會限制使用者操作次數、阻擋流程、或因環境不同而改變判斷結果」的共同規則。
這類規則常見於:
- 提出需求次數上限
- 同分類 / 同專家 / 同案件重複操作限制
- Redis 防連點或短時間 rate limit
- production-only 風控
- 測試環境為了可重現而繞過或強制開啟的限制
完整 business flow 仍放在 業務流程;這裡只回答「限制在哪裡、怎麼算、環境是否有差異、測試怎麼避免誤判」。
不回答什麼
- 不重寫完整 API 流程。
- 不記錄單次測試 ID,除非是必要的誤判案例。
- 不把所有 guard 都列進來;只有會反覆影響測試、migration、排查的限制規則才放這裡。
- 不把 downstream queue / payment 規則混進來;那些放在 Queue、付款或 Log 對應文件。
文件架構
限制與風控規則/
README.md
search_add.md
redis_double_click.md
環境差異.md後續可依流程擴充:
quote_request_copy.md
provider_accept_narrow_match.md
want_to_contact_provider.md目前先建立:
| 文件 | 用途 |
|---|---|
| search_add | search_add 提出需求與發案前風控限制 |
| redis_double_click | Redis 短 TTL 防連點 / 去重的共同判讀方式 |
| 環境差異 | 測試、staging、production 對限制與風控規則的差異總覽 |
後續若某個限制跨多支 API 使用,再抽成獨立文件。例如 Redis 防連點可從 search_add / copy / payment 拆成 redis_double_click.md。
規則分類
| 類型 | 判斷方式 | 常見來源 | 例子 |
|---|---|---|---|
| DB count limit | 查資料表筆數與時間窗 | quote_requests, quote_bids | 同 user / category 24 小時內提出需求上限 |
| Redis short TTL | incrementKey() / isDoubleClick() | RedisUtil | 防連點、短時間重複操作 |
| daily marker | 每日一筆紀錄 | daily_access | 每日 user access activity,注意不是發案上限 |
| production-only | EnvFactory::getEnv() | code guard | 相同專業類別專家不可發案 |
| config-based | ProConfig / DB 設定 | config / category | quote.bid_count_limit, category flags |
| exception user / category | 寫死例外 | code constant / literal id | 特定 user 或 category 不套用限制 |
每條限制規則必寫欄位
新增限制文件時,至少寫清楚:
| 欄位 | 說明 |
|---|---|
| 規則名稱 | 例如「同分類 24 小時提出需求上限」 |
| 入口流程 | 例如 search_add, copy, provider_accept_narrow_match |
| 判斷時機 | 建資料前、建資料後、worker、付款前、通知前 |
| 限制條件 | user/category/request/provider/time window/count |
| 上限值 | 寫死值、config、DB 欄位或 Redis TTL |
| 使用資料 | table / Redis key / config |
| 環境差異 | 測試、staging、production 是否不同 |
| 例外條件 | official user、特定 category、特定 user id |
| 對外結果 | API error / message / status |
| 測試注意 | 需要 seed 幾筆資料、是否要清 Redis / DB side effect |
環境差異標示
限制規則必須特別標示「測試與正式環境是否一致」。
常見差異:
| 差異類型 | 說明 | 測試風險 |
|---|---|---|
| production-only guard | 非 production 直接跳過 | staging / PHPUnit 成功不代表 production 會成功 |
| force env flag | 測試用 env 強制開 production branch | 測試通過代表該 branch 可跑,不代表 staging 預設會跑 |
| Redis 開關 | use_redis 不同 | 防連點 / lock 在本機或測試環境可能不生效 |
| live DB drift | 測試資料會隨時間變動 | 24 小時 / 30 天 count 可能今天和明天不同 |
| worker timing | queue 被即時搬走 | 不要把查不到 queue row 當成限制沒跑 |
排查順序
遇到疑似「次數限制 / 風控擋住」時:
- 先確認 API response 的
error/message。 - 找到對應流程文件,例如 search_add。
- 確認限制是同步 guard、Redis、DB count 還是 production-only。
- 查使用資料前先確認 schema。
- 查環境設定與 env flag。
- 如果是測試,確認 fixture 是否已清理:
quote_requests
quote_request_limit_ids
daily_access
Redis key
queue / log side effect維護原則
- 不把「測試 fixture 為了製造限制」誤寫成產品規則。
- 不把
daily_access當成提出需求上限;它是每日 user access activity marker。 - 有時間窗的限制要寫明使用 DB
created、local timezone、還是 Redis TTL。 - 有 production-only 的限制要寫明 staging / PHPUnit 預設是否會跳過。
- 如果限制依賴 live DB count,測試文件要說明資料會漂移。