Back to PURGIFIER

Release notes

See what changed in each PURGIFIER release.

v0.58.3Current

Align the admin business dashboard surfaces with the existing admin tabs.

Changes

  • styleUse the admin tabs' rounded translucent panels, subtle borders, and compact data-list treatment throughout the dashboard.
  • styleMatch table headers, row dividers, source cards, plan cards, and filter controls to established admin styles.
  • testAssert the dashboard section and KPI surfaces use the shared admin card treatment.
v0.58.2

Add contextual explanations throughout the admin business dashboard.

Changes

  • featAdd a Lucide CircleQuestionMark help icon to every dashboard KPI and data section.
  • featExplain metric definitions, cohort windows, data sources, and revenue semantics in German and English.
  • testVerify all 12 help icons render and activation/payment explanations appear on hover.
v0.58.1

Polish activation and first-payment conversion insights in the admin dashboard.

Changes

  • styleHighlight activation and first-payment rates in clearer summary panels.
  • featAdd hover and click help text explaining cohort eligibility and metric definitions.
  • testVerify both contextual tooltips render on hover.
v0.58.0

Add a business insights dashboard as the default admin tab.

Changes

  • featAdd selectable UTC reporting periods, period comparisons, usage trends, registrations, active users, and recorded EUR revenue.
  • featAdd activation, first-payment conversion, D7/D30 cohort retention, and revenue mix by product and transaction type.
  • featAdd an admin-protected aggregate insights API and an accessible, localized dashboard for English and German admins.
  • testCover period math, cohort maturity, payment classification, API response behavior, and dashboard controls.
v0.57.4

Make diagnostic email results easier to scan.

Changes

  • styleAdd emoji indicators to the email heading, overall result, and individual check statuses.
  • testVerify indicators appear in both HTML and plain-text email output.
v0.57.3

Make diagnostics email delivery results easier to recognize at a glance.

Changes

  • styleAdd clear success and warning icons to diagnostics email status feedback.
v0.57.2

Improve admin diagnostics with Telegram delivery verification and optional email reports.

Changes

  • featSend a short Purgifier diagnostics message to Telegram when notifications are enabled; use the Bot API acknowledgement as the delivery result.
  • featLet admins opt in to email the diagnostics report to the configured admin address.
  • testCover Telegram acknowledgement, failure, timeout, disabled state, email opt-in, and report rendering.
v0.57.1

Improve the admin Status workflow and preserve diagnostic history between views.

Changes

  • fixRun database migrations before local development startup so diagnostic history is available.
  • fixComplete the admin endpoint label in both locale catalogs.
  • fixKeep the latest diagnostic report mounted while navigating between admin tabs.
  • featMake diagnostics, service status, and configuration panels collapsible while keeping their actions accessible.
  • testVerify saved diagnostic history loads without rerunning checks.
v0.57.0

Add an operational health dashboard and service activity reporting to the admin Status tab.

Changes

  • featAdd authenticated read-only service checks, bounded history, and a safe support report.
  • featShow backup and scheduler freshness, provider reachability, and practical remediation guidance.
  • featAdd aggregated request and account activity with masked source summaries.
  • testVerify public health output and administrator access boundaries.
v0.56.1

Refresh email delivery and CSS-processing dependencies within the supported app runtime.

Changes

  • fixUpdate the email transport and Next.js CSS dependency to patched versions.
  • testPreserve email delivery and release-history behavior after dependency updates.
v0.56.0

Add a public release history linked from the app version in the footer.

Changes

  • featAdd a release-notes page showing version dates, summaries, and change lists from the existing Markdown history.
  • featLink the footer version to release notes and add localized page labels and sitemap alternates.
  • fixKeep internal implementation details out of the public release history when they are not appropriate for a user-facing summary.
  • choreInclude release-note Markdown in the Docker runtime image for the Node.js page renderer.
  • testValidate release-note parsing, semantic-version ordering, and the current-version entry.
v0.55.2

Show the exact schema-release path and explain each required schema change before migrating a backup.

Changes

  • styleReplace the migration-count-only badge with the source, pending migration releases, and target version path.
  • styleCompact long backup-row paths to source, ellipsis, and target while retaining the full path in the tooltip and confirmation.
  • featList the user-facing impact of each pending schema migration in the confirmation, with a generic fallback for future migration IDs.
  • styleFormat migration confirmation details across readable lines while retaining the existing dialog design.
  • docsClarify that displayed version hops correspond to schema migrations, not every app release.
v0.55.1

Clarify pending restore state and provide a safe way to cancel a ready candidate.

Changes

  • fixAdd explicit cancellation for ready or approved restore candidates; remove only the staged candidate and marker, never the source or active database.
  • fixKeep Migrate from silently discarding a ready restore operation.
  • styleShow only valid Restore or Migrate actions and hide row actions blocked by another pending restore.
  • testCover candidate cancellation, rejection during candidate processing, and migration blocking while a restore is pending.
v0.55.0

Separate backup migration from restore intent so legacy databases can be prepared and reused without activating them.

Changes

  • featMigrate older backups on a temporary copy and publish a separately named current-schema backup with fresh metadata and source provenance.
  • fixRequire a separate explicit Restore action to stage and validate a candidate; the live database changes only during approved restart-time activation.
  • fixReconcile stale restore markers when their staged candidate is missing, allowing migration or restore to be retried safely.
  • styleShow migrated-backup provenance and clarify migration versus restore states in the admin UI and EN/DE translations.
  • testCover isolated backup migration, explicit restore approval, and stale-candidate recovery.
v0.54.1

Align database migration notifications with the PURGIFIER branded email design.

Changes

  • styleReplace the plain Arial restore notification with the dark branded email layout, status panel, and admin footer.
  • testAssert restore notifications retain the branded layout and HTML escaping.
v0.54.0

Use separate Migrate and Restore actions so the live SQLite database stays untouched until an operator approves and restarts the app container.

Changes

  • featMigrate and validate an operation-specific restore candidate inside the existing app container.
  • featRequire separate Restore approval after successful candidate migration; expose queued, migrating, ready, approved, and failed states in the admin panel.
  • fixActivate only explicitly approved candidates during app startup, take a final online safety snapshot, validate after cutover, and restore the previous database if activation fails.
  • docsDocument the staged restore workflow and docker compose restart purgifier recovery procedure.
v0.53.0

Notify the configured administrator at each backup restore and startup-migration stage.

Changes

  • featSend restore preflight, safety snapshot, installation, restart-required, migration-start, success, and failure emails to ADMIN_EMAIL or SMTP_USER.
  • featPersist a single restore operation marker on the backup volume so startup can report the restore outcome after a container restart.
  • choreShare SMTP transport configuration between the Next.js app and the standalone migration CLI; email delivery failures do not block recovery.
