Skip to content

OTR_MPASRetrospective

nishi_74322014 edited this page Nov 14, 2026 · 2 revisions

汎用認証サイトの振り返り(TDD・適合性テスト・リファレンス実装の骨格)

概要

汎用認証サイト(MultiPurposeAuthSite、MPAS)は、2026-09 から生成 AI(コーディング・エージェント)を本格的に使って開発している。
その途中、OpenID Foundation の Conformance Suite(適合性テスト) を回し始めると、多数の不具合が検出された。
ここから、「TDD で進めたほうが早かったのではないか」 という内省(ポストモーテムとレトロスペクティブ)が出ている。
ただし、当時(2017〜2022 年)はコーディング・エージェントが無く、人 1 名の作業だった。後知恵で当時を責めないことを前提に、
「今から、どう進めるか」を考える材料としてまとめる(3-1 の節)。
一方で、モジュール設計は、リファレンス実装の骨格があって良かったという評価もある。

このページは、次の 3 つをまとめる。

  1. MPAS で実際に起きたこと(事実)
  2. 関連する研究結果(調べた範囲。出典と確からしさを明記する)
  3. 研究と事実を合わせた読み取りと、次に試すこと(提案)
  • 事実・研究・読み取りを分けて書く。読み取りと提案は、作者の判断を待つ仮説であり、確定ではない。
  • 研究は、2026-11-14 に Web で調べた。多くはプレプリント(査読前)で、ベンチマークが関数・クラス単位であり、MPAS のような仕様準拠の IdP の実装に、そのまま当てはまるとは限らない。

詳細

1. MPAS で起きたこと(事実)

進め方の順序

2026-09〜11 の作業は、次の順に進んだ(開発履歴 の第 5 期)。

