# IndieAuth Removal: Phased Implementation Guide

## Overview

This document breaks down the IndieAuth server removal into testable phases, each with clear acceptance criteria and verification steps.

## Phase 1: Remove Authorization Server (4 hours)

### Objective
Remove the authorization endpoint and consent UI while keeping the system functional.

### Tasks

#### 1.1 Remove Authorization UI (30 min)
```bash
# Delete consent template
rm /home/phil/Projects/starpunk/templates/auth/authorize.html

# Verify
ls /home/phil/Projects/starpunk/templates/auth/
# Should be empty or not exist
```

#### 1.2 Remove Authorization Endpoint (1 hour)
In `/home/phil/Projects/starpunk/starpunk/routes/auth.py`:
- Delete `authorization_endpoint()` function
- Delete related imports from `starpunk.tokens`
- Keep admin auth routes intact

#### 1.3 Remove Authorization Tests (30 min)
```bash
# Delete test files
rm /home/phil/Projects/starpunk/tests/test_routes_authorization.py
rm /home/phil/Projects/starpunk/tests/test_auth_pkce.py
```

#### 1.4 Remove PKCE Implementation (1 hour)
From `/home/phil/Projects/starpunk/starpunk/auth.py`:
- Remove `generate_code_verifier()`
- Remove `calculate_code_challenge()`
- Remove PKCE validation logic
- Keep session management functions

#### 1.5 Update Route Registration (30 min)
Ensure no references to `/auth/authorization` in:
- URL route definitions
- Template URL generation
- Documentation

### Acceptance Criteria

✅ **Server Starts Successfully**
```bash
uv run python -m starpunk
# No import errors or missing route errors
```

✅ **Admin Login Works**
```bash
# Navigate to /admin/login
# Can still authenticate via IndieLogin.com
# Session created successfully
```

✅ **No Authorization Endpoint**
```bash
curl -I http://localhost:5000/auth/authorization
# Should return 404 Not Found
```

✅ **Tests Pass (Remaining)**
```bash
uv run pytest tests/ -k "not authorization and not pkce"
# All remaining tests pass
```

### Verification Commands
```bash
# Check for orphaned imports
grep -r "authorization_endpoint" /home/phil/Projects/starpunk/
# Should return nothing

# Check for PKCE references
grep -r "code_challenge\|code_verifier" /home/phil/Projects/starpunk/
# Should only appear in migration files or comments
```

---

## Phase 2: Remove Token Issuance (3 hours)

### Objective
Remove token generation and issuance while keeping token verification temporarily.

### Tasks

#### 2.1 Remove Token Endpoint (1 hour)
In `/home/phil/Projects/starpunk/starpunk/routes/auth.py`:
- Delete `token_endpoint()` function
- Remove token-related imports

#### 2.2 Remove Token Generation (1 hour)
In `/home/phil/Projects/starpunk/starpunk/tokens.py`:
- Remove `create_access_token()`
- Remove `create_authorization_code()`
- Remove `exchange_authorization_code()`
- Keep `verify_token()` temporarily (will modify in Phase 4)

#### 2.3 Remove Token Tests (30 min)
```bash
rm /home/phil/Projects/starpunk/tests/test_routes_token.py
rm /home/phil/Projects/starpunk/tests/test_tokens.py
```

#### 2.4 Clean Up Exceptions (30 min)
Remove custom exceptions:
- `InvalidAuthorizationCodeError`
- `ExpiredAuthorizationCodeError`
- Update error handling to use generic exceptions

### Acceptance Criteria

✅ **No Token Endpoint**
```bash
curl -I http://localhost:5000/auth/token
# Should return 404 Not Found
```

✅ **No Token Generation Code**
```bash
grep -r "create_access_token\|create_authorization_code" /home/phil/Projects/starpunk/starpunk/
# Should return nothing (except in comments)
```

✅ **Server Still Runs**
```bash
uv run python -m starpunk
# No import errors
```

✅ **Micropub Temporarily Broken (Expected)**
```bash
# This is expected and will be fixed in Phase 4
# Document that Micropub is non-functional during migration
```

