fix: 全APIの変更系ルート権限監査(require_write 付与の残り) #39

Closed
opened 2026-09-17 16:29:31 +00:00 by joe · 1 comment
Owner

概要

src/o2/api/__init__.py で _auth_deps = [Depends(require_read)] が多数のルーターに付与されており、変更系(POST/PUT/PATCH/DELETE)ルートに require_write が設定されていません。#38 で Web UI 露出分(masters/write/accounts の25ルート)は修正済みですが、残りのモジュールは未対応です。

現状(変更系ルート数の目安)

accounting(8) / ai(9) / automation(10) / bank_reconciliation(13) / billing_api(10) / billing_pricing(9) / fixed_assets(5) / iot(6) / masters(対応済) / multi_currency(4) / notes(5) / payroll(15) / purchase_invoices(5) / purchase_orders(8) / quotations(6) / sales_orders(6) / security(6) / set_products(5) / stocktaking(4) / sync(3) / tax(8) / tenants(2) / write(対応済) ほか

影響

  • Role.VIEWER のトークンで、販売/購買/在庫/給与/税務などの変更系 API を直接叩いてデータを変更できる
  • Web UI は現状 P1/P2 のみだが、P3 でこれら画面が露出すると同様の問題が表に出る

対応方針(要検討)

  1. ルート単位に dependencies=[Depends(require_write)] を付与(#38 と同じ方式。明示的で安全)
  2. もしくは メソッド判定の共通依存(POST/PUT/PATCH/DELETE は write、GET は read)を _auth_deps に適用。ただし POST を計算用途に使うエンドポイント(例: /api/ai/suggest, /api/chat)は read 権限のままにしたい場合があり、除外リスト設計が必要
  3. tenants/admin/security は既に require_platform_manage/require_manage で保護済みか確認

受け入れ条件

  • 変更系ルートの権限マトリクスを確定(write 必須 / 例外一覧)
  • Role.VIEWER で変更系が 403、GET は 200
  • 既存テストが緑(VIEWER 403 のテストを主要モジュールに追加)
  • test_api_schema.py / test_api_contract.py 緑

関連

  • #38(masters/write/accounts は対応済み)
  • AGENTS.md のロール定義(PLATFORM_ADMIN/ADMIN/ACCOUNTANT/VIEWER)
## 概要 `src/o2/api/__init__.py` で `_auth_deps = [Depends(require_read)]` が多数のルーターに付与されており、変更系(POST/PUT/PATCH/DELETE)ルートに `require_write` が設定されていません。#38 で Web UI 露出分(masters/write/accounts の25ルート)は修正済みですが、残りのモジュールは未対応です。 ## 現状(変更系ルート数の目安) `accounting`(8) / `ai`(9) / `automation`(10) / `bank_reconciliation`(13) / `billing_api`(10) / `billing_pricing`(9) / `fixed_assets`(5) / `iot`(6) / `masters`(対応済) / `multi_currency`(4) / `notes`(5) / `payroll`(15) / `purchase_invoices`(5) / `purchase_orders`(8) / `quotations`(6) / `sales_orders`(6) / `security`(6) / `set_products`(5) / `stocktaking`(4) / `sync`(3) / `tax`(8) / `tenants`(2) / `write`(対応済) ほか ## 影響 - `Role.VIEWER` のトークンで、販売/購買/在庫/給与/税務などの変更系 API を直接叩いてデータを変更できる - Web UI は現状 P1/P2 のみだが、P3 でこれら画面が露出すると同様の問題が表に出る ## 対応方針(要検討) 1. **ルート単位**に `dependencies=[Depends(require_write)]` を付与(#38 と同じ方式。明示的で安全) 2. もしくは **メソッド判定の共通依存**(POST/PUT/PATCH/DELETE は write、GET は read)を `_auth_deps` に適用。ただし POST を計算用途に使うエンドポイント(例: `/api/ai/suggest`, `/api/chat`)は read 権限のままにしたい場合があり、除外リスト設計が必要 3. `tenants`/`admin`/`security` は既に `require_platform_manage`/`require_manage` で保護済みか確認 ## 受け入れ条件 - [ ] 変更系ルートの権限マトリクスを確定(write 必須 / 例外一覧) - [ ] `Role.VIEWER` で変更系が 403、GET は 200 - [ ] 既存テストが緑(VIEWER 403 のテストを主要モジュールに追加) - [ ] `test_api_schema.py` / `test_api_contract.py` 緑 ## 関連 - #38(masters/write/accounts は対応済み) - AGENTS.md のロール定義(PLATFORM_ADMIN/ADMIN/ACCOUNTANT/VIEWER)
Author
Owner

対応完了: 全変更系ルートの権限監査

アプリ全体の変更系(POST/PUT/PATCH/DELETE)ルートに require_write を付与しました。main b52ed93 にマージ・push 済み。

付与結果(独立検証済み)

TOTAL mutating routes: 223
protected (write/manage/platform_manage): 207
exceptions (read のまま): 16
missing: 0
  • 新規付与 167ルート(#38 の25と合わせ、変更系は網羅)
  • 方式: 各変更系 decorator に dependencies=[Depends(require_write)](GET は対象外)

read のままにした例外(データを変更しない用途)

エンドポイント 理由
ai: /suggest /audit/{y}/{m} /forecast/* /analysis/financial /accountant/suggest 計算・参照
chat POST "" チャット計算
currencies POST /convert 為替換算
billing_pricing POST /prices/get 価格参照
document_chain POST /verify /verify-seal/{year} 検証
bank_reconciliation POST /parse /zengin/transfer/export プレビュー / データ生成(DB変更なし)
multi_currency POST /gain-loss 差損益計算
mcp POST /mcp JSON-RPC(下記の課題参照)
auth.py(公開)/ admin security tenants api_key(manage/platform_manage で既存保護) —

テスト

  • Web権限テスト tests/test_write_permissions.py 46 passed(VIEWER 変更系 403 / ACCOUNTANT 200-201 / VIEWER GET 200 を横断検証)
  • コアスイート 5337 passed, 0 failed

成果物

  • コミット b96c27f(167ルート付与)、d8e572d(計算系を read に精緻化)→ main b52ed93

残課題(別Issue)

MCP の POST /mcp は read 権限のままですが、src/o2/mcp/tools.py の dispatch_tool がロール検証を行わず、VIEWER トークンでも create_journal 等の更新系ツールを実行可能です(tenant scope 検証のみ)。→ #40 として起票。

本 Issue のスコープ(REST 変更系ルートの権限)は完了につきクローズします。

## 対応完了: 全変更系ルートの権限監査 アプリ全体の変更系(POST/PUT/PATCH/DELETE)ルートに `require_write` を付与しました。main `b52ed93` にマージ・push 済み。 ### 付与結果(独立検証済み) ``` TOTAL mutating routes: 223 protected (write/manage/platform_manage): 207 exceptions (read のまま): 16 missing: 0 ``` - 新規付与 **167ルート**(#38 の25と合わせ、変更系は網羅) - 方式: 各変更系 decorator に `dependencies=[Depends(require_write)]`(GET は対象外) ### read のままにした例外(データを変更しない用途) | エンドポイント | 理由 | |---|---| | `ai`: `/suggest` `/audit/{y}/{m}` `/forecast/*` `/analysis/financial` `/accountant/suggest` | 計算・参照 | | `chat POST ""` | チャット計算 | | `currencies POST /convert` | 為替換算 | | `billing_pricing POST /prices/get` | 価格参照 | | `document_chain POST /verify` `/verify-seal/{year}` | 検証 | | `bank_reconciliation POST /parse` `/zengin/transfer/export` | プレビュー / データ生成(DB変更なし) | | `multi_currency POST /gain-loss` | 差損益計算 | | `mcp POST /mcp` | JSON-RPC(下記の課題参照) | | `auth.py`(公開)/ `admin` `security` `tenants` `api_key`(manage/platform_manage で既存保護) | — | ### テスト - Web権限テスト `tests/test_write_permissions.py` **46 passed**(VIEWER 変更系 403 / ACCOUNTANT 200-201 / VIEWER GET 200 を横断検証) - コアスイート **5337 passed, 0 failed** ### 成果物 - コミット `b96c27f`(167ルート付与)、`d8e572d`(計算系を read に精緻化)→ main `b52ed93` ### 残課題(別Issue) MCP の `POST /mcp` は read 権限のままですが、`src/o2/mcp/tools.py` の `dispatch_tool` がロール検証を行わず、**VIEWER トークンでも `create_journal` 等の更新系ツールを実行可能**です(tenant scope 検証のみ)。→ **#40** として起票。 本 Issue のスコープ(REST 変更系ルートの権限)は完了につきクローズします。
joe closed this issue 2026-09-18 03:52:00 +00:00
Sign in to join this conversation.
No labels
h1-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
joe/o2#39
No description provided.