Skip to content

Commit 9febf5e

Browse files
authored
Merge pull request #91 from hideyukiMORI/feat/issue-89-field-trial-4
docs: Field Trial 4 レポート(SQLite共有MCP・ApiKey認証・CORSのDX検証)
2 parents 0ea5c3e + efe0be4 commit 9febf5e

1 file changed

Lines changed: 125 additions & 0 deletions

File tree

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Field Trial 4 — snippets: SQLite共有MCP・ApiKey認証・CORSのDX検証
2+
3+
## Date
4+
5+
2026-05-19
6+
7+
## Baseline
8+
9+
- nene2-python v0.1.0 (`uv add git+https://github.com/hideyukiMORI/nene2-python.git`)
10+
- Python 3.14.5(uv managed)
11+
- プロジェクト: **snippets** — コードスニペット管理 JSON API
12+
- エンティティ: `Snippet`(title, language, code)— 5 エンドポイント(CRUD)
13+
- **`SqlAlchemySnippetRepository`(SQLite ファイル)** — HTTP API と MCP が共有
14+
- **`ApiKeyAuthMiddleware`** ← FT1〜FT3 との差分①
15+
- **`CORSMiddleware`** ← FT1〜FT3 との差分②
16+
- **MCP + SQLite 共有** ← FT3-F2 の修正実証
17+
18+
## Goal
19+
20+
1. FT3-F2(MCP と HTTP API の状態共有)を SQLite で実証する
21+
2. `ApiKeyAuthMiddleware`(X-Api-Key ヘッダー)の設定体験を確認する
22+
3. `CORSMiddleware` の設定体験を確認する(FT3-F1 修正後の JSON 配列形式)
23+
4. 3 つを同時に組み合わせたときの摩擦を洗い出す
24+
25+
---
26+
27+
## Steps Taken
28+
29+
### 1. プロジェクト初期化・インストール
30+
31+
問題なし。FT1〜FT3 で確立されたパターン通り。
32+
33+
### 2. `.env` 設定
34+
35+
FT3-F1 修正後のドキュメントを参照。JSON 配列形式を迷わず使えた:
36+
37+
```dotenv
38+
API_KEYS=["ft4-api-key-1"]
39+
CORS_ORIGINS=["http://localhost:3000","http://localhost:5173"]
40+
```
41+
42+
→ FT3-F1 修正が効いていることを確認 ✓
43+
44+
### 3. ApiKeyAuthMiddleware
45+
46+
X-Api-Key なし → 401(`"A valid X-Api-Key header is required."`)✓
47+
X-Api-Key あり → 200 ✓
48+
49+
### 4. CORSMiddleware + ApiKeyAuthMiddleware の同時利用
50+
51+
最初の `add_middleware` 登録順:
52+
53+
```python
54+
# 誤った順序(最初に書いたコード)
55+
app.add_middleware(CORSMiddleware, ...) # 先に登録 = 内側
56+
app.add_middleware(ApiKeyAuthMiddleware, ...) # 後に登録 = 外側 ← preflight を遮断
57+
```
58+
59+
OPTIONS preflight → 401 になり CORS が機能しなかった(**F-1**)。
60+
61+
修正後(CORS を後に登録して外側にする):
62+
63+
```python
64+
app.add_middleware(ApiKeyAuthMiddleware, ...) # 先に登録 = 内側
65+
app.add_middleware(CORSMiddleware, ...) # 後に登録 = 外側 ← preflight が通る
66+
```
67+
68+
→ OPTIONS preflight → 200 + `access-control-allow-origin` 付き ✓
69+
70+
### 5. MCP + SQLite 状態共有(FT3-F2 実証)
71+
72+
HTTP API と MCP サーバーに同一の `DB_NAME=/tmp/ft4-snippets.db` を設定:
73+
74+
- HTTP API でスニペット作成 → MCP `list_snippets` で確認 → **見える**
75+
- MCP `create_snippet` で作成 → HTTP API `GET /snippets` で確認 → **見える**
76+
77+
FT3-F2 の修正(ドキュメントでの説明)が正しかったことを実動で証明。
78+
79+
---
80+
81+
## Friction Points
82+
83+
### F-1 CORS + Auth 同時利用時のミドルウェア登録順が非自明
84+
85+
**severity**: 高
86+
**type**: ドキュメント不足
87+
88+
`CORSMiddleware``ApiKeyAuthMiddleware`(または `BearerTokenMiddleware`)を
89+
同時に使う場合、**CORS を後に登録して外側に置かないと OPTIONS preflight が 401 になる**
90+
91+
Starlette の逆順ルール(後に登録したものが外側)は既にドキュメントにあるが、
92+
「CORS は Auth より外側にしなければならない」という組み合わせ固有のルールがない。
93+
94+
```python
95+
# 正しい登録順(コメントは実行時の順序)
96+
app.add_middleware(ErrorHandlerMiddleware, ...) # ① 最初に実行(最内側)
97+
app.add_middleware(SecurityHeadersMiddleware) #
98+
app.add_middleware(RequestIdMiddleware) #
99+
app.add_middleware(RequestLoggingMiddleware) #
100+
app.add_middleware(RequestSizeLimitMiddleware, ...) #
101+
app.add_middleware(ThrottleMiddleware, ...) # ⑥(任意)
102+
app.add_middleware(ApiKeyAuthMiddleware, ...) # ⑦ Auth
103+
app.add_middleware(CORSMiddleware, ...) # ⑧ 最後に実行(最外側)← CORS は必ず最後
104+
```
105+
106+
**Follow-up**: ミドルウェアの組み合わせパターンを `docs/reference/framework-modules.md`
107+
`docs/how-to/new-project.md` に追記する。
108+
109+
---
110+
111+
## Summary
112+
113+
| ID | 摩擦 | 深刻度 | 種別 | Follow-up Issue |
114+
|-----|-------------------------------------------------|--------|------------------|-----------------|
115+
| F-1 | CORS + Auth 同時利用時の登録順が非自明(preflight 401)|| ドキュメント不足 | #90 |
116+
117+
FT2/FT3 で修正した以下の項目はすべてスムーズに動作:
118+
- SQLite 永続化リポジトリパターン(#73
119+
- `write()` 返り値(#74
120+
- `db_url` 生成(#75
121+
- `list[str]` の JSON 配列形式(#81
122+
- MCP + SQLite 共有(#82)— 実動で証明
123+
124+
次回 FT5 は WebSocket または `SqlAlchemyTransactionManager.transactional()` の検証を推奨。
125+
または F-1 修正後に PyPI 公開フローに移行するタイミング。

0 commit comments

Comments
 (0)