Windshift 0.9.0 - "Sea Trials"
Windshift 0.9.0 makes the helpdesk a first-class part of the product. Service levels arrive with
metrics, goals, and working calendars. The support queue becomes a configurable workspace view with
live counts and bulk actions. Email intake is rebuilt around separate mailbox connections and
routing. Tickets can be merged and split, and portal customers can share requests across their
organisation.
The release also adds customer data export and retention-aware erasure, turns incidents into
work-item state, marks AI chat changes in history, moves workspace bundles and packs between
instances, makes navigation configurable, and speeds up large installations. Five rounds of release
bug hunting also closed a number of security issues before they shipped.
Highlights
Service levels
Service levels are here. Every item is evaluated as it changes, so SLA cycles start, pause, and stop
immediately, and breaches and warnings are delivered through Windshift's event system.
Workspace admins configure metrics, conditions, and goals under Service levels, using Windshift's
query language with validation at save time. Goals can be grouped by priority, and working calendars
define timezone, weekly hours, and holidays. Calendar changes preview their impact, and a running
cycle keeps the calendar it started with, so recalculation never rewrites history. Teams bind to
workspaces, and coverage gaps surface when a team's hours do not line up. Warning thresholds,
pause/stop/start rules, and on-demand recalculation complete the admin surface.
Items show an SLA panel, lists and boards carry SLA indicators, and a compliance report summarizes
completed, breached, and average cycles. SLA triggers and events work in automations and
notifications, and the configuration is available through API v2 and the ws CLI. Jira SLA
configuration and cycles import directly.
The support desk comes together
Support queues become a real workspace view. Queues are scope-aware and configurable: build them
with a query-language filter builder, route by collection, choose which columns show, and see live
counts for unassigned, team-owned, and waiting tickets. Bulk actions are supported, and the queue is
a toggleable navigation entry rather than a fixed tab.
Agents get canned responses to insert into replies, helpdesk triggers and customer actions in the
automation editor, and a customer context sidebar on external requests. Request participants appear
only on external requests, and comments and attachments can be marked internal so they never reach a
customer.
Support metrics arrive as dashboard and workspace widgets: first response, resolution time, reopen
rate, volume, backlog trend, and SLA compliance. First response counts the first public agent
comment, and resolution time is recorded once, on first close. A built-in helpdesk pack provisions
the whole configuration in one apply. Zammad users also get a support overview with ticket history
and status counts (@Optic00,
#306).
Email intake, redesigned
Email channels are split into two clear concepts. A mailbox is a connection: inbound address and
IMAP or OAuth credentials, with no routing or target. An intake is a feed from a folder on a
mailbox that turns new mail into items in one workspace (or a portal), with its own item type,
request type, rate limit, and processing rules. Credentials belong to the connection, and
permissions are checked against both the mailbox and the target. The SMTP AUTH mechanism is
selectable per channel, so servers that only offer LOGIN or CRAM-MD5 work without a global
override (@m0nt0).
The email and portal conversation loop is closed. A portal submission can email the customer, the
customer's reply threads back onto the same ticket, and a new email from someone with open tickets
no longer creates a duplicate. The outbound reply queue is visible and operable: retry a stuck
reply, discard one that should not send, and watch pending and exhausted counts in the metrics. A
per-sender hourly cap holds floods instead of dropping them, and operators can requeue limited mail
after raising the limit. An intake can send an optional submission receipt and link the resulting
request into the portal.
Reply routing, threading, and reply authorization were reworked, and OAuth callbacks are bound to
the account that started the flow, so a forwarded authorization URL can no longer attach someone
else's provider credentials to your identity (WI-1641).
Ticket merge and split
Tickets can be merged into a canonical one and split into a subticket. Merging moves comments,
attachments, links, watchers, email threading, and pending replies, refuses to orphan subtickets,
and marks comments private when requesters differ so one customer never sees another's content. The
duplicate remains as a read-only redirect to the canonical ticket. Splitting creates a child ticket
from selected comments and attachments with an explicit assignee and requester, with no silent
inheritance. Both operations appear in the audit trail like any other change.
Ticket imports improved too. CSV ticket import is available with asset-set portal access, and the
Jira import can map onto existing entities interactively instead of only creating new ones.
Imported customers record their provenance, and search uses Jira's enhanced JQL API (GH #301).
A portal customers can share
Portal customers belong to organisations, and 0.9.0 gives those organisations a real visibility
model. Global admins define contact levels, each organisation chooses who may see shared requests
and who decides sharing, and requests can be shared individually, shared automatically, or not
shared. The creator and explicit participants always keep access, and shared viewers can
participate. Cross-organisation isolation applies to both lists and individual requests, so guessing
an ID fails the same way as leaving it out. Customer management appears in navigation as soon as a
portal exists.
The customer data lifecycle is much more complete. Auto-created customers record their origin and
can be cleaned up in bulk, and a customer can be deactivated for security. Article 15/20 data export
ships for portal customers, erasure respects retention rules and records DSAR evidence, and
background jobs clean up expired portal credentials and knowledge-base events. Requests support
attachments and reply notifications, and asset reports can prefill a request type from row actions.
Incidents and on-call
Incidents are now work items with a dedicated team field, so they live in the same views,
permissions, and history as everything else. Acknowledge, unacknowledge, and resolve handle
concurrent updates safely, and unacknowledging restarts escalation from the current step.
AI you can audit
When the AI chat changes an item, the history entry records it, including the model and cost behind
the change (@valentimarco). Chat turns are metered
like other provider calls, "catch me up" now includes parent and sub-item context, and the item AI
actions menu has a new icon. Agent readiness errors now render properly and point at the
permission grants that fix them. OpenCode Go joins the native LLM providers.
Also in 0.9.0
- Workspace bundles, config sets, and packs. Whole workspaces can be exported as bundles and
imported into another instance, including their configuration sets, with a conformance check that
reports drift and can repair it. Configuration-set templates carry link types, imported config
sets are adopted rather than duplicated, and a failed pack apply rolls back instead of leaving a
half-provisioned workspace. Framework packs get a manifest and apply flow, and the built-in
helpdesk pack ships with the release. - Navigation you control. A new navigation configuration view lets workspaces and global
collections choose what appears in their sidebar and in what order, with per-scope visibility
toggles. The support queue is a toggleable entry, workspace-only tools stay hidden where they do
not apply, and saved settings carry over cleanly as the toggleable set grows. - Delegated administration and restricted workspaces. Management surfaces for non-system-admins,
such as channel management and asset sets, move behind a delegated admin area that appears only
when the user holds a delegated capability. Workspaces can be created with visibility restricted
to the creator, and the admin directory gains a Visibility column so the setting is discoverable. - Collections are shared by default. Collections are now visible to the people who can see their
items: workspace members for workspace-linked collections, every authenticated user for global
collections, with an owner-only Private opt-out. Marking a collection private also unpublishes its
public board. - A portal knowledge base. A channel manager can publish a workspace's Pages tree, either the
whole workspace or a sub-page subtree, into a portal's knowledge base. Published articles get
deep-linkable routes and a browse listing, agents can insert knowledge-page links into replies,
and the portal resolves those links only for pages it publishes. Usage is recorded for reporting. - Helpdesk operations. New Prometheus metrics expose outbox depth, the age of the oldest queued
reply, exhausted replies, rate-limited intake, and poll errors, with a runbook covering setup,
mailbox and outbox recovery, and SLA operations. The audit trail records merge, split, assignment,
bulk-update, agent-reply, automation-run, and knowledge-base publish decisions, and automation
comments no longer re-trigger the rule that created them. - @mention emails. Mentioning someone in a comment sends a dedicated email that carries the
comment body, so a teammate can act on the mention without opening Windshift (WI-1726). - One work-item modal. Opening an item from a list, board, dashboard, notification, or link now
uses a single global modal with built-in create and edit screens, so navigation is consistent and
the URL stays shareable (@danielraab). - A better work-item list. Shared column configuration for list and tree views, story points and
estimates editable inline, a status picker in item details and linked items, and a command palette
that understands external links (@danielraab,
#325,
#331). - Dashboard and diagnostics. Dashboard items open in the work-item modal as real links, watched
feeds follow item activity, the daily briefing reports generation health, and the What's New and
Your Activity widgets use the standard work-item card. - Jira import, hardened. Interactive mapping onto existing entities, enhanced-JQL search, ADF
rich-text custom fields rendered as Markdown, paginated Data Center bulk fetches, and resumable
imports so an interrupted import continues instead of duplicating.
Performance and polish
Faster with every workspace
Pages load only what they show. The workspace directory pages on the server, admin and settings
lists are bounded, picker options are capped, comment threads render a window instead of the whole
history, test-case rows load as you scroll, and time tabs load on activation. Worklog reports
aggregate on the server, asset-type fields load concurrently, and item detail loads its references,
assignees, teams, and milestone options once per open.
Live updates are pushed instead of polled. An open board refreshes when something changes rather
than on a timer, and reconnecting reconciles once without duplicating the initial load. Idle import
and issue-sync polling was reduced.
Security
Several rounds of bug hunting closed issues before release. OAuth callbacks for user integrations
and source control are bound to the account that started them. Child-item reads through the AI
tools, REST v1 and v2, and the detail service are scoped to the caller's accessible workspaces, and
cross-workspace hierarchy reads are filtered to items the caller can view. Concurrent event streams
are capped per user, portal approver access respects served-workspace scope, support-metric segments
the caller cannot view are dropped, and discarded replies erase recipient identity. On-call
escalation policies and their targets are scoped to the owning team, importing view settings or SLAs
requires workspace admin, making a collection private unpublishes its public board, removing a
participant revokes their thread reply access, and internal Jira Service Management attachments stay
hidden from portal customers. Security libraries were updated, and the responsible-disclosure guide
from 0.8.9 remains the place to send findings.
Bug fixes
- Business-time arithmetic now handles DST gaps, skipped midnights, and duplicate holidays, and
counts DST transitions in the trailing partial week correctly. - Removing a mention from a comment cancels its queued email, and editing a comment no longer
delivers the pre-edit body. - GitHub pull requests are correctly treated as merged
(@spatialy). wsaccepts bothcanceledandcancelledfor milestone status flags
(@spatialy).- Safe reads rejected by the per-user concurrency limit are retried with backoff instead of
failing, so boards and pickers no longer break under request bursts
(@dpb97). - Empty list responses encode as
[]instead ofnull, and canceled requests report as client
aborts rather than 500s. - Item detail reloads when the key's workspace route changes, and stale loads no longer break SPA
navigation. - Boards and collections resolve workspaces beyond the cached directory page, and the workspace
picker is limited to administered connected workspaces. - Merged duplicates are hidden from portal lists for the same requester and render as read-only
redirects. - Custom-field rows are unified in the item detail sidebar, whitespace-only descriptions count as
blank for required fields, multiselect custom fields stay arrays on create, and linking custom
fields stay off create screens. - Merging enforces the cycle guard against the current parent chain, and SLA badges refresh when
they become visible. - Comment privacy is enforced in automations, and the insert-canned-response and notify-customer
actions re-check permissions at run time. - Email intake deduplication is scoped to the intake folder, keeps deleted tickets deduplicated, and
no longer duplicates a sender who already has open tickets. - Jira imports retain datetime precision, preserve partial comment and worklog fetches, fork
comments and attachments on a workspace-changing reimport, and render ADF rich text as Markdown.
Upgrade notes
Email intake
Existing inbound email channels are migrated automatically: each becomes a mailbox connection plus
one intake on its configured folder, preserving workspace or portal routing, item type, rate limit,
and processing rules. Nothing needs to be re-entered. If a channel relied on the legacy fallback,
review your intakes: a disabled intake now stops processing instead of falling back to the old
channel configuration.
Collections are shared by default
Collections used to be visible only to their creator unless marked public. 0.9.0 flips the default:
workspace-linked collections are visible to members with item.view, and global collections to
every authenticated user. Existing collections are migrated to the shared default; owners can switch
one back to Private in the editor. Public (unauthenticated) boards still require an explicit public
flag, and making a collection private unpublishes its board.
Attachments and private comments
Attachments can be marked internal and comments private; internal content is hidden from portal
customers. This is also applied to Jira Service Management attachments on import.
Service levels
Service levels require no manual migration. Workspace admins configure metrics, conditions, goals,
working calendars, and team bindings under Service levels, and Jira SLA configuration and cycles can
be imported. The built-in helpdesk pack provisions a working helpdesk configuration in one apply.
Thank you
Thank you to Ben (@Optic00) for the Zammad observability work and
security patches, to @valentimarco for AI chat provenance and
metering, to Yulian (@spatialy) for the GitHub and milestone fixes,
to Daniel (@danielraab) for the work-item list, modal, and command
palette improvements, to Dominik (@dpb97) for the concurrency-limit
retry fix, and to Pietro (@m0nt0) for per-channel SMTP AUTH. Thanks also
to everyone who took the time to report issues and test the release candidates.