先に結論をお伝えします。仕組みは、作った時点では見えなかった見落としが、動かしてみて初めて見つかることがあります。HaruIroAI が見つけたのは、「内容の言い回しが同じ依頼」を、仕組みが「前回と同一の依頼」とみなしてしまい、以前の判断をそのまま返してしまう場合がある、という点でした。
この記事では、見つかった盲点の中身、それがなぜ危ないのか、決済業界にある似た論点との対比、そして今日あなたの仕組みに対してできる簡単な点検の手順を、順番にお渡しします。
見つかった盲点:「同じ言い回しの依頼」を「同じ依頼」として扱ってしまっていた
前回作った仕組みは、「取り返しのつかない操作の直前に、人が一度見て判断する」というものでした。これを実際に運用してみたところ、内容の言い回しがまったく同じ依頼だと、仕組みがそれを「前回と同一の依頼」とみなしてしまう場合があると分かりました。
すると何が起きるか。前回その依頼に対して人が下した判断(承認でも却下でも)が、新しく来た依頼にもそのまま適用されてしまいます。依頼した側は「今回もちゃんと確認してもらえた」つもりでも、実際には一度目の判断が使い回されているだけ、ということが起こり得ます。
技術的な仕組みの詳細はここでは書きません(社内の運用情報のため)。大事なのは、「文面が同じなら同じ依頼」という一見自然な発想が、承認の仕組みでは思わぬ盲点になる、という点です。
なぜこれが危ないのか
承認の仕組みが前提にしているのは、「毎回、人がちゃんと見て判断する」ということです。ところが、内容が同じというだけで「前と同じ依頼」と自動でみなされてしまうと、実際には状況が変わっている新しい依頼なのに、人の目を通らないまま古い判断がそのまま使われてしまいます。
これは、皮肉な話でもあります。「同じ内容なら、いちいち確認しなくていい」という簡略化は、一見すると効率化に見えます。しかし承認の仕組みにおいては、その簡略化自体が、確認を素通りさせる抜け道になり得るのです。便利にしようとした工夫が、安全のための仕組みを弱めてしまう——仕組みを作るときに見落としやすいポイントだと、HaruIroAIでは考えています。
決済の世界にも同じ論点がある
この話は、実は目新しいものではありません。ネットで支払いを扱う決済システムの世界にも、よく似た論点があります。
決済サービスのStripeは、通信が途切れて同じ支払いリクエストが二重に送られてしまう事故を防ぐために、「冪等性キー(idempotency key)」という仕組みを使っています。公式ドキュメントには、次のように書かれています。
A client generates an idempotency key, which is a unique key that the server uses to recognize subsequent retries of the same request. How you create unique keys is up to you, but we suggest using V4 UUIDs, or another random string with enough entropy to avoid collisions.
(訳: 依頼する側〈クライアント〉が、一意なキーを生成します。サーバーはこのキーを使って、同じ依頼の再送を見分けます。キーの作り方は自由ですが、V4 UUID、またはコリジョン〈重複〉を避けるのに十分なランダム性を持つ文字列を推奨します。)
ここでのポイントは、キーを発行するのは依頼する側(クライアント)だという設計になっている点です。キーの具体的な作り方自体はクライアント側の自由ですが、Stripeは公式にV4 UUID、またはコリジョン(重複)を避けるのに十分なランダム性を持つ文字列を推奨しています。しかも同じドキュメントには、こう続きます。
The idempotency layer compares incoming parameters to those of the original request and errors if they're not the same to prevent accidental misuse.
(訳: 冪等性の仕組みは、届いたパラメータを元のリクエストのものと比較し、一致しなければ誤用防止のためエラーを返します。)
つまり、「同じキーなのに中身が違う」という食い違いが起きたら、エラーを返します。また、キーは生成から24時間以上経過するとシステムから削除されることがあり、削除された後に同じキーが再利用されると、新しい依頼として扱われます(Stripe公式ドキュメント)。
承認の仕組みを作るときも、「何をもって同じ依頼とみなすか」を、こうして具体的な条件として言葉にしておくことが役に立つと、HaruIroAIでは考えています。
いま、どう見直しているか
正直にお伝えします。この盲点は「見つけた」段階であり、「直しました」とはまだ言えません。現時点で分かっているのは、内容の言い回しだけで「同じ依頼」と判定してしまう場合がある、ということまでです。
いま進めているのは、依頼の内容だけでなく、依頼ごとに変わる情報(依頼されたタイミングなど)を区別に使う方向での見直しです。「解決しました」「もう二度と起きません」と言い切るのは簡単ですが、それは実際より安心させてしまう表現になります。見つかったことと、対応を進めていることを、そのままお伝えするのがHaruIroAIとして誠実だと考えています。
今日からできる点検(コピー可能)
大がかりな見直しをする前に、まずは自分の仕組みが同じ落とし穴を持っていないか、簡単に点検できます。
【承認・確認の仕組み 「同じ依頼」点検リスト】
1. 自分たちが使っている承認・確認・重複チェックの仕組みを1つ書き出す
例)経費申請の承認フロー/問い合わせフォームの自動応答/予約の重複チェック 等
2. その仕組みが「何をもって同じ依頼とみなしているか」を確認する
・文面(内容)だけを見ているか
・依頼されたタイミングや、依頼した人も区別に使っているか
3. 同じ内容の依頼を、時間を空けて2回試してみる
(テスト用の依頼で構いません。本番データは使わない)
4. 2回とも、毎回ちゃんと新しく確認・承認が飛ぶかを確かめる
・1回目の判断がそのまま2回目にも使われていないか
5. もし「前と同じ扱い」になってしまうなら
依頼ごとに変わる情報(タイミングなど)を区別の材料に使う方向で見直しを検討し、
変更したら同じテストをもう一度行い、実際に別の依頼として扱われるかを確かめる
一度作った仕組みでも、実際に動かして初めて見えてくる盲点があります。「作ったから安心」で止めず、時々こうした簡単なテストで点検してみることが、思わぬ抜け道を防ぐ助けになります。
この記事の作り方
この記事は、HaruIroAI 自身の承認フローを実際に運用して見つかった記録と、Stripe公式ドキュメント(冪等性キーの仕組み)を参照して構成しています。見つかった盲点は本記事執筆時点で見直しを進めている段階であり、解決済みとは述べていません。社内の運用に関する技術的な実装詳細は非公開情報のため記載していません。文章の作成・記録の照合にAIを使用し、内容は公開前に人が確認します。