---
title: I6 檢查結果：資料存取層
---

# I6 檢查結果：資料存取層

> 檢查日期 2026-09-09～10｜耗時 105 分鐘｜對應卡片 CM-1618｜**FR-081 最後一棒**

---

## 🔴 一句話結論

**工具在這 28 個檔裡沒找到問題，但首腦補查發現：這個套件建的六張資料表，完全沒有「每個客戶只能看自己資料」的隔離機制——連用來分辨客戶的欄位都沒有。**

---

## 這一棒在檢查什麼

問題單的資料怎麼存進資料庫、怎麼查出來——28 個檔案。

**為什麼「預期產出低」還是要檢查**：客戶資料隔離的最後一道防線就在這一層。FR-079 那次也是在同樣「預期低產出」的地方，查出一張表完全沒有隔離設定。

---

## 找到什麼

工具找到的兩條**都不在資料存取層**，是研究員追到範圍外的舊問題：

| # | 位置 | 狀態 |
|---|---|---|
| 1 | `github_issue_adapter.py:43` | **第六次被撈到**，重複 |
| 2 | `jedi_issue/.env` | 重複（CM-1573 舊案） |

**工具在這 28 個檔裡找到的新問題：0 個。**

---

## 🔴 首腦補查：卡片點名要查的兩件事

### 問題一：六張資料表完全沒有客戶隔離

**白話**：資料庫有一個機制叫 RLS（Row Level Security），作用是「**每個客戶只能看到自己的資料**」——就算程式寫錯了，資料庫這一層也會擋住。這是最後一道防線。

首腦逐張表去查出貨用的資料庫結構檔：

| 資料表 | 有開客戶隔離嗎 | 隔離規則幾條 | 有「這是哪個客戶的」欄位嗎 |
|---|---|---:|---|
| `issues`（問題單） | ❌ 沒有 | 0 | ❌ 沒有 |
| `labels`（標籤） | ❌ 沒有 | 0 | ❌ 沒有 |
| `members`（成員） | ❌ 沒有 | 0 | ❌ 沒有 |
| `issue_assignee_mapping` | ❌ 沒有 | 0 | ❌ 沒有 |
| `issue_label_mapping` | ❌ 沒有 | 0 | ❌ 沒有 |
| `issue_upload_file_mapping` | ❌ 沒有 | 0 | ❌ 沒有 |
| **`feedback_issues`**（主專案自己建的） | ✅ **有** | **4** | ✅ 有 |

**對比非常清楚**：主專案自己建的那張表，隔離機制完整；**套件建的六張表，一張都沒有。**

**這比 FR-079 查到的更徹底**：那次那張表至少還有「這是哪個客戶的」欄位，只是沒設隔離規則——補上規則就好。**這六張連欄位都沒有，要補隔離得先改資料表結構。**

### 這件事目前的實際影響：有限，但機制上沒有防線

首腦追了主專案怎麼用它：

```python
# app/feedback/service/issue_service.py 第 41 行
self.project_name = "CM"     # 寫死
# 第 46 行的註解：任一租戶建 feedback issue 都走這份平台設定
```

**目前所有客戶的意見回饋都寫進同一個「平台專案」，本來就是共用的**，不是「應該隔離卻沒隔離」。真正帶客戶身分的是主專案那張 `feedback_issues` 表（有隔離），使用者看到的清單經過它。

**所以現在不是可以被利用的漏洞。但有兩件事要記住**：

1. **資料庫層對這六張表沒有任何第二道防線**——`feedback_issues` 的隔離是唯一屏障。配合 I2 查到的「改／刪不檢查歸屬」，**沒有兜底**。
2. **哪天這個套件被用在需要客戶隔離的場景，會直接出事**——套件本身沒有隔離能力，這是設計缺口不是設定疏漏。

**處置**：判「低／設計註記」，**併入 CM-1630 的背景說明，不另開卡。**

### 問題二：問題單編號猜不猜得到？→ ✅ 猜不到

```python
# jedi_issue/common/utils/common_util.py
def generate_uuid():
    return str(uuid.uuid4())
```

**用的是 uuid4，是密碼學等級的隨機，猜不到。** 與 FR-079 那次的結論一致。

這件事重要，是因為如果編號可以猜，那些「只靠編號就能存取」的功能風險就會放大。**現在確認猜不到，那些功能的風險維持在原本判定的等級。**

---

## 📌 開卡時的一個小疏失（首腦自陳）

卡片的檢查範圍寫了一個**不存在的路徑**（`jedi_issue/infra/issue/mapper/`）。實際上 mapper 相關檔案都在 `label/` 和 `member/` 底下，**已經被其他路徑涵蓋了**。

工具照實指出了這件事。**檔案數 28 仍然對得上、沒有漏檢查**，但這是開卡時應該用指令逐條驗證卻沒做到位的地方。記錄下來給後面的棒次參考。

---

## 這份結果可信到什麼程度

### 「找到的是真的嗎」→ ✅ 可信

兩條都是 3 票全過，9 票全數投出、零漏投。首腦補查的隔離結論，是逐張表去核對出貨用的資料庫結構檔得出的。

### 「資料存取層乾淨嗎」→ ⚠️ 工具說沒問題，但**這是快篩模式的「沒問題」**

報告自己寫了一句很誠實的話：「**快篩模式下的『沒發現問題』，比徹底檢查後的『沒發現問題』證據力弱**」。

**而首腦補查證明了：工具的「沒發現問題」確實漏掉了東西**——那六張表沒有客戶隔離。

**為什麼工具看不到**：因為那不是「程式碼寫錯了」，是「資料表結構少了東西」。研究員讀的是程式碼，**資料庫結構不在他們的視野裡**。

**這是給後面棒次的重點**：資料庫層的問題要靠人主動去查資料表結構，不能等工具報。

---

## 執行概況（技術細節）

| 項目 | 數字 |
|---|---|
| 檢查範圍 | 28 個檔案 |
| 派出／回報的研究員 | 2 / 2 |
| 候選問題 → 去除重複 | 3 → 3 |
| 投票數 | 9 |
| 沒投到票的 | 0 |
| **範圍內新問題（工具）** | **0** |
| **首腦補查項目** | **2（其中一項是新發現）** |
| 耗時 | 105 分鐘 |
