# ADR-016: IndieAuth Client Discovery Mechanism

## Status

**Superseded by ADR-019** - IndieLogin.com does not use h-app microformats for client discovery. PKCE implementation is the correct solution.

## Context

StarPunk uses IndieLogin.com as a delegated IndieAuth provider for admin authentication. During the first production deployment to https://starpunk.thesatelliteoflove.com, authentication failed with the error:

```
Request Error
There was a problem with the parameters of this request.

This client_id is not registered (https://starpunk.thesatelliteoflove.com)
```

### Root Cause

The IndieAuth specification requires authorization servers to verify client applications by fetching the `client_id` URL and discovering client metadata. StarPunk's implementation was missing this client discovery mechanism entirely.

### Why This Was Missed

1. Phase 3 authentication design focused on the authentication flow but didn't address client identification
2. Testing used DEV_MODE which bypasses IndieAuth entirely
3. The IndieAuth spec has evolved over time (2020 → 2022 → current) with different discovery mechanisms
4. Client discovery is a prerequisite that wasn't explicitly called out in our design

### IndieAuth Client Discovery Standards

The IndieAuth specification (as of 2025) supports three discovery mechanisms:

#### 1. OAuth Client ID Metadata Document (Current - 2022+)

A JSON document at `/.well-known/oauth-authorization-server` or linked via `rel="indieauth-metadata"`:

```json
{
  "issuer": "https://example.com",
  "client_id": "https://example.com",
  "client_name": "App Name",
  "client_uri": "https://example.com",
  "redirect_uris": ["https://example.com/callback"]
}
```

**Pros**: Current standard, machine-readable, clean separation
**Cons**: Newer standard, may not be supported by older servers

#### 2. h-app Microformats (Legacy - Pre-2022)

HTML microformats markup in the page:

```html
<div class="h-app">
  <a href="https://example.com" class="u-url p-name">App Name</a>
</div>
```

**Pros**: Widely supported, backward compatible, simple
**Cons**: Uses "legacy" standard, mixes presentation and metadata

#### 3. Basic HTTP 200 (Minimal)

Some servers accept any valid HTTP 200 response as sufficient client verification.

**Pros**: Simplest possible
**Cons**: Provides no metadata, not standards-compliant

## Decision

**Implement h-app microformats in base.html template**

We will add microformats2 h-app markup to the site footer for IndieAuth client discovery.

## Rationale

### Why h-app Microformats?

1. **Simplicity**: 3 lines of HTML vs new route with JSON endpoint
   - Aligns with project philosophy: "Every line of code must justify its existence"
   - Minimal implementation complexity

2. **Compatibility**: Works with all IndieAuth servers
   - Supports legacy servers (IndieLogin.com likely runs older code)
   - Backward compatible with 2020-era IndieAuth spec
   - Forward compatible (current spec still supports h-app)

3. **Pragmatic**: Addresses immediate production need
   - V1 requirement is "working IndieAuth authentication"
   - h-app provides necessary client verification
   - Low risk, high confidence in success

4. **Low Maintenance**: No new routes or endpoints
   - Template-based, no server-side logic
   - No additional testing surface
   - Can't break existing functionality

5. **Standards-Compliant**: Still part of IndieAuth spec
   - Officially supported for backward compatibility
   - Used by many IndieAuth clients and servers
   - Well-documented and understood

### Why Not OAuth Client ID Metadata Document?

While this is the "current" standard, we rejected it for V1 because:

1. **Complexity**: Requires new route, JSON serialization, additional tests
2. **Uncertainty**: Unknown if IndieLogin.com supports it (software may be older)
3. **Risk**: Higher chance of bugs in new endpoint
4. **V1 Scope**: Violates minimal viable product philosophy

This could be added in V2 for modern IndieAuth server support.

### Why Not Basic HTTP 200?

This provides no client metadata and isn't standards-compliant. While some servers may accept it, it doesn't fulfill the spirit of client verification and could fail with stricter authorization servers.

## Implementation

### Location

`templates/base.html` in the `<footer>` section

### Code

```html
<footer>
  <p>StarPunk v{{ config.get('VERSION', '0.6.1') }}</p>

  <!-- IndieAuth client discovery (h-app microformats) -->
  <div class="h-app" hidden aria-hidden="true">
    <a href="{{ config.SITE_URL }}" class="u-url p-name">{{ config.get('SITE_NAME', 'StarPunk') }}</a>
  </div>
</footer>
```

### Attributes Explained

- `class="h-app"`: Microformats2 root class for application metadata
- `hidden`: HTML5 attribute to hide from visual display
- `aria-hidden="true"`: Hide from screen readers (not content, just metadata)
- `class="u-url p-name"`: Microformats2 properties for URL and name
- Uses Jinja2 config variables for dynamic values

## Consequences

### Positive

