# mimir-inbox — UI front end for large-document / book ingestion into the Muninn # KB, over the muninn-gate API (browser -> mimir-inbox -> staging -> path-addressed # POST /jobs to the gate; bytes never reach the gate). No Dockerfile upstream # (vh/mimir-inbox); this is infra-ops's, modeled on the muninn-gate one. # # All 7 RUNTIME deps are public PyPI — NO private index, NO BuildKit secret # (unlike muninn-gate, which needed muninn-dispatch at runtime). # # docker build -t mimir-inbox:0.0.1 . FROM python:3.11-slim RUN pip install --no-cache-dir uv==0.11.* WORKDIR /app COPY pyproject.toml uv.lock README.md ./ COPY src ./src # Install project + deps from the lockfile, EXCLUDING the dev group. --no-dev is # load-bearing, not just leaner: the dev group carries muninn-dispatch via a path # source ("../Worldtree/packages/muninn-dispatch") that is absent in the image, # AND INV-MI-7 asserts runtime code never imports muninn_dispatch. Runtime deps # resolve entirely from PyPI. RUN uv sync --no-dev --frozen --no-cache # SINGLE-STAGE BY DESIGN — DO NOT convert to multi-stage that copies only .venv. # `uv sync` installs the project EDITABLE-linked back to /app/src/mimir_inbox (not # copied into site-packages), so mimir_inbox.__file__ — and the 16 templates + 442 # static assets (vendored design CSS + htmx) it serves from — resolve out of src/. # Dropping src/ in a final layer would kill the app at import; if it somehow got # past import it would 404 every asset. src/ MUST remain alongside .venv. # (mimir-dev preflight, 2026-08-01: `uv sync --no-dev --frozen` boots green with # the path source absent; the alternative safe shape is `uv build --wheel` + # install the wheel, which copies assets into site-packages.) ENV PATH="/app/.venv/bin:$PATH" # The launcher (compose) owns --host/--port; no CMD here. Runs as uid 1000 (set # in compose) — the sole writer to the staging root; /app is read-only to it.