Implements tag/category system backend following microformats2 p-category specification. Database changes: - Migration 008: Add tags and note_tags tables - Normalized tag storage (case-insensitive lookup, display name preserved) - Indexes for performance New module: - starpunk/tags.py: Tag management functions - normalize_tag: Normalize tag strings - get_or_create_tag: Get or create tag records - add_tags_to_note: Associate tags with notes (replaces existing) - get_note_tags: Retrieve note tags (alphabetically ordered) - get_tag_by_name: Lookup tag by normalized name - get_notes_by_tag: Get all notes with specific tag - parse_tag_input: Parse comma-separated tag input Model updates: - Note.tags property (lazy-loaded, prefer pre-loading in routes) - Note.to_dict() add include_tags parameter CRUD updates: - create_note() accepts tags parameter - update_note() accepts tags parameter (None = no change, [] = remove all) Micropub integration: - Pass tags to create_note() (tags already extracted by extract_tags()) - Return tags in q=source response Per design doc: docs/design/v1.3.0/microformats-tags-design.md Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
4.0 KiB
IndieAuth Authentication Fix - Quick Summary
Status: Solution Identified, Ready for Implementation Priority: CRITICAL Estimated Fix Time: 1-2 hours Confidence: 95%
The Problem
IndieLogin.com rejects authentication with:
This client_id is not registered (https://starpunk.thesatelliteoflove.com)
Root Cause
StarPunk is using an outdated client discovery approach. The IndieAuth specification evolved in 2022 from HTML microformats (h-app) to JSON metadata documents. IndieLogin.com now requires the modern JSON approach.
What we have: h-app microformats in HTML footer What IndieLogin expects: JSON metadata document at a well-known URL
The Solution
Implement OAuth Client ID Metadata Document endpoint.
Quick Implementation
- Add new route in your Flask app:
@app.route('/.well-known/oauth-authorization-server')
def oauth_client_metadata():
"""OAuth Client ID Metadata Document for IndieAuth discovery."""
metadata = {
'issuer': current_app.config['SITE_URL'],
'client_id': current_app.config['SITE_URL'],
'client_name': 'StarPunk',
'client_uri': current_app.config['SITE_URL'],
'redirect_uris': [
f"{current_app.config['SITE_URL']}/auth/callback"
],
'grant_types_supported': ['authorization_code'],
'response_types_supported': ['code'],
'code_challenge_methods_supported': ['S256'],
'token_endpoint_auth_methods_supported': ['none']
}
response = jsonify(metadata)
response.cache_control.max_age = 86400 # Cache 24 hours
response.cache_control.public = True
return response
- Add discovery link to
templates/base.htmlin<head>:
<link rel="indieauth-metadata" href="/.well-known/oauth-authorization-server">
- Keep existing h-app in footer for backward compatibility
Testing
# Test endpoint exists and returns JSON
curl -s https://starpunk.thesatelliteoflove.com/.well-known/oauth-authorization-server | jq .
# Verify client_id matches URL (should return: true)
curl -s https://starpunk.thesatelliteoflove.com/.well-known/oauth-authorization-server | \
jq '.client_id == "https://starpunk.thesatelliteoflove.com"'
Critical Requirements
client_idfield MUST exactly match the URL where document is served- Use
current_app.config['SITE_URL']- never hardcode URLs redirect_urismust be an array, not a string- Return
Content-Type: application/json(jsonify does this automatically)
Why This Will Work
- Specification Compliant: Implements current IndieAuth spec (2022+) exactly
- Matches Error Behavior: IndieLogin.com is checking for client registration/metadata
- Industry Standard: All modern IndieAuth clients use this approach
- Low Risk: Purely additive, no breaking changes
- Observable: Can verify endpoint before testing auth flow
What Changed in IndieAuth
| Version | Method | Status |
|---|---|---|
| 2020 | h-app microformats | Legacy (supported for compatibility) |
| 2022+ | JSON metadata document | Current standard |
IndieAuth spec now says servers "SHOULD" fetch metadata document and "SHOULD abort if fetching fails" - this explains the rejection.
Documentation
Full details in:
/home/phil/Projects/starpunk/docs/reports/indieauth-client-discovery-root-cause-analysis.md(comprehensive analysis)/home/phil/Projects/starpunk/docs/decisions/ADR-017-oauth-client-metadata-document.md(architecture decision)
Next Steps
- Implement the JSON metadata endpoint
- Add discovery link to HTML
- Deploy to production
- Test authentication flow with IndieLogin.com
- Verify successful login
- Update version to v0.6.2
- Update CHANGELOG
Rollback Plan
If this doesn't work (unlikely):
- Contact IndieLogin.com for clarification
- Consider alternative IndieAuth provider
- Implement self-hosted IndieAuth server
Analysis Date: 2025-11-19 Architect: StarPunk Architect Agent Reviewed: IndieAuth spec, OAuth spec, IndieLogin.com behavior