1. ✅ **Production Authentication Works**: Fixes critical blocker
2. ✅ **Standards Compliant**: Follows IndieAuth legacy standard
3. ✅ **Widely Compatible**: Works with old and new IndieAuth servers
4. ✅ **Simple to Maintain**: No server-side logic, just HTML
5. ✅ **Easy to Test**: Simple HTML assertion in tests
6. ✅ **Low Risk**: Minimal change, hard to break
7. ✅ **No Breaking Changes**: Purely additive

### Negative

1. ⚠️ **Uses Legacy Standard**: h-app is pre-2022 spec
   - Mitigation: Still officially supported, widely used
2. ⚠️ **Mixes Concerns**: Metadata in presentation template
   - Mitigation: Acceptable for V1, can refactor for V2
3. ⚠️ **Not Future-Proof**: May need modern JSON endpoint eventually
   - Mitigation: Can add alongside h-app in future (hybrid approach)

### Neutral

1. **Information Disclosure**: Reveals site URL and name
   - Already public in HTML title and page content
   - No additional sensitive information exposed

2. **Performance**: Adds ~80 bytes to HTML
   - Negligible impact on page load
   - No server-side processing overhead

## Alternatives Considered

### Alternative 1: OAuth Client ID Metadata Document

**Implementation**: New route `GET /.well-known/oauth-authorization-server` returning JSON

**Rejected Because**:
- Higher complexity (new route, tests, JSON serialization)
- Unknown IndieLogin.com compatibility
- Violates V1 minimal scope
- Can add later if needed

### Alternative 2: Hybrid Approach (Both h-app and JSON)

**Implementation**: Both h-app markup AND JSON endpoint

**Rejected Because**:
- Unnecessary complexity for V1
- Duplication of data
- h-app alone is sufficient for current need
- Can upgrade to hybrid in V2 if required

### Alternative 3: Do Nothing (Rely on DEV_MODE)

**Rejected Because**:
- Production authentication completely broken
- Forces insecure development mode in production
- Violates security best practices
- Makes project undeployable

## Testing Strategy

### Unit Tests

Add to `tests/test_templates.py`:

```python
def test_h_app_microformats_present(client):
    """Verify h-app client discovery markup exists"""
    response = client.get('/')
    assert response.status_code == 200
    assert b'class="h-app"' in response.data

def test_h_app_contains_site_url(client, app):
    """Verify h-app contains correct site URL"""
    response = client.get('/')
    assert app.config['SITE_URL'].encode() in response.data
```

### Integration Tests

1. Use microformats parser to verify h-app structure
2. Test with actual IndieLogin.com authentication
3. Verify no "client_id not registered" error

### Manual Testing

1. Deploy to production
2. Attempt admin login via IndieAuth
3. Verify authentication flow completes successfully

## Migration Path

No migration required:
- No database changes
- No configuration changes
- No breaking API changes
- Purely additive HTML change

Existing authenticated sessions remain valid.

## Future Considerations

### V2 Potential Enhancements

1. **Add JSON Metadata Endpoint**: Implement modern OAuth Client ID Metadata Document
2. **Hybrid Support**: Maintain h-app for compatibility while adding JSON
3. **Extended Metadata**: Add logo_uri, more detailed application info
4. **Dynamic Client Registration**: Support programmatic client registration

### Upgrade Path

When implementing V2 enhancements:

1. Keep h-app markup for backward compatibility
2. Add `/.well-known/oauth-authorization-server` endpoint
3. Add `<link rel="indieauth-metadata">` to HTML head
4. Document support for both legacy and modern discovery

This allows gradual migration without breaking existing integrations.

## Compliance

### IndieWeb Standards

- ✅ IndieAuth specification (legacy client discovery)
- ✅ Microformats2 h-app specification
- ✅ HTML5 standard (hidden attribute)
- ✅ ARIA accessibility standard

### Project Standards

- ✅ ADR-001: Minimal dependencies (no new packages)
- ✅ "Every line of code must justify its existence"
- ✅ Standards-first approach
- ✅ Progressive enhancement (server-side only)

## References

- [IndieAuth Specification](https://www.w3.org/TR/indieauth/)
- [Microformats2 h-app](https://microformats.org/wiki/h-app)
- [IndieLogin.com](https://indielogin.com/)
- [OAuth 2.0 Client ID Metadata Document](https://www.rfc-editor.org/rfc/rfc7591.html)

## Related Documents

- Phase 3: Authentication Design (`docs/design/phase-3-authentication.md`)
- ADR-005: IndieLogin Authentication (`docs/decisions/ADR-005-indielogin-authentication.md`)
- IndieAuth Client Discovery Analysis (`docs/reports/indieauth-client-discovery-analysis.md`)

## Version Impact

**Bug Classification**: Critical
**Version Increment**: v0.6.0 → v0.6.1 (patch release)
**Reason**: Critical bug fix for broken production authentication

---

**Decided**: 2025-11-19
**Author**: StarPunk Architect Agent
**Supersedes**: None
**Superseded By**: None (current)
