アーキテクチャ(技術スタック)
先行リリース(催事+アイテム+商社〈卸〉)を本番運用に載せるための技術スタックの確定版。2026-08-20 に前提を確定したもので、実装はこの構成を正とする。
確定スタック
Section titled “確定スタック”| 項目 | 採用 | 備考 |
|---|---|---|
| フロント+サーバー | Next.js(App Router) | フロントとサーバー層を1つのTSアプリに統合。Server Components / Server Actions 主体 |
| 言語 | TypeScript(strict) | |
| ホスティング | Vercel(Node ランタイム) | Next.js一級ホスト。重いサーバー処理でもCPU/タイムアウトの制約を受けにくい |
| データベース | Supabase(PostgreSQL・新規プロジェクト) | ValueOSも Supabase。卸は現行運用が正のため同系DBに寄せる。リージョンは東京 |
| DBアクセス層(ORM) | Drizzle(+Drizzle Kit) | 型安全・軽量・SQL寄り。マイグレーションをコード側で一元管理 |
| 認証 | Supabase Auth(+最小RLS) | 本社=Google、代理店=メール招待制(後述) |
| ファイル保存 | Supabase Storage | 公的書類写真・帳票PDF(署名付きURL) |
| UI | Tailwind v4 + shadcn/ui | 現行モックの画面部品を移植 |
| パッケージ管理 | pnpm | |
| リポジトリ | 新規 Next リポジトリ | クリーンに新設。画面部品を移植し、現行モックは参照用に残す |
| ドキュメント | 現行の Cloudflare Pages(vec003-crmdocs)を継続 |
なぜこの構成か
Section titled “なぜこの構成か”- Next.js:フロントとサーバー層を1つのTSアプリで持てる(API別建て不要)。エコシステム・認証パターン・情報量・寿命が最も厚く、クライアントのValueOS(Next.js+Supabase)とも発想が揃う。
- バックエンド未着手の”今”が最適な選定タイミング:本番の難所はこれから作るため、器(フレームワーク)を最良にしても沈むのはモックのフロント外殻だけで、画面部品(Tailwind/shadcn/React)は移植できる。
- 重い業務ロジック/KPIはサーバー側に置くのが業界の合意。クライアント直叩きにはしない(後述)。
レイヤ設計(3層)
Section titled “レイヤ設計(3層)”| 層 | 技術 | 役割 |
|---|---|---|
| フロント | Next.js(Client Components/必要箇所のみ) | 画面・UI状態 |
| サーバー・ドメイン層 | Next.js の Server Components / Server Actions / Route Handlers(TS) | 卸/決済/予実の業務ロジックを集約。service_role を保持し、単体テスト可能に保つ |
| データ | Supabase(Postgres+Auth+Storage) | 保存・認証・ファイル。KPIはDB内で事前計算 |
- DBアクセスはサーバー経由のみ(
service_role)。ブラウザはDBを直接叩かない(anonキーをブラウザに配らない)。 - 卸/決済の不変条件・多テーブル原子更新は Postgres 関数(RPC) で担保(発注→請求→入金・三社間決済)。
- 予実/KPI は マテリアライズドビュー+pg_cron でDB内に事前計算し、画面は結果を読むだけにする(重い集計をHTTP同期で回さない)。
認可(RLSは”最小バックストップ”)
Section titled “認可(RLSは”最小バックストップ”)”RLSを主役にすると運用が重くなるため、本構成では認可の主役をサーバー層のTSに置く。
- 主役=サーバー層のTS:代理店の自社データ隔離・6ロールの出し分けを、
agency_id/roleを使ったTSコードで判定(一箇所・テスト可能・デバッグ容易)。 - RLSは全テーブルON+“
service_roleのみ許可”の一律最小ポリシー(=既定拒否。RLS無効テーブルが素通しになる事故を防ぐ多層防御の薄い方)。 - 凝ったRLSを書くのは、将来ブラウザがSupabaseを直接触る箇所だけ(Realtime購読・Storage署名URL 等を導入する場合)。当面は不要。
- 唯一の規律:DBアクセスは必ずサーバー層を通すこと。
認証設計(形態別)
Section titled “認証設計(形態別)”| 形態 | ログイン方式 | 登録方法 | データ範囲 |
|---|---|---|---|
| スーパーユーザー(Ouver 運用・管理) | メール+パスワード(別途発行) | 別途プロビジョニング(VEドメイン外) | 運用に必要な全体(保守・管理) |
| 本社社員(本部管理者/社内営業/経理/発注担当) | Google OAuth | 自己ログイン | ロールに応じた社内データ |
| 代理店(管理権限者) | メール+パスワード/マジックリンク | 管理者の招待制 | 自社の催事・希望・報告のみ |
| 催事スタッフ(代理店配下) | 同上 | 代理店管理権限者/本部が招待 | 自社の催事のみ |
- Ouver メンバーは「管理スーパーユーザー」として別途用意したアカウントで入る(
@valueecology.jpのGoogleログインとは別系統)。運用・保守はこのスーパーユーザーで行う。 - 本社Googleの許可ドメインは
@valueecology.jpのみ。Auth Hook/DBトリガでメールドメインを検証し、それ以外のGoogleログインを拒否する。 - ロールモデル上、スーパーユーザーは業務ロール(本部管理者ほか)より上位のシステム/運用ロールとして
profiles.roleに持たせる。 - 代理店は招待制(メールの自己サインアップは無効化、
inviteUserByEmailで発行)。約40社に個別アカウントを配布。 profilesテーブル(ValueOSのstaff_profiles相当)にrole/agency_id/dept(部署。履歴は 部門の自動導出 の部署履歴)を持ち、セッションからrole/agency_idを解決してサーバー層の認可に用いる。
- 通知台帳(
NOTIFY_RULES)を土台に、キュー+ワーカー(Server Action/将来的にEdge/外部キュー)で非同期送信する設計とする。 - 実送信の配線と、会社ごとの手段振り分け(メール/LINE/Slack)は未確定=要確認(通知 参照)。まずは台詳とキューの器まで。
データ移行方針(モック→本番)
Section titled “データ移行方針(モック→本番)”lib/*.tsの型(既に ValueOS スキーマ相当に整備済み)を Drizzle スキーマ+Postgres へ写像し、マイグレーションで管理する。- 画面部品(shadcn/React/Tailwind)を新規 Next リポへ移植。ルーティング・データ取得は Next(App Router)へ作り替える。
- マスタ → 催事 → 卸 → 予実 の順に、モックのデータ層を Supabase 実DBへ差し替える(現行の増分運用と同じ刻み)。
- 実データ(代理店等の実PII)は認証+認可で保護された環境でのCSV取込に限定し、公開URLには載せない。書類は Supabase Storage。
- 環境は local / staging / production の3面。Vercel(アプリ)+ Supabase(DB、東京リージョン)。
- Supabase/Vercel は Ouver が契約・請求する(Ouver 所有)。有償プラン(Supabase Pro 相当)想定。データはクライアントの事業情報だが、契約・課金の名義は Ouver。
- ドメイン層は Vitest で単体テスト、CI で lint / typecheck / test / build。開発は dev-flow(worktree・並列実装・検証・レビュー)を継続。
- 通知の実送信配線と、会社ごとの手段振り分け(メール/LINE/Slack)。
(解決済:Supabase/Vercel は Ouver が契約・請求。Ouver メンバーは 管理スーパーユーザーで入る。本社Google許可ドメインは @valueecology.jp のみ。)