松葉/ Matsuba
アプリケーション基盤 実装レポート
クラウド基盤(Google Cloud + Supabase + Resend + GitHub で用意した「器」)の上に、実際に動くアプリケーションの共通土台(コード側)を実装しました。複数の言語・サービスをひとつのリポジトリに束ね、型の共有・データベースの認可・イベントの受け渡し・自動デプロイまでを組み上げ、手元のパソコンでの稼働から本番環境への初回デプロイまでを疎通(リクエストや通知が経路を通って相手に届き、応答が返る状態)させた到達点を、図と表で 1 ページずつまとめています。
共通土台の要点By the numbers
実装した土台を象徴する 4 つの数字です。いずれも「業務機能そのもの」ではなく、その業務機能を載せるための土台にあたります。土台が正しく組まれていないと、後から載せる機能すべてに不具合や手戻りが波及します。
Monorepo
4 + 7アプリ / 共通部品
4 つのアプリと 7 つの共通部品(パッケージ)を、1 つのリポジトリ(モノレポ)に同居。TypeScript と Go の 2 言語が混在します。
Typed Events
13イベント定義
「ファイルがアップロードされた」等の出来事の形を 1 か所で定義し、TypeScript と Go の両方を自動生成。送り手と受け手で型がズレません。
Authorization
3 + RLSDB 経路 / 行レベル
データベースへ触る経路を用途別に 3 つだけに限定し、最後は行レベルセキュリティ(RLS)が「あなたが見てよい行か」を DB 側で判定します。
Keyless Deploy
0発行した鍵
ソース変更時の自動デプロイ(CD)は鍵を発行しない方式(WIF)。この仕組みで本番環境への初回デプロイまで疎通を確認しました。
本資料の構成Ten chapters
テーマ別に 10 ページへ分けました。最初の「全体像」で俯瞰してから、土台の外側(リポジトリ・型)→ 中核(データベース・設計)→ 連携(イベント・検査)→ 画面・自動化、の順に読むと流れがつかめます。
全体像Architecture
リポジトリ(モノレポ)→ ビルド → 4 サービス + 1 ジョブ → 外部(Supabase / GCS / Drive / Pub/Sub)の連動を 1 枚の図に。成果物の全件一覧も併載しています。
図で見る Workspaceモノレポと開発環境Monorepo
複数言語・複数アプリを 1 リポジトリに束ねる「4 軸」の仕組みと、手元のパソコンで 4 サービスを起動して本番リソースに繋ぐローカル開発環境を整えました。
読む Type Safety型と契約の共有Contracts
1 つの定義から TypeScript と Go の両方を自動生成し、画面とサーバの間も共通の検証ルール(Zod)で繋ぎます。型のズレを構造的に起きなくする仕組みです。
読む Authorizationデータベースと認可境界Database
DB へ触る 3 つの経路と、行レベルセキュリティ(RLS)による Box 単位の認可境界。さらに、追記専用の監査ログを整えました。
読む Clean Architectureバックエンドの設計Backend
業務処理を 4 つの層に分け、依存の向きを内側へ一方通行に揃える「クリーンアーキテクチャ」。変更に強く、テストしやすい骨格を先に用意しました。
読む Messagingイベント駆動の整合性Events
「更新はできたが通知は送れなかった」を防ぐ Outbox パターン、流通を担う Pub/Sub、二重処理を防ぐ 2 層の冪等性、取りこぼしの退避先(DLQ)。
読む Antivirusウイルス検査の連携Scanning
アップロードされたファイルを、検査が終わるまで利用させない仕組み。ストレージの変更を起点に検査サービスを自動起動し、結果でバケットを振り分けます。
読む Design System画面の基盤Frontend
どの画面を作っても松葉らしい配色・書体・形が自動で当たるデザイン基盤と、既製の画面部品 55 種を 1 つずつ精査して採否を判断した結果をまとめます。
読む Keyless CD自動デプロイCI/CD
ソースコードを更新すると、変更のあったサービスだけを、鍵を発行しない安全な方式(WIF)で自動的に本番へ反映します。初回デプロイの疎通まで確認済みです。
読む Workflowsユースケース別ワークフローUse Cases
これまでの仕組みが、実際の業務ではどう連携するか。「アップロード→検査」「Drive 同期」「各種スケジュール」を 3 つの連携パターンに整理して図示します。
読む土台を貫く 4 つの設計方針Four design principles
個別ページの細部に入る前に、全体を貫いている考え方をお示しします。「なぜ業務機能の前にこれだけの土台が要るのか」が腹落ちする補助線として読んでください。
1 つの定義から型を生む
イベントの形は protobuf で 1 か所に定義し、TypeScript と Go を自動生成。画面とサーバの間も Zod スキーマで共有し、型のズレを「起こりうるミス」ではなく「構造的に起きない」状態にします。
認可を多層で締める
DB へ触る経路を用途別に 3 つに限定し、最後は 行レベルセキュリティ(RLS)が DB 側で最終判定。アプリ側に抜けがあっても、他人の Box のデータは構造的に見えません。
イベントを取りこぼさない
更新と通知の食い違いを防ぐ Outbox、二重処理を防ぐ 2 層の冪等性、失敗を捨てない 退避先(DLQ)。13 種のイベントすべてに同じ構造の退避先を 1 対 1 で用意しました。
鍵を発行しない自動化
ソース変更時の自動デプロイは Workload Identity Federation(WIF)でキーレス。JSON 鍵ファイルを 1 つも発行せず、リポジトリ単位で身元を限定して本番へ反映します。
本資料の読み方How to read
推奨の読み順: まず「全体像」で俯瞰し、以降は上のカードの並び順(モノレポ → 型と契約 → DBと認可 → 設計 → イベント駆動 → 検査連携 → 画面基盤 → 自動デプロイ → ユースケース)に読み進めるのがおすすめです。各ページは独立して読めます。
専門用語について: 本文中で初めて登場する専門用語には括弧で日本語の補足を添えています(例: モノレポ(複数のアプリ・部品を 1 つのリポジトリにまとめて管理する方式))。用語自体は正式名称のまま使っています。
実装済みと今後の区別: 現時点は土台(コードの骨格)を組み、本番疎通まで確認した段階です。実際の業務処理(ファイル操作や通知の中身)は今後の開発で載せていきます。図では実線=実装済み・本番疎通済み、破線=未実装(今後の開発で対応)として区別しています。誇張せず、到達点を事実のまま記しています。
次のページ: 全体像(成果物が本番でどう連動するかを 1 枚の図にまとめました)