Skip to content

Releases: SpicyDaemon/OpsMender-AI

v1.2.0

Choose a tag to compare

@github-actions github-actions released this 17 Oct 13:27
e1a2119

[1.2.0] - 2026-10-17

Fixed

  • With several app instances behind a load balancer, or scheduler replicas
    in distributed mode, a due audit schedule ran once per process and every
    process probed every SLA target. A due audit schedule is now claimed with
    one row update before it runs, a claim lasts one interval and the run
    releases it; each SLA target's poll is claimed the same way, so every
    job runs once across all processes and a process that dies mid-run hands
    its job to another after the interval. The admin guide says how many
    replicas may run (any number; SQLite serves one process).

Security

  • AI Sessions now mark alert text, incident descriptions and tool output as
    data in every prompt that carries them, with one plain rule that such text
    is never an instruction. Credential-shaped strings in tool output (keys,
    tokens, private keys, password= values) are redacted before the model,
    the session record and any ticket see them. An alert whose text addresses
    the assistant ("ignore your instructions", "as the AI, run") is flagged on
    the incident and in the audit log at intake and never acted on; what a
    session may do is still decided by the tier gate alone. A corpus of
    injected alerts proves the gate blocks or asks for approval at every tier.
  • A model config whose saved key setting is not a variable name (a key
    pasted before such values were refused) is now listed without it, for
    every role, with a not a variable name: edit this config note on the
    Models page; the server logs the config ids at startup, never the values.
  • Skill Studio no longer suggests safe for a tool whose name starts with
    explain: an EXPLAIN ANALYZE runs the statement it explains, so such a
    tool is suggested as caution for review.
  • An identity provider that publishes a single bare key instead of a key
    set no longer ends a sign-in as a server error when that key does not fit
    the id token; the sign-in is refused like any other bad token.
  • A model's key setting must now be the provider's own variable
    (ANTHROPIC_API_KEY, OPENAI_API_KEY, AZURE_OPENAI_API_KEY) or one the
    server operator lists in OPSMENDER_MODEL_KEY_VARS, and the providers with
    a fixed host (anthropic, openai, azure_openai) refuse a base URL
    anywhere else. Before, an admin could name any variable the server holds,
    the token signing secret included, and pair it with any URL, so a model
    setting could send that value to a host of their choosing. The free-URL
    providers (ollama, openai_compatible) keep any URL but may only use
    listed keys. Model configs saved before this change keep working until
    edited.
  • A local (stdio) MCP server now receives only PATH, the OS basics and the
    variables its own configuration names. Before, it received every variable
    of the app, so a server (and through it an admin) could read the token
    signing secret or the database URL. A server saved before this change
    keeps receiving everything until an admin saves it again, which the MCP
    page points out; a server defined in OPSMENDER_MCP_SERVERS_JSON inherits
    only with "inherit_env": true. A server that needs KUBECONFIG or
    AWS_PROFILE gets it named in its variables.

Changed

  • The MCP SDK moves to 1.30.0, and CI's audit no longer ignores its
    advisory. A remote (SSE or HTTP) MCP server is now followed through a
    redirect only within its own scheme, host and port; any other redirect
    fails the connection with a message naming the other origin, so an
    admin enters that URL if it is the server they mean.
  • Every workflow runs on the Node 24 releases of its actions (checkout v7,
    setup-python v7, setup-node v7, upload-artifact v7, download-artifact v8,
    action-gh-release v3, codeql-action v4, setup-uv v10.3.0 (it publishes no
    moving major tag), upload-pages-artifact
    v5, deploy-pages v5, setup-buildx-action v4, build-push-action v7, and
    trivy-action 0.36.0 whose own steps run on Node 24), and the repository
    carries .nvmrc (24) beside the frontend's engines field, so Node 24
    is the minimum everywhere.

v1.1.2

Choose a tag to compare

