- ADR-062: Timestamp-based slug format (supersedes ADR-007)
- Updated v1.5.0 RELEASE.md with 6-phase plan
- Updated BACKLOG.md with deferred N+1 query locations
- Developer questions and architect responses for Phase 1
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add pillow-heif dependency for iPhone photo support
- Auto-convert HEIC to JPEG (browsers can't display HEIC)
- Graceful error if pillow-heif not installed
- Handles RGBA/P mode conversion to RGB
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements media upload logging per docs/design/v1.4.1/media-logging-design.md
Changes:
- Add logging to save_media() in starpunk/media.py:
* INFO: Successful uploads with file details
* WARNING: Validation/optimization/variant failures
* ERROR: Unexpected system errors
- Remove duplicate logging in Micropub media endpoint
- Add 5 comprehensive logging tests in TestMediaLogging class
- Bump version to 1.4.1
- Update CHANGELOG.md
All media upload operations now logged for debugging and observability.
Validation errors, optimization failures, and variant generation issues
are tracked at appropriate log levels. Original functionality unchanged.
Test results: 28/28 media tests pass, 5 new logging tests pass
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Complete Phase 5 of v1.4.0 "Media" release with comprehensive release
preparation.
CHANGELOG Updates:
- Added v1.4.0rc1 section with comprehensive release notes
- Documented all four phases:
* Large Image Support (50MB limit, tiered resize)
* Image Variants (thumb, small, medium, large)
* Micropub Media Endpoint (W3C compliant)
* Enhanced Feed Media (Media RSS, JSON Feed extension)
- Standards compliance documented (W3C Micropub, Media RSS 2.0)
- Storage impact and backwards compatibility notes
- Configuration options (STARPUNK_ABOUT_URL)
Version Bump:
- Updated starpunk/__init__.py to 1.4.0rc1
- Version info tuple includes rc1 designator
Implementation Report:
- Created docs/design/v1.4.0/2025-12-16-v140-implementation-complete.md
- Complete summary of all five phases
- Test results: 850 passing, 19 failing
- Known issues documented (flaky tests, feed cache)
- Acceptance criteria checklist
- Deployment and rollback procedures
- Release recommendation: Ready for RC testing
Test Results:
- Full test suite executed: 850 passed, 19 failed (98% pass rate)
- Core v1.4.0 functionality verified working
- Failures in known flaky tests and unrelated areas
- 5 minutes 58 seconds execution time
Release Status:
- All five phases complete
- Ready for release candidate testing
- Manual verification recommended before final release
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Document completed Phase 4 implementation with test results,
verification output, and backwards compatibility notes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement W3C Micropub media endpoint for external client uploads.
Changes:
- Add POST /micropub/media endpoint in routes/micropub.py
- Accept multipart/form-data with 'file' field
- Require bearer token with 'create' scope
- Return 201 Created with Location header
- Validate, optimize, and generate variants via save_media()
- Update q=config response to advertise media-endpoint
- Include media-endpoint URL in config response
- Add 'photo' post-type to supported types
- Add photo property support to Micropub create
- extract_photos() function to parse photo property
- Handles both simple URL strings and structured objects with alt text
- _attach_photos_to_note() function to attach photos by URL
- Only attach photos from our server (by URL match)
- External URLs logged but ignored (no download)
- Maximum 4 photos per note (per ADR-057)
- SITE_URL normalization pattern
- Use .rstrip('/') for consistent URL comparison
- Applied in media endpoint and photo attachment
Per design document: docs/design/v1.4.0/media-implementation-design.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements tag/category rendering in RSS 2.0, Atom 1.0, and JSON Feed 1.1
syndication feeds. Tags added in v1.3.0 are now visible to feed readers.
Changes:
- Load tags in feed generation (_get_cached_notes)
- Add <category> elements to RSS 2.0 feeds
- Add <category term/label> to Atom 1.0 feeds
- Add "tags" array to JSON Feed 1.1 items
- Omit empty tags field in JSON Feed (minimal approach)
Standards compliance:
- RSS 2.0: category element with display name
- Atom 1.0: RFC 4287 category with term and label attributes
- JSON Feed 1.1: tags array of strings
Per design: docs/design/v1.3.1/feed-tags-design.md
Implementation: docs/design/v1.3.1/2025-12-10-feed-tags-implementation.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement Phase 3 of v1.3.0 tags feature per microformats-tags-design.md:
Routes (starpunk/routes/public.py):
- Add /tag/<tag> archive route with normalization and 404 handling
- Pre-load tags in index route for all notes
- Pre-load tags in note route for individual notes
Admin (starpunk/routes/admin.py):
- Parse comma-separated tag input in create route
- Parse tag input in update route
- Pre-load tags when displaying edit form
- Empty tag field removes all tags
Templates:
- Add tag input field to templates/admin/edit.html
- Add tag input field to templates/admin/new.html
- Use Jinja2 map filter to display existing tags
Implementation details:
- Tag URL parameter normalized to lowercase before lookup
- Tags pre-loaded using object.__setattr__ pattern (like media)
- parse_tag_input() handles trim, dedupe, normalization
- All existing tests pass (micropub categories, admin routes)
Per architect design:
- No pagination on tag archives (acceptable for v1.3.0)
- No autocomplete in admin (out of scope)
- Follows existing media loading patterns
Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Implement Phase 2 of v1.3.0 per microformats-tags-design.md
Template Updates:
- templates/index.html: Add h-feed properties (u-url, enhanced p-author with u-photo/p-note, feed-level u-photo)
- templates/index.html: Add p-category markup with rel="tag" to note previews
- templates/note.html: Add p-category markup with rel="tag" for tags
- templates/note.html: Enhance author h-card with u-photo and p-note (hidden for parsers)
- templates/note.html: Document u-photo placement outside e-content per draft spec
- templates/tag.html: Create new tag archive template with h-feed structure
Key Decisions Applied:
- Tags ordered alphabetically by display_name (ready for backend)
- rel="tag" on all p-category links per microformats2 spec
- Author bio (p-note) hidden with display: none for semantic parsing
- Dual u-photo elements intentional for parser compatibility
- Graceful fallback when author photo/bio not available
Templates are backward compatible and ready for backend integration.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements tag/category system backend following microformats2 p-category specification.
Database changes:
- Migration 008: Add tags and note_tags tables
- Normalized tag storage (case-insensitive lookup, display name preserved)
- Indexes for performance
New module:
- starpunk/tags.py: Tag management functions
- normalize_tag: Normalize tag strings
- get_or_create_tag: Get or create tag records
- add_tags_to_note: Associate tags with notes (replaces existing)
- get_note_tags: Retrieve note tags (alphabetically ordered)
- get_tag_by_name: Lookup tag by normalized name
- get_notes_by_tag: Get all notes with specific tag
- parse_tag_input: Parse comma-separated tag input
Model updates:
- Note.tags property (lazy-loaded, prefer pre-loading in routes)
- Note.to_dict() add include_tags parameter
CRUD updates:
- create_note() accepts tags parameter
- update_note() accepts tags parameter (None = no change, [] = remove all)
Micropub integration:
- Pass tags to create_note() (tags already extracted by extract_tags())
- Return tags in q=source response
Per design doc: docs/design/v1.3.0/microformats-tags-design.md
Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
## Added
- Feed Media Enhancement with Media RSS namespace support
- RSS enclosure, media:content, media:thumbnail elements
- JSON Feed image field for first image
- ADR-059: Full feed media standardization roadmap
## Fixed
- Media display on homepage (was only showing on note pages)
- Responsive image sizing with CSS constraints
- Caption display (now alt text only, not visible)
- Logging correlation ID crash in non-request contexts
## Documentation
- Feed media design documents and implementation reports
- Media display fixes design and validation reports
- Updated ROADMAP with v1.3.0/v1.4.0 media plans
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements the metrics instrumentation framework that was missing from v1.1.1.
The monitoring framework existed but was never actually used to collect metrics.
Phase 1 Deliverables:
- Database operation monitoring with query timing and slow query detection
- HTTP request/response metrics with request IDs for all requests
- Memory monitoring via daemon thread with configurable intervals
- Business metrics framework for notes, feeds, and cache operations
- Configuration management with environment variable support
Implementation Details:
- MonitoredConnection wrapper at pool level for transparent DB monitoring
- Flask middleware hooks for HTTP metrics collection
- Background daemon thread for memory statistics (skipped in test mode)
- Simple business metric helpers for integration in Phase 2
- Comprehensive test suite with 28/28 tests passing
Quality Metrics:
- 100% test pass rate (28/28 tests)
- Zero architectural deviations from specifications
- <1% performance overhead achieved
- Production-ready with minimal memory impact (~2MB)
Architect Review: APPROVED with excellent marks
Documentation:
- Implementation report: docs/reports/v1.1.2-phase1-metrics-implementation.md
- Architect review: docs/reviews/2025-11-26-v1.1.2-phase1-review.md
- Updated CHANGELOG.md with Phase 1 additions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Root cause: Template expects flat structure (metrics.database.count) but
monitoring module provides nested structure (metrics.by_type.database.count)
with different field names (avg_duration_ms vs avg).
Solution: Route Adapter Pattern - transformer function maps data structure
at presentation layer.
Changes:
- Add transform_metrics_for_template() function to admin.py
- Update metrics_dashboard() route to use transformer
- Provide safe defaults for missing/empty metrics data
- Handle all operation types: database, http, render
Testing: All 32 admin route tests passing
Documentation:
- Updated implementation report with actual fix details
- Created consolidated hotfix design documentation
- Architectural review by architect (approved with minor concerns)
Technical debt: Adapter layer should be replaced with proper data
contracts in v1.2.0
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Create developer-qa.md with architect's answers to all 20
implementation questions from the developer's design review.
This is the proper format for Q&A between developer and architect
during design review, not an ADR (which is for architectural
decisions with lasting impact).
Content includes:
- 6 critical questions with answers (config, db pool, logging, etc.)
- 8 important questions (session migration, Unicode, health checks)
- 6 nice-to-have clarifications (testing, monitoring, dashboard)
- Implementation phases (3 weeks)
- Integration guidance
Developer now has clear guidance to proceed with v1.1.1 implementation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixes critical issue where migration 002 indexes already existed in SCHEMA_SQL,
causing 'index already exists' errors on databases created before v1.0.0-rc.1.
Changes:
- Removed duplicate index definitions from SCHEMA_SQL (database.py)
- Enhanced migration system to detect and handle indexes properly
- Added comprehensive documentation of the fix
Version bumped to 1.0.0-rc.2 with full changelog entry.
Refs: docs/reports/2025-11-24-migration-fix-v1.0.0-rc.2.md
- Updated 42 references from indieauth.spec.indieweb.org to www.w3.org/TR/indieauth
- Ensures consistency across all documentation
- Points to the authoritative W3C specification
- No functional changes, documentation update only
Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- Add comprehensive Micropub endpoint design document
- Define token management approach for IndieAuth
- Specify minimal V1 feature set (create posts, queries)
- Defer media endpoint and advanced features to post-V1
- Add ADR-028 documenting implementation strategy
- 8-10 day implementation timeline to unblock V1
The Micropub endpoint is the final blocker for V1.0.0 release.