docker compose passes an empty .env line as OPENAI_BASE_URL="", and with
base_url=None the openai SDK fell back to that empty value, so every
call failed with "Connection error". Always pass the base URL
explicitly. Also disable gunicorn's unused control socket, which
logged a permission error because /app is read-only for the app user.
Found while deploying to the homelab server.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A real API call returned 429 "You have no credits remaining" without the
word "quota", so the UI wrongly said the AI was busy. Match quota,
credit and billing wording; test uses the real message.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Optional OPENAI_BASE_URL for OpenAI-compatible endpoints or proxies
- Tests run the real openai SDK against a local stub server: request
shape (model, auth, strict json_schema), text cleanup, photo import
and an authentication error mapped to the UI message
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- SSRF-safe fetcher: public IPs only, connects to the checked address,
redirects re-validated, size/time limits, honest user agent
- schema.org/Recipe JSON-LD extraction (graphs, HowToSections, ISO
durations, yields, keywords, images) without extra dependencies;
AI fallback on plain page text when no structured recipe exists
- Instagram: one login-free request to the public embed page; when
Instagram withholds the caption, the import page explains how to paste
the text or import a screenshot instead
- Suggested source photo can be downloaded and attached on save
- Text import works without AI (text becomes the description)
- Installable PWA with manifest, icons and Android share target
- Offline tests for SSRF rules, parsers, Instagram and import views
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- recipes/ai.py: Chat Completions with strict JSON schema (Structured
Outputs), Pydantic re-validation, plausibility clamping, prompt treats
input as data only
- "Mit KI aufbereiten" on create/edit form returns an editable draft
- Import page: photo/screenshot (vision, downscaled JPEG, not stored) and
pasted text; drafts pre-fill the recipe form with a preview
- Clear UI messages for timeout, rate limit, quota, auth, model and
connection errors; without OPENAI_API_KEY AI features show a notice
- Optional per-user and global daily AI limits (default unlimited)
- Tests for response parsing, schema strictness, error mapping, views
Co-Authored-By: Claude Opus 5.5 <[email protected]>