It finally happened: the Ticket Zoom history and links tabs agreed to show up to work regardless of which database is on-call. No more blank divs. No more 500s. Just crisp HTMX fragments rendered through Pongo2, real history rows captured for every new action, and a little bit of tasteful sarcasm.
Here’s the kind of snapshot we expect to see going forward:

What Shipped
- History tab learns to read the room: We now join against
article_data_mimeso imported tickets bring their original subjects along. PostgreSQL always behaved, but MariaDB used to respond with “who?"—problem solved. - History recorder goes hands-free: The shared
history.Recordernow fires for ticket creation, notes, status flips, pending timers, priority moves, queue moves, ownership changes, merges—you name it. Every fresh action leaves a breadcrumb without the handlers rolling their own SQL. - Links tab makes peace with placeholders: The repository duplicates the ticket ID argument when
database.ConvertQueryexpands$1to multiple?markers, so MariaDB stops throwing tantrums about math homework. - Pongo2 all the way down: Both fragments render exclusively through the shared Pongo2 renderer, matching our “no html/template” policy and keeping helper functions consistent.
- Better empty states: When there’s nothing to show, we say so plainly instead of pretending the tab doesn’t exist. Honesty is still the best UX.
Why It Matters
Agents importing tickets from Znuny now see the actual story (subjects, queues, priorities) without diving into the database. Meanwhile, operations teams can flip between PostgreSQL and MariaDB without encountering “expected 3 arguments, got 2” in their logs. That’s one less excuse to avoid running make restart. And because every new action writes a ticket-history row automatically, the timeline stays truthful even when agents bounce between tabs, channels, or even database engines.
What’s Next
Now that every action is recorded and rendered, it’s time to make the timeline smarter: grouping rapid-fire events, layering instant HTMX refreshes after updates, and wiring up filters so agents can zero in on the signal. Harmony achieved—next up, harmony with a beat.
Bonus Track: Database Détente
While the tabs were learning to harmonize, the test harness did too. The MariaDB container now runs the same integration fixtures as PostgreSQL (schema/seed/test_integration*.sql), so the API and HTMX suites no longer behave like two different bands. make test-db-up spins up either engine with identical seed data, which means every ticket, queue stat, and seeded test user shows up no matter which driver is on deck. Flip the TEST_DB_DRIVER environment variable and you get the same results—just a different accent. Bonus perk: the password-reset tooling mirrors the same split, so make reset-password delegates to driver-aware helpers and keeps .env secrets in sync no matter which database takes the solo.