Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ nix develop --command bash -c "cd web && npm run test:e2e"
| 正本(変更したら) | 再生成コマンド | コミットすべき生成物 | CI ジョブ |
|---|---|---|---|
| backend の OpenAPI スキーマ(`app/schemas/` の Pydantic、router のシグネチャ・query/path パラメータ・**endpoint/schema の docstring**) | `make codegen-types` | `web/src/api/generated.ts`(`backend/openapi.json` は gitignore で対象外) | `codegen-drift`(ADR-0007) |
| backend の依存定義(`backend/pyproject.toml` の `[project.dependencies]`) | `cd backend && uv lock`(nix devshell 経由) | `backend/uv.lock` | `test-backend` / `codegen-drift` の `uv sync --locked`(ADR-0021 Phase 0) |

- **判定基準**: 「OpenAPI スペックに出るものを変えたか」。エンドポイントの追加・削除、リクエスト/レスポンス型の変更、query/path パラメータの増減はもちろん、**docstring の文言変更だけでも description として spec に反映される**ため再生成が要る(今回の codegen-drift はこれで発生)。
- backend の `app/schemas/` / `app/routers/` を触ったら、`make ci` 前に `make codegen-types` を回して `git diff web/src/api/generated.ts` を確認する。差分が出たら必ず同じ PR でコミットする。
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/SEC_apply/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ Missing Exploit Tests: 4
- 設計変更は必ず後述の exploit テストとセットで固定する。
7. **依存 / サプライチェーン対応**:
- CVE 解消のバージョン更新は `--force` で無視せず該当パッケージを更新(`.claude/rules/security.md` の依存関係節)。更新後に再度 audit を回して解消を確認。
- 緩いバージョン指定は pin(`requirements.txt` の `==` / lockfile commit)に寄せる。
- 緩いバージョン指定は pin(`backend/pyproject.toml [project.dependencies]` の `==` + `uv.lock` / lockfile commit)に寄せる。
- GitHub Actions の `uses:` がタグ参照なら commit SHA 固定へ(直近 commit「GitHub Actions のサプライチェーン保護」の方針を踏襲)。
- 不審な新規依存(typosquatting / dependency confusion / postinstall)は導入を止め、代替を提案。
8. **Missing Exploit Tests(攻撃者視点の回帰テスト)**:
Expand Down
6 changes: 3 additions & 3 deletions .claude/skills/SEC_review/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,13 @@ description: Use when running a security review / vulnerability check against th

### 13. 依存監査 / サプライチェーン攻撃リスク(Dependency & Supply Chain)

既知 CVE だけでなく「依存経路そのものが攻撃面になる」観点で見る。CI には既に audit が配線済み(`.github/workflows/ci.yml`: `npm audit --audit-level=high` / `uv tool run pip-audit -r requirements.txt`)なので、ローカルでは差分の妥当性確認に重点を置く。
既知 CVE だけでなく「依存経路そのものが攻撃面になる」観点で見る。CI には既に audit が配線済み(`.github/workflows/ci.yml`: `npm audit --audit-level=high` / uv.lock を export した requirements への `pip-audit`)なので、ローカルでは差分の妥当性確認に重点を置く。

