Skip to content

usertour

v0.8.1 Breaking

This release includes 1 breaking change for platform teams planning a safe upgrade.

βœ“ No known CVEs patched
Read the diff β†’ Tool health β†’ What is this tool? β†’

✓ No known CVEs patched in this version

Topics

announcements appcues chameleon checklist in-app nps
+8 more
onboarding pendo surveys tooltips tour userflow userpilot walkme

Affected surfaces

auth rbac

ReleasePort's take

Light signal
editorial:auto 10d

Release 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 summary

Updates πŸ› Fixes, Capability.X, and capability across a mixed release.

Changes in this release

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. getContent returned 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 codeName previously leaked Prisma's P2002 as a generic 500; it now returns E0048 (ResourceAlreadyExistsError).
  • Deleting a localization with localized version data no longer 500s. The delete now cascades VersionOnLocalization rows in one transaction.
  • Step / version-localization mutations stop bouncing on soft-deleted content. contentVersionIsEditable null-guards before reading editedVersionId.

πŸ› οΈ 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_CAPABILITIES matrix in @usertour/constants is 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 one PermissionGuard that 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 PermissionGuard with a scope-resolver registry. Each resolver registers how to derive
    projectId from 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's useAppContext().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.ts and drives two surfaces: permission.e2e-spec.ts (jest, 312 deny-direction assertions + cross-project IDOR coverage) and test/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 do await 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

Track usertour

Get notified when new releases ship.

Sign up free

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

All releases β†’

Related context

Earlier breaking changes

  • v0.8.3 Removes the insecure 'development-key-not-secure' fallback for ENCRYPTION_KEY; operators must set the env var explicitly.
  • v0.7.5 All 60 workspace packages move to @usertour/* from @usertour-packages/*

Beta — feedback welcome: [email protected]