Files
StarPunk/docs/design/phase-4-quick-reference.md
Phil Skentelbery 0cca8169ce feat: Implement Phase 4 Web Interface with bugfixes (v0.5.2)
## Phase 4: Web Interface Implementation

Implemented complete web interface with public and admin routes,
templates, CSS, and development authentication.

### Core Features

**Public Routes**:
- Homepage with recent published notes
- Note permalinks with microformats2
- Server-side rendering (Jinja2)

**Admin Routes**:
- Login via IndieLogin
- Dashboard with note management
- Create, edit, delete notes
- Protected with @require_auth decorator

**Development Authentication**:
- Dev login bypass for local testing (DEV_MODE only)
- Security safeguards per ADR-011
- Returns 404 when disabled

**Templates & Frontend**:
- Base layouts (public + admin)
- 8 HTML templates with microformats2
- Custom responsive CSS (114 lines)
- Error pages (404, 500)

### Bugfixes (v0.5.1 → v0.5.2)

1. **Cookie collision fix (v0.5.1)**:
   - Renamed auth cookie from "session" to "starpunk_session"
   - Fixed redirect loop between dev login and admin dashboard
   - Flask's session cookie no longer conflicts with auth

2. **HTTP 404 error handling (v0.5.1)**:
   - Update route now returns 404 for nonexistent notes
   - Delete route now returns 404 for nonexistent notes
   - Follows ADR-012 HTTP Error Handling Policy
   - Pattern consistency across all admin routes

3. **Note model enhancement (v0.5.2)**:
   - Exposed deleted_at field from database schema
   - Enables soft deletion verification in tests
   - Follows ADR-013 transparency principle

### Architecture

**New ADRs**:
- ADR-011: Development Authentication Mechanism
- ADR-012: HTTP Error Handling Policy
- ADR-013: Expose deleted_at Field in Note Model

**Standards Compliance**:
- Uses uv for Python environment
- Black formatted, Flake8 clean
- Follows git branching strategy
- Version incremented per versioning strategy

### Test Results

- 405/406 tests passing (99.75%)
- 87% code coverage
- All security tests passing
- Manual testing confirmed working

### Documentation

- Complete implementation reports in docs/reports/
- Architecture reviews in docs/reviews/
- Design documents in docs/design/
- CHANGELOG updated for v0.5.2

### Files Changed

**New Modules**:
- starpunk/dev_auth.py
- starpunk/routes/ (public, admin, auth, dev_auth)

**Templates**: 10 files (base, pages, admin, errors)
**Static**: CSS and optional JavaScript
**Tests**: 4 test files for routes and templates
**Docs**: 20+ architectural and implementation documents

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 23:01:53 -07:00

565 lines
11 KiB
Markdown

