app.bettersight.io/backend/app.py

47 lines
1.5 KiB
Python

import os
import logging
from flask import Flask
from dotenv import load_dotenv
load_dotenv()
logging.basicConfig(level=logging.INFO)
# Sentry — guarded on SENTRY_DSN being set, so earlier phases and local
# dev never silently depend on it (CLAUDE.md §22 Observability). Must
# be initialised before the Flask app is constructed so FlaskIntegration
# can instrument it.
SENTRY_DSN = os.getenv('SENTRY_DSN')
if SENTRY_DSN:
import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
from sentry_sdk.integrations.rq import RqIntegration
def _scrub_sensitive_data(event, hint):
"""Removes headers (which may carry X-API-Key/session tokens) from Sentry events. PII must never reach Sentry."""
if 'request' in event:
event['request'].pop('headers', None)
return event
sentry_sdk.init(
dsn=SENTRY_DSN,
integrations=[FlaskIntegration(), RqIntegration()],
traces_sample_rate=0.1,
environment=os.getenv('FLASK_ENV', 'production'),
send_default_pii=False,
before_send=_scrub_sensitive_data,
)
from extensions import limiter, cors # noqa: E402
from api import api_bp # noqa: E402
# Entry point only — imports and wires everything together. Business
# logic lives in services/, data access in repositories/, routes in
# api.py. Nothing else belongs in this file per CLAUDE.md §5/§18.
app = Flask(__name__)
limiter.init_app(app)
cors.init_app(app)
app.register_blueprint(api_bp)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=False)