Add h-app microformats markup to base.html to enable IndieLogin.com to verify StarPunk as a legitimate OAuth client. Without this markup, IndieLogin returns "client_id is not registered" error, blocking all production authentication. The h-app markup provides client identification per IndieAuth legacy standard, which is widely supported by authorization servers including IndieLogin.com. Changes: - Add h-app microformats div to base.html footer (hidden) - Update version to v0.6.1 (patch release per ADR-008) - Update CHANGELOG.md with v0.6.1 release notes - Add 6 comprehensive tests for h-app markup (all passing) - Create ADR-016 documenting client discovery decision - Create architecture analysis report - Create implementation report Tests: 456 total, 455 passing (99.78%) New tests: 6 for h-app microformats (100% passing) Fixes critical bug preventing production authentication. Related: Phase 3 Authentication implementation, ADR-016 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
19 KiB
IndieAuth Client Discovery Error - Architectural Analysis
Date: 2025-11-19 Reviewer: StarPunk Architect Agent Issue: Production IndieAuth failure - "client_id is not registered" Severity: CRITICAL - Blocks all production authentication Status: Analysis complete, solution identified
Executive Summary
The proposed fix is INCORRECT and will not resolve the issue.
The error "This client_id is not registered" occurs because IndieLogin.com cannot fetch and verify the client_id URL (https://starpunk.thesatelliteoflove.com). The proposed fix of adding rel="authorization_endpoint" and rel="token_endpoint" links to the HTML head is backwards - these links advertise where a user's identity provider endpoints are, not where a client application's endpoints are.
Root Cause: StarPunk is missing client identification metadata that IndieAuth servers need to verify the application.
Correct Solution: Implement one of three IndieAuth client discovery mechanisms (detailed below).
Understanding IndieAuth Client Discovery
The Authentication Flow
When a user tries to authenticate:
- User submits their identity URL (me) to StarPunk
- StarPunk redirects user to IndieLogin.com with:
client_id=https://starpunk.thesatelliteoflove.comredirect_uri=https://starpunk.thesatelliteoflove.com/auth/callbackstate=<csrf-token>
- IndieLogin.com fetches the client_id URL to verify the client
- IndieLogin.com authenticates the user
- IndieLogin.com redirects back to StarPunk
The error occurs at step 3 - IndieLogin.com cannot verify StarPunk as a legitimate client.
What IndieAuth Servers Look For
Per the IndieAuth specification (2025 edition), authorization servers must verify clients by fetching the client_id URL and looking for one of these (in order of preference):
1. Client ID Metadata Document (Current Standard - 2022+)
A JSON document at /.well-known/oauth-authorization-server or linked via rel="indieauth-metadata":
{
"issuer": "https://starpunk.thesatelliteoflove.com",
"client_id": "https://starpunk.thesatelliteoflove.com",
"client_name": "StarPunk",
"client_uri": "https://starpunk.thesatelliteoflove.com",
"logo_uri": "https://starpunk.thesatelliteoflove.com/static/logo.png",
"redirect_uris": [
"https://starpunk.thesatelliteoflove.com/auth/callback"
]
}
2. h-app Microformats (Legacy - Pre-2022)
HTML microformats markup in the client_id page:
<div class="h-app">
<a href="https://starpunk.thesatelliteoflove.com" class="u-url p-name">StarPunk</a>
<img src="/static/logo.png" class="u-logo" alt="StarPunk">
<p class="p-summary">A minimal IndieWeb CMS for publishing notes</p>
</div>
3. Basic HTML (Minimal Fallback)
At minimum, the client_id URL must return a valid HTML page (some servers accept any 200 OK response).
Analysis of Proposed Fix
What Was Proposed
Add to templates/base.html:
<link rel="authorization_endpoint" href="https://indielogin.com/auth">
<link rel="token_endpoint" href="https://indielogin.com/token">
Why This Is Wrong
These rel values serve a completely different purpose:
- authorization_endpoint and token_endpoint advertise where a user's identity provider has its endpoints
- They would be used on a user's personal website (their
meURL), not on a client application - They tell IndieAuth clients "here's where to authenticate ME", not "here's information about THIS application"
Example of correct usage: If Alice's personal site is https://alice.example.com, HER website would include:
<link rel="authorization_endpoint" href="https://alice.example.com/auth">
<link rel="token_endpoint" href="https://alice.example.com/token">
This tells IndieAuth clients "to authenticate Alice, use these endpoints."
StarPunk is a client application, not an identity provider, so these links are inappropriate and won't solve the registration error.
Why It Appeared to Work (If It Did)
If adding these links appeared to resolve the issue, it's likely coincidental:
- The HTTP request to the client_id URL succeeded (returned 200 OK)
- IndieLogin.com accepted the basic HTML response
- The specific
relvalues were ignored
This would be a fragile solution that doesn't follow standards.
Correct Solutions
Recommendation: Solution 2 (h-app Microformats)
I recommend implementing h-app microformats for backward compatibility and simplicity.
Solution 1: Client ID Metadata Document (Most Standards-Compliant)
Complexity: Medium Standards: Current (2022+) Compatibility: Modern IndieAuth servers only
Implementation
- Create endpoint:
GET /.well-known/oauth-authorization-server - Return JSON metadata document
- Set
Content-Type: application/json
Code Location: starpunk/routes/public.py
@public_bp.route('/.well-known/oauth-authorization-server')
def client_metadata():
"""OAuth Client ID Metadata Document for IndieAuth"""
metadata = {
"issuer": current_app.config['SITE_URL'],
"client_id": current_app.config['SITE_URL'],
"client_name": current_app.config.get('SITE_NAME', 'StarPunk'),
"client_uri": current_app.config['SITE_URL'],
"redirect_uris": [
f"{current_app.config['SITE_URL']}/auth/callback"
]
}
return jsonify(metadata)
Pros:
- Current standard (2022+)
- Clean separation of concerns
- Machine-readable
- Easy to extend
Cons:
- Not supported by older IndieAuth servers
- Requires new route
- May not be supported by IndieLogin.com if it's running older code
Solution 2: h-app Microformats (Recommended)
Complexity: Low Standards: Legacy (pre-2022) but widely supported Compatibility: All IndieAuth servers
Implementation
Add to templates/base.html in the <body> (or create a dedicated footer/header):
<div class="h-app" style="display: none;">
<a href="{{ config.SITE_URL }}" class="u-url p-name">{{ config.SITE_NAME }}</a>
<p class="p-summary">A minimal IndieWeb CMS for publishing notes</p>
</div>
Minimal version (if we want to keep it even simpler):
<div class="h-app" hidden>
<a href="{{ config.SITE_URL }}" class="u-url p-name">StarPunk</a>
</div>
Where to add: In base.html, inside <body> tag, preferably in the footer area.
Pros:
- Widely supported (backward compatible)
- Simple to implement (3 lines of HTML)
- No new routes needed
- Likely what IndieLogin.com expects
- Can be hidden from users (display: none or hidden attribute)
Cons:
- Uses "legacy" standard (though still widely supported)
- Mixes presentation and authentication metadata
Solution 3: Hybrid Approach (Most Robust)
Implement both solutions for maximum compatibility:
- Add h-app microformats to base.html (for legacy support)
- Add /.well-known/oauth-authorization-server endpoint (for modern support)
Pros:
- Works with all IndieAuth servers
- Future-proof
- Standards-compliant
Cons:
- Slight duplication of information
- More implementation work
Testing the Fix
Verification Steps
-
Test client_id fetch:
curl -I https://starpunk.thesatelliteoflove.comShould return 200 OK
-
Verify h-app markup (if using Solution 2):
curl https://starpunk.thesatelliteoflove.com | grep h-appShould show the h-app div
-
Test with IndieAuth validator: Use https://indieauth.spec.indieweb.org/validator or a similar tool
-
Test actual auth flow:
- Navigate to /admin/login
- Enter your identity URL
- Verify IndieLogin.com accepts the client_id
- Complete authentication
Expected Results After Fix
- IndieLogin.com should no longer show "client_id is not registered"
- User should see authentication prompt for their identity
- Successful auth should redirect back to StarPunk
Architecture Decision Record
This issue reveals a gap in our Phase 3 implementation - we implemented IndieAuth authentication but not IndieAuth client identification.
Should We Create an ADR?
Yes - This is an architectural decision about how StarPunk identifies itself to authorization servers.
ADR Subject: Client identification mechanism for IndieAuth
Decision Points:
- Which client discovery mechanism to implement
- Whether to support legacy h-app or modern JSON metadata
- Where to place the metadata (route vs template)
Recommended ADR Outcome
Decision: Implement h-app microformats in base.html (Solution 2)
Rationale:
- Simplicity: Aligns with project philosophy ("minimal code")
- Compatibility: Works with all IndieAuth servers including older ones
- Pragmatic: IndieLogin.com likely expects h-app (it's older software)
- Low Risk: 3 lines of HTML vs new route with JSON endpoint
- V1 Scope: Minimal viable solution for single-user system
Future Considerations:
- V2 could add JSON metadata endpoint for standards compliance
- Hybrid approach if we encounter compatibility issues
Version Impact Analysis
Is This a Bug or Missing Feature?
Classification: Bug (Critical)
Reasoning:
- Phase 3/4 claimed to implement "IndieAuth authentication"
- Production authentication is completely broken
- Feature was tested only in DEV_MODE (bypasses IndieAuth)
- This is a missing requirement from the IndieAuth spec
Version Number Impact
Current Version: v0.6.0 (released 2025-11-19)
Recommended Version After Fix: v0.6.1
Rationale (per ADR-008 Versioning Strategy):
- Not v0.7.0: This is a bug fix, not a new feature
- Not v1.0.0: Not a breaking change to API or data format
- v0.6.1: Patch release for critical bug fix
Severity Level: CRITICAL
- Production authentication completely broken
- No workaround except switching to DEV_MODE (insecure)
- Affects all production deployments
Git Strategy
Branch Strategy (per ADR-009)
Recommended Approach: Hotfix branch
git checkout -b hotfix/indieauth-client-discovery
Rationale:
- Critical production bug
- Needs immediate fix
- Should be merged directly to main
- Should be tagged as v0.6.1
Not a Feature Branch because:
- This isn't new functionality
- It's fixing broken production behavior
- Hotfix process is appropriate
Commit Strategy
Single Commit vs Multiple Commits:
Recommend single atomic commit:
- Change is small (adding h-app markup)
- Logically cohesive
- Easy to cherry-pick or revert if needed
Commit Message Template:
Fix IndieAuth client discovery for production authentication
Add h-app microformats markup to base.html to enable IndieLogin.com
to verify StarPunk as a legitimate OAuth client. Without this markup,
IndieLogin returns "client_id is not registered" error, blocking all
production authentication.
The h-app markup provides client identification per IndieAuth legacy
standard, which is widely supported by authorization servers including
IndieLogin.com.
Fixes critical bug preventing production authentication.
Related: Phase 3 Authentication implementation
Documentation Updates Required
Files to Update
-
CHANGELOG.md:
- Add v0.6.1 section
- Document bug fix under "Fixed"
- Reference IndieAuth client discovery
-
docs/decisions/ADR-016-indieauth-client-discovery.md (NEW):
- Document decision to use h-app microformats
- Explain alternatives considered
- Document why this was missed in Phase 3
-
docs/design/phase-3-authentication.md (UPDATE):
- Add section on client discovery requirements
- Document h-app implementation
- Note this as errata/addition to original spec
-
docs/reports/indieauth-client-discovery-fix.md (NEW):
- Implementation report
- Testing results
- Deployment notes
Acceptance Criteria for Fix
The fix is complete when:
- h-app microformats added to base.html (or JSON endpoint implemented)
- StarPunk homepage returns 200 OK and contains client identification
- IndieLogin.com accepts client_id without "not registered" error
- Full authentication flow works in production
- Tests added to verify h-app markup presence
- ADR-016 created documenting decision
- CHANGELOG.md updated for v0.6.1
- Version bumped to v0.6.1 in starpunk/init.py
- Hotfix branch merged to main
- Release tagged as v0.6.1
- Production deployment tested and verified
Implementation Specification
Recommended Implementation (h-app microformats)
File: templates/base.html
Location: Add in <footer> section, before closing </footer> tag
Code:
<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>
Justification for Location:
- Footer is semantically appropriate for metadata
hiddenattribute hides from visual presentationaria-hidden="true"hides from screen readers- Still parseable by IndieAuth servers
- Doesn't affect page layout
CSS Not Required: The hidden attribute provides sufficient hiding.
Risk Assessment
Risks of Current State (No Fix)
- CRITICAL: Production authentication completely broken
- Users cannot access admin interface in production
- Forces use of DEV_MODE (security risk)
- Project cannot be deployed to production
Risks of Proposed Fix (h-app microformats)
- LOW: Minimal risk
- Small, localized change
- Widely supported standard
- Easy to revert if issues occur
- No database migrations
- No breaking changes
Risks of Alternative Fix (JSON metadata endpoint)
- MEDIUM: Moderate risk
- New route could have bugs
- May not be supported by IndieLogin.com
- More code to test
- Higher chance of unintended side effects
Performance Impact
h-app Microformats (Recommended)
Impact: Negligible
- Adds ~80 bytes to HTML response
- No additional HTTP requests
- No database queries
- No server-side processing
- Minimal parsing overhead for IndieAuth servers
Performance Score: No measurable impact
JSON Metadata Endpoint
Impact: Minimal
- One additional route
- Negligible JSON serialization overhead
- Only called during auth flow (infrequent)
- No database queries
Performance Score: Negligible impact
Security Considerations
Security Impact of h-app Microformats
Positive:
- Enables proper IndieAuth client verification
- Prevents client impersonation
Neutral:
- Exposes client metadata (already public via HTTP)
- No sensitive information disclosed
No Security Risks Identified
Information Disclosure
The h-app markup reveals:
- Site URL (already public)
- Site name (already public in page title)
Assessment: No additional information disclosure beyond what's already in public HTML.
Standards Compliance Checklist
IndieWeb Standards
- Implements IndieAuth client discovery (currently missing)
- Uses h-app microformats OR Client ID Metadata Document
- Client metadata accessible via HTTP GET
- Client_id URL returns 200 OK
Web Standards
- Valid HTML5 (hidden attribute is standard)
- Valid microformats2 (h-app, u-url, p-name)
- Accessible (aria-hidden for screen readers)
- SEO neutral (hidden content not indexed)
Testing Strategy
Unit Tests
File: tests/test_templates.py (new file or existing)
Test Cases:
- Test h-app markup present in base.html
- Test h-app contains correct URL
- Test h-app contains site name
- Test h-app is hidden from visual display
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
assert b'class="u-url p-name"' 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
Manual Testing:
- Deploy to production
- Attempt IndieAuth login
- Verify no "client_id not registered" error
- Complete authentication flow
- Access admin dashboard
Automated Testing:
- Use IndieAuth validator tool
- Verify microformats parsing
Deployment Considerations
Deployment Process
- Build: No build changes required
- Database: No migrations required
- Configuration: No config changes required
- Rollback: Simple (revert commit)
Rollout Strategy
Recommended: Direct deployment (low risk)
- Merge hotfix branch to main
- Tag as v0.6.1
- Deploy to production
- Verify authentication works
- Monitor for issues
No Gradual Rollout Needed:
- Change is low risk
- No breaking changes
- Easy to revert
Container Impact
Container Build:
- No Containerfile changes needed
- Rebuild image to include template update
- Same base image and dependencies
Container Tag: Update to v0.6.1
Lessons Learned
What Went Wrong
- Incomplete Specification: Phase 3 design didn't include client discovery requirements
- Testing Gap: Only tested with DEV_MODE (bypasses IndieAuth)
- Spec Understanding: Missed IndieAuth client identification requirement
- Documentation: IndieAuth spec has multiple versions (2020, 2022) with different requirements
Process Improvements
- Testing Requirements: Always test production authentication paths
- Spec Review: Review full IndieAuth specification, not just authentication flow
- Integration Testing: Test with actual IndieLogin.com, not just mocks
- Documentation: Cross-reference all IndieWeb specs (IndieAuth, Micropub, Webmention)
Future Prevention
- Create comprehensive IndieAuth compliance checklist
- Add integration tests with actual authorization servers
- Review all IndieWeb specs for hidden requirements
- Test in production-like environment (not just DEV_MODE)
Conclusion
Proposed Fix Assessment: ❌ INCORRECT
Correct Fix: Add h-app microformats to base.html
Severity: CRITICAL (blocks production authentication)
Recommended Action: Implement Solution 2 (h-app microformats) immediately
Version: Bump to v0.6.1 (patch release)
Branch Strategy: Use hotfix branch per ADR-009
Documentation: Create ADR-016, update CHANGELOG.md
Risk Level: LOW (simple, well-understood fix)
Timeline: Can be implemented in < 1 hour
Next Steps for Developer
- Create hotfix branch:
hotfix/indieauth-client-discovery - Add h-app microformats to
templates/base.html - Update version to v0.6.1 in
starpunk/__init__.py - Add tests for h-app markup presence
- Create ADR-016 documenting decision
- Update CHANGELOG.md with v0.6.1 entry
- Create implementation report
- Test authentication flow in production
- Commit with message template above
- Merge to main and tag v0.6.1
Analysis by: StarPunk Architect Agent Date: 2025-11-19 Document Version: 1.0 Status: Ready for implementation