順 内容 テストの位置づけ
1 適合性の分析(ANALYSIS-IdP.md)。項目に番号を振る(A〜E) 分析表が仕様の代わり
2 項目ごとに修正し、回帰テスト(E2E の RT- 番号)を足す 修正と同時、または後
3 責務ごとに分けてレビュー(#294)、同種の不良を全モジュールで探す(#331) 型ごとに再現テスト
4 品質の羅針盤(#315):テストの期待値を弱める変更の検出、別モデルのレビュー テストの保護
5 適合性テスト(Conformance Suite)を回す(#350。D-14) 外部の、独立した判定者
  • 適合性テストの導入は、最後(5)になった。実装がある程度動かないと、適合性テストは回せないため(Discovery・JWKS・登録・認可・トークンと、TLS・issuer の環境が先に要る)。
    実際に、回せるようにする土台作りだけで、#350 の段階 1〜4 を要した。
  • 2 の回帰テストは、不具合を見つけた後に足す形で、仕様から先に書いたテストではない。

適合性テストで見つかったもの

2026-11-14 時点の作業中ブランチ(origin/5th_agent)で、#350 の土台を除く 19 件が fixed になっている。
内訳:スタブ(#351)、テスト自体の不具合(#356)、配備の手引き(#369)を除く、製品コードの不適合が 16 件。

領域 例(Issue)
応答の形式・型 expires_in が文字列(#353)、値の無い email を空文字列で返す(#354)、at_hash・response_types_supported(#360)
仕様の読み違い response_type=code token で nonce を必須にしていた(#361)、client_assertion_type の無い client_assertion(#368)、引けない request_uri(#362)
暗号・署名の細部 暗号化した id_token 内の JWS の kid・alg(#352・#355)、Request Object の alg(#370)、JARM の alg(#370)
FAPI 2.0 の要件 PKCE(S256)の必須化(#366)、refresh_token を入れ替えない(#367)、PAR の DPoP の鍵への紐付け(#365)
鍵・登録の扱い jwks_uri の鍵の入れ替え(#363)、sector_identifier_uri(#364)、PAR・CIBA の口の aud(#371)
  • 適合性テストの oidcc-basic は、設定の不足による失敗(FAILED 3・TIMEOUT 2)を先に直し、残った1 件が OP の不適合だった(#350 の段階 2)。
    つまり、環境の問題と製品の不具合を切り分ける作業にも手間がかかった。
  • 自前の E2E テスト(126 ファイル規模)と、分析表(ANALYSIS-IdP.md)の A〜E・C-59 までの項目を通った後でも、上の不適合は残っていた。
    自前のテストと分析が見ていなかったものを、適合性テストが見つけたことになる。

リファレンス実装の骨格が効いた場所

  • 11-09 以降の修正(上記の 16 件など)が触ったのは、CommonLibrary の STS の核(TokenProviders・Extensions/Sts。24 ファイル) と、両版の Controllers(18 ファイル)に集まっている。
    新しい層や構造は、足していない。
  • 骨格は、2018-12 の自前の核(CmnEndpoints)への切り替えで決まり(開発履歴 の「転換点」)、2026-10 の責務ごとの分割(#294)で整理された。
  • 1 件の修正が、どのモジュールの、どのパーシャルに入るかが分かりやすく、エージェントへの指示(「CmnEndpoints.ClientAuthentication.cs の ...」)も具体的に書けた。

2. 関連する研究(調べた範囲)

確からしさの凡例:◎ 査読済み・原典を確認/○ プレプリント・要旨を確認/△ 二次情報(未確認)

2-1. 「テストを仕様にして、先に渡す」と、生成の正確さが上がる

研究 内容 確からしさ
TiCoder(Fakhoury ら、IEEE TSE 2024) 意図をテストで確かめ合う対話を入れると、4 つの LLM・2 つのデータセットで pass@1 が平均 +45.97 ポイント(5 回の対話以内)。利用者研究(15 名)では、生成コードの誤りに気付きやすく、負荷も下がった ◎
Test-Driven Development and LLM-based Code Generation(ACM、2024) GPT-4・Llama 3 で、問題文にテストを足すと MBPP・HumanEval の成功率が上がる ○
LLM4TDD(arXiv 2312.04687) テストを1 つずつ渡す進め方の実践指針(メソッド名・曖昧な整数のケースの明確化など)。LeetCode と ChatGPT で評価 ○
Scaling Test-Driven Code Generation from Functions to Classes(arXiv 2602.03557) クラス単位に拡張。8 つの LLM で、クラスの正しさが最良の直接生成より 12〜26 ポイント上がる。ただし依存の順序づけ・修復を含む全体の効果で、テストだけの効果を切り出していない ○
  • 限界:どれも関数・クラス単位のベンチマーク(HumanEval・MBPP・LeetCode・ClassEval)。プロトコル準拠の IdP のようなシステムでの研究は、見つからなかった。

2-2. 「TDD をしなさい」と指示するだけでは、効かないことがある

  • TDAD(arXiv 2603.17973):SWE-bench Verified で、コードとテストの依存関係を渡す(どのテストを回すべきかを示す)と、リグレッションが 6.08% → 1.82%(70% 減)。
    一方、「TDD の手順で進めよ」という指示だけを足すと、9.94% に悪化した。
    著者の結論は、「手順を指示するより、文脈(何を確かめるか)を渡すほうが効く」。
    (サンプルが小さい:100 件と 25 件。小型のオープン モデル。確からしさ:○)

2-3. 自分が書いたコードから書いたテストは、独立した判定者にならない

  • On the risk of coding before testing(Konstantinou ら、arXiv 2607.05139):LLM がコードを先に書き、その後にテストを書くと、コードの誤りがテストに伝わる。
    欠陥の検出率は、先にコードを見たテストが 14%、独立に作ったテストが 25%。(確からしさ:○)
  • Building to the Test(Ma ら、arXiv 2606.28430):エージェントは、確認される物を作る。
    隠したテスト(222 件の Playwright)を渡すと、点数は満点近くになるが、テストが見る振る舞いだけを持つデモを作り、本体のライブラリは未完・放置ということが起きた。(確からしさ:○。2 つのエージェントによる小規模な実験)
  • Are Coding Agents Generating Over-Mocked Tests?(Hora ら、MSR 2026):2025 年の 120 万コミット・2,168 リポジトリの調査で、エージェントのコミットは、モックを足す割合が高い(36% 対 非エージェント 26%)。モックの多いテストは、実際の連携を確かめにくい。(確からしさ:○。採択済みの会議論文)
  • (参考)同じモデルが書くコードとテストは、盲点を共有するという実務者の指摘(相関誤差)もある。ただし二次情報(△)。

2-4. 仕様準拠・プロトコル実装

  • iPanda(arXiv 2507.00378)・AutoSpec(arXiv 2511.17977):RFC の文書から、LLM が適合性テストや仕様の文法を作る研究。
    ただし、これらはテストの生成の研究で、「既存の適合性テスト(OIDF のような)を判定者にして、エージェントが実装を直す」研究は、見つからなかった。
  • LLM が生成したコードのセキュリティ:複数の研究で、脆弱性を含むことが示されている(例:Security of LLM-generated Code。○)。
    OAuth / OIDC に特化した測定は、見つからなかった。事例の報告(OAuth のパラメータ注入など)はあるが、因果は報告者の解釈で、確からしさは低い(△)。

2-5. リポジトリの文脈(AGENTS.md)と既存の構造

  • Evaluating AGENTS.md(arXiv 2602.11988):LLM が生成した文脈ファイルは成功率を 0.5〜2% 下げ、人が書いたものは約 4% 上げる程度。コストは 20% 超増える。(○)
  • On the Impact of AGENTS.md Files on the Efficiency(arXiv 2601.20404):別の測定(効率)では、トークン消費が減る。測るものが違うので、結果が割れている。(○)
  • 「リファレンス実装の骨格」や「既存のモジュール設計」が、エージェントの生成の質に与える効果を、直接測った研究は、見つからなかった。
    間接的には、TDAD の 「文脈を渡すほうが、手順を指示するより効く」 が、骨格の効果と整合する(が、同じものではない)。

3. 読み取り(仮説)

3-1. 当時の制約(後知恵への注意)

  • コーディング・エージェントが無かった:2026 年に、分析・修正・環境の構築・テストの追加を、エージェントに回せるようになって、
    適合性テストを回し、見つかった不適合を直す作業が、現実的なコストになった。
  • 人 1 名の作業だった:独立した判定者を整える・回す・結果を切り分ける作業は、当時の人手では重かった。
  • 実装が無いと、適合性テストは回せない:最小の骨格(プレーンな ASP.NET Identity の初期)は、動かすための合理的な出発点だった。
  • したがって、「最後になった」は判断の誤りではなく、コストと順序の制約である。以下は、これから(エージェントがいる前提)の進め方の考察である。

3-2. 「TDD にすべきだった」は、半分正しい

  • 研究は、テスト(実行できる仕様)を先に渡すと、生成の正確さが上がることを、一貫して示している(2-1)。
  • ただし、自分のコードから書いたテストは独立した判定者にならない(2-3)。MPAS の自前 E2E が、適合性テストが見つけた不適合を見ていなかったことと、整合する。
  • したがって、効いたのは、TDD の手順そのものよりも、独立した判定者(外部の oracle)を持つこと(持てる時点で、外側のループに据えること)だったと考えられる。
    • MPAS では、それは Conformance Suite(OIDF が仕様から作った、独立した判定者)。
    • 「TDD」ではなく「外部 oracle 先行」 と呼ぶほうが正確。
  • 「手順を指示するだけでは悪化しうる」(TDAD)ことも踏まえると、エージェントへの指示は「TDD でやれ」ではなく、「この判定者(テスト)を通せ」という文脈を渡す 形が、よい。

3-3. 適合性テストを先行させる場合の注意

  • テストに合わせて作る(Building to the Test):判定者を渡すと、判定者が見るものだけを作る危険がある。
    MPAS では、期待値の変更の検出器・別モデルのレビュー・責務ごとのレビュー(品質の羅針盤)が、これを抑える層になっている。
  • 適合性テストは、仕様の全部ではない:FAPI・CIBA などは代表の 1 通りしか回していない(#350 の段階 4)。
    見えない部分は、分析表と、自前のテストで補う必要がある。
  • 環境の切り分けのコスト:環境(TLS・ポート・設定)の問題と、製品の不具合の切り分けに手間がかかった(上記)。回す環境を整えるコストも、先行のコストに含める。

3-4. 適合性テストを軸にした TDD は成り立つか(二重ループ)

成り立つ。ただし、適合性テストは内側のループには向かない。

観点 適合性テスト(Conformance Suite) 自前の E2E・単体テスト
判定者 外部(OIDF が仕様から作る) 自前(作者・エージェント)
粒度・速さ モジュール単位・1 回が分単位。環境が要る ケース単位・秒〜分
失敗の原因 環境・設定・実装のどれかを切り分ける必要がある 直す場所に近い(局所化しやすい)
守備範囲 仕様適合(代表の 1 通り)。仕様の全部ではない Issue の回帰、画面、同時実行・DB の方言、Web の一般的な慣例・脆弱性への準拠など、仕様の外
ループ 外側(受け入れの基準) 内側(赤・緑を回す)
  • 進め方:最小の骨格を動かす → 適合性テストのプラン(oidcc-config → oidcc-basic → Implicit・Hybrid → FAPI など)を、外側のループとして段階的に緑にする。
    各モジュールの失敗は、内側のループ(自前のテストで再現して直す)で潰す。ATDD の二重ループに近い。
  • 役割は競合しない:適合性テストは、仕様適合の独立した判定者。分析表・レビュー・自前のテストは、判定者が見ない領域の探索と、回帰の防止である
    (MPAS では、有効期限・CORS・同意のスキップ・同時実行・DB の方言は、適合性テストの守備範囲の外で見つかった)。
  • E2E の重心の移り変わり(作者の所感):E2E は、当初 Issue ごとのテスト(Tests/Issues。100 ファイル)が中心で、仕様適合の判定もここで担っていた。
    適合性テストが登場して、仕様適合を任せられるので、E2E は Issue の回帰に集中してよい状態になった(Issue の回帰は、最重要である)。
    さらに、E2E には、Web の一般的な慣例や脆弱性への準拠・対応という、新しい役割が与えられる見込みである。
  • 役割分担の方針は、品質の羅針盤 の「適合性テストと E2E の役割分担」に書いた。

3-5. 骨格は、効いたと考えられる(が、測った研究は無い)

(骨格は、適合性テストを回せるようにする前提でもある:骨格が無いと、赤の理由が環境かどうかの判別すらできない。)

  • 修正が限られたモジュールに集まった(1 の最後)ことは、骨格が局所化を助けたことと整合する。
  • ただし、「骨格が無かった場合」との比較はしていない。作者の評価として書き、測定した事実とは区別する。
  • 骨格が良く機能した理由の仮説:
    • 責務の境界が仕様の節に近い(認可・トークン・クライアント認証・PAR・DPoP など)ので、「どの仕様の、どの節の不適合か」から、直す場所が決まる。
    • 同種の不良を全モジュールで探す(#331)作業が、骨格の単位で回せた。

3-6. 骨格は、人手で作る必要が無くなるか(作者の考察)

骨格が効いたとして、その骨格を、これからも人手で作る必要があるのか。作者の考察は、次のとおり。

  • 骨格も、生成 AI で作れるようになる可能性がある。 生成 AI を使った YOLO(まず作ってみる)と TDD(判定者を先に置く)の手法で、
    人手の骨格より優れた骨格が作れるなら、人手で作る必要は無くなってくる。
  • ただし、プロダクトの個性のようなものは、無くなっていく可能性がある。 生成 AI が作る骨格は、平均的で、どれも似た形になりやすい。
    骨格には、責務の切り方・名前・境界の置き方に、作り手の設計の意図が出る。それが薄れる。
  • 対策の案:要件などを別途、生成 AI に食わせ、骨格に反映させることができれば、有効に機能する可能性がある。
    つまり、骨格の源泉を、「人の手」から「人が書いた要件・設計の意図」に移す。

読み取り(仮説):

  • この考察を、本ページの他の結論と合わせると、人が持つべきものが、「骨格そのもの」から、「骨格を決める入力」(要件・設計の意図・判定者)に移ることになる。
    判定者(適合性テスト)と、要件・設計の意図の両方が外から与えられるなら、骨格は、再生成できる中間物になる。
  • MPAS の骨格は、自前の核への切り替え(2018-12)で人が決めた設計の意図(開発履歴)を含む。
    もし再生成するなら、この意図を、要件・設計メモ(DesignNotes/・ANALYSIS*.md)として文書にしておくことが、入力になる。
  • 注意:「骨格を再生成して、同じ品質が出る」ことは、測っていない(3-5 と同じく、研究も、調べた範囲では見つからなかった)。
    再生成した骨格を、適合性テストと E2E で判定できることは、前提条件になる(3-4)。
  • 個性の喪失は、悪いこととは限らない。差別化が骨格にあるのか、要件にあるのかで、評価が変わる。
    MPAS は IdP / STS で、境界の契約が標準の仕様なので、骨格に差別化は少なく、再生成に向くほうだと考えられる(コアと枝葉)。
    一方、業務のドメインに近い層ほど、個性(業務の意図)が骨格に出るので、要件を食わせる工夫が要る。

4. 次に試すこと(提案)

Keep(続ける)

  • リファレンス実装の骨格(責務ごとの分割)。
  • 品質の羅針盤(期待値の保護・別モデルのレビュー)と、修正ごとに回帰テストを足す運用。

Problem(課題)

  • 適合性テスト(独立した判定者)の導入が最後になり、見つかった不適合がまとまって出た(当時の制約による。3-1)。
  • 回帰テストは修正の後に足しているので、自分の理解を写したテストになりやすい。
  • 適合性テストは代表の 1 通りで、未確認の部分がある。

Try(次に試す)

  1. 判定者を外側のループに据える:最小の骨格が動いたら、次の仕様の追加(例:新しい FAPI のプロファイル)は、適合性テストのプランを、実装の前に回せる状態にしてから始める(3-4)。
  2. 仕様の節から、別の担当(別のエージェント・別のモデル)がテストを書く:コードを書く側に、テストを書かせない(独立性。2-3)。
    各テストに、根拠の仕様の節を付ける([Basis] の運用が使える。品質の羅針盤)。
  3. 指示は手順ではなく文脈で:エージェントへの指示は、「TDD で」ではなく、「この適合性テストのモジュールを通す」「この節の MUST を満たす」 と書く(TDAD)。
  4. テストへの過剰適合を検出する:判定者を通った後、本体が実際に呼ばれているか(デモ・スタブで通していないか)を、カバレッジ・別モデルのレビューで確かめる(Building to the Test)。
  5. 測る:1 件の不適合ごとに、どの時点(分析・自前のテスト・レビュー・適合性テスト)で見つかったかを記録し、どの層が何を取りこぼすかを実測する。
    (コミットのトレーラー Found-By: が使える。#335 の運用)
  6. 骨格の効果を測る:次に新しい枝葉(別の仕様の IdP など)を作るとき、骨格あり・なしの差を、手戻りの数で比べる。
  7. 骨格を、生成 AI に作らせる実験をする:枝葉の新規(別の仕様の IdP など)で、要件・設計の意図の文書を食わせて骨格を生成させ、適合性テスト・E2E で判定する。人手の骨格と、手戻りの数・設計の意図の反映を比べる(3-6)。

参考


Tags: 再構築

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki
開発基盤部会 Wiki

移行管理: DONE / TODO

Clone this wiki locally