604 lines
19 KiB
YAML
604 lines
19 KiB
YAML
# Design Document Schema
|
|
# The source of truth for system design - all tasks derive from this
|
|
# Created during DESIGNING phase, approved before IMPLEMENTING
|
|
|
|
# ============================================================================
|
|
# NAMING CONVENTIONS (ENFORCED)
|
|
# ============================================================================
|
|
# These conventions ensure consistency between design, types, and implementation
|
|
#
|
|
# DESIGN DOCUMENT uses:
|
|
# - snake_case for field names (e.g., created_at, user_id, stripe_customer_id)
|
|
# - snake_case for table names (e.g., users, order_items)
|
|
# - PascalCase for model/component names (e.g., User, OrderItem, UserCard)
|
|
# - camelCase for props/events (e.g., onClick, showActions, onSubmit)
|
|
#
|
|
# TYPE GENERATOR converts:
|
|
# - snake_case fields → camelCase (e.g., created_at → createdAt)
|
|
# - This matches TypeScript/Prisma client conventions
|
|
#
|
|
# VALIDATION:
|
|
# - Field names MUST be snake_case (lowercase with underscores)
|
|
# - Model/Component names MUST be PascalCase
|
|
# - Props/Events MUST be camelCase
|
|
#
|
|
# Examples:
|
|
# ✅ CORRECT:
|
|
# - Field: user_id, created_at, stripe_customer_id
|
|
# - Model: User, OrderItem, PaymentIntent
|
|
# - Prop: showActions, isLoading, maxItems
|
|
#
|
|
# ❌ WRONG:
|
|
# - Field: userId (should be user_id)
|
|
# - Field: CreatedAt (should be created_at)
|
|
# - Model: user_card (should be UserCard)
|
|
# - Prop: show_actions (should be showActions)
|
|
#
|
|
naming_conventions:
|
|
fields:
|
|
pattern: snake_case
|
|
description: "Field names use snake_case (e.g., user_id, created_at)"
|
|
examples:
|
|
valid: [id, user_id, created_at, stripe_customer_id, first_name]
|
|
invalid: [userId, createdAt, stripeCustomerId, firstName]
|
|
|
|
models:
|
|
pattern: PascalCase
|
|
description: "Model names use PascalCase (e.g., User, OrderItem)"
|
|
examples:
|
|
valid: [User, OrderItem, PaymentIntent, UserSubscription]
|
|
invalid: [user, order_item, payment_intent]
|
|
|
|
components:
|
|
pattern: PascalCase
|
|
description: "Component names use PascalCase (e.g., UserCard, LoginForm)"
|
|
examples:
|
|
valid: [UserCard, LoginForm, PaymentButton]
|
|
invalid: [userCard, login_form]
|
|
|
|
props:
|
|
pattern: camelCase
|
|
description: "Props use camelCase (e.g., showActions, isLoading)"
|
|
examples:
|
|
valid: [showActions, isLoading, maxItems, onSubmit]
|
|
invalid: [show_actions, is_loading]
|
|
|
|
events:
|
|
pattern: camelCase
|
|
description: "Events use camelCase with 'on' prefix (e.g., onClick, onSubmit)"
|
|
examples:
|
|
valid: [onClick, onSubmit, onDelete, onValueChange]
|
|
invalid: [on_click, OnSubmit]
|
|
|
|
tables:
|
|
pattern: snake_case
|
|
description: "Table names use snake_case plural (e.g., users, order_items)"
|
|
examples:
|
|
valid: [users, order_items, payment_intents]
|
|
invalid: [Users, OrderItems]
|
|
|
|
# ============================================================================
|
|
# DOCUMENT METADATA
|
|
# ============================================================================
|
|
design_document:
|
|
# Links to workflow
|
|
workflow_version: string # e.g., v001
|
|
feature: string # Feature being implemented
|
|
|
|
# Timestamps
|
|
created_at: timestamp
|
|
updated_at: timestamp
|
|
approved_at: timestamp | null
|
|
|
|
# Design status
|
|
status: draft | review | approved | rejected
|
|
|
|
# Revision tracking
|
|
revision: integer # Increments on changes
|
|
revision_notes: string # What changed in this revision
|
|
|
|
# ============================================================================
|
|
# EXTERNAL DEPENDENCIES (Already Implemented)
|
|
# ============================================================================
|
|
# Use this section to reference models, APIs, or components that already exist
|
|
# in the codebase and are NOT part of this design document. This allows your
|
|
# new entities to depend on existing implementations without validation errors.
|
|
#
|
|
# Supports two formats:
|
|
# Simple: - ModelName
|
|
# Detailed: - id: ModelName
|
|
# - name: "Human readable name"
|
|
# - description: "What this provides"
|
|
#
|
|
external_dependencies:
|
|
description: "Pre-existing entities that new entities can depend on"
|
|
|
|
# Existing data models (Prisma models, database tables)
|
|
models:
|
|
- id: string # Model ID or name (e.g., User, Label, Artist)
|
|
name: string # Optional: Human-readable name
|
|
description: string # Optional: What this model provides
|
|
|
|
# Existing API endpoints
|
|
api_endpoints:
|
|
- id: string # API ID (e.g., api_get_labels)
|
|
summary: string # Optional: What this API does
|
|
path: string # Optional: API path for reference
|
|
|
|
# Existing UI components
|
|
components:
|
|
- id: string # Component ID (e.g., component_button)
|
|
name: string # Optional: Component name
|
|
description: string # Optional: What this component provides
|
|
|
|
# Example usage:
|
|
example:
|
|
models:
|
|
# Simple format (just the ID)
|
|
- User
|
|
- Label
|
|
|
|
# Detailed format
|
|
- id: Artist
|
|
name: "Artist Model"
|
|
description: "Existing artist entity with name, image, popularity"
|
|
|
|
api_endpoints:
|
|
- id: api_get_labels
|
|
summary: "Get all music labels"
|
|
path: "/api/labels"
|
|
|
|
components:
|
|
- id: component_button
|
|
name: "Button"
|
|
description: "Standard button component"
|
|
|
|
# ============================================================================
|
|
# LAYER 1: DATA MODELS (ER Diagram)
|
|
# ============================================================================
|
|
data_models:
|
|
description: "Database entities and their relationships"
|
|
|
|
model_schema:
|
|
# Identity
|
|
id: string # model_<name> (e.g., model_user, model_post)
|
|
name: string # PascalCase entity name (e.g., User, Post)
|
|
description: string # What this model represents
|
|
|
|
# Table/Collection info
|
|
table_name: string # snake_case (e.g., users, posts)
|
|
|
|
# Fields
|
|
fields:
|
|
- name: string # snake_case field name
|
|
type: enum # string | integer | boolean | datetime | uuid | json | text | float | decimal | enum
|
|
constraints: [enum] # primary_key | foreign_key | unique | not_null | indexed | auto_increment | default
|
|
default: any # Default value if constraint includes 'default'
|
|
enum_values: [string] # If type is 'enum', list valid values
|
|
description: string # Field purpose
|
|
|
|
# Relations to other models
|
|
relations:
|
|
- type: enum # has_one | has_many | belongs_to | many_to_many
|
|
target: string # Target model_id (e.g., model_post)
|
|
foreign_key: string # FK field name
|
|
through: string # Junction table for many_to_many
|
|
on_delete: enum # cascade | set_null | restrict | no_action
|
|
|
|
# Indexes
|
|
indexes:
|
|
- fields: [string] # Fields in index
|
|
unique: boolean # Is unique index
|
|
name: string # Index name
|
|
|
|
# Timestamps (common pattern)
|
|
timestamps: boolean # Auto-add created_at, updated_at
|
|
soft_delete: boolean # Add deleted_at for soft deletes
|
|
|
|
# Validation rules (business logic)
|
|
validations:
|
|
- field: string # Field to validate
|
|
rule: string # Validation rule (e.g., "email", "min:8", "max:100")
|
|
message: string # Error message
|
|
|
|
# Example
|
|
example_model:
|
|
id: model_user
|
|
name: User
|
|
description: "Application user account"
|
|
table_name: users
|
|
fields:
|
|
- name: id
|
|
type: uuid
|
|
constraints: [primary_key]
|
|
description: "Unique identifier"
|
|
- name: email
|
|
type: string
|
|
constraints: [unique, not_null, indexed]
|
|
description: "User email address"
|
|
- name: name
|
|
type: string
|
|
constraints: [not_null]
|
|
description: "Display name"
|
|
- name: password_hash
|
|
type: string
|
|
constraints: [not_null]
|
|
description: "Bcrypt hashed password"
|
|
- name: role
|
|
type: enum
|
|
enum_values: [user, admin, moderator]
|
|
constraints: [not_null, default]
|
|
default: user
|
|
description: "User role for authorization"
|
|
relations:
|
|
- type: has_many
|
|
target: model_post
|
|
foreign_key: user_id
|
|
on_delete: cascade
|
|
timestamps: true
|
|
soft_delete: false
|
|
validations:
|
|
- field: email
|
|
rule: email
|
|
message: "Invalid email format"
|
|
- field: password_hash
|
|
rule: min:60
|
|
message: "Invalid password hash"
|
|
|
|
# ============================================================================
|
|
# LAYER 2: API ENDPOINTS
|
|
# ============================================================================
|
|
api_endpoints:
|
|
description: "REST API endpoints with request/response contracts"
|
|
|
|
endpoint_schema:
|
|
# Identity
|
|
id: string # api_<verb>_<resource> (e.g., api_create_user)
|
|
|
|
# HTTP
|
|
method: enum # GET | POST | PUT | PATCH | DELETE
|
|
path: string # URL path (e.g., /api/users/:id)
|
|
|
|
# Description
|
|
summary: string # Short description
|
|
description: string # Detailed description
|
|
|
|
# Tags for grouping
|
|
tags: [string] # e.g., [users, authentication]
|
|
|
|
# Path parameters
|
|
path_params:
|
|
- name: string # Parameter name (e.g., id)
|
|
type: string # Data type
|
|
description: string
|
|
|
|
# Query parameters (for GET)
|
|
query_params:
|
|
- name: string # Parameter name
|
|
type: string # Data type
|
|
required: boolean
|
|
default: any
|
|
description: string
|
|
|
|
# Request body (for POST/PUT/PATCH)
|
|
request_body:
|
|
content_type: string # application/json
|
|
schema:
|
|
type: object | array
|
|
properties:
|
|
- name: string
|
|
type: string
|
|
required: boolean
|
|
validations: [string] # Validation rules
|
|
description: string
|
|
example: object # Example request body
|
|
|
|
# Response schemas by status code
|
|
responses:
|
|
- status: integer # HTTP status code
|
|
description: string
|
|
schema:
|
|
type: object | array
|
|
properties:
|
|
- name: string
|
|
type: string
|
|
example: object
|
|
|
|
# Dependencies
|
|
depends_on_models: [string] # model_ids this endpoint uses
|
|
depends_on_apis: [string] # api_ids this endpoint calls (internal)
|
|
|
|
# Authentication/Authorization
|
|
auth:
|
|
required: boolean
|
|
roles: [string] # Required roles (empty = any authenticated)
|
|
|
|
# Rate limiting
|
|
rate_limit:
|
|
requests: integer # Max requests
|
|
window: string # Time window (e.g., "1m", "1h")
|
|
|
|
# Example
|
|
example_endpoint:
|
|
id: api_create_user
|
|
method: POST
|
|
path: /api/users
|
|
summary: "Create a new user"
|
|
description: "Register a new user account with email and password"
|
|
tags: [users, authentication]
|
|
request_body:
|
|
content_type: application/json
|
|
schema:
|
|
type: object
|
|
properties:
|
|
- name: email
|
|
type: string
|
|
required: true
|
|
validations: [email]
|
|
description: "User email address"
|
|
- name: name
|
|
type: string
|
|
required: true
|
|
validations: [min:1, max:100]
|
|
description: "Display name"
|
|
- name: password
|
|
type: string
|
|
required: true
|
|
validations: [min:8]
|
|
description: "Password (will be hashed)"
|
|
example:
|
|
email: "user@example.com"
|
|
name: "John Doe"
|
|
password: "securepass123"
|
|
responses:
|
|
- status: 201
|
|
description: "User created successfully"
|
|
schema:
|
|
type: object
|
|
properties:
|
|
- name: id
|
|
type: uuid
|
|
- name: email
|
|
type: string
|
|
- name: name
|
|
type: string
|
|
- name: created_at
|
|
type: datetime
|
|
example:
|
|
id: "550e8400-e29b-41d4-a716-446655440000"
|
|
email: "user@example.com"
|
|
name: "John Doe"
|
|
created_at: "2025-01-16T10:00:00Z"
|
|
- status: 400
|
|
description: "Validation error"
|
|
schema:
|
|
type: object
|
|
properties:
|
|
- name: error
|
|
type: string
|
|
- name: details
|
|
type: array
|
|
example:
|
|
error: "Validation failed"
|
|
details: ["Email is invalid", "Password too short"]
|
|
- status: 409
|
|
description: "Email already exists"
|
|
schema:
|
|
type: object
|
|
properties:
|
|
- name: error
|
|
type: string
|
|
example:
|
|
error: "Email already registered"
|
|
depends_on_models: [model_user]
|
|
depends_on_apis: []
|
|
auth:
|
|
required: false
|
|
roles: []
|
|
|
|
# ============================================================================
|
|
# LAYER 3: UI PAGES
|
|
# ============================================================================
|
|
pages:
|
|
description: "Application pages/routes"
|
|
|
|
page_schema:
|
|
# Identity
|
|
id: string # page_<name> (e.g., page_users, page_user_detail)
|
|
name: string # Human-readable name
|
|
|
|
# Routing
|
|
path: string # URL path (e.g., /users, /users/[id])
|
|
layout: string # Layout component to use
|
|
|
|
# Data requirements
|
|
data_needs:
|
|
- api_id: string # API endpoint to call
|
|
purpose: string # Why this data is needed
|
|
on_load: boolean # Fetch on page load
|
|
|
|
# Components used
|
|
components: [string] # component_ids used on this page
|
|
|
|
# SEO
|
|
seo:
|
|
title: string
|
|
description: string
|
|
|
|
# Auth requirements
|
|
auth:
|
|
required: boolean
|
|
roles: [string]
|
|
redirect: string # Where to redirect if not authorized
|
|
|
|
# State management
|
|
state:
|
|
local: [string] # Local state variables
|
|
global: [string] # Global state dependencies
|
|
|
|
# Example
|
|
example_page:
|
|
id: page_users
|
|
name: "Users List"
|
|
path: /users
|
|
layout: layout_dashboard
|
|
data_needs:
|
|
- api_id: api_list_users
|
|
purpose: "Display user list"
|
|
on_load: true
|
|
components: [component_user_list, component_user_card, component_pagination]
|
|
seo:
|
|
title: "Users"
|
|
description: "View all users"
|
|
auth:
|
|
required: true
|
|
roles: [admin]
|
|
redirect: /login
|
|
|
|
# ============================================================================
|
|
# LAYER 3: UI COMPONENTS
|
|
# ============================================================================
|
|
components:
|
|
description: "Reusable UI components"
|
|
|
|
component_schema:
|
|
# Identity
|
|
id: string # component_<name> (e.g., component_user_card)
|
|
name: string # PascalCase component name
|
|
|
|
# Props (input)
|
|
props:
|
|
- name: string # Prop name
|
|
type: string # TypeScript type
|
|
required: boolean
|
|
default: any
|
|
description: string
|
|
|
|
# Events (output)
|
|
events:
|
|
- name: string # Event name (e.g., onClick, onSubmit)
|
|
payload: string # Payload type
|
|
description: string
|
|
|
|
# API calls (if component fetches data)
|
|
uses_apis: [string] # api_ids this component calls directly
|
|
|
|
# Child components
|
|
uses_components: [string] # component_ids used inside this component
|
|
|
|
# State
|
|
internal_state: [string] # Internal state variables
|
|
|
|
# Styling
|
|
variants: [string] # Style variants (e.g., primary, secondary)
|
|
|
|
# Example
|
|
example_component:
|
|
id: component_user_card
|
|
name: UserCard
|
|
props:
|
|
- name: user
|
|
type: User
|
|
required: true
|
|
description: "User object to display"
|
|
- name: showActions
|
|
type: boolean
|
|
required: false
|
|
default: true
|
|
description: "Show edit/delete buttons"
|
|
events:
|
|
- name: onEdit
|
|
payload: "User"
|
|
description: "Fired when edit button clicked"
|
|
- name: onDelete
|
|
payload: "string"
|
|
description: "Fired when delete confirmed, payload is user ID"
|
|
uses_apis: []
|
|
uses_components: [component_avatar, component_button]
|
|
internal_state: [isDeleting]
|
|
variants: [default, compact]
|
|
|
|
# ============================================================================
|
|
# DEPENDENCY GRAPH (Auto-generated from above)
|
|
# ============================================================================
|
|
dependency_graph:
|
|
description: "Execution order based on dependencies - auto-generated"
|
|
|
|
# Layers for parallel execution
|
|
layers:
|
|
- layer: 1
|
|
name: "Data Models"
|
|
description: "Database schema - no dependencies"
|
|
items:
|
|
- id: string # Entity ID
|
|
type: model # model | api | page | component
|
|
dependencies: [] # Empty for layer 1
|
|
|
|
- layer: 2
|
|
name: "API Endpoints"
|
|
description: "Backend APIs - depend on models"
|
|
items:
|
|
- id: string
|
|
type: api
|
|
dependencies: [string] # model_ids
|
|
|
|
- layer: 3
|
|
name: "UI Layer"
|
|
description: "Pages and components - depend on APIs"
|
|
items:
|
|
- id: string
|
|
type: page | component
|
|
dependencies: [string] # api_ids, component_ids
|
|
|
|
# Full dependency map for visualization
|
|
dependency_map:
|
|
model_user:
|
|
depends_on: []
|
|
depended_by: [api_create_user, api_list_users, api_get_user]
|
|
api_create_user:
|
|
depends_on: [model_user]
|
|
depended_by: [page_user_create, component_user_form]
|
|
page_users:
|
|
depends_on: [api_list_users, component_user_list]
|
|
depended_by: []
|
|
|
|
# ============================================================================
|
|
# DESIGN VALIDATION RULES
|
|
# ============================================================================
|
|
validation_rules:
|
|
external_dependencies:
|
|
- "External entities are treated as pre-existing (already implemented)"
|
|
- "External entities don't require task generation"
|
|
- "External models can be referenced in relations and depends_on_models"
|
|
- "External APIs can be referenced in depends_on_apis and data_needs"
|
|
- "External components can be referenced in uses_components and page components"
|
|
|
|
models:
|
|
- "Every model must have a primary_key field"
|
|
- "Foreign keys must reference existing models"
|
|
- "Relation targets must exist in data_models OR external_dependencies.models"
|
|
- "Enum types must have enum_values defined"
|
|
|
|
apis:
|
|
- "Every API must have at least one response defined"
|
|
- "POST/PUT/PATCH must have request_body"
|
|
- "depends_on_models must reference existing models OR external_dependencies.models"
|
|
- "depends_on_apis must reference existing APIs OR external_dependencies.api_endpoints"
|
|
- "Path params must match :param patterns in path"
|
|
|
|
pages:
|
|
- "data_needs must reference existing api_ids OR external_dependencies.api_endpoints"
|
|
- "components must reference existing component_ids OR external_dependencies.components"
|
|
- "auth.redirect must be a valid path"
|
|
|
|
components:
|
|
- "uses_apis must reference existing api_ids OR external_dependencies.api_endpoints"
|
|
- "uses_components must reference existing component_ids OR external_dependencies.components"
|
|
- "No circular component dependencies"
|
|
|
|
graph:
|
|
- "No circular dependencies in dependency_graph"
|
|
- "All entities must be assigned to a layer"
|
|
- "Layer N items can only depend on Layer < N items OR external dependencies"
|
|
- "External dependencies are treated as Layer 0 (pre-existing)"
|