### Verification Commands
```bash
# Check for token generation references
grep -r "generate_token\|issue_token" /home/phil/Projects/starpunk/
# Should be empty

# Verify exception cleanup
grep -r "InvalidAuthorizationCodeError" /home/phil/Projects/starpunk/
# Should be empty
```

---

## Phase 3: Database Schema Simplification (2 hours)

### Objective
Remove authorization and token tables from the database.

### Tasks

#### 3.1 Create Removal Migration (30 min)
Create `/home/phil/Projects/starpunk/migrations/003_remove_indieauth_tables.sql`:
```sql
-- Remove IndieAuth server tables
BEGIN TRANSACTION;

-- Drop dependent objects first
DROP INDEX IF EXISTS idx_tokens_hash;
DROP INDEX IF EXISTS idx_tokens_user_id;
DROP INDEX IF EXISTS idx_tokens_client_id;
DROP INDEX IF EXISTS idx_auth_codes_code;
DROP INDEX IF EXISTS idx_auth_codes_user_id;

-- Drop tables
DROP TABLE IF EXISTS tokens CASCADE;
DROP TABLE IF EXISTS authorization_codes CASCADE;

-- Clean up any orphaned sequences
DROP SEQUENCE IF EXISTS tokens_id_seq;
DROP SEQUENCE IF EXISTS authorization_codes_id_seq;

COMMIT;
```

#### 3.2 Run Migration (30 min)
```bash
# Backup database first
pg_dump $DATABASE_URL > backup_before_removal.sql

# Run migration
uv run python -m starpunk.migrate
```

#### 3.3 Update Schema Documentation (30 min)
Update `/home/phil/Projects/starpunk/docs/design/database-schema.md`:
- Remove token table documentation
- Remove authorization_codes table documentation
- Update ER diagram

#### 3.4 Remove Old Migration (30 min)
```bash
# Archive old migration
mv /home/phil/Projects/starpunk/migrations/002_secure_tokens_and_authorization_codes.sql \
   /home/phil/Projects/starpunk/migrations/archive/
```

### Acceptance Criteria

✅ **Tables Removed**
```sql
-- Connect to database and verify
\dt
-- Should NOT list 'tokens' or 'authorization_codes'
```

✅ **No Foreign Key Errors**
```sql
-- Check for orphaned constraints
SELECT conname FROM pg_constraint
WHERE conname LIKE '%token%' OR conname LIKE '%auth%';
-- Should return minimal results (only auth_state related)
```

✅ **Application Starts**
```bash
uv run python -m starpunk
# No database connection errors
```

✅ **Admin Functions Work**
- Can log in
- Can create posts
- Sessions persist

### Rollback Plan
```bash
# If issues arise
psql $DATABASE_URL < backup_before_removal.sql
# Re-run old migration
psql $DATABASE_URL < /home/phil/Projects/starpunk/migrations/archive/002_secure_tokens_and_authorization_codes.sql
```

---

## Phase 4: External Token Verification (4 hours)

### Objective
Replace internal token verification with external provider verification.

### Tasks

#### 4.1 Implement External Verification (2 hours)
Create new verification in `/home/phil/Projects/starpunk/starpunk/micropub.py`:
```python
import hashlib
import httpx
from typing import Optional, Dict, Any
from flask import current_app

# Simple in-memory cache
_token_cache = {}

def verify_token(bearer_token: str) -> Optional[Dict[str, Any]]:
    """Verify token with external endpoint"""
    # Check cache
    token_hash = hashlib.sha256(bearer_token.encode()).hexdigest()
    if token_hash in _token_cache:
        data, expiry = _token_cache[token_hash]
        if time.time() < expiry:
            return data
        del _token_cache[token_hash]

    # Verify with external endpoint
    endpoint = current_app.config.get('TOKEN_ENDPOINT')
    if not endpoint:
        return None

    try:
        response = httpx.get(
            endpoint,
            headers={'Authorization': f'Bearer {bearer_token}'},
            timeout=5.0
        )

        if response.status_code != 200:
            return None

        data = response.json()

        # Validate response
        if data.get('me') != current_app.config.get('ADMIN_ME'):
            return None

        if 'create' not in data.get('scope', '').split():
            return None

        # Cache for 5 minutes
        _token_cache[token_hash] = (data, time.time() + 300)

        return data

    except Exception as e:
        current_app.logger.error(f"Token verification failed: {e}")
        return None
```

