AIと組む個人開発で、外部サービスに何を預けて何を持たないか

English

この記事の目次

あらまし

課金もログインも問い合わせの受け取りも、外部のサービスへ預けました。会員と課金について自分のデータベースに残すのは、誰がどのプランの会員かという対応づけと、購読と購入の状態の控えだけです。控えを持つのは、読者が有料記事を開くたびにサイトが決済サービスへ購読の状態を確認しに行くと、表示が遅くなるからです。AIと一緒に開発していると、実装そのものはいくらでも進められます。だから最初に決めるべきことは、何を作れるかではなく、何を自分で持たないかでした。

この記事は、外部サービスに何を預けて何を持たないかを僕がどう決めたか、そしてそのとおりにAIと組んで作っていくと実際に何が起きて、どう工夫したかの記録です。二週間ほどの開発の中で、問い合わせの保存を一度作り切ってから取り下げたこと、AIが確信を持って書いた古い仕様で二度つまずいたこと、サイトが動いているかを外から定期的に確かめる監視(外形監視)の候補をAIがそろえ、僕が別の基準で選び直したことを、順に書きます。

対象読者と持ち帰れるもの

AIエージェントにコードの多くを書いてもらいながら、一人で課金のあるサービスを作ろうとしている人に向けた記事です。個人のデータをどこまで自分で持ち、どこから外部のサービスへ預けるかの決め方と、その基準を先に決めておくとなぜ効くのかを持ち帰れます。あわせて、AIが古い仕様を確信して書いてしまう癖にどんな決まりで対処したか、規約や価格の調べものはAIに任せて、費用と権限を縛る判断は人が下す、という分け方の実例も書きます。この記事は、このサイト自身をAIと一緒に作る過程に基づく実践の記録です。

その日のあらすじ

外部サービスに何を預けて何を持たないかを、AIエージェントと組みながら二週間ほどかけて決めていきました。問い合わせの本文を自前のデータベースへ保存する仕組みは、動作の確認まで済ませたうえで取り下げ、サイトのフォームから外部のフォームサービスへ預け替えました。支払いのカードの入力は、決済サービスが自社の側で表示する決済ページへ完全に渡し、カード情報とパスワードは自分のサイトで一切扱いません。会員と課金の正しい記録は決済サービスの側に置き、自分の側は対応づけと控えだけを持ちます。あわせて、AIが書いた設計は現行の公式ドキュメントの本文まで読んで確かめる、費用は外形監視まで含めて人が先に上限を決める、という二つの決まりも組み込みました。

何を持たないかを決める前に、やるべきことの全体を知る

自分で作るか、外部のサービスへ預けるか、そもそも持たないか、という判断はそれ自体が高度で、うまくやるには手前にもう一段の考えが必要です。何を預けて何を持たないかを決めるには、課金も認証も法務も監視も性能もセキュリティも、やるべきことの全体が見えていなければなりません。全体が見えないまま決めると、預けるべきデータを自分で抱えたり、逆に、課金や権限のような自分で守るべき責任まで外部へ丸投げしたりしかねないからです。

この全体を、一人で漏れなく把握するのは難しいことでした。そこで僕は、やるべきことの一覧をAIに列挙させ、その一覧に抜けが無いかを、視点を分けたいくつもの検証で確かめました。コードと設定のセキュリティの監査と、表示の速さの監査を別々の課題としてAIに頼み、リリースの準備の抜けと外部サービスの無料枠の上限も別の視点で点検させ、読者が実際に取る操作を一つずつ並べて抜けを探し、規約と法務は法律と各サービスの規約の原文にあたって総点検しました。一つの視点の列挙は必ずどこかが抜けるので、視点を重ねて抜けを埋めるのです。そのうえで、人が自分の目で確かめる対象は、落ちたら取り返しのつかない領域、つまりお金と権限と個人のデータと法務の重みづけと、最後の裁定だけに絞りました。

持たないものを、先に基準として決める

AIと一緒だと、実装は事実上いくらでも進められます。問い合わせを受け取る処理も、保存するデータベースのテーブルも、動作の確認も、指示すれば短い時間で返ってきます。すると、作れるかどうかは判断の材料から抜け落ちて、持つべきかどうかだけが残ります。だから、何を自分で持たないかという基準を、人が先に決めておくことにしました。

基準は一つで、持つものを最小にすることです。個人のデータを保存する機能を作りたくなったら、まず外部の預け先を探します。自前で持つのは、課金と認証と権限のように、正しい記録が自分の側に無いと成り立たないものだけに絞りました。

