Product Plan 仕様書
バージョン 0.1.0 — 2026年2月
Product Plan は、プロダクトの実装方法を記述する。product.lock.json の実装ブループリントである。
Lock は WHAT(何を構築するか)を定義する。Plan は HOW(どう構築するか)を定義する。
Plan はAIが読むためのものである。人間はスキップできるが、問題が起きたときに理解できる。
完全なロック仕様については、Product Lock Specification を参照のこと。
目次
1. ファイル間の関係
product.lock.json → プロダクトが何であるか(WHAT)(人間が承認する)
product.plan.md → どう構築するか(HOW)(AIが従う)
codebase → 実際のプロダクト(AI Reviewer がロックに照らして検証する)
| 持っているもの | できること |
|---|---|
| Lock のみ | AIがプロダクトを構築し、実装に関する判断を自ら行う |
| Lock + Plan | AIが同じアーキテクチャで全く同じプロダクトを構築する |
| Lock + Plan + Codebase | AI Reviewer がすべてが一致しているか検証する |
| Plan のみ | AIは構築できるが、検証すべきプロダクト境界がない |
2. 設計原則
- Lock から派生する — Plan は Lock が定義するすべてを、省略なく矛盾なく実装しなければならない(MUST)
- 再現可能 — 同じ Plan を読んだ異なるAIエージェントが、構造的に同一のコードベースを生成すべきである(SHOULD)
- プレーンテキスト — Markdown 形式。圧縮、エンコード、暗号化はしない
- 完全 — Plan には Lock がカバーしないすべての実装判断が含まれる。この Plan を持つAIは直接コードを書ける
- スタック固有 — 同じ Lock に対して複数の Plan を持てる(TypeScript 版、Python 版、Go 版)
3. フォーマット
ファイル名は product.plan.md でなければならず(MUST)、product.lock.json と並べてプロジェクトルートに配置する。
# Product Plan: {name} v{version}
> Lock: product.lock.json
> Stack: {一行のスタック要約}
> Generated: {日付}
## Stack
| Layer | Choice |
|-------|--------|
| Language | TypeScript 5.x |
| Runtime | Node.js 20 |
| Framework | Next.js 15 (App Router) |
| Database | PostgreSQL 16 |
| ORM | Prisma 6 |
| Auth | Supabase Auth (magic link) |
| Validation | Zod |
| State | TanStack Query + Zustand |
| Styling | Tailwind CSS 4 + shadcn/ui |
| Deploy | Vercel |
## Schemas
{型、制約、リレーションを含む完全なエンティティスキーマ。}
## Endpoints
{すべての機能の API コントラクト。}
## Implementation Steps
{ゼロから構築するための順序付きステップ。}
4. 必須セクション
すべての Plan は以下のセクションを含まなければならない(MUST)。
4.1 Stack
プロダクトの各レイヤーの技術選定。
## Stack
| Layer | Choice |
|-------|--------|
| Language | TypeScript 5.x |
| Runtime | Node.js 20 |
| Framework | Next.js 15 (App Router) |
| Database | PostgreSQL 16 |
| ORM | Prisma 6 |
| Auth | Supabase Auth (magic link) |
| Validation | Zod |
| State | TanStack Query + Zustand |
| Styling | Tailwind CSS 4 + shadcn/ui |
| Deploy | Vercel |
4.2 Schemas
型、制約、リレーション、インデックスを含む完全なエンティティ定義。Lock の entities がコードで何になるかを示す。
## Schemas
### User
| Field | Type | Constraints |
|-------|------|-------------|
| id | uuid | PK, default gen_random_uuid() |
| email | varchar(255) | UNIQUE, NOT NULL |
| name | varchar(100) | NOT NULL |
| avatarUrl | text | nullable |
| role | enum(Admin,Member,Guest) | NOT NULL, default 'Member' |
| createdAt | timestamptz | NOT NULL, default now() |
Relations: has many Message, has many Conversation (via membership)
### Message
| Field | Type | Constraints |
|-------|------|-------------|
| id | uuid | PK |
| content | text | NOT NULL |
| senderId | uuid | FK → User.id, NOT NULL |
| conversationId | uuid | FK → Conversation.id, NOT NULL |
| createdAt | timestamptz | NOT NULL, default now() |
Relations: belongs to User (sender), belongs to Conversation
Index: (conversationId, createdAt)
Plan は Lock で指定されたフィールドだけでなく、すべてのフィールドを含まなければならない(MUST)。Lock に ["id", "name", "email"] がある場合、Plan は型、制約、デフォルト値、リレーション、インデックスを追加する。Plan は Lock に記載されていないフィールド(例:createdAt、updatedAt)を追加してもよい(MAY)。
4.3 Endpoints
各機能を実装する API エンドポイント。Lock 内のすべての機能は少なくとも1つのエンドポイント(またはバックグラウンドジョブ)にマッピングされなければならない(MUST)。
## Endpoints
### Messages
#### sendMessage
- `POST /api/messages`
- Auth: Member, Admin
- Body: `{ content: string, conversationId: string }`
- Response: `201 { message: Message }`
- Side effects: broadcast to conversation subscribers
- Validation: content 1-5000 chars, conversationId must exist
#### deleteMessage
- `DELETE /api/messages/:id`
- Auth: Admin only (or message owner)
- Response: `204`
各エンドポイントは以下を含まなければならない(MUST):
- HTTP メソッドとパス
- 認証要件
- リクエストボディ / クエリパラメータ
- レスポンスの形状とステータスコード
- バリデーションルール
- 副作用(ある場合)
4.4 Implementation Steps
ゼロから構築するための順序付きステップ。AIがこれらのステップに従うことで完全なプロダクトを生成する。
## Implementation Steps
1. Initialize Next.js 15 project with TypeScript
2. Install dependencies: prisma, @supabase/supabase-js, zod, tailwindcss
3. Configure Prisma schema with all entities
4. Run prisma migrate to create database
5. Set up Supabase Auth with magic link
6. Create auth middleware
7. Implement API routes: messages, conversations, groups
8. Implement background jobs: fetchNews, enrichNews
9. Create UI pages: login, dashboard, conversations, settings
10. Configure RLS policies
11. Test all features against lock
12. Generate product.lock.json and verify
ルール:
- 番号付き、順序付き
- 各ステップは独立して検証可能であるべき(SHOULD)
- 粒度:各ステップ ≒ AIの1作業セッション
5. 任意セクション
プロダクトが必要とする場合にこれらのセクションを含める。
5.1 Architecture
非自明なパターンが使用される場合(マイクロサービス、イベントソーシング、CQRS など)。
## Architecture
REST API with Next.js Route Handlers. Supabase handles auth, database, storage, and real-time subscriptions. Single deployment on Vercel.
- API: Next.js Route Handlers (REST)
- Auth: Supabase middleware, RLS on database
- Real-time: Supabase Realtime subscriptions
- File storage: Supabase Storage
5.2 File Structure
プロジェクトのレイアウトが非標準または説明が必要な場合。
## File Structure
├── prisma/schema.prisma
├── src/
│ ├── app/
│ │ ├── (auth)/login/
│ │ ├── (dashboard)/
│ │ └── api/
│ ├── components/
│ │ ├── ui/ ← shadcn プリミティブ
│ │ └── features/ ← ドメインコンポーネント
│ ├── lib/
│ │ ├── db.ts
│ │ ├── auth.ts
│ │ └── validations/
│ ├── hooks/
│ └── types/
└── package.json
5.3 Auth & Permissions
Lock に actors や permissions がある場合。
## Auth & Permissions
- Auth method: Supabase magic link (email OTP)
- Session: JWT stored in httpOnly cookie
- Middleware: `src/lib/auth.ts` extracts user + role
- Route protection: middleware checks role before handler
| Actor | Implementation |
|-------|---------------|
| Admin | role='admin' in users table, full access |
| Member | role='member', default for new signups |
| Guest | no auth, public routes only |
RLS policies:
- messages: SELECT for conversation members, INSERT for Member/Admin
- conversations: SELECT for members, INSERT for Member/Admin
5.4 Background Jobs
Lock にシステムストーリー(自律的な振る舞い)がある場合。
## Background Jobs
### fetchNews
- Trigger: cron every 30 minutes
- Process: fetch from RSS feeds → parse → store as NewsArticle
- Error handling: retry 3x, log failures
### enrichNewsWithAi
- Trigger: after new NewsArticle created
- Process: call local LLM → generate summary, impact, signal → update article
- Rate limit: 10 req/min to LLM
5.5 Third-party Services
外部サービスを使用する場合。
## Third-party Services
| Service | Purpose | Config |
|---------|---------|--------|
| Supabase | Auth + DB + Storage + Realtime | SUPABASE_URL, SUPABASE_ANON_KEY |
| OpenAI / Local LLM | AI enrichment | OPENAI_API_KEY or OLLAMA_URL |
| Resend | Transactional email | RESEND_API_KEY |
5.6 Environment Variables
外部設定が必要な場合。
## Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| DATABASE_URL | Yes | PostgreSQL connection string |
| SUPABASE_URL | Yes | Supabase project URL |
| SUPABASE_ANON_KEY | Yes | Supabase anonymous key |
| OPENAI_API_KEY | No | OpenAI API key (if not using local LLM) |
5.7 Denied Items Implementation
Lock に denied フィールドがある場合。
## Denied Items Implementation
- videoCall: no WebRTC, no video-related dependencies, no video UI
- voiceCall: no audio streaming, no voice-related dependencies
- Reaction: no reaction model, no reaction endpoints, no emoji picker on messages
6. 規約
6.1 命名規則
Plan は Lock の規約ではなく、ターゲット言語の規約を使用する。
| Lock の記述 | TypeScript の Plan | Python の Plan | Go の Plan |
|---|---|---|---|
sendMessage (camelCase) |
sendMessage |
send_message |
SendMessage |
User (PascalCase) |
User |
User (class) / users (table) |
User |
6.2 Schemas
- Lock で指定されたフィールドだけでなく、すべてのフィールドを含める
- Lock に
["id", "name", "email"]がある場合、Plan は型、制約、デフォルト値、リレーション、インデックスを追加する - Plan は Lock に記載されていないフィールド(例:
createdAt、updatedAt)を追加してもよい(MAY)— Lock は指定されたものだけを制約する
6.3 Endpoints
- Lock 内のすべての機能は少なくとも1つのエンドポイント(またはバックグラウンドジョブ)にマッピングされなければならない(MUST)
- リクエスト/レスポンスの形状を含める
- 認証要件を含める
- バリデーションルールを含める
- 副作用を含める
6.4 Implementation Steps
- 番号付き、順序付き
- 各ステップは独立して検証可能であるべき(SHOULD)(「ステップ5の後、認証が動作するはず」)
- 粒度:各ステップ ≒ AIの1作業セッション
7. Lock と Plan の比較
| 側面 | Lock | Plan |
|---|---|---|
| 対象 | 人間(承認/拒否) | AI(実装) |
| 内容 | プロダクト境界(WHAT) | 実装ブループリント(HOW) |
| フォーマット | JSON(決定的) | Markdown(可読) |
| スタック | 言及しない | 完全に指定 |
| エンティティフィールド | 名前のみ | 名前 + 型 + 制約 + リレーション |
| 機能 | 能力の名前 | 完全な API コントラクト |
| ストーリー | 自然言語のフロー | エンドポイント + バックグラウンドジョブへのマッピング |
| パーミッション | ロール-機能マトリクス | 認証ミドルウェア + RLS ポリシー |
| ポータビリティ | 言語非依存 | スタック固有 |
この仕様は Product Lock Specification の一部です。