#### 4.2 Update Configuration (30 min)
In `/home/phil/Projects/starpunk/starpunk/config.py`:
```python
# External IndieAuth settings
TOKEN_ENDPOINT = os.getenv('TOKEN_ENDPOINT', 'https://tokens.indieauth.com/token')
ADMIN_ME = os.getenv('ADMIN_ME')  # Required

# Validate configuration
if not ADMIN_ME:
    raise ValueError("ADMIN_ME must be configured")
```

#### 4.3 Remove Old Token Module (30 min)
```bash
rm /home/phil/Projects/starpunk/starpunk/tokens.py
```

#### 4.4 Update Tests (1 hour)
Update `/home/phil/Projects/starpunk/tests/test_micropub.py`:
```python
@patch('starpunk.micropub.httpx.get')
def test_external_token_verification(mock_get):
    mock_response = Mock()
    mock_response.status_code = 200
    mock_response.json.return_value = {
        'me': 'https://example.com',
        'scope': 'create update'
    }
    mock_get.return_value = mock_response

    # Test verification
    result = verify_token('test-token')
    assert result is not None
    assert result['me'] == 'https://example.com'
```

### Acceptance Criteria

✅ **External Verification Works**
```bash
# With a valid token from tokens.indieauth.com
curl -X POST http://localhost:5000/micropub \
  -H "Authorization: Bearer VALID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type": ["h-entry"], "properties": {"content": ["Test"]}}'
# Should return 201 Created
```

✅ **Invalid Tokens Rejected**
```bash
curl -X POST http://localhost:5000/micropub \
  -H "Authorization: Bearer INVALID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type": ["h-entry"], "properties": {"content": ["Test"]}}'
# Should return 403 Forbidden
```

✅ **Token Caching Works**
```python
# In test environment
token = "test-token"
result1 = verify_token(token)  # External call
result2 = verify_token(token)  # Should use cache
# Verify only one external call made
```

✅ **Configuration Validated**
```bash
# Without ADMIN_ME set
unset ADMIN_ME
uv run python -m starpunk
# Should fail with clear error message
```

### Performance Verification
```bash
# Measure token verification time
time curl -X GET http://localhost:5000/micropub \
  -H "Authorization: Bearer VALID_TOKEN" \
  -w "\nTime: %{time_total}s\n"
# First call: <500ms
# Cached calls: <50ms
```

---

## Phase 5: Documentation and Discovery (2 hours)

### Objective
Update all documentation and add proper IndieAuth discovery headers.

### Tasks

#### 5.1 Add Discovery Links (30 min)
In `/home/phil/Projects/starpunk/templates/base.html`:
```html
<head>
    <!-- Existing head content -->

    <!-- IndieAuth Discovery -->
    <link rel="authorization_endpoint" href="https://indieauth.com/auth">
    <link rel="token_endpoint" href="{{ config.TOKEN_ENDPOINT }}">
    <link rel="micropub" href="{{ url_for('micropub.micropub_endpoint', _external=True) }}">
</head>
```

#### 5.2 Update User Documentation (45 min)
Create `/home/phil/Projects/starpunk/docs/user-guide/indieauth-setup.md`:
```markdown
# Setting Up IndieAuth for StarPunk

## Quick Start

1. Add these links to your personal website's HTML:
   ```html
   <link rel="authorization_endpoint" href="https://indieauth.com/auth">
   <link rel="token_endpoint" href="https://tokens.indieauth.com/token">
   <link rel="micropub" href="https://your-starpunk.com/micropub">
   ```

2. Configure StarPunk:
   ```ini
   ADMIN_ME=https://your-website.com
   TOKEN_ENDPOINT=https://tokens.indieauth.com/token
   ```

3. Use any Micropub client!
```