外部へ渡せば安心、という話ではありません。それでも、持つより預けるほうが良いと言える理由は二つあります。第一に、漏れたときの被害は、何を持っているかで決まります。脆弱性を防ぎ切れる前提には立てない以上、持っていないものは漏れようがない、というのがいちばん強い守りです。第二に、カード情報やログインの本人確認のようなデータには、それを守ること自体を本業にしている専門の事業者がいます。一人の開発者が、同じ水準の守りの体制と投資を続けるのは現実的ではありません。だから預け先は、規約とデータの扱いを原文まで読んで確かめて選びます。預けたあとも、預け先とのつなぎ目を守る仕事は自分に残ります。会員との対応づけの表を正しく保つことや、決済サービスから届く通知が本物かを確かめることが、それです。

この基準を決めるきっかけは、問い合わせの取り下げでした。AIが受け取りの処理と保存のテーブルまで実装し、動作も確かめ終えていた仕組みを、僕が二つの理由で差し戻したのです。一つは、漏れたときの被害をいちばん小さくするためです。本文と返信先を自分で持たず、外部のフォームサービスへ預けてしまえば、自分のデータベースが漏れたとしても、そこに問い合わせは入っていません。もう一つは、使えるデータベースの容量にも限りがあるからです。この判断を決まりとして書き残したので、次からは作る前に止まれます。

カード情報とパスワードも同じです。ログインの確認は、メールのリンクをたどってもらう認証へ任せ、支払いは、決済サービスが自社の側で表示する決済ページへそのまま渡します。だから、カード番号が自分のサイトを通ることはありません。これは被害を小さくするためだけではなく、配信サービスの無料の規約が、無料のサイトでカード情報を取り扱うことそのものを禁じているからでもあります。

会員と課金の正しい記録も、自分では持ちません。誰がどのプランを購読していて、支払いがいま有効かは、実際にお金が動く決済サービスの側だけが正しく知っています。自分のデータベースにも同じ台帳を持つと、正しい記録が二つできてしまい、決済の通知を一つ取りこぼしただけで食い違って、どちらを信じるかという問題が生まれます。だから正しい記録は決済サービスの側の一つに決め、自分のデータベースには、それを指す対応づけと、購読と購入の状態の控えだけを置きました。控えは、読者が有料記事を開くたびに決済サービスへ問い合わせて読者を待たせないための、手元の写しです。壊れても、決済サービスの記録から引き直せば戻ります。いいねやお気に入りのような、個人に結びつく書き込みはログインを最低の条件にし、匿名から受けてよいのは、記事の閲覧数のような個人に結びつかない集計だけに絞りました。

AIが確信して書く古い仕様を、現行の公式ドキュメントで確かめる

AIは、訓練したときのデータにある古い仕様を、確信を持って、しかももっともらしく書きます。だから、そのまま通してしまいそうになります。僕は決済まわりで二度つまずきました。一度目は、請求書から支払いを直接指すinvoice.payment_intentというフィールドを、AIが記憶のまま使っていた件です。決済サービスは2025年の春の更新でこのフィールドを廃止し、請求と支払いの対応をinvoice.paymentsという配列で表す形へ変えていました。

二度目は、もっと見つけにくい形でした。購読を期末で解約する予約は、以前の仕様ではcancel_at_period_endという真偽値のフィールドで届き、trueなら期末で解約する、という読み方でした。現行の仕様ではこのフィールドが非推奨になり、いつ解約になるかという時刻のcancel_atで届く形に変わっています。AIは古い知識のままcancel_at_period_endを読むコードを書いていたので、読者が予約した解約がアカウントに記録されない不具合になりました。機械のテストはこれをすり抜けていて、見つけたのは、僕がテスト用の環境で実際に解約を操作したときです。仕様の変更は、フィールドのあるなしだけでなく、届く中身の意味そのものにも起きるのです。

三度目になりかけた件もあります。同じ人が購読を二本持つのを防ぐ仕組みで、AIが、既存の設定を調べる前に、解約と返金を自前で行う回避策を組みかけました。公式ドキュメントを読むと、顧客の購読を一本に制限する設定が最初からあったので、それを使う形に組み直しました。この三つの経験から、外部サービスは使う前に現行の公式ドキュメントを実際に読み、フィールドの名前も設定の場所も、記憶ではなくその本文で確かめてから書く、という決まりを定めました。

