chore(ci): API インベントリ差分検知の追加(API追加・認可回帰の機械検知) - #1895
Merged
Conversation
WEKO3 の全HTTPエンドポイントを棚卸しした台帳に対して、API の追加・仕様変更・
認可の回帰を PR ごとに機械検知する仕組み。
【このリポジトリは public のため、データは一切置かない】
台帳(weko3_api_list_full.tsv)は「どの経路を・どう叩けば・何が取れるか」と
実証結果を持つ。公開領域に置かず、秘密リポジトリで管理して環境変数
WEKO_API_INVENTORY_DIR で参照する(scripts/paths.py)。
CI の出力も --summary-only で件数のみ。Actions のログ・artifact・PRコメントは
誰でも読めるため、URI や endpoint 名は出さない。
- tools/api-inventory/scripts/ ツール一式
Phase 1-3 静的抽出/観点付与/実機実測(既存の参考実装)
Phase 5 build_checklist.py 57列 → 24列
Phase 6 snapshot.py 実機url_map(UI/API両アプリ)+ModelView権限+AST属性
diff_snapshot.py スナップショット間の差分、ゲート G1-G7
reconcile.py スナップショット ↔ 台帳の突き合わせ(抽出漏れ検知)
changed_rows.py git差分 → 再レビューが必要な台帳行
Phase 7 fixtures.py 到達可否測定用の最小コーパス投入
probe_ci.py フィクスチャ駆動の実測、ゲート G8/G9
paths.py $WEKO_API_INVENTORY_DIR の解決(未設定なら理由を添えて中断)
- tools/api-inventory/ci/ 設置手順(README.md)とワークフロー
- .github/workflows/api-inventory-drift.yml
Secret(API_INVENTORY_REPO / API_INVENTORY_TOKEN)が未設定なら何もせずスキップ。
fork からの PR では起動しない。
- .github/pull_request_template.md CI の想定に合わせて更新
API変更PRでの秘密側ベースライン更新を必須項目化、ゲート対処表、
公開領域にデータをコミットしていないことの確認項目
経路の抽出は実機 url_map を正とする。AST の @bp.route/add_url_rule では
357ルートしか拾えず、実機903ルート(static除く)の52%が Flask-Admin 自動生成・
@expose・config駆動REST・pip側パッケージ由来で原理的に見えないため。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HXo9u6PoTf6VRKr3aiGvZ3
Secret 判定 → deploy key での private checkout → 保存済みスナップショットと 台帳の突き合わせ、までを Docker なしで検証する。install.sh を回さないため 1分程度で終わる。--summary-only の出力に明細が混じっていないことも確認する。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXo9u6PoTf6VRKr3aiGvZ3
配線確認は完了したので一時ワークフローを削除し、本番の api-inventory-drift を push でも起動できるようにして実機込みで確認する。確認後に push トリガは削除する。 - push イベントでは pull_request.base.sha が無いため github.event.before に フォールバックする(changed_rows.py の比較元) - job の if 条件を push イベントでも成立するようにした Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXo9u6PoTf6VRKr3aiGvZ3
CI で全ステップ成功を確認したので後片付けと調整を行う。 - 一時的な push トリガを削除(トリガは pull_request / workflow_dispatch のみ) - --summary-only でも W6(依存パッケージの版変化)はパッケージ名を出すようにした。 公開PyPIの版情報で機密性が無く、名前が無いと原因を追えないため。 経路名・所見を出さない方針は他のゲートで維持する。 - ci/README.md に「ベースラインは CI と同じ環境で作る」を追記。 手元のdocker環境(302パッケージ)で作ったベースラインを CI の install.sh --no-cache 環境(301パッケージ)と比べると W6 が2件出る。 経路(endpoints=860/AST結合=495/属性不明=365)は完全一致しており差は依存の版のみ。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXo9u6PoTf6VRKr3aiGvZ3
台帳は「どのリビジョンの WEKO3 に対する調査結果か」が分からないと意味を失うため、 秘密リポジトリ側にも WEKO3 と同名のタグを打つ運用を ci/README.md 3c に明記した。 バージョンアップ時の流れ(ベースライン再生成 → reconcile 差分0 → changed_rows の 再確認 → commit → 同名タグ)も記載。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXo9u6PoTf6VRKr3aiGvZ3
指定基準(P0至急/P0最優先/P1/P2/P3/P4/対象外)で台帳を機械判定する。 判定は上から順に評価し最初に合致したものを採用する。 - 「対象外」と P3 は P2 より先に評価する。admin-access で保護された管理画面や 意図的公開(OAI-PMH等)を「認証なしの読み取り系」として P2 に落とすと、 実際に見るべき行が埋もれるため。ただし指摘や★実証がある行は対象外にしない。 - build_checklist.py は priority/priority_reason を末尾に引き継ぐ。既存列の 位置を動かすと README の awk 例が全て壊れるため末尾に追加する。 - scripts/README.md に Phase 8 と機械判定の限界を記載。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXo9u6PoTf6VRKr3aiGvZ3
API インベントリ差分(件数のみ)
ベースラインとの差分API インベントリ差分レポート
判定: ✅ PASS (FAIL 0 / WARN 1)サマリ
[WARN] W6 依存パッケージの版が変化した — 2件
台帳との突き合わせスナップショット ↔ インベントリ 突き合わせ
判定: ✅ 一致 (0件)
|
API インベントリ差分(件数のみ)
ベースラインとの差分API インベントリ差分レポート
判定: ✅ PASS (FAIL 0 / WARN 1)サマリ
[WARN] W6 依存パッケージの版が変化した — 2件
台帳との突き合わせスナップショット ↔ インベントリ 突き合わせ
判定: ✅ 一致 (0件)
|
- test_coverage.py を新規追加。test_file と impl_func を突き合わせて対応する テスト関数を特定し、正常値/異常値/境界値/例外処理の4観点を静的判定する。 同定できなかった行は「特定不能」として区別する(テストが無いと断定できないため)。 - prioritize.py: 「データ破壊」を「既存の実データを不可逆に壊すこと」と定義し直し、 P0(至急) を data_target/data_store の「ファイル実体」+更新/削除+未認証到達に限定。 新規作成のみで既存データを壊さないものは認証が無くても P1 に置く。 テスト観点が確認できない行を P2 まで引き上げる規則を追加(上限 P2)。 - build_checklist.py: テスト観点5列を24列版へ引き継ぐ(=31列)。 - scripts/README.md: Phase 8 を更新し、test_coverage.py → prioritize.py の 実行順が必須である旨を明記。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXo9u6PoTf6VRKr3aiGvZ3
API インベントリ差分(件数のみ)
ベースラインとの差分API インベントリ差分レポート
判定: ✅ PASS (FAIL 0 / WARN 1)サマリ
[WARN] W6 依存パッケージの版が変化した — 2件
台帳との突き合わせスナップショット ↔ インベントリ 突き合わせ
判定: ✅ 一致 (0件)
|
参照系でも露出内容が認証情報または非公開データの実体であれば P1 に上げる。 判定材料は sec_pattern/sec_exposed/sec_detail に限定し、指摘または★実証が ある行だけを対象にする。restricted_content と access_variance は適切に 制限されている旨の記述にも「非公開」が出るため判定に使わない。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXo9u6PoTf6VRKr3aiGvZ3
API インベントリ差分(件数のみ)
ベースラインとの差分API インベントリ差分レポート
判定: ✅ PASS (FAIL 0 / WARN 1)サマリ
[WARN] W6 依存パッケージの版が変化した — 3件
台帳との突き合わせスナップショット ↔ インベントリ 突き合わせ
判定: ✅ 一致 (0件)
|
deprecated 列の未使用/非推奨/実質未使用/呼出元なし、および dynamic_verified の 経路なしから非利用を判定し、cleanup 列に根拠を残す。認可上の判定が P2 以下なら priority を整理対象に置き換え、P0/P1 は優先度を維持して理由に付記する。 あわせて末尾の派生列(priority/priority_reason/test_*/cleanup)の並びを prioritize.py が正規化するようにした。従来は test_coverage.py と prioritize.py の 実行順で列位置が入れ替わっていた。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXo9u6PoTf6VRKr3aiGvZ3
Phase 1-9 は作り方の説明で、日々の更新に必要な手順が散っていた。 scripts/README.md の冒頭に「台帳の更新手順」を新設し、以下を1箇所にまとめた。 - 大原則(24列版と派生列は手編集しない、test_coverage → prioritize の実行順) - ケース1: 派生列の再計算だけ - ケース2: 台帳への行追加・修正(列数の検算と reconcile による確認込み) - ケース3: バージョンアップに伴う全面更新(タグ付けまで) - 各スクリプトが何を読み書きするかの一覧 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXo9u6PoTf6VRKr3aiGvZ3
reconcile_allow.json を一次情報として、実機 url_map に存在しない行を 環境依存に分類する。整理対象(削除候補)とは区別し、別環境では有効になるため 削除対象にしない。dynamic_verified を判定に使うと実測欄の粒度のばらつきで 同一グループが別区分に割れるため、allow リストに寄せた。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HXo9u6PoTf6VRKr3aiGvZ3
API インベントリ差分(件数のみ)
ベースラインとの差分API インベントリ差分レポート
判定: ✅ PASS (FAIL 0 / WARN 1)サマリ
[WARN] W6 依存パッケージの版が変化した — 3件
台帳との突き合わせスナップショット ↔ インベントリ 突き合わせ
判定: ✅ 一致 (0件)
|
API インベントリ差分(件数のみ)
ベースラインとの差分API インベントリ差分レポート
判定: ✅ PASS (FAIL 0 / WARN 1)サマリ
[WARN] W6 依存パッケージの版が変化した — 3件
台帳との突き合わせスナップショット ↔ インベントリ 突き合わせ
判定: ✅ 一致 (0件)
|
API インベントリ差分(件数のみ)
ベースラインとの差分API インベントリ差分レポート
判定: ✅ PASS (FAIL 0 / WARN 1)サマリ
[WARN] W6 依存パッケージの版が変化した — 3件
台帳との突き合わせスナップショット ↔ インベントリ 突き合わせ
判定: ✅ 一致 (0件)
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概要 (Summary)
WEKO3 の全 HTTP エンドポイントを対象に、API の追加・仕様変更・認可の回帰を PR ごとに機械検知する仕組みを追加します。ツールとワークフローのみで、アプリケーションコードへの変更はありません。
tools/api-inventory/scripts/— 生成・検証ツール一式tools/api-inventory/ci/— 設置手順(README.md)とワークフロー.github/workflows/api-inventory-drift.yml.github/pull_request_template.md— CI の想定に合わせて更新変更タイプ (Type of Change)
このリポジトリにデータを置いていません
台帳(API 一覧とその調査結果)は、経路ごとの認可状況を含むため public な本リポジトリには置きません。別管理とし、ツールは環境変数
WEKO_API_INVENTORY_DIRで参照します。未設定なら理由を添えて中断します(scripts/paths.py)。CI の出力も
--summary-onlyで 件数のみです。Actions のログ・artifact・PR コメントは誰でも読めるため、URI や endpoint 名は出しません。出力に明細が混じっていないことを assert するステップも入れています。Secret(
API_INVENTORY_REPO/API_INVENTORY_SSH_KEY)が未設定の場合、ワークフローは何もせずスキップします。fork からの PR でも起動しません。何を検知するか
経路の抽出は実機 url_map を正とします。 ソースの
@blueprint.route/add_url_ruleを AST で全部拾っても 357 ルートで、実機 903 ルート(static 除く)の 52% は Flask-Admin の自動生成・@expose・config 駆動 REST・modules/配下に無い pip パッケージ由来で、静的解析では原理的に見えないためです。動作検証 (Verification)
実際に CI を走らせて全ステップ成功を確認しました。
まっさらな CI 環境(
install.sh --no-cache)でも、手元の環境と同一の結果になりました。artifact が件数のみであることも確認済みです。
既知の制限
modules/配下を変更した PR でのみ対象行が発生します。本 PR はツールのみのため対象 0 件で、実測経路は CI 上では未検証です(手元では検証済み)。install.sh)で作る必要があります。異なる環境で作ると依存パッケージの版差で WARN が出続けます(ci/README.md§3b)。既存 CI への影響
なし。既存の
ui-tests.yml/unit-tests.ymlには手を入れていません。追加するジョブはpull_requestとworkflow_dispatchでのみ起動します。導入手順
tools/api-inventory/ci/README.mdに記載しています(配置、導入順序、ベースラインの更新ルール、ゲートが FAIL したときの対処、トラブルシュート)。