"""Entrypoint. Runs the Flask app over HTTPS (self-signed cert in dev). TLS is mandatory in this design: the passphrase and all plaintext stay in the browser, and the API only makes sense over an encrypted channel so browsers refuse to send crypto JS/code over an untrusted channel ( mixed content / HSTS-chaining attacks). Two modes: - certs/cert.pem + certs/key.pem present -> serve https://127.0.0.1:8443 - otherwise -> generate a self-signed certificate (only for local dev) and start on https://127.0.0.1:8443 If openssl is unavailable, falls back to plain HTTP on 5000 with a loud warning — dev convenience only, NOT suitable for production. """ import os import ssl import subprocess import sys from backend.app import app from backend import storage CERT = os.path.join("certs", "cert.pem") KEY = os.path.join("certs", "key.pem") def _ensure_self_signed_cert(): if os.path.exists(CERT) and os.path.exists(KEY): return os.makedirs("certs", exist_ok=True) subprocess.run( [ "openssl", "req", "-x509", "-newkey", "rsa:2048", "-keyout", KEY, "-out", CERT, "-days", "365", "-nodes", "-subj", "/CN=localhost", "-addext", "subjectAltName=DNS:localhost,IP:127.0.0.1", ], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, ) print("Self-signed dev certificate created in certs/.") def main(): storage.init_db() port = int(os.environ.get("PORT", "8443")) host = os.environ.get("HOST", "127.0.0.1") try: _ensure_self_signed_cert() context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) context.load_cert_chain(CERT, KEY) print(f"Serving on https://{host}:{port} (self-signed dev TLS).") app.run(host=host, port=port, ssl_context=context) except (FileNotFoundError, subprocess.CalledProcessError) as e: print(f"WARNING: no TLS available ({e}); falling back to HTTP.", file=sys.stderr) app.run(host=host, port=5000) if __name__ == "__main__": main()