@github-actions github-actions released this 16 Oct 18:31
e0d917d

[1.1.2] - 2026-10-16

Security

  • While a person's temporary password must still change (a new account an
    admin created, or a temporary password an admin set), their session can
    only read their own profile, change the password and use MFA. Every other
    API call from that session, creating an API token included, answers 403
    with password_change_required, their live streams are refused, and an
    open dashboard tab goes to the password change page. Before, only the web
    app asked for the change, and the API served that session in full,
    including creating API tokens.
  • Listing the Rosters a person leaves on demotion or deactivation now checks
    that the person belongs to your workspace, like the other People routes
    (404 otherwise). Before, it answered for a person of another workspace;
    one instance runs one workspace, so this only mattered if a second
    workspace row existed.
  • Model discovery (GET /models) now accepts connection settings (a base
    URL, a key variable, an API version, a region, a profile, a project or a
    location) only from admins; every other role, and their API tokens, gets
    403 before anything is read or called. Before, any signed-in user, a
    Viewer included, could name an environment variable and a URL, and
    OpsMender sent that variable's value to the URL as a bearer key, which
    could expose the token signing secret, the database URL or a provider key.
    A model's key setting must now be written like an environment variable
    name (letters, digits and underscores, not starting with a digit);
    discovery and the model save routes refuse anything else with 400
    before reading or storing it, without repeating it. Settings saved before
    this change are not rewritten. An unknown provider in discovery answers
    400 instead of a server error.
  • The generic command guard now also catches common runner names: terminal,
    console, tty, pty, shellexec, bash_tool, invoke_expression,
    subprocess, popen, os_system, sudo, su, docker, podman,
    nerdctl, crictl and systemctl, names that start with bash_,
    powershell_, pwsh_, sh_, terminal_, console_, sudo_, docker_
    or subprocess_, and names that end with _terminal, _console, _bash,
    _powershell, _pwsh, _subprocess or _cypher, in any case or separator
    style (Terminal, BashTool, bash-tool, PowerShellExecute). It also
    catches the runner tools of common MCP servers, such as kubectl_generic,
    call_kubectl, call_aws, execute_kubectl, ssh_execute,
    start_process, execute_code, browser_run_code_unsafe and
    explain_sql_statement (which runs the statement when it analyzes it); the
    MCP Skills page lists all of them and the bounded tools to classify in a
    Skill instead. Before, terminal,
    shellexec, bash_tool and the like were ordinary tools, so a Skill entry
    or glob that allowed one let it run at Tier 0, without approval at Tier 1,
    and in environment scans. Now they are blocked at Tier 0 and Tier 2 and in
    environment scans. At Tier 1 they ask for operator approval, and run once
    approved, even where the Skill blocks them
    : the guard is checked before a
    tool's own tier policy, so a T1 policy of blocked or advisory, or no
    entry for the tool, no longer refuses it. To block one at every tier, add it
    to the Skill's deny-list with deny: true. A narrowly scoped tool that a
    new prefix or suffix catches, such as docker_logs, console_url,
    get_console or aws_console, needs an entry with its exact name and
    allow_generic: true to run under its own tier policies again. Skill
    Studio's Generate from tools and AI assist now mark these names as generic
    and pre-set them to deny, as they already did for the older runner names.
  • OIDC sign-in and Teams actions now name the signature algorithms they
    accept. An identity provider's id token must be signed with an asymmetric
    algorithm that its discovery document lists (RS256 when it lists none), and
    a Teams action with RS256, the algorithm Bot Framework signs with. Before,
    both checks used whatever algorithm the token named (python-jose advisory
    GHSA-3qf3-8w2g-rqmx), and a token naming HS256 or none caused a server
    error instead of a refusal. An identity provider set to sign id tokens with
    HS256 (the client secret), or with an RSASSA-PSS algorithm (PS256 and up)
    that the token library cannot verify, is now refused with a clear message;
    set it to RS256 or ES256. Both checks also try only the published keys
    that can verify the token (only those with its key id when any key has
    it), so a key set that lists an EC key before the RSA key, or holds a key
    that cannot be used, no longer refuses a valid token.
  • The web app is now built with Next.js 16.4.1 (from 16.2.3) and tested with
    Vitest 4.1.11 (from 3.2.4), which carry the fixes for the published
    advisories against both, including three Next.js advisories from
    2026-10-14 that 16.4.0 does not fix. None reached a running OpsMender: it
    serves a static export with no Next.js server or image optimizer. The
    locked Mako moves to 1.4.3.
  • Every pull request and release now audits dependencies: the web app's
    runtime npm packages fail the check on a high or critical advisory, and
    the installed Python packages fail it on any known advisory (checked
    against OSV). Three advisories are ignored because they do not apply:
    GHSA-3qf3-8w2g-rqmx in python-jose (every token check names its
    algorithms), GHSA-wj6h-64fc-37mp in ecdsa (it affects signing, which
    OpsMender never does with ecdsa) and GHSA-84m7-p3x7-pcfv in the MCP SDK
    (it affects MCP servers; OpsMender only connects to them as a client).

