docs: add Phase 5 design and architectural review documentation
- Add ADR-014: RSS Feed Implementation - Add ADR-015: Phase 5 Implementation Approach - Add Phase 5 design documents (RSS and container) - Add pre-implementation review - Add RSS and container validation reports - Add architectural approval for v0.6.0 release Architecture reviews confirm 98/100 (RSS) and 96/100 (container) scores. Phase 5 approved for production deployment. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
434
docs/designs/phase-5-quick-reference.md
Normal file
434
docs/designs/phase-5-quick-reference.md
Normal file
@@ -0,0 +1,434 @@
|
||||
# Phase 5 Quick Reference Guide
|
||||
|
||||
**Phase**: 5 - RSS Feed & Production Container
|
||||
**Version**: 0.6.0
|
||||
**Status**: Implementation Ready
|
||||
|
||||
## Pre-Implementation Setup
|
||||
|
||||
### Version Numbering
|
||||
**Decision**: Go directly from 0.5.1 → 0.6.0
|
||||
- Phase 5 introduces significant new functionality (RSS feeds and container deployment)
|
||||
- Skip intermediate versions (e.g., 0.5.2) - go straight to 0.6.0
|
||||
- This follows semantic versioning for new feature additions
|
||||
|
||||
### Git Workflow
|
||||
**Decision**: Use feature branch `feature/phase-5-rss-container`
|
||||
1. Create and checkout feature branch:
|
||||
```bash
|
||||
git checkout -b feature/phase-5-rss-container
|
||||
```
|
||||
2. Implement all Phase 5 features on this branch
|
||||
3. Create PR to merge into main when complete
|
||||
4. This provides cleaner history and easier rollback if needed
|
||||
|
||||
## Overview
|
||||
|
||||
Phase 5 implements:
|
||||
1. RSS 2.0 feed generation for syndicating published notes
|
||||
2. Production-ready container for deployment with HTTPS/IndieAuth testing
|
||||
|
||||
## Implementation Checklist
|
||||
|
||||
### Part 1: RSS Feed (Estimated: 3-4 hours)
|
||||
|
||||
#### Step 1: Create Feed Module
|
||||
- [ ] Create `starpunk/feed.py`
|
||||
- [ ] Implement `generate_feed()` using feedgen
|
||||
- [ ] Implement `format_rfc822_date()` for date formatting
|
||||
- [ ] Implement `get_note_title()` for title extraction
|
||||
- [ ] Implement `clean_html_for_rss()` for CDATA safety
|
||||
|
||||
#### Step 2: Add Feed Route
|
||||
- [ ] Update `starpunk/routes/public.py`
|
||||
- [ ] Add `@bp.route("/feed.xml")` handler
|
||||
- [ ] Implement in-memory caching (5 minutes)
|
||||
- [ ] Add ETag generation and support
|
||||
- [ ] Set proper Content-Type and Cache-Control headers
|
||||
|
||||
#### Step 3: Update Templates
|
||||
- [ ] Add RSS discovery link to `templates/base.html`
|
||||
- [ ] Add RSS link to navigation in `templates/index.html`
|
||||
|
||||
#### Step 4: Configuration
|
||||
- [ ] Update `starpunk/config.py` with feed settings
|
||||
- [ ] Add FEED_MAX_ITEMS (default: 50)
|
||||
- [ ] Add FEED_CACHE_SECONDS (default: 300)
|
||||
- [ ] Update `.env.example` with feed variables
|
||||
|
||||
#### Step 5: RSS Testing
|
||||
- [ ] Create `tests/test_feed.py` for unit tests
|
||||
- [ ] Create `tests/test_routes_feed.py` for route tests
|
||||
- [ ] Test feed generation with various note counts
|
||||
- [ ] Test caching behavior
|
||||
- [ ] Test ETag validation
|
||||
- [ ] Validate with W3C Feed Validator
|
||||
|
||||
### Part 2: Production Container (Estimated: 3-4 hours)
|
||||
|
||||
#### Step 6: Create Container Files
|
||||
- [ ] Create `Containerfile` with multi-stage build
|
||||
- [ ] Create `compose.yaml` for orchestration
|
||||
- [ ] Create `.containerignore` to exclude unnecessary files
|
||||
- [ ] Create `Caddyfile.example` for reverse proxy
|
||||
- [ ] Create `nginx.conf.example` as alternative
|
||||
|
||||
#### Step 7: Add Health Check
|
||||
- [ ] Add `/health` endpoint to `starpunk/__init__.py`
|
||||
- [ ] Check database connectivity
|
||||
- [ ] Check filesystem access
|
||||
- [ ] Return JSON with status and version
|
||||
|
||||
#### Step 8: Container Configuration
|
||||
- [ ] Update `.env.example` with container variables
|
||||
- [ ] Add VERSION=0.6.0
|
||||
- [ ] Add WORKERS=4
|
||||
- [ ] Add WORKER_TIMEOUT=30
|
||||
- [ ] Document environment variables
|
||||
|
||||
#### Step 9: Container Testing
|
||||
- [ ] Build container with Podman
|
||||
- [ ] Build container with Docker
|
||||
- [ ] Test container startup
|
||||
- [ ] Test health endpoint
|
||||
- [ ] Test data persistence
|
||||
- [ ] Test with compose orchestration
|
||||
|
||||
#### Step 10: Production Deployment Testing
|
||||
- [ ] Deploy container to public server
|
||||
- [ ] Configure reverse proxy (Caddy or Nginx)
|
||||
- [ ] Set up HTTPS with Let's Encrypt
|
||||
- [ ] Test IndieAuth authentication flow
|
||||
- [ ] Verify callback URLs work
|
||||
- [ ] Test session creation and persistence
|
||||
|
||||
### Part 3: Documentation (Estimated: 1-2 hours)
|
||||
|
||||
#### Step 11: Update Documentation
|
||||
- [ ] Update CHANGELOG.md for v0.6.0
|
||||
- [ ] Increment version in `starpunk/__init__.py` from 0.5.1 to 0.6.0
|
||||
- [ ] Create deployment guide
|
||||
- [ ] Document RSS feed usage
|
||||
- [ ] Document container deployment
|
||||
- [ ] Document IndieAuth testing with HTTPS
|
||||
|
||||
## File Locations
|
||||
|
||||
### New Files
|
||||
```
|
||||
starpunk/feed.py # RSS generation module
|
||||
Containerfile # Container build definition
|
||||
compose.yaml # Container orchestration
|
||||
.containerignore # Container build exclusions
|
||||
Caddyfile.example # Caddy reverse proxy config
|
||||
nginx.conf.example # Nginx reverse proxy config
|
||||
tests/test_feed.py # Feed unit tests
|
||||
tests/test_routes_feed.py # Feed route tests
|
||||
docs/designs/phase-5-rss-and-container.md # This phase design
|
||||
docs/designs/phase-5-quick-reference.md # This guide
|
||||
docs/decisions/ADR-014-rss-feed-implementation.md # RSS ADR
|
||||
```
|
||||
|
||||
### Modified Files
|
||||
```
|
||||
starpunk/routes/public.py # Add /feed.xml route
|
||||
starpunk/__init__.py # Add /health endpoint
|
||||
starpunk/config.py # Add feed configuration
|
||||
templates/base.html # Add RSS discovery link
|
||||
templates/index.html # Add RSS nav link
|
||||
.env.example # Add feed/container vars
|
||||
CHANGELOG.md # Document v0.6.0
|
||||
```
|
||||
|
||||
## Key Implementation Details
|
||||
|
||||
### RSS Feed Module
|
||||
|
||||
**File**: `starpunk/feed.py`
|
||||
|
||||
**Core Function**:
|
||||
```python
|
||||
from feedgen.feed import FeedGenerator
|
||||
from starpunk.notes import list_notes
|
||||
|
||||
def generate_feed(site_url, site_name, site_description, notes, limit=50):
|
||||
"""Generate RSS 2.0 XML feed"""
|
||||
fg = FeedGenerator()
|
||||
|
||||
# Set channel metadata
|
||||
fg.title(site_name)
|
||||
fg.link(href=site_url, rel='alternate')
|
||||
fg.description(site_description)
|
||||
fg.language('en')
|
||||
fg.link(href=f'{site_url}/feed.xml', rel='self')
|
||||
|
||||
# Add items
|
||||
for note in notes[:limit]:
|
||||
fe = fg.add_entry()
|
||||
fe.title(get_note_title(note))
|
||||
fe.link(href=f'{site_url}/note/{note.slug}')
|
||||
fe.guid(f'{site_url}/note/{note.slug}', permalink=True)
|
||||
fe.pubDate(note.created_at.replace(tzinfo=timezone.utc))
|
||||
fe.description(note.html) # HTML content
|
||||
|
||||
return fg.rss_str(pretty=True).decode('utf-8')
|
||||
```
|
||||
|
||||
### Feed Route
|
||||
|
||||
**File**: `starpunk/routes/public.py`
|
||||
|
||||
**Add to existing blueprint**:
|
||||
```python
|
||||
@bp.route("/feed.xml")
|
||||
def feed():
|
||||
"""RSS 2.0 feed endpoint with caching"""
|
||||
# Check cache (implementation in design doc)
|
||||
# Generate feed if cache expired
|
||||
# Return XML with proper headers
|
||||
pass
|
||||
```
|
||||
|
||||
### Health Check Endpoint
|
||||
|
||||
**File**: `starpunk/__init__.py`
|
||||
|
||||
**Add before return app**:
|
||||
```python
|
||||
@app.route('/health')
|
||||
def health_check():
|
||||
"""Container health check"""
|
||||
try:
|
||||
# Check database and filesystem
|
||||
return jsonify({'status': 'healthy', 'version': '0.6.0'}), 200
|
||||
except Exception as e:
|
||||
return jsonify({'status': 'unhealthy', 'error': str(e)}), 500
|
||||
```
|
||||
|
||||
### Containerfile
|
||||
|
||||
**Key Sections**:
|
||||
```dockerfile
|
||||
# Multi-stage build for smaller image
|
||||
FROM python:3.11-slim AS builder
|
||||
# ... install dependencies in venv ...
|
||||
|
||||
FROM python:3.11-slim
|
||||
# ... copy venv, run as non-root ...
|
||||
|
||||
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "4", "app:app"]
|
||||
```
|
||||
|
||||
## Testing Commands
|
||||
|
||||
### RSS Feed Testing
|
||||
```bash
|
||||
# Unit tests
|
||||
uv run pytest tests/test_feed.py -v
|
||||
|
||||
# Route tests
|
||||
uv run pytest tests/test_routes_feed.py -v
|
||||
|
||||
# Manual test
|
||||
curl http://localhost:5000/feed.xml
|
||||
|
||||
# Validate XML
|
||||
curl http://localhost:5000/feed.xml | xmllint --noout -
|
||||
|
||||
# W3C Validation (manual)
|
||||
# Visit: https://validator.w3.org/feed/
|
||||
# Enter: http://your-domain.com/feed.xml
|
||||
```
|
||||
|
||||
### Container Testing
|
||||
```bash
|
||||
# Build with Podman
|
||||
podman build -t starpunk:0.6.0 -f Containerfile .
|
||||
|
||||
# Build with Docker
|
||||
docker build -t starpunk:0.6.0 -f Containerfile .
|
||||
|
||||
# Run with Podman
|
||||
mkdir -p container-data/notes
|
||||
podman run -d --name starpunk \
|
||||
-p 127.0.0.1:8000:8000 \
|
||||
-v $(pwd)/container-data:/data:rw,Z \
|
||||
--env-file .env \
|
||||
starpunk:0.6.0
|
||||
|
||||
# Check health
|
||||
curl http://localhost:8000/health
|
||||
|
||||
# Check feed
|
||||
curl http://localhost:8000/feed.xml
|
||||
|
||||
# View logs
|
||||
podman logs starpunk
|
||||
|
||||
# Test with compose
|
||||
podman-compose up -d
|
||||
podman-compose logs -f
|
||||
```
|
||||
|
||||
## Configuration Examples
|
||||
|
||||
### .env for Container
|
||||
```bash
|
||||
# Required
|
||||
SITE_URL=https://your-domain.com
|
||||
SITE_NAME=My StarPunk Site
|
||||
ADMIN_ME=https://your-identity.com
|
||||
SESSION_SECRET=<random-secret>
|
||||
|
||||
# Feed configuration
|
||||
FEED_MAX_ITEMS=50
|
||||
FEED_CACHE_SECONDS=300
|
||||
|
||||
# Container configuration
|
||||
VERSION=0.6.0
|
||||
ENVIRONMENT=production
|
||||
WORKERS=4
|
||||
FLASK_ENV=production
|
||||
FLASK_DEBUG=0
|
||||
```
|
||||
|
||||
### Caddy Reverse Proxy
|
||||
```caddy
|
||||
your-domain.com {
|
||||
reverse_proxy localhost:8000
|
||||
|
||||
log {
|
||||
output file /var/log/caddy/starpunk.log
|
||||
}
|
||||
|
||||
encode gzip zstd
|
||||
}
|
||||
```
|
||||
|
||||
### Nginx Reverse Proxy
|
||||
```nginx
|
||||
upstream starpunk {
|
||||
server localhost:8000;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name your-domain.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://starpunk;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Common Issues & Solutions
|
||||
|
||||
### Issue: Feed not updating
|
||||
**Solution**: Check cache duration (5 minutes default), force refresh by restarting
|
||||
|
||||
### Issue: Container won't start
|
||||
**Solution**: Check logs (`podman logs starpunk`), verify .env file exists
|
||||
|
||||
### Issue: IndieAuth callback fails
|
||||
**Solution**: Verify SITE_URL matches public URL exactly (no trailing slash)
|
||||
|
||||
### Issue: Data not persisting
|
||||
**Solution**: Check volume mount is correct, verify permissions
|
||||
|
||||
### Issue: RSS validation errors
|
||||
**Solution**: Check date formatting (RFC-822), verify XML structure
|
||||
|
||||
## Deployment Workflow
|
||||
|
||||
### 1. Local Testing
|
||||
```bash
|
||||
# Test feed locally
|
||||
uv run flask --app app.py run --debug
|
||||
curl http://localhost:5000/feed.xml
|
||||
```
|
||||
|
||||
### 2. Container Testing
|
||||
```bash
|
||||
# Build and test container
|
||||
podman build -t starpunk:0.6.0 .
|
||||
podman run -d -p 8000:8000 --name starpunk-test starpunk:0.6.0
|
||||
curl http://localhost:8000/health
|
||||
```
|
||||
|
||||
### 3. Production Deployment
|
||||
```bash
|
||||
# On server
|
||||
git clone <repo>
|
||||
cd starpunk
|
||||
cp .env.example .env
|
||||
# Edit .env with production values
|
||||
|
||||
# Build and run
|
||||
podman-compose up -d
|
||||
|
||||
# Configure reverse proxy (Caddy or Nginx)
|
||||
# Set up HTTPS with certbot or Caddy auto-HTTPS
|
||||
|
||||
# Test IndieAuth
|
||||
# Visit https://your-domain.com/admin/login
|
||||
```
|
||||
|
||||
## Success Criteria
|
||||
|
||||
Phase 5 complete when:
|
||||
- [ ] RSS feed validates with W3C validator
|
||||
- [ ] Feed appears correctly in RSS readers
|
||||
- [ ] Container builds and runs successfully
|
||||
- [ ] Health check endpoint responds
|
||||
- [ ] Data persists across container restarts
|
||||
- [ ] IndieAuth works with public HTTPS URL
|
||||
- [ ] All tests pass (>90% coverage)
|
||||
- [ ] Documentation complete
|
||||
- [ ] Version incremented from 0.5.1 to 0.6.0 in `starpunk/__init__.py`
|
||||
- [ ] Feature branch `feature/phase-5-rss-container` merged to main
|
||||
|
||||
## Time Estimate
|
||||
|
||||
- RSS Feed Implementation: 3-4 hours
|
||||
- Container Implementation: 3-4 hours
|
||||
- Testing: 2-3 hours
|
||||
- Documentation: 1-2 hours
|
||||
|
||||
**Total**: 9-13 hours
|
||||
|
||||
## Next Steps After Completion
|
||||
|
||||
1. Ensure all changes committed on feature branch:
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "feat: implement RSS feed and production container (v0.6.0)"
|
||||
```
|
||||
2. Create PR to merge `feature/phase-5-rss-container` into main
|
||||
3. After merge, tag release on main:
|
||||
```bash
|
||||
git checkout main
|
||||
git pull
|
||||
git tag -a v0.6.0 -m "Release 0.6.0: RSS feed and production container"
|
||||
git push --tags
|
||||
```
|
||||
4. Create implementation report in `docs/reports/`
|
||||
5. Begin Phase 6 planning (Micropub implementation)
|
||||
|
||||
## Reference Documents
|
||||
|
||||
- [Phase 5 Full Design](/home/phil/Projects/starpunk/docs/designs/phase-5-rss-and-container.md)
|
||||
- [ADR-014: RSS Implementation](/home/phil/Projects/starpunk/docs/decisions/ADR-014-rss-feed-implementation.md)
|
||||
- [Versioning Strategy](/home/phil/Projects/starpunk/docs/standards/versioning-strategy.md)
|
||||
- [Git Branching Strategy](/home/phil/Projects/starpunk/docs/standards/git-branching-strategy.md)
|
||||
|
||||
---
|
||||
|
||||
**Phase**: 5
|
||||
**Version**: 0.6.0
|
||||
**Date**: 2025-11-18
|
||||
**Status**: Ready for Implementation
|
||||
Reference in New Issue
Block a user