Portal.C Documentation
Portal.Cプロジェクトのドキュメントへようこそ!
プロジェクト概要
Portal.Cは、Tech.C Ventureのメンバー管理とイベント管理を行うWebアプリケーションです。技育プロジェクトVol.16で開発される、Tech.C Venture初の基盤システムです。
主要機能
- 認証・ログイン機能: ZITADEL認証基盤を使用した認証システム
- メンバープロフィール機能: 学年自動計算、24時間限定ステータス、スキルタグ管理
- 時間割閲覧機能: 学年・専攻でフィルタリング可能なメンバー時間割
- イベント管理機能: イベント一覧表示と参加表明
- 管理者画面: イベント登録、参加者管理
技術スタック
- フロントエンド: Next.js 15 (App Router), React 19, TypeScript 5.6+
- バックエンド: TypeScript
- データベース: Supabase (PostgreSQL)
- 認証基盤: ZITADEL (NextAuth.js経由)
- スタイリング: Tailwind CSS
- UIコンポーネント: @openameba/spindle-ui
- ホスティング: Vercel
ドキュメント構成
Getting Started
開発を始めるための基本的な情報
- 開発者向けオンボーディング - 環境構築から開発フローまで
Architecture
プロジェクトのアーキテクチャ設計
- アーキテクチャ設計 - Clean Architectureの詳細設計
- マイグレーション計画 - アーキテクチャ移行計画
Development Guide
開発時のガイドライン
- AGENTS設定 - AI開発支援の設定
Specification (SDD)
プロジェクトの仕様書とガイドライン
- Steering: プロジェクト全体のガイドライン
- Product, Tech, Structure
- Specs: 機能仕様書
- Clean Architecture Refactor
クイックスタート
- 開発者向けオンボーディングを読む
- アーキテクチャ設計でプロジェクト構造を理解
- AGENTS設定でAI開発支援を設定
リンク
Portal.C 開発者向けオンボーディングガイド
Portal.Cプロジェクトへようこそ!このガイドでは、新しい開発メンバーがスムーズにプロジェクトに参加できるよう、必要な情報をまとめています。
目次
プロジェクト概要
Portal.Cは、Tech.C Ventureのメンバー管理とイベント管理を行うWebアプリケーションです。技育プロジェクトVol.16で開発される、Tech.C Venture初の基盤システムです。
主要機能
- 認証・ログイン機能: ZITADEL認証基盤を使用した認証システム
- メンバープロフィール機能: 学年自動計算、24時間限定ステータス、スキルタグ管理
- 時間割閲覧機能: 学年・専攻でフィルタリング可能なメンバー時間割
- イベント管理機能: イベント一覧表示と参加表明
- 管理者画面: イベント登録、参加者管理
技術スタック
- フロントエンド: Next.js 15 (App Router), React 19, TypeScript 5.6+
- バックエンド: TypeScript
- データベース: Supabase (PostgreSQL)
- 認証基盤: ZITADEL (NextAuth.js経由)
- スタイリング: Tailwind CSS
- UIコンポーネント: @openameba/spindle-ui
- ホスティング: Vercel
前提知識
開発に参加する前に、以下の技術についての基礎知識があることが望ましいです:
必須
- TypeScript: プロジェクト全体がTypeScriptで書かれています
- React: React 19の基本的な理解
- Next.js: App Routerの基本(Server Components / Client Components)
- Git: バージョン管理の基本操作
あると良い
- Clean Architecture: プロジェクトのアーキテクチャパターン
- PostgreSQL: データベース設計とクエリ
- Tailwind CSS: ユーティリティファーストCSSフレームワーク
- Supabase: BaaS(Backend as a Service)の概念
学習リソース
開発環境のセットアップ
1. 前提条件
以下のツールをインストールしてください:
- Node.js 18+: nvmの使用を推奨
- npm: Node.jsに同梱(プロジェクトではnpmを使用)
- Git: バージョン管理
- エディタ: VSCode推奨(プロジェクトには設定ファイルが含まれています)
2. リポジトリのクローン
git clone https://github.com/Tech-C-Venture/Portal.C.git
cd Portal.C
3. 依存関係のインストール
npm install
4. 環境変数の設定
.env.exampleをコピーして.envファイルを作成:
cp .env.example .env
.envファイルを編集し、以下の値を設定してください:
# ZITADEL認証
ZITADEL_ISSUER=https://your-zitadel-instance.zitadel.cloud
ZITADEL_CLIENT_ID=your_client_id
# NextAuth
NEXTAUTH_SECRET=your_secret_key_here # openssl rand -base64 32 で生成
NEXTAUTH_URL=http://localhost:3000
# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key
注意: 環境変数の実際の値は、プロジェクトリードまたは運営メンバーから入手してください。
5. Supabaseのセットアップ
- Supabase ダッシュボードにアクセス
- プロジェクトを作成または既存のプロジェクトに接続
- SQL Editorで
supabase/migrations/内のマイグレーションファイルを順番に実行:20241216000001_create_members_table.sql20241216000002_create_tags_table.sql20241216000003_create_events_table.sql20241216000004_create_timetables_table.sql
6. 開発サーバーの起動
npm run dev
ブラウザで http://localhost:3000 を開いて動作を確認してください。
7. ビルドとリントの確認
# ビルド確認
npm run build
# リント実行
npm run lint
# テスト実行
npm run test
プロジェクト構造の理解
Portal.CはClean Architectureパターンを採用しています。以下の4層構造で設計されています。
ディレクトリ構造
Portal.C/
├── src/ # Clean Architecture実装
│ ├── domain/ # ドメイン層(ビジネスロジック)
│ │ ├── entities/ # エンティティ(Member, Event, Timetable)
│ │ └── value-objects/ # 値オブジェクト(Email, StudentId等)
│ ├── application/ # アプリケーション層(ユースケース)
│ │ ├── use-cases/ # ビジネスロジック実行単位
│ │ ├── ports/ # インターフェース定義(リポジトリ等)
│ │ ├── dtos/ # データ転送オブジェクト
│ │ └── mappers/ # Entity ↔ DTO変換
│ └── infrastructure/ # インフラストラクチャ層
│ ├── repositories/ # データアクセス実装
│ ├── database/ # Supabaseクライアント
│ └── di/ # 依存性注入コンテナ
├── app/ # プレゼンテーション層(Next.js App Router)
│ ├── events/ # イベント関連ページ
│ ├── members/ # メンバー関連ページ
│ ├── profile/ # プロフィールページ
│ ├── timetable/ # 時間割ページ
│ ├── admin/ # 管理画面
│ └── api/ # API Routes
├── components/ # Reactコンポーネント
│ ├── layout/ # レイアウトコンポーネント
│ └── ui/ # UIコンポーネント
├── lib/ # ユーティリティ関数
├── types/ # TypeScript型定義
├── supabase/ # Supabase設定とマイグレーション
└── .kiro/ # Kiro開発フレームワーク
├── steering/ # プロジェクト全体のガイドライン
└── specs/ # 機能仕様書
Clean Architectureの層構造
┌─────────────────────────────────────────────┐
│ Presentation Layer │
│ (app/, components/ - Next.js App Router) │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Application Layer │
│ (use-cases/, ports/, dtos/, mappers/) │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Infrastructure Layer │
│ (repositories/, database/, auth/, di/) │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Domain Layer │
│ (entities/, value-objects/) │
└─────────────────────────────────────────────┘
依存性ルール: 内側の層は外側の層に依存しません。
- Domain Layer: ビジネスロジック、外部依存なし
- Application Layer: ユースケース、Domainのみに依存
- Infrastructure Layer: 外部サービス統合(DB、認証等)
- Presentation Layer: UI、Application/Domainに依存
重要なファイル
| ファイル | 説明 |
|---|---|
README.md | プロジェクト概要とセットアップ手順 |
CLAUDE.md | AI開発支援用の指示(Kiro Spec-Driven Development) |
docs/ARCHITECTURE.md | Clean Architectureの詳細設計 |
.kiro/steering/ | プロジェクト全体のガイドライン(product.md, tech.md, structure.md) |
package.json | 依存関係とスクリプト定義 |
tsconfig.json | TypeScript設定(パスエイリアス含む) |
開発ワークフロー
Kiro Spec-Driven Development
Portal.CではKiroスタイルのSpec-Driven Developmentを採用しています。これにより、要件定義→設計→実装の流れが明確になり、AI支援開発が効率化されます。
基本フロー
-
Phase 0(オプション): プロジェクトガイドラインの準備
/kiro:steering: ガイドライン管理/kiro:steering-custom: カスタムガイドライン作成
-
Phase 1(仕様策定):
# 1. 仕様初期化 /kiro:spec-init "新機能の説明" # 2. 要件定義 /kiro:spec-requirements {feature-name} # 3. ギャップ分析(オプション、既存コードベースとの整合性確認) /kiro:validate-gap {feature-name} # 4. 設計 /kiro:spec-design {feature-name} [-y] # 5. 設計レビュー(オプション) /kiro:validate-design {feature-name} # 6. タスク生成 /kiro:spec-tasks {feature-name} [-y] -
Phase 2(実装):
# タスク実装 /kiro:spec-impl {feature-name} [task-numbers] # 実装検証(オプション) /kiro:validate-impl {feature-name} -
進捗確認:
/kiro:spec-status {feature-name}
実例:新機能追加の流れ
# 例:通知機能の追加
/kiro:spec-init "メンバーへのプッシュ通知機能"
/kiro:spec-requirements notification-feature
/kiro:spec-design notification-feature -y
/kiro:spec-tasks notification-feature -y
/kiro:spec-impl notification-feature 1-3
Gitワークフロー
-
ブランチ作成:
git checkout -b feature/your-feature-name -
開発とコミット:
git add . git commit -m "feat: 機能の説明" -
プッシュ:
git push -u origin feature/your-feature-name -
プルリクエスト作成:
- GitHubでPRを作成
- レビューを依頼
- CI/CDが通ることを確認
コミットメッセージ規約
Conventional Commitsに準拠:
feat: 新機能の追加fix: バグ修正docs: ドキュメント更新style: コードフォーマット変更refactor: リファクタリングtest: テスト追加・修正chore: ビルドプロセス・ツール変更
コーディング規約
TypeScript
- 型安全性:
any型は使用禁止、適切な型定義を使用 - strict mode: TypeScript strict modeを有効化
- 命名規則:
- ファイル名: PascalCase(コンポーネント)、camelCase(ユーティリティ)
- 関数/変数: camelCase
- 型/インターフェース: PascalCase
- 定数: UPPER_SNAKE_CASE
React / Next.js
- Server Components優先: デフォルトでServer Componentsを使用
- Client Components:
'use client'が必要な場合のみ使用 - コンポーネント設計: 単一責任の原則に従う
- Hooks: カスタムフックは
useプレフィックスを付ける
Clean Architectureルール
-
依存性の方向:
- Domain → (依存なし)
- Application → Domain
- Infrastructure → Application, Domain
- Presentation → Application, Domain
-
レイヤー間通信:
- Use Caseを通じてビジネスロジックを実行
- Repositoryインターフェース(ports)を定義し、実装(Infrastructure)を注入
-
データフロー:
// NG: Presentationから直接Repository実装を参照 import { SupabaseMemberRepository } from '@/infrastructure/repositories/SupabaseMemberRepository'; // OK: DIコンテナ経由でインターフェースを取得 import { container } from '@/infrastructure/di/setup'; import { REPOSITORY_KEYS } from '@/infrastructure/di/keys'; const repository = container.resolve<IMemberRepository>(REPOSITORY_KEYS.MEMBER);
コードレビューチェックリスト
- 型安全性が保たれているか(
anyを使っていないか) - Clean Architectureの依存性ルールに違反していないか
- テストが追加されているか
- ESLintエラーがないか
- コミットメッセージが規約に従っているか
よくある問題とトラブルシューティング
1. npm installでエラーが出る
原因: Node.jsのバージョンが古い
解決方法:
# Node.jsバージョン確認
node -v
# nvmでNode.js 18+をインストール
nvm install 18
nvm use 18
2. 環境変数が読み込まれない
原因: .envファイルが正しく設定されていない
解決方法:
.envファイルがプロジェクトルートに存在するか確認- サーバーを再起動(
npm run dev) - ブラウザのキャッシュをクリア
3. Supabaseへの接続エラー
原因: Supabase認証情報が間違っている、またはマイグレーションが未実行
解決方法:
# 環境変数を確認
echo $NEXT_PUBLIC_SUPABASE_URL
echo $NEXT_PUBLIC_SUPABASE_ANON_KEY
# Supabaseダッシュボードでマイグレーションが実行されているか確認
# SQL Editorでテーブルの存在を確認
SELECT * FROM members LIMIT 1;
4. 型エラーが出る
原因: 型定義が古い、または間違った型を使用している
解決方法:
# 型定義を再生成(Supabaseの場合)
npx supabase gen types typescript --project-id YOUR_PROJECT_ID > types/database.types.ts
# TypeScriptキャッシュをクリア
rm -rf .next
npm run build
5. ZITADELログインエラー
原因: ZITADEL設定が間違っている
解決方法:
ZITADEL_ISSUERとZITADEL_CLIENT_IDが正しいか確認- ZITADELダッシュボードでリダイレクトURIが
http://localhost:3000/api/auth/callback/zitadelに設定されているか確認
6. Clean Architectureの依存性エラー
原因: 誤った方向の依存性
解決方法:
- Domainレイヤーで外部ライブラリをインポートしていないか確認
- Presentationレイヤーから直接Infrastructure実装をインポートしていないか確認
- Use Caseを通じてビジネスロジックを実行しているか確認
参考資料
プロジェクト内ドキュメント
- README.md: プロジェクト概要
- docs/ARCHITECTURE.md: Clean Architecture詳細設計
- CLAUDE.md: AI開発支援の指示
- .kiro/steering/: プロジェクトガイドライン
技術スタック公式ドキュメント
- Next.js Documentation
- React Documentation
- TypeScript Handbook
- Supabase Documentation
- Tailwind CSS Documentation
- ZITADEL Documentation
アーキテクチャ・設計パターン
学習リソース
サポート
質問や問題がある場合は、以下の方法でサポートを受けられます:
- GitHub Issues: バグ報告や機能リクエスト
- プルリクエストレビュー: コードレビューで質問
- Tech.C Venture内部チャット: プロジェクトメンバーに直接質問
- プロジェクトリード: 木戸(認証基盤担当)
開発を楽しんでください! 🎉
何か困ったことがあれば、遠慮なくチームメンバーに質問してください。
Clean Architecture 設計ドキュメント
アーキテクチャ概要
Portal.CはClean Architectureパターンを採用し、以下の4層構造で設計されています。
┌─────────────────────────────────────────────┐
│ Presentation Layer │
│ (app/, components/ - Next.js App Router) │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Application Layer │
│ (use-cases/, ports/, dtos/, mappers/) │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Infrastructure Layer │
│ (repositories/, database/, auth/, di/) │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Domain Layer │
│ (entities/, value-objects/) │
└─────────────────────────────────────────────┘
レイヤー構成
1. Domain Layer (src/domain/)
責務: ビジネスロジックとエンティティ定義 依存: なし(外部ライブラリ・フレームワーク不使用)
- entities/: Member, Event, Timetable
- value-objects/: Email, StudentId, EventCapacity, CurrentStatus
特徴:
- イミュータブル設計
- バリデーションロジック内包
- 純粋なTypeScript(フレームワーク非依存)
2. Application Layer (src/application/)
責務: ユースケースとアプリケーションロジック 依存: Domain Layer のみ
- use-cases/: GetMemberProfile, RegisterForEvent等
- ports/: IMemberRepository, IEventRepository等(インターフェース定義)
- dtos/: MemberDTO, EventDTO等(データ転送オブジェクト)
- mappers/: Entity ↔ DTO変換
特徴:
- 依存性逆転の原則(ポートインターフェース定義)
- Result型によるエラーハンドリング
- トランザクション境界の定義
3. Infrastructure Layer (src/infrastructure/)
責務: 外部サービスとの統合 依存: Application Layer, Domain Layer
- repositories/: SupabaseMemberRepository等(ポート実装)
- database/: Supabaseクライアント設定
- di/: 依存性注入コンテナ
特徴:
- リポジトリパターン
- データマッパー(DB型 ↔ ドメインエンティティ)
- PostgreSQL関数によるトランザクション処理
4. Presentation Layer (app/, components/)
責務: UI表示とユーザーインタラクション 依存: Application Layer, Domain Layer
- app/: Next.js App Router(Server Components)
- components/: Reactコンポーネント(Client Components)
特徴:
- Server Components: データ取得、ユースケース呼び出し
- Client Components: インタラクティブUI
- Server Actions: フォーム送信等
依存性ルール
Domain ← Application ← Infrastructure
↑ ↑
└────── Presentation ────┘
原則: 内側の層は外側の層に依存しない
依存性注入(DI)
軽量DIコンテナを使用:
import { container } from '@/infrastructure/di/setup';
import { REPOSITORY_KEYS } from '@/infrastructure/di/keys';
// リポジトリの解決
const memberRepository = container.resolve<IMemberRepository>(
REPOSITORY_KEYS.MEMBER
);
登録: モジュールファクトリーパターン
memberModule: メンバー関連の依存性eventModule: イベント関連の依存性timetableModule: 時間割関連の依存性
データフロー
Server Component → Repository
// 1. Server Componentでデータ取得
async function getMembers() {
const repository = container.resolve<IMemberRepository>(REPOSITORY_KEYS.MEMBER);
const result = await repository.findAll();
// 2. Entity → DTO変換
return MemberMapper.toDTOList(result.value);
}
// 3. Client Componentに渡す
<MemberList members={members} />
ユースケース実行
// 1. ユースケース取得
const useCase = new RegisterForEventUseCase(eventRepository);
// 2. 実行
const result = await useCase.execute(eventId, memberId);
// 3. Result型でエラーハンドリング
if (!result.success) {
console.error(result.error);
}
トランザクション処理
Supabase(PostgreSQL)の関数を使用:
CREATE FUNCTION register_for_event(p_event_id UUID, p_member_id UUID)
RETURNS void AS $$
BEGIN
-- 定員チェック + 参加登録を原子的に実行
...
END;
$$ LANGUAGE plpgsql;
テスト戦略
- Domain Layer: ユニットテスト(外部依存なし)
- Application Layer: ユニットテスト(モックリポジトリ)
- Infrastructure Layer: 統合テスト(Supabase接続)
- Presentation Layer: E2Eテスト(Playwright/Cypress)
ディレクトリ構造
Portal.C/
├── src/
│ ├── domain/ # ドメイン層
│ │ ├── entities/
│ │ └── value-objects/
│ ├── application/ # アプリケーション層
│ │ ├── use-cases/
│ │ ├── ports/
│ │ ├── dtos/
│ │ └── mappers/
│ └── infrastructure/ # インフラストラクチャ層
│ ├── repositories/
│ ├── database/
│ └── di/
├── app/ # プレゼンテーション層(Server Components)
└── components/ # プレゼンテーション層(Client Components)
パスエイリアス
{
"@/domain/*": ["./src/domain/*"],
"@/application/*": ["./src/application/*"],
"@/infrastructure/*": ["./src/infrastructure/*"]
}
開発ワークフロー
-
新機能追加時:
- Domain Entityを定義
- Application Use Caseを実装
- Infrastructure Repositoryを実装
- DI登録
- Presentation統合
-
変更時:
- 影響範囲を層で限定
- 依存性ルールを守る
- テストで担保
参考資料
- Clean Architecture (Robert C. Martin)
- Hexagonal Architecture (Ports & Adapters)
- Domain-Driven Design
マイグレーション計画
AI-DLC and Spec-Driven Development
Kiro-style Spec Driven Development implementation on AI-DLC (AI Development Life Cycle)
Project Memory
Project memory keeps persistent guidance (steering, specs notes, component docs) so Codex honors your standards each run. Treat it as the long-lived source of truth for patterns, conventions, and decisions.
- Use
.kiro/steering/for project-wide policies: architecture principles, naming schemes, security constraints, tech stack decisions, api standards, etc. - Use local
AGENTS.mdfiles for feature or library context (e.g.src/lib/payments/AGENTS.md): describe domain assumptions, API contracts, or testing conventions specific to that folder. Codex auto-loads these when working in the matching path. - Specs notes stay with each spec (under
.kiro/specs/) to guide specification-level workflows.
Project Context
Paths
- Steering:
.kiro/steering/ - Specs:
.kiro/specs/
Steering vs Specification
Steering (.kiro/steering/) - Guide AI with project-wide rules and context
Specs (.kiro/specs/) - Formalize development process for individual features
Active Specifications
- Check
.kiro/specs/for active specifications - Use
/prompts:kiro-spec-status [feature-name]to check progress
Development Guidelines
- Think in English, generate responses in English. All Markdown content written to project files (e.g., requirements.md, design.md, tasks.md, research.md, validation reports) MUST be written in the target language configured for this specification (see spec.json.language).
Minimal Workflow
- Phase 0 (optional):
/prompts:kiro-steering,/prompts:kiro-steering-custom - Phase 1 (Specification):
/prompts:kiro-spec-init "description"/prompts:kiro-spec-requirements {feature}/prompts:kiro-validate-gap {feature}(optional: for existing codebase)/prompts:kiro-spec-design {feature} [-y]/prompts:kiro-validate-design {feature}(optional: design review)/prompts:kiro-spec-tasks {feature} [-y]
- Phase 2 (Implementation):
/prompts:kiro-spec-impl {feature} [tasks]/prompts:kiro-validate-impl {feature}(optional: after implementation)
- Progress check:
/prompts:kiro-spec-status {feature}(use anytime)
Development Rules
- 3-phase approval workflow: Requirements → Design → Tasks → Implementation
- Human review required each phase; use
-yonly for intentional fast-track - Keep steering current and verify alignment with
/prompts:kiro-spec-status - Follow the user’s instructions precisely, and within that scope act autonomously: gather the necessary context and complete the requested work end-to-end in this run, asking questions only when essential information is missing or the instructions are critically ambiguous.
Steering Configuration
- Load entire
.kiro/steering/as project memory - Default files:
product.md,tech.md,structure.md - Custom files are supported (managed via
/prompts:kiro-steering-custom)
Steering
Steeringは、プロジェクト全体のガイドラインとルールを定義します。AI開発支援において、これらのガイドラインがプロジェクトの一貫性を保つための基盤となります。
ファイル構成
Steeringの役割
Steeringファイルは、以下の目的で使用されます:
- AI開発支援の指針: Claude CodeやCodexなどのAI開発ツールが、プロジェクトの標準に沿った提案を行うための参照情報
- 開発者のオンボーディング: 新規メンバーがプロジェクトの方針を理解するための資料
- 一貫性の維持: プロジェクト全体で統一された設計思想を保つためのガイドライン
更新方法
Steeringファイルは、プロジェクトの成長に伴って更新されます:
# Steeringファイルの更新
/kiro:steering
# カスタムSteeringファイルの作成
/kiro:steering-custom
詳細はルートディレクトリのCLAUDE.mdやAGENTS.mdを参照してください。
Product Overview
Portal.C is a member and event management web application for Tech.C Venture, developed as part of the Giiku Project Vol.16. It serves as Tech.C Venture’s first foundational system, providing event bulletin board and participant management capabilities.
Core Capabilities
- Member Profile Management: Comprehensive member information including automatic grade calculation from enrollment year, retention flags, skill/interest tags, and time-limited status updates
- Event Management: Event listing, registration, participation tracking, and capacity management
- Timetable System: Grade and department-based filtering for member schedules
- Authentication & Authorization: ZITADEL-based authentication with role-based access control (admin roles for administrative functions)
- Administrative Functions: Event creation, participation tracking by ID, and member management
Target Use Cases
- Tech.C Venture members discovering and participating in events
- Administrators creating and managing events
- Members viewing each other’s profiles and timetables for collaboration
- Tracking member participation and engagement metrics
- Sharing current status (24-hour limited, Discord-like status feature)
Value Proposition
Portal.C provides Tech.C Venture with a centralized platform for community engagement, replacing fragmented communication channels with a unified system that tracks member activities, facilitates event participation, and strengthens community bonds through profile discovery and shared schedules.
Focus on patterns and purpose, not exhaustive feature lists
Technology Stack
Architecture
Currently: Standard Next.js application structure with direct database access from UI components. Target: Clean Architecture with proper layer separation (Domain, Application, Infrastructure, Presentation).
Core Technologies
- Language: TypeScript 5.6+
- Framework: Next.js 15 (App Router)
- Runtime: Node.js 18+
- Database: Supabase (PostgreSQL)
- Authentication: ZITADEL via NextAuth.js 4.24
- Styling: Tailwind CSS 3.4
- UI Components: @openameba/spindle-ui 3.1.4
Key Libraries
- @supabase/ssr: Server-side rendering support for Supabase
- @supabase/supabase-js: Supabase client library
- next-auth: Authentication for Next.js
- date-fns: Date manipulation utilities
- matter-js: Physics engine for hero animations
- clsx: Utility for constructing className strings
Development Standards
Type Safety
- TypeScript strict mode enabled
- No
anytypes - use proper type definitions - Database types generated from Supabase schema
Code Quality
- ESLint with Next.js configuration
- Consistent file naming and structure
- Component-based architecture
Testing
- Testing infrastructure to be established during clean architecture migration
Development Environment
Required Tools
- Node.js 18+
- npm or yarn
- Supabase CLI (for type generation)
- Git
Common Commands
# Dev: npm run dev
# Build: npm run build
# Start: npm start
# Lint: npm run lint
# Type generation: npx supabase gen types typescript --project-id YOUR_PROJECT_ID > types/database.types.ts
Key Technical Decisions
- Next.js 15 App Router: Modern React architecture with server components
- Supabase: Managed PostgreSQL with built-in auth, real-time, and storage capabilities
- ZITADEL for Auth: Enterprise-grade authentication separate from application logic
- Spindle UI: Consistent design system for UI components
- Clean Architecture Migration: Planned refactoring to separate concerns and improve testability
Infrastructure
- Hosting: Vercel (optimized for Next.js)
- Database: Supabase-managed PostgreSQL
- Auth Provider: ZITADEL instance
Document standards and patterns, not every dependency
Project Structure
Organization Philosophy
Current: Standard Next.js structure with pages, components, and lib utilities.
Target (Clean Architecture): Layer-based organization with clear dependency rules:
- Domain Layer: Business logic and entities (no external dependencies)
- Application Layer: Use cases and application services
- Infrastructure Layer: External services (database, auth, APIs)
- Presentation Layer: UI components and pages (Next.js App Router)
Directory Patterns
Current Structure
Pages and Routing
Location: /app/
Purpose: Next.js App Router pages and API routes
Example: /app/events/page.tsx, /app/api/auth/[...nextauth]/route.ts
UI Components
Location: /components/
Purpose: Reusable React components
Example: /components/layout/Navigation.tsx, /components/MatterHero.tsx
Utilities and Clients
Location: /lib/
Purpose: Utility functions and external service clients
Example: /lib/supabase/client.ts, /lib/auth.ts
Type Definitions
Location: /types/
Purpose: TypeScript type definitions
Example: /types/database.types.ts, /types/index.ts
Target Structure (Clean Architecture)
Domain Layer
Location: /src/domain/
Purpose: Core business entities, value objects, and business rules. No framework dependencies.
Example: /src/domain/entities/Member.ts, /src/domain/value-objects/Email.ts
Application Layer
Location: /src/application/
Purpose: Use cases, DTOs, and interfaces for external dependencies
Example: /src/application/use-cases/RegisterForEvent.ts, /src/application/ports/MemberRepository.ts
Infrastructure Layer
Location: /src/infrastructure/
Purpose: Implementations of external dependencies (DB, auth, external APIs)
Example: /src/infrastructure/repositories/SupabaseMemberRepository.ts, /src/infrastructure/auth/ZitadelAuthProvider.ts
Presentation Layer
Location: /src/presentation/ (or keep in /app/ and /components/)
Purpose: Next.js pages, components, controllers
Example: /app/events/page.tsx with controller separation
Naming Conventions
- Files:
- Components: PascalCase (e.g.,
MemberCard.tsx) - Utilities: camelCase (e.g.,
formatDate.ts) - Pages: kebab-case or lowercase (Next.js convention)
- Components: PascalCase (e.g.,
- Components: PascalCase
- Functions: camelCase
- Types/Interfaces: PascalCase
Import Organization
// External dependencies
import { createBrowserClient } from "@supabase/ssr";
// Internal absolute imports (current)
import { MatterHero } from "@/components/MatterHero";
import type { Event } from "@/types";
// Target (Clean Architecture)
import { Member } from "@/domain/entities/Member";
import { RegisterForEvent } from "@/application/use-cases/RegisterForEvent";
import { SupabaseMemberRepository } from "@/infrastructure/repositories/SupabaseMemberRepository";
Path Aliases:
@/: Maps to project root (configured in tsconfig.json)
Code Organization Principles
Current State
- UI components directly import and use Supabase clients
- Business logic mixed with presentation logic
- No clear separation of concerns
Target State (Clean Architecture)
-
Dependency Rule: Inner layers don’t depend on outer layers
- Domain → (no dependencies)
- Application → Domain
- Infrastructure → Application, Domain
- Presentation → Application, Domain
-
Dependency Inversion: Application layer defines interfaces, infrastructure implements them
-
Use Case Driven: Each feature is a use case in the application layer
-
Testability: Business logic can be tested without UI or database
Document patterns, not file trees. New files following patterns shouldn’t require updates
Specs
Specsは、個別の機能や変更に対する仕様書を管理します。各機能の要件定義、設計、タスク、実装状況を追跡します。
アクティブな仕様
- Clean Architecture Refactor - クリーンアーキテクチャへのリファクタリング
Spec-Driven Development (SDD)
Portal.CではKiro-style Spec-Driven Developmentを採用しています。これにより、要件定義→設計→実装の流れが明確になり、AI支援開発が効率化されます。
基本フロー
-
要件定義 (
/kiro:spec-requirements)- 機能の要件を詳細に記述
- EARS形式での要件記述
-
ギャップ分析 (
/kiro:validate-gap) - オプション- 既存コードベースとの整合性確認
-
設計 (
/kiro:spec-design)- アーキテクチャ設計
- 技術選定
- インターフェース定義
-
タスク生成 (
/kiro:spec-tasks)- 実装タスクの分解
- 優先順位付け
-
実装 (
/kiro:spec-impl)- TDD方式での実装
- タスク単位での進捗管理
-
検証 (
/kiro:validate-impl) - オプション- 要件との整合性確認
詳細はルートディレクトリのCLAUDE.mdやAGENTS.mdを参照してください。
新しい仕様の作成
# 新しい機能の仕様初期化
/kiro:spec-init "機能の説明"
# 要件定義
/kiro:spec-requirements {feature-name}
# 設計
/kiro:spec-design {feature-name}
# タスク生成
/kiro:spec-tasks {feature-name}
# 実装
/kiro:spec-impl {feature-name} [task-numbers]
Clean Architecture Refactor
Portal.CをClean Architectureパターンに基づいてリファクタリングするための仕様書です。
概要
既存のコードベースを、保守性と拡張性に優れたClean Architectureパターンに移行します。これにより、ビジネスロジックと外部依存を明確に分離し、テスタビリティを向上させます。
ドキュメント
- Requirements - 要件定義(EARS形式)
- Design - アーキテクチャ設計の詳細
- Tasks - 実装タスクの一覧
- Research - 技術調査とアーキテクチャ分析
- Gap Analysis - 既存コードとのギャップ分析
進捗確認
/kiro:spec-status clean-architecture-refactor
アーキテクチャ構造
┌─────────────────────────────────────────────┐
│ Presentation Layer │
│ (app/, components/ - Next.js App Router) │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Application Layer │
│ (use-cases/, ports/, dtos/, mappers/) │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Infrastructure Layer │
│ (repositories/, database/, auth/, di/) │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Domain Layer │
│ (entities/, value-objects/) │
└─────────────────────────────────────────────┘
依存性ルール
内側の層は外側の層に依存しません:
- Domain Layer: ビジネスロジック、外部依存なし
- Application Layer: ユースケース、Domainのみに依存
- Infrastructure Layer: 外部サービス統合(DB、認証等)
- Presentation Layer: UI、Application/Domainに依存
詳細はDesignを参照してください。
Requirements Document
導入
本ドキュメントは、Portal.CをスタンダードなNext.jsアーキテクチャからClean Architectureへリファクタリングするための要件を定義します。このリファクタリングの目的は、レイヤーの適切な分離により、テスタビリティ、保守性、関心の分離を向上させながら、既存のすべての機能を維持することです。
Portal.Cは、Tech.C Venture向けのメンバー・イベント管理Webアプリケーションであり、Next.js 15、Supabase、ZITADELを使用しています。現在の構造(app/, components/, lib/, types/)から、ドメイン駆動設計の原則に基づいた明確なレイヤー構造(src/domain/, src/application/, src/infrastructure/, src/presentation/)へ移行します。
Requirements
Requirement 1: ディレクトリ構造とレイヤー分離
Objective: 開発者として、Clean Architectureの原則に従った明確なレイヤー構造を持つことで、各レイヤーの責務を理解し、保守性の高いコードベースを実現したい。
Acceptance Criteria
- The Portal.C shall プロジェクトルートに
src/ディレクトリを作成し、すべてのアプリケーションコードを格納する - The Portal.C shall
src/配下にdomain/,application/,infrastructure/,presentation/の4つのレイヤーディレクトリを作成する - The Portal.C shall 各レイヤーディレクトリ内に、機能別のサブディレクトリを配置する(例:domain/entities/, domain/value-objects/, application/use-cases/, application/ports/)
- The Portal.C shall 既存の
app/ディレクトリをNext.js App Router用に保持し、プレゼンテーション層のページルーティングとして使用する - The Portal.C shall 既存の
components/ディレクトリをUIコンポーネント用に保持し、プレゼンテーション層の一部として使用する - The Portal.C shall
lib/およびtypes/ディレクトリから適切なレイヤーへコードを移行する - The Portal.C shall
tsconfig.jsonにパスエイリアスを設定し、各レイヤーへの絶対パスインポートを可能にする(例:@/domain/, @/application/, @/infrastructure/, @/presentation/)
Requirement 2: ドメインレイヤーの設計
Objective: 開発者として、外部依存を持たないビジネスロジックとエンティティを明確に定義することで、ビジネスルールの純粋性を保ち、テストしやすいコアロジックを実現したい。
Acceptance Criteria
- The Portal.C shall
src/domain/entities/にビジネスエンティティを定義する(Member, Event, Timetable等) - The Portal.C shall ドメインエンティティは外部ライブラリやフレームワークに依存しないプレーンなTypeScriptクラスまたはインターフェースとして実装する
- The Portal.C shall
src/domain/value-objects/に値オブジェクトを定義する(Email, StudentId, EventCapacity等) - The Portal.C shall 値オブジェクトはイミュータブルであり、バリデーションロジックを内包する
- The Portal.C shall
src/domain/services/にドメインサービスを配置し、複数のエンティティにまたがるビジネスロジックを実装する - The Portal.C shall ドメインレイヤーはアプリケーション層、インフラストラクチャ層、プレゼンテーション層のいずれにも依存しない
- When ドメインエンティティを作成または変更する際、the Portal.C shall ビジネスルールのバリデーションを実行し、不正な状態を防ぐ
Requirement 3: アプリケーションレイヤーの設計
Objective: 開発者として、ユースケースごとにアプリケーションロジックを整理し、ドメインとインフラストラクチャを橋渡しすることで、機能の実装と変更を容易にしたい。
Acceptance Criteria
- The Portal.C shall
src/application/use-cases/にユースケースクラスを配置する(RegisterForEvent, CreateMember, UpdateProfile等) - The Portal.C shall 各ユースケースは単一の責務を持ち、
execute()メソッドまたは同等のエントリーポイントを提供する - The Portal.C shall
src/application/ports/にリポジトリインターフェースとサービスインターフェースを定義する(IMemberRepository, IEventRepository, IAuthService等) - The Portal.C shall
src/application/dtos/にデータ転送オブジェクトを配置し、レイヤー間のデータ受け渡しに使用する - The Portal.C shall アプリケーション層はドメイン層のみに依存し、インフラストラクチャ層やプレゼンテーション層には依存しない
- When ユースケースを実行する際、the Portal.C shall ポートインターフェースを通じてインフラストラクチャ層の実装を呼び出す(依存性逆転の原則)
- If ユースケース実行中にビジネスルール違反が発生した場合、then the Portal.C shall 適切なドメインエラーまたはアプリケーションエラーをスローする
- The Portal.C shall 各ユースケースにトランザクション境界を定義し、データ整合性を保証する
Requirement 4: インフラストラクチャレイヤーの設計
Objective: 開発者として、外部サービス(データベース、認証、API)との統合を抽象化し、技術的な実装詳細をビジネスロジックから分離したい。
Acceptance Criteria
- The Portal.C shall
src/infrastructure/repositories/にリポジトリの具体的実装を配置する(SupabaseMemberRepository, SupabaseEventRepository等) - The Portal.C shall リポジトリ実装はアプリケーション層で定義されたポートインターフェースを実装する
- The Portal.C shall
src/infrastructure/database/にSupabaseクライアント設定とデータベース接続ロジックを配置する - The Portal.C shall
src/infrastructure/auth/にZITADEL認証プロバイダーとNextAuth設定を配置する - The Portal.C shall インフラストラクチャ層の実装はドメインエンティティとDTOの変換ロジックを含む
- When リポジトリメソッドを呼び出す際、the Portal.C shall データベース固有の型(Supabase型)をドメインエンティティに変換する
- If データベースクエリがエラーを返した場合、then the Portal.C shall アプリケーション層で処理可能な標準化されたエラーに変換する
- The Portal.C shall
src/infrastructure/external/に外部API連携ロジックを配置する(必要に応じて) - The Portal.C shall インフラストラクチャ層の各実装は、依存性注入によりアプリケーション層に提供される
Requirement 5: プレゼンテーションレイヤーの設計
Objective: 開発者として、UIロジックとビジネスロジックを分離し、Next.jsのApp Router機能を活用しながら、Clean Architectureの原則に従った実装を実現したい。
Acceptance Criteria
- The Portal.C shall
app/ディレクトリをNext.js App Routerのページルーティング用に保持する - The Portal.C shall
components/ディレクトリをプレゼンテーション層のUIコンポーネント用に保持する - The Portal.C shall ページコンポーネント(app/*/page.tsx)はサーバーコンポーネントとして実装し、ユースケースを直接呼び出す
- The Portal.C shall クライアントコンポーネントは
use clientディレクティブを使用し、インタラクティブなUIロジックのみを含む - The Portal.C shall プレゼンテーション層のコンポーネントはユースケースまたはDTOを通じてアプリケーション層と通信する
- The Portal.C shall UIコンポーネントは直接データベースクライアント(Supabase)や認証クライアント(ZITADEL)を呼び出さない
- When フォーム送信やユーザーアクションが発生した際、the Portal.C shall 対応するユースケースを呼び出し、ビジネスロジックを実行する
- If ユースケース実行がエラーを返した場合、then the Portal.C shall ユーザーに適切なエラーメッセージを表示する
- The Portal.C shall Server ActionsをNext.js 15の推奨パターンに従って実装し、ユースケースへの橋渡しを行う
Requirement 6: 依存性ルールの遵守
Objective: 開発者として、Clean Architectureの依存性ルール(内側のレイヤーは外側のレイヤーに依存しない)を厳格に守ることで、アーキテクチャの整合性と変更容易性を維持したい。
Acceptance Criteria
- The Portal.C shall ドメイン層は他のいずれのレイヤー(アプリケーション、インフラストラクチャ、プレゼンテーション)にも依存しない
- The Portal.C shall アプリケーション層はドメイン層のみに依存し、インフラストラクチャ層やプレゼンテーション層には依存しない
- The Portal.C shall インフラストラクチャ層はアプリケーション層とドメイン層に依存可能だが、プレゼンテーション層には依存しない
- The Portal.C shall プレゼンテーション層はアプリケーション層とドメイン層に依存可能だが、インフラストラクチャ層の具体的実装には依存しない
- When アプリケーション層が外部サービスとの統合を必要とする際、the Portal.C shall ポートインターフェースを定義し、インフラストラクチャ層がそれを実装する(依存性逆転の原則)
- The Portal.C shall TypeScriptのコンパイラオプションやリンターを設定し、依存性ルール違反を検出する
- If レイヤー間の不正な依存が検出された場合、then the Portal.C shall ビルドまたはリント時にエラーを報告する
Requirement 7: 既存機能の保持
Objective: ユーザーおよび管理者として、リファクタリング後も既存のすべての機能が正常に動作し、ユーザー体験が損なわれないことを確認したい。
Acceptance Criteria
- The Portal.C shall メンバープロフィール管理機能(プロフィール表示、編集、入学年度からの学年自動計算、在籍フラグ、スキル/興味タグ、24時間限定ステータス更新)をリファクタリング後も提供する
- The Portal.C shall イベント管理機能(イベント一覧、登録、参加追跡、定員管理)をリファクタリング後も提供する
- The Portal.C shall タイムテーブルシステム機能(学年・学部フィルタリング、メンバースケジュール表示)をリファクタリング後も提供する
- The Portal.C shall ZITADEL認証とロールベースアクセス制御(管理者ロール)をリファクタリング後も提供する
- The Portal.C shall 管理機能(イベント作成、ID別参加追跡、メンバー管理)をリファクタリング後も提供する
- The Portal.C shall Spindle UIコンポーネントライブラリを使用したUIデザインをリファクタリング後も維持する
- When リファクタリング後のアプリケーションを起動した際、the Portal.C shall すべての既存ページとルートが正常にアクセス可能である
- When 既存のユーザーフローを実行した際、the Portal.C shall リファクタリング前と同一の結果と動作を提供する
- If リファクタリング中に機能の動作変更が必要な場合、then the Portal.C shall 事前に関係者に通知し、承認を得る
Requirement 8: テスタビリティの向上
Objective: 開発者として、ビジネスロジックとインフラストラクチャロジックを独立してテストできる環境を構築し、コードの品質と信頼性を向上させたい。
Acceptance Criteria
- The Portal.C shall ドメイン層のエンティティと値オブジェクトを外部依存なしでユニットテスト可能にする
- The Portal.C shall アプリケーション層のユースケースをモックリポジトリを使用してユニットテスト可能にする
- The Portal.C shall インフラストラクチャ層のリポジトリ実装をインテグレーションテスト可能にする
- The Portal.C shall
src/配下の各レイヤーに対応する__tests__/ディレクトリまたは.test.tsファイルを配置する - When ユースケースのテストを実行する際、the Portal.C shall リポジトリインターフェースのモック実装を注入し、データベースアクセスなしでテストを実行できる
- The Portal.C shall テストフレームワーク(Jest, Vitest等)とテストランナーを設定し、自動テスト実行環境を構築する
- The Portal.C shall テストカバレッジツールを導入し、コードカバレッジを測定可能にする
- When ドメインロジックに変更を加えた際、the Portal.C shall 既存のユニットテストが自動的に検証し、リグレッションを防ぐ
Requirement 9: マイグレーション戦略と段階的移行
Objective: 開発チームとして、リファクタリングを安全かつ段階的に実施し、開発速度を維持しながらリスクを最小化したい。
Acceptance Criteria
- The Portal.C shall リファクタリングを機能単位またはドメイン単位で段階的に実施する
- The Portal.C shall 新しいレイヤー構造と既存の構造が一時的に共存可能なマイグレーション計画を策定する
- When 新しいレイヤー構造への移行を開始する際、the Portal.C shall まず小規模な機能(例:メンバープロフィール表示)をパイロットとして移行する
- The Portal.C shall 各マイグレーション段階で既存機能のリグレッションテストを実施し、動作を検証する
- The Portal.C shall 既存のインポートパスを新しいレイヤー構造に段階的に更新するためのツールまたはスクリプトを用意する
- If マイグレーション中に重大な問題が発見された場合、then the Portal.C shall ロールバック可能な状態を維持する(Gitブランチ戦略)
- The Portal.C shall 各マイグレーション段階の完了基準(定義済みテストの通過、コードレビュー承認等)を明確にする
- When すべての機能が新しいレイヤー構造に移行完了した際、the Portal.C shall 古い構造のコードを削除し、クリーンな状態にする
Requirement 10: ドキュメントと開発者体験
Objective: 開発チームとして、新しいアーキテクチャの理解を促進し、開発者が効率的に作業できる環境を提供したい。
Acceptance Criteria
- The Portal.C shall Clean Architectureの各レイヤーの責務と依存性ルールを説明するドキュメントを提供する
- The Portal.C shall 新しいユースケースを追加する際の開発ガイドラインとコード例を提供する
- The Portal.C shall リポジトリインターフェースと実装の追加方法を説明するドキュメントを提供する
- The Portal.C shall ディレクトリ構造とファイル配置規則を説明するREADMEを各レイヤーディレクトリに配置する
- When 新しい開発者がプロジェクトに参加する際、the Portal.C shall オンボーディングドキュメントを通じてアーキテクチャの概要を理解できる
- The Portal.C shall コード生成スクリプトまたはテンプレートを提供し、新しいエンティティ、ユースケース、リポジトリの作成を支援する
- The Portal.C shall 既存のSteering Context(
.kiro/steering/)を更新し、新しいアーキテクチャパターンを反映する
技術設計書: Clean Architecture リファクタリング
概要
本設計は、Portal.Cを標準的なNext.jsアーキテクチャからClean Architectureへリファクタリングするための技術的アプローチを定義します。このリファクタリングにより、レイヤーの適切な分離、テスタビリティの向上、保守性の改善を実現しながら、既存のすべての機能を維持します。
Portal.Cは、Tech.C Venture向けのメンバー・イベント管理Webアプリケーションであり、現在Next.js 15、Supabase、ZITADELを使用しています。現在の構造(app/, components/, lib/, types/)から、ドメイン駆動設計の原則に基づいた明確なレイヤー構造(src/domain/, src/application/, src/infrastructure/, src/presentation/)へ移行します。
ユーザー: 開発チーム、Tech.C Ventureのメンバーと管理者
影響: 既存のコードベース構造を根本的に変更しますが、ユーザー向け機能は完全に維持されます。開発者体験は、明確なレイヤー分離とテスト可能性の向上により大幅に改善されます。
目標
- レイヤー分離の実現: Domain、Application、Infrastructure、Presentationの4層を明確に分離し、Clean Architectureの依存性ルールを遵守
- テスタビリティの向上: ビジネスロジックとインフラストラクチャロジックを独立してテスト可能にする環境を構築
- 既存機能の保持: リファクタリング後もすべての既存機能(メンバー管理、イベント管理、タイムテーブル、認証)が正常に動作
- 段階的移行: 7段階の移行計画により、リスクを最小化しながら安全にリファクタリングを実施
- 開発者体験の改善: 明確なアーキテクチャパターンとドキュメントにより、新しい開発者のオンボーディングと機能追加を容易化
非目標
- 機能追加: 本リファクタリングは既存機能の再構築のみを対象とし、新機能追加は含まない
- UIデザインの変更: Spindle UIコンポーネントとデザインシステムはそのまま維持
- データベーススキーマの変更: 既存のSupabaseスキーマは変更せず、そのまま活用
- 認証システムの変更: ZITADELとNextAuth.jsの統合はそのまま維持
- パフォーマンス最適化: アーキテクチャ変更に伴う自然な改善は期待されるが、積極的な最適化は別途実施
アーキテクチャ
既存アーキテクチャ分析
現在のパターン
- 標準的なNext.js構造: app/ディレクトリによるファイルベースルーティング
- 直接的なデータアクセス: UIコンポーネントから直接Supabaseクライアントを呼び出す想定(現在はモックデータ)
- 型定義とビジネスロジックの混在: types/index.tsに
calculateGrade(),isStatusValid()などのビジネスロジックが含まれる - レイヤー分離なし: プレゼンテーション、ビジネスロジック、データアクセスが明確に分離されていない
再利用可能な資産
- ✅ データベーススキーマ完全構築済み: members, tags, events, timetablesテーブル、RLS設定済み
- ✅ 認証基盤設定完了: ZITADEL OIDC統合、NextAuth.js設定、ロールベースアクセス制御
- ✅ Supabaseクライアント: 4種類のクライアント(browser, server, admin, middleware)
- ✅ 型定義システム: Supabase自動生成型、アプリケーション型
- ✅ UIコンポーネント: Spindle UI統合、ページコンポーネント実装済み
技術的制約
- Next.js 15 App Routerの使用が必須
- Supabaseをデータベースとして使用
- ZITADELを認証基盤として使用
- TypeScript strict mode有効
アーキテクチャパターンと境界マップ
選択パターン: Clean Architecture(4層モデル)
根拠:
- ドメインロジックとインフラストラクチャの明確な分離
- 依存性逆転の原則により、ビジネスロジックが外部技術に依存しない
- テスタビリティと保守性の大幅な向上
- Next.js 15 App Routerとの互換性が高い(調査により実証済み)
graph TB
subgraph Presentation["プレゼンテーション層 (Presentation)"]
Pages["Pages<br/>app/"]
Components["UI Components<br/>components/"]
ServerActions["Server Actions"]
end
subgraph Application["アプリケーション層 (Application)"]
UseCases["Use Cases"]
Ports["Ports<br/>(Interfaces)"]
DTOs["DTOs"]
end
subgraph Domain["ドメイン層 (Domain)"]
Entities["Entities"]
ValueObjects["Value Objects"]
DomainServices["Domain Services"]
end
subgraph Infrastructure["インフラストラクチャ層 (Infrastructure)"]
Repositories["Repositories<br/>(Implementations)"]
Database["Database<br/>(Supabase)"]
Auth["Auth<br/>(ZITADEL)"]
end
Pages --> ServerActions
ServerActions --> UseCases
Components --> ServerActions
UseCases --> Ports
UseCases --> DTOs
UseCases --> Entities
Repositories -.implements.-> Ports
Repositories --> Database
Repositories --> Auth
Entities --> ValueObjects
DomainServices --> Entities
ドメイン/機能境界:
- Member管理: プロフィール、学年計算、ステータス管理、スキル/興味タグ
- Event管理: イベント作成、参加登録、定員管理、参加追跡
- Timetable管理: 時間割表示、学年/学部フィルタリング
- 認証・認可: ZITADEL統合、ロールベースアクセス制御
既存パターンの保持:
- Next.js 15 App Routerのファイルベースルーティング(app/ディレクトリ)
- Spindle UIコンポーネントライブラリ
- Tailwind CSSスタイリング
- Supabaseデータベーススキーマ
新規コンポーネントの根拠:
- Domain層: 外部依存のないビジネスロジックのカプセル化
- Application層: ユースケース駆動の開発と依存性逆転の実現
- Infrastructure層: 外部サービスとの統合を抽象化し、テスト可能性を向上
- Presentation層の分離: UIロジックとビジネスロジックの明確な分離
Steering準拠:
- TypeScript strict mode有効(Type Safety)
- Clean Architectureへの移行(tech.mdで明記)
- 既存の技術スタック保持(Next.js 15, Supabase, ZITADEL)
- ドメイン駆動設計の原則に基づいたレイヤー構造(structure.md)
技術スタック
| レイヤー | 選択/バージョン | 本機能での役割 | 備考 |
|---|---|---|---|
| Language | TypeScript 5.6+ | 全レイヤーで型安全性を確保 | strict mode有効、any型禁止 |
| Framework | Next.js 15 (App Router) | プレゼンテーション層のフレームワーク | Server Components/Client Components、Server Actions |
| Runtime | Node.js 18+ | サーバーサイド実行環境 | Edge Functionsサポート |
| Database | Supabase (PostgreSQL) | データ永続化 | RLS設定済み、型自動生成 |
| ORM/Client | @supabase/supabase-js | インフラストラクチャ層でのデータアクセス | リポジトリパターン実装の基盤 |
| Authentication | ZITADEL via NextAuth.js 4.24 | 認証・認可 | OIDC統合、ロールベース制御 |
| Dependency Injection | 軽量ファクトリーパターン | アプリケーション層とインフラ層の接続 | ioctopus風のインターフェースバインディング |
| Styling | Tailwind CSS 3.4 | UIスタイリング | 既存スタイル保持 |
| UI Components | @openameba/spindle-ui 3.1.4 | UIコンポーネントライブラリ | 既存コンポーネント保持 |
| Testing | Jest または Vitest(段階7で決定) | ユニット/統合テスト | Next.js 15互換性を考慮 |
技術選択の根拠:
- 軽量DIパターン: reflect-metadata不要でNext.js Server Componentsと互換性が高い(調査により実証)
- Supabase継続: トランザクション処理はPostgreSQL関数+RPC経由で実現可能(公式ガイド)
- 既存スタック保持: データベーススキーマ、認証、UIコンポーネントは再利用可能な資産
詳細な調査結果はresearch.mdを参照。
システムフロー
メンバープロフィール取得フロー
sequenceDiagram
participant User as ユーザー
participant Page as Page Component<br/>(Server)
participant Action as Server Action
participant UseCase as GetMemberProfile<br/>UseCase
participant Repo as IMemberRepository<br/>(Port)
participant Impl as SupabaseMember<br/>Repository
participant DB as Supabase DB
User->>Page: ページアクセス
Page->>Action: getMemberProfile(id)
Action->>UseCase: execute(id)
UseCase->>Repo: findById(id)
Repo->>Impl: findById(id)
Impl->>DB: SELECT * FROM members
DB-->>Impl: Row data
Impl->>Impl: mapToEntity(row)
Impl-->>Repo: Member entity
Repo-->>UseCase: Member entity
UseCase->>UseCase: ビジネスルール適用
UseCase-->>Action: MemberDTO
Action-->>Page: MemberDTO
Page->>Page: UIレンダリング
Page-->>User: プロフィール表示
フロー決定事項:
- Server ComponentsがデフォルトでServer Actionsを呼び出す
- UseCaseがビジネスロジックを集約
- リポジトリがDB型→ドメインエンティティへの変換を担当
- DTOでレイヤー間のデータ転送を実施
イベント参加登録フロー(トランザクション)
sequenceDiagram
participant User as ユーザー
participant Client as Client Component
participant Action as Server Action
participant UseCase as RegisterForEvent<br/>UseCase
participant Repo as IEventRepository<br/>(Port)
participant Impl as SupabaseEvent<br/>Repository
participant DB as Supabase<br/>(RPC Function)
User->>Client: 参加ボタンクリック
Client->>Action: registerForEvent(memberId, eventId)
Action->>UseCase: execute({memberId, eventId})
UseCase->>UseCase: ビジネスルール検証<br/>(定員チェック等)
UseCase->>Repo: registerMember(memberId, eventId)
Repo->>Impl: registerMember(memberId, eventId)
Impl->>DB: rpc('register_for_event',<br/>{p_member_id, p_event_id})
Note over DB: トランザクション内:<br/>1. participations INSERT<br/>2. events UPDATE<br/>3. COMMIT
DB-->>Impl: Success/Error
Impl-->>Repo: Result
Repo-->>UseCase: Result
UseCase-->>Action: DTO or Error
Action-->>Client: Response
Client->>Client: UI更新
Client-->>User: 登録完了/エラー表示
フロー決定事項:
- トランザクション処理はPostgreSQL関数をRPC経由で呼び出す(Supabase公式パターン)
- PostgRESTが自動的にrpc()をトランザクションでラップ
- ビジネスルール検証はUseCaseで実施(定員チェック等)
- エラーハンドリングはレイヤー間で標準化されたResult型を使用
要件トレーサビリティ
| 要件 | 概要 | コンポーネント | インターフェース | フロー |
|---|---|---|---|---|
| 1.1 | src/ディレクトリ作成 | ディレクトリ構造 | - | - |
| 1.2 | domain/等4層作成 | Domain, Application, Infrastructure, Presentation | - | - |
| 1.3 | 機能別サブディレクトリ | entities/, use-cases/, repositories/ | - | - |
| 1.4 | app/ディレクトリ保持 | Pages (app/) | - | - |
| 1.5 | components/保持 | UI Components | BaseUIProps | - |
| 1.6 | lib/,types/移行 | 全レイヤーに分散 | - | - |
| 1.7 | tsconfig.jsonパスエイリアス | - | - | - |
| 2.1 | エンティティ定義 | Member, Event, Timetable | Entity interfaces | - |
| 2.2 | 外部依存なし実装 | Domain層全体 | - | - |
| 2.3 | 値オブジェクト | Email, StudentId, EventCapacity | ValueObject interfaces | - |
| 2.4 | イミュータビリティ | 値オブジェクト | - | - |
| 2.5 | ドメインサービス | GradeCalculator(必要時) | DomainService interfaces | - |
| 2.6 | レイヤー依存ルール | 依存性注入メカニズム | - | - |
| 2.7 | バリデーション実行 | Entity constructor/methods | - | - |
| 3.1 | ユースケースクラス | GetMemberProfile, RegisterForEvent等 | IUseCase | プロフィール取得、イベント登録 |
| 3.2 | execute()メソッド | 全ユースケース | IUseCase.execute() | - |
| 3.3 | ポートインターフェース | IMemberRepository, IEventRepository等 | Repository interfaces | - |
| 3.4 | DTO定義 | MemberDTO, EventDTO等 | DTO interfaces | 全フロー |
| 3.5 | Domain層のみ依存 | Application層 | - | - |
| 3.6 | ポート経由呼び出し | ユースケース→リポジトリ | - | 全フロー |
| 3.7 | エラースロー | ユースケース | DomainError, AppError | - |
| 3.8 | トランザクション境界 | ユースケース | - | イベント登録 |
| 4.1 | リポジトリ実装 | SupabaseMemberRepository等 | IMemberRepository等 | 全フロー |
| 4.2 | ポート実装 | 全リポジトリ | - | - |
| 4.3 | Supabaseクライアント | DatabaseClient | - | - |
| 4.4 | ZITADEL認証 | AuthProvider | IAuthService | - |
| 4.5 | 型変換ロジック | データマッパー | - | - |
| 4.6 | DB型→ドメイン変換 | mapToEntity() | - | プロフィール取得 |
| 4.7 | エラー変換 | リポジトリ | - | - |
| 4.8 | 外部API連携 | (該当なし) | - | - |
| 4.9 | 依存性注入 | DIContainer | - | - |
| 5.1 | app/保持 | Pages | - | - |
| 5.2 | components/保持 | UI Components | - | - |
| 5.3 | サーバーコンポーネント | Page components | - | プロフィール取得 |
| 5.4 | クライアントコンポーネント | Interactive UI | - | イベント登録 |
| 5.5 | ユースケース通信 | Server Actions | - | 全フロー |
| 5.6 | 直接呼び出し禁止 | アーキテクチャルール | - | - |
| 5.7 | ユースケース呼び出し | Server Actions | - | 全フロー |
| 5.8 | エラー表示 | Error UI Components | ErrorDTO | 全フロー |
| 5.9 | Server Actions実装 | Server Actions | - | 全フロー |
| 6.1-6.7 | 依存性ルール | 全レイヤー | - | - |
| 7.1-7.9 | 既存機能保持 | 全機能 | - | - |
| 8.1-8.8 | テスタビリティ | テストフレームワーク、モック | - | - |
| 9.1-9.8 | マイグレーション | 7段階計画 | - | - |
| 10.1-10.7 | ドキュメント | READMEs, ガイド | - | - |
コンポーネントとインターフェース
コンポーネント概要
| コンポーネント | ドメイン/レイヤー | 目的 | 要件カバレッジ | 主要依存関係 (優先度) | 契約 |
|---|---|---|---|---|---|
| Member | Domain/Entities | メンバービジネスロジック | 2.1, 2.2, 2.7 | ValueObjects (P0) | State |
| Email, StudentId | Domain/ValueObjects | 値オブジェクト | 2.3, 2.4 | - | State |
| IMemberRepository | Application/Ports | リポジトリインターフェース | 3.3 | Member (P0) | Service |
| GetMemberProfile | Application/UseCases | プロフィール取得ユースケース | 3.1, 3.2, 3.6 | IMemberRepository (P0), Member (P0) | Service |
| RegisterForEvent | Application/UseCases | イベント登録ユースケース | 3.1, 3.2, 3.8 | IEventRepository (P0), Event (P0) | Service |
| MemberDTO | Application/DTOs | データ転送オブジェクト | 3.4 | - | State |
| SupabaseMemberRepository | Infrastructure/Repositories | リポジトリ実装 | 4.1, 4.2, 4.6 | Supabase Client (P0), IMemberRepository (P0) | Service |
| DatabaseClient | Infrastructure/Database | Supabaseクライアント | 4.3 | @supabase/supabase-js (P0) | Service |
| AuthProvider | Infrastructure/Auth | ZITADEL認証プロバイダー | 4.4 | NextAuth.js (P0), ZITADEL (P0) | Service |
| DIContainer | Infrastructure/DI | 依存性注入コンテナ | 4.9 | - | Service |
| MemberProfilePage | Presentation/Pages | メンバープロフィールページ | 5.1, 5.3 | GetMemberProfile (P0), MemberDTO (P0) | - |
| EventRegistrationButton | Presentation/Components | イベント登録ボタン | 5.2, 5.4 | RegisterForEvent (P0) | - |
| Server Actions | Presentation/Actions | Server Actions | 5.5, 5.7, 5.9 | UseCases (P0) | API |
ドメイン層 (Domain Layer)
Member Entity
| フィールド | 詳細 |
|---|---|
| 目的 | メンバーのビジネスロジックとルールをカプセル化 |
| 要件 | 2.1, 2.2, 2.7 |
| オーナー/レビュアー | 開発チーム |
責務と制約
- メンバーの状態管理とバリデーション
- 学年計算ロジック(入学年度から自動計算)
- ステータス有効性チェック(24時間限定)
- 在籍フラグ管理
- ドメイン境界: 単一のメンバーアグリゲート、他のエンティティに依存しない
依存関係
- Outbound: Email (値オブジェクト) — メールアドレス検証 (P0)
- Outbound: StudentId (値オブジェクト) — 学籍番号検証 (P0)
契約: State [x]
State Management
状態モデル:
interface Member {
readonly id: string;
readonly name: string;
readonly email: Email;
readonly studentId: StudentId;
readonly enrollmentYear: number;
readonly isActive: boolean;
readonly status?: {
readonly text: string;
readonly expiresAt: Date;
};
readonly skills: readonly string[];
readonly interests: readonly string[];
readonly createdAt: Date;
readonly updatedAt: Date;
// ビジネスロジックメソッド
calculateGrade(currentYear: number, currentMonth: number): number;
isStatusValid(): boolean;
updateStatus(text: string): Member;
deactivate(): Member;
}
永続化と整合性:
- イミュータブル: すべてのプロパティはreadonlyであり、更新は新しいインスタンスを返す
- 整合性: コンストラクタでバリデーションを実施し、不正な状態を防ぐ
同時実行戦略:
- エンティティ自体は状態を持たない(純粋関数型アプローチ)
- 同時実行制御はリポジトリ層で実施(楽観的ロック等)
実装ノート
- 統合: types/index.tsの既存ビジネスロジック(calculateGrade, isStatusValid)を移行
- バリデーション: コンストラクタでEmail、StudentIdの値オブジェクトを使用した検証
- リスク: イミュータブル実装によるパフォーマンス影響は軽微(調査結果より)
Email, StudentId (値オブジェクト)
| フィールド | 詳細 |
|---|---|
| 目的 | ビジネスルールを持つ値のカプセル化とバリデーション |
| 要件 | 2.3, 2.4 |
責務と制約
- 値のバリデーションと不変性の保証
- ビジネスルールの実装(例: メールアドレス形式、学籍番号形式)
- 等価性比較
契約: State [x]
State Management
Emailモデル:
interface Email {
readonly value: string;
// ファクトリーメソッド
static create(value: string): Result<Email, ValidationError>;
// 等価性
equals(other: Email): boolean;
}
StudentIdモデル:
interface StudentId {
readonly value: string;
static create(value: string): Result<StudentId, ValidationError>;
equals(other: StudentId): boolean;
}
永続化と整合性:
- イミュータブル: 生成後は変更不可
- バリデーション: ファクトリーメソッドで生成時に検証
実装ノート
- バリデーション: 正規表現でメールアドレス形式、学籍番号形式を検証
- リスク: バリデーションロジックの複雑性は低い
アプリケーション層 (Application Layer)
IMemberRepository (ポートインターフェース)
| フィールド | 詳細 |
|---|---|
| 目的 | メンバーリポジトリの抽象化インターフェース |
| 要件 | 3.3 |
責務と制約
- メンバーエンティティのCRUD操作インターフェースを定義
- トランザクション境界なし(単一エンティティ操作)
- ドメイン境界: Memberアグリゲート
依存関係
- Inbound: GetMemberProfile UseCase — プロフィール取得 (P0)
- Inbound: UpdateMemberProfile UseCase — プロフィール更新 (P0)
- Outbound: Member Entity — ビジネスロジック (P0)
契約: Service [x]
Service Interface
interface IMemberRepository {
findById(id: string): Promise<Result<Member | null, RepositoryError>>;
findAll(params: QueryParams): Promise<Result<Member[], RepositoryError>>;
findByEmail(email: Email): Promise<Result<Member | null, RepositoryError>>;
create(member: Member): Promise<Result<Member, RepositoryError>>;
update(id: string, member: Partial<Member>): Promise<Result<Member, RepositoryError>>;
delete(id: string): Promise<Result<void, RepositoryError>>;
}
interface QueryParams {
limit?: number;
offset?: number;
filters?: {
isActive?: boolean;
enrollmentYear?: number;
};
}
事前条件:
findById,update,delete: idは有効なUUID形式create: memberは有効なMemberエンティティ(バリデーション済み)
事後条件:
findById: 存在する場合はMemberエンティティ、存在しない場合はnullcreate,update: 成功時は保存されたMemberエンティティを返すdelete: 成功時はvoid、エンティティは削除される
不変条件:
- すべてのメソッドはResult型を返し、エラーハンドリングを明示的に
実装ノート
- 統合: Infrastructure層のSupabaseMemberRepositoryが実装
- バリデーション: エンティティレベルで実施済み、リポジトリは永続化のみ
- リスク: Supabaseクエリビルダーとの型安全性を確保(TypeScript型生成)
IEventRepository (ポートインターフェース)
| フィールド | 詳細 |
|---|---|
| 目的 | イベントリポジトリの抽象化インターフェース |
| 要件 | 3.3 |
責務と制約
- イベントエンティティのCRUD操作インターフェース
- イベント参加登録(トランザクション処理)
- ドメイン境界: Eventアグリゲート、Participationアグリゲート
依存関係
- Inbound: RegisterForEvent UseCase — イベント登録 (P0)
- Inbound: GetEventList UseCase — イベント一覧取得 (P0)
- Outbound: Event Entity — ビジネスロジック (P0)
契約: Service [x]
Service Interface
interface IEventRepository {
findById(id: string): Promise<Result<Event | null, RepositoryError>>;
findAll(params: EventQueryParams): Promise<Result<Event[], RepositoryError>>;
create(event: Event): Promise<Result<Event, RepositoryError>>;
update(id: string, event: Partial<Event>): Promise<Result<Event, RepositoryError>>;
delete(id: string): Promise<Result<void, RepositoryError>>;
// トランザクション処理(RPC経由)
registerMember(memberId: string, eventId: string): Promise<Result<void, RepositoryError>>;
unregisterMember(memberId: string, eventId: string): Promise<Result<void, RepositoryError>>;
// 参加者取得
getParticipants(eventId: string): Promise<Result<Member[], RepositoryError>>;
}
interface EventQueryParams {
limit?: number;
offset?: number;
filters?: {
startDateFrom?: Date;
startDateTo?: Date;
};
}
事前条件:
registerMember,unregisterMember: memberId, eventIdは有効なUUIDregisterMember: イベントの定員に空きがある(ビジネスロジックで事前チェック)
事後条件:
registerMember: participationsテーブルにレコード追加、eventsのparticipant_count増加(トランザクション)unregisterMember: participationsテーブルからレコード削除、eventsのparticipant_count減少(トランザクション)
不変条件:
- トランザクション処理の原子性を保証(RPC経由でPostgreSQL関数実行)
実装ノート
- 統合: Infrastructure層のSupabaseEventRepositoryが実装
- バリデーション: PostgreSQL関数内でビジネスルール検証(定員チェック等)
- リスク: RPC関数の型安全性を確保(TypeScript型生成とテスト)
GetMemberProfile UseCase
| フィールド | 詳細 |
|---|---|
| 目的 | メンバープロフィール取得ユースケース |
| 要件 | 3.1, 3.2, 3.6 |
責務と制約
- メンバープロフィールの取得とDTOへの変換
- ビジネスルール適用(例: 学年計算、ステータス有効性チェック)
- トランザクション境界: なし(読み取り専用)
- ドメイン境界: Memberアグリゲート
依存関係
- Inbound: Server Actions — プレゼンテーション層からの呼び出し (P0)
- Outbound: IMemberRepository — データ取得 (P0)
- Outbound: Member Entity — ビジネスロジック (P0)
契約: Service [x]
Service Interface
interface IUseCase<TInput, TOutput> {
execute(input: TInput): Promise<Result<TOutput, UseCaseError>>;
}
interface GetMemberProfileUseCase extends IUseCase<GetMemberProfileInput, MemberDTO> {
execute(input: GetMemberProfileInput): Promise<Result<MemberDTO, UseCaseError>>;
}
interface GetMemberProfileInput {
memberId: string;
currentYear: number;
currentMonth: number;
}
事前条件:
- memberIdは有効なUUID形式
- currentYear, currentMonthは有効な日付
事後条件:
- 成功時: MemberDTOを返す(学年計算済み、ステータス有効性チェック済み)
- 失敗時: MemberNotFoundError または RepositoryError
不変条件:
- ビジネスロジックは常にドメインエンティティ内で実行
- DTOはシリアライズ可能な型のみ(Date→ISO文字列等)
実装ノート
- 統合: Server Actionsから呼び出され、リポジトリを通じてデータ取得
- バリデーション: エンティティのcalculateGrade(), isStatusValid()を使用
- リスク: DTOシリアライゼーションでDate型の扱いに注意
RegisterForEvent UseCase
| フィールド | 詳細 |
|---|---|
| 目的 | イベント参加登録ユースケース |
| 要件 | 3.1, 3.2, 3.8 |
責務と制約
- イベント参加登録とビジネスルール検証
- トランザクション境界: 定義あり(participations INSERT + events UPDATE)
- ドメイン境界: Event, Member, Participationアグリゲート
依存関係
- Inbound: Server Actions — プレゼンテーション層からの呼び出し (P0)
- Outbound: IEventRepository — イベント登録 (P0)
- Outbound: IMemberRepository — メンバー取得 (P1)
- Outbound: Event Entity — ビジネスロジック (P0)
契約: Service [x]
Service Interface
interface RegisterForEventUseCase extends IUseCase<RegisterForEventInput, void> {
execute(input: RegisterForEventInput): Promise<Result<void, UseCaseError>>;
}
interface RegisterForEventInput {
memberId: string;
eventId: string;
}
事前条件:
- memberId, eventIdは有効なUUID
- メンバーが存在し、アクティブである
- イベントが存在し、定員に空きがある
事後条件:
- 成功時: participationsテーブルにレコード追加、eventsのparticipant_count増加
- 失敗時: EventFullError, MemberNotFoundError, EventNotFoundError
不変条件:
- トランザクション処理の原子性を保証(RPC経由)
- ビジネスルール違反時はロールバック
実装ノート
- 統合: IEventRepository.registerMember()を呼び出し、RPC関数実行
- バリデーション: PostgreSQL関数内で定員チェック、重複チェック
- リスク: トランザクション失敗時のエラーハンドリングとユーザーへのフィードバック
MemberDTO, EventDTO (データ転送オブジェクト)
| フィールド | 詳細 |
|---|---|
| 目的 | レイヤー間のデータ転送 |
| 要件 | 3.4 |
責務と制約
- シリアライズ可能なプレーンオブジェクト
- ビジネスロジックを持たない
- Server ComponentsとClient Components間のデータ転送
契約: State [x]
State Management
interface MemberDTO {
id: string;
name: string;
email: string; // Email値オブジェクトから文字列に変換
studentId: string; // StudentId値オブジェクトから文字列に変換
enrollmentYear: number;
grade: number; // 計算済み
isActive: boolean;
status?: {
text: string;
expiresAt: string; // Date → ISO文字列
isValid: boolean; // 計算済み
};
skills: string[];
interests: string[];
createdAt: string; // Date → ISO文字列
updatedAt: string; // Date → ISO文字列
}
interface EventDTO {
id: string;
title: string;
description: string;
startDate: string; // Date → ISO文字列
endDate: string; // Date → ISO文字列
capacity: number;
participantCount: number;
location: string;
createdAt: string; // Date → ISO文字列
}
永続化と整合性:
- DTOは一時的なデータ転送用のみ、永続化しない
- ドメインエンティティ→DTO、DTO→ドメインエンティティの変換はユースケース層で実施
実装ノート
- 統合: Server ActionsでDTOをJSON形式でシリアライズ
- バリデーション: DTOからエンティティへの変換時にバリデーション再実施
- リスク: Date型のシリアライゼーション(ISO文字列に統一)
インフラストラクチャ層 (Infrastructure Layer)
SupabaseMemberRepository (リポジトリ実装)
| フィールド | 詳細 |
|---|---|
| 目的 | IMemberRepositoryの具体的実装 |
| 要件 | 4.1, 4.2, 4.6 |
責務と制約
- Supabaseクライアントを使用したCRUD操作
- DB型(Database[‘public’][‘Tables’][‘members’][‘Row’])→Memberエンティティの変換
- エラーハンドリングと標準化されたエラー型への変換
- ドメイン境界: Memberアグリゲート
依存関係
- Inbound: GetMemberProfile UseCase — データ取得 (P0)
- Outbound: Supabase Client — データベースアクセス (P0)
- Outbound: Member Entity — ドメインモデル (P0)
- External: @supabase/supabase-js — Supabaseクライアントライブラリ (P0)
調査結果: Supabaseの型自動生成機能により、型安全性が確保される(公式ドキュメント)
契約: Service [x]
Service Interface
class SupabaseMemberRepository implements IMemberRepository {
constructor(private readonly client: SupabaseClient<Database>) {}
async findById(id: string): Promise<Result<Member | null, RepositoryError>> {
// 実装詳細は省略(インターフェース遵守)
}
async findAll(params: QueryParams): Promise<Result<Member[], RepositoryError>> {
// 実装詳細は省略
}
async create(member: Member): Promise<Result<Member, RepositoryError>> {
// 実装詳細は省略
}
// データマッパー(private)
private mapToEntity(row: Database['public']['Tables']['members']['Row']): Member {
// DB型 → ドメインエンティティへの変換
}
private mapToRow(member: Member): Database['public']['Tables']['members']['Insert'] {
// ドメインエンティティ → DB型への変換
}
}
事前条件:
- Supabase clientが初期化済み
- データベーススキーマがマイグレーション済み
事後条件:
- すべてのメソッドは標準化されたResult型を返す
- データベースエラーはRepositoryErrorに変換
不変条件:
- データマッパーは純粋関数であり、副作用を持たない
- RLS(Row Level Security)ポリシーを尊重
実装ノート
- 統合: lib/supabase/server.tsのSupabaseクライアントを使用
- バリデーション: エンティティコンストラクタで実施済み、リポジトリは永続化のみ
- リスク: RLS設定によるクエリ失敗を適切にハンドリング
SupabaseEventRepository (リポジトリ実装)
| フィールド | 詳細 |
|---|---|
| 目的 | IEventRepositoryの具体的実装 |
| 要件 | 4.1, 4.2, 4.6 |
責務と制約
- Supabaseクライアントを使用したCRUD操作
- RPC経由でのトランザクション処理(registerMember, unregisterMember)
- DB型→Eventエンティティの変換
- ドメイン境界: Event, Participationアグリゲート
依存関係
- Inbound: RegisterForEvent UseCase — イベント登録 (P0)
- Outbound: Supabase Client — データベースアクセス、RPC (P0)
- Outbound: Event Entity — ドメインモデル (P0)
- External: @supabase/supabase-js — Supabaseクライアントライブラリ (P0)
調査結果: RPC関数はPostgRESTによって自動的にトランザクションでラップされる(調査結果)
契約: Service [x], Batch [x]
Service Interface
class SupabaseEventRepository implements IEventRepository {
constructor(private readonly client: SupabaseClient<Database>) {}
async registerMember(memberId: string, eventId: string): Promise<Result<void, RepositoryError>> {
const { data, error } = await this.client.rpc('register_for_event', {
p_member_id: memberId,
p_event_id: eventId
});
if (error) {
return Result.err(this.mapError(error));
}
return Result.ok(undefined);
}
// 他のメソッドは省略
}
Batch / Job Contract
トリガー: RegisterForEvent UseCaseからの呼び出し
入力/バリデーション:
p_member_id: UUID形式p_event_id: UUID形式- PostgreSQL関数内でビジネスルール検証(定員チェック、重複チェック)
出力/宛先:
- 成功時: void(データベースに永続化)
- 失敗時: RepositoryError(EventFull, AlreadyRegistered等)
冪等性と回復:
- PostgreSQL関数内でトランザクション処理(原子性保証)
- 重複登録はUNIQUE制約でエラー
- リトライはアプリケーション層で実施(RPC呼び出しのリトライ)
実装ノート
- 統合: PostgreSQL関数
register_for_eventをRPC経由で呼び出し - バリデーション: PostgreSQL関数内でビジネスルール実施
- リスク: RPC関数の型安全性(TypeScript型生成とテスト)
DatabaseClient (Supabaseクライアント)
| フィールド | 詳細 |
|---|---|
| 目的 | Supabaseクライアントの初期化と提供 |
| 要件 | 4.3 |
責務と制約
- Server Components用のSupabaseクライアント初期化
- 環境変数からの設定読み込み
- RLS(Row Level Security)統合
依存関係
- Inbound: 全リポジトリ実装 — データベースアクセス (P0)
- External: @supabase/ssr — Server-side rendering support (P0)
- External: @supabase/supabase-js — Supabaseクライアント (P0)
契約: Service [x]
Service Interface
interface IDatabaseClient {
getServerClient(): SupabaseClient<Database>;
getAdminClient(): SupabaseClient<Database>;
}
class DatabaseClient implements IDatabaseClient {
getServerClient(): SupabaseClient<Database> {
// lib/supabase/server.tsの既存実装を活用
}
getAdminClient(): SupabaseClient<Database> {
// lib/supabase/admin.tsの既存実装を活用
}
}
事前条件:
- 環境変数(NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY)が設定済み
事後条件:
- 初期化されたSupabaseClientインスタンスを返す
- RLSポリシーが適用される(ServerClient)またはバイパスされる(AdminClient)
実装ノート
- 統合: 既存のlib/supabase/配下のクライアントを活用
- バリデーション: 環境変数の検証(起動時)
- リスク: AdminClientの誤用防止(使用箇所を限定)
AuthProvider (ZITADEL認証プロバイダー)
| フィールド | 詳細 |
|---|---|
| 目的 | ZITADEL認証とNextAuth.jsの統合 |
| 要件 | 4.4 |
責務と制約
- ZITADEL OIDCプロバイダーの設定
- NextAuth.jsコールバック設定
- ロールベースアクセス制御(adminロール)
- セッション管理
依存関係
- Inbound: Server Components, Middleware — 認証状態取得 (P0)
- External: NextAuth.js 4.24 — 認証フレームワーク (P0)
- External: ZITADEL — 認証プロバイダー (P0)
契約: Service [x]
Service Interface
interface IAuthService {
getCurrentUser(): Promise<User | null>;
hasRole(role: string): Promise<boolean>;
signIn(redirectUrl?: string): Promise<void>;
signOut(redirectUrl?: string): Promise<void>;
}
class AuthProvider implements IAuthService {
async getCurrentUser(): Promise<User | null> {
// NextAuth.jsのgetServerSession()を使用
}
async hasRole(role: string): Promise<boolean> {
// JWTからロール情報を抽出
}
}
事前条件:
- ZITADEL設定済み(Client ID, Client Secret, Issuer URL)
- NextAuth.js設定完了
事後条件:
- 認証済みユーザーのセッション情報を返す
- ロール情報を含むJWTトークン
実装ノート
- 統合: 既存のlib/auth-options.tsを活用
- バリデーション: JWTトークンの検証(NextAuth.jsが自動実施)
- リスク: ZITADELのダウンタイムやレート制限への対応
DIContainer (依存性注入コンテナ)
| フィールド | 詳細 |
|---|---|
| 目的 | 軽量DIメカニズムの提供 |
| 要件 | 4.9 |
責務と制約
- インターフェースベースの依存性登録
- 型安全な依存性解決
- ドメインモジュールによるファクトリーパターン
依存関係
- Inbound: 全ユースケース — 依存性解決 (P0)
- Inbound: Server Actions — 依存性注入 (P0)
契約: Service [x]
Service Interface
type DIKey<T> = symbol | string;
interface IDIContainer {
register<T>(key: DIKey<T>, implementation: new (...args: any[]) => T): void;
registerSingleton<T>(key: DIKey<T>, implementation: new (...args: any[]) => T): void;
resolve<T>(key: DIKey<T>): T;
}
class DIContainer implements IDIContainer {
private registry: Map<DIKey<any>, any> = new Map();
private singletons: Map<DIKey<any>, any> = new Map();
register<T>(key: DIKey<T>, implementation: new (...args: any[]) => T): void {
this.registry.set(key, implementation);
}
registerSingleton<T>(key: DIKey<T>, implementation: new (...args: any[]) => T): void {
if (!this.singletons.has(key)) {
const instance = new implementation();
this.singletons.set(key, instance);
}
}
resolve<T>(key: DIKey<T>): T {
if (this.singletons.has(key)) {
return this.singletons.get(key);
}
const Implementation = this.registry.get(key);
if (!Implementation) {
throw new Error(`No implementation registered for key: ${String(key)}`);
}
return new Implementation();
}
}
// ドメインモジュールファクトリー
function memberModule(di: IDIContainer): void {
const MemberRepoKey = Symbol('IMemberRepository');
di.registerSingleton(MemberRepoKey, SupabaseMemberRepository);
}
function eventModule(di: IDIContainer): void {
const EventRepoKey = Symbol('IEventRepository');
di.registerSingleton(EventRepoKey, SupabaseEventRepository);
}
事前条件:
- すべての依存関係が登録済み(アプリケーション起動時)
事後条件:
- 型安全な依存性解決
- シングルトンインスタンスの再利用
実装ノート
- 統合: Server Actions内でDIContainerを初期化し、ユースケースに注入
- バリデーション: キーの重複登録を防止
- リスク: 循環依存の検出と防止
調査結果: ioctopus風の軽量DIパターンはNext.js Server Componentsと互換性が高い(調査記事)
プレゼンテーション層 (Presentation Layer)
MemberProfilePage (Server Component)
| フィールド | 詳細 |
|---|---|
| 目的 | メンバープロフィールページのレンダリング |
| 要件 | 5.1, 5.3 |
責務と制約
- Server Componentとしてサーバーサイドでレンダリング
- GetMemberProfile UseCaseを呼び出してデータ取得
- UIコンポーネントへのDTOの受け渡し
依存関係
- Inbound: ユーザーアクセス — ページ表示 (P0)
- Outbound: GetMemberProfile UseCase — データ取得 (P0)
- Outbound: MemberProfileCard Component — UI表示 (P0)
実装ノート
- 統合: app/members/[id]/page.tsxで実装
- バリデーション: UseCaseからのエラーをエラーページで表示
- リスク: Server Componentsでのエラーハンドリング(Next.js 15のerror.tsxを活用)
調査結果: Server Componentsはデフォルトでasync/awaitをサポート(Next.js公式ドキュメント)
EventRegistrationButton (Client Component)
| フィールド | 詳細 |
|---|---|
| 目的 | イベント参加登録ボタン |
| 要件 | 5.2, 5.4 |
責務と制約
- Client Componentとしてインタラクティブ性を提供
- Server Actionを呼び出してイベント登録
- ローディング状態とエラー表示
依存関係
- Inbound: ユーザークリック — イベント登録 (P0)
- Outbound: registerForEvent Server Action — データ送信 (P0)
契約: State [x]
State Management
interface EventRegistrationButtonProps {
eventId: string;
memberId: string;
isRegistered: boolean;
}
interface EventRegistrationButtonState {
isLoading: boolean;
error: string | null;
}
実装ノート
- 統合: components/events/EventRegistrationButton.tsxで実装
- バリデーション: Server Actionからのエラーをユーザーに表示
- リスク: Server Action呼び出し時のネットワークエラーハンドリング
Server Actions
| フィールド | 詳細 |
|---|---|
| 目的 | プレゼンテーション層とアプリケーション層の橋渡し |
| 要件 | 5.5, 5.7, 5.9 |
責務と制約
use serverディレクティブでServer Actionsを定義- UseCaseをDIContainerから解決して実行
- Result型からHTTPレスポンスまたはDTOへの変換
依存関係
- Inbound: Server Components, Client Components — データ送受信 (P0)
- Outbound: UseCases — ビジネスロジック実行 (P0)
- Outbound: DIContainer — 依存性解決 (P0)
契約: API [x]
API Contract
| Method | Endpoint | Request | Response | Errors |
|---|---|---|---|---|
| POST | Server Action: getMemberProfile | { memberId: string } | MemberDTO | MemberNotFound, RepositoryError |
| POST | Server Action: registerForEvent | { memberId: string, eventId: string } | void | EventFull, MemberNotFound, RepositoryError |
| POST | Server Action: updateMemberProfile | { memberId: string, data: Partial | MemberDTO | ValidationError, RepositoryError |
実装例:
'use server';
export async function getMemberProfile(memberId: string): Promise<MemberDTO> {
const di = initializeDI(); // DIContainer初期化
const useCase = di.resolve<GetMemberProfileUseCase>(GetMemberProfileUseCaseKey);
const result = await useCase.execute({
memberId,
currentYear: new Date().getFullYear(),
currentMonth: new Date().getMonth() + 1
});
if (result.isErr()) {
throw new Error(result.error.message); // Next.js 15がエラーをキャッチ
}
return result.value;
}
export async function registerForEvent(memberId: string, eventId: string): Promise<void> {
const di = initializeDI();
const useCase = di.resolve<RegisterForEventUseCase>(RegisterForEventUseCaseKey);
const result = await useCase.execute({ memberId, eventId });
if (result.isErr()) {
throw new Error(result.error.message);
}
}
実装ノート
- 統合: app/actions/配下にドメイン別にファイル配置(member-actions.ts, event-actions.ts)
- バリデーション: UseCaseからのエラーをNext.js 15のエラーハンドリングに委譲
- リスク: Server Actionsのシリアライゼーション制約(DTOは常にシリアライズ可能)
調査結果: Server ActionsはNext.js 15の推奨パターン(公式ドキュメント)
データモデル
ドメインモデル
アグリゲートとトランザクション境界
erDiagram
MEMBER ||--o{ PARTICIPATION : registers
EVENT ||--o{ PARTICIPATION : has
MEMBER ||--o{ MEMBER_TAG : has
TAG ||--o{ MEMBER_TAG : tagged
MEMBER ||--o{ TIMETABLE : has
MEMBER {
uuid id PK
string name
string email
string student_id
int enrollment_year
boolean is_active
string status_text
timestamp status_expires_at
timestamp created_at
timestamp updated_at
}
EVENT {
uuid id PK
string title
text description
timestamp start_date
timestamp end_date
int capacity
int participant_count
string location
timestamp created_at
}
PARTICIPATION {
uuid id PK
uuid member_id FK
uuid event_id FK
timestamp registered_at
}
TAG {
uuid id PK
string name
string category
}
MEMBER_TAG {
uuid member_id FK
uuid tag_id FK
}
TIMETABLE {
uuid id PK
uuid member_id FK
int day_of_week
int period
string course_name
string classroom
}
エンティティ、値オブジェクト、ドメインイベント
- Memberアグリゲート(ルート): id, name, email (値オブジェクト), studentId (値オブジェクト), enrollmentYear, isActive, status, skills, interests
- Eventアグリゲート(ルート): id, title, description, startDate, endDate, capacity, participantCount, location
- Participationエンティティ: id, memberId, eventId, registeredAt(EventアグリゲートとMemberアグリゲートの関連)
- Timetableエンティティ: id, memberId, dayOfWeek, period, courseName, classroom(Memberアグリゲート配下)
- 値オブジェクト: Email, StudentId, EventCapacity(バリデーションロジックを内包)
ビジネスルールと不変条件
-
Member:
- emailはEmail値オブジェクトで検証済み
- studentIdはStudentId値オブジェクトで検証済み
- statusは24時間で無効化(isStatusValid()メソッド)
- gradeはenrollmentYearから自動計算(calculateGrade()メソッド)
-
Event:
- participantCountはcapacityを超えない(PostgreSQL関数で検証)
- startDateはendDateより前
-
Participation:
- member, eventの組み合わせは一意(UNIQUE制約)
論理データモデル
構造定義
既存のSupabaseスキーマを維持(supabase/migrations/配下):
membersテーブル: 主キー(id), UNIQUE(email, student_id), インデックス(enrollment_year, is_active)eventsテーブル: 主キー(id), インデックス(start_date)participationsテーブル: 主キー(id), 外部キー(member_id, event_id), UNIQUE(member_id, event_id)tagsテーブル: 主キー(id), UNIQUE(name, category)member_tagsテーブル: 複合主キー(member_id, tag_id)timetablesテーブル: 主キー(id), 外部キー(member_id), インデックス(member_id)
整合性と完全性
- トランザクション境界: イベント参加登録(participations INSERT + events UPDATE)はPostgreSQL関数で原子性保証
- カスケーディングルール: members削除時、participations, member_tags, timetablesをCASCADE削除
- 時間的側面: created_at, updated_atで監査ログ、status_expires_atで時間制限ステータス
物理データモデル
PostgreSQL(Supabase)
既存のデータベーススキーマを維持:
- テーブル定義:
supabase/migrations/配下のSQLマイグレーションファイル - インデックス: enrollment_year, is_active, start_date等にインデックス設定済み
- 制約: PRIMARY KEY, FOREIGN KEY, UNIQUE, NOT NULL制約設定済み
- 関数: calculate_grade()関数(入学年度から学年を自動計算)
- RLS(Row Level Security): 認証済みユーザーのみアクセス可能、adminロールは全権限
パーティショニング戦略
現時点では不要(データ量が小規模)。将来的にeventsテーブルをstart_dateでパーティショニング可能。
データ契約と統合
APIデータ転送
- リクエスト/レスポンススキーマ: MemberDTO, EventDTO等(TypeScriptインターフェース)
- バリデーションルール: エンティティコンストラクタで実施
- シリアライゼーション形式: JSON(Next.js Server Actions)
イベントスキーマ
現時点ではイベント駆動アーキテクチャは不採用。将来的にSupabase Realtimeを活用可能。
クロスサービスデータ管理
- 分散トランザクションパターン: PostgreSQL関数によるローカルトランザクション
- データ同期戦略: 同期的なRPC呼び出し
- 結果整合性: リアルタイム要件なし、即時整合性
エラーハンドリング
エラー戦略
Result型パターン
すべてのレイヤーでResult型を使用し、エラーハンドリングを明示的に:
type Result<T, E = Error> =
| { isOk: true; value: T; isErr: false; error: never }
| { isOk: false; value: never; isErr: true; error: E };
class Result {
static ok<T>(value: T): Result<T, never> {
return { isOk: true, value, isErr: false, error: undefined as never };
}
static err<E>(error: E): Result<never, E> {
return { isOk: false, value: undefined as never, isErr: true, error };
}
}
エラーカテゴリとレスポンス
ドメインエラー(ビジネスルール違反)
InvalidEmailError: メールアドレス形式不正 → フィールドレベルバリデーションメッセージInvalidStudentIdError: 学籍番号形式不正 → フィールドレベルバリデーションメッセージStatusExpiredError: ステータス期限切れ → 警告メッセージとステータス更新促進
アプリケーションエラー(ユースケース実行失敗)
MemberNotFoundError: メンバーが存在しない → 404エラーページEventNotFoundError: イベントが存在しない → 404エラーページEventFullError: イベント定員超過 → ユーザーに定員超過メッセージ表示AlreadyRegisteredError: 既に登録済み → ユーザーに登録済みメッセージ表示
インフラストラクチャエラー(外部サービス障害)
DatabaseConnectionError: データベース接続エラー → 5xxエラーページ、リトライAuthenticationError: 認証失敗 → ログインページへリダイレクトAuthorizationError: 認可失敗 → 403エラーページ
システムエラー(予期しないエラー)
UnexpectedError: 予期しないエラー → 5xxエラーページ、ログ記録
モニタリング
- エラー追跡: すべてのエラーをログ記録(console.error)、将来的にSentryなどの監視ツール統合
- ヘルスモニタリング: Supabase接続状態、ZITADEL認証状態を定期的に監視
- ログ: 構造化ログ(JSON形式)でエラー詳細、スタックトレース、ユーザーコンテキストを記録
テスト戦略
ユニットテスト
ドメイン層
- MemberエンティティのcalculateGrade()メソッド
- Memberエンティティのi sStatusValid()メソッド
- Email値オブジェクトのバリデーション
- StudentId値オブジェクトのバリデーション
- Eventエンティティの定員チェックロジック
アプリケーション層
- GetMemberProfile UseCaseの実行(モックリポジトリを使用)
- RegisterForEvent UseCaseの実行(モックリポジトリを使用)
- DTOからエンティティへの変換ロジック
統合テスト
インフラストラクチャ層
- SupabaseMemberRepositoryのfindById()メソッド(実データベース使用)
- SupabaseEventRepositoryのregisterMember()メソッド(実データベース、RPC関数)
- データマッパーの変換ロジック(DB型↔ドメインエンティティ)
プレゼンテーション層
- Server Actionsの呼び出しとレスポンス
- Server ComponentsとClient Componentsの統合
E2E/UIテスト
クリティカルユーザーパス
- メンバープロフィール表示フロー
- イベント参加登録フロー
- 管理者によるイベント作成フロー
- メンバー一覧表示とフィルタリング
- タイムテーブル表示とフィルタリング
パフォーマンステスト
負荷テスト
- 同時100ユーザーのイベント参加登録
- 1000件のメンバー一覧表示
- タイムテーブルの複雑なフィルタリングクエリ
スケーラビリティテスト
- Supabaseの接続プール上限テスト
- Next.js Server Componentsのレンダリング時間計測
マイグレーション戦略
7段階マイグレーション計画
flowchart TB
Start([開始]) --> Phase1[段階1: 基盤整備<br/>ディレクトリ構造、DI、設定]
Phase1 --> Phase2[段階2: ドメイン層<br/>エンティティ、値オブジェクト]
Phase2 --> Phase3[段階3: アプリケーション層<br/>ユースケース、ポート、DTO]
Phase3 --> Phase4[段階4: インフラストラクチャ層<br/>リポジトリ、データマッパー]
Phase4 --> Validation1{動作検証}
Validation1 -->|OK| Phase5[段階5: プレゼンテーション統合<br/>パイロット機能]
Validation1 -->|NG| Rollback1[ロールバック]
Phase5 --> Validation2{動作検証}
Validation2 -->|OK| Phase6[段階6: 全機能移行<br/>残機能の移行]
Validation2 -->|NG| Rollback2[ロールバック]
Phase6 --> Validation3{動作検証}
Validation3 -->|OK| Phase7[段階7: テスト・ドキュメント<br/>ユニット/統合テスト]
Validation3 -->|NG| Rollback3[ロールバック]
Phase7 --> Complete([完了])
Rollback1 --> Phase1
Rollback2 --> Phase5
Rollback3 --> Phase6
段階別詳細
段階1: 基盤整備(3日)
- ディレクトリ作成(src/domain, application, infrastructure, presentation)
- tsconfig.jsonパスエイリアス設定(@/domain, @/application等)
- DIContainer実装(軽量ファクトリーパターン)
- 完了基準: ビルドエラーなし、パスエイリアス動作確認
段階2: ドメイン層(5日)
- Member, Event, Timetableエンティティ実装
- Email, StudentId, EventCapacity値オブジェクト実装
- types/index.tsのビジネスロジック移行
- 完了基準: ドメインロジックのユニットテストパス
段階3: アプリケーション層(4日)
- IMemberRepository, IEventRepository, ITimetableRepositoryポートインターフェース定義
- MemberDTO, EventDTO, TimetableDTO定義
- GetMemberProfile, RegisterForEventユースケース実装(パイロット)
- 完了基準: ユースケースのユニットテスト(モックリポジトリ)パス
段階4: インフラストラクチャ層(5日)
- SupabaseMemberRepository, SupabaseEventRepository実装
- データマッパー実装(mapToEntity, mapToRow)
- PostgreSQL関数作成(register_for_event, unregister_from_event)
- 完了基準: リポジトリの統合テストパス
段階5: プレゼンテーション統合(4日)
- パイロット機能(メンバー一覧ページ)をユースケース統合
- Server Actions実装(getMemberProfile, registerForEvent)
- エラーハンドリング統合
- 完了基準: パイロット機能の動作確認、既存機能が破壊されていない
段階6: 全機能移行(5日)
- 残機能の移行(イベント一覧、タイムテーブル、管理画面)
- モックデータを実データに置き換え
- 既存のlib/, types/ディレクトリから不要ファイル削除
- 完了基準: すべての既存機能が新レイヤーで動作
段階7: テストとドキュメント(4日)
- ユニットテスト完全実装
- 統合テスト実装
- E2Eテスト実装(クリティカルパス)
- アーキテクチャドキュメント作成
- 開発者オンボーディングガイド作成
- 完了基準: テストカバレッジ80%以上、ドキュメント完成
ロールバック戦略
- Gitブランチ戦略: 各段階ごとにブランチ作成(feature/phase-1等)
- ロールバックトリガー: 重大なバグ、既存機能の破壊、パフォーマンス劣化
- ロールバック手順: 前段階のブランチにマージ、問題修正後に再実施
検証チェックポイント
各段階で以下を検証:
- ビルドエラーなし
- TypeScript型エラーなし
- 既存機能が破壊されていない
- 新機能が期待通り動作
- パフォーマンス劣化なし
セキュリティ考慮事項
脅威モデリング
- SQLインジェクション: Supabaseクエリビルダーとパラメータ化クエリで防止
- XSS: Next.jsのデフォルトエスケープ、Spindle UIコンポーネント使用
- CSRF: Next.js Server ActionsのCSRFトークン自動生成
- 認証バイパス: ZITADELとNextAuth.jsによる認証、RLSポリシーで二重チェック
認証と認可パターン
- 認証: ZITADEL OIDC → NextAuth.js → セッション管理
- 認可: ロールベースアクセス制御(adminロール)、RLSポリシー
データ保護とプライバシー
- 個人情報: メールアドレス、学籍番号はRLSポリシーで保護
- ステータス: 24時間で自動無効化
- パスワード: ZITADELで管理(Portal.Cでは保存しない)
パフォーマンスとスケーラビリティ
目標メトリクス
- ページロード時間: 初回ロード < 2秒、以降 < 1秒
- APIレスポンス: メンバー一覧取得 < 500ms、イベント登録 < 1秒
- 同時接続: 100同時ユーザー対応
スケーリングアプローチ
- 水平スケーリング: Vercelの自動スケーリング、Supabaseの接続プール
- 垂直スケーリング: 必要に応じてSupabaseプラン変更
キャッシング戦略
- Next.js 15キャッシング: Server Componentsの自動キャッシュ
- Supabaseキャッシング: メンバー一覧など頻繁にアクセスされるデータをNext.js側でキャッシュ
- 再検証: 1時間ごとに再検証(revalidate: 3600)
サポートリファレンス
調査ソース
- Clean Architecture in Next.js 15
- Next.js Clean Architecture GitHub
- DI Patterns in Next.js
- Supabase Transactions and RLS
- Supabase TypeScript Support
- Next.js Server Components Official Docs
- Repository Pattern with TypeScript
詳細な調査結果はresearch.mdを参照。
TypeScript型定義の詳細
詳細な型定義はSupporting Referencesセクションではなく、各コンポーネントのService Interface、State Managementセクションに記載しています。
PostgreSQL関数定義
-- register_for_event: イベント参加登録(トランザクション処理)
CREATE OR REPLACE FUNCTION register_for_event(
p_member_id UUID,
p_event_id UUID
)
RETURNS BOOLEAN AS $$
DECLARE
v_capacity INT;
v_participant_count INT;
BEGIN
-- イベント情報取得
SELECT capacity, participant_count INTO v_capacity, v_participant_count
FROM events
WHERE id = p_event_id;
-- 定員チェック
IF v_participant_count >= v_capacity THEN
RAISE EXCEPTION 'Event is full';
END IF;
-- 参加登録
INSERT INTO participations (member_id, event_id, registered_at)
VALUES (p_member_id, p_event_id, NOW());
-- 参加者数更新
UPDATE events
SET participant_count = participant_count + 1
WHERE id = p_event_id;
RETURN TRUE;
EXCEPTION
WHEN unique_violation THEN
RAISE EXCEPTION 'Already registered';
WHEN OTHERS THEN
RAISE;
END;
$$ LANGUAGE plpgsql SECURITY INVOKER;
-- unregister_from_event: イベント参加解除(トランザクション処理)
CREATE OR REPLACE FUNCTION unregister_from_event(
p_member_id UUID,
p_event_id UUID
)
RETURNS BOOLEAN AS $$
BEGIN
-- 参加解除
DELETE FROM participations
WHERE member_id = p_member_id AND event_id = p_event_id;
-- 参加者数更新
UPDATE events
SET participant_count = participant_count - 1
WHERE id = p_event_id;
RETURN TRUE;
END;
$$ LANGUAGE plpgsql SECURITY INVOKER;
設計完了日: 2025-12-16 バージョン: 1.0.0 ステータス: 設計承認待ち
実装計画
-
1. レイヤー基盤を整備する
-
1.1 (P) レイヤーディレクトリとパスエイリアスを確定する
src配下にドメイン、アプリケーション、インフラ、プレゼンテーションの境界を新設し、既存のApp RouterとUIコンポーネント領域をプレゼンテーションとして明示する- 各レイヤーのサブディレクトリ構成を合意し、依存方向を示すパスエイリアスをTypeScript設定に反映する
- 新構成で型チェックとビルドが通ることを短いサンプルで確認し、逸脱時の検知方法を共有する
- Requirements: 1.1,1.2,1.3,1.4,1.5,1.7
-
1.2 (P) 既存資産のレイヤー配置計画を策定する
- libやtypesの責務を洗い出し、ドメイン・アプリケーション・インフラへの移行先をマッピングする
- 旧構成と新構成が一時共存する期間の参照ルールと移行順を決め、影響範囲を可視化する
- インポート更新を自動化するスクリプトや手順を準備し、段階的移行で破綻しないようにする
- Requirements: 1.6,9.2,9.5
-
2. ドメイン層を純粋なビジネスロジックとして構築する
-
2.1 (P) エンティティと値オブジェクトを定義する
- Member・Event・Timetableの状態とふるまいを不変モデルで表現し、学年計算や定員チェックなどのビジネスルールを内包させる
- Email・StudentId・EventCapacityの値オブジェクトを実装し、生成時にバリデーションを行う
- 複数エンティティに跨るロジックをドメインサービスに集約し、外部依存を持たない形にする
- Requirements: 2.1,2.2,2.3,2.4,2.5,2.7
-
2.2 (P) ドメインの独立性と不変条件を検証する
- ドメイン層が外部ライブラリや他レイヤーへ依存していないことを静的に確認する
- 生成・更新時に不正状態を拒否するガードを用意し、例外やエラー型の扱いを決める
- 既存ビジネスロジックを移行しても振る舞いが変わらないことをサンプルで確認する
- Requirements: 2.6,2.7,6.1
-
3. アプリケーション層でユースケース駆動のAPIを構築する
-
3.1 (P) ポートとDTO契約を定義する
- リポジトリや認証サービスのポートを整理し、依存性逆転を前提としたインターフェース契約を用意する
- サーバー・クライアント間でシリアライズ可能なDTOを設計し、日付やIDの取り扱いルールを決める
- アプリケーション層がドメインのみを参照することを確認し、境界外参照を検知する仕組みを組み込む
- Requirements: 3.3,3.4,3.5,6.2
-
3.2 (P) クエリ系ユースケースを実装する
- プロフィール取得や一覧取得のユースケースでexecuteエントリーポイントを整備し、Resultベースのエラーハンドリングを適用する
- ドメインエンティティからDTOへの変換責務を明確にし、ビジネスルールの評価順序を固定する
- 失敗時の例外種別と呼び出し側への伝播方法を揃え、再利用しやすいレスポンス形に整える
- Requirements: 3.1,3.2,3.6,3.7
-
3.3 (P) コマンド系ユースケースを実装する
- 参加登録やプロフィール更新などの書き込みユースケースにトランザクション境界を設定する
- ポート経由でインフラ層を呼び出し、重複登録や定員超過などのビジネスルールを実行前に検証する
- 例外とアプリケーションエラーを分類し、呼び出し元がUIに伝えやすい形で返す
- Requirements: 3.1,3.2,3.6,3.8
-
4. インフラストラクチャで外部サービス統合を実現する
-
4.1 (P) データアクセス基盤を整える
- Supabaseクライアントの初期化手順と資格情報検証を整理し、RLSを前提とした接続パターンを固める
- 接続失敗や認証エラー時の標準化されたエラー構造を用意し、上位層が扱えるようにする
- Requirements: 4.3,4.7
-
4.2 (P) リポジトリ実装とデータマッピングを行う
- Member・Event・Timetable向けのリポジトリでCRUDと検索を実装し、ポート契約に沿ったResultを返す
- データベースの型とドメインモデルを相互に変換するマッパーを用意し、欠損値や不正値の扱いを定義する
- 外部API連携が必要な場合の拡張ポイントを決め、依存注入で切り替えられるようにする
- Requirements: 4.1,4.2,4.5,4.6,4.8
-
4.3 (P) 認証基盤と依存性注入を統合する
- 認証プロバイダーをポート契約に沿って実装し、ロール判定やセッション取得の流れを統一する
- DIコンテナにリポジトリとサービスを登録し、シングルトン管理やテスト用差し替えの方針を決める
- Requirements: 4.4,4.9,7.4
-
4.4 (P) トランザクション処理をRPCで実装する
- 参加登録・解除の処理をデータベース側のRPCで原子的に実行し、定員チェックを含むビジネスルールを担保する
- RPCの結果とエラーをアプリケーション層で扱えるフォーマットに正規化する
- Requirements: 3.8,4.1,4.2
-
5. プレゼンテーション層でユースケースとUIを接続する
-
5.1 Server Actionsを実装しユースケースを橋渡しする
- サーバーコンテキストでユースケースを解決し、DTOを返却する標準フローを整える
- エラーをユーザー向けメッセージや再入力案内に変換する規約を決める
- Requirements: 5.5,5.7,5.9
-
5.2 ページとUIをClean Architectureに合わせて再構成する
- 主要ページをサーバーコンポーネント基調にし、ユースケース経由でデータ取得・操作を行う流れに統一する
- クライアントコンポーネントはインタラクションに専念させ、サーバー経由の呼び出し境界を明文化する
- 既存のプロフィール、イベント、タイムテーブル、管理機能が同等の体験で動作し、UIライブラリのデザインを維持することを確認する
- Requirements: 5.1,5.2,5.3,5.4,5.6,5.8,7.1,7.2,7.3,7.5,7.6
-
5.3 エラー体験と通知を統一する
- ユースケースからの失敗理由をUIで一貫した表示や再試行導線に落とし込み、想定外エラーを捕捉する仕組みを入れる
- 入力検証エラーと権限エラーで異なる挙動(再入力・リダイレクト等)を定義し、ユーザーが迷わないようにする
- Requirements: 5.7,5.8
-
6. 依存性ルールと静的検証を整備する
-
6.1 (P) レイヤー依存性チェックを自動化する
- ドメイン→アプリケーション→インフラ→プレゼンテーションの依存方向を守るための静的解析ルールを設定する
- プレゼンテーションからインフラ実装へ直接依存しないようパス制約を導入し、違反時にビルドを止める
- Requirements: 6.1,6.2,6.3,6.4
-
6.2 (P) 開発フローでのガードを導入する
- ポート未経由の依存や循環参照を検出するリンター/型設定を追加し、CIでも実行する
- パスエイリアスの解決と型チェックを強化し、設定漏れや誤参照を早期に検知する
- Requirements: 6.5,6.6,6.7
-
7. 段階的移行で既存機能を保護する
-
7.1 (P) パイロット移行を計画し実施する
- 小規模な機能をパイロットとして新アーキテクチャに載せ、旧構成との共存ポリシーとロールバック手順を明確にする
- パイロット完了時に関係者へ共有し、挙動変更があれば承認を取る
- Requirements: 7.9,9.1,9.2,9.3
-
7.2 全機能を新レイヤーへ移行しクリーンアップする
- イベント、タイムテーブル、管理、プロフィール各機能を順次新レイヤーに移し、Spindle UIを維持したまま動作確認する
- 旧インポートパスを新しいエイリアスへ更新し、移行済みコードの重複や未使用部分を除去する
- 移行完了後に旧構成への依存を断ち、クリーンな状態を保証する
- Requirements: 1.6,5.1,5.2,5.4,5.6,7.1,7.2,7.3,7.4,7.5,7.6,9.5,9.8
-
7.3 リグレッションとロールバックの検証を行う
- 主要ユーザーフロー(プロフィール、イベント登録、タイムテーブル、管理操作)がリファクタ前と同じ結果を返すことを確認する
- すべてのページがアクセス可能であることと、性能劣化がないことを検証する
- 段階ごとに戻せるブランチやタグを用意し、問題発生時に安全に戻せることを確認する
- Requirements: 7.7,7.8,9.4,9.6,9.7
-
8. テスト体系を整備し品質を担保する
-
8.1 (P) テスト基盤とカバレッジ計測を準備する
- Next.js 15と互換性のあるテストランナーとカバレッジツールを導入し、各レイヤーのテスト配置方針を決める
- テストコマンドをCIに組み込み、閾値設定で品質ゲートを用意する
- Requirements: 8.4,8.6,8.7
-
8.2 (P) ドメインのユニットテストを追加する
- 学年計算やステータス有効性などのビジネスロジックを外部依存なしで検証する
- 値オブジェクトのバリデーションが期待通りに失敗するケースも網羅する
- Requirements: 8.1,8.8
-
8.3 (P) アプリケーションユースケースのテストを実装する
- モックリポジトリを注入してユースケースの正常系・異常系を検証し、エラー分類が正しく返ることを確認する
- DTO変換のシリアライズ性をチェックし、境界でのデータ欠損を防ぐ
- Requirements: 8.2,8.5,8.8
-
8.4 (P) インフラ統合テストを実施する
- リポジトリ実装がデータソースと正しくやり取りできることを確認し、マッピングのずれを検出する
- トランザクション系のRPCが期待通りにコミット/ロールバックされることを検証する
- Requirements: 8.3
-
8.5 (P) 重要フローのE2Eを整備する
- プロフィール表示、イベント登録、管理操作、タイムテーブル表示などのクリティカルパスをE2Eでカバーする
- UI上のエラー表示やフィルタリング結果が期待通りであることを確認し、リグレッションの早期検知を図る
- Requirements: 7.7,7.8
-
9. 開発者体験とナレッジを整備する
-
9.1 (P) アーキテクチャガイドを整備する
- レイヤー責務と依存性ルールを説明するガイドを用意し、新しいユースケース追加時の手順と例を示す
- リポジトリ追加方法とディレクトリ配置規則をまとめ、各レイヤーに短いREADMEを配置する
- Requirements: 10.1,10.2,10.3,10.4
-
9.2 (P) 開発者オンボーディングを準備する
- 新規参加者がセットアップから主要フロー実行まで辿れるオンボーディング資料を整える
- 振る舞い変更が必要な場合の承認・通知プロセスを含め、運用上のガイドラインをまとめる
- Requirements: 10.5,10.7
-
9.3 (P) コード生成テンプレートとスクリプトを用意する
- 新しいエンティティ・ユースケース・リポジトリを作成するためのテンプレートやスクリプトを提供し、開発手順を標準化する
- Steering Contextを最新のアーキテクチャパターンに合わせて更新する
- Requirements: 10.6,10.7
技術調査レポート: Clean Architecture リファクタリング
調査概要
本調査は、Portal.CをClean Architectureへリファクタリングするための技術的実現可能性と実装パターンを検証することを目的としています。
1. Clean Architecture for Next.js 15 App Router
調査ソース
- Modern Full Stack Application Architecture Using Next.js 15+
- Next.js Clean Architecture GitHub Repository
- Clean Architecture in Next.js 14: A Practical Guide
- Next.js 15 Folder Structure Guide
主要な発見
レイヤー構造
src/domain/: ビジネスルール、エンティティ、値オブジェクト(外部依存なし)src/application/: ユースケース、ポートインターフェース、DTOsrc/infrastructure/: 外部サービスアダプター(DB、認証、API)src/presentation/またはapp/+components/: Next.js App Routerエントリーポイント
Next.js 15統合パターン
- Server Componentsがデフォルト: データ取得とレンダリングをサーバーで実行
- Client Componentsは選択的: インタラクティブ性が必要な箇所のみ
- Server Actions: レイヤー間通信の主要メカニズム(
use serverディレクティブ) - 境界の明確化:
use serverとuse clientディレクティブがレイヤー分離を強制
依存性ルール
- Server Componentsはデフォルトで、データベース操作や認証などをサーバーレイヤーで処理
- コンポーネントは直接データベースを呼び出さず、Server Actionsを介して実行
- 検証スキーマ(Zod)をクライアントとサーバー間で共有
ベストプラクティス
- レイアウトツリーを最初にモデル化
- Route Groupsを使用してURLをクリーンに保つ
- Server vs Clientの境界を明示的に
- クライアントJSを最小化し、データアクセスをサーバー(RSC)にプッシュ
推奨事項
app/ディレクトリをNext.js App Routerページとして保持src/配下にClean Architectureレイヤーを作成- Server ActionsをApplication層とPresentation層の橋渡しとして使用
- TypeScriptの厳密な型チェックを活用
2. 依存性注入 (Dependency Injection) パターン
調査ソース
- Clean Architecture Layering in Next.js with DI
- Dependency Injection with NextJS and TypeScript
- Managing Dependency Injection with Nextjs Apps
主要な発見
Feature Layer(ビジネスロジック)のDI
- UseCaseとRepositoryをインターフェースベースのバインディングで接続
- Adapter Patternに従い、ビジネスロジックをデータソースから分離
- 一意のDIキーを使用した型安全な依存性解決
export default interface UserRepository {
create(params: CreateUserParams): ApiTask<true>;
update(params: UpdateUserParams): ApiTask<true>;
delete(ids: string[]): ApiTask<true>;
}
export const userRepoKey = "userRepoKey";
Application Layer(React/Next.js統合)のDI
- MVVMパターンを実装
- ViewModelとViewをBridge Patternで接続
- Server ComponentからClient ComponentへのViewModel受け渡しに一意のVMキーを使用
モジュール登録ファクトリー
export default function userModule(di: DependencyContainer) {
di.register(userRepoKey, UserRepositoryImpl);
return di;
}
DIライブラリ選択肢
- TSyringe: TypeScript専用、デコレータベース、reflect-metadata必要
- Awilix: JavaScript/TypeScript両対応、軽量
- InversifyJS: TypeScript専用、機能豊富
- ioctopus: reflect-metadataなし、全ランタイム対応(推奨)
Next.js 15 Server Components対応
- 環境変数ベースの設定(T3 Env + Zod)
- 集中化されたORMインスタンス(Drizzle)
- Server ActionsをコンポーネントへのケイパビリティとしてInject
推奨事項
- 軽量DIアプローチ: ファクトリー関数パターン + インターフェースバインディング
- ioctopusまたはAwilixを推奨(Next.js Server Componentsと互換性が高い)
- インターフェースベースのDIキーを使用して型安全性を確保
- ドメインモジュールをDIファクトリーとして組織化
3. Supabase トランザクション処理
調査ソース
- Transactions and RLS in Supabase Edge Functions
- Supabase JavaScript API Reference - RPC
- Easy functions and transactions using Postgres + PostgREST
- Supabase TypeScript Support
主要な発見
トランザクションサポートの制約
- supabase-jsクライアントはトランザクションをサポートしない
- PostgRESTベースのため、クライアントサイドでのトランザクション境界は不可
推奨されるワークアラウンド
- PostgreSQL関数をRPC経由で呼び出す(推奨)
- データベースに複数のクエリをトランザクション内で実行するSQL関数を作成
- Edge FunctionまたはServer ActionからRPCで呼び出す
- 重要: PostgRESTはrpc()呼び出しを自動的にトランザクションでラップする
CREATE OR REPLACE FUNCTION register_for_event(
p_member_id UUID,
p_event_id UUID
)
RETURNS BOOLEAN AS $$
BEGIN
-- トランザクション内で複数操作を実行
INSERT INTO participations (member_id, event_id) VALUES (p_member_id, p_event_id);
UPDATE events SET participant_count = participant_count + 1 WHERE id = p_event_id;
RETURN TRUE;
EXCEPTION
WHEN OTHERS THEN
RETURN FALSE;
END;
$$ LANGUAGE plpgsql SECURITY INVOKER;
const { data, error } = await supabase.rpc('register_for_event', {
p_member_id: memberId,
p_event_id: eventId
});
-
Edge Functionsで直接データベースアクセス
- Edge FunctionsはサーバーサイドのためPostgRESTを経由せず直接データベースアクセス可能
- 純粋なSQLトランザクションを使用可能
-
ORM使用(Prisma等)
- トランザクションサポートが必要な場合、PrismaなどのORMを使用
TypeScript型サポート
- Supabase CLIで型生成:
supabase gen types typescript --project-id [id] > database.types.ts - RPC関数は戻り値型を自動的に推論
- null制約、生成カラムを検出
セキュリティベストプラクティス
- SECURITY INVOKERを使用(デフォルト、推奨)
- SECURITY DEFINERを使用する場合、search_pathを明示的に設定
推奨事項
- 複雑なユースケース: PostgreSQL関数をRPC経由で呼び出す
- 単純なCRUD: Supabase標準クエリを使用
- トランザクション境界はユースケースレベルで定義
- RPC関数の型安全性を確保(TypeScript型生成)
4. Server Components と Client Components のデータフロー
調査ソース
- Next.js Official Docs: Server and Client Components
- Client vs Server Components in Next.js 15 — A Deep Dive
- React Server Components in Next.js 15: A Deep Dive
- Next.js 15: Simplifying Server Data Fetching
主要な発見
コンポジションパターン(Server → Client)
- Server ComponentはClient Componentを含むことができる
- Client ComponentはServer Componentを直接含むことはできないが、
childrenプロップを通じて受け取ることは可能
// ✅ 許可: Server Component → Client Component
<ClientModal>
<ServerCart /> {/* childrenとして渡される */}
</ClientModal>
// ❌ 禁止: Client Component内で直接Server Componentをインポート
import ServerCart from './ServerCart'; // エラー
依存性フロールール
- Server Component → Client Component: ✅ 一般的なパターン
- Client Component → Server Component: ❌ 許可されない
- Server Component → Server Component: ✅ 完全サポート
- Client Component → Client Component: ✅ 完全サポート
Next.js 15のデータ取得
getServerSidePropsを非同期Server Componentパターンで置き換え- async/awaitを直接Server Component内で使用
- 自動キャッシングと再検証(
revalidateオプション)
アーキテクチャの特徴
- ストリーミングファーストのHTMLとデータの段階的配信
- コンポーネントレベルのコード分割(Server Componentsはクライアントに到達しない)
- 並列データ取得(複数の非同期操作を同時実行)
- コンポーネントおよびフェッチレベルの細粒度キャッシング
パフォーマンスの利点
- デフォルトでServer Componentsを使用し、サーバーでUIをレンダリングしてキャッシュ
- ブラウザの負荷を軽減し、パフォーマンスを向上
推奨事項
- Server Componentsをデフォルトとして使用
- データ取得はServer Components内で直接実行
- Client Componentsはインタラクティブな要素のみに制限
childrenパターンでServer ComponentsをClient Componentsに渡す- async/await構文でデータフローを直感的に
5. Repository パターン TypeScript 実装
調査ソース
- Clean Architecture in Node.js: Repository Pattern with TypeScript and Prisma
- Using Clean Architecture and Unit of Work Pattern
- TypeScript Clean Architecture GitHub
- Atomic Repositories in Clean Architecture
主要な発見
インターフェース設計戦略
- エンティティインターフェース: データモデル構造を定義(ITask, IProject)
- クエリパラメータインターフェース: ページネーションとフィルタリングロジックを処理
- リポジトリインターフェース: 利用可能なデータ操作を指定(list, get, create, update)
データマッピングアプローチ
- 各リポジトリにprivate
mapEntity()メソッドを含む - ORM結果をドメインインターフェースに変換
- レイヤー間の型一貫性を確保
interface IMemberRepository {
findById(id: string): Promise<Member | null>;
findAll(params: QueryParams): Promise<Member[]>;
create(member: Member): Promise<Member>;
update(id: string, member: Partial<Member>): Promise<Member>;
delete(id: string): Promise<void>;
}
class SupabaseMemberRepository implements IMemberRepository {
private mapToEntity(row: Database['public']['Tables']['members']['Row']): Member {
return {
id: row.id,
name: row.name,
// ... マッピングロジック
};
}
async findById(id: string): Promise<Member | null> {
const { data, error } = await this.client
.from('members')
.select('*')
.eq('id', id)
.single();
if (error || !data) return null;
return this.mapToEntity(data);
}
}
Mixinパターンを使用したリポジトリ構造
- BaseRepository: 共有されたクライアントアクセスとページネーションデフォルト
- AddEntityRepository: エンティティ固有の操作をMixin関数として
- ComposedRepository: Mixinを統一されたインスタンスに結合
Clean Architectureの利点
- 関心の分離を促進
- テスタビリティを向上
- データレイヤーの交換を容易化
推奨事項
- Application層でリポジトリインターフェースを定義
- Infrastructure層で具体的な実装を提供
- データマッパーメソッドでDB型↔ドメインエンティティ変換
- 型安全性を確保(TypeScriptの厳密な型)
- 汎用リポジトリよりも専用リポジトリパターンを優先
6. アーキテクチャ決定記録 (ADR)
ADR-001: レイヤー構造
決定: src/配下にdomain/, application/, infrastructure/, presentation/の4層を作成
根拠:
- Clean Architectureの標準的なレイヤー分離
- Next.js 15 App Routerとの互換性
- テスタビリティと保守性の向上
代替案:
- Hexagonal Architecture(ポート&アダプター): より複雑、オーバーエンジニアリングの懸念
- 3層アーキテクチャ: レイヤー分離が不十分
ADR-002: 依存性注入メカニズム
決定: 軽量ファクトリーパターン + インターフェースバインディング(ioctopus または カスタム実装)
根拠:
- Next.js 15 Server Componentsとの互換性
- reflect-metadata不要(全ランタイム対応)
- Tree-shaking対応でバンドルサイズ最小化
- 学習曲線が緩やか
代替案:
- TSyringe: reflect-metadata必要、Next.js Server Componentsと互換性の問題
- InversifyJS: 重量級、複雑なセットアップ
ADR-003: トランザクション処理戦略
決定: PostgreSQL関数をRPC経由で呼び出す
根拠:
- supabase-jsはトランザクション未サポート
- PostgRESTがrpc()を自動的にトランザクションでラップ
- RLS(Row Level Security)との統合が容易
- 型安全性(TypeScript型生成)
代替案:
- Edge Functionsで直接データベースアクセス: 複雑性増加、RLS統合が困難
- ORMの追加(Prisma): 技術スタック増加、学習コスト
ADR-004: Server/Client Component 分離戦略
決定: Server Componentsをデフォルト、Client Componentsはuse clientで明示的に
根拠:
- Next.js 15のベストプラクティス
- パフォーマンス最適化(サーバーレンダリング)
- データ取得の直感性(async/await)
- バンドルサイズ削減
代替案:
- すべてClient Components: パフォーマンス悪化、バンドルサイズ増大
- 手動でのスプリット: 複雑性増加、一貫性の欠如
ADR-005: リポジトリパターン実装
決定: 専用リポジトリ(エンティティごと)+ データマッパー
根拠:
- 明確な責務分離
- 型安全性の確保
- Supabaseクエリビルダーとの統合が容易
- テストしやすい
代替案:
- 汎用リポジトリ: 型安全性が低い、ビジネスロジックの表現が困難
- Active Recordパターン: ドメイン層とインフラ層の混在
7. リスクと軽減策
技術的リスク
リスク 1: Next.js 15 Server ComponentsとDIの統合複雑性
- 影響: 中
- 軽減策:
- パイロット機能(メンバー一覧)で最初に検証
- ioctopusまたはシンプルなファクトリーパターンを使用
- 公式ドキュメントとコミュニティパターンを参照
リスク 2: Supabaseトランザクション制約
- 影響: 中
- 軽減策:
- PostgreSQL関数をRPC経由で呼び出す戦略を採用
- 段階2で実装パターンを確立
- 型安全性を確保(TypeScript型生成)
リスク 3: Server/Client Componentデータシリアライゼーション
- 影響: 低〜中
- 軽減策:
- DTOを使用してシリアライズ可能な型のみを渡す
- Date型はISO文字列に変換
- Next.js公式ドキュメントのベストプラクティスに従う
プロジェクトリスク
リスク 4: チームの学習曲線
- 影響: 中
- 軽減策:
- 段階的移行により各段階で学習
- アーキテクチャドキュメントとガイドライン作成
- コードレビューとペアプログラミング
リスク 5: 並行開発期間の複雑性
- 影響: 中
- 軽減策:
- 既存コードを破壊しない
- 新機能は新レイヤーで実装
- 明確なマイグレーション計画(7段階)
8. 未解決の調査項目
実装段階での検証が必要な項目
-
エンティティ実装方式
- クラスベース vs インターフェース+純粋関数
- テスタビリティと保守性のトレードオフ
- 推奨: パイロット機能で両方を試し、チームの嗜好に基づいて決定
-
キャッシング戦略
- Next.js 15のキャッシング機能との統合
- リポジトリレベルのキャッシング vs ユースケースレベルのキャッシング
- 推奨: 段階5以降で性能要件に基づいて実装
-
エラーハンドリング標準化
- ドメインエラー、アプリケーションエラー、インフラエラーの分類
- Result型 vs Exception
- 推奨: 段階2-3でエラー型システムを確立
-
テストフレームワーク選定
- Jest vs Vitest
- モックライブラリ選定
- 推奨: 段階7で決定、Next.js 15との互換性を考慮
9. 推奨実装アプローチ
ハイブリッドアプローチ(Option C)
段階1: 基盤整備
- ディレクトリ構造作成(src/domain, application, infrastructure)
- tsconfig.jsonパスエイリアス設定
- 軽量DIメカニズム実装(ファクトリーパターン)
段階2: ドメイン層
- エンティティ実装(Member, Event, Timetable)
- 値オブジェクト実装(Email, StudentId, EventCapacity)
- 既存types/index.tsのビジネスロジックを移行
段階3: アプリケーション層
- リポジトリインターフェース定義
- DTO定義
- パイロットユースケース実装(GetMemberProfile, ListMembers)
段階4: インフラストラクチャ層
- リポジトリ実装(SupabaseMemberRepository)
- データマッパー実装
- RPC関数作成(必要に応じて)
段階5: プレゼンテーション層統合
- パイロットページ(メンバー一覧)をユースケース統合
- Server Actions実装
- エラーハンドリング統合
段階6: 全機能移行
- 残機能の移行(イベント、時間割、管理画面)
- モックデータを実データに置き換え
段階7: テストとドキュメント
- ユニットテスト実装
- インテグレーションテスト
- アーキテクチャドキュメント作成
10. まとめ
技術的実現可能性: ✅ 高い
根拠:
- Next.js 15はClean Architectureパターンをサポート
- 依存性注入の軽量実装パターンが確立
- Supabaseトランザクションの実用的ワークアラウンド存在
- Server/Client Componentsのデータフロー明確
- リポジトリパターンのTypeScript実装パターン豊富
推奨技術スタック
- レイヤー構造: Clean Architecture 4層(Domain, Application, Infrastructure, Presentation)
- DI: 軽量ファクトリーパターン(ioctopusまたはカスタム)
- トランザクション: PostgreSQL関数 + RPC
- データフロー: Server Componentsデフォルト + Server Actions
- リポジトリ: 専用リポジトリ + データマッパー
次のステップ
- 要件の最終承認
- 技術設計ドキュメント生成(design.md)
- タスク分解とマイルストーン設定
- パイロット機能の実装開始
ギャップ分析: Clean Architecture リファクタリング
1. 現状調査
1.1 既存コードベースの構造
ディレクトリレイアウト
Portal.C/
├── app/ # Next.js 15 App Router ページ
│ ├── admin/ # 管理画面
│ ├── events/ # イベント一覧ページ
│ ├── members/ # メンバー一覧ページ
│ ├── profile/ # プロフィール編集ページ
│ ├── timetable/ # 時間割ページ
│ ├── layout.tsx # ルートレイアウト
│ ├── page.tsx # ホームページ
│ └── api/auth/ # NextAuth APIルート
├── components/ # UIコンポーネント
│ ├── layout/Navigation.tsx
│ └── MatterHero.tsx
├── lib/ # ユーティリティとクライアント
│ ├── auth.ts # 認証ヘルパー
│ ├── auth-options.ts # NextAuth設定
│ ├── utils.ts # 汎用ユーティリティ
│ └── supabase/ # Supabaseクライアント
│ ├── client.ts # ブラウザクライアント
│ ├── server.ts # サーバークライアント
│ ├── admin.ts # 管理者クライアント
│ └── middleware.ts # ミドルウェア
├── types/ # 型定義
│ ├── database.types.ts # Supabase自動生成型
│ └── index.ts # アプリケーション型定義 + ビジネスロジック
└── supabase/migrations/ # データベーススキーマ
├── 20241216000001_create_members_table.sql
├── 20241216000002_create_tags_table.sql
├── 20241216000003_create_events_table.sql
└── 20241216000004_create_timetables_table.sql
再利用可能な資産
1. データベーススキーマ(完全構築済み)
- membersテーブル: ZITADEL ID統合、学年自動計算関数、RLS(Row Level Security)設定済み
- tagsテーブル: スキル・興味タグ管理
- eventsテーブル: イベント情報、参加者管理
- timetablesテーブル: メンバーの時間割情報
2. 認証基盤(設定完了)
- ZITADEL OIDC統合(lib/auth-options.ts)
- NextAuth.js設定
- ロールベースアクセス制御(admin ロール対応)
- セッション管理
3. Supabaseクライアント(4種類)
- ブラウザクライアント(lib/supabase/client.ts)
- サーバークライアント(lib/supabase/server.ts)
- 管理者クライアント(lib/supabase/admin.ts)
- ミドルウェアクライアント(lib/supabase/middleware.ts)
4. 型定義システム
- Supabase自動生成型(types/database.types.ts)
- アプリケーション型(types/index.ts): Member, Event, Timetable, Participation
5. UIコンポーネント
- Spindle UI統合(@openameba/spindle-ui)
- Tailwind CSS設定
- レイアウトコンポーネント(Navigation)
- ページコンポーネント(会員、イベント、時間割、管理画面)
アーキテクチャパターンと制約
現在のパターン
- 標準的なNext.js構造: app/ディレクトリによるファイルベースルーティング
- 直接的なデータアクセス: UIコンポーネントから直接Supabaseクライアントを呼び出す想定(現在はモックデータ)
- 型定義とビジネスロジックの混在: types/index.tsに
calculateGrade(),isStatusValid()などのビジネスロジックが含まれる - レイヤー分離なし: プレゼンテーション、ビジネスロジック、データアクセスが明確に分離されていない
技術的制約
- Next.js 15 App Routerの使用が必須
- Supabaseをデータベースとして使用
- ZITADELを認証基盤として使用
- TypeScript strict mode有効
命名規則
- コンポーネント: PascalCase(Navigation.tsx, MatterHero.tsx)
- ユーティリティ: camelCase(utils.ts, auth.ts)
- 型定義: PascalCase(Member, Event)
インポートパターン
- 絶対パスインポート:
@/エイリアス使用 - 例:
import type { Member } from "@/types"
1.2 統合ポイント
データモデル/スキーマ
- PostgreSQL(Supabase)スキーマ完全定義
- 学年自動計算はデータベース関数で実装済み
- Row Level Security(RLS)設定済み
- TypeScript型は自動生成可能
認証メカニズム
- ZITADEL OIDC provider
- NextAuth.jsによるセッション管理
- JWT内にロール情報を含む
- RLSとの統合(auth.jwt())
外部API/サービス
- Supabase API(データベース、認証、ストレージ)
- ZITADEL(認証プロバイダー)
2. 要件実現可能性分析
2.1 技術的ニーズ(EARS要件からの抽出)
データモデル
- ✅ Memberエンティティ: データベーススキーマ、型定義完備
- ✅ Eventエンティティ: データベーススキーマ、型定義完備
- ✅ Timetableエンティティ: データベーススキーマ、型定義完備
- ✅ 値オブジェクト候補: Email, StudentId, EventCapacity(実装は未)
API/サービス
- ✅ Supabaseクライアント: 4種類のクライアント実装済み
- ✅ 認証サービス: ZITADEL統合完了
- ❌ リポジトリインターフェース: 未実装
- ❌ ユースケース: 未実装
UI/コンポーネント
- ✅ ページコンポーネント: 全ページ実装済み(モックデータ使用)
- ✅ UIライブラリ: Spindle UI導入済み
- ⚠️ データバインディング: 現在はモックデータ、実データ統合が必要
ビジネスルール/バリデーション
- ⚠️ 学年計算: データベース関数とTypeScript関数に重複実装
- ⚠️ ステータス有効性チェック: TypeScript関数のみ(types/index.ts)
- ❌ 値オブジェクトバリデーション: 未実装
- ❌ ドメインルール: エンティティ内にカプセル化されていない
非機能要件
セキュリティ
- ✅ Row Level Security設定済み
- ✅ ロールベースアクセス制御
- ⚠️ 入力バリデーション: フロントエンドのみ、サーバーサイド強化が必要
パフォーマンス
- ✅ データベースインデックス設定済み
- ❌ クエリ最適化: リポジトリパターンで実装予定
- ❌ キャッシング: 未実装
スケーラビリティ
- ✅ Supabase(PostgreSQL)でスケーラブル
- ✅ Vercelホスティングでスケーラブル
信頼性
- ⚠️ トランザクション境界: ユースケース層で定義予定
- ❌ エラーハンドリング: 統一されたエラー処理が必要
2.2 ギャップと制約の特定
欠落機能
1. ドメイン層(完全欠如)
- エンティティクラス/インターフェース
- 値オブジェクト
- ドメインサービス
- ビジネスルールのカプセル化
2. アプリケーション層(完全欠如)
- ユースケース実装
- ポートインターフェース(リポジトリ、サービス)
- DTO(データ転送オブジェクト)
- アプリケーションサービス
3. インフラストラクチャ層(部分的実装)
- ✅ Supabaseクライアント存在
- ❌ リポジトリ実装
- ❌ データマッパー(DB型 ↔ ドメインエンティティ変換)
- ❌ 依存性注入メカニズム
4. プレゼンテーション層(部分的実装)
- ✅ ページコンポーネント存在
- ❌ ユースケース統合
- ❌ Server Actions(Next.js 15推奨パターン)
- ❌ 統一されたエラー表示
5. テスト基盤(未実装)
- ユニットテストフレームワーク
- インテグレーションテスト
- モック/スタブ実装
調査が必要な項目
1. 依存性注入(DI)の実装方法
- 選択肢:
- ファクトリー関数パターン(軽量)
- DIコンテナライブラリ(TSyringe, InversifyJS)
- Next.js App Routerネイティブパターン
- 調査ポイント: Next.js 15 Server Componentsとの相性、パフォーマンス影響
2. トランザクション処理
- 調査ポイント: Supabaseでのトランザクション実装方法、ユースケース境界での実装パターン
3. Server ComponentsとClient Componentsのデータ転送
- 調査ポイント: DTOのシリアライゼーション、Date型の扱い、エラー伝播
4. エンティティ実装方式
- 選択肢:
- クラスベース(メソッド含む)
- インターフェース + 純粋関数
- 調査ポイント: TypeScriptでの推奨パターン、テスタビリティ
5. リポジトリインターフェースの粒度
- 調査ポイント: 汎用リポジトリ vs 専用リポジトリ、Supabaseクエリビルダーとの統合
既存アーキテクチャからの制約
1. Next.js App Routerの制約
- ファイルベースルーティング(app/ディレクトリ)必須
- Server ComponentsとClient Componentsの分離
- Server Actionsの使用推奨
2. Supabaseの制約
- PostgreSQL専用(NoSQL非対応)
- RLSによるアクセス制御
- リアルタイムサブスクリプション機能
3. ZITADEL統合
- OIDC標準準拠
- JWT内にロール情報を格納
- NextAuth.jsとの統合
2.3 複雑性の指標
機能タイプ
- ドメインロジック: 中程度(学年計算、ステータス有効性チェック、イベント参加管理)
- データアクセス: 標準的CRUD + RLS統合
- 外部統合: 認証(ZITADEL)、データベース(Supabase)
- ワークフロー: シンプル(メンバー登録、イベント参加、プロフィール更新)
アーキテクチャの複雑性
- レイヤー数: 4層(Domain, Application, Infrastructure, Presentation)
- 抽象化レベル: 高(ポート/アダプター、依存性逆転)
- 新規パターン: リポジトリパターン、ユースケースパターン、依存性注入
3. 実装アプローチオプション
Option A: 既存コンポーネントの拡張
該当しない理由: Clean Architectureへのリファクタリングは、既存の構造を根本的に変更する必要があり、単なる拡張では実現不可能。
評価: ❌ 適用不可
Option B: 新規コンポーネント作成
アプローチ: 既存コードを保持したまま、完全に新しいレイヤー構造(src/domain/, src/application/, src/infrastructure/)を作成し、段階的に機能を移行。
新規作成の根拠
- Clean Architectureは既存の構造と根本的に異なる
- レイヤー分離の原則に従うには、新しいディレクトリ構造が必須
- 既存コードとの並行運用により、段階的移行が可能
統合ポイント
- app/ディレクトリ: プレゼンテーション層として保持、新しいユースケースを呼び出す
- lib/supabase/: 新しいリポジトリ実装のアダプターとして使用
- types/: ドメインエンティティ定義に段階的に移行
責任境界
- src/domain/: ビジネスルール、エンティティ、値オブジェクト(外部依存なし)
- src/application/: ユースケース、ポートインターフェース、DTO
- src/infrastructure/: リポジトリ実装、Supabase統合、ZITADEL統合
- app/ + components/: プレゼンテーション層(ユースケースを呼び出す)
トレードオフ
- ✅ クリーンな分離、テストしやすい
- ✅ 段階的移行が可能
- ✅ 既存機能を壊さない
- ❌ ディレクトリ数増加、初期学習コスト
- ❌ 並行期間中のコード重複
評価: ✅ 推奨される基本アプローチ
Option C: ハイブリッドアプローチ(推奨)
アプローチ: Option Bをベースに、既存の安定した資産(Supabaseクライアント、ZITADEL設定、UIコンポーネント)を活用しながら、段階的に新しいレイヤーを導入。
組み合わせ戦略
段階1: 基盤整備(Week 1)
- 新しいディレクトリ構造作成(src/domain/, src/application/, src/infrastructure/)
- tsconfig.jsonパスエイリアス設定
- 依存性注入メカニズム選定・実装
段階2: ドメイン層(Week 1-2)
- エンティティ実装(Member, Event, Timetable)
- 値オブジェクト実装(Email, StudentId, EventCapacity)
- ドメインサービス(必要に応じて)
- 既存資産活用: types/index.tsのビジネスロジックを移行
段階3: アプリケーション層(Week 2)
- ポートインターフェース定義(IMemberRepository, IEventRepository等)
- DTO定義
- 基本ユースケース実装(1-2個のパイロットユースケース)
段階4: インフラストラクチャ層(Week 2-3)
- リポジトリ実装(SupabaseMemberRepository等)
- データマッパー(DB型 ↔ ドメインエンティティ変換)
- 既存資産活用: lib/supabase/クライアントをアダプターとして使用
段階5: プレゼンテーション層統合(Week 3)
- パイロットページ(例: メンバー一覧)をユースケース統合
- Server Actions実装
- エラーハンドリング統合
- 既存資産活用: 既存のUIコンポーネントとSpindle UI
段階6: 全機能移行(Week 3-4)
- 残りの機能(イベント、時間割、管理画面)を移行
- モックデータを実データに置き換え
- 既存資産活用: 既存のページ構造とルーティング
段階7: テストとドキュメント(Week 4)
- ユニットテスト実装
- インテグレーションテスト
- アーキテクチャドキュメント作成
- 開発者オンボーディングガイド
段階的実装の詳細
パイロット機能選定: メンバー一覧ページ
- シンプルなCRUD操作
- 既存のUIコンポーネント活用可能
- 学習曲線が緩やか
移行戦略:
- 新しいレイヤーでメンバー一覧機能を完全実装
- 既存のapp/members/page.tsxをリファクタリング
- 動作確認・フィードバック収集
- 他の機能に適用
リスク軽減策
技術的リスク:
- DI実装の複雑性: パイロット機能で検証後、パターン確立
- Server Components統合: Next.js 15公式ドキュメント参照、コミュニティパターン調査
- トランザクション処理: Supabaseドキュメント参照、段階2で調査完了
プロジェクトリスク:
- 段階的移行: 各段階で動作確認、必要に応じてロールバック可能
- 並行開発: 既存コードを破壊しない、新機能追加は新レイヤーで実装
- 知識共有: 段階ごとにドキュメント更新、チームレビュー実施
トレードオフ
- ✅ バランスの取れたアプローチ
- ✅ 既存資産を最大限活用
- ✅ リスク分散(段階的移行)
- ✅ 各段階でフィードバック可能
- ❌ 計画の複雑性
- ❌ 段階間の調整が必要
評価: ⭐ 強く推奨 - 最もバランスが取れた実装アプローチ
4. 実装の複雑性とリスク
工数見積もり
工数: XL (3-4週間、約26-41日)
内訳
- 基盤整備: 2-3日(ディレクトリ構造、DI、設定)
- ドメイン層: 5-7日(エンティティ、値オブジェクト、サービス)
- アプリケーション層: 4-5日(ユースケース、ポート、DTO)
- インフラストラクチャ層: 5-7日(リポジトリ、データマッパー、統合)
- プレゼンテーション層: 4-5日(Server Actions、統合、エラーハンドリング)
- 全機能移行: 3-5日(残機能の移行、モックデータ置き換え)
- テストとドキュメント: 3-5日(ユニット/統合テスト、ドキュメント)
- バッファ: 2-4日(予期しない問題対応)
合計: 26-41日(1人、フルタイム換算)
リスク評価
リスク: Medium
リスク要因
技術的未知数(Medium リスク):
- Next.js 15 App Routerでの依存性注入パターン
- Supabaseトランザクション処理
- Server ComponentsとClient Componentsのデータ転送
軽減策:
- 段階1で技術調査とパイロット実装
- Next.js 15公式ドキュメントとコミュニティベストプラクティス参照
- Supabaseドキュメントとサンプルコード調査
アーキテクチャ変更の影響(Medium リスク):
- 既存コードとの共存期間
- チームの学習曲線
- パターンの一貫性
軽減策:
- 段階的移行により影響を最小化
- 各段階でコードレビューとペアプログラミング
- アーキテクチャドキュメントとガイドライン作成
データ統合(Low リスク):
- データベーススキーマ完全構築済み
- Supabaseクライアント動作確認済み
軽減策:
- 既存のデータベーススキーマとクライアントを活用
- データマッパーで型安全性を確保
パフォーマンス(Low リスク):
- レイヤー追加によるオーバーヘッド
- 不適切なクエリパターン
軽減策:
- リポジトリパターンでクエリ最適化
- 必要に応じてキャッシング導入
- パフォーマンステスト実施
成功のための鍵
- 段階的アプローチ: 各段階で動作確認とフィードバック
- 既存資産活用: データベーススキーマ、認証、UIコンポーネント
- 明確なドキュメント: アーキテクチャガイド、コーディング規約
- 継続的レビュー: コードレビュー、ペアプログラミング
- テスト駆動: ドメイン層とアプリケーション層のユニットテスト
5. 要件-資産マッピング
Requirement 1: ディレクトリ構造とレイヤー分離
| 受入基準 | 既存資産 | ギャップ | タグ |
|---|---|---|---|
| src/ディレクトリ作成 | なし | 新規作成が必要 | Missing |
| domain/, application/, infrastructure/, presentation/作成 | なし | 新規作成が必要 | Missing |
| app/ディレクトリ保持 | ✅ 既存 | プレゼンテーション層として再定義 | Refactor |
| components/ディレクトリ保持 | ✅ 既存 | プレゼンテーション層として再定義 | Refactor |
| lib/, types/から移行 | ✅ 既存 | 適切なレイヤーへ移行が必要 | Refactor |
| tsconfig.jsonパスエイリアス | ⚠️ 部分的(@/のみ) | レイヤー別エイリアス追加 | Extend |
推奨アプローチ: Option C - 新規ディレクトリ作成 + 既存ディレクトリ活用
Requirement 2: ドメインレイヤーの設計
| 受入基準 | 既存資産 | ギャップ | タグ |
|---|---|---|---|
| エンティティ定義(Member, Event, Timetable) | ⚠️ types/index.ts(型定義のみ) | クラス/インターフェース実装が必要 | Missing |
| 外部依存なしの実装 | ❌ 現在ビジネスロジック混在 | 純粋なドメインロジックに分離 | Missing |
| 値オブジェクト(Email, StudentId等) | ❌ なし | 新規実装が必要 | Missing |
| イミュータビリティとバリデーション | ❌ なし | 値オブジェクトに実装 | Missing |
| ドメインサービス | ❌ なし | 必要に応じて実装 | Missing |
| レイヤー依存ルール | ❌ 現在制約なし | TypeScript設定で強制 | Missing |
| ビジネスルールバリデーション | ⚠️ calculateGrade, isStatusValid存在 | エンティティ内にカプセル化 | Refactor |
推奨アプローチ: Option B - 新規作成(既存のビジネスロジックを移行)
Requirement 3: アプリケーションレイヤーの設計
| 受入基準 | 既存資産 | ギャップ | タグ |
|---|---|---|---|
| ユースケースクラス | ❌ なし | 新規実装が必要 | Missing |
| 単一責務とexecute()メソッド | ❌ なし | パターン確立が必要 | Missing |
| ポートインターフェース | ❌ なし | 新規定義が必要 | Missing |
| DTO定義 | ❌ なし | 新規定義が必要 | Missing |
| ドメイン層のみに依存 | ❌ 現在制約なし | レイヤールール強制 | Missing |
| 依存性逆転の原則 | ❌ なし | DI実装が必要 | Unknown |
| エラーハンドリング | ⚠️ 部分的 | 統一されたエラー型が必要 | Missing |
| トランザクション境界 | ❌ なし | 実装パターン調査が必要 | Unknown |
推奨アプローチ: Option B - 新規作成(調査項目あり)
調査項目:
- Next.js 15での依存性注入パターン
- Supabaseトランザクション処理方法
Requirement 4: インフラストラクチャレイヤーの設計
| 受入基準 | 既存資産 | ギャップ | タグ |
|---|---|---|---|
| リポジトリ実装 | ❌ なし | 新規実装が必要 | Missing |
| ポートインターフェース実装 | ❌ なし | アプリケーション層定義後に実装 | Missing |
| Supabaseクライアント設定 | ✅ lib/supabase/(4種類) | アダプターとして活用 | Extend |
| ZITADEL認証プロバイダー | ✅ lib/auth-options.ts | アダプターとして活用 | Extend |
| DB型↔ドメインエンティティ変換 | ❌ なし | データマッパー実装が必要 | Missing |
| エラー変換 | ⚠️ 部分的 | 標準化されたエラー型に変換 | Missing |
| 外部API統合 | ⚠️ 必要に応じて | 現時点では不要 | N/A |
| 依存性注入 | ❌ なし | DI実装が必要 | Unknown |
推奨アプローチ: Option C - 既存Supabaseクライアント活用 + 新規リポジトリ実装
Requirement 5: プレゼンテーションレイヤーの設計
| 受入基準 | 既存資産 | ギャップ | タグ |
|---|---|---|---|
| app/ディレクトリ保持 | ✅ 既存 | ユースケース統合が必要 | Refactor |
| components/ディレクトリ保持 | ✅ 既存 | UIロジックのみに制限 | Refactor |
| サーバーコンポーネント | ⚠️ 一部実装 | ユースケース呼び出しに変更 | Refactor |
| クライアントコンポーネント | ⚠️ 一部実装 | インタラクティブUIのみに制限 | Refactor |
| ユースケース/DTO通信 | ❌ 現在直接データアクセス | 統合が必要 | Missing |
| データベース/認証直接呼び出し禁止 | ❌ 現在想定 | パターン変更が必要 | Constraint |
| Server Actions | ❌ なし | Next.js 15推奨パターン実装 | Missing |
| エラー表示 | ⚠️ 部分的 | 統一されたエラーUI | Missing |
推奨アプローチ: Option C - 既存ページ/コンポーネント活用 + ユースケース統合
Requirement 6: 依存性ルールの遵守
| 受入基準 | 既存資産 | ギャップ | タグ |
|---|---|---|---|
| ドメイン層独立性 | ❌ 現在制約なし | レイヤー分離が必要 | Missing |
| アプリケーション層依存ルール | ❌ 現在制約なし | レイヤー分離が必要 | Missing |
| インフラストラクチャ層依存ルール | ❌ 現在制約なし | レイヤー分離が必要 | Missing |
| プレゼンテーション層依存ルール | ❌ 現在制約なし | レイヤー分離が必要 | Missing |
| 依存性逆転の原則 | ❌ なし | ポート/アダプターパターン実装 | Missing |
| TypeScript/リンター設定 | ⚠️ 基本設定のみ | レイヤー依存ルール強制設定 | Missing |
| ビルド/リント時エラー検出 | ❌ なし | 設定強化が必要 | Missing |
推奨アプローチ: Option B - 新規実装(TypeScript設定とリンター強化)
Requirement 7: 既存機能の保持
| 受入基準 | 既存資産 | ギャップ | タグ |
|---|---|---|---|
| メンバー管理機能 | ✅ UI実装済み(モック) | 実データ統合が必要 | Refactor |
| イベント管理機能 | ✅ UI実装済み(モック) | 実データ統合が必要 | Refactor |
| タイムテーブル機能 | ✅ UI実装済み(モック) | 実データ統合が必要 | Refactor |
| 認証機能 | ✅ ZITADEL統合完了 | 新レイヤーとの統合 | Extend |
| 管理者機能 | ✅ UI実装済み | 実データ統合が必要 | Refactor |
| データベーススキーマ | ✅ 完全構築済み | そのまま使用 | ✓ Ready |
| 回帰テスト | ❌ なし | テスト実装が必要 | Missing |
推奨アプローチ: Option C - 既存UI活用 + 新レイヤー統合
Requirement 8-10(テスタビリティ、マイグレーション、ドキュメント)
| 要件エリア | 既存資産 | ギャップ | タグ |
|---|---|---|---|
| テストフレームワーク | ❌ なし | Jest/Vitest導入が必要 | Missing |
| ユニットテスト | ❌ なし | ドメイン/アプリケーション層実装 | Missing |
| 統合テスト | ❌ なし | リポジトリ/ユースケーステスト実装 | Missing |
| マイグレーション計画 | ❌ なし | 7段階計画作成済み | ✓ Planned |
| アーキテクチャドキュメント | ❌ なし | 作成が必要 | Missing |
| 開発者ガイド | ❌ なし | 作成が必要 | Missing |
| コード生成テンプレート | ❌ なし | 作成推奨 | Missing |
推奨アプローチ: Option B - 新規作成(段階7で実装)
6. まとめ
現状とギャップの要約
Portal.Cは、データベーススキーマと認証システムが完全に構築されているものの、アーキテクチャ層の分離が存在しない標準的なNext.jsアプリケーションです。Clean Architectureへのリファクタリングには、以下の主要ギャップが存在します:
- ドメイン層: 完全欠如(エンティティ、値オブジェクト、サービス)
- アプリケーション層: 完全欠如(ユースケース、ポート、DTO)
- インフラストラクチャ層: 部分的実装(クライアント存在、リポジトリなし)
- プレゼンテーション層: 部分的実装(UI存在、統合なし)
- テスト基盤: 未実装
一方で、以下の技術的資産が活用可能:
- ✅ Supabaseデータベーススキーマ完全構築
- ✅ ZITADEL認証統合完了
- ✅ 型定義システム整備済み
- ✅ UIコンポーネント実装済み
推奨アプローチ
Option C: ハイブリッドアプローチ(段階的移行)を強く推奨します。
理由:
- 既存の安定した資産(データベース、認証、UI)を最大限活用
- 段階的移行によりリスクを最小化
- 各段階で動作確認とフィードバックが可能
- チームの学習曲線を緩やか化
7段階の移行計画:
- 基盤整備(ディレクトリ、DI、設定)
- ドメイン層(エンティティ、値オブジェクト)
- アプリケーション層(ユースケース、ポート、DTO)
- インフラストラクチャ層(リポジトリ、データマッパー)
- プレゼンテーション層統合(パイロット機能)
- 全機能移行(残機能の移行)
- テストとドキュメント
工数とリスク
- 工数: XL (3-4週間、約26-41日)
- リスク: Medium(技術的未知数はあるが軽減策明確)
デザインフェーズでの優先調査項目
- 依存性注入: Next.js 15での実装パターン(ファクトリー vs DIコンテナ)
- トランザクション処理: Supabaseでの実装方法
- データ転送: Server Components ↔ Client Componentsのベストプラクティス
- エンティティ実装: クラスベース vs インターフェース+関数
- リポジトリ粒度: 汎用 vs 専用リポジトリパターン
成功のための鍵
- 段階的アプローチ: 各段階で検証とフィードバック
- 既存資産活用: データベース、認証、UIを最大限利用
- 明確なドキュメント: アーキテクチャガイド、規約
- 継続的レビュー: コードレビュー、ペアプログラミング
- テスト駆動: ドメイン層・アプリケーション層のユニットテスト
次のステップ: /kiro:spec-design clean-architecture-refactor を実行して、技術設計ドキュメントを生成してください。
Settings
.kiro/settings/は、Spec-Driven Development (SDD)フレームワークの設定ファイルを管理します。これらの設定は、AI開発エージェント(Claude Code、Cursor、Codex、Geminiなど)がプロジェクトの標準に沿った開発を行うためのルールとテンプレートを定義しています。
構成
Rules
開発プロセスにおける各フェーズのルールと原則を定義
- Design Discovery (Full) - 完全版の設計発見プロセス
- Design Discovery (Light) - 軽量版の設計発見プロセス
- Design Principles - 設計の原則
- Design Review - 設計レビューのガイドライン
- EARS Format - 要件記述フォーマット
- Gap Analysis - ギャップ分析の手法
- Steering Principles - ステアリングの原則
- Tasks Generation - タスク生成のルール
- Tasks Parallel Analysis - タスク並列分析
Templates
仕様書やステアリング文書のテンプレート
Specs Templates
- Design Template - 設計書テンプレート
- Requirements Template - 要件定義テンプレート
- Requirements Init Template - 要件初期化テンプレート
- Research Template - 調査テンプレート
- Tasks Template - タスクテンプレート
Steering Templates
- Product Template - プロダクトステアリングテンプレート
- Tech Template - 技術ステアリングテンプレート
- Structure Template - 構造ステアリングテンプレート
Custom Steering Templates
- API Standards - API標準テンプレート
- Authentication - 認証テンプレート
- Database - データベーステンプレート
- Deployment - デプロイテンプレート
- Error Handling - エラーハンドリングテンプレート
- Security - セキュリティテンプレート
- Testing - テストテンプレート
使用方法
これらの設定ファイルは、以下のAI開発ツールで使用されます:
- Claude Code (
.claude/commands/kiro/,.claude/agents/kiro/) - Cursor IDE (
.cursor/commands/kiro/) - Codex CLI (
.codex/prompts/) - Gemini CLI (
.gemini/commands/kiro/) - GitHub Copilot (
.github/prompts/)
各ツールは、これらの設定を参照して一貫した開発プロセスを実現します。
Rules
SDDフレームワークにおける各フェーズのルールと原則を定義します。これらのルールは、AI開発エージェントが一貫性のある高品質な開発を行うためのガイドラインです。
Design Rules
Design Discovery (Full)
完全版の設計発見プロセス。既存コードベースの詳細な分析と、新機能との統合方法を検討します。
Design Discovery (Light)
軽量版の設計発見プロセス。小規模な変更や明確な要件に対して使用します。
Design Principles
設計の基本原則。SOLID原則、Clean Architecture、DRYなどの設計パターンを定義します。
Design Review
設計レビューのチェックリストとガイドライン。設計の品質を保証するためのレビュー項目です。
Requirements Rules
EARS Format
要件記述フォーマット(Easy Approach to Requirements Syntax)。明確で検証可能な要件を記述するためのルールです。
Gap Analysis
既存コードベースと新要件のギャップを分析する手法。影響範囲と実装戦略を明確にします。
Steering Rules
Steering Principles
ステアリング文書の作成原則。プロジェクト全体のガイドラインを定義する際のルールです。
Tasks Rules
Tasks Generation
実装タスクの生成ルール。要件と設計から具体的な実装タスクを分解する方法を定義します。
Tasks Parallel Analysis
タスクの並列実行可能性を分析するルール。依存関係を考慮した効率的なタスク実行計画を立てます。
Full Discovery Process for Technical Design
Objective
Conduct comprehensive research and analysis to ensure the technical design is based on complete, accurate, and up-to-date information.
Discovery Steps
1. Requirements Analysis
Map Requirements to Technical Needs
- Extract all functional requirements from EARS format
- Identify non-functional requirements (performance, security, scalability)
- Determine technical constraints and dependencies
- List core technical challenges
2. Existing Implementation Analysis
Understand Current System (if modifying/extending):
- Analyze codebase structure and architecture patterns
- Map reusable components, services, utilities
- Identify domain boundaries and data flows
- Document integration points and dependencies
- Determine approach: extend vs refactor vs wrap
3. Technology Research
Investigate Best Practices and Solutions:
-
Use WebSearch to find:
- Latest architectural patterns for similar problems
- Industry best practices for the technology stack
- Recent updates or changes in relevant technologies
- Common pitfalls and solutions
-
Use WebFetch to analyze:
- Official documentation for frameworks/libraries
- API references and usage examples
- Migration guides and breaking changes
- Performance benchmarks and comparisons
4. External Dependencies Investigation
For Each External Service/Library:
- Search for official documentation and GitHub repositories
- Verify API signatures and authentication methods
- Check version compatibility with existing stack
- Investigate rate limits and usage constraints
- Find community resources and known issues
- Document security considerations
- Note any gaps requiring implementation investigation
5. Architecture Pattern & Boundary Analysis
Evaluate Architectural Options:
- Compare relevant patterns (MVC, Clean, Hexagonal, Event-driven)
- Assess fit with existing architecture and steering principles
- Identify domain boundaries and ownership seams required to avoid team conflicts
- Consider scalability implications and operational concerns
- Evaluate maintainability and team expertise
- Document preferred pattern and rejected alternatives in
research.md
6. Risk Assessment
Identify Technical Risks:
- Performance bottlenecks and scaling limits
- Security vulnerabilities and attack vectors
- Integration complexity and coupling
- Technical debt creation vs resolution
- Knowledge gaps and training needs
Research Guidelines
When to Search
Always search for:
- External API documentation and updates
- Security best practices for authentication/authorization
- Performance optimization techniques for identified bottlenecks
- Latest versions and migration paths for dependencies
Search if uncertain about:
- Architectural patterns for specific use cases
- Industry standards for data formats/protocols
- Compliance requirements (GDPR, HIPAA, etc.)
- Scalability approaches for expected load
Search Strategy
- Start with official sources (documentation, GitHub)
- Check recent blog posts and articles (last 6 months)
- Review Stack Overflow for common issues
- Investigate similar open-source implementations
Output Requirements
Capture all findings that impact design decisions in research.md using the shared template:
- Key insights affecting architecture, technology alignment, and contracts
- Constraints discovered during research
- Recommended approaches and selected architecture pattern with rationale
- Rejected alternatives and trade-offs (documented in the Design Decisions section)
- Updated domain boundaries that inform Components & Interface Contracts
- Risks and mitigation strategies
- Gaps requiring further investigation during implementation
Light Discovery Process for Extensions
Objective
Quickly analyze existing system and integration requirements for feature extensions.
Focused Discovery Steps
1. Extension Point Analysis
Identify Integration Approach:
- Locate existing extension points or interfaces
- Determine modification scope (files, components)
- Check for existing patterns to follow
- Identify backward compatibility requirements
2. Dependency Check
Verify Compatibility:
- Check version compatibility of new dependencies
- Validate API contracts haven’t changed
- Ensure no breaking changes in pipeline
3. Quick Technology Verification
For New Libraries Only:
- Use WebSearch for official documentation
- Verify basic usage patterns
- Check for known compatibility issues
- Confirm licensing compatibility
- Record key findings in
research.md(technology alignment section)
4. Integration Risk Assessment
Quick Risk Check:
- Impact on existing functionality
- Performance implications
- Security considerations
- Testing requirements
When to Escalate to Full Discovery
Switch to full discovery if you find:
- Significant architectural changes needed
- Complex external service integrations
- Security-sensitive implementations
- Performance-critical components
- Unknown or poorly documented dependencies
Output Requirements
- Clear integration approach (note boundary impacts in
research.md) - List of files/components to modify
- New dependencies with versions
- Integration risks and mitigations
- Testing focus areas
Technical Design Rules and Principles
Core Design Principles
1. Type Safety is Mandatory
- NEVER use
anytype in TypeScript interfaces - Define explicit types for all parameters and returns
- Use discriminated unions for error handling
- Specify generic constraints clearly
2. Design vs Implementation
- Focus on WHAT, not HOW
- Define interfaces and contracts, not code
- Specify behavior through pre/post conditions
- Document architectural decisions, not algorithms
3. Visual Communication
- Simple features: Basic component diagram or none
- Medium complexity: Architecture + data flow
- High complexity: Multiple diagrams (architecture, sequence, state)
- Always pure Mermaid: No styling, just structure
4. Component Design Rules
- Single Responsibility: One clear purpose per component
- Clear Boundaries: Explicit domain ownership
- Dependency Direction: Follow architectural layers
- Interface Segregation: Minimal, focused interfaces
- Team-safe Interfaces: Design boundaries that allow parallel implementation without merge conflicts
- Research Traceability: Record boundary decisions and rationale in
research.md
5. Data Modeling Standards
- Domain First: Start with business concepts
- Consistency Boundaries: Clear aggregate roots
- Normalization: Balance between performance and integrity
- Evolution: Plan for schema changes
6. Error Handling Philosophy
- Fail Fast: Validate early and clearly
- Graceful Degradation: Partial functionality over complete failure
- User Context: Actionable error messages
- Observability: Comprehensive logging and monitoring
7. Integration Patterns
- Loose Coupling: Minimize dependencies
- Contract First: Define interfaces before implementation
- Versioning: Plan for API evolution
- Idempotency: Design for retry safety
- Contract Visibility: Surface API and event contracts in design.md while linking extended details from
research.md
Documentation Standards
Language and Tone
- Declarative: “The system authenticates users” not “The system should authenticate”
- Precise: Specific technical terms over vague descriptions
- Concise: Essential information only
- Formal: Professional technical writing
Structure Requirements
- Hierarchical: Clear section organization
- Traceable: Requirements to components mapping
- Complete: All aspects covered for implementation
- Consistent: Uniform terminology throughout
- Focused: Keep design.md centered on architecture and contracts; move investigation logs and lengthy comparisons to
research.md
Section Authoring Guidance
Global Ordering
- Default flow: Overview → Goals/Non-Goals → Requirements Traceability → Architecture → Technology Stack → System Flows → Components & Interfaces → Data Models → Optional sections.
- Teams may swap Traceability earlier or place Data Models nearer Architecture when it improves clarity, but keep section headings intact.
- Within each section, follow Summary → Scope → Decisions → Impacts/Risks so reviewers can scan consistently.
Requirement IDs
- Reference requirements as
2.1, 2.3without prefixes (no “Requirement 2.1”). - All requirements MUST have numeric IDs. If a requirement lacks a numeric ID, stop and fix
requirements.mdbefore continuing. - Use
N.M-style numeric IDs whereNis the top-level requirement number from requirements.md (for example, Requirement 1 → 1.1, 1.2; Requirement 2 → 2.1, 2.2). - Every component, task, and traceability row must reference the same canonical numeric ID.
Technology Stack
- Include ONLY layers impacted by this feature (frontend, backend, data, messaging, infra).
- For each layer specify tool/library + version + the role it plays; push extended rationale, comparisons, or benchmarks to
research.md. - When extending an existing system, highlight deviations from the current stack and list new dependencies.
System Flows
- Add diagrams only when they clarify behavior:
- Sequence for multi-step interactions
- Process/State for branching rules or lifecycle
- Data/Event for pipelines or async patterns
- Always use pure Mermaid. If no complex flow exists, omit the entire section.
Requirements Traceability
- Use the standard table (
Requirement | Summary | Components | Interfaces | Flows) to prove coverage. - Collapse to bullet form only when a single requirement maps 1:1 to a component.
- Prefer the component summary table for simple mappings; reserve the full traceability table for complex or compliance-sensitive requirements.
- Re-run this mapping whenever requirements or components change to avoid drift.
Components & Interfaces Authoring
- Group components by domain/layer and provide one block per component.
- Begin with a summary table listing Component, Domain, Intent, Requirement coverage, key dependencies, and selected contracts.
- Table fields: Intent (one line), Requirements (
2.1, 2.3), Owner/Reviewers (optional). - Dependencies table must mark each entry as Inbound/Outbound/External and assign Criticality (
P0blocking,P1high-risk,P2informational). - Summaries of external dependency research stay here; detailed investigation (API signatures, rate limits, migration notes) belongs in
research.md. - design.md must remain a self-contained reviewer artifact. Reference
research.mdonly for background, and restate any conclusions or decisions here. - Contracts: tick only the relevant types (Service/API/Event/Batch/State). Unchecked types should not appear later in the component section.
- Service interfaces must declare method signatures, inputs/outputs, and error envelopes. API/Event/Batch contracts require schema tables or bullet lists covering trigger, payload, delivery, idempotency.
- Use Integration & Migration Notes, Validation Hooks, and Open Questions / Risks to document rollout strategy, observability, and unresolved decisions.
- Detail density rules:
- Full block: components introducing new boundaries (logic hooks, shared services, external integrations, data layers).
- Summary-only: presentational/UI components with no new boundaries (plus a short Implementation Note if needed).
- Implementation Notes must combine Integration / Validation / Risks into a single bulleted subsection to reduce repetition.
- Prefer lists or inline descriptors for short data (dependencies, contract selections). Use tables only when comparing multiple items.
Shared Interfaces & Props
- Define a base interface (e.g.,
BaseUIPanelProps) for recurring UI components and extend it per component to capture only the deltas. - Hooks, utilities, and integration adapters that introduce new contracts should still include full TypeScript signatures.
- When reusing a base contract, reference it explicitly (e.g., “Extends
BaseUIPanelPropswithonSubmitAnswercallback”) instead of duplicating the code block.
Data Models
- Domain Model covers aggregates, entities, value objects, domain events, and invariants. Add Mermaid diagrams only when relationships are non-trivial.
- Logical Data Model should articulate structure, indexing, sharding, and storage-specific considerations (event store, KV/wide-column) relevant to the change.
- Data Contracts & Integration section documents API payloads, event schemas, and cross-service synchronization patterns when the feature crosses boundaries.
- Lengthy type definitions or vendor-specific option objects should be placed in the Supporting References section within design.md, linked from the relevant section. Investigation notes stay in
research.md. - Supporting References usage is optional; only create it when keeping the content in the main body would reduce readability. All decisions must still appear in the main sections so design.md stands alone.
Error/Testing/Security/Performance Sections
- Record only feature-specific decisions or deviations. Link or reference organization-wide standards (steering) for baseline practices instead of restating them.
Diagram & Text Deduplication
- Do not restate diagram content verbatim in prose. Use the text to highlight key decisions, trade-offs, or impacts that are not obvious from the visual.
- When a decision is fully captured in the diagram annotations, a short “Key Decisions” bullet is sufficient.
General Deduplication
- Avoid repeating the same information across Overview, Architecture, and Components. Reference earlier sections when context is identical.
- If a requirement/component relationship is captured in the summary table, do not rewrite it elsewhere unless extra nuance is added.
Diagram Guidelines
When to include a diagram
- Architecture: Use a structural diagram when 3+ components or external systems interact.
- Sequence: Draw a sequence diagram when calls/handshakes span multiple steps.
- State / Flow: Capture complex state machines or business flows in a dedicated diagram.
- ER: Provide an entity-relationship diagram for non-trivial data models.
- Skip: Minor one-component changes generally do not need diagrams.
Mermaid requirements
graph TB
Client --> ApiGateway
ApiGateway --> ServiceA
ApiGateway --> ServiceB
ServiceA --> Database
- Plain Mermaid only – avoid custom styling or unsupported syntax.
- Node IDs – alphanumeric plus underscores only (e.g.,
Client,ServiceA). Do not use@,/, or leading-. - Labels – simple words. Do not embed parentheses
(), square brackets[], quotes", or slashes/.- ❌
DnD[@dnd-kit/core]→ invalid ID (@). - ❌
UI[KanbanBoard(React)]→ invalid label (()). - ✅
DndKit[dnd-kit core]→ use plain text in labels, keep technology details in the accompanying description. - ℹ️ Mermaid strict-mode will otherwise fail with errors like
Expecting 'SQE' ... got 'PS'; remove punctuation from labels before rendering.
- ❌
- Edges – show data or control flow direction.
- Groups – using Mermaid subgraphs to cluster related components is allowed; use it sparingly for clarity.
Quality Metrics
Design Completeness Checklist
- All requirements addressed
- No implementation details leaked
- Clear component boundaries
- Explicit error handling
- Comprehensive test strategy
- Security considered
- Performance targets defined
- Migration path clear (if applicable)
Common Anti-patterns to Avoid
❌ Mixing design with implementation ❌ Vague interface definitions ❌ Missing error scenarios ❌ Ignored non-functional requirements ❌ Overcomplicated architectures ❌ Tight coupling between components ❌ Missing data consistency strategy ❌ Incomplete dependency analysis
Design Review Process
Objective
Conduct interactive quality review of technical design documents to ensure they are solid enough to proceed to implementation with acceptable risk.
Review Philosophy
- Quality assurance, not perfection seeking
- Critical focus: Limit to 3 most important concerns
- Interactive dialogue: Engage with designer, not one-way evaluation
- Balanced assessment: Recognize strengths and weaknesses
- Clear decision: Definitive GO/NO-GO with rationale
Scope & Non-Goals
- Scope: Evaluate the quality of the design document against project context and standards to decide GO/NO-GO.
- Non-Goals: Do not perform implementation-level design, deep technology research, or finalize technology choices. Defer such items to the design phase iteration.
Core Review Criteria
1. Existing Architecture Alignment (Critical)
- Integration with existing system boundaries and layers
- Consistency with established architectural patterns
- Proper dependency direction and coupling management
- Alignment with current module organization
2. Design Consistency & Standards
- Adherence to project naming conventions and code standards
- Consistent error handling and logging strategies
- Uniform configuration and dependency management
- Alignment with established data modeling patterns
3. Extensibility & Maintainability
- Design flexibility for future requirements
- Clear separation of concerns and single responsibility
- Testability and debugging considerations
- Appropriate complexity for requirements
4. Type Safety & Interface Design
- Proper type definitions and interface contracts
- Avoidance of unsafe patterns (e.g.,
anyin TypeScript) - Clear API boundaries and data structures
- Input validation and error handling coverage
Review Process
Step 1: Analyze
Analyze design against all review criteria, focusing on critical issues impacting integration, maintainability, complexity, and requirements fulfillment.
Step 2: Identify Critical Issues (≤3)
For each issue:
🔴 **Critical Issue [1-3]**: [Brief title]
**Concern**: [Specific problem]
**Impact**: [Why it matters]
**Suggestion**: [Concrete improvement]
**Traceability**: [Requirement ID/section from requirements.md]
**Evidence**: [Design doc section/heading]
Step 3: Recognize Strengths
Acknowledge 1-2 strong aspects to maintain balanced feedback.
Step 4: Decide GO/NO-GO
- GO: No critical architectural misalignment, requirements addressed, clear implementation path, acceptable risks
- NO-GO: Fundamental conflicts, critical gaps, high failure risk, disproportionate complexity
Traceability & Evidence
- Link each critical issue to the relevant requirement(s) from
requirements.md(ID or section). - Cite evidence locations in the design document (section/heading, diagram, or artifact) to support the assessment.
- When applicable, reference constraints from steering context to justify the issue.
Output Format
Design Review Summary
2-3 sentences on overall quality and readiness.
Critical Issues (≤3)
For each: Issue, Impact, Recommendation, Traceability (e.g., 1.1, 1.2), Evidence (design.md section).
Design Strengths
1-2 positive aspects.
Final Assessment
Decision (GO/NO-GO), Rationale (1-2 sentences), Next Steps.
Interactive Discussion
Engage on designer’s perspective, alternatives, clarifications, and necessary changes.
Length & Focus
- Summary: 2–3 sentences
- Each critical issue: 5–7 lines total (including Issue/Impact/Recommendation/Traceability/Evidence)
- Overall review: keep concise (~400 words guideline)
Review Guidelines
- Critical Focus: Only flag issues that significantly impact success
- Constructive Tone: Provide solutions, not just criticism
- Interactive Approach: Engage in dialogue rather than one-way evaluation
- Balanced Assessment: Recognize both strengths and weaknesses
- Clear Decision: Make definitive GO/NO-GO recommendation
- Actionable Feedback: Ensure all suggestions are implementable
Final Checklist
- Critical Issues ≤ 3 and each includes Impact and Recommendation
- Traceability: Each issue references requirement ID/section
- Evidence: Each issue cites design doc location
- Decision: GO/NO-GO with clear rationale and next steps
EARS Format Guidelines
Overview
EARS (Easy Approach to Requirements Syntax) is the standard format for acceptance criteria in spec-driven development.
EARS patterns describe the logical structure of a requirement (condition + subject + response) and are not tied to any particular natural language.
All acceptance criteria should be written in the target language configured for the specification (for example, spec.json.language / en).
Keep EARS trigger keywords and fixed phrases in English (When, If, While, Where, The system shall, The [system] shall) and localize only the variable parts ([event], [precondition], [trigger], [feature is included], [response/action]) into the target language. Do not interleave target-language text inside the trigger or fixed English phrases themselves.
Primary EARS Patterns
1. Event-Driven Requirements
- Pattern: When [event], the [system] shall [response/action]
- Use Case: Responses to specific events or triggers
- Example: When user clicks checkout button, the Checkout Service shall validate cart contents
2. State-Driven Requirements
- Pattern: While [precondition], the [system] shall [response/action]
- Use Case: Behavior dependent on system state or preconditions
- Example: While payment is processing, the Checkout Service shall display loading indicator
3. Unwanted Behavior Requirements
- Pattern: If [trigger], the [system] shall [response/action]
- Use Case: System response to errors, failures, or undesired situations
- Example: If invalid credit card number is entered, then the website shall display error message
4. Optional Feature Requirements
- Pattern: Where [feature is included], the [system] shall [response/action]
- Use Case: Requirements for optional or conditional features
- Example: Where the car has a sunroof, the car shall have a sunroof control panel
5. Ubiquitous Requirements
- Pattern: The [system] shall [response/action]
- Use Case: Always-active requirements and fundamental system properties
- Example: The mobile phone shall have a mass of less than 100 grams
Combined Patterns
- While [precondition], when [event], the [system] shall [response/action]
- When [event] and [additional condition], the [system] shall [response/action]
Subject Selection Guidelines
- Software Projects: Use concrete system/service name (e.g., “Checkout Service”, “User Auth Module”)
- Process/Workflow: Use responsible team/role (e.g., “Support Team”, “Review Process”)
- Non-Software: Use appropriate subject (e.g., “Marketing Campaign”, “Documentation”)
Quality Criteria
- Requirements must be testable, verifiable, and describe a single behavior.
- Use objective language: “shall” for mandatory behavior, “should” for recommendations; avoid ambiguous terms.
- Follow EARS syntax: [condition], the [system] shall [response/action].
Gap Analysis Process
Objective
Analyze the gap between requirements and existing codebase to inform implementation strategy decisions.
Analysis Framework
1. Current State Investigation
-
Scan for domain-related assets:
- Key files/modules and directory layout
- Reusable components/services/utilities
- Dominant architecture patterns and constraints
-
Extract conventions:
- Naming, layering, dependency direction
- Import/export patterns and dependency hotspots
- Testing placement and approach
-
Note integration surfaces:
- Data models/schemas, API clients, auth mechanisms
2. Requirements Feasibility Analysis
-
From EARS requirements, list technical needs:
- Data models, APIs/services, UI/components
- Business rules/validation
- Non-functionals: security, performance, scalability, reliability
-
Identify gaps and constraints:
- Missing capabilities in current codebase
- Unknowns to be researched later (mark as “Research Needed”)
- Constraints from existing architecture and patterns
-
Note complexity signals:
- Simple CRUD / algorithmic logic / workflows / external integrations
3. Implementation Approach Options
Option A: Extend Existing Components
When to consider: Feature fits naturally into existing structure
-
Which files/modules to extend:
- Identify specific files requiring changes
- Assess impact on existing functionality
- Evaluate backward compatibility concerns
-
Compatibility assessment:
- Check if extension respects existing interfaces
- Verify no breaking changes to consumers
- Assess test coverage impact
-
Complexity and maintainability:
- Evaluate cognitive load of additional functionality
- Check if single responsibility principle is maintained
- Assess if file size remains manageable
Trade-offs:
- ✅ Minimal new files, faster initial development
- ✅ Leverages existing patterns and infrastructure
- ❌ Risk of bloating existing components
- ❌ May complicate existing logic
Option B: Create New Components
When to consider: Feature has distinct responsibility or existing components are already complex
-
Rationale for new creation:
- Clear separation of concerns justifies new file
- Existing components are already complex
- Feature has distinct lifecycle or dependencies
-
Integration points:
- How new components connect to existing system
- APIs or interfaces exposed
- Dependencies on existing components
-
Responsibility boundaries:
- Clear definition of what new component owns
- Interfaces with existing components
- Data flow and control flow
Trade-offs:
- ✅ Clean separation of concerns
- ✅ Easier to test in isolation
- ✅ Reduces complexity in existing components
- ❌ More files to navigate
- ❌ Requires careful interface design
Option C: Hybrid Approach
When to consider: Complex features requiring both extension and new creation
-
Combination strategy:
- Which parts extend existing components
- Which parts warrant new components
- How they interact
-
Phased implementation:
- Initial phase: minimal viable changes
- Subsequent phases: refactoring or new components
- Migration strategy if needed
-
Risk mitigation:
- Incremental rollout approach
- Feature flags or configuration
- Rollback strategy
Trade-offs:
- ✅ Balanced approach for complex features
- ✅ Allows iterative refinement
- ❌ More complex planning required
- ❌ Potential for inconsistency if not well-coordinated
4. Out-of-Scope for Gap Analysis
- Defer deep research activities to the design phase.
- Record unknowns as concise “Research Needed” items only.
5. Implementation Complexity & Risk
- Effort:
- S (1–3 days): existing patterns, minimal deps, straightforward integration
- M (3–7 days): some new patterns/integrations, moderate complexity
- L (1–2 weeks): significant functionality, multiple integrations or workflows
- XL (2+ weeks): architectural changes, unfamiliar tech, broad impact
- Risk:
- High: unknown tech, complex integrations, architectural shifts, unclear perf/security path
- Medium: new patterns with guidance, manageable integrations, known perf solutions
- Low: extend established patterns, familiar tech, clear scope, minimal integration
Output Checklist
- Requirement-to-Asset Map with gaps tagged (Missing / Unknown / Constraint)
- Options A/B/C with short rationale and trade-offs
- Effort (S/M/L/XL) and Risk (High/Medium/Low) with one-line justification each
- Recommendations for design phase:
- Preferred approach and key decisions
- Research items to carry forward
Principles
- Information over decisions: Provide analysis and options, not final choices
- Multiple viable options: Offer credible alternatives when applicable
- Explicit gaps and assumptions: Flag unknowns and constraints clearly
- Context-aware: Align with existing patterns and architecture limits
- Transparent effort and risk: Justify labels succinctly
Steering Principles
Steering files are project memory, not exhaustive specifications.
Content Granularity
Golden Rule
“If new code follows existing patterns, steering shouldn’t need updating.”
✅ Document
- Organizational patterns (feature-first, layered)
- Naming conventions (PascalCase rules)
- Import strategies (absolute vs relative)
- Architectural decisions (state management)
- Technology standards (key frameworks)
❌ Avoid
- Complete file listings
- Every component description
- All dependencies
- Implementation details
- Agent-specific tooling directories (e.g.
.cursor/,.gemini/,.claude/) - Detailed documentation of
.kiro/metadata directories (settings, automation)
Example Comparison
Bad (Specification-like):
- /components/Button.tsx - Primary button with variants
- /components/Input.tsx - Text input with validation
- /components/Modal.tsx - Modal dialog
... (50+ files)
Good (Project Memory):
## UI Components (`/components/ui/`)
Reusable, design-system aligned primitives
- Named by function (Button, Input, Modal)
- Export component + TypeScript interface
- No business logic
Security
Never include:
- API keys, passwords, credentials
- Database URLs, internal IPs
- Secrets or sensitive data
Quality Standards
- Single domain: One topic per file
- Concrete examples: Show patterns with code
- Explain rationale: Why decisions were made
- Maintainable size: 100-200 lines typical
Preservation (when updating)
- Preserve user sections and custom examples
- Additive by default (add, don’t replace)
- Add
updated_attimestamp - Note why changes were made
Notes
- Templates are starting points, customize as needed
- Follow same granularity principles as core steering
- All steering files loaded as project memory
- Light references to
.kiro/specs/and.kiro/steering/are acceptable; avoid other.kiro/directories - Custom files equally important as core files
File-Specific Focus
- product.md: Purpose, value, business context (not exhaustive features)
- tech.md: Key frameworks, standards, conventions (not all dependencies)
- structure.md: Organization patterns, naming rules (not directory trees)
- Custom files: Specialized patterns (API, testing, security, etc.)
Task Generation Rules
Core Principles
1. Natural Language Descriptions
Focus on capabilities and outcomes, not code structure.
Describe:
- What functionality to achieve
- Business logic and behavior
- Features and capabilities
- Domain language and concepts
- Data relationships and workflows
Avoid:
- File paths and directory structure
- Function/method names and signatures
- Type definitions and interfaces
- Class names and API contracts
- Specific data structures
Rationale: Implementation details (files, methods, types) are defined in design.md. Tasks describe the functional work to be done.
2. Task Integration & Progression
Every task must:
- Build on previous outputs (no orphaned code)
- Connect to the overall system (no hanging features)
- Progress incrementally (no big jumps in complexity)
- Validate core functionality early in sequence
- Respect architecture boundaries defined in design.md (Architecture Pattern & Boundary Map)
- Honor interface contracts documented in design.md
- Use major task summaries sparingly—omit detail bullets if the work is fully captured by child tasks.
End with integration tasks to wire everything together.
3. Flexible Task Sizing
Guidelines:
- Major tasks: As many sub-tasks as logically needed (group by cohesion)
- Sub-tasks: 1-3 hours each, 3-10 details per sub-task
- Balance between too granular and too broad
Don’t force arbitrary numbers - let logical grouping determine structure.
4. Requirements Mapping
End each task detail section with:
_Requirements: X.X, Y.Y_listing only numeric requirement IDs (comma-separated). Never append descriptive text, parentheses, translations, or free-form labels.- For cross-cutting requirements, list every relevant requirement ID. All requirements MUST have numeric IDs in requirements.md. If an ID is missing, stop and correct requirements.md before generating tasks.
- Reference components/interfaces from design.md when helpful (e.g.,
_Contracts: AuthService API)
5. Code-Only Focus
Include ONLY:
- Coding tasks (implementation)
- Testing tasks (unit, integration, E2E)
- Technical setup tasks (infrastructure, configuration)
Exclude:
- Deployment tasks
- Documentation tasks
- User testing
- Marketing/business activities
Optional Test Coverage Tasks
- When the design already guarantees functional coverage and rapid MVP delivery is prioritized, mark purely test-oriented follow-up work (e.g., baseline rendering/unit tests) as optional using the
- [ ]*checkbox form. - Only apply the optional marker when the sub-task directly references acceptance criteria from requirements.md in its detail bullets.
- Never mark implementation work or integration-critical verification as optional—reserve
*for auxiliary/deferrable test coverage that can be revisited post-MVP.
Task Hierarchy Rules
Maximum 2 Levels
- Level 1: Major tasks (1, 2, 3, 4…)
- Level 2: Sub-tasks (1.1, 1.2, 2.1, 2.2…)
- No deeper nesting (no 1.1.1)
- If a major task would contain only a single actionable item, collapse the structure and promote the sub-task to the major level (e.g., replace
1.1with1.). - When a major task exists purely as a container, keep the checkbox description concise and avoid duplicating detailed bullets—reserve specifics for its sub-tasks.
Sequential Numbering
- Major tasks MUST increment: 1, 2, 3, 4, 5…
- Sub-tasks reset per major task: 1.1, 1.2, then 2.1, 2.2…
- Never repeat major task numbers
Parallel Analysis (default)
- Assume parallel analysis is enabled unless explicitly disabled (e.g.
--sequentialflag). - Identify tasks that can run concurrently when all conditions hold:
- No data dependency on other pending tasks
- No shared file or resource contention
- No prerequisite review/approval from another task
- Validate that identified parallel tasks operate within separate boundaries defined in the Architecture Pattern & Boundary Map.
- Confirm API/event contracts from design.md do not overlap in ways that cause conflicts.
- Append
(P)immediately after the task number for each parallel-capable task:- Example:
- [ ] 2.1 (P) Build background worker - Apply to both major tasks and sub-tasks when appropriate.
- Example:
- If sequential mode is requested, omit
(P)markers entirely. - Group parallel tasks logically (same parent when possible) and highlight any ordering caveats in detail bullets.
- Explicitly call out dependencies that prevent
(P)even when tasks look similar.
Checkbox Format
- [ ] 1. Major task description
- [ ] 1.1 Sub-task description
- Detail item 1
- Detail item 2
- _Requirements: X.X_
- [ ] 1.2 Sub-task description
- Detail items...
- _Requirements: Y.Y_
- [ ] 1.3 Sub-task description
- Detail items...
- _Requirements: Z.Z, W.W_
- [ ] 2. Next major task (NOT 1 again!)
- [ ] 2.1 Sub-task...
Requirements Coverage
Mandatory Check:
- ALL requirements from requirements.md MUST be covered
- Cross-reference every requirement ID with task mappings
- If gaps found: Return to requirements or design phase
- No requirement should be left without corresponding tasks
Use N.M-style numeric requirement IDs where N is the top-level requirement number from requirements.md (for example, Requirement 1 → 1.1, 1.2; Requirement 2 → 2.1, 2.2), and M is a local index within that requirement group.
Document any intentionally deferred requirements with rationale.
Parallel Task Analysis Rules
Purpose
Provide a consistent way to identify implementation tasks that can be safely executed in parallel while generating tasks.md.
When to Consider Tasks Parallel
Only mark a task as parallel-capable when all of the following are true:
- No data dependency on pending tasks.
- No conflicting files or shared mutable resources are touched.
- No prerequisite review/approval from another task is required beforehand.
- Environment/setup work needed by this task is already satisfied or covered within the task itself.
Marking Convention
- Append
(P)immediately after the numeric identifier for each qualifying task.- Example:
- [ ] 2.1 (P) Build background worker for emails
- Example:
- Apply
(P)to both major tasks and sub-tasks when appropriate. - If sequential execution is requested (e.g. via
--sequentialflag), omit(P)markers entirely. - Keep
(P)outside of checkbox brackets to avoid confusion with completion state.
Grouping & Ordering Guidelines
- Group parallel tasks under the same parent whenever the work belongs to the same theme.
- List obvious prerequisites or caveats in the detail bullets (e.g., “Requires schema migration from 1.2”).
- When two tasks look similar but are not parallel-safe, call out the blocking dependency explicitly.
- Skip marking container-only major tasks (those without their own actionable detail bullets) with
(P)—evaluate parallel execution at the sub-task level instead.
Quality Checklist
Before marking a task with (P), ensure you have:
- Verified that running this task concurrently will not create merge or deployment conflicts.
- Captured any shared state expectations in the detail bullets.
- Confirmed that the implementation can be tested independently.
If any check fails, do not mark the task with (P) and explain the dependency in the task details.
Templates
SDDフレームワークで使用する各種ドキュメントテンプレートです。これらのテンプレートを使用することで、一貫性のある仕様書とステアリング文書を作成できます。
Specs Templates
新機能や変更の仕様書を作成するためのテンプレート群です。
- Design Template: アーキテクチャ設計書のテンプレート
- Requirements Template: 要件定義書のテンプレート
- Requirements Init Template: 要件初期化のテンプレート
- Research Template: 技術調査レポートのテンプレート
- Tasks Template: 実装タスクリストのテンプレート
Steering Templates
プロジェクト全体のガイドラインを定義するためのテンプレート群です。
- Product Template: プロダクト要件とビジネスルールのテンプレート
- Tech Template: 技術スタックと技術的制約のテンプレート
- Structure Template: プロジェクト構造とアーキテクチャ原則のテンプレート
Custom Steering Templates
特定のドメインに特化したステアリングテンプレート群です。
- API Standards: API設計標準
- Authentication: 認証・認可の方針
- Database: データベース設計指針
- Deployment: デプロイ戦略
- Error Handling: エラーハンドリング規約
- Security: セキュリティガイドライン
- Testing: テスト戦略
使用方法
- 適切なテンプレートを選択
- プロジェクト固有の情報で埋める
.kiro/steering/または.kiro/specs/に保存- AI開発エージェントがこれらを参照して開発を進める
Specs Templates
新機能や変更の仕様書を作成するためのテンプレート群です。
Templates
- Design: アーキテクチャ設計書のテンプレート
- Requirements: 要件定義書のテンプレート
- Requirements Init: 要件初期化のテンプレート
- Research: 技術調査レポートのテンプレート
- Tasks: 実装タスクリストのテンプレート
使用方法
- 適切なテンプレートを選択
- プロジェクト固有の情報で埋める
.kiro/specs/{feature-name}/に保存- AI開発エージェントがこれらを参照して開発を進める
Design Document Template
Purpose: Provide sufficient detail to ensure implementation consistency across different implementers, preventing interpretation drift.
Approach:
- Include essential sections that directly inform implementation decisions
- Omit optional sections unless critical to preventing implementation errors
- Match detail level to feature complexity
- Use diagrams and tables over lengthy prose
Warning: Approaching 1000 lines indicates excessive feature complexity that may require design simplification.
Sections may be reordered (e.g., surfacing Requirements Traceability earlier or moving Data Models nearer Architecture) when it improves clarity. Within each section, keep the flow Summary → Scope → Decisions → Impacts/Risks so reviewers can scan consistently.
Overview
2-3 paragraphs max Purpose: This feature delivers [specific value] to [target users]. Users: [Target user groups] will utilize this for [specific workflows]. Impact (if applicable): Changes the current [system state] by [specific modifications].
Goals
- Primary objective 1
- Primary objective 2
- Success criteria
Non-Goals
- Explicitly excluded functionality
- Future considerations outside current scope
- Integration points deferred
Architecture
Reference detailed discovery notes in
research.mdonly for background; keep design.md self-contained for reviewers by capturing all decisions and contracts here. Capture key decisions in text and let diagrams carry structural detail—avoid repeating the same information in prose.
Existing Architecture Analysis (if applicable)
When modifying existing systems:
- Current architecture patterns and constraints
- Existing domain boundaries to be respected
- Integration points that must be maintained
- Technical debt addressed or worked around
Architecture Pattern & Boundary Map
RECOMMENDED: Include Mermaid diagram showing the chosen architecture pattern and system boundaries (required for complex features, optional for simple additions)
Architecture Integration:
- Selected pattern: [name and brief rationale]
- Domain/feature boundaries: [how responsibilities are separated to avoid conflicts]
- Existing patterns preserved: [list key patterns]
- New components rationale: [why each is needed]
- Steering compliance: [principles maintained]
Technology Stack
| Layer | Choice / Version | Role in Feature | Notes |
|---|---|---|---|
| Frontend / CLI | |||
| Backend / Services | |||
| Data / Storage | |||
| Messaging / Events | |||
| Infrastructure / Runtime |
Keep rationale concise here and, when more depth is required (trade-offs, benchmarks), add a short summary plus pointer to the Supporting References section and
research.mdfor raw investigation notes.
System Flows
Provide only the diagrams needed to explain non-trivial flows. Use pure Mermaid syntax. Common patterns:
- Sequence (multi-party interactions)
- Process / state (branching logic or lifecycle)
- Data / event flow (pipelines, async messaging)
Skip this section entirely for simple CRUD changes.
Describe flow-level decisions (e.g., gating conditions, retries) briefly after the diagram instead of restating each step.
Requirements Traceability
Use this section for complex or compliance-sensitive features where requirements span multiple domains. Straightforward 1:1 mappings can rely on the Components summary table.
Map each requirement ID (e.g., 2.1) to the design elements that realize it.
| Requirement | Summary | Components | Interfaces | Flows |
|---|---|---|---|---|
| 1.1 | ||||
| 1.2 |
Omit this section only when a single component satisfies a single requirement without cross-cutting concerns.
Components and Interfaces
Provide a quick reference before diving into per-component details.
- Summaries can be a table or compact list. Example table:
Component Domain/Layer Intent Req Coverage Key Dependencies (P0/P1) Contracts ExampleComponent UI Displays XYZ 1, 2 GameProvider (P0), MapPanel (P1) Service, State - Only components introducing new boundaries (e.g., logic hooks, external integrations, persistence) require full detail blocks. Simple presentation components can rely on the summary row plus a short Implementation Note.
Group detailed blocks by domain or architectural layer. For each detailed component, list requirement IDs as 2.1, 2.3 (omit “Requirement”). When multiple UI components share the same contract, reference a base interface/props definition instead of duplicating code blocks.
[Domain / Layer]
[Component Name]
| Field | Detail |
|---|---|
| Intent | 1-line description of the responsibility |
| Requirements | 2.1, 2.3 |
| Owner / Reviewers | (optional) |
Responsibilities & Constraints
- Primary responsibility
- Domain boundary and transaction scope
- Data ownership / invariants
Dependencies
- Inbound: Component/service name — purpose (Criticality)
- Outbound: Component/service name — purpose (Criticality)
- External: Service/library — purpose (Criticality)
Summarize external dependency findings here; deeper investigation (API signatures, rate limits, migration notes) lives in research.md.
Contracts: Service [ ] / API [ ] / Event [ ] / Batch [ ] / State [ ] ← check only the ones that apply.
Service Interface
interface [ComponentName]Service {
methodName(input: InputType): Result<OutputType, ErrorType>;
}
- Preconditions:
- Postconditions:
- Invariants:
API Contract
| Method | Endpoint | Request | Response | Errors |
|---|---|---|---|---|
| POST | /api/resource | CreateRequest | Resource | 400, 409, 500 |
Event Contract
- Published events:
- Subscribed events:
- Ordering / delivery guarantees:
Batch / Job Contract
- Trigger:
- Input / validation:
- Output / destination:
- Idempotency & recovery:
State Management
- State model:
- Persistence & consistency:
- Concurrency strategy:
Implementation Notes
- Integration:
- Validation:
- Risks:
Data Models
Focus on the portions of the data landscape that change with this feature.
Domain Model
- Aggregates and transactional boundaries
- Entities, value objects, domain events
- Business rules & invariants
- Optional Mermaid diagram for complex relationships
Logical Data Model
Structure Definition:
- Entity relationships and cardinality
- Attributes and their types
- Natural keys and identifiers
- Referential integrity rules
Consistency & Integrity:
- Transaction boundaries
- Cascading rules
- Temporal aspects (versioning, audit)
Physical Data Model
When to include: When implementation requires specific storage design decisions
For Relational Databases:
- Table definitions with data types
- Primary/foreign keys and constraints
- Indexes and performance optimizations
- Partitioning strategy for scale
For Document Stores:
- Collection structures
- Embedding vs referencing decisions
- Sharding key design
- Index definitions
For Event Stores:
- Event schema definitions
- Stream aggregation strategies
- Snapshot policies
- Projection definitions
For Key-Value/Wide-Column Stores:
- Key design patterns
- Column families or value structures
- TTL and compaction strategies
Data Contracts & Integration
API Data Transfer
- Request/response schemas
- Validation rules
- Serialization format (JSON, Protobuf, etc.)
Event Schemas
- Published event structures
- Schema versioning strategy
- Backward/forward compatibility rules
Cross-Service Data Management
- Distributed transaction patterns (Saga, 2PC)
- Data synchronization strategies
- Eventual consistency handling
Skip subsections that are not relevant to this feature.
Error Handling
Error Strategy
Concrete error handling patterns and recovery mechanisms for each error type.
Error Categories and Responses
User Errors (4xx): Invalid input → field-level validation; Unauthorized → auth guidance; Not found → navigation help
System Errors (5xx): Infrastructure failures → graceful degradation; Timeouts → circuit breakers; Exhaustion → rate limiting
Business Logic Errors (422): Rule violations → condition explanations; State conflicts → transition guidance
Process Flow Visualization (when complex business logic exists): Include Mermaid flowchart only for complex error scenarios with business workflows.
Monitoring
Error tracking, logging, and health monitoring implementation.
Testing Strategy
Default sections (adapt names/sections to fit the domain)
- Unit Tests: 3–5 items from core functions/modules (e.g., auth methods, subscription logic)
- Integration Tests: 3–5 cross-component flows (e.g., webhook handling, notifications)
- E2E/UI Tests (if applicable): 3–5 critical user paths (e.g., forms, dashboards)
- Performance/Load (if applicable): 3–4 items (e.g., concurrency, high-volume ops)
Optional Sections (include when relevant)
Security Considerations
Use this section for features handling auth, sensitive data, external integrations, or user permissions. Capture only decisions unique to this feature; defer baseline controls to steering docs.
- Threat modeling, security controls, compliance requirements
- Authentication and authorization patterns
- Data protection and privacy considerations
Performance & Scalability
Use this section when performance targets, high load, or scaling concerns exist. Record only feature-specific targets or trade-offs and rely on steering documents for general practices.
- Target metrics and measurement strategies
- Scaling approaches (horizontal/vertical)
- Caching strategies and optimization techniques
Migration Strategy
Include a Mermaid flowchart showing migration phases when schema/data movement is required.
- Phase breakdown, rollback triggers, validation checkpoints
Supporting References (Optional)
- Create this section only when keeping the information in the main body would hurt readability (e.g., very long TypeScript definitions, vendor option matrices, exhaustive schema tables). Keep decision-making context in the main sections so the design stays self-contained.
- Link to the supporting references from the main text instead of inlining large snippets.
- Background research notes and comparisons continue to live in
research.md, but their conclusions must be summarized in the main design.
Requirements Document
Introduction
{{INTRODUCTION}}
Requirements
Requirement 1: {{REQUIREMENT_AREA_1}}
Objective: As a {{ROLE}}, I want {{CAPABILITY}}, so that {{BENEFIT}}
Acceptance Criteria
- When [event], the [system] shall [response/action]
- If [trigger], then the [system] shall [response/action]
- While [precondition], the [system] shall [response/action]
- Where [feature is included], the [system] shall [response/action]
- The [system] shall [response/action]
Requirement 2: {{REQUIREMENT_AREA_2}}
Objective: As a {{ROLE}}, I want {{CAPABILITY}}, so that {{BENEFIT}}
Acceptance Criteria
- When [event], the [system] shall [response/action]
- When [event] and [condition], the [system] shall [response/action]
Requirements Document
Project Description (Input)
{{PROJECT_DESCRIPTION}}
Requirements
Research & Design Decisions Template
Purpose: Capture discovery findings, architectural investigations, and rationale that inform the technical design.
Usage:
- Log research activities and outcomes during the discovery phase.
- Document design decision trade-offs that are too detailed for
design.md. - Provide references and evidence for future audits or reuse.
Summary
- Feature:
<feature-name> - Discovery Scope: New Feature / Extension / Simple Addition / Complex Integration
- Key Findings:
- Finding 1
- Finding 2
- Finding 3
Research Log
Document notable investigation steps and their outcomes. Group entries by topic for readability.
[Topic or Question]
- Context: What triggered this investigation?
- Sources Consulted: Links, documentation, API references, benchmarks
- Findings: Concise bullet points summarizing the insights
- Implications: How this affects architecture, contracts, or implementation
Repeat the subsection for each major topic.
Architecture Pattern Evaluation
List candidate patterns or approaches that were considered. Use the table format where helpful.
| Option | Description | Strengths | Risks / Limitations | Notes |
|---|---|---|---|---|
| Hexagonal | Ports & adapters abstraction around core domain | Clear boundaries, testable core | Requires adapter layer build-out | Aligns with existing steering principle X |
Design Decisions
Record major decisions that influence design.md. Focus on choices with significant trade-offs.
Decision: <Title>
- Context: Problem or requirement driving the decision
- Alternatives Considered:
- Option A — short description
- Option B — short description
- Selected Approach: What was chosen and how it works
- Rationale: Why this approach fits the current project context
- Trade-offs: Benefits vs. compromises
- Follow-up: Items to verify during implementation or testing
Repeat the subsection for each decision.
Risks & Mitigations
- Risk 1 — Proposed mitigation
- Risk 2 — Proposed mitigation
- Risk 3 — Proposed mitigation
References
Provide canonical links and citations (official docs, standards, ADRs, internal guidelines).
- Title — brief note on relevance
- …
Implementation Plan
Task Format Template
Use whichever pattern fits the work breakdown:
Major task only
- {{NUMBER}}. {{TASK_DESCRIPTION}}{{PARALLEL_MARK}}
- {{DETAIL_ITEM_1}} (Include details only when needed. If the task stands alone, omit bullet items.)
- Requirements: {{REQUIREMENT_IDS}}
Major + Sub-task structure
- {{MAJOR_NUMBER}}. {{MAJOR_TASK_SUMMARY}}
- {{MAJOR_NUMBER}}.{{SUB_NUMBER}} {{SUB_TASK_DESCRIPTION}}{{SUB_PARALLEL_MARK}}
- {{DETAIL_ITEM_1}}
- {{DETAIL_ITEM_2}}
- Requirements: {{REQUIREMENT_IDS}} (IDs only; do not add descriptions or parentheses.)
Parallel marker: Append
(P)only to tasks that can be executed in parallel. Omit the marker when running in--sequentialmode.Optional test coverage: When a sub-task is deferrable test work tied to acceptance criteria, mark the checkbox as
- [ ]*and explain the referenced requirements in the detail bullets.
Steering Templates
プロジェクト全体のガイドラインを定義するためのテンプレート群です。
Templates
使用方法
- 適切なテンプレートを選択
- プロジェクト固有の情報で埋める
.kiro/steering/に保存- AI開発エージェントがこれらを参照して開発を進める
Product Overview
[Brief description of what this product does and who it serves]
Core Capabilities
[3-5 key capabilities, not exhaustive features]
Target Use Cases
[Primary scenarios this product addresses]
Value Proposition
[What makes this product unique or valuable]
Focus on patterns and purpose, not exhaustive feature lists
Technology Stack
Architecture
[High-level system design approach]
Core Technologies
- Language: [e.g., TypeScript, Python]
- Framework: [e.g., React, Next.js, Django]
- Runtime: [e.g., Node.js 20+]
Key Libraries
[Only major libraries that influence development patterns]
Development Standards
Type Safety
[e.g., TypeScript strict mode, no any]
Code Quality
[e.g., ESLint, Prettier rules]
Testing
[e.g., Jest, coverage requirements]
Development Environment
Required Tools
[Key tools and version requirements]
Common Commands
# Dev: [command]
# Build: [command]
# Test: [command]
Key Technical Decisions
[Important architectural choices and rationale]
Document standards and patterns, not every dependency
Project Structure
Organization Philosophy
[Describe approach: feature-first, layered, domain-driven, etc.]
Directory Patterns
[Pattern Name]
Location: /path/
Purpose: [What belongs here]
Example: [Brief example]
[Pattern Name]
Location: /path/
Purpose: [What belongs here]
Example: [Brief example]
Naming Conventions
- Files: [Pattern, e.g., PascalCase, kebab-case]
- Components: [Pattern]
- Functions: [Pattern]
Import Organization
// Example import patterns
import { Something } from '@/path' // Absolute
import { Local } from './local' // Relative
Path Aliases:
@/: [Maps to]
Code Organization Principles
[Key architectural patterns and dependency rules]
Document patterns, not file trees. New files following patterns shouldn’t require updates
Custom Steering Templates
特定のドメインに特化したステアリングテンプレート群です。
Templates
- API Standards: API設計標準
- Authentication: 認証・認可の方針
- Database: データベース設計指針
- Deployment: デプロイ戦略
- Error Handling: エラーハンドリング規約
- Security: セキュリティガイドライン
- Testing: テスト戦略
使用方法
- プロジェクトに必要なテンプレートを選択
- プロジェクト固有の情報で埋める
.kiro/steering/にカスタムファイルとして保存- AI開発エージェントがこれらを参照して開発を進める
カスタムステアリングの作成
/kiro:steering-custom
このコマンドでカスタムステアリングファイルを対話的に作成できます。
API Standards
[Purpose: consistent API patterns for naming, structure, auth, versioning, and errors]
Philosophy
- Prefer predictable, resource-oriented design
- Be explicit in contracts; minimize breaking changes
- Secure by default (auth first, least privilege)
Endpoint Pattern
/{version}/{resource}[/{id}][/{sub-resource}]
Examples:
/api/v1/users/api/v1/users/:id/api/v1/users/:id/posts
HTTP verbs:
- GET (read, safe, idempotent)
- POST (create)
- PUT/PATCH (update)
- DELETE (remove, idempotent)
Request/Response
Request (typical):
{ "data": { ... }, "metadata": { "requestId": "..." } }
Success:
{ "data": { ... }, "meta": { "timestamp": "...", "version": "..." } }
Error:
{ "error": { "code": "ERROR_CODE", "message": "...", "field": "optional" } }
(See error-handling for rules.)
Status Codes (pattern)
- 2xx: Success (200 read, 201 create, 204 delete)
- 4xx: Client issues (400 validation, 401/403 auth, 404 missing)
- 5xx: Server issues (500 generic, 503 unavailable) Choose the status that best reflects the outcome.
Authentication
- Credentials in standard location
Authorization: Bearer {token}
- Reject unauthenticated before business logic
Versioning
- Version via URL/header/media-type
- Breaking change → new version
- Non-breaking → same version
- Provide deprecation window and comms
Pagination/Filtering (if applicable)
- Pagination:
page,pageSizeor cursor-based - Filtering: explicit query params
- Sorting:
sort=field:asc|descReturn pagination metadata inmeta.
Focus on patterns and decisions, not endpoint catalogs.
Authentication & Authorization Standards
[Purpose: unify auth model, token/session lifecycle, permission checks, and security]
Philosophy
- Clear separation: authentication (who) vs authorization (what)
- Secure by default: least privilege, fail closed, short-lived tokens
- UX-aware: friction where risk is high, smooth otherwise
Authentication
Method (choose + rationale)
- Options: JWT, Session, OAuth2, hybrid
- Choice: [our method] because [reason]
Flow (high-level)
1) User proves identity (credentials or provider)
2) Server verifies and issues token/session
3) Client sends token per request
4) Server verifies token and proceeds
Token/Session Lifecycle
- Storage: httpOnly cookie or Authorization header
- Expiration: short-lived access, longer refresh (if used)
- Refresh: rotate tokens; respect revocation
- Revocation: blacklist/rotate on logout/compromise
Security Pattern
- Enforce TLS; never expose tokens to JS when avoidable
- Bind token to audience/issuer; include minimal claims
- Consider device binding and IP/risk checks for sensitive actions
Authorization
Permission Model
- Choose one: RBAC / ABAC / ownership-based / hybrid
- Define roles/attributes centrally; avoid hardcoding across codebase
Checks (where to enforce)
- Route/middleware: coarse-grained gate
- Domain/service: fine-grained decisions
- UI: conditional rendering (no security reliance)
Example pattern:
requirePermission('resource:action'); // route
if (!user.can('resource:action')) throw ForbiddenError(); // domain
Ownership
- Pattern: owner OR privileged role can act
- Verify on entity boundary before mutation
Passwords & MFA
- Passwords: strong policy, hashed (bcrypt/argon2), never plaintext
- Reset: time-limited token, single-use, notify user
- MFA: step-up for risky operations (policy-driven)
API-to-API Auth
- Use API keys or OAuth client credentials
- Scope keys minimally; rotate and audit usage
- Rate limit by identity (user/key)
Focus on patterns and decisions. No library-specific code.
Database Standards
[Purpose: guide schema design, queries, migrations, and integrity]
Philosophy
- Model the domain first; optimize after correctness
- Prefer explicit constraints; let database enforce invariants
- Query only what you need; measure before optimizing
Naming & Types
- Tables:
snake_case, plural (users,order_items) - Columns:
snake_case(created_at,user_id) - FKs:
{table}_idreferencing{table}.id - Types: timezone-aware timestamps; strong IDs; precise money types
Relationships
- 1:N: FK in child
- N:N: join table with compound key
- 1:1: FK + UNIQUE
Migrations
- Immutable migrations; always add rollback
- Small, focused steps; test on non-prod first
- Naming:
{seq}_{action}_{object}(e.g.,002_add_email_index)
Query Patterns
- ORM for simple CRUD and safety; raw SQL for complex/perf-critical
- Avoid N+1 (eager load/batching); paginate large sets
- Index FKs and frequently filtered/sorted columns
Connection & Transactions
- Use pooling (size/timeouts based on workload)
- One connection per unit of work; close/return promptly
- Wrap multi-step changes in transactions
Data Integrity
- Use NOT NULL/UNIQUE/CHECK/FK constraints
- Validate at DB when appropriate (defense in depth)
- Prefer generated columns for consistent derivations
Backup & Recovery
- Regular backups with retention; test restores
- Document RPO/RTO targets; monitor backup jobs
Focus on patterns and decisions. No environment-specific settings.
Deployment Standards
[Purpose: safe, repeatable releases with clear environment and pipeline patterns]
Philosophy
- Automate; test before deploy; verify after deploy
- Prefer incremental rollout with fast rollback
- Production changes must be observable and reversible
Environments
- Dev: fast iteration; debugging enabled
- Staging: mirrors prod; release validation
- Prod: hardened; monitored; least privilege
CI/CD Flow
Code → Test → Build → Scan → Deploy (staged) → Verify
Principles:
- Fail fast on tests/scans; block deploy
- Artifact builds are reproducible (lockfiles, pinned versions)
- Manual approval for prod; auditable trail
Deployment Strategies
- Rolling: gradual instance replacement
- Blue-Green: switch traffic between two pools
- Canary: small % users first, expand on health Choose per risk profile; document default.
Zero-Downtime & Migrations
- Health checks gate traffic; graceful shutdown
- Backwards-compatible DB changes during rollout
- Separate migration step; test rollback paths
Rollback
- Keep previous version ready; automate revert
- Rollback faster than fix-forward; document triggers
Configuration & Secrets
- 12-factor config via env; never commit secrets
- Secret manager; rotate; least privilege; audit access
- Validate required env vars at startup
Health & Monitoring
- Endpoints:
/health,/health/live,/health/ready - Monitor latency, error rate, throughput, saturation
- Alerts on SLO breaches/spikes; tune to avoid fatigue
Incident Response & DR
- Standard playbook: detect → assess → mitigate → communicate → resolve → post-mortem
- Backups with retention; test restore; defined RPO/RTO
Focus on rollout patterns and safeguards. No provider-specific steps.
Error Handling Standards
[Purpose: unify how errors are classified, shaped, propagated, logged, and monitored]
Philosophy
- Fail fast where possible; degrade gracefully at system boundaries
- Consistent error shape across the stack (human + machine readable)
- Handle known errors close to source; surface unknowns to a global handler
Classification (decide handling by source)
- Client: Input/validation/user action issues → 4xx
- Server: System failures/unexpected exceptions → 5xx
- Business: Rule/state violations → 4xx (e.g., 409)
- External: 3rd-party/network failures → map to 5xx or 4xx with context
Error Shape (single canonical format)
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable message",
"requestId": "trace-id",
"timestamp": "ISO-8601"
}
}
Principles: stable code enums, no secrets, include trace info.
Propagation (where to convert)
- API layer: Convert domain errors → HTTP status + canonical body
- Service layer: Throw typed business errors, avoid stringly-typed errors
- Data/external layer: Wrap provider errors with safe, actionable codes
- Unknown errors: Bubble to global handler → 500 + generic message
Example pattern:
try { return await useCase(); }
catch (e) {
if (e instanceof BusinessError) return respondMapped(e);
logError(e); return respondInternal();
}
Logging (context over noise)
Log: operation, userId (if available), code, message, stack, requestId, minimal context. Do not log: passwords, tokens, secrets, full PII, full bodies with sensitive data. Levels: ERROR (failures), WARN (recoverable/edge), INFO (key events), DEBUG (diagnostics).
Retry (only when safe)
Retry when: network/timeouts/transient 5xx AND operation is idempotent. Do not retry: 4xx, business errors, non-idempotent flows. Strategy: exponential backoff + jitter, capped attempts; require idempotency keys.
Monitoring & Health
Track: error rates by code/category, latency, saturation; alert on spikes/SLI breaches.
Expose health: /health (live), /health/ready (ready). Link errors to traces.
Focus on patterns and decisions. No implementation details or exhaustive lists.
Security Standards
[Purpose: define security posture with patterns for validation, authz, secrets, and data]
Philosophy
- Defense in depth; least privilege; secure by default; fail closed
- Validate at boundaries; sanitize for context; never trust input
- Separate authentication (who) and authorization (what)
Input & Output
- Validate at API boundaries and UI forms; enforce types and constraints
- Sanitize/escape based on destination (HTML, SQL, shell, logs)
- Prefer allow-lists over block-lists; reject early with minimal detail
Authentication & Authorization
- Authentication: verify identity; issue short-lived tokens/sessions
- Authorization: check permissions before actions; deny by default
- Centralize policies; avoid duplicating checks across code
Pattern:
if (!user.hasPermission('resource:action')) throw ForbiddenError();
Secrets & Configuration
- Never commit secrets; store in secret manager or env
- Rotate regularly; audit access; scope minimal
- Validate required env vars at startup; fail fast on missing
Sensitive Data
- Minimize collection; mask/redact in logs; encrypt at rest and in transit
- Restrict access by role/need-to-know; track access to sensitive records
Session/Token Security
- httpOnly + secure cookies where possible; TLS everywhere
- Short expiration; rotate on refresh; revoke on logout/compromise
- Bind tokens to audience/issuer; include minimal claims
Logging (security-aware)
- Log auth attempts, permission denials, and sensitive operations
- Never log passwords, tokens, secrets, full PII; avoid full bodies
- Include requestId and context to correlate events
Headers & Transport
- Enforce TLS; HSTS
- Set security headers (CSP, X-Frame-Options, X-Content-Type-Options)
- Prefer modern crypto; disable weak protocols/ciphers
Vulnerability Posture
- Prefer secure libraries; keep dependencies updated
- Static/dynamic scans in CI; track and remediate
- Educate team on common classes; encode as patterns above
Focus on patterns and principles. Link concrete configs to ops docs.
Testing Standards
[Purpose: guide what to test, where tests live, and how to structure them]
Philosophy
- Test behavior, not implementation
- Prefer fast, reliable tests; minimize brittle mocks
- Cover critical paths deeply; breadth over 100% pursuit
Organization
Options:
- Co-located:
component.tsx+component.test.tsx - Separate:
/src/...and/tests/...Pick one as default; allow exceptions with rationale.
Naming:
- Files:
*.test.*or*.spec.* - Suites: what is under test; Cases: expected behavior
Test Types
- Unit: single unit, mocked dependencies, very fast
- Integration: multiple units together, mock externals only
- E2E: full flows, minimal mocks, only for critical journeys
Structure (AAA)
it('does X when Y', () => {
// Arrange
const input = setup();
// Act
const result = act(input);
// Assert
expect(result).toEqual(expected);
});
Mocking & Data
- Mock externals (API/DB); never mock the system under test
- Use factories/fixtures; reset state between tests
- Keep test data minimal and intention-revealing
Coverage
- Target: [% overall]; higher for critical domains
- Enforce thresholds in CI; exceptions require review rationale
Focus on patterns and decisions. Tool-specific config lives elsewhere.