Update released
Right after the CSV import release, we kept polishing the product backlog — both how it feels in your hands and how the machine room behaves under load. This release wraps up that round.
⚡ The product backlog list feels noticeably lighter
We added three composite indexes covering the queries the product backlog list issues, and the server’s default-sort no longer needs an extra pass to reorder rows. The bigger your project’s PBI count, the more you’ll feel it.
While we were there, we also cleaned up the loading window: you now see a row skeleton (faintly drawn placeholders) during the brief wait on initial mount and tab switches. Before, a “zero rows” overlay could flash through that gap — especially visible under real-world network latency. That ghost flash is gone.
🎯 The Incomplete tab actually returns only incomplete items
If you selected the Incomplete tab on the product backlog list, completed PBIs could occasionally sneak in. The tab selection wasn’t always pushed down to the server-side filter; now it always is. You can focus on incomplete work without second-guessing the list.
The “refinement candidates” widget on the dashboard now applies the same server-side filter: candidates are pulled from the incomplete set directly, so high-volume projects don’t silently drop incomplete PBIs out of view.
🧭 Completed-epic cards hide on projects with Epic turned off
The “Completed epics” card on the stats dashboard and the “Achieved epics” card on the overall stats detail page no longer render for projects where the Epic feature is off.
The UI had been hiding adjacent sections already, but a render-timing window could still flash the card, and the underlying data was readable through other paths. Now both the display and the data stay locked to projects with Epic on.
🛡 Removed a misleading suffix on completed rows
We dropped the “PBI-XXXXXX” suffix that appeared next to completed items. It looked like a sequential ID, but it was actually pulled from the tail of an internal identifier and could happen to match an adjacent row by coincidence. To prevent misreads, we removed the display entirely.
The “N days ago completed” relative timestamp on the Completed tab is also gone. Editing a completed PBI used to silently rewrite that value, so it looked authoritative but could quietly drift. “When did this finish” is now left to the Sprint column, which carries that meaning honestly.
🔒 Stricter public-redirect targets
We tightened the redirect handling around login. The public host and HTTP/HTTPS scheme are now pinned server-side, so a spoofed header can no longer relocate users to an attacker-controlled domain. A rare case where an internal port number could leak into the redirect URL is also resolved.
🧱 A calmer machine room — explicit DB connection and request-timeout limits
To keep heavy spikes (like CSV imports) from squeezing the shared database connection budget, and to prevent long-hanging requests from holding server resources, we’ve placed explicit upper bounds:
- The number of DB connections held per API instance is now externalized to environment variables, and the server fails fast on startup if values are unset or invalid (so the safety net can’t be silently disabled by misconfiguration).
- GraphQL requests have a 30-second timeout. Exceeding it returns a dedicated error code distinguishable from authentication errors. Real-time subscription connections are exempt and continue to stay open for long sessions, as before.
- We’ve also pinned HTTP server read/write timeouts to harden against Slowloris-style TCP resource exhaustion.
Normal-load response times (CSV import of 1,000 rows typically completes in 5–10 seconds) are unaffected.
📦 Security-advisory dependency updates
We’ve updated next, mermaid, ws, protobufjs, postcss, and brace-expansion to their advisory-patched versions. No user-facing functional change — just keeping pace with the upstream fixes.
📮 Contact us
If you have any questions or feedback, please don’t hesitate to reach out.
- ✉️ Email: info@on-your-side.llc