This release includes 1 breaking change for platform teams planning a safe upgrade.
✓ No known CVEs patched in this version
Topics
+8 more
Affected surfaces
ReleasePort's take
Light signalRelease v0.8.1 fixes several API endpoints that previously returned 500 errors for softβdeleted objects, now returning typed notβfound responses; it also improves error messaging in toasts and refactors permission checks into a unified matrix.
Why it matters: Bugfixes eliminate 500 crashes on getContent, querySessionDetail, attribute/event mutations, and localization deletions, directly improving reliability for developers and SREs. The refactor consolidates 93 scattered decorators into a single ROLE_CAPABILITIES matrix, simplifying permission management.
Summary
AI summaryUpdates π Fixes, Capability.X, and capability across a mixed release.
Changes in this release
| Type | Severity | Summary | CVE |
|---|---|---|---|
| Feature | Medium |
Error toasts now display the server's actual error reason instead of static "Failed to X". Error toasts now display the server's actual error reason instead of static "Failed to X". Source: llm_adapter@2026-05-24 Confidence: high |
β |
| Feature | Medium |
Save dialogs confirm success with a green toast on success and stay open on failure, preserving user input. Save dialogs confirm success with a green toast on success and stay open on failure, preserving user input. Source: llm_adapter@2026-05-24 Confidence: high |
β |
| Feature | Medium |
Settings navigation and routes hide or redirect based on actual user capabilities from a single roleβcapability matrix. Settings navigation and routes hide or redirect based on actual user capabilities from a single roleβcapability matrix. Source: llm_adapter@2026-05-24 Confidence: high |
β |
| Bugfix | Medium |
Viewing a soft-deleted content no longer 500s; returns typed not-found response. Viewing a soft-deleted content no longer 500s; returns typed not-found response. Source: llm_adapter@2026-05-24 Confidence: high |
β |
| Bugfix | Medium |
Viewing a soft-deleted session no longer 500s; returns typed not-found response. Viewing a soft-deleted session no longer 500s; returns typed not-found response. Source: llm_adapter@2026-05-24 Confidence: high |
β |
| Bugfix | Medium |
Duplicate event/attribute names now return typed error E0048 instead of generic 500. Duplicate event/attribute names now return typed error E0048 instead of generic 500. Source: llm_adapter@2026-05-24 Confidence: high |
β |
| Bugfix | Medium |
Deleting a localization with version data no longer 500s; cascades deletes in one transaction. Deleting a localization with version data no longer 500s; cascades deletes in one transaction. Source: llm_adapter@2026-05-24 Confidence: high |
β |
| Bugfix | Medium |
Step / version-localization mutations stop bouncing on soft-deleted content; nullβguards before reading editedVersionId. Step / version-localization mutations stop bouncing on soft-deleted content; nullβguards before reading editedVersionId. Source: llm_adapter@2026-05-24 Confidence: high |
β |
| Refactor | Medium |
Permission surface refactored to a single ROLE_CAPABILITIES matrix and unified PermissionGuard; replaces 93 scattered decorators. Permission surface refactored to a single ROLE_CAPABILITIES matrix and unified PermissionGuard; replaces 93 scattered decorators. Source: llm_adapter@2026-05-24 Confidence: high |
β |
Full changelog
This release introduces a capability-based permission system that runs from a single role-capability matrix on the server through to the navigation gating in the web app. User-visible deltas are mostly about feedback β error toasts now show the server's
actual reason, save dialogs confirm success and keep your input on failure, and a handful of admin pages no longer crash when you open a soft-deleted record. Under the hood, 11 per-module permission guards collapse into one capability guard backed by a
93-endpoint authorization test matrix.
What's Changed
π‘οΈ Settings nav and routes match real permissions
VIEWER members previously saw greyed-out menu items and pages the backend would reject anyway (Themes, Integrations, API Keys, Team management). The web app now hides or redirects based on the user's actual capabilities, derived from a single
server-defined role-capability matrix. A VIEWER lands on a cleaner Settings shell with only what they can use.
π¬ Error toasts show the server's actual reason
A handful of admin actions (End / Delete session, several integration and API-key flows) used to swallow the server's error and show a static "Failed to X" string. They now surface the real reason β "You do not have permission to access this project",
"A resource with this identifier already exists", and so on. The destructive toast shape is also unified across the app, dropping the odd "Error" headers that appeared in five places and nowhere else.
β Save dialogs confirm success and retain input on failure
Create / Update Attribute and Event dialogs used to close silently on success (no green toast) and also close on failure (eating the user's input). They now show a "successfully updated" toast on success, stay open on failure so you can retry without
retyping, and the submit button no longer gets stuck loading on the failure path.
π Fixes
- Viewing a soft-deleted content no longer 500s.
getContentreturned a generic 500 when the underlying row was soft-deleted; it now returns a typed not-found response the UI can render. - Viewing a soft-deleted session no longer 500s. Same shape for
querySessionDetail. - Duplicate event / attribute names return a typed error. Creating a row with a duplicate
codeNamepreviously leaked Prisma'sP2002as a generic 500; it now returnsE0048(ResourceAlreadyExistsError). - Deleting a localization with localized version data no longer 500s. The delete now cascades
VersionOnLocalizationrows in one transaction. - Step / version-localization mutations stop bouncing on soft-deleted content.
contentVersionIsEditablenull-guards before readingeditedVersionId.
π οΈ Under the hood
The server's permission surface was refactored end-to-end. The bullets above are the visible deltas; here's the architectural shape behind them:
- A single
ROLE_CAPABILITIESmatrix in@usertour/constantsis the source of truth for "what each role can do". The previous pattern of 93@Roles([VIEWER, ADMIN, OWNER])decorators scattered across resolvers is replaced by
@RequirePermission(Capability.X)plus onePermissionGuardthat reads the matrix. Adding a new role is now one matrix row, not 93 decorator edits. - 11 per-module guards (content / environments / biz / integration / localizations / attributes / themes / events / analytics / team / projects) collapse into one
PermissionGuardwith a scope-resolver registry. Each resolver registers how to derive
projectIdfrom its args (e.g.contentId β content.projectId), so the guard's "is this user a member of the resource's owning project" check is one code path. UserOnProject.capabilities: [String]is now part of the GraphQL schema. The web app'suseAppContext().can(capability)reads from this array instead of re-deriving from the role string, so frontend and backend gates can't drift.- A 93-endpoint Γ 5-role authorization test matrix lives in
test/e2e/endpoints.tsand drives two surfaces:permission.e2e-spec.ts(jest, 312 deny-direction assertions + cross-project IDOR coverage) andtest/smoke/spot-check.sh(env-driven bash
tool, 558-row diagnostic against a seeded fixture). Adding a new role-gated endpoint is one row in the table; both surfaces pick it up. - Test factories adopt the outline-style "recursive override" shape β
buildX(prisma, overrides?)auto-builds missing parent FKs, so a new spec can doawait buildStep(prisma)and get a fully-wired project β environment β content β version β step
chain in one line.
Full Changelog: https://github.com/usertour/usertour/compare/v0.8.0...v0.8.1
Breaking Changes
- Permission guards replaced by a single `Capability`βbased system; all perβmodule decorators (`@Roles`) removed in favor of `@RequirePermission(Capability.X)`.
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About usertour
Usertour is an open-source user onboarding platform. It allows you to create in-app product tours, checklists, and surveys in minutesβeffortlessly and with full control.The open-source alternative to Userflow and Appcues
Related context
Related tools
Beta — feedback welcome: [email protected]