# Phase 4: Quick Reference
**Phase**: Web Interface
**Version**: 0.5.0
**Status**: Design Complete
**Dependencies**: Phase 3 (Authentication) ✓
## Critical Decision: Development Authentication
**Question**: Should we implement a dev auth mechanism for local testing?
**Answer**: ✓ **YES** - Implement with strict safeguards
**Why**: Enable local testing without deploying to IndieLogin.com
**How**: Separate `/dev/login` route that only works when `DEV_MODE=true`
**Safety**: Returns 404 when disabled, visual warnings, config validation
**Details**: See ADR-011
---
## What Phase 4 Delivers
### Public Interface
- Homepage with recent notes (`/`)
- Note permalinks (`/note/<slug>`)
- Microformats2 markup (h-feed, h-entry)
### Admin Interface
- Login via IndieLogin (`/admin/login`)
- Dashboard with note list (`/admin`)
- Create notes (`/admin/new`)
- Edit notes (`/admin/edit/<id>`)
- Delete notes (`/admin/delete/<id>`)
### Development Tools
- Dev auth for local testing (`/dev/login`)
- Configuration validation
- Dev mode warnings
---
## Routes Summary
### Public (No Auth)
```
GET / Homepage (note list)
GET /note/<slug> Note permalink
```
### Auth Flow
```
GET /admin/login Login form
POST /admin/login Start IndieLogin flow
GET /auth/callback IndieLogin callback
POST /admin/logout Logout
```
### Admin (Auth Required)
```
GET /admin Dashboard
GET /admin/new Create note form
POST /admin/new Save new note
GET /admin/edit/<id> Edit note form
POST /admin/edit/<id> Update note
POST /admin/delete/<id> Delete note
```
### Dev (DEV_MODE Only)
```
GET /dev/login Instant login (bypasses IndieLogin)
```
---
## File Structure
### New Files (~2,770 lines total)
```
starpunk/routes/ # Route handlers
├── public.py # Public routes
├── admin.py # Admin routes
├── auth.py # Auth routes
└── dev_auth.py # Dev routes
starpunk/dev_auth.py # Dev auth module
templates/ # Jinja2 templates
├── base.html
├── index.html
├── note.html
└── admin/
├── base.html
├── login.html
├── dashboard.html
├── new.html
└── edit.html
static/css/style.css # ~350 lines
static/js/preview.js # Optional markdown preview
tests/
├── test_routes_public.py
├── test_routes_admin.py
└── test_dev_auth.py
```
### Modified Files
```
starpunk/config.py # Add DEV_MODE, DEV_ADMIN_ME, VERSION
app.py # Register routes, validate config
CHANGELOG.md # Add v0.5.0 entry
```
---
## Configuration
### New Environment Variables
```bash
# Development Mode (default: false)
DEV_MODE=false # Set to 'true' for local dev
DEV_ADMIN_ME= # Your identity URL for dev mode
# Version (for display)
VERSION=0.5.0
```
### Development Setup
```bash
# For local development
DEV_MODE=true
DEV_ADMIN_ME=https://yoursite.com
# For production (or leave unset)
DEV_MODE=false
ADMIN_ME=https://yoursite.com
```
---
## Security Measures
### Dev Auth Safeguards
1. **Explicit Configuration**: Requires `DEV_MODE=true`
2. **Separate Routes**: `/dev/login` (not `/admin/login`)
3. **Route Protection**: Returns 404 if DEV_MODE=false
4. **Config Validation**: Prevents DEV_MODE + production URL
5. **Visual Warnings**: Red banner when dev mode active
6. **Logging**: All dev auth logged with warnings
### Production Security
- All admin routes use `@require_auth`
- HttpOnly, Secure, SameSite cookies
- CSRF state tokens
- Session expiry (30 days)
- Jinja2 auto-escaping (XSS prevention)
---
## Template Architecture
### Microformats
**Homepage** (h-feed):
```html
<div class="h-feed">
<article class="h-entry">
<div class="e-content">...</div>
<time class="dt-published">...</time>
<a class="u-url" href="...">permalink</a>
</article>
</div>
```
**Note Page** (h-entry):
```html
<article class="h-entry">
<div class="e-content">{{ note.html|safe }}</div>
<a class="u-url" href="{{ url_for('public.note', slug=note.slug) }}">
<time class="dt-published" datetime="{{ note.created_at.isoformat() }}">
{{ note.created_at.strftime('%B %d, %Y') }}
</time>
</a>
</article>
```
### Flash Messages
```python
# In routes
flash('Note created successfully', 'success')
flash('Error: Note not found', 'error')
# In templates
{% with messages = get_flashed_messages(with_categories=true) %}
{% for category, message in messages %}
<div class="flash flash-{{ category }}">{{ message }}</div>
{% endfor %}
{% endwith %}
```
---
## CSS Architecture
### Variables
```css
:root {
/* Colors */
--color-text: #333;
--color-bg: #fff;
--color-link: #0066cc;
--color-success: #28a745;
--color-error: #dc3545;
--color-warning: #ffc107;
/* Typography */
--font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--font-mono: 'SF Mono', Monaco, monospace;
/* Spacing */
--spacing-md: 1rem;
--spacing-lg: 2rem;
/* Layout */
--max-width: 42rem;
}
```
### Mobile-First
```css
/* Base: Mobile */
body { padding: 1rem; }
/* Tablet and up */
@media (min-width: 768px) {
body { padding: 2rem; }
}
```
---
## Testing Strategy
### Coverage Target: >90%
### Unit Tests
- Public routes (homepage, note permalink)
- Admin routes (dashboard, create, edit, delete)
- Dev auth (login, validation, route protection)
### Integration Tests
- Full auth flow (mocked IndieLogin)
- Create note end-to-end
- Edit note end-to-end
- Delete note end-to-end
### Manual Tests
- Browser testing (Chrome, Firefox, Safari)
- Mobile responsive
- Microformats validation (indiewebify.me)
- HTML5 validation (W3C)
- Real IndieLogin authentication
---
## Implementation Checklist
### Phase 4.1: Routes (8 hours)
- [ ] Create routes package
- [ ] Implement public routes
- [ ] Implement auth routes
- [ ] Implement admin routes
### Phase 4.2: Templates (6 hours)
- [ ] Base templates
- [ ] Public templates
- [ ] Admin templates
### Phase 4.3: Dev Auth (4 hours)
- [ ] dev_auth.py module
- [ ] Config validation
- [ ] Visual warnings
### Phase 4.4: CSS (4 hours)
- [ ] style.css
- [ ] Responsive design
### Phase 4.5: JS (Optional, 2 hours)
- [ ] preview.js
- [ ] Progressive enhancement
### Phase 4.6: Testing (8 hours)
- [ ] Route tests
- [ ] Integration tests
- [ ] >90% coverage
### Phase 4.7: Documentation (2 hours)
- [ ] Update CHANGELOG
- [ ] Document routes
- [ ] Version to 0.5.0
**Total: ~34 hours**
---
## Acceptance Criteria
### Must Pass
- [ ] All routes work correctly
- [ ] Authentication enforced on admin routes
- [ ] Dev auth blocked when DEV_MODE=false
- [ ] Templates render with microformats
- [ ] Flash messages work
- [ ] Test coverage >90%
- [ ] No security vulnerabilities
- [ ] Dev mode warnings display
- [ ] Mobile responsive
---
## Performance Targets
- Homepage: < 200ms
- Note page: < 200ms
- Admin pages: < 200ms
- Form submit: < 100ms
---
## Key Integrations
### With Existing Modules
**auth.py** (Phase 3):
```python
from starpunk.auth import require_auth, verify_session, destroy_session
@require_auth
def dashboard():
# User info in g.user_me
pass
```
**notes.py** (Phase 2):
```python
from starpunk.notes import (
get_all_notes,
get_note_by_slug,
create_note,
update_note,
delete_note
)
```
**database.py** (Phase 1):
```python
from starpunk.database import get_db
```
---
## Risk Mitigation
### Dev Auth Accidentally Enabled
**Risk**: Critical
**Mitigation**:
- Config validation
- Startup warnings
- Visual indicators
- Deployment checklist
- Documentation
### XSS Vulnerabilities
**Risk**: High
**Mitigation**:
- Jinja2 auto-escaping
- No user HTML
- Code review
- Security testing
### Session Theft
**Risk**: Medium
**Mitigation**:
- HttpOnly cookies
- Secure flag (production)
- SameSite=Lax
- HTTPS required
---
## Common Patterns
### Protected Route
```python
from starpunk.auth import require_auth
@app.route('/admin/dashboard')
@require_auth
def dashboard():
# g.user_me is set by require_auth
notes = get_all_notes()
return render_template('admin/dashboard.html', notes=notes)
```
### Creating a Note
```python
@app.route('/admin/new', methods=['POST'])
@require_auth
def create_note_submit():
content = request.form.get('content')
published = 'published' in request.form
try:
note = create_note(content, published)
flash(f'Note created: {note.slug}', 'success')
return redirect(url_for('admin.dashboard'))
except ValueError as e:
flash(f'Error: {e}', 'error')
return redirect(url_for('admin.new_note_form'))
```
### Dev Mode Check
```python
# In dev_auth.py
def dev_login():
if not current_app.config.get('DEV_MODE'):
abort(404) # Route doesn't exist
me = current_app.config.get('DEV_ADMIN_ME')
session_token = create_session(me)
current_app.logger.warning(
f"DEV MODE: Session created for {me} without authentication"
)
# Set cookie and redirect
response = redirect(url_for('admin.dashboard'))
response.set_cookie('session', session_token, httponly=True)
return response
```
---
## Troubleshooting
### Dev Auth Not Working
1. Check `DEV_MODE=true` in `.env`
2. Check `DEV_ADMIN_ME` is set
3. Restart Flask server
4. Check logs for warnings
### Templates Not Found
1. Check templates/ directory exists
2. Check template paths in render_template()
3. Restart Flask server
### CSS Not Loading
1. Check static/css/style.css exists
2. Check url_for('static', filename='css/style.css')
3. Clear browser cache
### Authentication Not Working
1. Check ADMIN_ME is set correctly
2. Check SESSION_SECRET is set
3. Check IndieLogin callback URL matches
4. Check browser cookies enabled
---
## Next Steps After Phase 4
### Phase 5: RSS Feed
- Generate `/feed.xml`
- Valid RSS 2.0
- Published notes only
### Phase 6: Micropub
- `/api/micropub` endpoint
- Accept h-entry posts
- IndieAuth token verification
### V1.0.0
- Complete V1 features
- Security audit
- Performance optimization
- Production deployment
---
## Documentation References
- **ADR-011**: Development Auth Decision
- **Phase 4 Design**: Complete specification
- **Assessment Report**: Architectural review
- **Phase 3 Report**: Authentication implementation
- **ADR-003**: Frontend Technology
- **ADR-005**: IndieLogin Authentication
- **ADR-010**: Authentication Module Design
---
## Git Workflow
```bash
# Create feature branch
git checkout -b feature/phase-4-web-interface main
# Implement, test, commit frequently
git commit -m "Add public routes"
git commit -m "Add admin routes"
git commit -m "Add templates"
git commit -m "Add dev auth"
git commit -m "Add CSS"
git commit -m "Add tests"
# Update version
# Edit starpunk/__init__.py: __version__ = "0.5.0"
# Edit CHANGELOG.md
git commit -m "Bump version to 0.5.0"
# Merge to main
git checkout main
git merge feature/phase-4-web-interface
# Tag
git tag -a v0.5.0 -m "Release 0.5.0: Web Interface complete"
# Push
git push origin main v0.5.0
```
---
**Status**: Ready for Implementation
**Estimated Effort**: 34 hours
**Target Version**: 0.5.0
**Developer**: Use with Phase 4 Design Document