- **既知 CVE スキャン**(実行可能なら):
- `nix develop --command bash -c "cd web && npm audit --audit-level=high"`
- `nix develop --command bash -c "cd backend && uv tool run pip-audit -r requirements.txt"`(実行できなければ「未実行・要手動」と記録。**本 skill で新規ツール導入はしない**)
- `nix develop --command bash -c "cd backend && uv export --frozen --no-emit-project --no-hashes --format requirements-txt --output-file /tmp/req-audit.txt && uv tool run --python 3.13 pip-audit -r /tmp/req-audit.txt"`(実行できなければ「未実行・要手動」と記録。**本 skill で新規ツール導入はしない**)
- High / Critical を Findings に取り込む
- **バージョン固定 / lockfile 整合**: 直接依存にレンジ指定(`^` / `~` / `*` / `>=` のみ)が無いか、lockfile(`package-lock.json` / `uv.lock` 等)が commit され integrity hash を持つか。`requirements.txt` が pin(`==`)されているか。
- **バージョン固定 / lockfile 整合**: 直接依存にレンジ指定(`^` / `~` / `*` / `>=` のみ)が無いか、lockfile(`package-lock.json` / `uv.lock` 等)が commit され integrity hash を持つか。`backend/pyproject.toml` の `[project.dependencies]` が pin(`==`)されているか(ADR-0021 Phase 0)
- **GitHub Actions のピン留め**: `uses:` がタグ(`@v4`)ではなく commit SHA で固定されているか(直近 commit「GitHub Actions のサプライチェーン保護」で対応済みの方針を維持。`rg -n 'uses:.*@v[0-9]' .github/workflows` で SHA 未固定を検出)。
- **新規・更新依存の素性**: 差分で追加された依存があれば、メンテ状況・ダウンロード規模・typosquatting(正規パッケージ名との1文字違い)・dependency confusion(社内名と公開名の衝突)を確認。`postinstall` / ビルドスクリプトを持つ npm パッケージは特に注視。
- **取得元の信頼性**: パッケージ取得が公式レジストリ(npm / PyPI)以外(任意 git URL / 直リンク tarball)を指していないか。
Expand Down
9 changes: 5 additions & 4 deletions .github/renovate.json5
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
prHourlyLimit: 4,

