# StarPunk v1.5.0 Release **Status**: Planning **Codename**: "Trigger" **Focus**: Cleanup, Test Coverage, and Quality of Life Improvements ## Overview This minor release focuses on technical debt reduction, improving test coverage to 90%, and addressing quality-of-life issues identified in previous release reviews. No new user-facing features are planned. ## Goals 1. **90% Test Coverage** - Increase overall test coverage from current baseline to 90% 2. **Address Backlog Technical Debt** - Resolve 6 specific backlog items 3. **Improve Code Quality** - Better error handling, atomicity, and performance ## Features ### 1. Test Coverage Target: 90% Increase overall test coverage to 90% minimum across all modules. #### Scope - Identify modules with coverage below 90% - Write missing unit tests for uncovered code paths - Add integration tests for critical workflows - Ensure edge cases and error paths are tested #### Acceptance Criteria - `uv run pytest --cov=starpunk` reports ≥90% overall coverage - No module below 85% coverage - All new code in this release has 100% coverage --- ### 2. MPO Format Test Coverage **Source**: Backlog - High Priority (Developer Review M1) Add test coverage for MPO (Multi-Picture Object) format handling. #### Current State - MPO conversion code exists at `starpunk/media.py` lines 163-173 - Advertised in CHANGELOG but untested #### Implementation - Add `test_mpo_detection_and_conversion()` to `TestHEICSupport` class - Create MPO test image using Pillow's MPO support - Test primary image extraction - Test conversion to JPEG #### Acceptance Criteria - MPO detection tested - MPO to JPEG conversion tested - Edge cases (corrupted MPO, single-frame MPO) tested --- ### 3. Debug File Storage Cleanup **Source**: Backlog - Medium Priority (Developer Review M2, Architect Review 1.2.2) Implement cleanup mechanism for failed upload debug files. #### Current State - Failed uploads saved to `data/debug/` directory - No cleanup mechanism exists - Potential disk space exhaustion #### Implementation 1. Add `DEBUG_SAVE_FAILED_UPLOADS` config option (default: `false` in production) 2. Implement automatic cleanup for files older than 7 days 3. Add disk space check or size limit (100MB max for debug folder) 4. Cleanup runs on application startup and periodically #### Configuration ```python DEBUG_SAVE_FAILED_UPLOADS = False # Enable only for debugging DEBUG_FILE_MAX_AGE_DAYS = 7 # Auto-delete after 7 days DEBUG_FILE_MAX_SIZE_MB = 100 # Maximum debug folder size ``` #### Acceptance Criteria - Debug files disabled by default in production - Old files automatically cleaned up when enabled - Disk space protected with size limit - Tests cover all cleanup scenarios --- ### 4. Filename Sanitization in Debug Path **Source**: Backlog - Medium Priority (Architect Review 1.2.3) Sanitize filenames before use in debug file paths. #### Current State - Original filename used directly at `starpunk/media.py` line 135 - Path traversal or special character issues possible #### Implementation ```python safe_filename = "".join(c for c in filename if c.isalnum() or c in "._-")[:50] ``` #### Acceptance Criteria - Filenames sanitized before debug path construction - Path traversal attempts neutralized - Special characters removed - Filename length limited - Tests cover malicious filename patterns --- ### 5. N+1 Query Pattern Fix **Source**: Backlog - Medium Priority (Architect Review 2.2.9) Eliminate N+1 query pattern in feed generation. #### Current State - `_get_cached_notes()` loads media and tags per-note - For 50 notes: 100 additional database queries - Performance degrades with note count #### Implementation 1. Create `get_media_for_notes(note_ids: List[int])` batch function 2. Create `get_tags_for_notes(note_ids: List[int])` batch function 3. Use single query with `WHERE note_id IN (...)` 4. Update `_get_cached_notes()` to use batch loading #### Example ```python def get_media_for_notes(note_ids: List[int]) -> Dict[int, List[dict]]: """Batch load media for multiple notes.""" # Single query: SELECT * FROM note_media WHERE note_id IN (?) # Returns: {note_id: [media_list]} ``` #### Acceptance Criteria - Feed generation uses batch queries - Query count reduced from O(n) to O(1) for media/tags - Performance improvement measurable in tests - No change to API behavior --- ### 6. Atomic Variant Generation **Source**: Backlog - Medium Priority (Architect Review 2.2.6) Make variant file generation atomic with database commits. #### Current State - Files written to disk before database commit - Database commit failure leaves orphaned files #### Implementation 1. Write variant files to temporary location first 2. Database insert in transaction 3. Move files to final location after successful commit 4. Cleanup temp files on any failure #### Flow ``` 1. Generate variants to temp directory 2. BEGIN TRANSACTION 3. INSERT media record 4. INSERT variant records 5. COMMIT 6. Move files from temp to final location 7. On failure: rollback DB, delete temp files ``` #### Acceptance Criteria - No orphaned files on database failures - No orphaned database records on file failures - Atomic operation for all media saves - Tests simulate failure scenarios --- ### 7. Default Slug Format Change **Source**: Backlog - Medium Priority Change default slug format from content-based to timestamp-based. #### Current State - Slugs generated from note content - Can produce unwanted slugs from private content #### New Format - Default: `YYYYMMDDHHMMSS` (e.g., `20251216143052`) - Duplicate handling: append `-1`, `-2`, etc. - Custom slugs still supported via `mp-slug` #### Implementation 1. Update `generate_slug()` function in `starpunk/slug_utils.py` 2. Generate timestamp-based slug by default 3. Check for duplicates and append suffix if needed 4. Preserve custom slug functionality #### Example ```python def generate_slug(content: str = None, custom_slug: str = None) -> str: if custom_slug: return sanitize_slug(custom_slug) # Default: timestamp-based timestamp = datetime.now().strftime("%Y%m%d%H%M%S") return ensure_unique_slug(timestamp) ``` #### Acceptance Criteria - New notes use timestamp slugs by default - Duplicate timestamps handled with suffix - Custom `mp-slug` still works - Existing notes unchanged - Tests cover all slug generation scenarios --- ## Out of Scope - New user-facing features - UI changes - New feed formats - Micropub extensions - Database schema changes (except for bug fixes) ## Dependencies - v1.4.x complete - No new external dependencies expected ## Success Criteria 1. ✅ Test coverage ≥90% overall 2. ✅ MPO format has test coverage 3. ✅ Debug file cleanup implemented and tested 4. ✅ Filename sanitization implemented and tested 5. ✅ N+1 query pattern eliminated 6. ✅ Variant generation is atomic 7. ✅ Default slugs are timestamp-based 8. ✅ All existing tests continue to pass 9. ✅ No regressions in functionality ## Related Backlog Items After completion, the following backlog items should be marked complete or moved to "Recently Completed": - MPO Format Test Coverage (High) - Debug File Storage Without Cleanup Mechanism (Medium) - Filename Not Sanitized in Debug Path (Medium) - N+1 Query Pattern in Feed Generation (Medium) - Transaction Not Atomic in Variant Generation (Medium) - Default Slug Change (Medium)