ワダチを作る #14:公開の前に、別のモデル(Fable)にセカンドオピニオンを頼んで、公開した

前回(#13)で、利用規約や紹介のページを作り、あとは本番の Access を外すだけになりました。

その前に、ここまでのコードと文を、別の目で見直してもらうことにしました。今回は、そのレビューと、実際に公開した話です。

  • 書いたのとは別のモデル(Fable)に、5 つの観点でレビューを頼んだ
  • 報告を 1 件ずつ確かめて、直すもの・直さないものを決めた
  • 公開の前に直すものを直して、本番の Access を外した

なぜ、別のモデルに頼んだか

ワダチのコードと文は、ほとんど同じモデル(Claude の Opus)が書いています。同じ頭で見直すと、書いたときと同じ思い込みのまま、通してしまうおそれがあります。

ちょうど、Claude の新しいモデル「Fable」が、使っているプラン(Max)で、しばらくのあいだ使えました。そこで、Fable にセカンドオピニオンを頼むことにしました。ねらいは 2 つです。

  • 違うモデルの目で見て、同じ見落としを重ねない
  • 決めた経緯を知らない、新しい目で見る(「前に確かめたから大丈夫」という思い込みがない)

ハコヅミでも、ベータ版の前に同じレビューをしています。そのときは別のモデルを使えず、同じモデルの新しいセッションで行いました。それでも、直す Issue がいくつも出ました。

頼み方

観点を 5 つに分け、観点ごとに、新しいセッションで頼みました。

  1. 全ソース(バグと、よりよい構成)
  2. セキュリティ
  3. 利用規約・プライバシーポリシー(文と実装のずれ)
  4. テスト(空振りしているテスト、確かめていない経路)
  5. 画面の使い方(提案だけ)

どの回にも、同じ前置きを付けています。要点は次のとおりです。

  • 直させない。報告だけ。重い順に、何が問題か・ファイルと行・どういう入力で何が起きるか・確信の度合い
  • 「こう決めた」と書いてあることでも、決め方そのものが危なければ指摘してよい
  • 前のセッションの経緯(記憶)は、判断の根拠にしない。今のコードと文を読んで判断する
  • 問題がなかったところは、「何を見て、問題がないと判断したか」を書く(見ていないのか、見て大丈夫だったのかを区別するため)

報告は、うのみにしません。ふだんのセッションに戻って、1 件ずつ、本当に起きるかを確かめました。

見つかったこと

1. ソース:記録の画面が、無料プランの上限を大きく超えていた

いちばん大きかったのは、記録の画面が、表示のたびに、全期間の記録を読んで数え直しているという指摘です。

本番の Cloudflare のログ(Observability)を見ると、記録の画面の CPU 時間は、1 回 41〜114ms でした。Workers の無料プランの上限は、1 回 10ms です。まだエラーにはなっていませんでしたが、記録が増えるほど重くなります。この直しは、次回の話です。

ほかにも、小さな穴がいくつか見つかりました。

  • 始めた日を打ち間違えると(2026 年を 0226 年など)、記録の画面が何百年分を数えて、開けなくなる
  • 内容を 51 個以上選ぶと、エラーになる(D1 は、1 つの SQL 文に渡せる値が 100 個まで)
  • 2 つの端末からほぼ同時に保存すると、座った時間が減る・期間が 2 つできる、がまれに起きる

2. セキュリティ:他人のデータに届く経路は、なかった

Fable は、手元で確認用のユーザーを 2 人作り、利用者 B から A の習慣へ、17 種類のリクエストを実際に送って確かめていました。どれも 404 か 400 で、他人のデータに届く経路は見つかりませんでした。

指摘は 3 つでした。

  • 回数の制限が、無料プランの 1 日の枠を守れていない:ログインの始まりは、ログインしていなくても、1 回ごとにデータベースに 1 行書く。今の制限(1 分 30 回)では、枠を使い切れてしまう
  • 入口の判定(hooks)は URL をエンコードされたまま、画面の振り分けはデコードしたあとで見ていて、ずれがある(今は抜け道にならない)
  • Google のログインのトークンが、データベースに平文で残っている(アプリは使っていない)

3. 規約:「お知らせします」と書いたのに、知らせる場所がない

利用規約に「本サービスの中でお知らせします」と書いてあるのに、お知らせの仕組みがない、という指摘です。言われてみれば、そのとおりでした。

ほかにも、文と実装のずれが 10 件ほど。たとえば、「残しません」の直後に「残ります」と書いてある、タイムゾーンのクッキーがログインの前から付く、ブログに入っていないアクセス解析のクッキーのことを書いている、などです。

4. テスト:空振りはなかったが、言いすぎがあった

「断られること」を確かめるテスト 65 か所を、1 つずつ突き合わせてもらいました。空振りしているテストは、ありませんでした。

ただ、Issue の受入条件に「自動テストで確認」と書いたのに、実際にはテストが通っていない経路が 3 つありました。テストを足しました。

5. 画面:初めて使う人のつまずき

画面の絵 34 枚つきで、22 件の提案をもらいました。初めて使う人が、つまずきそうなところです。

  • 曜日を選んでも「曜日を指定」に切り替わらず、黙って「毎日」で保存される
  • 「やめる」が、確認なしで、すぐ実行される
  • 記録の画面に、毎日、割合(%)が出る。成績表のように見えて、「責めない」方針と合わない
  • タイマーを止めたあと、何が記録されたか分からない

直したもの・直さなかったもの

指摘を確かめて、公開の前に直すものを 6 つの Issue にしました。

  • 小さな穴(始めた日の範囲、内容の数、同時の保存)
  • 守りの強化(ログインの回数を 1 分 10 回に、パスの判定をデコードしたあとに、Google のトークンを暗号にして保存)
  • 記録の画面を軽くする
  • お知らせを作る(ハコヅミと同じ作り)
  • 規約・ポリシー・画面の文を、実装に合わせる
  • 初めて使う人のつまずき(曜日を触ったら自動で「曜日を指定」に、「やめる」に確認、記録の画面から割合を外す、タイマーの結果を出す、など)

直さないと決めたものには、理由を残しました。たとえば、GitHub Actions の参照を、タグではなくコミットの番号で固定する、という指摘です。安全にはなりますが、版を上げる手間が増えます。使っているのは GitHub 公式のものだけなので、長く 1 人で保守する方針を優先しました。

画面の提案のうち、すぐに直さないものは、あとで直す Issue(ステップ5)にしました。

公開した

直しを本番に出したあと、前回書いた手順で、本番の Access を外しました。Access の画面の操作は、人が行います。

  1. 本番で、招待制が効いていることを確かめた。招待していないアカウントでログインすると、「このアカウントは、招待されていません」と断られ、ユーザーも作られない
  2. 本番の Access と、ホーム画面のアイコンのための例外の設定を消した
  3. curl とブラウザで、ログインしていなくても、トップページ・使い方・規約が見え、記録の画面はログインの画面に移ることを確かめた

招待制を確かめるには、「まだユーザーがいない Google アカウント」が要ります。ところが、手元のアカウントは、確かめる前に一度ログインしてしまっていました。そこで、その行を本番のデータベースから人が消してから、試しました。

あわせて、Cloudflare のレート制限ルール(IP アドレスごとに 10 秒 100 回まで)を入れました。アプリの中の回数の制限は送信しか数えないので、読むだけのリクエストもまとめて抑えるためです。無料プランでは、ルールの画面に「ホスト名」の欄がなく、「式を編集」で http.host eq "wadachi.jiru-labo.com" と書きました。

招待制は、続けます。ベータ版のあいだは、初めて使い始められるのは、招待した人だけです。ステップ4のマイルストーンを閉じて、ステップ5(その他の機能強化)に進みました。

おわりに

  • 書いたのとは別のモデルに、観点ごとに、直させずに報告だけを頼んだ
  • 報告は、うのみにせず、1 件ずつ確かめてから直した。直さないものは、理由を残した
  • いちばん大きな収穫は、本番の CPU 時間が、無料プランの上限を大きく超えていたことに気づけたこと
  • 「自動テストで確認」と書いたのに通っていない経路は、レビューでなければ気づけなかった

次回は、記録の画面の CPU 時間を下げた話と、その途中で気づいた、データベースの「読む行の数」の落とし穴です。

← トップページに戻る