確認できなかったときに、通していた:「fail-open」が転売品を招いた話
トレカダッシュ 開発の記録 / 2026年10月
iOS アプリ「トレカダッシュ」で、「Amazon に転売の価格がたくさん入ってきている」という報告が、アプリ内の不具合報告から 3 件届きました。うち 1 件は、¥79,800 の、明らかな転売品でした。原因は、わざと入れていた「確認できなかったら通す」という設計の、盲点でした。HANDOFF とコミット(2026年7月30日)の記録で書きます。
このサイトには、トレカダッシュの作品ページはまだありません。ここに書くのは、開発の記録です。
価格の関門と、「通す」設計
アプリは、通販サイト(楽天市場、Yahoo!ショッピング、Amazon など)の出品を拾って、フィードに出します。そのとき、出品価格が、商品の定価から見て妥当かを調べる「価格の関門」があります。定価を、AI(Web 検索つき)に調べさせて、極端に高い転売品を弾く仕組みです。
この関門には、「定価を確認できなかった場合は、審査せずに通す」という動きがありました。これは意図した設計です。AI が本当に定価を知らない商品を、確認できないだけで除外してしまうと、本物の出品まで消してしまうからです。いわゆる fail-open(失敗したら開く=通す)です。
盲点:検索の上限に達した場合も、同じ道を通っていた
AI の Web 検索には、1 日 300 回の上限があります(想定外の費用を防ぐための回路遮断器)。ところが、関門は、定価を確認できなかった理由を、区別していませんでした。
- AI が「この商品の定価は知らない」と答えた。
- 1 日の上限に達して、確認すること自体ができなかった。
この二つが、どちらも「定価不明 → 通す」の同じ道を通っていました。前者は意図どおりです。後者は、「調べる前に、道が閉まっていた」だけなのに、関門が、素通しになっていたのです。
穴が、実害になった理由
この穴は、前の変更(Amazon の対象を広げた回)をきっかけに表に出ました。対象を広げたことで、新しく価格を確認する必要がある商品が、一気に増えました。その結果、1 日の上限に、頻繁に達するようになった。上限に達した間は、関門が素通しになって、転売品が大量に混ざりました。
さらに、二次被害がありました。定価が分からなかった結果は、理由を問わず24 時間キャッシュされる設計でした。そのため、一度上限に当たった商品は、上限が解除されたあとも、最大 24 時間、素通しのままになります。
直し方:理由を区別する
専用の目印(QUOTA_EXCEEDED)を作って、二つを区別できるようにしました。
| 状況 | 関門の動き |
|---|---|
| AI が本当に定価を知らなかった(null) | これまでどおり通す(fail-open のまま) |
| 1 日の上限で、確認自体ができなかった(QUOTA_EXCEEDED) | 除外する(fail-close) |
後者は、24 時間のキャッシュにも入れません。次に呼ばれたときに、あらためて確認を試みます。この関門は、楽天市場、Yahoo!ショッピング、Amazon、AI による出品の発見、楽天ブックスの先着など、価格の審査を使うすべての機能に共通なので、一回の修正が、広い範囲に効きます(コミットの記録では、18 の関数を配備しています)。
報告のあった 3 件は、手作業で非表示にしました。そのあとは、5 分おきに動く再審査のバッチが、同じ見逃しを拾い直す想定です。
確認できていないこと:記録には、「上限のリセット後に、転売価格の報告が来なくなったかを、次のセッションで確認する」と書いてあります。その結果は、この記事を書いた時点で、記録にありません。
ほかの判定にも、同じ穴は無いか
その後の点検(2026年7月30日)で、販売形式の判定や商品の照合など、ほかの AI による判定も確認しました。いずれも、失敗したときは、安全側(除外、または null)に倒れる設計で、新しい fail-open の穴は見つかりませんでした。
分かったこと
「確認できなかった」には、二種類ある。知らなかったのと、調べられなかったのと。
- 通す設計は、「通してよい理由」を、はっきりさせてから使う。「分からないから通す」と「調べられないから通す」は、別のものです。
- 失敗の結果を、理由を問わず、キャッシュしない。一時的な失敗を、24 時間、固定してしまいました。
- 前の変更が、別の場所の穴を、実害にする。Amazon の対象を広げたことが、上限の穴を、表に出しました。
この記事は、HANDOFF(第182回)とコミット(2026年7月30日)の記録から書きました。
この話に出てくるもの
- 一度だけ生まれた誤字が、店ごとに増えていった — 同じアプリの、別の記録
- 「減るはず」が、二度外れた — 同じアプリの、AI 呼び出しの記録
ほかの記録
- 一度だけ生まれた誤字が、店ごとに増えていった:「30th SEREBRATION」の件 — 誤字の商品が一度作られると、既存の商品として再利用され、店ごとに増える。13記事を直し、短い見出しを完全一致で拾う予防を入れ、保険のチェックの限界まで確かめた記録。
- 「しょうがない」を測り直したら、取得の費用は8分の1だった — 「イオンとあみあみは費用が重くて縮められない」は、古い単価に基づく思い込みだった。3つの取得設定で同じページを比べて、描画が丸ごと無駄だと分かった記録。
- App Store 審査で「Guideline 2.1 Information Needed」が届いた:求められた6つ — 初めての審査で届いたのは、不合格ではなく Guideline 2.1「Information Needed」だった。求められた六つ(実機の画面収録、目的、外部サービスの一覧など)と、前に直したこととのつながり。
コメント
感想や、記事の間違いの指摘は、ここへ。書くには、GitHub のアカウントが要ります。
押すと、giscus(giscus.app)と GitHub に接続します。押さなければ、接続しません。詳しくはあつかいに書いています。