## 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>
14 KiB
ADR-011: Development Authentication Mechanism
Status
Accepted
Context
During Phase 4 development (Web Interface), the team needs to test authentication-protected routes locally. However, IndieLogin.com requires:
- A publicly accessible callback URL (HTTPS)
- A real domain with valid DNS
- External network connectivity
This creates friction for local development:
- Cannot test protected routes without deploying
- Cannot run tests without network access
- Cannot develop offline
- Slow iteration cycle (deploy to test auth flows)
The question: Should we implement a development-only authentication mechanism?
Requirements for Dev Auth (if implemented)
- Must work for local testing - Allow developers to authenticate locally
- Must be easy to use - Minimal configuration required
- Must NEVER exist in production - Critical security requirement
- Must integrate seamlessly - Work with existing auth module
- Must allow protected route testing - Enable full workflow testing
- Must not compromise security - No backdoors in production code
Security Criticality
This is an extremely sensitive decision. Implemented incorrectly, a dev auth mechanism could:
- Create a production authentication bypass
- Expose admin functionality to attackers
- Violate IndieWeb authentication principles
- Undermine the entire security model
Decision
YES - Implement a development authentication mechanism with strict safeguards
Approach: Environment-Based Toggle with Explicit Configuration
We will implement a separate development authentication pathway that:
- Only activates when explicitly configured
- Uses a different route from production auth
- Clearly indicates development mode
- Requires explicit opt-in via environment variable
- Logs prominent warnings when active
- Cannot coexist with production configuration
Implementation Design
Configuration
# Development mode (mutually exclusive)
DEV_MODE=true
DEV_ADMIN_ME=https://yoursite.com # Identity to simulate
# Production mode
DEV_MODE=false # or unset
ADMIN_ME=https://yoursite.com
SITE_URL=https://production.example.com
Route Structure
# Production authentication (always available)
GET /admin/login # IndieLogin flow
POST /admin/login # Initiate IndieLogin
GET /auth/callback # IndieLogin callback
POST /admin/logout # Logout
# Development authentication (DEV_MODE only)
GET /dev/login # Development login form
POST /dev/login # Instant login (no external service)
Dev Auth Flow
# /dev/login (GET)
def dev_login_form():
# Check DEV_MODE is enabled
if not current_app.config.get('DEV_MODE'):
abort(404) # Route doesn't exist in production
# Render simple form or auto-login
return render_template('dev/login.html')
# /dev/login (POST)
def dev_login():
# Check DEV_MODE is enabled
if not current_app.config.get('DEV_MODE'):
abort(404)
# Get configured dev admin identity
me = current_app.config.get('DEV_ADMIN_ME')
# Create session directly (bypass IndieLogin)
session_token = create_session(me)
# Log warning
current_app.logger.warning(
f"DEV MODE: Created session for {me} without authentication"
)
# Set cookie and redirect
response = redirect('/admin')
response.set_cookie('session', session_token,
httponly=True, secure=False)
return response
Safeguards
1. Route Registration Protection
# In app.py or routes module
def register_routes(app):
# Always register production routes
register_production_auth_routes(app)
# Only register dev routes if DEV_MODE enabled
if app.config.get('DEV_MODE'):
app.logger.warning(
"=" * 60 + "\n"
"WARNING: Development authentication enabled!\n"
"This should NEVER be used in production.\n"
"Set DEV_MODE=false for production deployments.\n" +
"=" * 60
)
register_dev_auth_routes(app)
2. Configuration Validation
def validate_config(app):
dev_mode = app.config.get('DEV_MODE', False)
if dev_mode:
# Require DEV_ADMIN_ME
if not app.config.get('DEV_ADMIN_ME'):
raise ConfigError("DEV_MODE requires DEV_ADMIN_ME")
# Prevent production config in dev mode
if app.config.get('SITE_URL', '').startswith('https://'):
app.logger.error(
"WARNING: DEV_MODE with production SITE_URL detected"
)
else:
# Require production config
if not app.config.get('ADMIN_ME'):
raise ConfigError("Production mode requires ADMIN_ME")
3. Visual Indicators
<!-- base.html template -->
{% if config.DEV_MODE %}
<div style="background: red; color: white; padding: 10px; text-align: center;">
⚠️ DEVELOPMENT MODE - Authentication bypassed
</div>
{% endif %}
4. Test Detection
# In tests/conftest.py
@pytest.fixture
def app():
app = create_app()
app.config['DEV_MODE'] = True
app.config['DEV_ADMIN_ME'] = 'https://test.example.com'
app.config['TESTING'] = True
return app
File Organization
starpunk/
├── auth.py # Production auth functions (unchanged)
├── dev_auth.py # Development auth functions (new)
└── routes/
├── auth.py # Production auth routes
└── dev_auth.py # Dev auth routes (conditional registration)
templates/
└── dev/
└── login.html # Simple dev login form
Rationale
Why Implement Dev Auth?
Development Velocity: 10/10
- Test protected routes instantly
- No deployment required for auth testing
- Faster iteration cycle
- Enable offline development
- Simplify CI/CD testing
Developer Experience: 10/10
- Remove friction from local development
- Make onboarding easier
- Enable rapid prototyping
- Reduce cognitive load
Testing Benefits: 10/10
- Test auth flows without network
- Deterministic test behavior
- Faster test execution
- Enable integration tests
- Mock external dependencies
Why This Specific Approach?
Separate Routes (vs modifying production routes):
- Clear separation of concerns
- No conditional logic in production code
- Easy to audit security
- Impossible to accidentally enable in production
Explicit DEV_MODE (vs detecting localhost):
- Explicit is better than implicit
- Prevents accidental activation
- Clear intent in configuration
- Works in any environment
Separate Configuration Variables (vs reusing ADMIN_ME):
- Prevents production config confusion
- Makes dev mode obvious
- Enables validation logic
- Clear intent
Module Separation (vs mixing in auth.py):
- Production auth code stays clean
- Easy to review for security
- Can exclude from production builds
- Clear architectural boundary
Consequences
Positive
- Faster Development - Test auth flows without deployment
- Better Testing - Comprehensive test coverage possible
- Offline Development - No network dependency
- Simpler Onboarding - New developers can start immediately
- CI/CD Friendly - Tests run without external services
- Clear Separation - Dev code isolated from production
Negative
- Additional Code - ~100 lines of dev-specific code
- Maintenance Burden - Another code path to maintain
- Potential Misuse - Could be accidentally enabled
- Security Risk - If misconfigured, creates vulnerability
Mitigations
For Accidental Activation:
- Startup warnings if DEV_MODE enabled
- Configuration validation
- Visual indicators in UI
- Documentation emphasizing risk
For Security:
- Separate routes (not modifying production)
- Explicit configuration required
- 404 if DEV_MODE disabled
- Logging all dev auth usage
- Code review checklist
For Maintenance:
- Keep dev auth code simple
- Document clearly
- Include in test coverage
- Regular security audits
Alternatives Considered
1. No Dev Auth - Always Use IndieLogin (Rejected)
Approach: Require deployment for auth testing
Pros:
- No security risk
- No additional code
- Forces realistic testing
Cons:
- Slow development cycle
- Cannot test offline
- Requires deployment infrastructure
- Painful onboarding
Verdict: Rejected - Too much friction for development
2. Mock IndieLogin in Tests Only (Rejected)
Approach: Mock httpx responses in tests, no dev mode
Pros:
- Works for tests
- No production risk
- Simple implementation
Cons:
- Doesn't help manual testing
- Cannot test in browser
- Doesn't solve local development
- Still requires deployment for UI testing
Verdict: Rejected - Solves tests but not development workflow
3. Localhost Detection (Rejected)
Approach: Auto-enable dev auth if running on localhost
Pros:
- No configuration needed
- Automatic
Cons:
- Implicit behavior (dangerous)
- Could run production on localhost
- Hard to disable
- Security through obscurity
Verdict: Rejected - Too implicit, risky
4. Special Password (Rejected)
Approach: Accept a special dev password for local auth
Pros:
- Familiar pattern
- Easy to implement
Cons:
- Password in code or config
- Could leak to production
- Not IndieWeb-compatible
- Defeats purpose of IndieLogin
Verdict: Rejected - Undermines authentication model
5. Self-Hosted IndieAuth Server (Rejected)
Approach: Run local IndieAuth server for development
Pros:
- Realistic auth flow
- No dev auth code needed
- Tests full integration
Cons:
- Complex setup
- Additional service to run
- Doesn't work offline
- Violates simplicity principle
Verdict: Rejected - Too complex for V1
6. Session Injection via CLI (Considered)
Approach: Command-line tool to create dev sessions directly in DB
python -m starpunk dev-login --me https://test.com
Pros:
- No web routes needed
- Very explicit
- Hard to misuse
- Clean separation
Cons:
- Less convenient than web UI
- Doesn't test login flow
- Requires DB access
- Extra tooling
Verdict: Good alternative, but web route is more ergonomic
7. Separate Dev Auth Endpoint with Token (Considered)
Approach: /dev/auth?token=SECRET route with shared secret
Pros:
- Prevents accidental use
- Simple implementation
- Works in browser
Cons:
- Secret in URL (logs)
- Still a backdoor
- Not much better than env var
Verdict: Similar risk profile, less clear
Implementation Phases
Phase 1: Core Dev Auth (Phase 4)
- Implement dev_auth.py module
- Add DEV_MODE configuration
- Create /dev/login routes
- Add configuration validation
- Update documentation
Phase 2: Developer Experience (Phase 4)
- Visual dev mode indicators
- Startup warnings
- Better error messages
- Quick-start guide
Phase 3: Security Hardening (Before v1.0)
- Security audit of dev auth
- Penetration testing
- Code review checklist
- Production deployment guide
Security Checklist
Before v1.0 release:
- DEV_MODE defaults to false
- Production docs emphasize security
- Deployment guide includes check for DEV_MODE=false
- Startup warnings are prominent
- Routes return 404 when DEV_MODE=false
- No way to enable DEV_MODE in production config
- Security audit completed
- Code review of dev auth implementation
- Test that production build doesn't include dev routes
- Documentation warns about risks
Testing Strategy
Unit Tests
- Test dev auth functions in isolation
- Test configuration validation
- Test route registration logic
- Test DEV_MODE toggle behavior
Integration Tests
- Test full dev auth flow
- Test production auth still works
- Test DEV_MODE disabled blocks dev routes
- Test visual indicators appear
Security Tests
- Test dev routes return 404 in production mode
- Test configuration validation catches mistakes
- Test cannot enable with production URL
- Test logging captures dev auth usage
Documentation Requirements
Developer Guide
- How to enable DEV_MODE for local development
- Clear warnings about production use
- Explanation of security model
- Troubleshooting guide
Production Deployment Guide
- Checklist to verify DEV_MODE=false
- How to validate production configuration
- What to check before deployment
Security Documentation
- Threat model for dev auth
- Security trade-offs
- Mitigation strategies
- Incident response if misconfigured
Success Criteria
Dev auth implementation is successful if:
- ✓ Developers can test protected routes locally
- ✓ No production deployment needed for auth testing
- ✓ Tests run without network dependencies
- ✓ DEV_MODE cannot be accidentally enabled in production
- ✓ Clear visual/log indicators when active
- ✓ Production auth code remains unchanged
- ✓ Security audit passes
- ✓ Documentation is comprehensive
References
- ADR-005: IndieLogin Authentication
- ADR-010: Authentication Module Design
- OWASP Authentication Cheat Sheet
- The Twelve-Factor App - Dev/Prod Parity
ADR: 011 Date: 2025-11-18 Status: Accepted Decision: Implement environment-based development authentication with strict safeguards Impact: Development workflow, testing, security architecture