← Home

Changelog

Every shipped change, newest first. Sourced from CHANGELOG.md in the repo.

  1. 2026-06-18

    Fix

    • ·Preset-Laden überträgt jetzt den Effekt-Typ ans Gerät (#80). Beim Laden einer .prst-Datei – und beim Speichern in einen Slot – sendete der Editor nur Toggle, Parameter und Author per USB-MIDI, aber nie den Effekt-Typ selbst (SysEx sub=0x14). Das Gerät behielt dadurch seinen zuvor geladenen Algorithmus pro Block, sodass Parameter und An/Aus-Zustand auf dem falschen Effekt landeten (die App zeigte z. B. „UK 800", während das Gerät noch „Tweedy" hatte und keine Werte übernahm). Beide Sync-Pfade senden jetzt pro Block in der Reihenfolge Effektwechsel → Parameter → Toggle, mit kurzer Settling-Pause, damit das Gerät den Algorithmus umschalten kann, bevor die Parameter ankommen.
  2. 2026-05-19

    Security

    • ·Admin-Flag wird auf allen öffentlichen Read-Paths enforced. Gallery, /api/share/[token], /share/[token]/download, /share/[token]/json und Sitemap filtern jetzt zusätzlich auf flagged: false. Bis hierher konnte ein admin-geflaggtes Preset weiter ausgeliefert und von Googlebot gecrawlt werden — Moderation entzieht Inhalte jetzt tatsächlich.
    • ·fast-xml-builder HIGH-Advisory geschlossen(GHSA-5wm8-gmm8-39j9, CVSS 6.1) durch npm update @aws-sdk/client-s3. Erreichte prod via @aws-sdk/xml-builder.
    • ·Admin-PATCH-User akzeptiert keine Email-Änderung mehr. Bisher konnte ein kompromittierter Admin-Account Victim-Emails überschreiben und sofort einen Password-Reset triggern → Account-Takeover. Email-Änderungen brauchen jetzt einen Out-of-Band-Weg.
    • ·Avatar-Upload gehärtet: Magic-Byte-Probe (JPEG/PNG/WebP Signaturen), limitInputPixels: 25 M und try/catch um sharp() — eine PNG-Bombe oder umbenannte Binärdatei erzeugt jetzt 400 statt 500 mit CPU-/RAM-Spike.
    • ·Avatar-Cache immutable entfernt(Cache-Control: public, max-age=3600). Eine Admin-User-Löschung wirkt jetzt innerhalb einer Stunde an jedem Cache-Layer.

    Fix

    • ·Middleware-Auth-Guard erkennt pt-BR. Die Regex (de|en|es|fr|it|pt) war beim Locale-Add nicht mitgezogen worden, sodass /pt-BR/profile & /pt-BR/admin den Cookie-Presence-Check der Middleware übersprangen. Page-Level-validateSession hat es abgefangen — kein Datenleck —, aber Defense-in-Depth weg. Regex wird jetzt aus LOCALES generiert; Test stellt sicher, dass jeder Eintrag der LOCALES-Tuple gematcht wird.
    • ·/api/admin/comments nutzt withAdminAuth-Wrapperstatt manuellem try/catch(requireAdmin) — konsistent zu allen anderen /api/admin/* Routen.
  3. 2026-05-19

    Features

    • ·30 s Audio-Schnipsel pro Preset. Owner können beim Save-to-Gallery oder nachträglich auf /share/[token] ein MP3- oder M4A/AAC-File (max 30 s, max 2 MB) anhängen. Player erscheint auf der Share-Page (voll), im Homepage-Featured-Block und auf jeder Gallery-Card (Icon). Nur ein Player spielt gleichzeitig — Klick auf einen Card-Play pausiert alle anderen.
    • ·Admin-Audit für fremdes Audio. Wenn ein Admin Audio eines fremden Presets ersetzt oder löscht, wird die Aktion mit Reason (bei Delete) im AdminAction-Log auditiert.

    Storage / Validation

    • ·Neuer Garage S3-Bucket gp200editor-audio. Server prüft Mime + Magic Bytes + Größe (≤ 2 MB) + Dauer (≤ 30.5 s via music-metadata) vor jedem S3 PUT.

    Schema

    • ·Drei neue nullable Felder auf Preset: audioKey, audioMimeType, audioDurationMs.
  4. 2026-05-19

    Features

    • ·Brasilianisches Portugiesisch (pt-BR) als 7. Locale. Vorher war pt.json faktisch brasilianisch übersetzt (Salvar/Senha/usuário/arquivo); der Inhalt wandert nach pt-BR.json und steht jetzt brasilianischen Nutzern als eigenes Locale mit 🇧🇷-Flag im Switcher zur Verfügung. pt.json wurde mit ~175 gezielten Substitutionen auf echtes europäisches Portugiesisch konvertiert (Guardar/Palavra-passe/utilizador/ficheiro/Iniciar sessão/A guardar/A carregar/Ligar/Registo/Rastreio).

    i18n-Polish (Sprach-Review aller 7 Locales)

    • ·DE/IT: 4 Admin-Buttons (Unpublish/Republish/Flag/Unflag) waren noch englisch — jetzt übersetzt.
    • ·DE: home.featured.title hatte den „Featured ·"-Präfix verloren — wieder dran.
    • ·IT: home.featured.title hatte „Top Rated" englisch — jetzt „Più votati".
    • ·FR: tu/vous-Inkonsistenz behoben — drei FAQ-Antworten + zwei Tooltips + die Verify-Confirm-Seite waren in vous, während die App sonst tu nutzt. E-Mail-Templates bleiben bewusst in vous (formaler Kontext).
    • ·PT-BR: Ein EU-PT-Slip in gallery.rate.ownPresetTooltip korrigiert.

    Fix

    • ·Übersetzungs-Skript-Bug korrigiert. Beim BR→EU-Sweep der legal.privacyOverviewText wurde „salvo quando exigido por lei" (im Sinne von „außer wenn") fälschlich zu „guardado quando exigido por lei" umgeschrieben. Zurückgedreht.
  5. 2026-05-19

    Security

    • ·Comments leak after un-publish — fixed. GET /api/presets/[id]/comments now refuses to return the thread when the preset has been made non-public or flagged. POST top-level + Reply gained the same gate (Reply previously checked neither). Anyone who had the preset id from a previous public link can no longer continue reading a thread the author tried to retract.
    • ·Featured-Preset Sybil-Dampening verstärkt. Bayes-Konstante m von 5 auf 10 — eine einzelne 5★-Bewertung von einem Accomplice-Account scoret jetzt nur noch ~4.09 (statt 4.17) und schiebt sich nicht mehr vor etablierte Presets mit echtem Rating-Verlauf.

    Bugfixes

    • ·Inline-Rating Optimistic-UI ohne Rollbackbei fehlgeschlagenem POST blieb die UI bei der Phantom-Bewertung. Snapshot+Restore + errorTooltip-Toast.
    • ·Comment-Textarea verlor Inhalt bei 429/Auth-FailCommentForm clear jetzt nur bei Success; bei Fehler steht der Text zum Retry da.
    • ·CommentSection swallowed 401/5xx silentlyseparate Toasts für Rate-Limit, Session-Expired und generischen Fehler.
    • ·Gallery-Rating Page 2+ zeigte falschen Countbereits-bewertete Presets jenseits der ersten SSR-Page bekamen existingRating=0, was bei Re-Rating zu Phantom-Counts führte. Session-Lookup zog ans /api/gallery-Endpoint, jede Card trägt jetzt korrekte Rating-Context.
    • ·AdminCommentsTab hatte keine Pagination-UIalle Comments jenseits der ersten 50 waren unerreichbar. Load-More-Button + In-Flight-Guard.

    UI / i18n

    • ·Confirm-Dialog vor User-Soft-Delete. Klick auf „Delete" beim eigenen Kommentar öffnet jetzt einen Bestätigungsdialog (Soft-Delete ist nicht reversibel — body wird genullt). Admin-Hard-Delete behält seinen separaten Reason-Dialog.
    • ·Drei hardcoded englische Strings korrigiert(Comments Header, Email verification required, Admin-Cancel-Button) — jetzt in allen 6 Locales übersetzt.
    • ·Toter i18n-Key entfernt(comments.adminDeleteReasonLabel — Admin-Tab nutzt admin.comments.hardDeleteReasonLabel).

    Schema / Performance

    • ·Index Comment(createdAt DESC)die Admin-Moderation-Liste sortiert ohne presetId-Filter; der bisherige Compound-Index half nicht. Cheap forward-looking change.
    • ·Shared commentSerializerAvatar-Mapping (avatarKey → /api/avatar/<key>) lebt jetzt in src/lib/commentSerializer.ts; PATCH gab bisher den Raw-avatarKey zurück, alle anderen Routes serialisierten zu avatarUrl. Inkonsistenz behoben.
  6. 2026-05-18

    Features

    • ·Inline-Rating in der GalleryBewertungen können direkt auf der Gallery-Liste abgegeben werden. Anonyme Klicks zeigen einen Tooltip mit Login-Link; eigene Presets sind erwartungsgemäß nicht bewertbar.
    • ·Kommentare auf Share-PagesPlaintext-Kommentare mit 1-Level-Threading (Top-Level + Reply), max 1000 Zeichen, URLs werden automatisch verlinkt (rel=nofollow). Verifizierte User können kommentieren, jederzeit editieren und soft-löschen. Soft-Delete zeigt einen Platzhalter, Replies bleiben sichtbar.
    • ·Admin-Moderation für KommentareNeuer Tab im Admin-Dashboard: Liste der letzten 50 Kommentare. Hard-Delete erfordert einen Grund (5–200 Zeichen) und wird im AdminAction-Log auditiert; kaskadiert auf Replies.
    • ·Featured Preset auf der StartseiteBayes-Average (m=5, C=globaler Durchschnitt) über alle Presets mit Ratings der letzten 30 Tage. Hero-Block mit Signal-Chain-Grafik (Amp/Cab-Realnamen), Sternebewertung, Beschreibung und den 3 neuesten Kommentaren. Fallback auf All-Time-Best wenn das 30-Tage-Fenster leer ist.
    • ·FX-Loop SEND/RETURN editorneuer Insertion-Point-Editor analog zum offiziellen Valeton GP-200 Editor. Pfeile ( SEND, RETURN) lassen sich per Drag & Drop oder Tastatur (←/→) zwischen den 11 Effekt-Slots (PRE…VOL) verschieben. Bypass-Anzeige wenn SEND === RETURN. ARIA-konform (role="slider", vollständige Screenreader-Labels in allen 6 Sprachen).
    • ·Live MIDI für FX-LoopSEND/RETURN-Bewegungen werden bei verbundenem Gerät sofort als SysEx sub=0x20 ans Pedal geschickt. Push-Constraint (SEND ≤ RETURN) feuert bei Bedarf zwei Messages, um beide Pfeile synchron zu halten.
    • ·.prst Codec für FX-LoopSEND/RETURN werden an Bytes 0x92/0x93 (innerhalb des Routing-Section-Headers) gelesen und geschrieben. Round-Trip-stabil, inkl. rawSource-basierter Presets.

    Schema

    • ·Neue Tabelle Commentmit Self-FK für 1-Level-Threading (parentId nullable), Soft-Delete-Marker (deletedAt/deletedBy), Cascade-Delete bei Preset/User/Parent-Removal.

    Protocol

    • ·sub=0x20 Reorder vs. FX-Loop Move differenziertdecoded[14]/[15] halten SEND/RETURN (vorher fälschlich als Konstanten markiert); decoded[27] ist ein Diskriminator: 0x08 = SEND verschoben, 0xBA = RETURN verschoben, 0x44 = reine Routing-Umordnung. Reverse-engineered aus zwei USB-MIDI-Captures (2026-05-18), byte-für-byte verifiziert.
  7. 2026-04-11

    Features

    • ·PRST Library + JSON API145 curated Valeton GP-200 presets ingested from guitarpatches.com, each served with real-world amp/cab names (e.g. "Marshall® JCM800", "Fender® '65 Twin Reverb"). New /api/share/[token]/json endpoint serves a round-trip JSON document with signal chain, highlights, and raw preset data.
    • ·SEO-crawlable signal chain on share pagesevery share page now renders the full effect chain as semantic HTML with both Valeton fake names and real-world brand names. Google rich results supported via schema.org/Product markup per preset.
    • ·Amp category landing pages64 new pages at /[locale]/amp/[slug] (e.g. /en/amp/marshall-jcm800, /en/amp/mesa-boogie-dual-rectifier-modern-mode), each listing all presets using that amp. Pre-rendered for both locales.
    • ·hreflang + canonical + JSON-LDevery share page gets <link rel="alternate" hreflang> for de/en/x-default, <link rel="canonical">, schema.org/Product JSON-LD with auto-extracted brand, Open Graph + Twitter Card metadata.
    • ·Dynamic Open Graph images1200×630 PNG per share page generated on demand via Next.js 15 ImageResponse, showing preset name + amp + cab real names with Preset Forge branding.
    • ·Ingest pipelinenew scripts/ingest-presets.ts CLI with four source adapters: guitarpatches.com (polite 10s crawl delay), GitHub Code Search, Valeton factory folder, and a manual curated-URL list. Automatic validation (TSRP magic + checksum), dedup by source URL + sha256 content hash, auto-generated descriptions + tags.
    • ·Sitemap coverage586 URLs including 128 amp category pages, 450 preset URLs (de/en/json), and 8 static pages. Force-dynamic so newly-ingested presets become indexable without redeploying.

    Bugfixes

    • ·Decoder NaN handlingreal .prst files from guitarpatches.com carry NaN bytes in unused effect params; the decoder now substitutes 0 so validation doesn't drop ~10% of the library.
    • ·Factory-size checksum1176-byte factory presets no longer trip the out-of-bounds read at offset 0x4C6.
    • ·Description generatorgenerateDescription no longer produces "cabinet cabinet" when the real name already contains the module label.
    • ·metadataBaseOpen Graph image URLs now resolve to https://preset-forge.com/... instead of http://localhost:3000/....

    Local CI

    • ·GitHub Actions removedreplaced with scripts/local-ci.sh running lint + typecheck + vitest + next build locally. New npm run ci entry point.

    Performance + Security (pre-library)

    • ·Paginated GET /api/presets and /presets SSR page (default 100, max 500) — previously unbounded.
    • ·Capped sitemap.xml query at 10 000 rows with orderBy: updatedAt desc.
    • ·Memoized getEffectParams lookup in EffectParams.
    • ·Middleware regex compilation moved to module scope (single pattern instead of three per request).
    • ·next-intl upgraded to 4.9.1 (GHSA-8f24-v5vv-gm5j open redirect).
    • ·DELETE /api/admin/users/[id] refuses to delete admins — forces an auditable PATCH demotion first.
    • ·Per-IP rate limit on /api/auth/forgot-password alongside the existing per-email limit, closing the account enumeration side-channel.
  8. 2026-03-24

    Features

    • ·Live param updates from hardwareWhen the user turns knobs on the GP-200 (Volume, Gain, Presence, Bass, Middle, Treble), sliders update in real-time in the webapp. New sub=0x10 D→H knob notification parsing with discriminator (bytes[29:37]=all zeros = knob, otherwise = toggle).
    • ·AMP Head PanelNew AmpHeadPanel component showing the AMP block's main knobs (Gain/Presence/Volume + Bass/Middle/Treble) prominently at the top of the editor. Auto-detects AMP model from preset.
    • ·Collapsible head sectionsAMP Head, Preset Info + Patch Settings, and Controller sections can be independently toggled via a button bar at the top of the editor.
    • ·Auto-load preset namesAfter device connect, all 256 preset names load automatically in the background. Previously required opening the slot browser first.

    Bugfixes

    • ·Correct initial slot detectionState dump decoded[8:10] LE16 contains the active slot. Previously always returned slot 0. Verified via captures 084047 (slot 13/04-B) and 084156 (slot 0/01-A).
    • ·Bank switching on device slot changeWhen device changes to a slot in a different bank, editor now pulls the entire new bank and switches tab. Previously loaded wrong preset into wrong tab.
    • ·MIDI operation serializationBackground loadPresetNames no longer conflicts with pullPreset/pushPreset. Added pauseNameLoading() that aborts name loader before any pull/push/write operation.
    • ·Nibble-encode slot for slots > 127SysEx data bytes must be 0-127. Slot 252 (64-A) was sent as raw 0xFC (invalid). Now nibble-encoded at [25:26] in buildPresetChange and decoded in onMidiMessage.
    • ·Status bar shows editor preset namecurrentPresetName from editor takes priority over stale cached presetNames.
    • ·ControllerPanel visible when disconnectedShows at 50% opacity instead of hidden.
    • ·Cache-Control no-store in dev modePrevents browser from serving stale JS after code changes.

    Protocol

    • ·State dump header decodeddecoded[0:10]: constants + active slot at [8:10] LE16. Verified via captures 084047 (slot 13/04-B) and 084156 (slot 0/01-A).
    • ·D→H Knob notification (sub=0x10) byte[22]=block, byte[24]=param, [29:37]=zeros discriminator, [37:45]=nibble float32 value. AMP block=3: param 0=Gain, 1=Presence, 2=Volume, 3=Bass, 4=Middle, 5=Treble.
  9. 2026-03-23

    Features

    • ·EXP controller assignmentsHardware-verified EXP1/EXP2 parameter selection + min/max via SysEx (sub=0x14 + sub=0x18).
    • ·NAM upload analysisCaptured IR upload protocol (sub=0x1C, multi-chunk).
    • ·Patch SettingsVOL/PAN/Tempo live editing via sub=0x10.

    Protocol

    • ·Save-to-Slot sub-slot indexdecoded[4] = A(0)/B(1)/C(2)/D(3). Without this, save always wrote to slot A.
    • ·Effekt-Change-Response (sub=0x0C) Block index, effect ID decoded from D→H notification.
    • ·EXP/Controller AssignmentNavigation (sub=0x18) + Min/Max write (sub=0x14), hardware-verified.
Changelog — Preset Forge