評価と調整

Sushi SaaS の構造

強制されるレイヤー、そのトレードオフ、二つ目のアーキテクチャを作らず機能を追加する方法を説明します。

このガイドは、最初のプロダクト機能をどこに置くか判断する、導入チーム向けの説明です。Sushi SaaS はすべての機能領域で一つの水平アーキテクチャを使い、テストで規約を強制します。

リクエストが通る経路

src/app/**       ルートとページ — HTTP の入口と出口

src/services/**  業務ルール、調整、不変条件

src/models/**    型付き永続化;db() を呼べる唯一の層

src/db/**        スキーマ、マイグレーション、接続

ルートは入力を解析して応答します。サービスは処理が許可されるかを判断し、副作用を調整します。モデルはデータベースの読み書きを一手に引き受けます。データベース制約は、並行するリクエストに対する最後の防御です。

ブラウザーにも別の境界があります。

Server Component  → サービスを直接呼ぶ
Client Component  → src/api/** → 共通 API クライアント → /api/**

サーバーから自分自身への HTTP 呼び出しを避け、クライアント側のエラーを一つのレスポンス契約にそろえます。正確な規則はアーキテクチャとエラー契約を参照してください。

水平レイヤーを選んだ理由

課金、クレジット、ストレージ、予約、タスクは、いずれも認証、テナントの範囲、エラー処理、永続化を必要とします。同じレイヤーを使うことで責務の置き場所が予測可能になり、アーキテクチャテストが規約外の近道を検出できます。

一方で、一つの機能が複数のディレクトリに分かれます。大規模なプロダクトでは、機能ごとにまとめる垂直構造の方が追いやすい場合もあります。ただし二つの構造を混ぜると、次のクエリや業務ルールの置き場所が二つになり、どちらか一方に統一するより分かりにくくなります。

選択肢

  • 既定構造を維持:強い規約と共通基盤を求める小規模チーム向けです。
  • 垂直スライスへ全面移行:それがチーム標準なら、機能領域全体を移動し、tests/unit/architecture.test.ts も更新します。既存規則の横に src/features という別方式の島を作らないでください。
  • 短期プロトタイプ向けに簡略化:後で移行する費用を受け入れる場合だけです。ルートから DB へ直接書き込むなら、例外を増やすのではなく、テストも意図に合わせて変更します。

テナント設計もアーキテクチャ判断

すべてのユーザーに個人用の組織が作られます。そのため、一人で使う顧客もチームも、同じ組織単位の課金、クレジット、ファイル、上限を利用でき、「ユーザー所有」と「チーム所有」という二つの経路を持たずに済みます。

将来チーム機能を追加する可能性があるなら、この設計を維持します。常に一人で使う製品なら組織の仕組みを除く選択もできますが、認可、スキーマ、モデル、課金、ストレージ、テストを一緒に変える必要があり、画面上の切り替えだけでは済みません。組織とチームを読んで判断してください。

管理コンソールを分けた理由

apps/admin は独自のページ、管理 API、データアクセス、MFA の入口、運用担当者の権限を持ちます。スキーマと認証データを共有しながら、別のオリジンへデプロイできます。ビルドとデプロイが一つ増える代わりに、運用アクセスの境界が明確になります。

一つのデプロイにまとめたい場合は顧客アプリへ統合できます。ただし、サーバー側の管理者認可と監査は維持してください。ナビゲーションを隠すだけではセキュリティ対策になりません。管理コンソールの設定から確認します。

横方向 layer を通る完全な縦 journey

画像 reference は構造の価値を示します。Route が auth、service が fingerprint、deterministic 5-credit spend、durable dispatch、model が SQL、DB constraint が relation、replaceable provider adapter、worker が private output または ledger compensation を担います。Route、service、DB、component、Playwright test が別々の boundary を証明します。

最初の有料 domain を設計する前に、1 つの 5-credit task が SaaS 全体をテストする理由を読んでください。

最初の機能領域を追加する

  1. src/typessrc/config で用語と上限を定義します。
  2. src/db にスキーマと、段階的な展開に安全なマイグレーションを追加します。
  3. 型付き CRUD を src/models に置きます。
  4. 認可、冪等性、副作用を src/services に置きます。
  5. ルートまたは Server Component を src/app に追加し、クライアントからの呼び出しには src/api を使います。
  6. サービスの規則、ルートの認証ゲート、金銭・クレジット処理の再実行をテストします。

プラン名を直接比較せず、利用可能な機能を確認してください。契約が変わったら運用手順書も更新します。本ガイドはスターターのコミット 2a1a04a に基づきます。

Sushi SaaS の構造 · Sushi SaaS