v0.52.0

Add automatic SQLite migrations before application startup and show backup compatibility before restore.

Changes

  • featAdd transactional, idempotent forward migrations for supported database changes through app release 0.50.6, with a consistent pre-migration backup and integrity checks.
  • featRun the migration gate before Next.js in Docker and npm production starts; unknown or newer migration ledgers stop startup instead of serving against an unsupported schema.
  • featAdd read-only backup schema preflight using backup appVersion and actual SQLite structure, with conditional restore confirmation and server-side revalidation.
  • fixReject migration work newer than the running app and serialize concurrent startup migrations.
  • fixUse SQLite online snapshots for manual, automatic, pre-restore, and migration backups; remove raw database-copy fallbacks.
  • fixIsolate Docker build-time SQLite from parallel Next.js workers to prevent SQLITE_BUSY during image builds.
  • fixLoad Next.js environment files before the npm migration gate resolves the production database path.
  • docsDocument explicit fresh database initialization separately from forward migrations.
v0.51.5

Clarify the privacy disclosures for OpenRouter and downstream model providers.

Changes

  • docsDisclose OpenRouter prompt routing, configured training restrictions, and variable downstream provider processing in German and English.
  • docsReplace the blanket DPA statement with provider-specific contractual disclosures.
v0.51.4

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.51.3

Preserve streamed model output when server-sent events arrive in partial network chunks.

Changes

  • fixParse provider SSE streams with eventsource-parser so fragmented OpenRouter events are buffered and decoded correctly.
  • testCover OpenRouter SSE events split across multiple network chunks.
v0.51.2

Correct the OpenRouter provider health check so valid models are not reported as missing.

Changes

  • fixQuery OpenRouter's per-model /endpoints resource in the admin provider status check instead of the unsupported model-detail path.
v0.51.1

Use GPT-6 Luna as the default primary model for OpenRouter.

Changes

  • fixSet OPENROUTER_MODEL's default to the verified OpenRouter model ID openai/gpt-6-luna and expose it in the admin model list.
  • testAssert OpenRouter selects GPT-6 Luna when no runtime override is configured.
  • docsUpdate the OpenRouter primary-model defaults while preserving GPT-4o-mini as the basic-mode fallback.
v0.51.0

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.50.7

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.50.5

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.50.4

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.50.3

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.50.2

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.50.1

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.50.0

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.49.6

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.49.5

Fix three bugs around plan-context leakage: targetLanguage: "original" normalization mismatch causing spurious translation gating (403/429), and toneOfVoice always being sent in request payload regardless of plan.

Changes

  • fixtargetLanguage "original" — validate.ts normalizes "original" → "Original" (Title Case) but both route.ts and v1/route.ts compared against lowercase "original", so the case mismatch made every no-translate request appear as a translation request; changed comparison to .toLowerCase() !== "original" in both routes
  • fixtransform-runner no longer sends targetLanguage at all when value is "original" — the field is now omitted (undefined) when no translation is wanted, eliminating the ambiguity at the source
  • fixtransform-runner no longer sends toneOfVoice as an empty string for non-pro users — changed from always-send to toneOfVoice || undefined, so the field is only included when it contains actual content
v0.49.4

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.49.2

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.47.3

Improved usability of the payment-sync auto-schedule time picker in the admin dashboard.

Changes

  • styleTime picker wrapped in a bordered card section with header label + active-mode badge
  • featSave button is disabled (no-op) when draft matches the already-saved value — prevents accidental re-saves
  • feat✕ Clear button appears when a time is set, allowing one-click reset to interval mode
  • styleSave button turns green on success, orange/accent when unsaved changes are pending
  • stylecolorScheme: "dark" on time input prevents the browser rendering a white-background clock picker
  • featAdded hint text below the picker explaining interval mode vs. daily mode
  • choreTwo new i18n keys added: payment_sync_auto_time_clear, payment_sync_auto_time_hint (DE + EN)
v0.47.1

Adds a configurable daily auto-sync time (UTC) for the payment sync scheduler, settable from the admin Payments tab without redeployment.

Changes

  • featGET/POST /api/admin/payment-sync-config — reads/writes Redis key hc:payment_sync_time ("HH:MM" UTC)
  • featAdmin Payments → Payment Sync section now shows an "Auto-sync time (UTC)" time picker with Save button
  • featauto-payment-sync.ts updated to support time-of-day scheduling — reads Redis on every cycle, so changes apply immediately; falls back to interval mode (PAYMENT_SYNC_INTERVAL_HOURS env) if no time is set
  • feati18n keys payment_sync_auto_time_* added to DE and EN
v0.47.0

Adds an automatic background payment sync scheduler that catches missed Creem webhooks (payment succeeded but callback never reached the server) without requiring manual admin intervention.

Changes

  • featExtract payment-sync logic from API route into src/lib/payment-sync.ts (runPaymentSync()) — callable by both the admin route and the new background scheduler
  • featsrc/lib/auto-payment-sync.ts — background scheduler that runs runPaymentSync() every 6 hours (configurable via PAYMENT_SYNC_INTERVAL_HOURS env var); first run 5 minutes after server startup
  • featRegister startAutoPaymentSync() in src/instrumentation.ts alongside existing background services
  • refactorsrc/app/api/admin/payment-sync/route.ts — now a thin wrapper (~30 lines) that delegates to runPaymentSync(); identical behaviour preserved
v0.46.1

Fixes missing payment event entry when a subscription is revived via admin payment sync.

Changes

  • fixpayment-sync Phase 1 — insert payment_sync.revived event into payment_events table when a DB-dead grant is revived from Creem (grant update was correct, but no event was written, so "Letzte Ereignisse" showed no pro activation)
  • featbilling-event-table.tsx — add "payment_sync.revived" → "Subscription revived" label to event type map
v0.46.0

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.45.2

Fixes "Last run" not updating in the UI after clicking "Run now", and fixes the route silently returning success when a backup didn't actually run.

Changes

  • fixrunAutoBackupIfDue return type changed from "ran" | "skipped" | "disabled" to { status: "ran"; lastRun: string } | { status: "skipped" | "disabled" } — the lastRun timestamp is now returned directly from the function so callers don't need a Redis round-trip to learn when the backup ran
  • fixauto-config POST route — runNow path now uses run.lastRun directly in the response (instead of re-reading from Redis, which could race or fail silently and return the old value)
  • fixauto-config POST route — if the backup did not run (status !== "ran"), the route now returns HTTP 500 (backup_did_not_run) instead of silently returning ok: true; the client will correctly show an error message instead of "Backup created."
