Init Repo
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
# Design Document
|
||||
|
||||
## Overview
|
||||
|
||||
This design implements a database schema enhancement to add a `project_id` column to the shots table, establishing a direct relationship between shots and projects. This change improves data integrity, enables project-scoped shot name uniqueness, and provides better query performance for project-based shot operations.
|
||||
|
||||
## Architecture
|
||||
|
||||
The enhancement follows a layered approach:
|
||||
|
||||
1. **Database Layer**: Add project_id column with foreign key constraint and index
|
||||
2. **Model Layer**: Update SQLAlchemy Shot model with project relationship
|
||||
3. **Schema Layer**: Update Pydantic schemas to include project_id
|
||||
4. **API Layer**: Modify endpoints to handle project_id in requests/responses
|
||||
5. **Service Layer**: Update business logic for project-scoped validation
|
||||
6. **Frontend Layer**: Update TypeScript interfaces and components
|
||||
|
||||
## Components and Interfaces
|
||||
|
||||
### Database Schema Changes
|
||||
|
||||
```sql
|
||||
-- Add project_id column to shots table
|
||||
ALTER TABLE shots ADD COLUMN project_id INTEGER;
|
||||
|
||||
-- Create foreign key constraint
|
||||
ALTER TABLE shots ADD CONSTRAINT fk_shots_project_id
|
||||
FOREIGN KEY (project_id) REFERENCES projects(id);
|
||||
|
||||
-- Create index for performance
|
||||
CREATE INDEX idx_shots_project_id ON shots(project_id);
|
||||
|
||||
-- Create composite index for project-scoped name uniqueness
|
||||
CREATE UNIQUE INDEX idx_shots_project_name_unique
|
||||
ON shots(project_id, name) WHERE deleted_at IS NULL;
|
||||
```
|
||||
|
||||
### Model Updates
|
||||
|
||||
**Shot Model (backend/models/shot.py)**:
|
||||
- Add `project_id` column as non-nullable foreign key
|
||||
- Add `project` relationship to Project model
|
||||
- Update uniqueness constraints to be project-scoped
|
||||
- Maintain backward compatibility with episode relationship
|
||||
|
||||
**Project Model (backend/models/project.py)**:
|
||||
- Add `shots` relationship back-reference
|
||||
|
||||
### Schema Updates
|
||||
|
||||
**ShotBase Schema**:
|
||||
- Add optional `project_id` field for API flexibility
|
||||
- Maintain episode_id as primary relationship identifier
|
||||
|
||||
**ShotResponse Schema**:
|
||||
- Include `project_id` in all response payloads
|
||||
- Add computed `project_name` field for frontend convenience
|
||||
|
||||
### API Endpoint Changes
|
||||
|
||||
**Shot Creation Endpoints**:
|
||||
- Automatically derive `project_id` from `episode_id`
|
||||
- Validate project consistency between episode and provided project_id
|
||||
- Update uniqueness validation to be project-scoped
|
||||
|
||||
**Shot Query Endpoints**:
|
||||
- Add optional `project_id` filter parameter
|
||||
- Include project information in response payloads
|
||||
- Maintain existing episode-based filtering
|
||||
|
||||
## Data Models
|
||||
|
||||
### Updated Shot Model Structure
|
||||
|
||||
```python
|
||||
class Shot(Base):
|
||||
__tablename__ = "shots"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
project_id = Column(Integer, ForeignKey("projects.id"), nullable=False, index=True)
|
||||
episode_id = Column(Integer, ForeignKey("episodes.id"), nullable=False)
|
||||
name = Column(String, nullable=False, index=True)
|
||||
# ... other existing fields
|
||||
|
||||
# Relationships
|
||||
project = relationship("Project", back_populates="shots")
|
||||
episode = relationship("Episode", back_populates="shots")
|
||||
# ... other existing relationships
|
||||
|
||||
# Constraints
|
||||
__table_args__ = (
|
||||
UniqueConstraint('project_id', 'name', name='uq_shot_project_name'),
|
||||
)
|
||||
```
|
||||
|
||||
### Frontend Interface Updates
|
||||
|
||||
```typescript
|
||||
interface Shot {
|
||||
id: number
|
||||
project_id: number
|
||||
episode_id: number
|
||||
name: string
|
||||
// ... other existing fields
|
||||
|
||||
// Optional computed fields
|
||||
project_name?: string
|
||||
}
|
||||
|
||||
interface ShotCreate {
|
||||
name: string
|
||||
project_id?: number // Optional, derived from episode if not provided
|
||||
// ... other existing fields
|
||||
}
|
||||
```
|
||||
|
||||
## Correctness Properties
|
||||
|
||||
*A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
|
||||
|
||||
### Property 1: Project-Episode Consistency
|
||||
*For any* shot in the system, the project_id must match the project_id of its associated episode
|
||||
**Validates: Requirements 1.2, 3.3, 4.2**
|
||||
|
||||
### Property 2: Project-Scoped Name Uniqueness
|
||||
*For any* project, shot names must be unique within that project scope (excluding soft-deleted shots)
|
||||
**Validates: Requirements 1.1, 1.4**
|
||||
|
||||
### Property 3: API Response Completeness
|
||||
*For any* shot API response, the response must include both the project_id field and all previously existing fields
|
||||
**Validates: Requirements 1.3, 3.1, 4.1**
|
||||
|
||||
### Property 4: Migration Data Preservation
|
||||
*For any* existing shot before migration, the shot data after migration should be identical except for the addition of the correct project_id derived from the episode relationship
|
||||
**Validates: Requirements 2.4, 2.5**
|
||||
|
||||
### Property 5: Project Filtering Accuracy
|
||||
*For any* project_id filter parameter, the API should return only shots that belong to that specific project
|
||||
**Validates: Requirements 3.4**
|
||||
|
||||
### Property 6: Bulk Operation Consistency
|
||||
*For any* bulk shot creation operation, all created shots must have the same project_id as their target episode
|
||||
**Validates: Requirements 3.5**
|
||||
|
||||
### Property 7: Soft Deletion Project Preservation
|
||||
*For any* shot that undergoes soft deletion, the project_id must be preserved for recovery operations
|
||||
**Validates: Requirements 4.5**
|
||||
|
||||
### Property 8: Permission System Continuity
|
||||
*For any* shot operation that was previously authorized, the same operation should remain authorized after the schema change
|
||||
**Validates: Requirements 4.4**
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Migration Errors
|
||||
- **Orphaned Episodes**: Handle episodes without valid project references
|
||||
- **Data Inconsistency**: Detect and report shots with mismatched episode-project relationships
|
||||
- **Constraint Violations**: Handle existing duplicate shot names within projects
|
||||
|
||||
### Runtime Errors
|
||||
- **Invalid Project ID**: Return 400 Bad Request for non-existent project references
|
||||
- **Project-Episode Mismatch**: Return 400 Bad Request when provided project_id doesn't match episode's project
|
||||
- **Duplicate Shot Names**: Return 409 Conflict for project-scoped name collisions
|
||||
|
||||
### Frontend Error Handling
|
||||
- **Migration Status**: Display migration progress and handle temporary unavailability
|
||||
- **Validation Errors**: Show clear messages for project-scoped naming conflicts
|
||||
- **Fallback Behavior**: Gracefully handle missing project information during transition
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Unit Tests
|
||||
- Test Shot model creation with project_id
|
||||
- Test project-scoped uniqueness validation
|
||||
- Test API endpoint parameter handling
|
||||
- Test schema serialization/deserialization
|
||||
|
||||
### Property-Based Tests
|
||||
- **Property 1 Test**: Generate random shots and verify project-episode consistency
|
||||
- **Property 2 Test**: Generate random shot names within projects and verify uniqueness enforcement
|
||||
- **Property 3 Test**: Create test data, run migration simulation, verify data preservation
|
||||
- **Property 4 Test**: Generate shots with various project_id values and verify foreign key constraints
|
||||
- **Property 5 Test**: Generate API requests in old format and verify response compatibility
|
||||
|
||||
### Integration Tests
|
||||
- Test complete shot creation workflow with project validation
|
||||
- Test shot querying with project filtering
|
||||
- Test bulk shot creation with project consistency
|
||||
- Test soft deletion with project_id preservation
|
||||
|
||||
### Migration Tests
|
||||
- Test migration script with various data scenarios
|
||||
- Test rollback procedures
|
||||
- Test performance with large datasets
|
||||
- Test constraint creation and validation
|
||||
|
||||
The testing approach uses **Pytest** for the Python backend with **Hypothesis** for property-based testing. Each property-based test will run a minimum of 100 iterations to ensure comprehensive coverage of the input space.
|
||||
Reference in New Issue
Block a user