v0.5.1
A usability and hardening pass: make the dashboard legible on first run, scope MCP setup to the project it belongs to, and close two local-attack surfaces.
Added
- First-run onboarding banner under the header: the 3-minute interactive tour, a one-click sample project, and the guide. Persists per browser and retires once the tour is completed or dismissed.
Changed
- Project-first navigation. The header surfaces a single destination, Projects. The MCP playground moved to a per-project page (
/projects/[id]/mcp), reached from an MCP button on the project header, auto-scoped to that project. The old/mcpredirects to the project list. - Plainer first-run copy and clearer empty states on the Projects and Features lists.
- Human-facing docs no longer use em dashes.
Fixed
- MCP page load time.
get_project_aggregateloads features concurrently (was N+1 sequential), tool examples stream in off the main thread, and JSON is formatted only on expand. Skeleton/spinner loaders instead of a blank page.
Security
- DNS-rebinding / CSRF hardening on the default loopback dashboard (always on): loopback
Host+ same-originOriginrequired, rebinding pages fail closed with403. - Path-traversal fix on bundle import:
../in bundle ids can no longer escape the snapshot tree; malformed bundles are rejected with400.
Full changelog: https://github.com/lyriks-io/unspaghettit/blob/main/CHANGELOG.md