Repository navigation
v1.1.1
[1.1.1] - 2026-10-10
Security
- Authorizing an HTTP MCP server no longer puts the PKCE verifier or the
client secret in the authorization link: its state is now a random,
single-use reference to the request, which stays on the server and
expires after 10 minutes. A restart during consent means starting the
authorization again. - When several globs in an MCP Skill match a tool, the strictest one now sets
its policy whatever order they are written in; before, the first listed
won, so a broad allow written first let a narrower blocked tool run. The
generic command guard also catches runner names in any case or separator
style (run-command,kubectl-exec,ExecuteCommand) andpython_repland
code_interpreter. Review skills that relied on a broad glob listed first. - SAML and OIDC sign-in now refuse a deactivated account before signing it
in, and change nothing about it. Before, the sign-in issued a token that
was refused only on its first use. - WeCom and Weixin updates are checked against their signature before
OpsMender decrypts or reads them, and a malformed body gets 400 instead of
a server error. Before, WeCom updates were decrypted without checking the
signature. - The Inbox and notification settings refuse API tokens, like the other
personal settings. - Open live streams of an AI session or the Inbox now close within about 15
seconds after their account is deactivated or its password changes, and a
session stream serves only sessions in your own workspace. Before, a
stream checked the account only when it opened. - Starting an AI session with no incident is now for admins only, including
through API tokens; operators got it before. Forcing a session past its
model's limit stays with the incident's owner and admins. - Viewers and viewer API tokens no longer receive credential values from SLA
probe targets or model configurations: probe URLs and model base URLs show
without user names, passwords, query strings or fragments, and probe
headers, bodies and other settings are left out. Exporting the Activity log
as CSV is now for admins and operators; Viewers still read the Activity
page, which the dashboard now opens to them (before, it said access denied
while the API answered). If a probe URL or model endpoint carried a token,
rotate it. - Workspace settings, invite and People routes now check that the workspace
and person named in the request are your own workspace and its members
(404 otherwise), and OpsMender never creates a second workspace. Before,
an admin could read and change any workspace or person by id, including
reset links and temporary passwords; one instance runs one workspace, so
this only mattered if a second workspace row existed. - Nobody can change their own role or deactivate their own account, including
through their API tokens; another admin can. Before, the only admin could
demote or deactivate themselves and leave nobody able to sign in as admin. - A password change now revokes every API token the person created: their own
change, an admin's temporary password and a reset link. The tokens return
401 at once and show as revoked, each with an Activity entry. Before, a
reset account kept working through its tokens. Create new tokens after a
password change, including for automation an admin set up. - Intake refuses alert bodies over 1 MiB with
413before reading them in
full, including bodies sent without a length; set
OPSMENDER_INGEST_MAX_BODY_BYTESto change the limit. Before, a body of any
size was read and stored whole in the ingest log. The token's delivery log
keeps a short row with the size and the limit, never the body. - MCP server credentials are now shown to admins only. Before this change
every signed-in account and API token, Viewers included, could read each
saved MCP server's command, arguments, URL and environment values, and the
last connection error, from the server list; Operators could also read the
launch details of servers configured in the environment from Settings.
Others now see the name, transport, state and environment variable names.
Rotate any credential stored in an MCP server's environment values,
arguments or URL, since any account could read it.
Added
- Operators can create, see and revoke their own Operator API tokens from
Profile. Admins still create any role from Settings and see everyone's. - Operators can open the Memories page. It lists global memories and their
teams' memories, with a Team column (Global for global memories) and a team
filter; operators edit or delete only their teams' memories. - Hand several incidents to another team at once from the incident list
(Actions > Hand off to team), with one required note. Each incident keeps
its service and gets the note on its timeline; if any can't be handed off,
none move. - Operators can ask someone from another team to join an incident as a
responder. The person gets an Inbox notice and an email naming who asked,
and only they accept or decline from the incident page. A pending request
holds one of the three responder slots until it is answered, expires after
30 minutes or the incident closes, and the requester learns the outcome.
Removed
- Memory feedback: the thumbs on the Memories page and in a session's
Memories used panel,POST /memories/{id}/feedback, and the
helpful_countandunhelpful_countfields of memory responses. Recall
ranking and eviction no longer weigh old feedback; pinned memories are
still never evicted.
Fixed
- The API's OpenAPI document now reports the installed version (
1.1.1), the
same oneopsmender --versionprints; it said0.2.0whatever the release. - The models and the database migrations now describe the same schema. On
PostgreSQL, the names of ingest tokens, MCP servers, model configurations,
skills, SLA targets and workflow profiles are unique per workspace, as the
models already said, and the models declare the JSONB columns and indexes
the migrations create. Saved data doesn't change. CI now fails a change
whose models and migrations disagree. - Scheduled reports keep their day and local time. A monthly report set
for the 31st runs on the last day of shorter months and returns to the 31st
(before, it moved to the 28th for good after February), and a weekly 09:00
report stays at 09:00 in its time zone when the clocks change (before, it
ran at a fixed UTC time and moved an hour). Existing schedules keep their
next run's day and time, in UTC. - Identical alerts that arrive at the same moment now all get a normal
answer and open one incident; before, all but one could fail with a server
error on PostgreSQL. Two Takes at the same moment on an incident without
an Escalation Chain now leave one owner and give the other the usual 409
instead of a server error. - An operator's Maintenance Window now lasts at most 24 hours, tells the
admins and the covered teams in their Inbox when it becomes active, and can
be edited, ended early (End now) or deleted by the operator who created
it; other operators can't, and only an admin changes what it covers. Before,
it could last years, told nobody, and its creator couldn't end it. - Taking someone off a Roster no longer moves everyone else's shifts. Removing,
deactivating or demoting a member to Viewer now keeps their place in the
rotation, and its shifts go to the next member. Before, the rotation was
recounted, so other people's shifts moved, the current one included.
Demoting someone to Viewer now takes them off every Roster, as deactivation
does (before, they stayed on it and paging skipped them), and both
confirmations list the Rosters and who takes the current shift. - Deactivating someone or making them a Viewer now stops their remaining
notification stages at once; before, their My Routing stages kept arriving
on incidents they could no longer act on. No stage is sent to anyone who
isn't an active admin or operator. Someone paged after an incident has an
owner (a responder added later, or Escalate now while the owner keeps it)
now gets only the first stage of their plan instead of every stage. - The next Escalation Chain level no longer pages before the people the
current level paged have had all their own notification stages. A level
escalates at the later of its timeout and the end of everyone's stages plus
an answer window (the last stage's wait; none if that stage couldn't be
sent), unless someone acknowledges. Someone with no stages saved, or who is
no longer an active admin or operator, holds nothing: the level timeout
alone decides. The wait for people's stages ends at most 10 minutes after
the level paged for P0 and P1 incidents, and 20 for P2 and P3; a longer
level timeout still applies. New levels and new My Routing stages wait 3
minutes (new levels waited 5 before), so with three stages at the default
wait, levels fire 9 minutes apart. My Routing shows the last stage's wait
as the answer window and warns when a priority's stages and answer window
take longer than that priority's limit; the chain editor's Preview timeline
shows each level's earliest time. - A recovery that arrives during a Maintenance Window now closes the incident
it clears, stopping its Escalation Chain and AI session without paging
anyone. Before, the window dropped it with every other alert, so an incident
opened before the window stayed open. New alerts in the window are still
dropped. - Deleting an incident also deletes the incidents combined into it, including
ones combined into those, and Activity records each with the incident it
was combined into. The delete confirmation lists them first, on the incident
list, in bulk and on the incident page. Before, they stayed behind with no
incident to point to, and their alert was swallowed when it fired again: it
now opens a new incident and pages, as do SLO violations, for incidents left
behind by earlier deletes. - Saving a postmortem's memory candidates follows the memory rules: operators
save them only for incidents on their teams' services, and an incident with
no service (Global memories) needs an admin. The postmortem editor and guide
no longer say saved candidates wait for review; like every memory, they are
recallable at once. Writing the postmortem follows the Resolve rule: admins
and operators on the team handling the incident write it, everyone else
reads it. - An operator's Maintenance Window on services their teams own, or on their
own teams, now takes effect at once instead of waiting for an admin. Other
operator windows still wait for approval, and a window naming a service,
team or Roster that doesn't exist is refused. - Updated the locked langgraph to 1.2.14, which brings langgraph-sdk 0.4.6
with the upstream fix for an authorization bypass in its resource handler
registration (CVE-2026-104873), along with langchain-core 1.6.7. OpsMender
uses only langgraph's graph runtime, not the SDK's handlers. - Operators, including an owner from another team, add responders only from
the team handling the incident (anyone when it has no team); admins still
add anyone. A refusal names the person and adds nobody, and the Add
responders dialog lists only the handling team for operators. - The owner and admins now control an incident's AI session: they start it,
take it over, stop it, switch its model, override its tier and message it,
on the web and from chat. Others watch; Start session stays disabled until
you take the incident. Starting, taking over or overriding a session never
changes who owns the incident. Approvals from an incident's AI session are
answered by its owner, operators of the team handling it and admins, on the
web and in chat. - Only admins and operators on the team handling an incident can resolve,
reopen or combine it, whether or not they own it or are helping. Responders
and owners from another team are refused on the incident page, the incident
list, Slack/resolve, chat buttons and phone key 3, and the incident page
shows Resolve only to people who can use it. Acknowledge no longer shows on
an incident someone else owns; Take over asks them instead. - An active owner now keeps an incident at every priority. Others who try to
acknowledge or take it are refused; assigning someone else over an owner
needs an admin or an operator of the handling team, a member of that team
as the new owner, and a note, which the previous owner receives in a notice.
Bulk reassign, and bulk acknowledge for someone else, follow the same rule.
Only the owner or an admin can release an incident, in OpsMender or with
Slack/release. Take over on an incident without an Escalation Chain, in
OpsMender or with Slack/take, now says to use Force take instead of doing
nothing or asking for an admin. - Only the team handling an incident can take or acknowledge it. Operators
outside that team are refused on every path (Take, Acknowledge, bulk
acknowledge, takeover requests, Slack/ackand/take, chat buttons and
phone key 1) unless its Escalation Chain paged them in the current run.
Admins always can, and incidents with no team keep the any-operator rule.
Take and Acknowledge show only for people who can use them. - The design audit gate (
scripts/design_audit.mjs) now fails when the
accessibility checker crashes on a page, when a page can't be captured, or
when nothing was captured at all. Pages that need a record the environment
doesn't have are listed as NOT RUN instead of being skipped silently. CI
checks these rules without a browser. - Reliability Maintenance Windows now send an explicit scope: All Targets
covers the workspace, a linked target covers its service, and a standalone
target covers only that probe. Create and update reject specific target IDs
under global scope and reject unknown or other-workspace probe IDs. Changing
a selection clears the previous service scope. Loading targets preserves
a new window's draft. Existing windows are not
rewritten automatically. - Monolith startup now stops AI sessions interrupted by an app restart,
records the interruption in their summaries and incident timelines, and
expires their pending approvals. Their model slots are freed for queued
sessions without retrying interrupted work. Queued sessions and approval
holds remain with their existing queue and expiry rules. - Personal notification steps are now claimed under a database lock. Two
schedulers can no longer send the same step twice, and an acknowledgement
or resolution that arrives while a step is being sent waits for that send,
then stops the rest: nothing is sent after it, and the step keeps the
acknowledged or resolved status. A team handoff, responder removal or
deletion during a send waits instead of failing, and steps still running on
a closed incident now stop. - Permanently deleting an incident, singly or in bulk, now records an Activity
entry for each incident (who deleted it, its title and when) in the same
transaction, and keeps its AI sessions' earlier Activity entries instead of
deleting them. Overlapping deletion requests cannot add duplicate entries.
The delete confirmations say so. - Reassigning an incident to another team and moving it to another service
now require a note. A missing or blank note is refused and nothing moves;
the note appears on the incident timeline. The Reassign and Manage incident
dialogs mark the note as required. - Chat actions and role-based notices now use the role shown on People, the
same role as sign-in and phone keys. A viewer demoted there can no longer
act from chat, an operator promoted there can, and new-incident, approval
and other role-targeted notices follow People role changes. - Viewers are no longer paged or made incident owners. Team levels page only
their admins and operators; a user or roster level whose person is now a
viewer on People is skipped as empty; adding an escalation level for a viewer
or assigning an incident to one is refused. - Phone keypad actions now check the caller's access when the key is pressed:
an active account, workspace membership and the Admin or Operator role shown
on People. Viewers, removed members and disabled or deleted users can no
longer acknowledge, escalate or resolve an incident through an unexpired
phone link. - Darkened the green, amber and cyan initials-avatar backgrounds so their white
text meets the minimum contrast ratio without changing saved color choices. - Voice Call stages now reach the configured calling channel and use the same
spoken summary and signed keypad link as immediate phone pages. Missing
configuration or a phone number records a skipped attempt with its reason;
answering a call does not acknowledge the incident. - Approved active Maintenance Windows now cover uptime samples by global,
service or team scope as well as legacy target lists. Roster windows do not
cover samples. Matching windows prevent new SLO burn incidents, including
burns from earlier outages; checks resume normally when the window ends. - Raised the PyJWT minimum to 2.14 and refreshed the locked package to include
upstream fixes for token verification and key handling vulnerabilities. - Updated the locked urllib3 to 2.8.0 for upstream fixes to HTTPS proxy TLS
settings and unbounded memory use in chunked responses. - An API token now acts at the lower of its own role and its creator's current
role in every permission check. Previously some incident, team, responder,
comment, maintenance and memory checks read the creator's account role, so an
Operator token created by an Admin could delete incidents, force-take or
reassign another team's incidents, delete other people's comments and
self-approve global Maintenance Windows. Demoting a token's creator now
lowers the token too. - Operators can no longer create global memories; global memories need an
Admin, as editing and deleting them already did. - Skill Studio now saves a reviewed policy change when Save is clicked from
the content editor. Debounced validation and validation on save remain active. - Demo seeding no longer prints its database connection URL. Demo users and
invitations use reserved example addresses. - The local image scanner reads the existing unfixed-vulnerability policy
from the correct configuration key, matching the hosted scan.
Changed
- Uptime and SLO percentages count maintenance samples as up instead of
excluding them. Two up, one down and two maintenance samples now report 80%
uptime, with one minute of downtime and two minutes of maintenance. Probe
results remain available in Outage History. Reliability now describes covered
samples as up, matching these numbers. - Refreshed all 13 demo screenshots from one clean seed, including the Tier 1
approval view. The capture script checks for test debris and real email
addresses. Browser QA now verifies policy widening, advisory-only services,
and overlapping tool sources with a single-source control.
Added
-
Reassign to another team. An incident that reached the wrong team can be
handed to the team it belongs to from the incident page. Admins and
operators on the incident's team can reassign it. The owner is released, the
receiving team's Escalation Chain pages from the first level (P2 and P3
incidents notify its members in their Inbox instead), and the timeline
records who moved it, where, and the optional note. The incident keeps its
service; the new team handles force takes, filters, reports, team-scoped
channel updates, and paging after a reopen. -
Add responders. Up to three people can be asked to help with an
incident besides its owner. Each one is paged once through their own
notification settings (Maintenance Windows don't hold the request) and gets
an Inbox notice with the optional message. Responders show next to the
owner, can be removed, and can leave. -
Workspace change history. Authenticated configuration changes now write
Activity entries with the actor, route, entity, operation, and a short
redacted before/after summary. Approval decisions name the decider, and
session tier overrides record the actor and tier transition. Credential
values are not copied into Activity. A change and its entry are saved in
the same database transaction, so if the entry cannot be written the change
is rolled back and the request fails. A row changed in several steps, such
as a reorder, gets one entry, and rows whose values did not change get none. -
Reopen pages again. Reopening a resolved P0 or P1 incident starts a new
escalation round at the first level and releases its former owner. The
timeline says whether paging restarted or why nobody was paged. -
Takeover consent in the incident page. Take on another person's incident
asks its owner to hand it over; the owner receives an Inbox notice and can
confirm within five minutes. The request then expires without changing
ownership. An admin, or an operator on the current owner's service team,
can force a takeover immediately with a required reason; the former owner
is notified and the reason appears on the timeline. -
Cross-service alert collision notice. When a provider-scoped alert is
absorbed by another service's active incident, the receiving service's
Escalation Chain responders get one Inbox notice (their Inbox mute
applies), and Respond channels scoped to the receiving team get one
informational message. The ingest log and the incident timeline record
both services. The incident's owner doesn't change, and nobody on the
receiving service is paged. -
Tool-source overlap warning. When a Service allowlists an MCP server and
a native connector that appear to reach the same system (an Atlassian MCP
server and a Jira connector, say), the Services table marks it
Overlapping tool sources, the service editor explains why, and
opsmender doctorreports a warning. Both tool sets still reach the AI,
which picks by description, and only the native connector links tickets to
the incident. The check is a heuristic and advisory only: it never changes
which tools a session gets and never blocks a session. Overlap details are
shown to admins and operators only.
Changed
-
Escalation Chain ties now prefer the earliest service link. Links that
existed before this upgrade share a backfilled creation time and retain
their former UUID tie order. The collision notice uses the same active-chain
selection as paging. -
MTTR now uses the incident's resolution timestamp, so later edits do not
move the metric. Existing resolved incidents are backfilled from their last
update time, the only timestamp available before this upgrade. -
The populated-data escalation migration archives extra duplicate page
markers asrecorded_legacyand advances affected chains to round 1.
Their next handoff therefore starts round 2; unaffected chains remain at
round 0. -
Handoff actions recheck permission after locking. If another operator
moves the incident to a new team before a reassignment or responder change
completes, the earlier team's operator cannot finish the stale action. -
Plain punctuation in tier gate messages. Blocked and approval reasons
from the tier gate now use a colon or comma instead of a dash, for example
"deny-list policy match: blocked at every tier". Only the wording changed;
the gate's decisions are identical. The punctuation check now covers the
tier gate too. -
One MCP server per service. The service editor selects one server; the
API rejects several with 422. Existing services that list several show a
warning, and saving keeps the selected one. -
P0 and P1 page; P2 and P3 notify. P3 incidents now notify, like P2,
instead of getting the unused "auto resolve" mode. New services default to
P1, and the service form explains which priorities page. Existing
services keep their priority: a service still at the old default, P2,
won't page until you raise it. -
Low-severity alerts notify. An alert whose severity is
loworinfo
notifies instead of paging, even on a P0 or P1 service; the incident keeps
the service's priority and its timeline says why it didn't page. The
generic intake adapter now readsinfoandinformationalaslow
(it used to read them asmedium). -
Plain punctuation throughout. The app, its messages, the docs and the
CLI no longer use em or en dashes. The browser tab reads "OpsMender";
empty values show a word ("None", "Never", "No data") instead of a dash;
tier options read "Tier 0: Autonomous"; and CloudWatch, GCP, OCI and
BugSnag alert titles use a colon ("[CloudWatch] cpu-high: ALARM"). New
Skills from the template use "## Tier 0: Autonomous" headings; Skills
with the older headings still parse. The AI is asked to write plainly
and skip em dashes, too. Incidents already stored keep their titles. -
Sessions without a service get no integrations. A service's allowlist is
what grants integration tools, so an incident with no service (a manual P2
or P3, or an SLO with no service) no longer gets every enabled connector. -
Helm sets
FORWARDED_ALLOW_IPSwhen ingress is enabled, from the new
ingress.trustedProxiesvalue (default"*"). Behind an ingress every
request comes from the ingress controller, so without it sign-in limits
counted everyone as one address and five wrong passwords locked an account
for everyone. Narrow it to your ingress controller's pod CIDR if other
workloads in the cluster aren't trusted.
Fixed
-
Incident-created Inbox notices exclude deactivated and deleted users.
-
/ackin chat names the current owner and suggests/takewhen someone
else holds the incident lock. -
Shared dialogs announce their title to assistive technology and keep
keyboard focus inside until closed. -
The quiet-hours regression test uses a fixed UTC time instead of depending
on the minute the suite happens to run. -
Paging the same person again. When someone whose staged notifications
had finished is paged again for the same incident (a new round, a reopen, or
a responder request), their notifications start over instead of being
skipped. -
Service handoff notes. Moving an incident to another service now records
the move and the optional handoff note on the timeline; the note was
previously dropped. -
Long incident titles in the Inbox. Inbox notices shorten titles to fit,
and a failed notice no longer fails the action that sent it. -
One combined alert clearing no longer resolves the incident. When
alerts were combined, a recovery for one of them resolved the whole
incident and stopped paging. The incident now stays open, notes the
cleared alert on its timeline, and resolves when its own alert clears. -
Escalate now on an owned incident pages one level. It used to turn the
owner's lock back into running escalation, so later levels kept paging on
schedule while someone owned the incident. The owner now keeps the lock. -
Deleting an ingest token that has received alerts returns
409and
asks you to revoke it instead; it used to fail with a server error on
Postgres. Its delivery log is kept as an audit record. -
Connector Skill instructions reach the AI. A Skill bound to an
integration connector could restrict the connector's tools, but its written
Custom Instructions never reached the model; for a service with only
integrations, the AI got no instructions at all. A session now receives the
active tier's instructions from each allowlisted connector's Skill, after
the MCP Skill's and labelled with the connector, at every stage. They are
guidance only and can't lift an approval or a deny. Connector AI Action
Workflows are still not used; sessions follow the MCP Skill's workflow. -
SLO burn-rate incidents page. They take their service's priority and
page its Escalation Chain like any other incident; before, they never
paged. A violation after the previous one resolved opens a new incident
instead of reopening the old one. Manual incidents, intake and SLO
violations now start paging through one shared path. -
Recurring Maintenance Windows recur. A window with a recurrence rule
(for exampleFREQ=WEEKLY;BYDAY=SU) now covers every repeat, not just the
first. An unreadable rule, or one repeating more often than hourly, is
rejected with 422. Team-scoped windows now also hold back pages, not just
intake, and Roster-scoped windows hold back pages sent through that
Roster's escalation level; before, they did nothing.
Upgrade note: existing recurring windows start repeating after the
upgrade. Check them before upgrading if any were set up long ago. -
The Reliability page no longer promises a P0. Creating an incident
from an SLO recommendation said it would be P0 and page; it takes the
service's priority. -
Everyone agrees on who is on call. Paging, the on-call API, the Roster
and chain calendars, and the Services table now build the on-call picture
the same way, from the Roster's real coverage window. Before, paging used a
default 09:00-17:00 window, so a night Roster could page nobody at 03:00
while the calendar named someone.- Shifts hand over at the Roster's handoff time (its coverage start), on the
Start Date and every shift after it. A round-the-clock Roster used to
switch people at local midnight. The weekly handoff day is the Start
Date's weekday; the unusedhandoff_dayfield stays legacy. - The Services table's "On call now" resolves at the current time instead
of the middle of today's coverage window. The chain calendar API accepts
at(withrange=today) for this. - The Dashboard's on-call coverage and the Rosters page's "On call now"
are right for Rosters in any time zone. Asked for "now", the on-call API
used the server's clock without a zone and read it as Roster-local time,
so a New York Roster at 13:00 showed nobody on a UTC server. - An Override for a deactivated user is ignored everywhere, as paging
already did, and is no longer flagged on the Roster calendar.
- Shifts hand over at the Roster's handoff time (its coverage start), on the
-
Quiet hours never block a page to the on-call person (D-4). When a
level targets a Roster, the person on call is paged even inside their quiet
hours. Quiet hours still apply to direct and team targets, and any page held
back by quiet hours or a Maintenance Window is now recorded as a skipped
delivery with the reason and a timeline note. Before, it vanished without a
record. -
Notification preferences are validated. Malformed quiet hours or routing
return 422 instead of failing silently at page time. Saving paging routing
no longer wipes the Inbox mutes set on the Inbox preferences page.
Upgrade note: an older nested quiet-hours shape ({"weekday": {...}})
was never read by paging and is now rejected on save; stored values load
unchanged. -
Escalation chains now visit every eligible level once. The first level
no longer stops at a 15-minute start-time cap. Each level, including the
final one, keeps its configured timeout; an unacknowledged chain then sends
one exhaustion notice to the team's Notification Channels and responders'
Inbox. An inactivity lock that lapses with no next level sends the same
notice while leaving the owner assigned. -
Deleting a level compacts the chain without skipping the next level in an
active incident. Empty or inactive targets are skipped immediately; a
suppressed or unconfigured delivery keeps its level timeout. A service
selects a matching priority chain, then an unfiltered chain, and warns on
the incident timeline and service form when none matches. -
Logical page markers now carry a run round and are unique per incident,
responder, level and round. Later levels and service handoffs can page the
same responder again without colliding with prior delivery history. Roster
writes reject invalid time zones and times, and an explicitnullin a
Roster update leaves that field unchanged instead of failing.
Upgrade note: duplicate historical logical markers are retained as
recorded_legacy; physical delivery and acknowledgement records are kept.
The nullablehard_deadline_atcolumn remains for compatibility but is no
longer used. Database claims prevent overlapping workers from dispatching
the same level twice; acceptance by a remote channel cannot be guaranteed
exactly once across a crash or ambiguous network response. -
Owning or closing an incident now stops paging, everywhere.
- Resolving through the web page, the incident list, phone keypad
3, an
alert recovery, a chat button, Slack/resolve, or combining incidents
stops the Escalation Chain and staged notifications, including snoozed
and acknowledged chains. Before, only chat and Slack resolves did. - Every way of taking ownership acknowledges the incident and stops paging:
Take, bulk acknowledge and reassign, phone keypad1, chat
Acknowledge, and taking over an AI session. - Acknowledging holds the incident under a lock (D-021). The owner's own
recorded actions keep it; 15 minutes without any of them, or a release,
pages the next level (never level 1 again). - Slack
/snoozeresumes the next level when the snooze ends (it used to
stay paused forever), and extends an owner's lock instead of dropping it.
Escalate now also works on snoozed and acknowledged chains. A snooze can last
up to seven days. - Only the current owner can confirm a takeover request (an admin can still
force one), and an unanswered request expires without a transfer. - Changing the service of a resolved incident no longer restarts paging.
- Phone keypad
1checks the current owner, so a responder paged after a
release can take the incident. - Inbox links for assignments, mentions and combined incidents open the
incident page instead of a missing page.
- Resolving through the web page, the incident list, phone keypad
-
API.
POST /incidents/{id}/ack,/assign,/takeand the bulk
acknowledge/reassign actions return 409 for a resolved or merged incident.
/ackreturns 409 while someone else holds the lock (use Take over or a
takeover request). Assigning an inactive user, or one outside the
workspace, returns 422. Confirming someone else's takeover returns 403, and
an expired request 409. The chain panel addspaused_untiland
last_activity_at.
Upgrade note: chains acknowledged before the upgrade stay finished, and
Slack snoozes set before it stay paused; neither re-pages on upgrade. -
SNS-wrapped CloudWatch alarms sent to a service intake URL now use the inner
alarm identity and state, so they dedup, and an OK resolves the incident.
Plain-text SNS messages still open an incident titled from the Subject or
message. Clearing alerts resolve only live incidents, and a firing alert
after resolution opens a new incident whether or not alert grouping is on.
A recovery with no live incident is logged and skipped instead of creating
a resolved incident that pages. Ingested firing and acknowledgment states
map toopen(the undefinedinvestigatingstatus is gone). A service
intake URL always uses its own token, even when other tokens are bound to
the service. JSON nested more than 64 levels deep is rejected with a 422.
Upgrade note: if a service's intake URL previously resolved to another
token bound to the same service, incidents it opened before the upgrade
won't match later deliveries; resolve those by hand.
Security
-
Accepted SAML assertion IDs are claimed in the database for their validity
window, so a replay is rejected across app workers. Assertions without an ID
or expiry are rejected. The container vulnerability scan now runs on pull
requests as well as onmain. -
Intake URLs are stored as a hash and shown once. A service's intake URL
carries the secret that lets a monitor post alerts and page a team, and it
used to be stored as plain text. Now only a hash is kept; the full URL is
shown once, when the service is created or an admin rotates it (Rotate
URL,POST /services/{id}/intake-url). Existing URLs keep working.
GET /servicesreturns a maskedintake_url_hintto admins and operators
instead ofintake_url. The access log shows only the first eight
characters of the secret, and revoking the URL's ingest token now retires
the URL instead of failing or quietly re-enabling it. -
A password change or reset ends older sessions. Tokens issued before an
admin reset, a reset link or a self-service change stop working on the API,
the live streams and a pending MFA challenge.POST /auth/me/passwordnow
returns a fresh token (200) instead of 204, so whoever changed their own
password stays signed in. The live streams also refuse a deactivated
user's token. -
A deny rule wins wherever it appears in a Skill. A
deny: trueentry
written below a broad glob such as*was ignored, so the denied tool ran
autonomously at Tier 0 and Tier 1; connector Skills had the same gap. Deny
now wins in any order, and over an exact entry for a tool a deny glob
matches, so narrow the glob to allow one tool.allow_genericopts a
generic runner out of the guardrail only on an exact-name entry, not a
glob. -
Chat approvals follow the same rules as the web.
/approveand
/rejectfrom chat refused nothing after the request expired and recorded
no approver; they now expire like the web, record the linked OpsMender
user, and count as the owner's activity. Chat commands also require a
verified user link. -
Viewers no longer see intake URLs. The URL carries the secret that
lets a monitor post alerts and page the team; only admins and operators
get it. -
Failed sign-ins are limited. Login, MFA verification, registration,
password-reset and invite links, and the SSO and SAML callbacks now refuse
a caller with429andRetry-Afterafter repeated failures: 5 per account
from one address and 100 per address in 15 minutes (configurable;0
turns a limit off). Reaching a limit writes onesign_in_lockoutaudit
entry. Keying on the address as well as the account means nobody can lock
another user out just by knowing their username.
Upgrade note: behind a reverse proxy, setFORWARDED_ALLOW_IPSto the
proxy's address, or every user shares the proxy's address and its limits. -
A deleted service's intake URL stops working. Deleting a service now
revokes its ingest tokens; before, the old URL kept creating incidents
with no service. -
Upgraded
anyiofrom 4.13.0 to 4.14.2 (4.15.1 on Python 3.15+) to fix
CVE-2026-63374 (critical).anyiois a transitive dependency ofhttpx,
FastAPI, and the model SDKs; no application code changed.
Documentation
- The integrations guide explains how to keep one source per capability
(including the connector-skill deny that keeps only the MCP route), that a
connector'sproject_keyis a default rather than a limit, and why
connector names should carry the project or space key. - The paging guide documents the full phone keypad (
1acknowledge,2
escalate,3resolve,*repeat), that the menu needs
OPSMENDER_PUBLIC_URL, and that the voice status-callback URL has no
receiving route in OpsMender (the.env.examplesaid otherwise). - The notification-preferences guide now matches the product: only P0 and P1
page, so the P2 and P3 routing rows aren't used; quiet hours can only hold
back P1; a chat stage posts to the channel's shared chat, not a direct
message; "sent" means the provider accepted a delivery, with no retries or
fallback; and Maintenance Windows cover team and Roster scopes and can
repeat. The Slack guide notes/snoozedefaults to30m. - My Routing says which priorities page: P2 and P3 are marked "Doesn't
page, so these stages aren't used".