Public-flip audit: env-driven paths, scrub audit-ticket prefixes, terser README

Lucy bind paths + LAN host pins replaced with env defaults. Repository URLs
→ git.sulkta.com. Audit-changelog scaffolding stripped from inline comments
(technical reasoning preserved). README sheds marketing scaffolding. AI-speak
in load-bearing prompts/SOULs left alone — that IS the product.
This commit is contained in:
Cobb Hayes 2026-05-27 11:42:56 -07:00
parent 84b16bc0ad
commit 592b4f1161
14 changed files with 201 additions and 270 deletions

130
README.md
View file

@ -1,100 +1,60 @@
# cauldron
Mealie-backed AI meal planner + shopping list for the family. LAN-only,
internal tool. Mealie at `recipes.sulkta.com` is the source of truth for
recipes / meal plans / shopping lists; cauldron is the AI layer + Abby's
branded UI on top.
Mealie-backed meal planner + shopping-list aggregator. Wraps a Mealie
instance with: an ingredient sterilizer (free-form quantities → structured
parses), a weekly meal-plan generator, and a household shopping list that
collapses cross-recipe duplicates.
## Status
## Stack
**v0.1 — backend bones (current).** Ingredient sterilizer endpoint working.
No UI yet; bearer-auth API only. Frontend + Authentik OIDC arrives in v0.2.
Native Kotlin Android in v0.5.
- Flask + gunicorn, Python 3.12
- Authentik (or any OIDC provider) for sessions
- MariaDB for per-user prefs + Fernet-encrypted Mealie tokens
- [clawdforge](https://github.com/Sulkta-Coop/clawdforge) for the AI layer
## Surface (v0.1)
Mealie remains the source of truth for recipes / plans / shopping lists.
Cauldron stores per-user prefs + cached metadata only.
## Run
```bash
cp .env.example .env # fill in secrets
docker compose up -d --build
curl http://localhost:7790/healthz
```
`CAULDRON_ENV_FILE=/path/to/secrets.env docker compose up -d` if your env
file lives outside the repo.
## Endpoints
```
GET /healthz liveness + clawdforge upstream
GET /api/recipes list Mealie recipes (paginated)
POST /api/sterilize/preview/<slug> dry-run AI parse, return proposals
POST /api/sterilize/apply/<slug> write parses back to Mealie
GET /login /auth/callback OIDC flow
GET /me account + integration status
GET /plan /list household plan + shopping list
GET /api/recipes (admin bearer) proxy Mealie list
POST /api/sterilize/preview/<slug> (admin bearer) dry-run parser
POST /api/sterilize/apply/<slug> (admin bearer) write parses back
```
All routes except `/healthz` require `Authorization: Bearer <ADMIN_BEARER>`.
Admin-bearer endpoints expect `Authorization: Bearer $ADMIN_BEARER`.
## Architecture
```
Abby's phone (later: Kotlin app)
cauldron (Flask, port 7790, LAN-only)
├─ Mealie API client ─── recipes.sulkta.com (source of truth)
├─ clawdforge client ─── 192.168.0.5:8800 (claude -p runner)
└─ Authentik OIDC (v0.2)
```
cauldron does NOT hold its own database in v0.1 — all state lives in Mealie.
A small Postgres/MariaDB schema lands in v0.2 for Abby-specific prefs +
chat history.
## Ingredient sterilizer
Mealie's CRF parser is mediocre. Cobb's hand-typed recipes have lots of
free-form quantity strings ("about 2 cups cooked white rice", "1 small
handful kale", "a pinch of salt") that don't aggregate cleanly into a
shopping list.
The sterilizer batches all ingredients of one recipe into a single Sonnet
call (via clawdforge), gets back parallel structured parses, then on apply
links each parse to existing Mealie food/unit records (creating any missing
by name) and PUTs the recipe back.
Preview is non-destructive — review proposals before apply.
```bash
# Dry-run preview
curl -sS -X POST -H "Authorization: Bearer $ADMIN_BEARER" \
http://192.168.0.5:7790/api/sterilize/preview/spaghetti-bolognese | jq .
# Apply (creates missing foods/units by default)
curl -sS -X POST -H "Authorization: Bearer $ADMIN_BEARER" \
http://192.168.0.5:7790/api/sterilize/apply/spaghetti-bolognese | jq .
```
## Deploy
1. `ssh lucy`
2. `cd /mnt/user/appdata && git clone <gitea-url> cauldron && cd cauldron/build`
(or wherever the deploy convention lands)
3. Drop `.env` at `/mnt/cache/appdata/secrets/cauldron.env` (chmod 600 root:root)
- `CLAWDFORGE_TOKEN` is already populated by the bootstrap (see `memory/2026-04-28.md`)
- `MEALIE_API_TOKEN` — mint at `recipes.sulkta.com` → user → API tokens
- `ADMIN_BEARER` — pick 32 bytes of entropy
- `SECRET_KEY` — 32 bytes for Flask sessions
4. `docker compose up -d --build`
5. Smoke: `curl http://192.168.0.5:7790/healthz`
## Roadmap
- v0.1 ✓ — sterilizer backend + Flask shell
- v0.2 — Authentik OIDC, Abby-branded web UI, palette CSS, postgres for prefs
- v0.3 — meal plan generator (week → Mealie meal plan write)
- v0.4 — shopping list aggregator (read meal plan → consolidated grocery list)
- v0.5 — native Kotlin + Compose Android app (read-only shopping list + plan view)
## Repo layout
## Layout
```
cauldron/
├─ cauldron/
│ ├─ config.py env-driven config
│ ├─ forge.py clawdforge HTTP client
│ ├─ mealie.py Mealie API client
│ ├─ sterilizer.py ingredient parse + apply pipeline
│ └─ server.py Flask app
├─ Dockerfile
├─ compose.yml
├─ requirements.txt
└─ .env.example
config.py env-driven config
forge.py clawdforge HTTP client
mealie.py Mealie API client
sterilizer.py ingredient parse + apply pipeline
aggregator.py cross-recipe shopping aggregator
server.py Flask app
scripts/
build_foods_seed.py USDA → foods seed
clean_foods_seed.py clawdforge-curated cleanup pass
```
## License
MIT.