docs: Add v1.5.0 "Trigger" release definition

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>
This commit is contained in:
2025-12-16 19:04:43 -07:00
parent 730eb8d58c
commit 7be2fb0f62
2 changed files with 263 additions and 6 deletions

View File

@@ -40,7 +40,7 @@
## High ## High
### MPO Format Test Coverage ### MPO Format Test Coverage *(Scheduled: v1.5.0)*
- **Description**: MPO conversion code exists but has no test coverage. MPO is advertised in the CHANGELOG but the handling is untested. - **Description**: MPO conversion code exists but has no test coverage. MPO is advertised in the CHANGELOG but the handling is untested.
- **Location**: `starpunk/media.py` lines 163-173 - **Location**: `starpunk/media.py` lines 163-173
- **Source**: Developer Review (M1) - **Source**: Developer Review (M1)
@@ -60,7 +60,7 @@
## Medium ## Medium
### Debug File Storage Without Cleanup Mechanism ### Debug File Storage Without Cleanup Mechanism *(Scheduled: v1.5.0)*
- **Description**: Failed uploads are saved to `data/debug/` directory for analysis, but there is no mechanism to clean up these files. This could consume significant disk space, especially if under attack. - **Description**: Failed uploads are saved to `data/debug/` directory for analysis, but there is no mechanism to clean up these files. This could consume significant disk space, especially if under attack.
- **Location**: `starpunk/media.py` lines 133-137 - **Location**: `starpunk/media.py` lines 133-137
- **Source**: Developer Review (M2), Architect Review (Issue 1.2.2) - **Source**: Developer Review (M2), Architect Review (Issue 1.2.2)
@@ -69,19 +69,19 @@
2. Implement automatic cleanup (files older than 7 days) 2. Implement automatic cleanup (files older than 7 days)
3. Add disk space check or size limit (e.g., 100MB max) 3. Add disk space check or size limit (e.g., 100MB max)
### Filename Not Sanitized in Debug Path (Security) ### Filename Not Sanitized in Debug Path (Security) *(Scheduled: v1.5.0)*
- **Description**: The original filename is used directly in the debug file path without sanitization, which could cause path traversal or special character issues. - **Description**: The original filename is used directly in the debug file path without sanitization, which could cause path traversal or special character issues.
- **Location**: `starpunk/media.py` line 135 - **Location**: `starpunk/media.py` line 135
- **Source**: Architect Review (Issue 1.2.3) - **Source**: Architect Review (Issue 1.2.3)
- **Approach**: Sanitize filename before use: `safe_filename = "".join(c for c in filename if c.isalnum() or c in "._-")[:50]` - **Approach**: Sanitize filename before use: `safe_filename = "".join(c for c in filename if c.isalnum() or c in "._-")[:50]`
### N+1 Query Pattern in Feed Generation ### N+1 Query Pattern in Feed Generation *(Scheduled: v1.5.0)*
- **Description**: In `_get_cached_notes()`, media and tags are loaded per-note in separate queries. For 50 notes, this is 100 additional database queries, degrading performance. - **Description**: In `_get_cached_notes()`, media and tags are loaded per-note in separate queries. For 50 notes, this is 100 additional database queries, degrading performance.
- **Location**: `starpunk/routes/public.py` lines 68-74 - **Location**: `starpunk/routes/public.py` lines 68-74
- **Source**: Architect Review (Issue 2.2.9) - **Source**: Architect Review (Issue 2.2.9)
- **Approach**: Implement batch loading function `get_media_for_notes(note_ids: List[int])` using a single query with `WHERE note_id IN (...)`. - **Approach**: Implement batch loading function `get_media_for_notes(note_ids: List[int])` using a single query with `WHERE note_id IN (...)`.
### Transaction Not Atomic in Variant Generation ### Transaction Not Atomic in Variant Generation *(Scheduled: v1.5.0)*
- **Description**: Files are written to disk before database commit. If the database commit fails, orphaned files remain on disk. - **Description**: Files are written to disk before database commit. If the database commit fails, orphaned files remain on disk.
- **Location**: `starpunk/media.py` lines 404-440 - **Location**: `starpunk/media.py` lines 404-440
- **Source**: Architect Review (Issue 2.2.6) - **Source**: Architect Review (Issue 2.2.6)
@@ -93,7 +93,7 @@
- **Source**: Architect Review (Security Assessment) - **Source**: Architect Review (Security Assessment)
- **Approach**: Implement Flask-Limiter or similar rate limiting middleware for upload routes. - **Approach**: Implement Flask-Limiter or similar rate limiting middleware for upload routes.
### Default Slug Change ### Default Slug Change *(Scheduled: v1.5.0)*
- The default slug should be a date time stamp - The default slug should be a date time stamp
- YYYYMMDDHHMMSS - YYYYMMDDHHMMSS
- Edge case, if the slug would somehow be a duplicate append a "-x" e.g. -1 - Edge case, if the slug would somehow be a duplicate append a "-x" e.g. -1

View File

@@ -0,0 +1,257 @@
# 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)