Promoting v1.3.0-rc.1 to stable release.
Changes:
- Updated version in starpunk/__init__.py to 1.3.0
- Updated CHANGELOG.md header to v1.3.0
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Release candidate v1.3.0-rc.1 with tags/categories and enhanced Microformats2 support.
Major features:
- Complete tag/category system with Micropub support
- Strict Microformats2 compliance (p-category, h-feed properties)
- Tag archive pages at /tags/{tag}
- Enhanced h-entry markup with dt-updated
- Proper h-feed structure on collection pages
Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
v1.3.1 "Syndicate Tags":
- RSS/Atom/JSON Feed category/tag support
v1.4.0 "Media":
- Micropub media endpoint (W3C compliant)
- Large image support (>10MB auto-resize)
- Enhanced feed media (image variants, full Media RSS)
Also adds tag-filtered feeds to backlog at medium priority.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Release candidate for v1.3.0 with tags/categories and enhanced Microformats2 support.
Features:
- Tag/category system with Micropub support
- Strict Microformats2 compliance (p-category, h-feed)
- Tag archive pages
- Enhanced h-entry markup
Generated with 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>
Promote v1.2.0-rc.2 to stable v1.2.0 release
- Merged rc.1 and rc.2 changelog entries
- Updated version in starpunk/__init__.py
- All features tested in production
🤖 Generated with [Claude Code](https://claude.com/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>
Fixes logging errors during app initialization and in background threads.
The correlation_id filter must be applied to handlers (not just loggers)
to ensure all log records have the correlation_id attribute before
formatting occurs.
Issue: Gunicorn workers were crashing due to missing correlation_id
in logs from memory monitor and other non-request contexts.
Promoting release candidate to stable production release.
v1.1.2 "Syndicate" - Enhanced Content Distribution
This release delivers comprehensive metrics instrumentation and multi-format
feed support (RSS, ATOM, JSON Feed) with content negotiation, caching, and
statistics dashboard.
No changes from v1.1.2-rc.2 - both production issues verified fixed.
Version: 1.1.2 (stable)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements the metrics instrumentation 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
- HTTP request/response metrics with request IDs
- Memory monitoring daemon thread
- Business metrics framework
- Configuration management
Quality Metrics:
- 28/28 tests passing (100%)
- Zero architectural deviations
- <1% performance overhead achieved
- Production-ready implementation
Architect Review: APPROVED with excellent marks
🤖 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>
Critical production hotfix resolving template/data structure mismatch
that caused 500 error on /admin/dashboard endpoint.
Root Cause:
Template expects flat structure (metrics.database.count) but monitoring
module provides nested structure (metrics.by_type.database.count) with
different field names.
Solution:
Route Adapter Pattern - transformer function maps nested monitoring data
to flat template structure at presentation layer.
Changes:
- Add transform_metrics_for_template() function
- Update metrics_dashboard() route to use transformer
- Provide safe defaults for missing metrics data
- Handle edge cases (empty dict, missing by_type)
Testing:
- All 32 admin route tests passing
- Transformer validated with full test coverage
- No breaking changes
Documentation:
- Consolidated hotfix design in docs/design/
- Architectural review completed (approved)
- Implementation report updated
- Misclassified ADRs removed (ADR-022, ADR-060)
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>
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>
Phase 1 of v1.1.1 "Polish" release focusing on production readiness.
Implements logging, connection pooling, validation, and error handling.
Following specs in docs/design/v1.1.1/developer-qa.md and ADRs 052-055.
**Structured Logging** (Q3, ADR-054)
- RotatingFileHandler (10MB files, keep 10)
- Correlation IDs for request tracing
- All print statements replaced with logging
- Context-aware correlation IDs (init/request)
- Logs written to data/logs/starpunk.log
**Database Connection Pooling** (Q2, ADR-053)
- Connection pool with configurable size (default: 5)
- Request-scoped connections via Flask g object
- Pool statistics for monitoring
- WAL mode enabled for concurrency
- Backward compatible get_db() signature
**Configuration Validation** (Q14, ADR-052)
- Validates presence and type of all config values
- Fail-fast startup with clear error messages
- LOG_LEVEL enum validation
- Type checking for strings, integers, paths
- Non-zero exit status on errors
**Centralized Error Handling** (Q4, ADR-055)
- Moved handlers to starpunk/errors.py
- Micropub spec-compliant JSON errors
- HTML templates for browser requests
- All errors logged with correlation IDs
- MicropubError exception class
**Database Module Reorganization**
- Moved database.py to database/ package
- Separated init.py, pool.py, schema.py
- Maintains backward compatibility
- Cleaner separation of concerns
**Testing**
- 580 tests passing
- 1 pre-existing flaky test noted
- No breaking changes to public API
**Documentation**
- CHANGELOG.md updated with v1.1.1 entry
- Version bumped to 1.1.1
- Implementation report in docs/reports/
🤖 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>
Comprehensive project plan updates to reflect v1.1.0 release:
New Documents:
- INDEX.md: Navigation index for all planning docs
- ROADMAP.md: Future version planning (v1.1.1 → v2.0.0)
- v1.1/RELEASE-STATUS.md: Complete v1.1.0 tracking
Updated Documents:
- v1/implementation-plan.md: Updated to v1.1.0, marked V1 100% complete
- v1.1/priority-work.md: Marked all items complete with actual effort
Changes:
- Fixed outdated status (was showing v0.9.5)
- Marked Micropub as complete (v1.0.0)
- Tracked all v1.1.0 features (search, slugs, migrations)
- Added clear roadmap for future versions
- Linked all ADRs and implementation reports
Project plan now fully synchronized with v1.1.0 "SearchLight" release.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fix custom slug extraction bug where mp-slug was being filtered
out by normalize_properties() before it could be used.
Changes:
- Extract mp-slug from raw request data before normalization
- Add tests for both form-encoded and JSON formats
- All 13 Micropub tests passing
Fixes issue where Quill-specified custom slugs were ignored.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Update CHANGELOG.md with fix details in Unreleased section.
Create comprehensive implementation report documenting:
- Root cause analysis
- Code changes made
- Test results (all 13 Micropub tests pass)
- Deployment notes
Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Fix bug where custom slugs (mp-slug) were being ignored because they
were extracted from normalized properties after being filtered out.
The root cause: normalize_properties() filters out all mp-* parameters
(line 139) because they're Micropub server extensions, not properties.
The old code tried to extract mp-slug from the normalized properties
dict, but it had already been removed.
The fix: Extract mp-slug directly from raw request data BEFORE calling
normalize_properties(). This preserves the custom slug through to
create_note().
Changes:
- Move mp-slug extraction to before property normalization (line 290-299)
- Handle both form-encoded (list) and JSON (string or list) formats
- Add comprehensive tests for custom slug with both request formats
- All 13 Micropub tests pass
Fixes the issue reported in production where Quill-specified slugs
were being replaced with auto-generated ones.
References:
- docs/reports/custom-slug-bug-diagnosis.md (architect's analysis)
- Micropub spec: mp-slug is a server extension parameter
Generated with 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>
Release v1.1.0 "Searchlight" with search, custom slugs, and RSS fix.
Changes:
- Updated version to 1.1.0 in starpunk/__init__.py
- Updated CHANGELOG.md with v1.1.0 release notes
- Created implementation report in docs/reports/
Release highlights:
- Full-text search with FTS5 (core functionality complete)
- Custom slugs via Micropub mp-slug property
- RSS feed ordering fix (newest first)
- Migration system redesign (INITIAL_SCHEMA_SQL)
All features implemented and tested. Search UI to be completed
in immediate follow-up work.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements FTS5-based full-text search for notes as specified in ADR-034.
Changes:
- Created migration 005_add_fts5_search.sql with FTS5 virtual table
- Created starpunk/search.py module with search functions
- Integrated FTS index updates into create_note() and update_note()
- DELETE trigger automatically removes notes from FTS index
- INSERT/UPDATE handled by application code (files not in DB)
Features:
- Porter stemming for better English search
- Unicode normalization for international characters
- Relevance ranking with snippets
- Graceful degradation if FTS5 unavailable
- Helper function to rebuild index if needed
Note: Initial FTS index population needs to be added to app startup.
Part of v1.1.0 (Phase 3).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This aligns with ADR-033's migration system redesign. The initial schema
represents the v1.0.0 baseline and should not be modified. All schema
changes after v1.0.0 must go in migration files.
Changes:
- Renamed SCHEMA_SQL → INITIAL_SCHEMA_SQL in database.py
- Updated all references in migrations.py comments
- Added comment: "DO NOT MODIFY - This represents the v1.0.0 schema state"
- No functional changes, purely documentation improvement
Part of v1.1.0 migration system redesign (Phase 2).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed bug where feedgen library was reversing the order of feed items.
Database returns notes in DESC order (newest first), but feedgen was
displaying them oldest-first in the RSS XML. Added reversed() wrapper
to maintain correct chronological order in the feed.
Added regression test to verify feed order matches database order.
Bug confirmed by testing:
- Database: [Note 2, Note 1, Note 0] (newest first)
- Old feed: [Note 0, Note 1, Note 2] (oldest first) ❌
- New feed: [Note 2, Note 1, Note 0] (newest first) ✅🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove leading slash when constructing URLs with SITE_URL
- SITE_URL already includes trailing slash per IndieAuth spec
- Fixes malformed Location header in Micropub responses
- Fixes malformed URLs in Microformats2 query responses
Changes:
- starpunk/micropub.py line 312: f"{site_url}notes/{note.slug}"
- starpunk/micropub.py line 383: f"{site_url}notes/{note.slug}"
- Added comments explaining SITE_URL trailing slash convention
- Updated version to 1.0.1 in starpunk/__init__.py
- Updated CHANGELOG.md with v1.0.1 release notes
Fixes double slash issue reported after v1.0.0 release.
Per ADR-039 and docs/releases/v1.0.1-hotfix-plan.md
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
First production-ready release of StarPunk - a minimal, self-hosted
IndieWeb CMS with full IndieAuth and Micropub compliance.
Changes:
- Update version to 1.0.0 in starpunk/__init__.py
- Update README.md version references and feature descriptions
- Finalize CHANGELOG.md with comprehensive v1.0.0 release notes
This milestone completes all V1 features:
- W3C IndieAuth specification compliance with endpoint discovery
- W3C Micropub specification implementation
- Robust database migrations with race condition protection
- Production-ready containerized deployment
- 536 tests passing with 87% code coverage
StarPunk is now ready for production use as a personal IndieWeb
publishing platform.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive architectural documentation for the migration race
condition fix, including:
- ADR-022: Architectural decision record for the fix
- migration-race-condition-answers.md: All 23 Q&A answered
- migration-fix-quick-reference.md: Implementation checklist
- migration-race-condition-fix-implementation.md: Detailed guide
These documents guided the implementation in v1.0.0-rc.5.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This major architectural change removes the built-in IndieAuth
authorization server in favor of external provider delegation.
Key changes:
- Remove authorization and token endpoints
- Remove token storage and management code
- Implement external token verification via configured endpoint
- Drop auth_codes and auth_tokens database tables
- Simplify security model by delegating to external providers
Breaking Changes:
- Existing tokens issued by StarPunk will no longer work
- Users must configure TOKEN_ENDPOINT in settings
- Micropub clients must obtain tokens from external providers
Benefits:
- Reduces codebase by ~500 lines of security-critical code
- Eliminates token storage and cryptographic responsibilities
- Maintains full IndieAuth specification compliance
- Simpler security model focused on verification only
Implements: ADR-050 (Remove Authorization Server)
Implements: ADR-030 (External Token Verification)
Migration: Database migrations 003 and 004 included
See docs/reports/indieauth-removal-implementation-report.md for
complete implementation details and migration guide.
Version: 1.0.0-rc.4
Fixed 5 failing tests related to code_verifier column which was
added by migration 001 but removed by migration 003.
Changes:
- Renamed legacy_db_without_code_verifier to legacy_db_basic
- Updated column_exists tests to use 'state' column instead of 'code_verifier'
- Updated test_run_migrations_legacy_database to test with generic column
- Replaced test_actual_migration_001 with test_actual_migration_003
- Fixed test_dev_mode_requires_dev_admin_me to explicitly override DEV_ADMIN_ME
All 551 tests now passing.
Part of Phase 1 completion: IndieAuth authorization server removal
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixes database migration detection for partially migrated databases.
This hotfix resolves an issue where migration 002 would fail to detect
existing migrated tables, causing conflicts on databases that had been
partially migrated.
CRITICAL HOTFIX for production deployment failure
Problem:
- Production database had migration 001 applied but not migration 002
- Migration 002's tables (tokens, authorization_codes) already existed from SCHEMA_SQL
- Smart detection only checked when migration_count == 0 (fresh database)
- For partially migrated databases (count > 0), tried to run full migration
- This failed with "table already exists" error
Solution:
- Always check migration 002's state, regardless of migration_count
- If tables exist with correct structure, skip table creation
- Create missing indexes only
- Mark migration as applied
Testing:
- Manual verification with production scenario: SUCCESS
- 561 automated tests passing
- test_run_migrations_partial_applied confirms fix works
Impact:
- Fixes deployment on partially migrated production databases
- No impact on fresh or fully migrated databases
- Backwards compatible with all database states
Version: 1.0.0-rc.2 → 1.0.0-rc.3
Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Hotfix 1.0.0-rc.2: Critical database migration fix
Resolves index conflict issue where migration 002 would fail on existing
databases due to duplicate index definitions in SCHEMA_SQL.
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
- Update version to 0.9.5 throughout README
- Clarify Micropub as coming in v1.0 (currently in development)
- Add note that database auto-initializes on first run
- Fix deployment documentation link to standards location
- Add .gitignore entry for test.ini temporary file
All changes approved by architect agent.
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- 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>
Implements token security and management as specified in ADR-029:
Database Changes (BREAKING):
- Add secure tokens table with SHA256 hashed storage
- Add authorization_codes table for IndieAuth token exchange
- Drop old insecure tokens table (invalidates existing tokens)
- Update SCHEMA_SQL to match post-migration state
Token Management (starpunk/tokens.py):
- Generate cryptographically secure tokens
- Hash tokens with SHA256 for secure storage
- Create and verify access tokens
- Create and exchange authorization codes
- PKCE support (optional but recommended)
- Scope validation (V1: only 'create' scope)
- Token expiry and revocation support
Testing:
- Comprehensive test suite for all token operations
- Test authorization code replay protection
- Test PKCE validation
- Test parameter validation
- Test token expiry
Security:
- Tokens never stored in plain text
- Authorization codes single-use with replay protection
- Optional PKCE for enhanced security
- Proper UTC datetime handling for expiry
Related:
- ADR-029: Micropub IndieAuth Integration Strategy
- Migration 002: Secure tokens and authorization codes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This agent helps maintain documentation organization and ensures
README.md stays current with the codebase.
🤖 Generated with [Claude Code](https://claude.com/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.
Added "Documentation Navigation" section with:
- Clear explanation of docs/ folder structure and purpose of each subdirectory
- Guidelines for finding existing documentation before implementing features
- Practical rules for when to create ADRs, design docs, reports, or standards
- File naming conventions for different document types
This improves agent and developer ability to navigate the documentation
system and maintain proper organization standards.
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Switched from GitLab CI to Gitea Actions for container builds.
Triggers on version tags, pushes to Gitea Container Registry.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Builds and pushes container images to GitLab Container Registry
when version tags (v*.*.*) are pushed.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
os.getenv() returns empty string instead of using default when env var
is set but empty. This caused SECRET_KEY to be empty when FLASK_SECRET_KEY=""
was in .env, breaking Flask sessions/flash messages.
Now treats empty string same as unset, properly falling back to SESSION_SECRET.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
IndieAuth authentication-only flows should redeem the code at the
authorization endpoint, not the token endpoint. The token endpoint
is only for authorization flows that need access tokens.
- Remove grant_type parameter (only needed for token flows)
- Change endpoint from /token to /authorize
- Update debug logging to reflect code verification flow
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The token exchange request was missing the required grant_type parameter
per OAuth 2.0 RFC 6749. IndieAuth providers that properly validate this
were rejecting the request with a 422 error.
- Add grant_type=authorization_code to token exchange data
- Add ADR-022 documenting the spec compliance requirement
🤖 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>
Shows the exact GET request URL being sent to IndieLogin.com's
/authorize endpoint, including all query parameters in their
encoded form. This helps debug authentication flow issues.
- Added debug log after auth_url construction in initiate_login()
- Logs complete URL with all parameters before redirect
- Version remains 0.9.1 (debugging enhancement only)
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>
h-app was invisible to IndieAuth parsers due to hidden and
aria-hidden attributes, preventing proper client discovery.
- Remove hidden and aria-hidden="true" from h-app div
- Update version to 0.7.1
- Update CHANGELOG with fix details
This provides backward compatibility for IndieAuth services
that rely on h-app microformat parsing.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add logging helper functions with automatic token redaction
- Implement comprehensive logging throughout auth flow
- Add production warning for DEBUG logging
- Add 14 new tests for logging functionality
- Update version to v0.7.0
🤖 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>