Add Flask web UI, Docker Compose, core engine + tests

- physcom core: CLI, 5-pass pipeline, SQLite repo, 37 tests
- physcom_web: Flask app with HTMX for entity/domain/pipeline/results CRUD
- Docker Compose: web + cli services sharing a named volume for the DB
- Clean up local settings to use wildcard permissions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Simonson, Andrew
2026-02-18 13:59:53 -06:00
parent 6e0f82835a
commit 8118a62242
54 changed files with 3505 additions and 1 deletions

60
src/physcom_web/app.py Normal file
View File

@@ -0,0 +1,60 @@
"""Flask application factory and DB setup."""
from __future__ import annotations
import os
from pathlib import Path
from flask import Flask, g
from physcom.db.schema import init_db
from physcom.db.repository import Repository
DEFAULT_DB = Path("data/physcom.db")
def get_repo() -> Repository:
"""Return a Repository scoped to the current request."""
if "repo" not in g:
db_path = Path(os.environ.get("PHYSCOM_DB", str(DEFAULT_DB)))
conn = init_db(db_path)
g.repo = Repository(conn)
return g.repo
def close_db(exc: BaseException | None = None) -> None:
repo: Repository | None = g.pop("repo", None)
if repo is not None:
repo.conn.close()
def create_app() -> Flask:
app = Flask(__name__)
app.secret_key = os.environ.get("FLASK_SECRET_KEY", "physcom-dev-key")
app.teardown_appcontext(close_db)
# Register blueprints
from physcom_web.routes.entities import bp as entities_bp
from physcom_web.routes.domains import bp as domains_bp
from physcom_web.routes.pipeline import bp as pipeline_bp
from physcom_web.routes.results import bp as results_bp
app.register_blueprint(entities_bp)
app.register_blueprint(domains_bp)
app.register_blueprint(pipeline_bp)
app.register_blueprint(results_bp)
@app.route("/")
def index():
from flask import redirect, url_for
return redirect(url_for("entities.entity_list"))
return app
def run() -> None:
"""Entry point for `physcom-web` script."""
app = create_app()
app.run(debug=True, port=int(os.environ.get("PORT", "5000")))