ログインしても章が開かない会員機能を直した日:ログイン後の戻り先とオープンリダイレクトの修正、問題データ75か所の総点検
ログインしても章が開かない会員機能を直した日
会員登録の通知が、思ったより届いていた。 登録してくれた人たちは、実際に問題を解いているのだろうか。 それが気になって、Claude Code に本番の利用状況を見てもらった。
返ってきた答えは「使える状態ではある。ただ、使っているのは一部」だった。 登録したまま、問題を1問も解いていない人がいる。
有料の章は無いつもりだった
最初は、本番 DB から会員ごとのログイン回数と回答数を集計してもらおうとした。 列名を直して再実行している間に、ちょうど私が管理者としてログインしたので、管理画面から見てもらう形に切り替えた。 状態をきちんと確かめてほしかったので、私から許可も出した。
Claude Code が見つけたのは、登録した人が期待するものを受け取れない作りだった。
- 仕訳問題集の「ログインして解放」から登録しても、ログイン後は表示が「購入して解放」に変わるだけで、追加で開く章が無い
- その購入ボタンは本番では必ず失敗し、画面には何も表示されない
私は「有料のページってあるんでしたっけ」と聞き返した。 有料化は予定にあるだけで、今は全部無料、ただしログインは必要、という作りのつもりでいた。 実際には、仕訳問題集の一部が有料扱いになっていた。 全部無料にするつもりだったのに、5月の修正で既定が逆になっていたという。
では、ログインしても使われないのは、開放されなかったからなのか。 Claude Code の見立ては「おそらく大きな理由の一つ。ただ、それだけとは言い切れない」だった。 私は、開放とログイン後の戻り先の両方を直すよう頼んだ。
デプロイの途中で止めたオープンリダイレクト
修正を本番に出すまでに、二度つまずいた。
一度目は、デプロイ用の作業ツリーを入れ替える操作が権限で止められたことだった。
本番のコミットに今回の修正だけを載せた作業ツリーを作り直し、そこからデプロイを流してもらった。
ビルド時に読むのは開発用のフラグと課金ゲートの変数だけで、課金ゲートは実行時に明示して渡すため、.env なしでビルドできた。
二度目は、デプロイを流している最中に、自動のセキュリティレビューが出した指摘だった。
ログイン後の戻り先に /.//evil.example を渡すと、正規化で //evil.example になり、外部サイトへ飛ばせてしまう。
脆弱なまま出さないよう、デプロイを止めて直してもらった。
止めた時点で本番は変わっておらず、中断したビルドのプロセスも残っていなかった。
直し方は、正規化したあとの戻り先が // で始まっていたらトップへ戻す、という1行である。
テスト17件と Codex のレビューを通してから流し直し、15:14 に本番へ出た。
同じ指摘は、同じリポジトリで並走していた別の2セッションでも、それぞれの自動セキュリティレビューから上がっていた。
片方のセッションでは、私から提案して、隣で走っている会員まわりのセッションへメッセージを送ってもらった。
返信は「safeRedirectPath の // 抜けはご指摘どおりで、修正済みです」というもので、本番にも 15:14 に反映済みだという。
/.//evil.example、/a/..//evil.example、/%2e//evil.example のテストも足してあった。
もう片方のセッションには、ほかのセッションがもう連絡しているはずだと伝え、修正のコミットが入っていることを確かめてもらった。
テスト用会員で、私のブラウザで一つずつ
デプロイのあと、テスト用会員で本番の操作を8項目通してもらい、すべて想定どおりに動いた。 主な項目は次のとおり。
- ログアウトした状態で問題集を開く
- 「ログインして解放」を押し、Google に渡る戻り先が問題集のページになっているかを見る
- ログイン後、12の節がすべて鍵なしで開くかを見る
- 以前は鍵がかかっていた節の問題を1問解く
- ランダム10問を開く(再読み込みで1問目が変わる)
- ログイン済みの状態で問題集からログインし直す、攻撃を模した戻り先を渡す
次に、私のブラウザでもステップバイステップで見せてもらった。 管理者でログインしている私のセッションに影響しないよう、ログイン状態を切り離した別のタブを開く。 テスト用会員でサインインしてから、そのタブにセッションを渡して再読み込みする。 いちばん右のタブが、テスト用会員でログインした画面になった。
画面を見ながら、○も×も混ぜて、3問連続の扱いまで想定しているものを全部試してほしいと頼んだ。
- 最後の問題では、「次へ」が「結果を見る →」に変わる
- 1問目を3回連続で正解すると「完了」になり、完了の数が0から1に増える
- ×が1回ある2問目は、2回正解した時点で直近3回が(×、○、○)になり、まだ「×1回」の区分に残る
問題を解く操作は、すべて想定どおりだった。
途中で一度、「左側/右側」を点検する検索のパターンが壊れていて、関係のない行まで大量に拾った。 スクリプトのファイルに書き直し、向きが本当に違う行だけを抜き出す形に改めてもらった。
同じ点検をほかのセッションでも回せるよう、問題集のテスト手順を手順書に足してもらった。 ところが、その追記が別のセッションのコミットに一緒に入ってしまった。 同じリポジトリでステージを共有していたためである。 内容は欠けずに入っていたので、履歴は書き換えていない。 以後のコミットは、変えたファイルだけを名指しする形にしてもらった。
絵と解説文の13件は、どこで間違ったのか
テストの報告には、解説の絵と解説文の誤りが13件挙がっていた。 直してほしいのはもちろんだが、引っかかったのは原因のほうだった。 私が書いて間違えることは多分ないと思っていたので、どの段階で間違いが入ったのかを調べてもらい、ほかにも同じ間違いがないかの総点検も頼んだ。
履歴をさかのぼると、データは2024年より前から来ていて、さらに古いリポジトリ2つまで追うことになった。 並行して、解説の画像と文をサブエージェント5体に手分けして点検させた。 フラグの立った画像は、直す前に全部見直してもらった。
行き着いた先は、2019年の元データだった。 私が書いた段階でも、移行の段階でもなく、元データに最初から入っていた。
修正は、文74か所と正解データ1か所の計75か所をスクリプトで当て、画像11枚を描き直す形にした。
- 空の欄が画面に描画されないことを確かめてから、残っていた「-」や制作メモを空文字にして消す
- JSON のインデントと改行コードを確かめ、読んで書き戻しても他が変わらないことを確認する
- ドライランで75か所すべてが想定どおりに当たってから適用する
- 再実行すると75件とも「適用済み」になって何も変えず、元データに当てると直したデータをそのまま再現する
画像は元の画像と並べ、文字の大きさや太さ、+/−の記号の細さまで寄せた。 このリポジトリは画像を Git LFS で管理しているので、古い画像は LFS 経由で取り出した。 サムネイルで+が少し黄色く見えたのは Windows のサブピクセル描画のせいで、これを切って描き直した。 中身の無い解説見出しを出さない判定も、練習画面とランダム10問の両方に足してもらった。 テスト45件が通り、ローカルでコミットした。
最後の報告は英語で返ってきた。 読んでも分からなかったので、日本語で書き直してもらった。
手形貸付と、消えた車両運搬具
判断が要る問題は、本番で1問ずつ開いて確かめることにした。 はじめはURLを並べてもらったが、タブを切り替えると見比べられないので、7問をそれぞれ別のタブで開いてもらった。
1問目は手形貸付の問題だった。 仕入先から受け取った約束手形は、商品の売買に伴わない手形の受取なので、受取手形ではなく手形貸付金で仕訳を切っている。 その支払期日が来て入金があったので手形貸付金が減る、という問題である。 カテゴリから見れば判別できるが、シャッフルして問題文だけを見ると判別できない。 そこで、問題文のほうを直すことにした。 入金を銀行の預金に合わせ、解説の画像も現金から当座預金へ描き直してもらった。
もう1問は、解説が最初から最後まで「建物」で正しく、問題文だけが違っていた。 この2問の問題文を直した。 途中、HTML のレポートを書き換える編集コマンドが複雑すぎて失敗し、1か所ずつ直す形に切り替えてもらった。
次の問題は、画面で見ると確かに、間接法なのに車両運搬具がそのまま消えていた。 ここは減価償却累計額のはずである。 念のため、表記の「間接法」が誤りなのではなく間接法の問題でよいのか、そして直接法の問題は別にあるのかを確かめた。 間接法の問題で合っていて、間違っていたのは正解データのほうだった。 ただし、直接法の問題はこの問題集に1問も無かった。 減価償却に関わる7問は、すべて間接法だった。
それなら直接法の問題を作ろう、と決めた。 Claude Code が出した作り方の案をそのまま採り、間接法の問題(残存価額10%)を手本に、減価償却の節の間接法2問のすぐ後ろへ2問を足してもらった。
本番に出したものと、まだ出していないもの
本番へは、前回と同じく、今の本番の版に今回の修正だけを載せて出した。 デプロイを待つ間に画像12枚を R2 に上げ、配信側のキャッシュ(最大4時間)に古い画像が残らないよう、その12枚の URL だけキャッシュを消してもらった。 デプロイは17:04に終わった。 直接法の2問は17:20に本番へ出し、テスト用会員で実際に解いて確かめてもらった。
解説の3つめの段落(「3分法との違い」など)が画面に出ていなかった件と、「5つの要素」の点灯(費用+と資産−)の直しは、コミットまで済ませた。 こちらは、まだ本番に出していない。
本文の無い見出し28問は明日へ
もう一つ、見出しだけあって本文の無い解説が、9種類28問見つかっていた。 例を1問開いてもらうと、商品を仕入れて引取運賃も現金で払った問題の解説のいちばん下に、「付随費用の取り扱い」という見出しだけがあり、その下は空だった。
見て、もともとあったものが引き継げていないのではないか、と思った。 元の文章は、別のリポジトリか、移行前のサイトのどちらかに入っているはずである。 ただ、どこに入っているかは見当がつかない。 このセッションで追うのはやめて、明日、調査して持ってくるところまでを1つのセッションの仕事にすると決めた。 それまでは見出しを非表示にしておく方針とし、問題点と経緯を含めた引き継ぎプロンプトを、ダウンロードフォルダのテキストファイルへ書き出してもらうよう頼んだ。
学び
- 登録の通知は届き続けていたのに、その先で章は開かず、購入ボタンは黙って失敗していた。通知が届くことと、登録した人が中身を使えることは、別々に確かめる必要があった
- 「全部無料、ログインだけ必要」のつもりの設定が、5月の修正で逆になっていた。自分が覚えている仕様と本番の既定は、ずれることがある
- 誤りの原因を「私が書き間違えたのか」から追うと、2019年の元データまで戻った。修正スクリプトは、再実行しても何も変えず、元データに当てると直したデータを再現する形にしたので、二度当てても壊れない
- 同じリポジトリで複数のセッションを走らせると、ステージを共有する。自分の追記が他人のコミットに入ったあとは、ファイルを名指ししてコミットする形に変えた
残っていること
- 本文の無い見出し9種類28問の元の文章を探して戻す(明日の調査セッション)
- 解説の3つめの段落の表示と「5つの要素」の点灯の直しを本番に出す
章が開かなかったことが、使われなかった理由のすべてなのかは、まだ分からない。 Claude Code も、それだけとは言い切れないと言っていた。