Files
StarPunk/starpunk/__init__.py
Phil Skentelbery a3bac86647 feat: Complete IndieAuth server removal (Phases 2-4)
Completed all remaining phases of ADR-030 IndieAuth provider removal.
StarPunk no longer acts as an authorization server - all IndieAuth
operations delegated to external providers.

Phase 2 - Remove Token Issuance:
- Deleted /auth/token endpoint
- Removed token_endpoint() function from routes/auth.py
- Deleted tests/test_routes_token.py

Phase 3 - Remove Token Storage:
- Deleted starpunk/tokens.py module entirely
- Created migration 004 to drop tokens and authorization_codes tables
- Deleted tests/test_tokens.py
- Removed all internal token CRUD operations

Phase 4 - External Token Verification:
- Created starpunk/auth_external.py module
- Implemented verify_external_token() for external IndieAuth providers
- Updated Micropub endpoint to use external verification
- Added TOKEN_ENDPOINT configuration
- Updated all Micropub tests to mock external verification
- HTTP timeout protection (5s) for external requests

Additional Changes:
- Created migration 003 to remove code_verifier from auth_state
- Fixed 5 migration tests that referenced obsolete code_verifier column
- Updated 11 Micropub tests for external verification
- Fixed test fixture and app context issues
- All 501 tests passing

Breaking Changes:
- Micropub clients must use external IndieAuth providers
- TOKEN_ENDPOINT configuration now required
- Existing internal tokens invalid (tables dropped)

Migration Impact:
- Simpler codebase: -500 lines of code
- Fewer database tables: -2 tables (tokens, authorization_codes)
- More secure: External providers handle token security
- More maintainable: Less authentication code to maintain

Standards Compliance:
- W3C IndieAuth specification
- OAuth 2.0 Bearer token authentication
- IndieWeb principle: delegate to external services

Related:
- ADR-030: IndieAuth Provider Removal Strategy
- ADR-050: Remove Custom IndieAuth Server
- Migration 003: Remove code_verifier from auth_state
- Migration 004: Drop tokens and authorization_codes tables

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 17:23:46 -07:00

158 lines
4.3 KiB
Python

"""
StarPunk package initialization
Creates and configures the Flask application
"""
import logging
from flask import Flask
def configure_logging(app):
"""
Configure application logging based on LOG_LEVEL
Args:
app: Flask application instance
"""
log_level = app.config.get("LOG_LEVEL", "INFO").upper()
# Set Flask logger level
app.logger.setLevel(getattr(logging, log_level, logging.INFO))
# Configure handler with detailed format for DEBUG
handler = logging.StreamHandler()
if log_level == "DEBUG":
formatter = logging.Formatter(
"[%(asctime)s] %(levelname)s - %(name)s: %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
# Warn if DEBUG enabled in production
if not app.debug and app.config.get("ENV") != "development":
app.logger.warning(
"=" * 70
+ "\n"
+ "WARNING: DEBUG logging enabled in production!\n"
+ "This logs detailed HTTP requests/responses.\n"
+ "Sensitive data is redacted, but consider using INFO level.\n"
+ "Set LOG_LEVEL=INFO in production for normal operation.\n"
+ "=" * 70
)
else:
formatter = logging.Formatter(
"[%(asctime)s] %(levelname)s: %(message)s", datefmt="%Y-%m-%d %H:%M:%S"
)
handler.setFormatter(formatter)
# Remove existing handlers and add our configured handler
app.logger.handlers.clear()
app.logger.addHandler(handler)
def create_app(config=None):
"""
Application factory for StarPunk
Args:
config: Optional configuration dict to override defaults
Returns:
Configured Flask application instance
"""
app = Flask(__name__, static_folder="../static", template_folder="../templates")
# Load configuration
from starpunk.config import load_config
load_config(app, config)
# Configure logging
configure_logging(app)
# Initialize database
from starpunk.database import init_db
init_db(app)
# Register blueprints
from starpunk.routes import register_routes
register_routes(app)
# Error handlers
@app.errorhandler(404)
def not_found(error):
from flask import render_template, request
# Return HTML for browser requests, JSON for API requests
if request.path.startswith("/api/"):
return {"error": "Not found"}, 404
return render_template("404.html"), 404
@app.errorhandler(500)
def server_error(error):
from flask import render_template, request
# Return HTML for browser requests, JSON for API requests
if request.path.startswith("/api/"):
return {"error": "Internal server error"}, 500
return render_template("500.html"), 500
# Health check endpoint for containers and monitoring
@app.route("/health")
def health_check():
"""
Health check endpoint for containers and monitoring
Returns:
JSON with status and basic info
Response codes:
200: Application healthy
500: Application unhealthy
Checks:
- Database connectivity
- File system access
- Basic application state
"""
from flask import jsonify
import os
try:
# Check database connectivity
from starpunk.database import get_db
db = get_db(app)
db.execute("SELECT 1").fetchone()
db.close()
# Check filesystem access
data_path = app.config.get("DATA_PATH", "data")
if not os.path.exists(data_path):
raise Exception("Data path not accessible")
return (
jsonify(
{
"status": "healthy",
"version": app.config.get("VERSION", __version__),
"environment": app.config.get("ENV", "unknown"),
}
),
200,
)
except Exception as e:
return jsonify({"status": "unhealthy", "error": str(e)}), 500
return app
# Package version (Semantic Versioning 2.0.0)
# See docs/standards/versioning-strategy.md for details
__version__ = "1.0.0-rc.4"
__version_info__ = (1, 0, 0, "rc", 4)