決まりを定めたあとは、検証の側でもこの読み方が効きました。監査のAIが、データベースの本来のアドレスを隠すために、配信サービスの保護を前段に挟む独自ドメインの対策を推奨してきたことがあります。ところが公式ドキュメントを読んで確かめると、この独自ドメインは、通信の暗号化の都合で配信サービスの保護を通せない方式でしか設定できず、前段の守りとしては成り立たないと分かりました。そもそもデータを守る本体は、前段のネットワークの保護ではなく、行ごとに誰が読み書きできるかをデータベース自身が判定する行レベルセキュリティと、アプリ側の権限の判定にあります。ここは役割の違う実際のユーザを作り、結合テストまで通して固めてあります。独自ドメインの代わりには、月の支出の上限と、サーバ側の関数を呼べる回数の上限と、外形監視の三つを組みました。これらは守りの本体ではなく、本体の外側で量のあふれを抑える歯止めです。同じ型の間違い、つまり古い仕様を記憶で読んでいる箇所がほかにも無いかは、外部サービスとやり取りする全箇所をAIに突き合わせさせ、届くデータの形が現行の仕様と食い違っていないことを確かめました。

調べるのはAIに任せ、費用と権限は人が縛る

外部サービスとの付き合い方では、規約や価格を読む調べものはAIに任せ、費用と権限を縛る最後の判断は人が下す、という分け方がいちばんうまくいきました。この分け方がはっきり出たのは、サイトが外から見て動いているかを間隔をあけて確かめ、落ちていたら知らせる外形監視の選定です。

AIは、商用でも使えるサービスを十四件、現行の価格と利用規約の原文まで読んで洗い出し、無料の範囲で使えるものを推奨として並べました。僕はここで選び直しました。無料であることよりも、有料でもよいから、どのページをどう監視するかの設定をコードとして持てて、そのうえで安いものを選ぶことにしたのです。

この基準には、安さより大事な理由があります。これからの開発では、いままで以上に多くの作業をAIに任せていきます。人が画面を操作しないと設定を変えられないサービスでは、その操作をAIに任せられません。APIで読み書きできるサービスなら、監視の対象を増やすことも、監視が正しく動いているかを確かめることも、AIの作業として組み込めます。そもそもこのサイトは、本人はただ研究と開発を続けるだけで、記事の制作もサイトの運用も自律的に回り続ける形を目指して作っています。その形では、つなぎ合わせる各システムをAPIでプログラマブルに、つまりコードから操作できることが、外部サービスへの要求そのものになります。だから多少高くても、APIで操作できるものを優先しました。選んだのは、一回の確認ごとに少額を払う従量の料金のサービスです。月に百円もかからず、登録のときにもらえる無料分だけで半年以上もちます。監視の設定はコードとしてリポジトリに置いてあるので、何度実行しても同じ結果になり、画面から手作業で足した設定を誤って消すこともありません。

費用の上限も、人が先に決めました。生成AIの利用には、組織の全体に月の支出の上限を掛けてあります。会話の機能にはさらに、一人の会員が一日に送れる量、一人の会員がひと月に送れる量、全会員の合計がひと月に使える量、という三つの上限を重ね、一回の会話でAIへ渡す文章の長さにも上限を置きました。どれかを超えたときは、処理を受け付けずに断り、先に確保していたその会員の利用の枠は戻します。

会話に使う生成AIの契約も、無料の枠ではなく有料のAPIを選びました。提供元の規約を読むと、無料の枠では、利用者が送った文章と生成された答えを、提供元が製品の改善に使うことがあり、人の目で確かめられる場合もあります。有料のAPIでは、製品の改善には使われないと明記されていました。会員が書いた会話の本文を提供元の学習や確認へ渡さないために、ここは費用を払うことにしました。

厳密さの度合いも、用途で分けました。課金と認証と権限は厳密に作り、いいねや閲覧数のような利用の目安は、おおよその集計と間引きで作って、余計な複雑さと費用を持ち込みません。これも、人が先に決めた縛りの一つです。

作れることより、預けられること

外形監視を一つ選ぶだけでも、AIが規約を洗い、僕が基準で選び直し、AIが作って動かして確かめる、という往復がありました。振り返れば、問い合わせは作ってから取り下げて外部へ預け、外形監視は外部のサービスを使い、いいねは会員に絞って自分で受け、独自ドメインの推奨は採りませんでした。どれも、自分で作るか、外部へ預けるか、そもそも持たないか、という同じ三択の判断です。その一つずつが、何を預けて何を持たないかの線を引き直していきました。

実装の量が制約でなくなったいまの開発で、最初に決めるべきだったのは、何を作るかではなく、何を自分で持たないか、言いかえれば、何を外部へ預けるかでした。持たないと先に決めてしまえば、漏れたときの心配も、たたむときに持ち出す苦労も、初めから消えます。基準を人が先に置き、現行の仕様の検証と費用の縛りを組み込んでおけば、AIにどれだけ量を出させても設計は破綻しません。作れるかを数えるより先に、何を預けられるかを決めます。ここで引けるのは預ける側の線までで、自分で書いたコードそのものが正しいかは、また別の守り方が必要です。その後ろ半分の話は、続きの一本に書きます。