Establish the LLeMbas foundation: FastAPI/Jinja/SQLite layout, the ORM
schema, and the original SVG identity.
Notable decisions, all recorded in comments at the point they matter:
- No Alembic. SQLite only, schema created at startup, so models carry a
few columns nothing reads yet (Message.parent_id for branching,
content_parts_json for multimodal turns). Adding them later to a live
database without migrations is the painful path.
- Sessions are server-side rows keyed by a SHA-256 of the cookie value,
not JWTs, so logout and bans revoke access immediately.
- Upstream API keys are Fernet-encrypted with a key derived from
LEMBAS_SECRET_KEY. decrypt() fails soft to "" so rotating the secret
degrades to re-entering keys rather than crashing the admin UI.
- Artwork is generated by scripts/build_artwork.py rather than hand-drawn
per file: the mallorn leaf appears in the icon, favicon, lockup and
banner, and one source is the only way those stay in sync. The wordmark
is Source Serif 4 (OFL) converted to outlines, because a README banner
cannot load a webfont and <text> would render in whatever serif the
viewer happens to have.
- Icons live in a template partial, not assets/, because same-document
<use href="#id"> is universally supported and the cross-document form
is not.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>