Focus: Cleanup, test coverage, and quality of life improvements Goals: - 90% test coverage target - MPO format test coverage (High backlog item) - Debug file storage cleanup (Medium backlog item) - Filename sanitization in debug path (Medium backlog item) - N+1 query pattern fix (Medium backlog item) - Atomic variant generation (Medium backlog item) - Default slug change to timestamp format (Medium backlog item) Backlog items marked as scheduled for v1.5.0. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
258 lines
7.3 KiB
Markdown
258 lines
7.3 KiB
Markdown
# 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)
|