LinkDesk/.kiro/specs/shot-project-id-enhancement/design.md

197 lines
7.5 KiB
Markdown

# 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.