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>
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>
The Note model has a `tags` property that uses `_cached_tags` internally.
Setting `tags` directly via object.__setattr__ conflicts with the property.
🤖 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>
## 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>
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>
CRITICAL production hotfix for v1.1.1-rc.2 addressing route conflict
that caused 500 errors on /admin/dashboard.
Changes:
- Renamed metrics dashboard route from /admin/dashboard to /admin/metrics-dashboard
- Added defensive imports for missing monitoring module with graceful fallback
- Updated version to 1.1.1-rc.2
- Updated CHANGELOG with hotfix details
- Created implementation report in docs/reports/
Testing:
- All 32 admin route tests pass (100%)
- 593/600 total tests pass (7 pre-existing failures unrelated to hotfix)
- Verified backward compatibility maintained
Design:
- Follows ADR-022 architecture decision
- Implements design from docs/design/hotfix-v1.1.1-rc2-route-conflict.md
- No breaking changes - all existing url_for() calls work correctly
Production Impact:
- Resolves 500 error at /admin/dashboard
- Notes dashboard remains at /admin/ (unchanged)
- Metrics dashboard now at /admin/metrics-dashboard
- Graceful degradation when monitoring module unavailable
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements full search functionality for StarPunk v1.1.0.
Search API Endpoint (/api/search):
- GET endpoint with query parameter (q) validation
- Pagination via limit (default 20, max 100) and offset parameters
- JSON response with results count and formatted search results
- Authentication-aware: anonymous users see published notes only
- Graceful handling of FTS5 unavailability (503 error)
- Proper error responses for missing/empty queries
Search Web Interface (/search):
- HTML search results page with Bootstrap-inspired styling
- Search form with HTML5 validation (minlength=2, maxlength=100)
- Results display with title, excerpt, date, and links
- Empty state for no results
- Error state for FTS5 unavailability
- Simple pagination (Next/Previous navigation)
Navigation Integration:
- Added search box to site navigation in base.html
- Preserves query parameter on results page
- Responsive design with emoji search icon
- Accessible with proper ARIA labels
FTS Index Population:
- Added startup check in __init__.py for empty FTS index
- Automatic rebuild from existing notes on first run
- Graceful degradation if population fails
- Logging for troubleshooting
Security Features:
- XSS prevention: HTML in search results properly escaped
- Safe highlighting: FTS5 <mark> tags preserved, user content escaped
- Query validation: empty queries rejected, length limits enforced
- SQL injection prevention via FTS5 query parser
- Authentication filtering: unpublished notes hidden from anonymous users
Testing:
- Added 41 comprehensive tests across 3 test files
- test_search_api.py: 12 tests for API endpoint validation
- test_search_integration.py: 17 tests for UI rendering and integration
- test_search_security.py: 12 tests for XSS, SQL injection, auth filtering
- All tests passing with no regressions
Implementation follows architect specifications from:
- docs/architecture/v1.1.0-validation-report.md
- docs/architecture/v1.1.0-feature-architecture.md
- docs/decisions/ADR-034-full-text-search.md
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The auth routes were registered under /admin/* but the IndieAuth
redirect_uri was configured as /auth/callback, causing 404 errors
when providers redirected back after authentication.
- Change auth blueprint url_prefix from "/admin" to "/auth"
- Update test expectations for new auth route paths
- Add ADR-022 documenting the architectural decision
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This fixes critical IndieAuth authentication by implementing PKCE (Proof Key
for Code Exchange) as required by IndieLogin.com API specification.
Added:
- PKCE code_verifier and code_challenge generation (RFC 7636)
- Database column: auth_state.code_verifier for PKCE support
- Issuer validation for authentication callbacks
- Comprehensive PKCE unit tests (6 tests, all passing)
- Database migration script for code_verifier column
Changed:
- Corrected IndieLogin.com API endpoints (/authorize and /token)
- State token validation now returns code_verifier for token exchange
- Authentication flow follows IndieLogin.com API specification exactly
- Enhanced logging with code_verifier redaction
Removed:
- OAuth metadata endpoint (/.well-known/oauth-authorization-server)
Added in v0.7.0 but not required by IndieLogin.com
- h-app microformats markup from templates
Modified in v0.7.1 but not used by IndieLogin.com
- indieauth-metadata link from HTML head
Security:
- PKCE prevents authorization code interception attacks
- Issuer validation prevents token substitution attacks
- Code verifier securely stored, redacted in logs, and single-use
Documentation:
- Version: 0.8.0
- CHANGELOG updated with v0.8.0 entry and v0.7.x notes
- ADR-016 and ADR-017 marked as superseded by ADR-019
- Implementation report created in docs/reports/
- Test update guide created in TODO_TEST_UPDATES.md
Breaking Changes:
- Users mid-authentication will need to restart login after upgrade
- Database migration required before deployment
Related: ADR-019
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixes critical IndieAuth authentication failure by implementing modern
JSON-based client discovery mechanism per IndieAuth spec section 4.2.
Added /.well-known/oauth-authorization-server endpoint returning JSON
metadata with client_id, redirect_uris, and OAuth capabilities.
Added <link rel="indieauth-metadata"> discovery hint in HTML head.
Maintained h-app microformats for backward compatibility with legacy
IndieAuth servers.
This resolves "client_id is not registered" error from IndieLogin.com
by providing the metadata document modern IndieAuth servers expect.
Changes:
- Added oauth_client_metadata() endpoint in public routes
- Returns JSON with client info (24-hour cache)
- Uses config values (SITE_URL, SITE_NAME) not hardcoded URLs
- Added indieauth-metadata link in base.html
- Comprehensive test suite (15 new tests, all passing)
- Updated version to v0.6.2 (PATCH increment)
- Updated CHANGELOG.md with detailed fix documentation
Standards Compliance:
- IndieAuth specification section 4.2
- OAuth Client ID Metadata Document format
- IANA well-known URI registry
- RFC 7591 OAuth 2.0 Dynamic Client Registration
Testing:
- 467/468 tests passing (99.79%)
- 15 new tests for OAuth metadata and discovery
- Zero regressions in existing tests
- Test coverage maintained at 88%
Related Documentation:
- ADR-017: OAuth Client ID Metadata Document Implementation
- IndieAuth Fix Summary report
- Implementation report in docs/reports/
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>