Implements the parallel.md workstreams (Agents A-E) toward REFACTOR_GOAL.md. Phase 1 — app factory + blueprints + /api/v1: - app.py -> create_app() factory (no module-level app); entrypoints updated - routes/ (auth, pages, settings, admin, assets) + blueprints/api.py at /api/v1 - config.py / extensions.py / security.py extracted; services/ layer added - endpoint names preserved so template url_for() calls keep resolving (static check: all 27 template url_for endpoints are defined routes) Phase 2 — one pluggable filter system: - filter_pipeline/registry.py: @register_stage / @register_plugin + discover_modules - engine._init_stages() instantiates registered stages (no hardcoded dict); process_batch is AI-aware: only short-circuits to the AI-disabled path when a filterset's stages declare requires_ai, so offline filtersets run with AI off - BaseFilterPlugin gets a consumer (stages/plugins.py); Keyword/Quality re-enabled via filter_config.json plugins config - comment tree modes ported to stages/comment_filter.py + shared rules.py; wired into /api/v1/posts/<uuid> and /api/v1/comments/<uuid> via FilterEngine.filter_comments() (fails open) - offline quality_filter filterset exercises plugins+ranker without AI - legacy filter_lib / comment_lib / html_generation_lib / generate_html / active_html path deleted Phase 3 prep — pluggable fetchers + Postgres models: - Post / Comment SQLAlchemy models added to models.py - migrate_content_to_db.py backfill (idempotent by uuid, batched, --dry-run) - platforms/ fetcher registry (extension point) - live reads/writes still go through PostService (disk JSON); cutover deferred Phase 6 — test harness: - pytest.ini + tests/ (conftest with in-memory SQLite fixture, no Postgres; stubbed polling/filter singletons) - test_app_factory.py (route registration, no module-level app), test_api_contracts.py (posts/post_detail/comments/filters shape with monkeypatched post_service + get_filter_engine), test_filter_pipeline.py + test_plugin_contract.py (Flask-free; validated locally 12/12 incl. drop-in stage/plugin discovered with zero core edits) Other: .gitignore added (__pycache__, data/, secrets); pytest in requirements. Verification: py_compile clean across the project; the Flask-free filter-pipeline and plugin-contract tests pass locally. App-factory / API-contract tests need deps+docker to run; runtime flask routes / Auth0-repeated-create_app also gated on docker. Co-Authored-By: Claude <noreply@anthropic.com>
56 lines
1.4 KiB
Docker
56 lines
1.4 KiB
Docker
FROM python:3.12-slim
|
|
|
|
LABEL maintainer="BalanceBoard"
|
|
LABEL description="BalanceBoard - Content aggregation platform with ethical design"
|
|
|
|
# Install system dependencies
|
|
RUN apt-get update && apt-get install -y \
|
|
postgresql-client \
|
|
libpq-dev \
|
|
gcc \
|
|
curl \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Create non-root user for security
|
|
RUN useradd -m -u 1000 appuser && \
|
|
mkdir -p /app && \
|
|
chown -R appuser:appuser /app
|
|
|
|
# Set working directory
|
|
WORKDIR /app
|
|
|
|
# Copy requirements first for better caching
|
|
COPY --chown=appuser:appuser requirements.txt .
|
|
|
|
# Install Python dependencies
|
|
RUN pip install --no-cache-dir -r requirements.txt
|
|
|
|
# Copy application code
|
|
COPY --chown=appuser:appuser . .
|
|
|
|
# Create necessary directories with proper permissions
|
|
RUN mkdir -p \
|
|
/app/data/posts \
|
|
/app/data/comments \
|
|
/app/data/moderation \
|
|
/app/static/avatars \
|
|
/app/backups \
|
|
&& chown -R appuser:appuser /app
|
|
|
|
# Switch to non-root user
|
|
USER appuser
|
|
|
|
# Expose Flask port
|
|
EXPOSE 5021
|
|
|
|
# Health check
|
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
|
|
CMD curl -f http://localhost:5021/ || exit 1
|
|
|
|
# Set Flask app environment variable
|
|
ENV FLASK_APP=app:create_app
|
|
|
|
# Run the application directly with Flask
|
|
# Note: start_server.py has venv checks that don't apply in Docker
|
|
CMD ["python", "-m", "flask", "--app", "app:create_app", "run", "--host=0.0.0.0", "--port=5021"]
|