Back to blog
✏️ v0.8.0 May 19, 2026

v0.8.0 — Edit comments + notes, agent-forward inbox, multi-scope landing project

Edit posted comments and notes (with distribution-aware '(edited)' indicator + reply-locks). Image attachments render inline with a fullscreen lightbox. Project-level role overrides + Agent flag now gate handler-only features per project, not just by global role. Agent-forwarded emails attribute the ticket to the original sender. Multi-scope inboxes get a pinned default landing project. Plus auto-resume on awaiting_input, lifetime AI token ledger, custom daily-digest hour.

v0.8.0 is a thread-and-inbox release. It fixes the small frictions that were quietly accumulating: comments you can’t fix after posting, vendor emails you forwarded into Resolvd that mis-attributed the ticket to you, a shared inbox that dropped prefix-less mail on the floor.

Edit a posted comment — but only until someone replies

Author can edit their own comments; Admin / Manager can edit anyone’s. System comments and inbound vendor replies stay locked because the timeline integrity matters more than fixing a typo on something that’s already in the audit trail.

The lock fires the moment a newer non-system comment lands on the same ticket. Quick correction window stays open until the next reply, then the comment is frozen — post a follow-up to communicate the correction instead of stealth-editing context the next reader was responding to.

Edit comment composer

Editing clears any AI provenance on the comment (it’s no longer purely AI output once a human revises it) and writes a comment_edited audit entry.

The (edited) indicator is distribution-aware

If you post a comment, notice a typo five seconds later, and edit it before anyone has seen the original — no (edited) badge. The original never escaped, so there’s nothing to label as changed.

Once anyone other than the author has either (a) opened the ticket thread or (b) received a notification email about the comment, a per-comment distributed_at is stamped. From that point on, edits surface the (edited) badge.

The logic ignores vendor outbound — vendor recipients are out of band and the badge is a UI cue for internal readers. Vendor outbound is also not re-fired on edit: the vendor already has the original email; if your correction needs to reach them, post a follow-up comment.

Notes can be edited too

Same pattern, simpler rules. Notes never fan out to vendors or submitters, so there’s no distribution gate — any note edit always shows (edited). Author or Admin / Manager can edit; the original author gets the action by default.

Image attachments — inline preview + lightbox

Image attachments now render as thumbnails inline on comments and on the Attachments tab. Click any thumbnail to open a fullscreen lightbox with filename, Download button, and Esc / click-outside / × to close.

Image lightbox

Non-image attachments keep their existing list / chip rendering. The lightbox uses the already-existing /api/attachments/:id/view endpoint — no new server work, just a UI that finally exercises it.

Project-level handler access — notes + Agent flag

The Project member panel previously offered role overrides Admin / Submitter / Viewer. Manager and Tech are now valid overrides too, matching the global role list. Combined with the per-project Agent flag, you can express:

  • A Submitter who happens to be a Tech-tier handler on Project A.
  • A Tech globally who shouldn’t pick up tickets on Project B (toggle Agent off there).
  • A Submitter who’s manually flagged Agent on a project so they receive @agents mentions and can post handler notes there.

The Notes tab access used to be global Admin / Manager / Tech only. It now also opens to project members with a handler role override or the Agent flag on the ticket’s project. The frontend tab visibility is driven by a server probe, so unauthorized viewers don’t see the tab at all.

Setting role override to Tech auto-ticks Agent (with the caveat that you can untick afterwards if a Tech on this project shouldn’t get assignments).

Project member role override + agent

Agent-forwarded email → original sender attribution

Internal agents have long been forwarding stuff to the helpdesk inbox. Until v0.8.0, those forwards attributed the ticket to the forwarding agent — the original sender disappeared.

Resolvd now unwraps standard forward markers (Begin forwarded message:, Forwarded message, Original Message), extracts the inner From: header, and:

  • Treats the inner sender as the submitter (submitted_by).
  • Auto-assigns the ticket to the forwarding agent (matched against the outer sender’s user record).
  • Audits both the creation + the auto-assign with Created via forward from <agent> on behalf of <user>.

