Fake LLM, local Supabase runtime, and tunnel auth for shareable local demos

pwliwanow makes Mike runnable end-to-end with no cloud accounts and adds a "shareable demo" mode for putting the local stack behind a Cloudflare Tunnel. The local-runtime pieces are clean env-flag opt-ins; the tunnel auth has a deployment gotcha worth reading before you pull it.

infrastructuresecurity

Three pieces ship in one commit (+3536/-445, 67 files).

The local runtime puts a vendored Supabase Docker Compose setup under docker/supabase/ covering Auth, Postgres, Storage, and supporting services. Supabase Storage's built-in S3 endpoint handles blobs, so no MinIO container is needed. backend/.env.local.example configures R2_ENDPOINT_URL to point at http://localhost:8000/storage/v1/s3 with R2_FORCE_PATH_STYLE=true. There's a filesystem fallback in storage.ts (MIKE_LOCAL_STORAGE_DIR) that kicks in when R2_ENDPOINT_URL points at localhost - this exists because Supabase Storage's file backend can fail on macOS/Docker filesystems that lack extended attributes.

The fake LLM (backend/src/lib/llm/fake.ts, MIKE_FAKE_LLM=1) plugs into both streamChatWithTools and completeText. It recognizes the tabular-review and prompt-generation system prompts and returns deterministic JSON in the right shapes so the UI exercises fully without an Anthropic or Gemini key. Seven sample documents are added under samples/ so the empty-state demo has actual content to show.

The tunnel auth adds requireExposureAuth middleware that checks a BACKEND_TUNNEL_AUTH_TOKEN header or HTTP Basic credentials. It's mounted globally - before all routes including /health. The frontend injects X-Tunnel-Auth from an env var into every API call. CORS is widened to a FRONTEND_URLS comma list.

One thing to verify before deploying the tunnel auth: the frontend gate lives in frontend/src/proxy.ts, but Next.js only auto-loads middleware.{ts,js}. A file named proxy.ts is dead code unless something imports it. If the Basic Auth gate on the frontend side isn't wired up, the Cloudflare Tunnel protection is backend-only.

Also: serverApiKeyAvailability() now reports whether server-side Gemini/Claude keys are configured, and the frontend uses those flags to offer those models to signed-in users. On a single-user demo this is fine. On any multi-tenant fork it means authenticated users can run calls on the operator's keys.

The follow-up commit is a pure README restructure with no code changes.

So what Worth pulling the local-runtime parts (fake LLM, vendored Supabase compose, filesystem storage fallback) individually - they're clean opt-ins behind env flags with no effect on production behavior. Be more careful with the tunnel auth: verify the `proxy.ts` Next.js middleware is actually loaded before relying on the frontend gate, and audit the `serverApiKeyAvailability` change if you run any multi-tenant setup.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

2 commits from pwliwanow/mike, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
5d0e74de Add local runtime and tunnel auth support Pawel Iwanow 2026-05-04 ↗ GitHub
ca2d1ea2 Document local development setup Pawel Iwanow 2026-05-04 ↗ GitHub

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-130.md from inside the repo you want the changes in.

⬇ Download capture-thread-130.md