~/work $ cat circlo/case-study.md

Circlo.

「IT が苦手でも大丈夫」を掲げるグループ運営アプリ。認証から課金まで、 その設計で下した判断と、その理由の記録。

役割
設計・実装・運用すべて
種別
グループ運営 Web アプリ(PTA・子ども会・自治会 ほか)
主な技術
Next.js · TypeScript · Supabase (Postgres/RLS) · Stripe · Playwright · Vercel
ステータス
運用中 · 継続開発

## overview

何をつくったか

よてい・おしらせ・やること・会費・当番──ばらばらだった役員の仕事を、スマホひとつにまとめる Web アプリ。

使うのは、必ずしも IT に強くない保護者やボランティアの方々。だから 「動くこと」だけでなく「怖くないこと」を設計の中心に置きました。 認証・認可・ファイル・課金・テスト・運用まで、通して設計しました。以下は、その過程で 「なぜそう決めたか」が伝わる判断をいくつか抜き出したものです。

## decisions

設計で下した判断

authz · defense-in-depth

認可を「画面を出さない」だけで守らない

課題

役員データ(名簿・会費・当番)は個人情報です。ログイン突破やセッション奪取が起きたとき、 「画面を描画しない」だけの防御では、データベースには生の情報が残ってしまう。 非エンジニアが毎日使う以上、設定ミスひとつで漏れる余地を消したかった。

選んだ手

2要素認証(TOTP)を用意し、一度登録した人には毎回の再検証を要求。そのうえで 「多要素で検証済みであること」を画面遷移・API・データベースの3層すべてで一致させました。 DB 層は既存の認可ロジックを壊さない“後付けのゲート”として重ねる方式を選び、 分散しがちな認可判断を最終的に DB へ収れんさせています。

効果

どれか1層の実装をミスしても、他の層が最後の砦になる。 「結局 DB が守る」という一本の筋が通り、認可の考え方がシンプルになりました。

storage · future-proofing

将来の「値上げ」に、設計で逃げ道をつくる

課題

小さく始めるサービスでは、将来のインフラ原価(とくにファイルの転送量)が読めません。 値上げや移行が必要になったとき、アプリ全体に手を入れる羽目になるのは避けたかった。

選んだ手

ストレージへのアクセスをひとつの抽象層に集約し、データベースには 保存先内のパスだけを持たせる構造に。バックエンドを別のオブジェクトストレージへ替えるときも、 その1ファイルの差し替えとデータ移送だけで済むようにしました。

効果

「今は手軽なものを使い、高くついたら替える」を、後から慌てず選べる状態に。 設計の時点で退路を持てたのが大きい。

billing · idempotency

お金の処理は「二重に効かない」を最優先に

課題

サブスク課金では、外部からの通知が再送されたり順序が前後するのは日常茶飯事。 これを雑に扱うと、二重反映や容量の不整合につながります。

選んだ手

外部通知は署名の検証そのものを認証とみなし、記録と反映をひとつのまとまった処理に。 「何度届いても結果は同じ」になるよう、毎回いまの契約状態から計算し直して上書きする方式にしました。

効果

再送や順序ゆらぎに強く、中途半端な状態が残らない。 お金まわりを安心して運用できる土台になりました。

quality · safety-net

壊れたデプロイを、ユーザーより先に捕まえる

課題

「IT が苦手でも大丈夫」を掲げる以上、不具合に最初にぶつかるのがユーザー、 という事態はいちばん避けたい。

選んだ手

主要な操作をブラウザ自動テスト(E2E)で通し、CI に組み込みました。さらに、テスト対象が 「いま反映された版」であることを待ち合わせる仕組みを入れ、 古い版に対して“緑”になる誤判定を防いでいます。

効果

後戻りバグをリリース前に捕まえられる。 ユーザーの信頼を静かに支える安全網になりました。

## takeaways

学んだこと

  • 認証〜課金〜運用まで通したことで、「どこを厚くし、どこを削るか」を選ぶ判断力がついた。
  • 完璧を狙うより、壊れても最後の砦が残る設計のほうが、非エンジニアの日常使いには効く。
  • 小さく始めるからこそ、将来のコストと移行を最初から設計へ織り込む価値を実感した。

// この記事の粒度について

設計の判断と効果までを公開し、再現手順・設定値・内部構成といった 運用上の機微は意図的に伏せています。より踏み込んだ技術詳細は、面談などで個別にお話しします。