#PREFIX in the outer subject still routes the project. Inner sender must already be an active internal user; external-sender shadow contacts are a follow-up.

The detection requires the outer sender to be an internal Resolvd user, which guards against external senders spoofing a “forwarded” payload to impersonate someone.

Multi-scope inbox — pinned default landing project

A shared inbox scoped to several projects previously dropped prefix-less mail into the manual queue. Now Admins can pin a default landing project per inbox: prefix-less mail auto-routes there instead.

Single-scope inboxes still auto-route as before; the picker only appears when an inbox has 2+ approved + recv-enabled scopes. Required project must be one of those scopes — if a later scope removal makes the default invalid, lookup degrades to “no route” gracefully.

Default landing project picker

awaiting_input → in_progress on inbound reply

When a vendor reply lands on a ticket sitting in awaiting_input, Resolvd now auto-transitions the ticket to in_progress and audits Auto-resumed: inbound reply received while awaiting input. Mirrors the existing gratitude-reopen path on resolved tickets, minus the gratitude filter — any reply unblocks a waiting ticket.

Works on both the tryAutoReply path (matched inbound replies on existing tickets) and the manual-queue match path (admin matches a queued email onto a ticket).

Lifetime AI token ledger

A small 3-cell card on Account → Preferences → AI Assist now shows your lifetime AI Assist usage: number of calls, total input tokens, total output tokens. Each cell is a SUM over the per-comment / per-ticket snapshots Resolvd already captured at apply time. Edits and deletes don’t subtract — the snapshot reflects what was actually consumed.

Only renders when the user has at least one AI call on record. Useful when you’re paying for your own API key and want to know the running total.

Daily digest delivery hour

email_digest=daily previously sent at 09:00 local. New per-user notification_digest_local_hour (0–23) lets each user pick when they want the daily digest. AccountPreferences exposes the selector only when you’ve picked the daily cadence.

Outbox cleanup

notification_outbox rows that sat unsent for >30 days are now hard-deleted on every flush tick. Backstops the “user toggles digest off after a row buffered” orphan case so the table stays bounded.

Build identity + manual update check

Self-hosters now have a way to tell at a glance what’s actually running and whether a newer release is out. Admin → System health gets a Build info card at the top showing the running version, short commit, and built-at timestamp.

Build info card

Backend Dockerfile reads APP_VERSION / APP_COMMIT / BUILT_AT build-args, exposed by a public GET /api/version (no PII; safe for health probes). A scripts/build-with-version.sh wrapper stamps the args from git describe --tags --always --dirty + short SHA + UTC timestamp so contributors get accurate values without manual fiddling.

The card has a Check for updates button that polls github.com/joshhearne/resolvd releases/latest and compares against the local semver. Reports one of:

  • Up to date with the latest release v0.8.0.
  • New release available: v0.9.0 — published 2026-06-12
  • You're ahead — pre-release or local build.
  • Couldn't reach GitHub: <error> (homelab / airgapped installs see this without consequence)

No background phone-home. The check fires only when an admin clicks the button. Airgapped installs never reach out unless someone asks them to.

Mobile-friendly Help page

The role-pill columns on the Help page’s Feature rows previously wrapped horizontally even on narrow viewports — squeezing long descriptions into skinny columns. Pills now stack vertically below 640px so the description text gets full width. Tablet+ keeps the original layout.

Smaller wins

  • VALID_ROLES on project members: Manager and Tech are now accepted (frontend offered them, backend rejected — straight bug fix).
  • Note mentions no longer accidentally stamp distributed_at on the comments table when a note id collides with a comment id (fixed via kind: 'note' on fanoutMention).
  • Help page documents all of the above with refreshed screenshots.

Upgrade notes

  • New columns: comments.edited_at, comments.distributed_at, ticket_notes.edited_at, email_backend_accounts.default_inbound_project_id. All IF NOT EXISTS, no manual migration needed.
  • One-time backfill on first startup: UPDATE comments SET distributed_at = created_at WHERE distributed_at IS NULL AND created_at < NOW() - INTERVAL '1 minute'. Ensures editing old comments still surfaces (edited).
  • No env var changes.

Full changelog on GitHub.