# ADR-031: IndieAuth Endpoint Discovery Implementation Details

## Status
Accepted

## Context

The developer raised critical implementation questions about ADR-030-CORRECTED regarding IndieAuth endpoint discovery. The primary blocker was the "chicken-and-egg" problem: when receiving a token, how do we know which endpoint to verify it with?

## Decision

For StarPunk V1 (single-user CMS), we will:

1. **ALWAYS use ADMIN_ME for endpoint discovery** when verifying tokens
2. **Use simple caching structure** optimized for single-user
3. **Add BeautifulSoup4** as a dependency for robust HTML parsing
4. **Fail closed** on security errors with cache grace period
5. **Allow HTTP in debug mode** for local development

### Core Implementation

```python
def verify_external_token(token: str) -> Optional[Dict[str, Any]]:
    """Verify token - single-user V1 implementation"""
    admin_me = current_app.config.get("ADMIN_ME")

    # Always discover from ADMIN_ME (single-user assumption)
    endpoints = discover_endpoints(admin_me)
    token_endpoint = endpoints['token_endpoint']

    # Verify and validate token belongs to admin
    token_info = verify_with_endpoint(token_endpoint, token)

    if normalize_url(token_info['me']) != normalize_url(admin_me):
        raise TokenVerificationError("Token not for admin user")

    return token_info
```

## Rationale

### Why ADMIN_ME Discovery?

StarPunk V1 is explicitly single-user. Only the admin can post, so any valid token MUST belong to ADMIN_ME. This eliminates the chicken-and-egg problem entirely.

### Why Simple Cache?

With only one user, we don't need complex profile->endpoints mapping. A simple cache suffices:

```python
class EndpointCache:
    def __init__(self):
        self.endpoints = None  # Single user's endpoints
        self.endpoints_expire = 0
        self.token_cache = {}  # token_hash -> (info, expiry)
```

### Why BeautifulSoup4?

- Industry standard for HTML parsing
- More robust than regex or built-in parsers
- Pure Python implementation available
- Worth the dependency for correctness

### Why Fail Closed?

Security principle: when in doubt, deny access. We use cached endpoints as a grace period during network failures, but ultimately deny access if we cannot verify.

## Consequences

### Positive
- Eliminates complexity of multi-user endpoint discovery
- Simple, clear implementation path
- Secure by default
- Easy to test and verify

### Negative
- Will need refactoring for V2 multi-user support
- Adds BeautifulSoup4 dependency
- First request after cache expiry has ~850ms latency

### Migration Impact
- Breaking change: TOKEN_ENDPOINT config removed
- Users must update configuration
- Clear deprecation warnings provided

## Alternatives Considered

### Alternative 1: Require 'me' Parameter
**Rejected**: Would violate Micropub specification

### Alternative 2: Try Multiple Endpoints
**Rejected**: Complex, slow, and unnecessary for single-user

### Alternative 3: Pre-warm Cache
**Rejected**: Adds complexity for minimal benefit

## Implementation Timeline

- **v1.0.0-rc.5**: Full implementation with migration guide
- Remove TOKEN_ENDPOINT configuration
- Add endpoint discovery from ADMIN_ME
- Document single-user assumption

## Testing Strategy

- Unit tests with mocked HTTP responses
- Edge case coverage (malformed HTML, network errors)
- One integration test with real IndieAuth.com
- Skip real provider tests in CI (manual testing only)

## References

- W3C IndieAuth Specification Section 4.2 (Discovery)
- ADR-043-CORRECTED (Original design)
- Developer analysis report (2025-11-24)