Fixed

  • Assigning an incident to someone else, and bulk reassign or bulk
    acknowledge for someone else, now refuse the change when the incident's
    owner changed after the request was checked, naming the current owner if
    there is one (409, or that incident's failure in a bulk action); nothing
    is written. Before, an assignment that arrived a moment after someone took
    the incident replaced them without a note or an Inbox notice. An
    assignment that arrives as the incident is resolved or merged is refused
    the same way; before, it answered a server error or reported success.
  • Alert intake refuses a body whose objects and arrays nest more than 64
    levels deep with 400 and opens no incident; the token's delivery log keeps
    a short row naming the limit, never the body. Every other route refuses a
    JSON body nested more than 64 levels with 400 before the route acts on
    it, and the Teams, Discord, Slack and ticket webhooks, which read their own
    bodies, refuse one too deep to read with their usual 400. A token nested
    too deeply to read (a session, an MFA challenge, an SSO or bot sign-in
    state, a voice link or a Teams token) is refused like any bad token.
    Before, intake accepted and stored deeply nested bodies and failed with a
    server error on the deepest, and a deeply nested body or token sent to
    other routes, such as saving My Routing settings, failed with a server
    error, sometimes after the value was saved.
  • On SQLite, the standalone binary's local database, identical alerts that
    arrive at the same moment now open one incident and page once: the app takes
    incoming alerts one at a time inside its process. Before, each alert could
    open its own incident and page again. Run one app process per SQLite
    database; several processes need PostgreSQL.
  • Inbox quiet hours and My Routing quiet hours are now saved separately, and
    saving one page never changes the other. Before, both pages wrote one
    shared setting: saving the Inbox notification preferences, even just a
    category mute, turned off the quiet hours that hold back P1 pages, saving
    My Routing turned off Inbox quiet hours, and after any Inbox save, Save
    routing failed with "[object Object]". A save the server refuses as
    invalid now shows the reason, in My Routing and the other pages. Through
    the API, Inbox quiet hours are under routing.in_app.quiet_hours of
    /users/me/notification-preferences, and its quiet_hours is My
    Routing's only. Upgrading moves saved Inbox quiet hours to their new
    place; SQLite evaluation databases are not migrated, so set Inbox quiet
    hours again there.
  • Reloading the Reliability page, or following a link out of the app, while
    it is still loading no longer logs "Failed to load reliability data" in the
    browser console: the browser cancels the page's requests then, and a
    cancelled or aborted request is not a failure. A load that really fails is
    still logged, also after you move to another page of the app.
  • Saving My Routing through the API with only one of the Inbox settings
    under routing.in_app (a category mute, say) no longer drops the other
    (the Inbox quiet hours); the settings are merged with what is saved. The
    My Routing page never sends them, so this only affected API calls.

Changed

  • The People guide now says what a Viewer sees: in the web app the Dashboard,
    the incident list and each incident's summary, the On Call Schedule,
    Activity, their Inbox and their own profile; through the API also the lists
    of Escalation Chains, Rosters, teams, services, memories and more, but not
    incident timelines or comments, reports or analytics. A Viewer can't list or
    open AI sessions or read their chat history, but sees each session's tool
    calls in Activity and its proposed actions in the approval list, can read
    which memories a session used, and can follow a running session's live
    stream, chat included, if they know its id. What a Viewer can open is
    unchanged; tests now hold the sidebar, the page guard, these API answers and
    the session content a Viewer reads to it. Before, the Auth guide said
    Viewers could read sessions and the People guide didn't say what a Viewer
    could open.
  • The two quiet-hours settings now s...
Read more

v1.1.1

Choose a tag to compare

@github-actions github-actions released this 10 Oct 04:32
23c1da8

[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) and python_repl and
    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 413 before reading them in
    full, including bodies sent without a length; set
    OPSMENDER_INGEST_MAX_BODY_BYTES to 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_count and unhelpful_count fields 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 one opsmender --version prints; it said 0.2.0 whatever 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
    no...
Read more

v1.1.0

Choose a tag to compare

@github-actions github-actions released this 09 Sep 20:13
bea5afa

This release makes OpsMender useful without an MCP server, gives skill authors a proper workbench, and lets Discord users act on incidents without leaving the channel.

What's new

Sessions without MCP. A service covered by native integration connectors can now run an AI session with no MCP server configured. Integration tools pass through the same tier gate, approvals, and audit log as MCP tools. If nothing provides tools for a service, the session says so and stays advisory rather than failing.

Skill Studio for either source. Skills can bind to an MCP server or to a native connector. Start from a template, discover the tools the source offers, validate the file before saving, and see exactly which operations changed and where permissions widened. Policy you write can make a connector stricter than its baseline but never looser.

Discord incident actions. Acknowledge, resolve, escalate, or start an AI session from a Discord message. Every button press is signature verified before it is parsed, matched to a linked account and its role, checked for replays, and written to the audit log.

Also in this release

  • The setup checklist and service toolset views now treat an active native integration as a valid tool source.
  • Native actions refused before admission are now recorded in the audit log.
  • The showcase site dropped its roadmap section and got new landing copy.

Downloads

Linux x64 and Windows x64 binaries are attached below with SHA256 checksums, along with a source archive. Both binaries report 1.1.0.

The full list of changes is in CHANGELOG.md.

v1.0.0

Choose a tag to compare

@github-actions github-actions released this 11 Jul 18:50

[1.0.0] - 2026-07-11

Added

  • MCP Skill free-form instructions. Custom Instructions now reach every
    model-driven incident stage. OpsMender parses and preserves per-tier
    Markdown, injects only the active tier's guidance, and keeps structured tool
    policy, deny lists, approval requirements, and backend guardrails
    authoritative.

  • Deterministic autonomy demonstrations. The demo seed now includes
    self-contained Tier 0 autonomous remediation, Tier 1 approval-gated, and
    Tier 2 advisory-only sessions with persisted workflow and audit events; the
    README screenshots show each policy producing a distinct outcome without a
    live model or network dependency.

  • Standalone SQLite evaluation. opsmender serve now initializes a local
    SQLite schema from ORM metadata, stamps it at the bundled Alembic head, and
    starts in development mode for a zero-PostgreSQL product trial. The
    PostgreSQL production migration path and migration-skip flag remain intact.

  • Release verification gate. Added reusable pull-request and release-tag
    verification for backend lint/tests, empty-Postgres migrations, frontend
    lint/typecheck/tests/build, and a container health smoke test. Backend tests
    now deselect live integration cases and enforce a 180-second per-test timeout.

  • Platform-neutral health probes. Added dependency-free /health/live and
    role-aware /health/ready endpoints with database and migration checks, while
    retaining /health as the backward-compatible liveness alias.

  • Simplification sprint — Phase 5 Voice & SMS calling. Added admin
    Settings for workspace Voice/SMS calling, with encrypted auth-token storage,
    DB-over-env resolution, availability for My Routing, and disabled
    Voice/SMS routing options when calling is not configured.

  • Noise and analytics sprint — Phase 0 tier clarity. Approval rows now show
    the requesting session tier, the demo seed separates Tier 1 approval-gated
    sessions from Tier 2 advisory blocking, and team-scoped maintenance windows
    mark status-page components as maintenance.

  • Noise and analytics sprint — Phase 1 alert-noise intelligence. Services
    now support inherited/on/off similar alert grouping, grouped Incident badges,
    flapping detection with P0 safety behavior, and workspace default controls.

  • Noise and analytics sprint — Phase 2 analytics. Added read-only Noise
    and Response analytics APIs with CSV export plus a dashboard Analytics page
    for alert volume, noise reduction, MTTA, and MTTR trends.

  • Noise and analytics sprint — Phase 3 API tokens. Added named,
    revocable, role-scoped REST API bearer tokens with Settings management,
    one-time secret display, audit attribution, and self-service denylist
    protections.

  • A+ closure sprint — final audit proof. Added
    scripts/live_update_proof.mjs, a Playwright two-context acceptance script
    that proves the dashboard's live incident refresh updates within the
    two-second budget with one notification WebSocket and no skeleton flash.
    Sprint-end re-grade remains GATE PASS 0/0/0.

Changed

  • Production configuration validation. Production startup now rejects
    placeholder secrets, non-PostgreSQL database URLs, weak configured bootstrap
    passwords, and invalid autonomy tiers, with warnings for wildcard CORS,
    missing public URLs, and enabled API documentation.

  • Simplification sprint — Phase 3 Models. Services now expose their
    service-specific model list as Models, backed by services.model_config_ids,
    and the session model picker is restricted to active service Models plus the
    workspace default model.

Breaking

  • Explicit Skill tier policies. Every executable Skill operation must now
    declare complete T0/T1/T2 behavior; underspecified runtime policies fail
    closed and deny entries remain unconditional. Existing stored and imported
    classification-only operations are deterministically upgraded to the prior
    conservative behavior and surfaced for operator review.

  • Simplification sprint — Phase 4 MCP servers. Service MCP server lists are
    now strict allowlists, backed by services.mcp_server_ids; empty service
    lists and sessions without a service get no MCP tools instead of falling back
    to any configured server.

Removed

  • Workspace Status Page. Removed the public/private Status Page feature
    entirely — the /status page, the Settings section, the per-incident status
    update publishing, the status_page_* tables and Organization columns, and
    the related API. Stakeholder communication is served by scheduled reports; the
    separate Atlassian Statuspage integration connector is unaffected. Migration
    n1o2p3q4r5s6 drops the tables and columns (downgrade recreates them).

  • Simplification sprint — Phase 1 Agent Teams. Removed Agent Teams from
    the API, database model, Settings, session start flow, and AI workflow
    runner; sessions now use the single-agent path by design.

  • Simplification sprint — Phase 2 Session workflow. Removed the Session
    Profiles page and per-session profile picker; admins now manage one
    workspace-wide Session workflow from Settings, and every new AI session stamps
    that default workflow configuration.

Fixed

  • Session notification task lifecycle. Scheduled session chat
    notifications are tracked in the application background-task registry so
    shutdown can drain them cleanly and session-state transitions cannot race an
    unmanaged SQLite read transaction.

  • Role-aware dashboard loading. Viewer and operator dashboard routes no
    longer issue requests their roles cannot make, while workspace branding is
    readable by every member and protected mutations remain admin-only.

  • Session audit history and approval layout. Completed and paused sessions
    hydrate their event streams from persisted audit entries, the desktop work
    area retains usable height as context grows, and approval actions fit within
    the table at supported desktop widths.

  • Integration and notification-channel brand icons. Restored the ServiceNow
    mark in the integration catalog; added recognizable Microsoft Teams,
    Lark/Feishu, DingTalk, and WeCom marks to the notification-platform picker;
    and replaced the monochrome Slack glyph with its official four-color mark.

  • A+ closure sprint — A-8 README screenshot set. The screenshot capture
    helper now uses the design-audit credential pattern with environment
    overrides and .env bootstrap fallback, captures the four launch README
    surfaces into site/public/screenshots/, refuses to capture an empty
    approval inbox, and the README now embeds the current screenshots with
    product captions. Skill parsing now fails closed on non-mapping YAML roots so
    malformed skill records cannot 500 session-tier resolution.

  • A+ closure sprint — A-9 motion micro-polish. Toasts now ease in with a
    short fade/rise and fade out before removal, shared modals open with a
    conservative backdrop fade plus panel fade/scale, and globals.css now has
    a global prefers-reduced-motion: reduce kill-switch for existing and new
    animations/transitions.

  • A+ closure sprint — A-6 command-palette incident search. Cmd/Ctrl+K now
    debounces incident search through listIncidents({ q, limit: 5 }), renders
    an Incidents section with severity badges and relative created times, drops
    stale responses, fails silently, and lets keyboard selection traverse static
    nav/actions plus incident hits as one list.

  • A+ closure sprint — A-5 memory severity tags. Incident memory severity
    tags now canonicalize to severity-<level> across recall derivation, LLM
    writeback, manual memory create/update, and postmortem memory extraction;
    an Alembic data migration normalizes existing incident_memories.tags rows
    while preserving order and deduping duplicates.

  • A+ closure sprint — A-4 Activity grouping. Activity now defaults to
    collapsible session groups with short session IDs, View session links, time
    spans, entry counts, blocked-count chips, grouped Search/Type/Tier/Status
    filters, and a toggle that restores the previous flat DataTable with its
    date range, column picker, expansion, and CSV behavior intact.

  • A+ closure sprint — A-3 mobile approvals. Pending approvals now use
    thumb-sized, full-width Approve, Reject, and Redirect actions below sm on
    the session-detail card and Approvals page; action JSON collapses behind an
    accessible disclosure on mobile while reason and expiry stay visible, and
    the Approvals page renders stacked mobile cards instead of the desktop
    table.

  • A+ closure sprint — A-2 dashboard onboarding. The first-run setup
    checklist now lives only on the Dashboard, has a slim progress bar and
    explicit "N of 5 steps" status, refreshes on focus/live events, silently
    hides when unavailable or complete, and no longer duplicates itself on the
    Incidents page.

  • A+ closure sprint — A-1 live updates. Dashboard, Approvals,
    Orchestration, Incidents, the notification Inbox bell, and the sidebar
    Approvals badge now share one live notification WebSocket with
    category-filtered, debounced subscribers; manual and fire-test incident
    creation emit incident.created in-app events so existing silent refreshers
    update without loading flashes.

  • UI/UX Polish sprint (design-audit remediation) — Phase C: Reliability
    maintenance polish (P-15).
    Maintenance windows now cross-link to Paging
    maintenance windows, explicitly note that they suppress paging too, and
    populate the Targets column with "All Targets" or scoped target badges.

  • UI/UX Polish sprint (design-audit remediation) — Phase C:
    Settings/Profile (P-20).
    Settings now uses a compact pointer row for
    Models, MCP Servers, and Notification Channels; Organization save is
    bottom-right in its card, and the profile page is titled "My profile."

  • **UI/UX Polish sprint (design-audit remediation) — Phase D...

Read more