// lockfile / locked input を定期的にリフレッシュする
// (package-lock.json / flake.lock / .terraform.lock.hcl)
// (package-lock.json / uv.lock / flake.lock / .terraform.lock.hcl)
lockFileMaintenance: {
enabled: true,
schedule: ["before 9am on monday"],
Expand All @@ -48,9 +48,10 @@
groupName: "github-actions",
},
{
// Python (backend/requirements.txt): == 完全固定を維持して版上げ PR を出す。
// CVE コメント付き行(anthropic / google-genai / starlette 等)も対象。
matchManagers: ["pip_requirements"],
// Python (backend/pyproject.toml [project.dependencies] + uv.lock / ADR-0021 Phase 0):
// == 完全固定を維持して版上げ PR を出す。pep621 manager が pyproject を更新し、
// uv.lock も同一 PR で追従する。CVE コメント付き行(anthropic / starlette 等)も対象。
matchManagers: ["pep621"],
rangeStrategy: "pin",
},
{
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/mutation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
with:
version: "latest"
enable-cache: true
cache-dependency-glob: "backend/requirements.txt"
cache-dependency-glob: "backend/uv.lock"

- name: Setup Python
run: uv python install 3.13
Expand All @@ -57,9 +57,10 @@ jobs:
libpango-1.0-0 libpangoft2-1.0-0 libpangocairo-1.0-0 \
libglib2.0-0 libgobject-2.0-0 libffi-dev libcairo2

# --locked: uv.lock が pyproject.toml と drift していたら fail する(ADR-0021 Phase 0)
- name: Install backend dependencies
working-directory: backend
run: uv pip install -r requirements.txt
run: uv sync --locked

# 生存ミュータントがあっても集計と通知は行うため continue-on-error にする
- name: Run mutmut
Expand Down
36 changes: 20 additions & 16 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -174,32 +174,39 @@ jobs:
with:
version: "latest"
enable-cache: true
cache-dependency-glob: "backend/requirements.txt"
cache-dependency-glob: "backend/uv.lock"

- name: Setup Python
run: uv python install 3.13

- name: バージョン確認
working-directory: backend
run: |
echo "Python : $(uv run python --version)"
echo "uv : $(uv --version)"
echo "ruff : $(uv run ruff --version)"

- name: WeasyPrint 用システムライブラリのインストール
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
libpango-1.0-0 libpangoft2-1.0-0 libpangocairo-1.0-0 \
libglib2.0-0 libgobject-2.0-0 libffi-dev libcairo2

# --locked: uv.lock が pyproject.toml と drift していたら fail する(ADR-0021 Phase 0)
- name: Install backend dependencies
working-directory: backend
run: uv pip install -r requirements.txt
run: uv sync --locked

- name: バージョン確認
working-directory: backend
run: |
echo "Python : $(uv run --no-sync python --version)"
echo "uv : $(uv --version)"
echo "ruff : $(uv run --no-sync ruff --version)"

# uv.lock の全依存(推移的依存込み)を requirements 形式へ export して監査する。
# --python 3.13: 監査時の依存解決を requires-python (==3.13.*) に合わせる
# (ツール既定の Python が 3.12 以下だと 3.13+ 必須の依存で解決に失敗する)
- name: 脆弱性スキャン (pip-audit)
working-directory: backend
run: uv tool run pip-audit -r requirements.txt
run: |
uv export --frozen --no-emit-project --no-hashes \
--format requirements-txt --output-file /tmp/requirements-audit.txt
uv tool run --python 3.13 pip-audit -r /tmp/requirements-audit.txt

- name: Lint backend
working-directory: backend
Expand Down Expand Up @@ -238,7 +245,7 @@ jobs:
with:
version: "latest"
enable-cache: true
cache-dependency-glob: "backend/requirements.txt"
cache-dependency-glob: "backend/uv.lock"

- name: Setup Python
run: uv python install 3.13
Expand All @@ -250,13 +257,10 @@ jobs:
libpango-1.0-0 libpangoft2-1.0-0 libpangocairo-1.0-0 \
libglib2.0-0 libgobject-2.0-0 libffi-dev libcairo2

- name: Create virtualenv
working-directory: backend
run: uv venv

# --locked: uv.lock が pyproject.toml と drift していたら fail する(ADR-0021 Phase 0)
- name: Install backend dependencies
working-directory: backend
run: uv pip install -r requirements.txt
run: uv sync --locked

- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ __pycache__/
*.egg-info/
.venv/
venv/
uv.lock
.coverage
htmlcov/

Expand Down
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,10 @@ setup: install-hooks install-backend install-web
install-hooks:
./scripts/setup-git-hooks.sh

# 依存の SSoT は backend/pyproject.toml [project.dependencies] + uv.lock(ADR-0021 Phase 0)。
# uv sync が uv.lock から .venv を構成する(.venv 廃止は Phase 1)。
install-backend:
nix develop --command bash -c "cd backend && (.venv/bin/python --version > /dev/null 2>&1 || (rm -rf .venv && uv venv)) && uv pip install --python .venv/bin/python -r requirements.txt"
nix develop --command bash -c "cd backend && uv sync"

install-web:
nix develop --command bash -c "cd web && npm ci"
Expand Down Expand Up @@ -265,7 +267,7 @@ metrics-ai-friendliness:
# 使用 OSS ライセンス一覧
# ------------------------------------------------------------------ #

# 直接依存 OSS の一覧と各ライセンスを web/package.json・backend/requirements.txt
# 直接依存 OSS の一覧と各ライセンスを web/package.json・backend/pyproject.toml
# から収集し THIRD_PARTY_LICENSES.md を再生成する。importlib.metadata を使うため
# backend の依存がインストール済みの Nix devshell 経由で実行する。
licenses:
Expand Down
15 changes: 12 additions & 3 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,16 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
&& rm -rf /var/lib/apt/lists/*

COPY requirements.txt ./
# 依存の SSoT は pyproject.toml + uv.lock(ADR-0021 Phase 0)。
# 本番ビルドの pip wheel → pip install 経路は変えず、lock から requirements.txt を
# ビルド時に生成して従来経路へ渡す(pip の Nix build 化は Phase 3 で行う)。
# uv 自体も供給網方針(P7)に合わせて == で固定する。
# --no-hashes: final stage はローカルビルドした wheel を install するため、
# sdist のハッシュ検証を要求すると不一致で失敗する
COPY pyproject.toml uv.lock ./
RUN pip install --no-cache-dir uv==0.8.17 \
&& uv export --frozen --no-emit-project --no-hashes \
--format requirements-txt --output-file requirements.txt

# wheel を /build/wheels に集約しておき、final stage で再利用する
RUN pip wheel --no-cache-dir --wheel-dir=/build/wheels -r requirements.txt
Expand All @@ -45,9 +54,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libglib2.0-0 libgobject-2.0-0 libffi-dev libcairo2 \
&& rm -rf /var/lib/apt/lists/*

# builder stage でビルドした wheel を流用して高速・確実に install する
# builder stage でビルドした wheel と、lock から生成した requirements.txt を流用する
COPY --from=builder /build/wheels /wheels
COPY requirements.txt ./
COPY --from=builder /build/requirements.txt ./
RUN pip install --no-cache-dir --no-index --find-links=/wheels -r requirements.txt \
&& rm -rf /wheels

Expand Down
59 changes: 59 additions & 0 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,62 @@
# 依存の SSoT は本ファイルの [project.dependencies] + uv.lock(ADR-0021 Phase 0)。
# 追加・更新後は `cd backend && uv lock` で uv.lock を再生成してコミットすること。
# 供給網リスク(レンジ内 yank / 侵害バージョンの混入)を避けるため全依存を == で固定する(P7)。
# CVE は CI の pip-audit が検出するので、検出時に明示バージョンを引き上げる運用とする。
[project]
name = "devforge-backend"
version = "0.0.0"
description = "DevForge backend (FastAPI)"
# libsql-experimental(sqlalchemy-libsql 経由)が Python 3.14 未対応のため 3.13 系に固定する
# (renovate.json5 の allowedVersions "<3.14" と同期)
requires-python = "==3.13.*"
dependencies = [
"fastapi==0.139.0",
# starlette は fastapi の推移的依存だが、PYSEC-2026-161(Host ヘッダ未検証による認証バイパス)
# 対策で明示固定する。さらに CVE-2026-54282 / CVE-2026-54283 対策で 1.3.1 へ更新
"starlette==1.3.1",
"uvicorn[standard]==0.51.0",
"sqlalchemy==2.0.51",
"sqlalchemy-libsql==0.2.0",
"alembic==1.18.5",
"pydantic[email]==2.13.4",
"python-dotenv==1.2.2",
"reportlab==5.0.0",
"google-cloud-storage==3.13.0",
"pytest==9.1.1",
"PyJWT[crypto]==2.13.0",
"httpx==0.28.1",
# マルチプロバイダ LLM(ADR-0013)。Gemini = google-genai、GPT = openai。
# Gemini / Anthropic は Vertex AI(SA→ADC)経由(ADR-0015)。anthropic[vertex] の
# extra が ADC 用の google-auth を引き込む。google-genai は vertexai=True で Vertex 対応。
"anthropic[vertex]==0.116.0",
"google-genai==2.11.0",
"openai==2.45.0",
# Stripe Checkout / Webhook 署名検証(ADR-0012 Phase 2)。公式ライブラリを使う
"stripe==15.3.0",
"PyGithub==2.9.1",
"slowapi==0.1.10",
"ruff==0.15.21",
"autopep8==2.3.2",
"markdown==3.10.2",
"weasyprint==69.0",
"pydyf==0.12.1",
"redis==8.0.1",
"isort==8.0.1",
"black==26.5.1",
"pytest-cov==7.1.0",
"google-cloud-tasks==2.23.0",
"pyasn1==0.6.4",
# CVE-2026-53538 / CVE-2026-53539 / CVE-2026-53540 対策で 0.0.31 以上へ更新済み
"python-multipart==0.0.32",
# ミューテーションテスト(週次 CI: .github/workflows/mutation.yml / ADR-0017)
"mutmut==3.6.0",
]

[tool.uv]
# backend はアプリケーション(app/ レイアウト)でありパッケージとして build/install しない。
# uv sync は依存のみを .venv へ導入する(ADR-0021 Phase 0。.venv 廃止は Phase 1)
package = false

[tool.pytest.ini_options]
pythonpath = ["."]
# --cov は Makefile / CI 側の pytest 呼び出しで付与する。addopts に置くと mutmut が
Expand Down
42 changes: 0 additions & 42 deletions backend/requirements.txt

This file was deleted.

Loading
Loading