#### 5.3 Update README (15 min)
- Remove references to built-in authorization
- Add "Prerequisites" section about external IndieAuth
- Update configuration examples

#### 5.4 Update CHANGELOG (15 min)
```markdown
## [0.5.0] - 2025-11-24

### BREAKING CHANGES
- Removed built-in IndieAuth authorization server
- Removed token issuance functionality
- All existing tokens are invalidated

### Changed
- Token verification now uses external IndieAuth providers
- Simplified database schema (removed token tables)
- Reduced codebase by ~500 lines

### Added
- Support for external token endpoints
- Token verification caching for performance
- IndieAuth discovery links in HTML

### Migration Guide
Users must now:
1. Configure external IndieAuth provider
2. Re-authenticate with Micropub clients
3. Update ADMIN_ME configuration
```

#### 5.5 Version Bump (15 min)
Update `/home/phil/Projects/starpunk/starpunk/__init__.py`:
```python
__version__ = "0.5.0"  # Breaking change per versioning strategy
```

### Acceptance Criteria

✅ **Discovery Links Present**
```bash
curl http://localhost:5000/ | grep -E "authorization_endpoint|token_endpoint|micropub"
# Should show all three link tags
```

✅ **Documentation Complete**
- [ ] User guide explains external provider setup
- [ ] README reflects new architecture
- [ ] CHANGELOG documents breaking changes
- [ ] Migration guide provided

✅ **Version Updated**
```bash
uv run python -c "import starpunk; print(starpunk.__version__)"
# Should output: 0.5.0
```

✅ **Examples Work**
- [ ] Example configuration in docs is valid
- [ ] HTML snippet in docs is correct
- [ ] Micropub client setup instructions tested

---

## Final Validation Checklist

### System Health
- [ ] Server starts without errors
- [ ] Admin can log in
- [ ] Admin can create posts
- [ ] Micropub endpoint responds
- [ ] Valid tokens accepted
- [ ] Invalid tokens rejected
- [ ] HTML has discovery links

### Code Quality
- [ ] No orphaned imports
- [ ] No references to removed code
- [ ] Tests pass with >90% coverage
- [ ] No security warnings

### Performance
- [ ] Token verification <500ms
- [ ] Cached verification <50ms
- [ ] Memory usage stable
- [ ] No database deadlocks

### Documentation
- [ ] Architecture docs updated
- [ ] User guide complete
- [ ] API docs accurate
- [ ] CHANGELOG updated
- [ ] Version bumped

### Database
- [ ] Old tables removed
- [ ] No orphaned constraints
- [ ] Migration successful
- [ ] Backup available

## Rollback Decision Tree

```
Issue Detected?
├─ During Phase 1-2?
│  └─ Git revert commits
│      └─ Restart server
├─ During Phase 3?
│  └─ Restore database backup
│      └─ Git revert commits
│          └─ Restart server
└─ During Phase 4-5?
   └─ Critical issue?
      ├─ Yes: Full rollback
      │   └─ Restore DB + revert code
      └─ No: Fix forward
          └─ Patch issue
              └─ Continue deployment
```

## Success Metrics

### Quantitative
- **Lines removed**: >500
- **Test coverage**: >90%
- **Token verification**: <500ms
- **Cache hit rate**: >90%
- **Memory stable**: <100MB

### Qualitative
- **Simpler architecture**: Clear separation of concerns
- **Better security**: Specialized providers handle auth
- **Less maintenance**: No auth code to maintain
- **User flexibility**: Choice of providers
- **Standards compliant**: Pure Micropub server

## Risk Matrix

| Risk | Probability | Impact | Mitigation |
|------|------------|---------|------------|
| Breaking existing tokens | Certain | Medium | Clear communication, migration guide |
| External service down | Low | High | Token caching, timeout handling |
| User confusion | Medium | Low | Comprehensive documentation |
| Performance degradation | Low | Medium | Caching layer, monitoring |
| Security vulnerability | Low | High | Use established providers |

---

**Document Version**: 1.0
**Created**: 2025-11-24
**Author**: StarPunk Architecture Team
**Status**: Ready for Implementation