v0.45.1

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.45.0

Adds a Redis-backed automatic backup scheduler with admin UI controls, filter bar, and source badges on the backup list.

Changes

  • featsrc/lib/backup-utils.ts — consolidated shared path helpers and types (getBackupDir, getDbPath, metaPath, ensureBackupDir, listBackups, BackupMeta, BackupEntry) extracted from backup route to eliminate triple duplication
  • featsrc/lib/auto-backup.ts — background auto-backup scheduler; Redis keys hc:autobackup:*; runAutoBackupIfDue({ force? }) writes atomic *.db.tmp → *.db; prunes purgifier-backup-auto-* beyond maxCount; startAutoBackupScheduler() runs immediately then every 10 min with .unref()
  • featsrc/app/api/admin/backup/auto-config/route.ts — GET returns config + computed nextRun; POST validates patch (intervalHours ∈ [6,12,24,48,168], maxCount 1–30), optional runNow forces immediate backup
  • refactorsrc/app/api/admin/backup/route.ts — replaced private helpers with import from backup-utils
  • refactorsrc/app/api/admin/backup/upload/route.ts — replaced private getBackupDir/listBackups with import from backup-utils
  • featsrc/instrumentation.ts — added startAutoBackupScheduler() call on server startup
  • featsrc/app/[locale]/admin/page.tsx — Database panel: auto-backup config section (toggle, interval pills, maxCount slider, last/next run display, run-now button); filter bar (All / Manual / Auto); source badges (AUTO / MANUAL / PRE-RESTORE) on each backup row
  • featsrc/locales/en/common.json + src/locales/de/common.json — 26 new keys for auto-backup UI (autoBackup_*, backup_filter_*, backup_badge_*)
v0.44.4

Account data tab: invitations row now expands to show the actual sent/received list with email, date, and status.

Changes

  • featnew GET /api/account/invitations route returning the user's sent (email + date + status) and received (date + status) invitations
  • featinvitations category row in /account?tab=data now renders a rich expandable list when clicked — sent entries show recipient email + date + coloured status dot; received entries show date + status dot
  • fixDataCategoryRow detail prop widened from string | null to ReactNode to allow inline JSX lists
v0.44.3

Fix invitations row in the account data tab — adds a sent/received breakdown as expandable detail text.

Changes

  • fixinvitations row in /account?tab=data now shows "X sent · Y received" as expandable detail when the user has any invitations; previously detail: null caused the row to have a misleading cursor-pointer with no expand behaviour
  • featadd invitationsSentLabel and invitationsReceivedLabel translation keys to all 8 locale files (de, en, fr, nl, es, it, pt, pl)
v0.44.2

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.44.1

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.44.0

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.43.1

Post-implementation review fixes for account deletion (v0.43.0): corrected localStorage keys, updated Help FAQ in all 8 locales, added admin pending cancellations panel and management endpoints, and ran the DB migration.

Changes

  • fixlocalStorage keys in billing page handleDelete() — was clearing stale heatLevel/inputText/lastResult/bulkQueue; now clears actual keys hc_draft, hc_voice_presets, purgifier_playground_key, purgifier-cookie-prefs
  • featHelp FAQ faq_a8 updated in all 8 locales — now mentions self-service deletion at Billing → Delete Account, with email fallback retained
  • featAdmin Status tab — Pending Cancellations panel showing count badge (orange when >0), list with subId/email/attempts/error, Dismiss button for manual resolution after Creem cancel
  • featGET /api/admin/pending-cancellations — lists all pending cancellation rows for admin
  • featDELETE /api/admin/pending-cancellations/[id] — dismisses a row after admin manually cancels in Creem
  • choreDB migration — pending_cancellations table created in local SQLite DB via scripts/migrate-pending-cancellations.cjs
  • choreMilestone account-deletion.md status updated to complete
v0.43.0

Self-service account deletion: users can permanently delete their account from the billing page with double-confirmation (email + "DELETE" keyword), with full GDPR-compliant data handling and Creem subscription cancellation.

Changes

  • featSelf-service account deletion via POST /api/account/delete
  • featShared deleteUser() lib — hard-deletes PII, anonymises usage/payment history, cancels Creem subscription, cleans Redis keys
  • featpendingCancellations schema table for Creem cancel retry queue
  • featHourly cancel-retry background sweep (src/lib/cancel-retry.ts) started via instrumentation
  • featDanger zone UI in billing page — collapsible, requires email + "DELETE" confirmation
  • refactorAdmin DELETE /api/admin/users/[id] now uses shared deleteUser() — gains full cleanup (apiKeys, invitations, Redis, Creem) it previously lacked
  • featsendDeletionConfirmation() email template added to mailer
  • feati18n — account deletion keys added to all 8 locale billing sections (de/en/fr/nl/es/it/pt/pl)
  • docsDatenschutz §5 updated — self-delete instructions and anonymisation behaviour documented
  • docsDatenschutz §11 updated — Art. 17 GDPR erasure now notes self-service path
  • docsAGB §10 added — account deletion rights, subscription cancellation on deletion, admin-only path for frozen accounts (DE + EN)
v0.42.6

Translate legal page notices for non-DE/EN locales and fix hardcoded strings in API docs.

Changes

  • fixLegal pages (AGB, Datenschutz, Impressum) now show a localized notice banner for FR/NL/ES/IT/PT/PL users explaining the document is only available in German and English
  • fixapi-docs.tsx — endpoint summaries and "Field"/"Type" table headers now use i18n keys; added getSummary() helper in EndpointBlock
  • featAdded legal.doc_notice translation key to all 8 locales (de/en/fr/nl/es/it/pt/pl)
  • featAdded docs_field, docs_type, docs_ep_transform, docs_ep_analyze, docs_ep_me, docs_ep_usage, docs_ep_health to apiKeys namespace in all 8 locales
v0.42.5

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.42.4

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.42.2

Second multilang gap-fix pass: OG image stat labels fully localized, number formatting uses native locale, missing-key handler added to prevent white screens.

