Open registration let anyone with the URL create an account. Two
changes address that:
- REGISTRATION_CODE (.env, optional): when set, registration requires
entering it correctly. Empty/unset keeps registration open, so
existing installs are unaffected until configured.
- is_admin flag on User: the first account ever created on an install
becomes admin automatically (existing installs get their oldest
account promoted via the startup migration, so nobody is locked
out of user management after upgrading).
Admins get a new "Benutzerverwaltung" panel in Einstellungen listing
every account (email, link/prompt counts, join date) with a delete
button per account — deleting cascades to that user's links and
prompts via the existing relationship cascade. Deleting your own
account through this page is blocked (redirects with an error) to
avoid accidental admin lockout. Non-admins get a 403 on the
/settings/users routes.
Also fixes several pre-existing German pluralization bugs found while
writing the new counts ("2 Linke" -> "2 Links", "Kontoen"/"Konton" ->
"Konten") — irregular plurals need a full word swap, not a suffix.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New /prompts section extends the existing database (new Prompt model,
same SQLite file) and mirrors the Links experience: add a prompt, get
it auto-categorized and tagged by AI, filter by category, full-text
search, sort, edit, or have the AI re-categorize it. A header nav
switch ("Links" / "Prompts") toggles between the two collections; the
shared topbar/menu markup was factored into _topbar.html and
_topbar_actions.html so both pages (and settings) stay in sync.
Each prompt card has a dedicated copy-to-clipboard icon next to
edit/delete, so a stored prompt can be reused immediately. Copying
uses the raw markdown source (not the rendered HTML) so structure
survives when pasted into another AI tool. The copy handler tries the
async Clipboard API first and falls back to a hidden-textarea +
execCommand('copy') for plain-http/non-secure contexts, with clear
success/failure icon feedback either way.
Prompt content supports Markdown and is rendered server-side
(app/mdrender.py) for the card preview. Since this is user-supplied
HTML-adjacent content, rendering goes through two defenses: the raw
text is escaped (only '<' and '&', not '>', so blockquotes keep
working) before conversion so no raw tag can survive, and the
resulting HTML is passed through bleach with a tag/attribute/protocol
allowlist so Markdown-generated links can't carry a javascript: URL.
Verified against raw <script>, <img onerror>, and javascript: link
payloads. The edit form always shows the raw Markdown source, never
the rendered HTML.
Also bumps the default APP_VERSION (shown in the footer) from 1.0.0
to 2.0.0 to mark this feature addition.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Links can now be edited manually (title, summary, category,
manufacturer, tags) via an inline edit form, with a "KI neu
beschreiben lassen" action that re-fetches the URL and lets the AI
regenerate all fields. Editing recomputes the search embedding.
Also adds an app footer showing author, version, and hostname.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
FastAPI + HTMX Web-App zum Speichern von Links mit automatischer
KI-Kategorisierung, Zusammenfassung und semantischer Suche (OpenAI).
Mehrbenutzer mit Login, SQLite-Persistenz, Docker/Docker-Compose-Setup.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>