## 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>
522 lines
14 KiB
Markdown
522 lines
14 KiB
Markdown
# 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)
|
|
|
|
1. **Must work for local testing** - Allow developers to authenticate locally
|
|
2. **Must be easy to use** - Minimal configuration required
|
|
3. **Must NEVER exist in production** - Critical security requirement
|
|
4. **Must integrate seamlessly** - Work with existing auth module
|
|
5. **Must allow protected route testing** - Enable full workflow testing
|
|
6. **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:
|
|
1. Only activates when explicitly configured
|
|
2. Uses a different route from production auth
|
|
3. Clearly indicates development mode
|
|
4. Requires explicit opt-in via environment variable
|
|
5. Logs prominent warnings when active
|
|
6. Cannot coexist with production configuration
|
|
|
|
### Implementation Design
|
|
|
|
#### Configuration
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```python
|
|
# 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
|
|
|
|
```python
|
|
# /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**
|
|
```python
|
|
# 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**
|
|
```python
|
|
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**
|
|
```html
|
|
<!-- 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**
|
|
```python
|
|
# 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
|
|
|
|
1. **Faster Development** - Test auth flows without deployment
|
|
2. **Better Testing** - Comprehensive test coverage possible
|
|
3. **Offline Development** - No network dependency
|
|
4. **Simpler Onboarding** - New developers can start immediately
|
|
5. **CI/CD Friendly** - Tests run without external services
|
|
6. **Clear Separation** - Dev code isolated from production
|
|
|
|
### Negative
|
|
|
|
1. **Additional Code** - ~100 lines of dev-specific code
|
|
2. **Maintenance Burden** - Another code path to maintain
|
|
3. **Potential Misuse** - Could be accidentally enabled
|
|
4. **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
|
|
|
|
```bash
|
|
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:
|
|
|
|
1. ✓ Developers can test protected routes locally
|
|
2. ✓ No production deployment needed for auth testing
|
|
3. ✓ Tests run without network dependencies
|
|
4. ✓ DEV_MODE cannot be accidentally enabled in production
|
|
5. ✓ Clear visual/log indicators when active
|
|
6. ✓ Production auth code remains unchanged
|
|
7. ✓ Security audit passes
|
|
8. ✓ Documentation is comprehensive
|
|
|
|
## References
|
|
|
|
- [ADR-005: IndieLogin Authentication](/home/phil/Projects/starpunk/docs/decisions/ADR-005-indielogin-authentication.md)
|
|
- [ADR-010: Authentication Module Design](/home/phil/Projects/starpunk/docs/decisions/ADR-010-authentication-module-design.md)
|
|
- [OWASP Authentication Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html)
|
|
- [The Twelve-Factor App - Dev/Prod Parity](https://12factor.net/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
|