Changes

  • fixopengraph-image.tsx — replaced hardcoded locale === "en" ? ... : "DE text" expressions with t.og_subtitle, t.og_stat_label_1/2/3 translation keys; all 6 new locales now render localized OG image text instead of German
  • featall 8 locales/*/common.json — added 4 new meta namespace keys: og_subtitle, og_stat_label_1, og_stat_label_2, og_stat_label_3 with locale-appropriate translations (DE/EN/FR/NL/ES/IT/PT/PL)
  • fixword-counter.tsx — dtLocale now uses locale directly (not hardcoded "de-DE"); FR/NL/ES/IT/PT/PL users get native number formatting
  • fixaccess-bar.tsx — same dtLocale fix; date and number display now uses correct locale for all 8 languages
  • fixrequest.ts — added onError + getMessageFallback to log missing keys instead of throwing; prevents white screens from any missed translation key in production
v0.42.1

Post-multilang gap-fix: corrects payment success URL for DE locale and OG image locale fallback for all 6 new locales.

Changes

  • fixcheckout-url.ts — removed locale === "de" ? "" : ... special-case; with localePrefix: 'always' all locales including DE use a URL prefix (/de/), so the success redirect now correctly generates /${locale}/?payment=success for every locale instead of / for DE (which would drop the ?payment=success query param on the next-intl redirect)
  • fixopengraph-image.tsx — imported all 8 locale common.json files (FR, NL, ES, IT, PT, PL were missing); the messages map now covers every locale so OG image text renders in the user's language instead of falling back to German
  • choreuse-translation.ts — updated stale JSDoc comment listing only "de" | "en" to include all 8 locales
v0.42.0

Full Tier 1 + Tier 2 multilanguage expansion: added FR, NL, ES, IT, PT (BR), and PL locales — 18 new translation files, updated i18n routing, admin EN passthrough, layout metadata, and language switcher replaced with scalable dropdown.

Changes

  • featAdded fr, nl, es, it, pt, pl to routing locales in src/i18n/routing.ts and domain config
  • featAdmin namespace EN passthrough in src/i18n/request.ts — all non-EN/non-DE locales receive admin keys from EN, avoiding 266-key translation overhead per locale
  • featUpdated src/app/[locale]/layout.tsx with ogLocaleMap, keywordsMap, and alternates.languages (including x-default) for all 8 locales
  • featReplaced DE|EN pill toggle in src/components/language-switcher.tsx with a scalable styled <select> dropdown showing all 8 ISO locale codes
  • featCreated src/locales/fr/common.json, fr/help.json, fr/cookies.json — French translations (all user-visible namespaces)
  • featCreated src/locales/nl/common.json, nl/help.json, nl/cookies.json — Dutch translations
  • featCreated src/locales/es/common.json, es/help.json, es/cookies.json — Spanish translations (Spain standard)
  • featCreated src/locales/it/common.json, it/help.json, it/cookies.json — Italian translations
  • featCreated src/locales/pt/common.json, pt/help.json, pt/cookies.json — Portuguese translations (Brazilian standard)
  • featCreated src/locales/pl/common.json, pl/help.json, pl/cookies.json — Polish translations
v0.41.9

Upgrade EventTypeHint tooltip in billing event table to use the same glassmorphism popover style as the HelpTip ? component.

Changes

  • stylereplaced native title attribute tooltip with a hover/tap floating popover on the (i) info icon in billing-event-table.tsx; matches HelpTip's rgba(20,20,20,0.96) background, blurred backdrop, and border style; shows raw Creem eventType in monospace inside the popover; overflow-safe repositioning and mobile close button included
v0.41.6

Admin payments table gains a sortable Date column, an Event Type filter dropdown, and the Order ID column now shows data (creemOrderId/creemSubId exposed from the API).

Changes

  • featSortable Date column in admin BillingEventTable — click ↑/↓ header to toggle ASC/DESC; sortDateDir + onSortDate props added to BillingEventTable
  • feat"Event" filter dropdown in admin payments filter bar — all raw Creem eventType values selectable; sent as eventType query param to API
  • featsortDir (asc|desc) toggle button in Date filter row — visual ↑ asc / ↓ desc indicator; default desc (newest first)
  • featAdmin payments API now exposes creemOrderId and creemSubId — Order ID column no longer shows "—" for every row
  • feateventType filter wired end-to-end (API WHERE clause, admin page state, query param)
  • fixsortDir param added to admin payments API — was always hardcoded DESC before
  • choreevents_filter_eventtype i18n key added to EN and DE locales
v0.41.5

Billing history now shows event sub-type labels (raw Creem event identifiers) beneath each Type entry, and enforces newest-first sort client-side.

Changes

  • featAdd getEventSubLabel() to billing-event-table.tsx — maps eventType (e.g. checkout.completed, subscription.scheduled_cancel, subscription.paid) to a small monospace chip rendered under the main type label
  • featDistinguish subscription.scheduled_cancel (period-end cancel) from subscription.canceled (immediate) in UI
  • featClient-side newest-first sort on billing page — defensive .sort() before paginator slice
  • choreAdd 12 i18n keys per locale (event_checkout, event_payment, event_sub_created, event_sub_paid, event_sub_canceled, event_sub_scheduled_cancel, event_sub_expired, event_refund, event_failed, event_sync_recovery, event_sync_expired) to both EN and DE
  • choreDelete scripts/patch-de-locale.js (one-time migration helper)
v0.41.2

Fix duplicate grants and stale isCancelled state created by payment sync orphan recovery.

Changes

  • fixbilling isCancelled now reads !activePro.autoRenew from the grant directly instead of checking the latest payment event status — prevents a sync recovery event from masking the actual cancellation state
  • fixpayment sync Phase 2 orphan recovery now checks for an existing pro grant before inserting — if one exists (re-subscribe scenario), it UPDATEs the grant with the new subId/expiresAt/autoRenew instead of creating a duplicate; prevents "2x active" in sync results
  • featpayment_sync.* events now display as "Plan recovery" / "Plan-Wiederherstellung" in billing history instead of "Pro subscription", making sync operations distinguishable from real purchases
  • choreadd desc to drizzle-orm imports in payment-sync route
v0.41.1

Fix payment sync date display (wrong year ~58000), show readable order IDs (ORD-...), and catch initial subscription payments during orphan scan.

Changes

  • fixtx.createdAt is Unix ms, not seconds — removed erroneous * 1000 multiplier; dates now show correctly
  • fixuse tx.order (readable ORD-... order number) instead of internal tx.id for orphan table Tx ID column
  • fixPhase 1 Last Order column now uses sub.lastTransaction?.order (order number) with fallback to sub.lastTransactionId
  • fixPhase 2 orphan scan now includes type === "payment" transactions (initial subscription checkouts), not only type === "invoice" renewals — catches new subscribers whose first payment was a one-time payment type
  • styleincrease order ID truncation from 8 → 14 chars so ORD-19CF911ABF91 is legible without the tooltip
v0.41.0

Re-subscribe after plan cancellation + bidirectional payment sync with Creem as source of truth (orphan detection, order/date info).

Changes

  • featexpose planCancelled flag from getUserAccess() → /api/me so the client detects cancelled-but-active plans
  • featmain page Pro button — enabled for cancelled users with "Re-subscribe →" text; badge shows "Cancelled" instead of "Active ✓"
  • featbilling page — adds "Re-subscribe to Pro" checkout button when plan is cancelled; pre-fills userId and email from /api/me
  • featpayment sync rewrite — bidirectional reconciliation, Creem as source of truth; 5 outcomes: ok / renewed / revived / scheduled_cancel / expired
  • featpayment sync Phase 2 — orphan detection: paginate Creem transactions for Pro product, find sub IDs missing from DB, resolve customer email, match user, create missing grant + paymentEvent
  • featpayment sync now surfaces order number (lastTransactionId), purchase date (subCreatedAt), last tx date (lastTxDate), and expiry (expiresAt) in the admin UI
  • featadmin payment sync tables expanded from 4 → 7 columns each (Phase 1 + Orphan tables)
  • feati18n — new keys for re-subscribe, plan_cancelled, and all new payment sync table column headers (EN/DE)
v0.40.4

Full per-column filter system for the Recent Events table in the admin payments dashboard.

Changes

  • featStatus filter — pill buttons for all/succeeded/renewed/cancelled/refunded/failed
  • featType filter — pill buttons for all/pro/blitz/refill (maps to productType column)
  • featPlan filter — pill buttons for all/pro/blitz
  • featDate range filter — from/to date pickers with dark color-scheme
  • featAmount range filter — min/max numeric inputs in euros (converted to cents in API)
  • feat"Clear filters" button visible when any filter is active
  • featAPI updated to accept 8 filter params with unified conditions[] WHERE clause
  • feateventsFilters state object + eventsFiltersRef + updateFilter() helper replacing single eventsFilterQ string
  • fixPaginator onPageChange/onPageSizeChange no longer pass stale eventsFilterQ arg
  • choreNew i18n keys — events_filter_clear, events_filter_status, events_filter_type, events_filter_plan, events_filter_date, events_filter_amount, events_filter_min, events_filter_max, events_filter_all in EN + DE
v0.40.2

Fix next-intl ICU parse error on admin page payment sync summary.

Changes

  • fixpayment_sync_summary locale keys used {{total}} double-brace placeholders which next-intl's ICU parser rejects as malformed arguments; changed to single-brace {total} and replaced manual .replace() chain with native t("payment_sync_summary", { total, expired, errors }) interpolation
v0.40.1

Fix 403 error from Creem API when cancelling a subscription programmatically.

Changes

  • fixCreem subscription cancel — changed { mode: "scheduled", onExecute: "cancel" } to { mode: "immediate" } to match Creem's documented API usage; mode: "scheduled" is in the SDK schema but not supported by the live API (returns 403 "Bad Request"); user-facing UX is unchanged — access continues until expiresAt in our system regardless of Creem's cancellation mode
  • fixbilling page cancel — re-fetch /api/billing after successful cancel instead of partial optimistic update, so the new cancel event row immediately appears in the billing history table without requiring a page refresh
v0.40.0

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.39.0

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.38.0

Hide all public-facing pricing and purchase UI with a "Coming Soon" banner for pre-launch legal safety.

Changes

  • featNew ComingSoonBanner component — glass panel with rocket icon and translated "Coming Soon" placeholder text
  • featHome page pricing section replaced with ComingSoonBanner; PaywallOverlay and ProUpsellToast hidden (commented out); RateLimitToast onUpgrade CTA removed
  • featHelp page plans & pricing comparison section replaced with ComingSoonBanner
  • featBilling page content replaced with ComingSoonBanner (page shell kept for nav/heading)
  • featHeader Billing nav link hidden — desktop and mobile
  • featProLimitOverlay Option B (€4.99 refill + Creem checkout) hidden; Options A and C (free) remain
  • choreAdd comingSoon i18n namespace to de/common.json and en/common.json
  • choreRemove unused imports (Shield, Lock from page.tsx; Receipt from header.tsx; RefreshCw, creemCheckoutUrl from pro-limit-overlay.tsx; Check, Minus from help/page.tsx)
v0.37.0

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.36.0

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.35.0

Backup metadata sidecar: every backup created through the Admin UI now ships a .meta.json companion file recording app version, timestamp, creator and Node version; the version badge is displayed in the backup list.

Changes

  • feat.meta.json sidecar written on backup creation — contains appVersion, createdAt, createdBy (admin email), nodeVersion
  • featlistBackups() reads the sidecar and attaches meta to each entry; missing sidecar (legacy / imported backups) is silently handled as meta: undefined
  • featDELETE /api/admin/backup removes the .meta.json companion when deleting a backup file
  • featAdmin UI backup list row shows v{appVersion} badge (monospace pill) when metadata is available; tooltip shows full provenance (version · creator · Node version)
  • refactorextracted BackupMeta and BackupEntry types in the backup route for clarity
v0.34.1

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.34.0

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.33.2

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.33.1

Billing page link is now visible to all authenticated users, not just active Pro/Blitz subscribers.

Changes

  • fixShow billing nav link to all authenticated users — previously hidden when plan was free; users with expired subscriptions could not navigate to their payment history
v0.33.0

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.32.4

Fix all subscription.* webhook handlers being silently skipped; add idempotency for double-event pro grants.

Changes

  • changefix: Added subId-based userId fallback lookup before the !userId guard for all subscription.* events — db.select({userId}).from(accessGrants).where(subId).get() resolves the user from the stored grant
  • changefix: Added idempotency check in checkout.completed pro branch — skips insert if a grant with the same subId already exists
  • changefix: Added idempotency check in subscription.created — skips if grant already exists (checkout.completed is the primary handler; subscription.created is a safety-net fallback)
  • changerefactor: Removed dead renewUserId inline DB-lookup from subscription.paid case; userId now resolved cleanly at the top level
  • changetest: Added real-Creem-payload tests (subId-only, no metadata userId) for subscription.paid (+2), subscription.created (+2), subscription.canceled (+1), subscription.scheduled_cancel (+1), subscription.expired (+1)
  • testAdded idempotency test for checkout.completed pro (+1 already in 0.32.3 suite)
  • Total80 tests (was 51 webhook + 21 checkout-url = 72; added 8 new webhook tests)
v0.32.3

Fix pro plan not being granted after successful checkout: three webhook bugs discovered and resolved.

Changes

  • fixRestore payload.data?.request_id as the primary userId extraction path; add payload.data?.metadata?.referenceId as second path
  • fixAdd productType === "pro" branch in checkout.completed handler — grants a 30-day pro access grant (with first-purchase bonus) instead of falling through to blitz
  • fixsubscription.paid / subscription.payment_succeeded — when userId is absent from payload, look up via accessGrants.subId to support subscription renewal webhooks
  • testUpdated userId extraction tests — primary path is now data.request_id, added data.metadata.referenceId test
  • testAdded 3 tests for checkout.completed with productType === "pro" (grant, no-blitz, no-double-bonus)
v0.32.2

Fix Creem checkout 400 error caused by invalid success_url format and incorrect webhook userId extraction path.

Changes

  • fixsuccessUrl now uses /?payment=success (trailing slash before ?) — http://localhost:3000?payment=success was rejected by Creem API with 400 "URL must be valid"; adding a path component satisfies Creem's URL validator
  • fixWebhook userId primary extraction path changed from payload.data?.request_id to payload.metadata?.referenceId — the @creem_io/nextjs adapter embeds referenceId inside the metadata object, not as a top-level request_id field
  • fixUpdated checkout-url.ts JSDoc comment: corrected description of how referenceId is forwarded
  • testUpdated checkout-url.test.ts — all metadata/customer assertions now use JSON.parse(params.get("metadata")!) and correct /?payment=success expectations
  • testUpdated webhook.test.ts — primary userId extraction test now uses metadata.referenceId path with corrected description
v0.32.1

Extract checkout URL builder into a testable lib, fix webhook test spelling, and add comprehensive test coverage for the SDK checkout path and all userId/productType extraction fallbacks.

Changes

  • refactorExtracted creemCheckoutUrl() from inline component functions into src/lib/checkout-url.ts — enables unit testing and removes duplication between paywall-overlay.tsx and pro-limit-overlay.tsx
  • fixsubscription.cancelled (British) → subscription.canceled (American) in webhook.test.ts — the test was asserting on the wrong event name after the production bug fix in v0.31.2
  • testAdded tests/unit/checkout-url.test.ts — 21 tests covering all params (productId, referenceId, metadata, successUrl locale prefix, customer email, server-side origin fallback, full URL composition)
  • testExtended webhook.test.ts with userId extraction group (5 tests) — covers SDK request_id primary path, metadata.user_id, data.metadata.user_id, checkout.metadata.user_id, and no-userId no-op
  • testExtended webhook.test.ts with productType extraction group (4 tests) — covers SDK camelCase metadata.productType, nested data.metadata.productType, legacy snake_case metadata.product_type, and default blitz fallback
  • testsubscription.canceled block now has 4 tests — covers event logged, no grant update (natural expiry), and confirms old British spelling falls to unhandled default
v0.32.0

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.31.3

Fix Creem checkout 404 by correcting both the payment link URL format and metadata parameter syntax.

Changes

  • fixCheckout URL changed from https://checkout.creem.io/<id> to https://creem.io/payment/<id> — the correct Creem payment link format per official docs
  • fixMetadata params changed from x_metadata_user_id / x_metadata_product_type (undocumented prefix) to metadata[user_id] / metadata[product_type] — bracket notation per Creem docs; metadata is now forwarded correctly in webhook payloads
v0.31.2

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.31.1

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.31.0

Fix the "Buy Now" button that silently did nothing, and add the legally required Digitalklausel consent checkbox (§ 356 Abs. 5 BGB) before every Creem checkout.

Changes

  • fixreplaced window.open(url, "_blank") with window.location.href = url in PaywallOverlay, ProUpsellToast, and ProLimitOverlay — popup blockers silently swallowed the new-tab open; direct navigation is reliable and correct since Creem redirects back via success_url
  • featadd Digitalklausel checkbox (§ 356 Abs. 5 BGB) — unticked by default, disables the buy button until ticked — inside each plan card in PaywallOverlay and above the refill button in ProLimitOverlay
  • featcheckout URLs now include success_url (returns to /?payment=success after payment) and request_url (cancel returns to homepage), plus x_metadata_product_type on all links
  • featcheckoutUrl() now returns "" instead of "#" when product ID is missing; an inline error banner is shown to the user instead of silent no-op
  • featpayment success detection — on return from Creem with ?payment=success, shows an info dialog and strips the param from the URL via window.history.replaceState
  • styleremoved passive legal_notice text from paywall overlay bottom strip (now superseded by active consent checkboxes); kept AGB · Datenschutz links
  • featadd digitalklausel, checkout_error keys to paywall namespace (DE + EN)
  • featadd digitalklausel key to proLimit namespace (DE + EN)
  • featadd payment_success key to page namespace (DE + EN)
v0.30.3

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.30.2

Adds a freeze/unfreeze toggle action button to the admin user list for testing account lock flows.

Changes

  • featNew POST /api/admin/users/[id]/freeze route — sets lockedUntil to 100 years in the future and marks all access grants as isFrozen: true with reason "dispute"; guards against freezing admin accounts
  • featFreeze toggle button in admin user list (mobile card + desktop table) — shows 🔒 Freeze on unlocked users, 🔓 Unfreeze on locked users; hidden for admin accounts; reloads current page/pageSize after action
v0.30.1

Gap fixes for the v0.30.0 paginator implementation — correct totals, synced state, and preserved filters.

Changes

  • fixLogs paginator total was showing unfiltered buffer size (max 200); now returns filtered count via new countFilteredLogs() in log-buffer.ts
  • fixusersPageSize React state was never updated after paginator page-size change; loadUsers now calls setUsersPageSize(q.pageSize) to keep UI in sync
  • fixTab switch to logs tab now preserves current level/search/page/pageSize filters instead of resetting to defaults
  • fixunfreezeUser now reloads payments at current page/pageSize instead of resetting to page 1
  • fixAdded void prefix to loadLogs call in tab-switch effect for consistent floating-promise handling
v0.30.0

Full pagination across all list surfaces in the admin panel and billing page — server-side for users, logs, and payments; client-side for invitations, API keys, API usage, and per-user billing history.

Changes

  • feat<Paginator> shared component with page, pageSize (number | "all"), total, compact mode, and configurable pageSizeOptions [25, 50, 100, 500, 1000, "all"]
  • featUsers — server-side filter + sort + pagination via updated GET /api/admin/users (accepts page, pageSize, q, plan, verified, sort, dir)
  • featLogs — server-side pagination via GET /api/admin/logs (accepts limit, offset); response includes total buffer size
  • featPayments — server-side pagination via GET /api/admin/payments (accepts page, pageSize); response includes recentEventsTotal
  • featInvitations, API Keys, API Usage per-user — client-side slice pagination (pageSize 25)
  • featPer-user billing inline rows — client-side pagination with billingPages state (pageSize 10)
  • featBilling page — client-side pagination over events list
  • refactorAdmin page filteredUsers derived state removed; all filtering/sorting now happens server-side
  • refactorloadUsers refactored to accept opts? with query ref for stable state tracking
  • refactorloadLogs and loadPayments updated to accept explicit page/pageSize params
  • fixSearch input uses 400ms debounce for server-side filtering; clear button triggers immediate reload
v0.29.0

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.28.0

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.27.1

Increased Redis health check timeout to accommodate slower initial connections on production servers.

Changes

  • fixRedis health check timeout increased from 2s → 5s with retry strategy. Prevents spurious "RedisConnection is closed" errors when Redis is slow to respond on initial connection.
v0.27.0

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.26.1

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.26.0

Add GDPR-compliant cookie consent banner using react-cookie-consent — full Cyber-Minimalist design with Accept All / Settings / Essential Only flow.

Changes

  • featCookie consent banner (src/components/cookie-consent-banner.tsx) — fixed bottom-right, fade-in, 3-button layout (Accept All / Settings / Essential Only), settings view with granular per-category toggles (Essential always on, Analytics + Preferences toggleable), accessible from initial load or via footer link
  • featCookie consent context (src/contexts/cookie-consent.tsx) — exposes useCookieConsent() hook with openSettings() / closeSettings() for programmatic access to cookie preferences modal
  • featCookie footer link — "Cookie Settings" link in footer (legal section) triggers preferences modal using context
  • featCookie consent helpers (src/lib/cookie-consent.ts) — hasConsented(), getConsent(), setConsent(), hasConsentFor() using react-cookie-consent's Cookies utility + localStorage for granular prefs
  • featTranslation keys — new cookies namespace in src/locales/de/cookies.json and src/locales/en/cookies.json (14 keys each), added "cookies" key to legal namespace for footer link
  • choreRegister cookies namespace in src/i18n/request.ts message loader
  • choreWrap app with <CookieConsentProvider> in src/app/[locale]/layout.tsx
  • choreAdd <CookieConsentBanner /> to layout
  • choreUpdate Footer component to include cookies link using context
  • choreInstall react-cookie-consent npm package
v0.25.5

Add Heat Level 5 visual feedback — brief red pulse animation on button click to underscore intensity.

Changes

  • featHeat Level 5 red pulse animation — when user clicks Level 5 button, the frame pulses red for 600ms using @keyframes heat5Pulse with danger color (#EF4444), emphasizing intensity through visual feedback
  • styleAdded .animate-heat5-pulse CSS animation class to globals.css with red border + glow effect
v0.25.4

Fix build failure caused by <a> tags navigating to / — replaced with locale-aware <Link>.

Changes

  • fixReplace <a href="/#pricing"> with <Link href="/#pricing"> in desktop and mobile nav to satisfy @next/next/no-html-link-for-pages lint rule
v0.25.3

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.25.2

Fix pricing nav link not working from sub-pages.

Changes

  • fixChange href="#pricing" to href="/#pricing" in desktop and mobile nav so the pricing anchor navigates to the home page pricing section from any page
v0.25.1

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.25.0

Adds a Redis-backed LLM provider and model selector, giving admins full runtime control over which LLM provider (Gemini, OpenAI, local) and model is used — without a redeploy.

Changes

  • featsrc/lib/llm-config.ts — new Redis-backed LLM config module; single MGET read, pipeline SET, DEL reset; precedence Redis → env var → hardcoded default; fail-open when Redis unavailable
  • featsrc/app/api/admin/llm/route.ts — new admin CRUD route (GET/POST/DELETE) for runtime LLM config; validates provider enum + model strings + localBaseUrl; fetches available local models; includes apiKeys and source metadata in response
  • featsrc/lib/llm.ts — refactored streamFromProvider to call getLlmConfig() once per request; removed getProvider(); model strings now resolved from config with basicModel flag support; streamFromOpenAI, streamFromLocal, streamFromGemini take explicit model/baseUrl params
  • featsrc/components/llm-config-panel.tsx — new admin UI panel; provider toggles, per-field source badges (redis/env/default), comboboxes with free-text input for custom models, Save (diff-only POST) and Reset (DELETE with confirm dialog), toast notifications
  • featsrc/app/[locale]/admin/page.tsx — LlmConfigPanel added to admin status tab
  • featsrc/app/api/admin/status/route.ts — checkLlm() reads active provider/model from getLlmConfig() instead of env vars directly
  • feati18n — 22 llm_* keys added to admin namespace in both DE and EN locale files
  • testtests/unit/llm-config.test.ts — 26 new unit tests covering getLlmConfig, getLlmConfigWithSource, setLlmConfig, resetLlmConfig with ioredis mock
  • testtests/unit/llm.test.ts — migrated from env-var based routing to vi.mock("@/lib/llm-config"); removed obsolete "unknown provider" test; all 26 tests pass
v0.24.3

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.24.1

Fixed 500 error when LLM_PROVIDER=local and the local endpoint is unreachable — now falls back to Gemini or OpenAI instead of crashing.

Changes

  • fixsrc/lib/llm.ts — when local provider throws (connection refused / unreachable), automatically retry with Gemini if GEMINI_API_KEY is set, then OpenAI if OPENAI_API_KEY is set; each fallback attempt is logged at warn level; if all fail, original error is re-thrown
v0.24.0

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.23.1

Suppress false-positive webpack cache warnings from next-intl's extractor tooling.

Changes

  • chorenext.config.mjs — added ignoreWarnings filter for next-intl extractor dynamic-import warnings; these were harmless but noisy in dev/build output
v0.23.0

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.22.2

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.22.1

Fix the admin log viewer being empty in local dev due to Next.js HMR creating fresh module instances with new ring-buffer arrays and new pino instances on every hot-reload cycle.

Changes

  • fixlog-buffer.ts — ring buffer array now stored on globalThis.__purgifierLogBuffer so it persists across HMR re-evaluations; all routes share the same buffer in the same Node.js process
  • fixlogger.ts — pino instance and Transform stream now built inside a buildLogger() guard that checks globalThis.__purgifierLogger; prevents creating duplicate stdout streams and ensures the single instance writes to the same globalThis buffer
v0.22.0

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.21.5

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.21.4

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.21.2

Users with the page already open now see the maintenance screen within 15 seconds of an admin enabling maintenance mode; maintenance-mode 503s no longer show a misleading "AI service unavailable" dialog.

Changes

  • featMaintenanceWatcher component — polls /api/maintenance every 15 s while the normal page is visible; calls router.refresh() when maintenance flips on so SSR immediately renders MaintenanceScreen
  • fixdisambiguate HTTP 503 in page.tsx onError — LLM_UNAVAILABLE code → show error dialog; maintenance/other 503 → router.refresh() so the full maintenance screen is shown cleanly
v0.21.1

Adds user-facing error dialog when the AI service is unreachable during a purge, and tightens up admin UI date/word-cap display.

Changes

  • featLLM unavailable error handling — POST /api/transform now returns 503 LLM_UNAVAILABLE when ECONNREFUSED/fetch-failed is detected; main page onError and outer catch both show an info dialog via setInfoDialog
  • feati18n keys page.error_llm_unavailable and page.error_llm_unavailable_detail added to DE and EN locales
  • fixall admin page dates now show full datetime (day + month + year + hour + minute) — was date-only in several places
  • fixBillingEventTable.formatDate now includes time component
  • fixremoved redundant cap {wordCap} from admin user list mobile card and desktop Plan cell
v0.21.0

Admin can now view any user's full payment history inline from the Users panel.

Changes

  • featBillingEventTable shared component extracted from billing page — handles desktop table, mobile cards, compact (inline) mode, plan badges (PRO/BLITZ/+50K), status badges, type labels, empty state; uses billing namespace translations internally
  • featGET /api/admin/billing?userId=xxx — admin-only route returning events + activeSub for any user (mirrors /api/billing logic exactly)
  • featAdmin Users panel — Receipt icon button per user row (mobile + desktop); clicking fetches and reveals an inline expand row with the compact BillingEventTable
  • refactorsrc/app/[locale]/billing/page.tsx — replaced ~130 lines of duplicated table/card JSX + helpers with <BillingEventTable events={...} />
  • fixReceipt icon re-added to billing page import (removed accidentally during refactor)
  • fixaccessGrants.subId field name corrected in admin billing route (was incorrectly creemSubId)
v0.20.5

Fix maintenance and registration toggles reverting to off immediately after enabling.

Changes

  • fixremoved router.refresh() from toggleMaintenance — the refresh was re-triggering the initial useEffect which re-fetched from Redis and overwrote the optimistic state with false
  • fixsame removal in toggleRegistration for the same reason
v0.20.4

Fix POST /api/admin/maintenance (and registration toggle) returning 500 when Redis write fails.

Changes

  • fixadded catch block to setMaintenanceMode — Redis errors no longer propagate as 500s
  • fixadded catch block to setRegistrationDisabled — same defensive pattern as the read functions
v0.20.3

Rearrange admin panel controls: put Maintenance, Registration, and a new Infra Status widget into a single 3-column row.

Changes

  • featMaintenance and Registration panels now side-by-side (3-column grid, responsive)
  • featCompact Infra Status panel as third column — shows DB, Redis, SMTP, active LLM with CheckCircle/XCircle/AlertCircle icons
  • featInfra Status auto-loads on admin page mount (no need to open Status tab to see health)
  • featInfra Status panel border/background turns red on error, yellow on warning
  • featInline refresh button on Infra Status panel
v0.20.2

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.20.1

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.20.0

Adds billing history page with payment event tracking, active subscription card, and Billing nav link for Blitz/Pro users.

Changes

  • featpaymentEvents DB table — tracks every payment/webhook event (plan, amount, currency, Creem IDs, grantId link)
  • featscripts/migrate-payment-events.cjs — DDL + backfill from existing accessGrants rows
  • featwebhook updated — inserts paymentEvents row on every handled event (blitz, pro, refill, renewal, cancellation)
  • featGET /api/billing route — returns payment events + active pro subscription info for authenticated user
  • feat/billing page — event table (desktop) + card list (mobile), active sub card with "Manage Subscription" link
  • featBilling nav link in header (desktop + hamburger) — shown when isAuthenticated && (isPro || isBlitz)
  • featbilling i18n namespace — DE + EN translations for all billing page strings
  • featnav.billing translation key — DE: "Abrechnung", EN: "Billing"
v0.19.2

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.19.1

Improves the admin Status tab LLM section to show all three providers at once, highlighting the active one and the configured model.

Changes

  • featcheckLlm() now always returns all three providers (Gemini + fallback, OpenAI, Local LLM) — active provider gets a real connectivity ping, inactive providers show skip status with key/model presence info
  • featAdded active?: boolean field to Check / StatusCheck types
  • styleStatusRow displays an orange active badge next to the active LLM provider name
  • styleModel/URL shown in the detail column for all providers (configured or not)
  • refactorRemoved redundant "LLM provider" line from the checked-at metadata bar (now visible directly in the LLM section)
v0.19.0

Adds an admin Status tab with real-time infrastructure health, LLM provider reachability, and environment variable configuration checks.

Changes

  • featNew /api/admin/status route — parallel checks for DB (Drizzle SELECT 1), Redis (PING), SMTP (nodemailer verify), LLM provider reachability (Gemini/OpenAI/Local via HTTP with 5s timeout), and 11 required env var presence checks
  • featAdmin dashboard "Status" tab — displays infra, LLM connectivity, and env config with OK/warn/error/skip indicators, manual Refresh button, and last-checked timestamp
  • fixAdmin status route uses getUserFromSessionWithDB + unauthorized()/forbidden() helpers consistent with all other admin routes
  • choreTranslation keys added for tab_status, status_title, status_refresh, status_checked_at, status_provider, status_infra, status_llm, status_env in both DE and EN locales
v0.18.3

Fixed all inaccurate API documentation example responses to match actual route output.

Changes

  • fixPOST /api/v1/transform response example — result is now an object { text, wordCount, durationMs, model } with a usage block; removed non-existent heatLevel, wordsIn, wordsOut fields
  • fixPOST /api/v1/analyze response example — score and label are now correctly nested under result; removed non-existent wordsAnalyzed field; added requestId
  • fixGET /api/v1/me response example — added missing name field
  • fixGET /api/v1/usage response example — added bonus and windowStart to fairUse; renamed resetAt → resetsAt; changed value from Unix timestamp to ISO string
  • fixGET /api/v1/health response example — was showing internal DB/Redis/SMTP check format; now correctly shows { ok, status, maintenance, version }
v0.18.2

The public help page now includes the full API documentation section, consistent with the API Keys page.

Changes

  • featApiDocs component added to the help page (/hilfe) between the FAQ and Support sections
v0.18.1

Logo now links to the home page from any route, and the API Keys page got a back button consistent with the admin and help pages.

Changes

  • fixHeader logo changed from <a href="#"> to <Link href="/"> — clicking the logo now always navigates to the main page regardless of current route
  • featAPI Keys page (/api-keys) now has a back button (ArrowLeft + "Back" label) matching the style used on the admin and help pages
v0.18.0

Security and reliability improvements.

Changes

Technical security details are not published here.

v0.17.0

Security and reliability improvements.

Changes

Technical security details are not published here.